sendGTMEvent for Next.js does not submit to Google Analytics
Asked Answered
U

3

7

I'm trying to learn how to submit a custom event to Google Analytics from a Next.js project. This documentation says I should use sendGTMEvent:

https://nextjs.org/docs/app/building-your-application/optimizing/third-party-libraries

When I use sendGTMEvent, it adds an item do the dataLayer, but nothing actually gets transmitted to Google Analytics. And I don't see any mention of my custom event in Google Analytics. This is the code I have:

/// app/layout.tsx
import GoogleAnalytics from './GoogleAnalytics'

export default async function RootLayout({
  children
}: {
  children: React.ReactNode
}) {

  return (
    <html>
      <body>
        <GoogleAnalytics />
        <main className="">{children}</main>
      </body>
    </html>
  )
}
/// app/GoogleAnalytics.tsx
'use client'

import { GoogleTagManager } from '@next/third-parties/google'

const gtmId : string = process.env.NEXT_PUBLIC_GOOGLE_ID ? process.env.NEXT_PUBLIC_GOOGLE_ID : ""

function GA() {

  return <GoogleTagManager gtmId={gtmId} />
}

export default GA
/// app/Form.tsx
'use client'

import { sendGTMEvent } from '@next/third-parties/google'


export default function Form() {
setInterval(() => {
  if( typeof window === "undefined" ) {
    return null
  }
    dataLayer.push({'event':'MyTest1','conversionValue':25});
    sendGTMEvent({ event: 'MyTest2', value: 'hello-world' })
    console.log('submitting' )
}, 3000);

  return <div>Hello World</div>
}

When I visit my browser at http://localhost:3000, I see the word Hello World, which means my website loaded properly. When I open up Chrome Developer Tools>Console, I see that every 3 seconds, the word submitting is visible. I can see that the dataLayer array is growing in length as more records are added to it.

But I don't see any attempts by my javascript to send data to Google. The Chrome Developer Tools>Network tab show zero attempts to submit anything to Google besides the initial page load.

I tried reading documentation and blogs on the subject, but it's not clear to me what function I am supposed to call to actually "send information" to GA?


Additional Notes:

When I visit Google Analytics and look at Real Time Dashboards, I do not see any mention of MyTest1 or MyTest2 in this widget here:

enter image description here

I tried clicking into each row to drill down further, but couldn't find any mention of MyTest1 or MyTest2

Umpire answered 29/12, 2023 at 21:10 Comment(4)
If you figured this out, I would appreciate an answer post!Puritanical
@AndrewK - I never got things to work. So instead, I cheated and build a JS module then imported it into my TypeScript module using the approach in this question here: #77743105Umpire
Thanks. I have been working on this for 5 hours with no resolution, so I will do the same.Puritanical
Same here, I could not make it work, checking your approach!Willowwillowy
M
4

First of all. dataLayer is just an array. It doesn't do anything on it's own. You need something to listen to its push method. Quite a few libraries do that. In particular, GTM. Therefore, when you debug, and you see changes in the array but no network requests, it's a telltale sign of GTM issues, so your next debugging step is to inspect GTM's internal logic.

From Next's or any other front-end framework's perspective, it does all properly. dataLayer is where the responsibility of the typical front-end ends and the world of analytics begins. So the problem is most definitely not in Next unless it doesn't load the GTM library, but you'd notice that, so it should be ok.

GTM is a large suite that will load gtag.js or many other libraries automatically and completely transparently to the front-end as needed. The caveat is that someone would have to go and set up the logic for events through GTM's UI. It's not a big deal, but it will certainly take some time. Read more about GTM here.

Most likely, you just lack GTM set up. You should go there, making sure the GTM suite you go to has the correct id. Whatever you have in your gtmId const. Or just open Elements and see the id in the dom script snippet, it should have the code that looks like GTM-XXXXXX. Ok, once you're there, make sure it doesn't have existing analytics logic and if it's indeed an empty container then:

  1. Make a tag of Google Tag type. Have your GA4 measurement id there as Tag ID so that it would send the event to the correct GA4 property. Set a page load trigger there. "All Pages" of the "Page View" type. This will effectively load the gtag library attuned to your GA4 property on every page.
  2. Make a trigger of type Custom Event (also known as Data Layer Event), and in the trigger have MyTest1 as a name.
  3. Make a GA4 event tag. Set the configuration tag from step 1 there as a configuration reference.
  4. Publish your GTM container to the production environment.

Done! Now every time you push the MyTest1 event, you should see a network request to Google's "collect" endpoint with essential generic data about the page.

You can do more, of course, like configuring Enhanced Ecommerce events or sending custom dimensions. You can see that in the link I posted above. Google tries to cover all use cases with their documentation.

Morelli answered 15/1 at 1:37 Comment(4)
July 2024, I believe in #2 you need to use a Custom Event Trigger - support.google.com/tagmanager/answer/7679219Stratigraphy
Yes. thank you. Corrected that. We normally don't call them custom events. That's just bad naming on Google's side. Custom events are usually JS events. Which GTM can't listen to natively, unlike other tag management systems.Morelli
I got it to work just now! [[ #3 needs needs a correction. Firing trigger is the All Custom Event from #2 ]] So essentially, you do Step #1 because you need the gtag library to load on every single page-route of the app. Then you do #2 to create a Trigger, where the trigger Event Name: MY_EVENT has to match the sendGTMEvent({ event: 'MY_EVENT', value: 'AppStoreLink' }) in th code #3 A tag to link GA4 Event, triggered by #2, so it pushes that to GA4Stratigraphy
What correction is needed in #3? GTM allows you parallel tracking into multiple GA4 properties destinations. It loads multiple copies of the GA4 lib for every property. Every event has to explicitly refer to particular measurement id. Step #1 is for library load, not for pageviews. It has an option (on by default) to also send pageviews for convenience, but that's not as important.Morelli
S
1

I used @BNazaruk's answer, and got it to work.

This is a diagram for how things are connected to get a single sendGTMEvent called "CTA_APPSTORE" to show up in Google Analytics dashboard.

flow-diagram to show

Stratigraphy answered 27/7 at 6:3 Comment(0)
D
0

I wrote a more visual tutorial at this link, for an imaginary payment flow with a custom purchase event: https://www.whitecitycode.com/blog/002-google-tag-manager-custom-event

But it does boil down to these steps:

  1. In Goole Analytics we need to setup a property and then for our shop we need to setup a web data stream. The result of setting up the stream is a Measurement ID (we need to remember this one as this is the piece of information used to link GTM afterwards).
  2. In this stream we set up a custom event, with just the event name being important: purchase.
  3. Setting up GTM involves as a first step connecting the two accounts via the Measurement ID by the means of an initialization tag. This tag is triggerd on all pages where the Google Tag Manager script is included and it configures the link between GTM and your website. Notice that the Tag ID in the configuration should be the same as the Measurement ID in GA Web Stream.
  4. Next we need to setup the tag and the trigger in GTM for the GA event. We do this by configuring a GA V4 Event tag in GTM. Notice the custom Purchase Trigger which is a trigger based just on the name of the event: purchase.
  5. We integrate in Next (v14) via the means of the @next/third-parties package as mentioned here: https://nextjs.org/docs/app/building-your-application/optimizing/third-party-libraries#google-tag-manager . Notice the order of the React components, with GTM abobe the body and GA bellow
import { GoogleTagManager } from '@next/third-parties/google'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <GoogleTagManager gtmId="GTM-XYZ" />
      <body>{children}</body>
      <GoogleAnalytics gaId="G-SOME" />
    </html>
  )
}
  1. we create the Thank you page were we track the purchase event. To this page we pass the payment session in case we want to extract from the session information about the purchase that we want to track in Analytics. We include on this page a front-end component that makes use of the sendGTMEvent call to send the custom event
import PurchaseTracker from '../../components/PurchaseTracker';

export default function PurchasePage() {
    return (
        <PurchaseTracker session={{id: "cevaid"}}></PurchaseTracker>
    )
}
  1. The actual tracking component just calls the GTM event code to mark the purchase. In a real-world scenario we would call the action on component load, while being careful not to duplicate calls on component lifecycle.
'use client'
import { sendGTMEvent } from '@next/third-parties/google';

type Props = {
    session: Record<string, unknown>
}
export default function PurchaseTracker({ session }: Props) {
    return (
        <button onClick={() => {
            sendGTMEvent({event: "purchase", value: {some: 20}});
        }}>Track</button>
    )
}
Dignitary answered 13/8 at 12:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.