Intro
Struggling to use
Google Analytics
on a React-app?
Do you only get data on the landing page of your app, instead of every page?This article will be about how to fix this problem!
The issue:
Google Analytics (GA) sends a pageview per page load, this means that if you would go on a certain page on your website, it requests that page from the server and loads it for the user. That is what GA records and sends as data.
(This is in the case of a simple page view, page-events will not be discussed here!)
And this is also what is the issue when trying to use GA on a React-app (or any single-page applications
). React will load the whole app at once and switch components directly on the browser side.
GA doesn't see this as a new page-load as it doesn't actually load a new page, but as a reload of the same page.
A solution:
There have been different kinds of solutions to this problem, but when I went looking for one I found it confusing to find a clear and up-to-date solution. So here I am, sharing my own recommendation!
The idea would be that, as GA recognizes the page reload of the root URL (
yourwebsite.com/
path/to/page) but not the URI (That is the part after the root: yourwebsite.com/path/to/page
), the trick would be to make it check that URI everytime it reloads. And send that as the whole location of the page.
This solution requires you to use those dependencies:
-
react-router-dom
andreact-ga
npm -i react-router-dom react-ga --save
or
yarn add react-router-dom react-ga --save
Create a file in your source folder and give it a name like useGaTracker.js
or something, you can name it however you want though.
STEP 1
- Go get your UA tracking code on GA.
If you already have created your GA property, you can find that code like this:
- Go to Admin
- Select the property you are using - and click on
Property Settings
- Copy your Tracking ID (should start with UA-xxxxxxx-x)
STEP 2
- Import
{ useEffect, useState }
fromreact
;{ useLocation }
fromreact-router-dom
andReactGA
fromreact-ga
inside the useGaTracker.js file.
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import ReactGA from "react-ga";
STEP 3
- Let's wright the function:
const useGaTracker = () => {
const location = useLocation();
const [initialized, setInitialized] = useState(false);
useEffect(() => {
if (!window.location.href.includes("localhost")) {
ReactGA.initialize("UA-xxxxxxxxx-x");
}
setInitialized(true);
}, []);
useEffect(() => {
if (initialized) {
ReactGA.pageview(location.pathname + location.search);
}
}, [initialized, location]);
};
export default useGaTracker;
useLocation()
is what we will use to get our routing as location.
The first useEffect()
will check if your project is running on a localhost, if not, it will initialize your Tracking ID in the ReactGA and set the state initialized
to TRUE.
The Second useEffect()
will send the pageview to GA with it's location.
This one will also know to send that information each time initialized
or location
has changed.
STEP 4
- Import this function into our routing file.
Go to the file that you use to route your components, and add your function in the router-component (in my case this would be my app.js file:
App.js
import { Route, Switch, Redirect } from 'react-router-dom'
import useGaTracker from './useGaTracker'
const App = () => {
useGaTracker();
return (
<div className="App">
<Switch>
<Route path="/" exact component={ Landing } />
<Route path="/about" exact component={ About } />
<Route path="/discord" exact component={ Discord } />
<Route path="/404" component={ Error } />
<Redirect to="/404" />
</Switch>
</div>
);
}
export default App;
Finally
- That's about it!
You should have a working connection that will save and send all the different routes you use in your routing file!
Top comments (7)
setInitialized(true);
This statement should be in if block.
useEffect(() => {
if (!window.location.href.includes("localhost")) {
ReactGA.initialize("UA-xxxxxxxxx-x");
setInitialized(true);
}
}, []);
In my case, using the useGaTracker hook in the routing component was not working, as the location returned undefined. I had to implement the hook in every page in order for it to work properly.
Hi Ilaria, thanks for clarifying on this! There is very little info out there on this and it can get frustrating! Would it be possible for you to clarify just a bit on how you managed to do this? Maybe show one example page where you implemented the hook? I know I sound super green but I'm still getting the same error and I'm sure I'm missing something.
Thanks!
Hi Sam, well long time has passed and in all honesty I don't really remember how I did it, but I had a look at the project where I was using this package and what I did was calling the useGaTracker hook in every page component like so - after importing it:
const Contact = () => {
useGaTracker();
const [ref, inView] = useInView();
const { getInTouchCtn, headingCtn, heading, descriptionCtn, linkCtn, link } =
useStyles(inView);
return (
.... etc etc
Also note, that the implementation of the hook in the article is not 100% correct - inside the first useEffect, setInitialize(true) should be inside the if statement, not outside:
useEffect(() => {
if (!window.location.href.includes("localhost")) {
ReactGA.initialize(
${process.env.REACT_APP_GA}
);setInitialized(true);
}
}, []);
You can have a look at my GitHub repo: github.com/IlariaCallegari/ilariac...
I just noticed that for some strange reason - probably exhaustion ehehe - I put the useGaTracker hook in src/utils, so head there if you want to see the hook implementation. And if you go into src/pages you can see how I called the hook.
Hope this helps!
Ilaria
Hello Basile, can you indicate the versions of react, react-router-dom and others module used?
What you indicate does not work for me and the following error is generated
useLocation
/node-projects/modules/hooks.js:29
26 | );
27 | }
28 |
Thanks!
not sure it is still useful, but try implementing the hook in every page, rather than only in the routing component. I had the same error, and it worked after doing this.
Thanks Basile!