In my latest CRA SPA I’ve done this:
My router: (The important line is <GATracker />
)
const App = () => {
return (
<BrowserRouter>
<GATracker />
<Switch>
<Route path={names.DOCS}>
<Docs />
</Route>
<Route path=...>
// ...
</Route>
// ...
</Switch>
</BrowserRouter>
);
};
And this is <GATracker />
(Sorry for the half-assed attempt at TS-ify this…)
import React, { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
declare global {
interface Window {
ga:
| {
(...args: any[]): void;
l: number;
q: any[];
}
| undefined;
}
}
const dev = process.env.NODE_ENV === 'development';
// prettier-ignore
// @ts-ignore
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};
window.ga && (window.ga.l = +new Date());
window.ga?.('create', process.env.REACT_APP_GA_TRACKING_ID, 'auto');
export const GATracker: React.FC<{}> = () => {
const location = useLocation();
useEffect(() => {
if (!window.ga || dev) {
return;
}
window.ga('send', 'pageview', location.pathname + location.search);
}, [location]);
return null;
};