How to set up Google Analytics for React-Router? How to set up Google Analytics for React-Router? reactjs reactjs

How to set up Google Analytics for React-Router?


Keep a reference to your history object. i.e.

import { createBrowserHistory } from 'history';var history = createBrowserHistory();ReactDOM.render((    <Router history={history}>        [...]

Then add a listener to record each pageview. (This assumes you've already set up the window.ga object in the usual manner.)

history.listen((location) => {    window.ga('set', 'page', location.pathname + location.search);    window.ga('send', 'pageview');});


Given that google analytics is loaded and initialised with a tracking id.

Here is a solution for react-router version 4 using the <Route> component to track page views.

<Route path="/" render={({location}) => {  if (typeof window.ga === 'function') {    window.ga('set', 'page', location.pathname + location.search);    window.ga('send', 'pageview');  }  return null;}} />

You simply render this component inside the <Router> (but not as a direct child of a <Switch>).

What happens is that whenever the location prop changes it causes a re-render of this component (not actually rendering anything) that fire a pageview.


I'm using React Router v4 and the Google Analytics Global Site Tag, which appears to be recommended at the time of writing this.

And here's my solution:

Create a component wrapped in withRouter from react-router-dom:

import React from 'react';import { withRouter } from 'react-router-dom';import { GA_TRACKING_ID } from '../config';class GoogleAnalytics extends React.Component {    componentWillUpdate ({ location, history }) {        const gtag = window.gtag;        if (location.pathname === this.props.location.pathname) {            // don't log identical link clicks (nav links likely)            return;        }        if (history.action === 'PUSH' &&            typeof(gtag) === 'function') {            gtag('config', GA_TRACKING_ID, {                'page_title': document.title,                'page_location': window.location.href,                'page_path': location.pathname            });        }    }    render () {        return null;    }}export default withRouter(GoogleAnalytics);

Simply add the component within your router (I believe ideally after any routes that would be matched and any Switch components, because the analytics function should not be priority over your site rendering):

import React from 'react';import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';import IndexPage from './IndexPage';import NotFoundPage from './NotFoundPage';import GoogleAnalytics from './GoogleAnalytics';const App = () => (    <Router>        <Switch>            <Route exact path="/" component={IndexPage} />            <Route component={NotFoundPage} />        </Switch>        <GoogleAnalytics />    </Router>);

As stated:

withRouter will re-render its component every time the route changes with the same props as render props

So when the route changes, the GoogleAnalytics component will update, it will receive the new location as props, and history.action will be either PUSH for a new history item or POP to signal going backwards through the history (which I think shouldn't trigger a page view, but you can adjust the if statements in componentWillUpdate as you see fit (you could even try componentDidUpdate with this.props instead, but I'm unsure which is better)).