Search code examples
google-analyticsgoogle-tag-managergoogle-analytics-4gtag.jspartytown

How to make gtag and gtm work with partytown in a react app


I need some help with google analytics, gtag and gtm scripts

This is how I am generating the partytown snippet in webpack ->

const snippetText = partytownSnippet({
  debug: config.env !== 'production',
  forward: [
    'dataLayer.push',
    'GoogleAnalyticsObject',
    'ga',
    'gtag'
  ],
  resolveUrl: (url, _location, type) => {
    const proxyScriptHosts = [
      'www.google-analytics.com',
      'www.googletagmanager.com',
    ];
    if (type === 'script' && !!url && proxyScriptHosts.find((proxyScriptHost) => url.host.includes(proxyScriptHost))) {
      const proxyUrl = new URL('https://my-proxy.com/api/proxy');
      proxyUrl.searchParams.append('url', url.href);
      return proxyUrl;
    }
    return url;
  }
});

Then I insert this snippet in my index.html file like this -

<script type="text/javascript">{snippetText}</script>

Now I need to load 3 scripts for my app, this is where I need help to understand what I am doing wrong -

  1. this is how I am loading the google analytics script -
<script type="text/partytown">
  window.dataLayer = window.dataLayer || [];
  window.gtag = function () {
    window.dataLayer.push(arguments);
  }
  window.GoogleAnalyticsObject = 'ga';
  window.ga = function () {
    window.ga.q = window.ga.q || [];
    window.ga.q.push(arguments);
  };
  window.ga.l = 1 * new Date();
</script>
<script type="text/partytown" async defer fetchpriority="low" src="https://www.google-analytics.com/analytics.js"></script>

in one of my react components, i am initializing google analytics like this ->

window.gtag('js', new Date());
window.gtag('config', gaId, options);

This works perfectly fine, i can see google analytics UA4 requests in the network tab working as expected!! 2. this is how i am loading the gtag script -

<script type="text/partytown" async defer fetchpriority="low" src="https://www.googletagmanager.com/gtag/js?id=${gtagId}"></script>
  1. this is how i am loading the gtm script -
<script type="text/partytown" async defer fetchpriority="low" src="https://www.googletagmanager.com/gtm.js?id=${gtmId}"></script>
<script type="text/partytown">
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
</script>

Gtag and GTM scripts aren't working, none of the events are being sent for them, please help me understand. I need ga, gtag, and gtm all 3 in my case working together Please help me with this, i've been stuck on it for quite some time, need to understand the right way to do this

I have searched in the official partytown docs and read various blogs online, this is as far as I've gotten


Solution

  • For anyone still trying to figure this out, I've got a working solution.

    1. Load your gtag.js script (either a server-side container or regular)

      <script type="text/partytown" src="<INSERT_GTAG_URL_HERE"></script>

    2. Create a second Partytown script directly below the script above to initialize everything

      <script type="text/partytown">
          dataLayer = window.dataLayer || [];
      
          // THIS NEXT LINE IS IMPORTANT
          window.gtag = function () {
              dataLayer.push(arguments);
          };
      
          window.gtag('js', new Date());
      
          // Set Google Analytics 4
          window.gtag('config', 'G-<GA4 ID>', {
              transport_url: '<TRANSPORT URL FOR SERVER SIDE CONTAINERS>',
              first_party_collection: true
          });
      
          // Set Google Analytics UA
          window.gtag('config', 'UA-<UA_ID>', {
              transport_url: '<TRANSPORT URL FOR SERVER SIDE CONTAINERS>',
              first_party_collection: true
          });
      
          // Set Google Ads
          window.gtag('config', 'AW-<GOOGLE_ADS_ID>');
      </script>
      
    3. Set the functions to forward to Partytown

      forward: ['dataLayer.push', 'gtag']

    The function declaration of: window.gtag = function () { dataLayer.push(arguments); }; is where the magic happens. If you were to declare the gtag function the way Google has explained, then partytown will throw a type error of TypeError: Cannot read properties of undefined (reading 'apply').

    Now you can freely call the gtag function in your non-partytown code like window.gtag('event', 'page_view')

    Note: You must initialize the gtag configs in the same partytown script where gtag is defined. Otherwise no events will be forwarded.

    Credit goes to this Partytown Github issue: https://github.com/BuilderIO/partytown/issues/382