next.js icon indicating copy to clipboard operation
next.js copied to clipboard

with-google-tag-manager: `pageview` event doesn't fire on initial page load

Open dsbrianwebster opened this issue 3 years ago • 8 comments

What example does this report relate to?

with-google-tag-manager

What version of Next.js are you using?

10.0.3

What version of Node.js are you using?

10.0.3

What browser are you using?

Chrome

What operating system are you using?

macOS

How are you deploying your application?

next start

Describe the Bug

pageview event doesn't fire on initial page load, only routchange

Expected Behavior

to be able set up a single tag in GTM to use the "pageview" dataLayer event, however the routeChangeComplete only fires on subsequent page views.

To Reproduce

  • start with-google-tag-manager up the example
  • add console.log("pageview"); inside the exported page view function
  • note in the console that it only appears on subsequent pageviews

We're going with a slight adaptation from the example, using a hook instead of a regular component. Either way, I think the addition of a call to gtm.pageview on initialPage would be a nice addition to with-google-tag-manager.

export default function useGTM() {
  const router = useRouter();

  React.useEffect(() => {
    const handleRouteChange = (url: string) => {
      // Wrap it in a rAF to ensure the correct data is sent
      // https://github.com/zeit/next.js/issues/6025
      requestAnimationFrame(() => gtm.pageview(url));
    }
    router.events.on('routeChangeComplete', handleRouteChange);
    return () => router.events.off('routeChangeComplete', handleRouteChange);
  }, [router.events]);
}

dsbrianwebster avatar Jan 12 '21 18:01 dsbrianwebster

You could try using this package. Init Google Tag Manger in app.js clientside.

React.useEffect(() => {
         // init GA/GTM
        TagManager.initialize({
	        gtmId: "YOUR-GTM-ID"
        })
}, []); 

sanders54 avatar Jan 13 '21 13:01 sanders54

I have a sneaky suspicion it's related to this https://github.com/vercel/next.js/issues/11535. We've also been having issues with several Pixel trackers who under-reported conversions and we think it's because of a similar reason. I'm investigating now

RXminuS avatar Jan 30 '21 00:01 RXminuS

@RXminuS, perhaps.

The requestAnimationFrame(() => gtm.pageview(url)); bit in our hook (above) might help #11535, I commented there as well.

But, I don't believe that routeChangeComplete is supposed to fire on the initialPage load though. So the primary need to close this issue is for the with-google-tag-manager example to fire a gtm.pageview(url) on the initial page load.

dsbrianwebster avatar Jan 30 '21 01:01 dsbrianwebster

We had the same problem, and therefore opened a PR with a solution we came up with at work!

https://github.com/vercel/next.js/pull/21824

Let me know if it fixes your issue!

balazsorban44 avatar Feb 03 '21 20:02 balazsorban44

@balazsorban44 really interesting approach using the reportWebVitals function! I like the logic behind it a lot and that would certainly solve the issue. Looking forward to seeing the feedback from the Next.js team you added for review.

dsbrianwebster avatar Feb 03 '21 22:02 dsbrianwebster

Hey @dsbrianwebster I've been using GTM quite a bit at work, we had to solve related issues. What you have said about the gtm.pageView event not firing on page load is correct, the main purpose of gtm.pageView is to deal with window.onLoad not firing when routing between pages, which causes issues with reporting.

You can also use the window.onLoad event to push data into the dataLayer, and I'm pretty sure you can use GTM to send data to analytics using triggers and tags.

Without completely understanding what it is you are aiming for, all I can provide is this quick and dirty example:

// _app.js

import '../styles/globals.css'
import { useEffect } from 'react'

function MyApp({ Component, pageProps }) {

  useEffect(() => {
    window.onload = () => {
      window.dataLayer?.push({ event: 'page view from onload' });
    };
  },[])

  return <Component {...pageProps} />
}

export default MyApp

I hope it helps, if not, feel free to give me more detail, e.g. how is the data being fed to analytics, is that even a factor? p.s. You can also setup a history event trigger to track all history state changes, without using callbacks via routeChangeComplete, but this also won't deal with window.onLoad.

What I also realised is that when I wanted to push more data via pageProps, using router.events didn't help, I've written more detail here in an article.

morganfeeney avatar Jun 23 '21 07:06 morganfeeney

Hey @dsbrianwebster I've been using GTM quite a bit at work, we had to solve related issues. What you have said about the gtm.pageView event not firing on page load is correct, the main purpose of gtm.pageView is to deal with window.onLoad not firing when routing between pages, which causes issues with reporting.

You can also use the window.onLoad event to push data into the dataLayer, and I'm pretty sure you can use GTM to send data to analytics using triggers and tags.

Without completely understanding what it is you are aiming for, all I can provide is this quick and dirty example:

// _app.js

import '../styles/globals.css'
import { useEffect } from 'react'

function MyApp({ Component, pageProps }) {

  useEffect(() => {
    window.onload = () => {
      window.dataLayer?.push({ event: 'page view from onload' });
    };
  },[])

  return <Component {...pageProps} />
}

export default MyApp

I hope it helps, if not, feel free to give me more detail, e.g. how is the data being fed to analytics, is that even a factor? p.s. You can also setup a history event trigger to track all history state changes, without using callbacks via routeChangeComplete, but this also won't deal with window.onLoad.

What I also realised is that when I wanted to push more data via pageProps, using router.events didn't help, I've written more detail here in an article.

thanks for this

pfcodes avatar Jun 06 '22 08:06 pfcodes

In my case, react1^8, next^13.

window.load is not firing well on every route changing I use useEffect with router.asPath and It works perfectly.

here's my short example

const router = useRouter();

useEffect(() => {
    const delay = setTimeout(() => {
      window.dataLayer.push({
        event: 'ShowPage',
      });
    }, 0);

    // To avoid fire event twice. react^18, on development mode.
    return () => {
      clearTimeout(delay);
    };
}, [router.asPath]);

ChoiKyubum avatar Nov 09 '22 05:11 ChoiKyubum