Meteor / React-Router v5 - Gtag google analytics - unrealistic bounce rate/time spent on page

Hi everyone,

I created a new topic because we were having a discussion with @a4xrbj1 on the subject on another topic but I think
1/ it could help more people
2/ more people can help us, if we separate this issue.

Problematic is the following : setting up a quite classic meteor / react / react-router app and implementing simply gtag in client / main.html head (simply copy/paste of the script given by google tag manager) it seems that I am getting very unrealistic bounce rate (95% sometimes) and session time (a few seconds). It seems google is not taking into account changing of page on a SPA like this. Apparently @a4xrbj1 is reporting similar issue. I also compare with facebook pixels results that clearly show a much better bounce rate.

Do you know of any library / solution to solve this ?

I have tried implementing this reply:

and will see result quite soon but it isn’t the most recent solution and gtag is changing regularly so wanted to have your feedbacks ? Alos maybe there is some specific meteor solution ?

FIRST EDIT: following this : Track Single Page App with Google Analytics 4 and Google Tag Manager I manage to rigger even on history change
thanks everyone for your help & stay safe.

1 Like

Sure. I use React will try to show you a “very” async version :).

I have added history NPM to my project.
In the entry js file of your client (index.js), on Meteor.startup I initiate the history prop and then pass it down to all my components like so: index.js -> App.js and then all components are served from here.

index.js


async function main () {
  const [
    { Meteor },
    React,
    ReactDOM,
    { Provider },
    { default: App },
    // import more things not relevant to this topic
    { createBrowserHistory }
  ] = await Promise.all([
    import('meteor/meteor'),
    import('react'),
    import('react-dom'),
    import('react-redux'),
    import('./layouts/App'),
    import('history')
  ])

  Meteor.startup(() => {
    const history = createBrowserHistory()
  
    ReactDOM.render(
      <Provider store={store}>
          <ConnectedRouter history={history}>
            <App history={history} /> /* this is the only relevant part for this topic */
          </ConnectedRouter>
      </Provider>, document.getElementById('app'))
    // }
  })
}

main()

In App.js. Here I wait for everything to be running and only then I load and start my google things. I don’t want these to affect my startup time on the user side. What I do is to wait for 6 seconds and then call this function:

handleGoogleAnalytics () {
    if (!window.GoogleAnalyticsObject) {
      const { history } = this.props /* this is the history passed from index.js*/
      import('react-ga')
        .then(ReactGA => {
          ReactGA.initialize('UA-xxxxxxx-1')
          ReactGA.set({ page: window.location.pathname })
          ReactGA.pageview(window.location.pathname)

          history.listen((location, action) => { // This listener is provided by the NPM library
            ReactGA.set({ page: location.pathname })
            ReactGA.pageview(location.pathname)
          })
        })
    }
  }

If you don’t use Redux, you could probably import “history” right into your App.js.
If you don’t want to add more NPM to your project you could probably use the browser’s listener on page changes. That would be something like this: https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate

window.onpopstate = event => {
    ReactGA.set({ page: document.location })
    ReactGA.pageview(document.location)
};
1 Like