最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Google Analytics 4 integration in React TS - Stack Overflow

programmeradmin3浏览0评论

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
  • 1 I can't tell whether this is a viable solution to circumvent potential errors with adblocker, but I can tell that the "void" errors are due to the fact that the Promise doesn't return anything. You may want to avoid implicit returns to console.log. Re: res and err throwing you could just type res: any and err: any. So there you go, current TS errors solved. What I'd try to do is to use useEffect to wrap ReactGA initialization conditionally inside the app.tsx and trycatch anything there instead of the index.tsx. – Moa Commented Aug 7, 2022 at 14:53
  • 1 "In general I am wondering what the benefit of using the library is?" I believe your arguments are reasonable enough to justify the benefit of using the library. I'd add that it is already a "React" library, so less plumbing needed. The best approach I can think of is to create a custom hook like in this article to wrap all your GA logic. – Moa Commented Aug 7, 2022 at 15:02
Add a comment  | 

2 Answers 2

Reset to default 18 +50

Since 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

发布评论

评论列表(0)

  1. 暂无评论