So currently one can chose between Universal Analytics and Google Analytics 4.
My arguments as why to use Google Analytics 4:
- Universal Analytics will be retired on July 1, 2023 so when I make a new setup I think it makes sense to already go with Google Analytics 4.
- The react-ga package does not work with GA-4 and as it seems it wont. The
react-ga
is in passive maintenance and it wont be updated to support GA-4 unless someone else makes a PR. - But there is the React Google Analytics 4 in short
react-ga4
module that works with GA-4
So I created a property on GA and followed this guide
I installed th module and just initialized in my main index.tsx file with ReactGA.initialize
.
The ID is not stored in an env file as it is public anyway according to this answer.
A test on localhost shows that GA picks up the data.
No more code is needed. GA4 is intelligent enough to measure all of those interactions automatically. You don’t have to bother to code them in your project. GA4 automatically measures interactions and content on sites in addition to standard page view measurement: Page views, scrolls, outbound clicks, site search, video engagement and file downloads. See: Enhanced measurement Events
Any other use case based events, we have to code by ourself. That’s basically unchanged from Universal Analytics.
So my 1. Question is: Are the information I gathered together correct? Would you integrate it in another way? Or am I missing something?
In general I am wondering what the benefit of using the library is?
--> Alternatively I could do for integration: Add the global site tag directly to your web pages
What is the better approach?
Now the second part, in the first code snippet you see the react-ga4 initialization in my index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import ReactGA from 'react-ga4';
ReactGA.initialize('G-XXXXXXXX');
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
A test on localhost shows that data gets picked up in GA dashboard. Perfect!
But then there is the problem with Adblocker crashes. It typically crashes the app if someone has an adblocker (adblocker blocks analytics request endpoints, no error handling, etc) and to mitigate this we detect whether the script didn't load and hence derive if the user has an adblocker that's preventing the GA script from loading. In my example code, I just ignore it and load the app... in other scenarios, I suppose you could invoke a modal to tell them to disable it (of course, that would come with extra code). Taken from spencer741 response
index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import ReactGA from 'react-ga4';
(async _ => {
await ReactGA.initialize('G-XXXXXXXXX')
.then(res => console.log("Analytics Success."))
.catch(err => console.log("Analytics Failure."))
.finally(() => {
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
});
})();
I know that this throws errors in Typescript right now:
Property 'then' does not exist on type 'void'.
Property 'catch' does not exist on type 'void'.
Property 'finally' does not exist on type 'void'.
'res' is declared but its value is never read.
Parameter 'res' implicitly has an 'any' type.
'err' is declared but its value is never read.
Parameter 'err' implicitly has an 'any' type.
But before I try to resolve the errors I would like to know if Is this a viable solution to circumvent potential errors with adblocker?
So currently one can chose between Universal Analytics and Google Analytics 4.
My arguments as why to use Google Analytics 4:
- Universal Analytics will be retired on July 1, 2023 so when I make a new setup I think it makes sense to already go with Google Analytics 4.
- The react-ga package does not work with GA-4 and as it seems it wont. The
react-ga
is in passive maintenance and it wont be updated to support GA-4 unless someone else makes a PR. - But there is the React Google Analytics 4 in short
react-ga4
module that works with GA-4
So I created a property on GA and followed this guide
I installed th module and just initialized in my main index.tsx file with ReactGA.initialize
.
The ID is not stored in an env file as it is public anyway according to this answer.
A test on localhost shows that GA picks up the data.
No more code is needed. GA4 is intelligent enough to measure all of those interactions automatically. You don’t have to bother to code them in your project. GA4 automatically measures interactions and content on sites in addition to standard page view measurement: Page views, scrolls, outbound clicks, site search, video engagement and file downloads. See: Enhanced measurement Events
Any other use case based events, we have to code by ourself. That’s basically unchanged from Universal Analytics.
So my 1. Question is: Are the information I gathered together correct? Would you integrate it in another way? Or am I missing something?
In general I am wondering what the benefit of using the library is?
--> Alternatively I could do for integration: Add the global site tag directly to your web pages
What is the better approach?
Now the second part, in the first code snippet you see the react-ga4 initialization in my index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import ReactGA from 'react-ga4';
ReactGA.initialize('G-XXXXXXXX');
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
A test on localhost shows that data gets picked up in GA dashboard. Perfect!
But then there is the problem with Adblocker crashes. It typically crashes the app if someone has an adblocker (adblocker blocks analytics request endpoints, no error handling, etc) and to mitigate this we detect whether the script didn't load and hence derive if the user has an adblocker that's preventing the GA script from loading. In my example code, I just ignore it and load the app... in other scenarios, I suppose you could invoke a modal to tell them to disable it (of course, that would come with extra code). Taken from spencer741 response
index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import ReactGA from 'react-ga4';
(async _ => {
await ReactGA.initialize('G-XXXXXXXXX')
.then(res => console.log("Analytics Success."))
.catch(err => console.log("Analytics Failure."))
.finally(() => {
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
});
})();
I know that this throws errors in Typescript right now:
Property 'then' does not exist on type 'void'.
Property 'catch' does not exist on type 'void'.
Property 'finally' does not exist on type 'void'.
'res' is declared but its value is never read.
Parameter 'res' implicitly has an 'any' type.
'err' is declared but its value is never read.
Parameter 'err' implicitly has an 'any' type.
But before I try to resolve the errors I would like to know if Is this a viable solution to circumvent potential errors with adblocker?
Share Improve this question asked Aug 1, 2022 at 15:14 user18943198user18943198 2 |2 Answers
Reset to default 18 +50Since there are no other answers, I'll try to answer OP's questions to the best of my abilities.
1. Are the information I gathered together correct?
Yes and no. Although both libraries do what they say they do, I'd take "GA4 is intelligent enough to measure all of those interactions automatically" with a pinch of salt, since both of them require some configuration to track custom events or multiple trackingId
and fine tune your analytics. See react-ga4
repository and react-ga
demo.
2. Would you integrate it in another way? Or am I missing something? If by "another way" you meant other than the question's examples, yes. As said in the comments, a better approach would be wrapping up all your GA logic, either with a Higher-Order Component or a custom hook (examples below).
3. In general I am wondering what the benefit of using the library is?
I think that depends on your project's needs. If you're working on a temporary project or minimum value product (MVP) that may not be in production a year from now, you might be better off with react-ga
since it's been battle-tested and currently has 600k downloads per week on NPM. If not, updating your code-base to react-ga4
might help minimising technical debts in the future and leveraging Google Analytics 4 updates.
4. What is the better approach?
From GA4 answers, there are currently 8 events you can further customize. Let's see how we could implement a custom hook with react-ga4
:
ga4.ts
import ga4 from 'react-ga4'
const TRACKING_ID = 'G-XXXXXXXXX-X'
const isProduction = process.env.NODE_ENV === 'production'
export const init = () => ga4.initialize(TRACKING_ID, {
testMode: !isProduction
})
export const sendEvent = (name: string) => ga4.event('screen_view', {
app_name: "myApp",
screen_name: name,
})
export const sendPageview = (path: string) => ga4.send({
hitType: 'pageview',
page: path
})
useAnalytics.ts
import React from 'react'
import { useLocation } from 'react-router-dom'
import * as analytics from './ga4'
export function useAnalytics() {
const location = useLocation()
React.useEffect(() => {
analytics.init()
}, [])
React.useEffect(() => {
const path = location.pathname + location.search
analytics.sendPageview(path)
}, [location])
}
export default useAnalytics
Alternatively, if you're not using react-router-dom
you could get the path from the global window
object, like so:
analytics.sendPageview(window.location.pathname)
Or with Next.js:
const router = useRouter()
analytics.sendPageview(router.asPath)
Usage
import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router, Switch } from 'react-router-dom'
import { useAnalytics } from './useAnalytics'
function App() {
useAnalytics() // add it here
return <Switch>...</Switch>
}
ReactDOM.render(
<Router>
<App />
</Router>,
node
)
5. Is this a viable solution to circumvent potential errors with adblocker?
There is a tutorial on FreeCodeCamp.org showing how to use proxies to avoid adblockers. You could also use libraries such as FuckAdBlock
, BlockAdBlock
or adblock-detect-react
to check if ad block is enabled on a page and initialize react-ga4
conditionally. As a reminder: it takes normally 24/48 hours for analytics to be gathered. New GA accounts can take a few days before it starts recording data.
import React from 'react'
import { useDetectAdBlock } from 'adblock-detect-react'
const useAnalytics = () => {
const adBlockDetected = useDetectAdBlock()
React.useEffect(() => {
if(!adBlockDetected) analytics.init()
}, [])
React.useEffect(() => {
if (!adBlockDetected) {
analytics.sendPageview(window.location.pathname)
}
} [adBlockDetected, path])
}
Hope that helps! Cheers.
The best solution is to use the gtag directly, if using reactjs paste the code into your index.html file under public
Image showing index.html file under public inside reactjs source code
Promise
doesn't return anything. You may want to avoid implicit returns toconsole.log
. Re:res
anderr
throwing you could just typeres: any
anderr: any
. So there you go, current TS errors solved. What I'd try to do is to useuseEffect
to wrapReactGA
initialization conditionally inside theapp.tsx
andtrycatch
anything there instead of theindex.tsx
. – Moa Commented Aug 7, 2022 at 14:53GA
logic. – Moa Commented Aug 7, 2022 at 15:02