How to set up Google Analytics for React-Router?
Solution 1:
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');
});
Solution 2:
Since react-router v5.1.0
this can be solved a lot easier with useLocation
.
usePageTracking.js
import { useEffect} from "react";
import { useLocation } from "react-router-dom";
import ReactGA from "react-ga";
const usePageTracking = () => {
const location = useLocation();
useEffect(() => {
ReactGA.initialize("UA-000000000-0");
ReactGA.pageview(location.pathname + location.search);
}, [location]);
};
export default usePageTracking;
App.js
const App = () => {
usePageTracking();
return (...);
};
See also:
- https://reactrouter.com/web/api/Hooks/uselocation
- https://github.com/react-ga/react-ga/issues/122
Here's a bit smarter version:
usePageTracking.js
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import ReactGA from "react-ga";
const usePageTracking = () => {
const location = useLocation();
const [initialized, setInitialized] = useState(false);
useEffect(() => {
if (!window.location.href.includes("localhost")) {
ReactGA.initialize("UA-000000000-0");
}
setInitialized(true);
}, []);
useEffect(() => {
if (initialized) {
ReactGA.pageview(location.pathname + location.search);
}
}, [initialized, location]);
};
export default usePageTracking;
Solution 3:
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.