partytown: GTM does not report history change events

Description

I’m trying to use the GTM via Partytown in Next.js. I have successfully loaded the scripts and got GTM to send the initial collect request, but it does not report page_view events after changing routes.

When testing the same setup without Partytown the collect requests get sent properly.

Behaviour when loading GTM normally:

https://user-images.githubusercontent.com/9134970/165815764-c2279ce8-10d9-435b-a73f-da89e2c5126e.mov

Behaviour when loading GTM via Partytown:

https://user-images.githubusercontent.com/9134970/165816399-0d170266-c910-4cce-ad40-4da17f1a0221.mov

Expected behaviour

GTM loaded via Partytown detects route changes and sends appropriate collect requests.

How to reproduce

Link to reproduction repo: https://github.com/MrPumpking/nextjs-partytown-gtag-bug

  • The main branch contains pure Next.js setup with GTM. Paste your GTM measurement ID in the .env file.
  • The partytown branch contains GTM loaded via Partytown.

When running each version, you can check the network tab in devtools for outgoing collect requests.

GTM setup GTM is connected with GA4 using the standard Tag.

gtm-tag-config

GA4 web stream has enabled enhanced measurement with the “Page changes based on browser history events” enabled.

image

image

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 21 (3 by maintainers)

Most upvoted comments

I spent some more time on this. Now I see that the problem is caused by history.pushState & history.replaceState not being called inside worker.

I added some more logic to Partytown’s internal LocationUpdate message handler. Now it detects how location has changed (either pushState, replaceState, pop state, etc). When needed it calls pushState or replaceState inside worker.

I already have a POC next.js app with proper history tracking 🎉

I will try to wrap it up and create MR sometime this week. There’s one ugly workaround in my code I would like to fix first.

I found the problem, I had to put the gtag on the window object (eg: window.gtag = function() {dataLayer.push(arguments)} Then in _document where I’m setting the partown-config:

forward: ["gtag"]

Now partytown properly forwards gtag() calls to the worker.

I have below code but it doesn’t seem to work in Angular App, I do see first request to https://analytics.google.com/g/collect when I open the app in browser, but on subsequent navigation no addional request is shown in Network tab.

Below is the code I am using for GA 4:

    <script>
        partytown = {
            forward: ["dataLayer.push"],
            logCalls: true,
            logGetters: true,
            logSetters: true,
            logImageRequests: true,
            logMainAccess: true,
            logSendBeaconRequests: true,
            logStackTraces: false,
            logScriptExecution: true
        };
    </script>
    <script src="/~partytown/debug/partytown.js"></script>


    <script type="text/partytown" src="https://www.googletagmanager.com/gtag/js?id=G-PMCHMHK7J9"></script>
    <script type="text/partytown">
        window.dataLayer = window.dataLayer || [];
        function gtag() { dataLayer.push(arguments); }
        gtag('js', new Date());

        gtag('config', 'G-PMCHMHK7J9');
    </script>

FWIW I narrowed this to popstate and hashchange events not being forwared by partytown (those 2 events are used by GTM’s “History Change”.

This code shows the problem:

<script
  type='text/partytown'
  dangerouslySetInnerHTML={{
    __html: `
      ['resize', 'popstate', 'pushstate', 'hashchange', 'load'].forEach(eventName => {
        window.addEventListener(eventName, () => console.log('[debug] ' + eventName + ' event triggered!'), false);
        console.log('[debug] registered  ' + eventName + ' event')
      })
    `
  }}
/>

Load and resize events are properly forwared to Partytown, but not others.

I’ve added a partytown-0.6.0 branch to the reproduction repository and GTM reporting works fine now - a collect request is being sent after each route change. @slawekkolodziej thanks for your work!

Yeah, I just tested version 0.6.0 and it seems to work just fine with the services I need.

Thanks @Vorseek , tried updating the gtm code but it didn’t work:

    <script type="text/partytown">
    (function (window, document, i) {
            //window['dataLayer'] = window[dataLayer] || [];
            //window['dataLayer'].push({ 'gtm.start': new Date().getTime(), 'event': 'gtm.js' });

            window.dataLayer = window.dataLayer || [];
            window.gtag = function gtag() {
            window.dataLayer.push(arguments);
            }
            gtag("js", new Date());
            gtag("config", window.NEXT_PUBLIC_GTAG_ID);


            var firstScript = document.getElementsByTagName('script')[0];
            var gtmScript = document.createElement('script');
            var dataLayer = 'dataLayer' != 'dataLayer' ? '&l=' + 'dataLayer' : '';


            gtmScript.async = true;

            // ORIGINAL
            gtmScript.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dataLayer;

            firstScript.parentNode.insertBefore(gtmScript, firstScript);
            })(window, document, 'GTM-NJFTK74');

    </script>

I am following this example to integrate Party town https://codesandbox.io/s/laughing-bush-u3j0xb?file=/index.html

Try change gtm.js to

window.dataLayer = window.dataLayer || [];
window.gtag = function gtag() {
  window.dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", window.NEXT_PUBLIC_GTAG_ID);

I thought about sending the page_view manually as specified in the documentation:

Router.events.on("routeChangeComplete", (newUrl) => {
  console.log("gtag", gtag);
  gtag("set", "page_path", newUrl);
  gtag("event", "page_view");
});

function MyApp({ Component, pageProps }: AppProps) {
  // ...
}

But I get the following error:

image image

I’ve also tried calling the dataLayer.push directly:

Router.events.on("routeChangeComplete", (newUrl) => {
  console.log("dataLayer value:", window.dataLayer.push);
  window.dataLayer.push("set", "page_path", newUrl);
  window.dataLayer.push("event", "page_view");
});

This time I don’t get any errors but there are still no outgoing requests to GTM:

image