Migrate to Netlify Today

Netlify announces the next evolution of Gatsby Cloud. Learn more

ContactSign Up

How to Add Google Analytics gtag to Gatsby Using Partytown 🎉

Paul Scanlon
March 23rd, 2022

Hi friends, are you well? Great, let’s get going.

As you might have already heard Google will, in the not too distant future drop support for its Universal Analytics tracking code… you’ve probably seen one, It looks like this UA-123ABC-1.

Universal Analytics will no longer process new data in standard properties beginning July 1, 2023. Prepare now by setting up and switching over to a Google Analytics 4 property.


With Gatsby you will have probably used gatsby-plugin-google-analytics to add the Universal Analytics tracking code to your Gatsby site.

In Part 1 of this post I’ll explain how you can switch from using the Universal Analytics tracking code to the newer Google Analytics 4 property or “gtag” using gatsby-plugin-google-gtag.

In Part 2 of this post I’ll be explaining how you can implement gtag with Partytown to give your site an extra performance boost without using plugins.

Part 1: How to Switch to Google’s New Google Analytics 4 Property

Following Google’s support docs you can create a new GA4 property in your Google Analytics Admin area. Make the switch to Google Analytics 4.

Now you’re ready to uninstall gatsby-plugin-google-analytics and install gatsby-plugin-google-gtag

It goes without saying but, like you would with any npm package, check the peer dependencies of the plugin before you install. It might not be compatible with the version of Gatsby you’re using. There’s some helpful tips about plugins in this post: Gatsby Plugin Not Working, But Why?

With both a Google Analytics 4 property setup and the plugin installed you can now make the relevant changes to your gatsby-config.js.

Done. That was pretty straightforward right?

But wait, there’s more.

Part 2: How to Implement Google gtag with Partytown

On Wednesday Mar 2nd 2022 I watched Ersin Akinci’s talk at GatsbyConf: Improve Your Lighthouse Score with Partytown and Gatsby… and I got super excited!

If you’re already familiar with Partytown and are keen to jump ahead I’ve prepared a demo repo with a pull request that shows the diff plus x2 Gatsby Cloud preview URLs.

With the following links you’ll be able to see the differences in Chrome Dev Tools Performance and Network tabs with and without Partytown implemented.

Partytown 🎉

Partytown is a lazy-loaded library to help relocate resource intensive scripts into a web worker, and off of the main thread. Its goal is to help speed up sites by dedicating the main thread to your code, and offloading third-party scripts to a web worker.

Partytown 🎉

Main thread?

The Partytown docs do a great job of explaining how it all works, and the diagram was particularly useful in helping me understand the role of web workers – I’d advise having a peek at the web workers section in the docs.

The general idea is, Partytown keeps the main thread clear which frees up resources that are used to execute the main application’s JavaScript (your website) – after all, this is the important bit, right?

Why is it important?

It’s important because third-party scripts have a habit of slowing down the time it takes for your website to load, and a slow-to-load website isn’t good for users, or performance metrics…. or $business!

What we know: Loading third-party scripts on the main thread impacts performance by delaying the time it takes for your site to become available and ready to use by your end users.

You can see from the below that amongst that mess on the Performance tab is the gtag script which is getting in the way of the application JavaScript – Blurg! 🤢

gta Performance tab

You’ll also notice on the Network tab that js?id=G-ABC123 is actually loaded before some of the more essential application JavaScript – Yikes! 😲

gtag Network tab

But with Partytown, third-party scripts are offloaded to a web worker (which runs in its own thread), which means your site is available more quickly to your end users.

Your users thank you, your business thanks you, and we thank you for making a faster web!

⚠️ A word of warning

I should point out that Partytown is currently in BETA and the method I’m about to describe can also be considered BETA! – It does work but it could change in the future!

…but fear ye not! I have it on good authority that a Script component will be coming to Gatsby later in 2022 and all of the Partytown goodness I’m about to explain will be baked in and ready for you to use in the usual sweet, sweet Gatsby way! 💜

Oh also, before I forget, we’ve added some of the methods used in this post to the official Partytown docs, these can be found on the following links.

Using Partytown with Gatsby

Uninstall Google Analytics Plugins

Install Partytown 🎉

Copy Partytown library files to static


The onPreBuild extension point is used to copy the ~partytown files into Gatsby’s static directory, this happens quite early on in the build process. Once Gatsby’s build steps are finished Gatsby copies the files from the static directory into the public directory, ready for when Partytown needs them and when your site is served from your CDN.

It’s worth noting onPreBuild is only called during the build process. If you need to use copyLibFiles while in development you can use onPreBootstrap which is called when running both gatsby build or gatsby develop.


You won’t need to commit the ~partytown files to git so you can go ahead an add the following to your .gitignore

Implement Partytown

There’s quite a lot going on here, so let me talk you through it.


onRenderBody is one of gatsby-ssr’s extension points and runs after each page is created by Gatsby. It can be used to set HTML <head /> or <body /> elements.

To set <script /> tags in the HTML <head /> you can use the setHeadComponents function.

There’s an if condition right at the beginning to ensure the script tags and Partytown component aren’t added while in development

<script />

I’d like to draw your attention to the type on the <script /> tag. Usually you’d expect to see type="text/javascript" but with Partytown this has changed to type="text/partytown".
This is so later on, when Partytown does its thing it’s able to locate the <script /> tags to offload to web workers. More on that in a moment.

It’s also worth pointing out that the actual gtag script is ever so slightly different to the example given on the Google docs: Install the global site tag, i’ll explain why in a moment. – Read on 💅

<Partytown />

The <Partytown /> React component can be configured using regular React Jsx props. You can read more about the Partytown React component in the docs, but I will explain the forward prop as this is where things can get a little complicated.

The forward Prop “Problem”

If you have a look at Google’s recommended approach you might notice some differences between the code snippet i’ve used above and the one shown in: Add gtag.js to your site.

There’s a small but important difference shown here in the diff.

When Partytown moves scripts into a web worker it creates a kind of clone of the window object, and when it does, function gtag() isn’t hoisted onto the cloned window object.

By defining window.gtag = function gtag() we can ensure that the gtag function as referenced by the forward prop will exist on the Partytown cloned window object.

Hat tip to Ward Peeters (Gatsby’s Principal Engineer, Tech Lead Open-Source) for this solution 🎩.

There’s one other small difference in the code snippet. Here’s the diff.

To ensure that a page view isn’t sent once the script is loaded you can set send_page_view to false.

In the next section I’ll explain how you can fire off events containing location data. For reference here’s the Google docs for: Measure Google Analytics Events.

Sending events


The onRouteUpdate function is called when the user changes routes, including on the initial load of the page. You can access the current location from the destructured props.

As with onRenderBody there’s an if condition right at the beginning to ensure the gtag event isn’t called while in development, and then inside a 100ms setTimeout is where you can fire off any event you like. I’ve called this one page_view and passed in a pagePath which can be constructed from properties contained within the location prop. The 100ms delay is required to ensure all side-effects such as React Helmet setting titles etc are complete before the gtag event is fired.

Once deployed you can see on the Performance tab in Chrome Dev Tools that Partytown is now taking charge of loading the Google Analytics script and waits until the main thread has finished loading / parsing all of your important application JavaScript (indicated by the red line in the image below) – Lovely stuff! 🥳

web worker Performance tab


And that’s it, it’s a little more work than slamming a <script /> tag in your HTML <head /> but offloading third-party scripts into web workers using Partytown will no doubt yield a substantial performance boost. In this demo, understandably, there’s not a huge perf boost but if you were to offload all of your third-party scripts you’d start to really get a taste of the vibe 😛.

What’s next?

This is a bit manual for now, but manual optimizations and those small efforts that can land in a big way. So rest assured, we’ll plan to make this even more seamless in the future!

Give @GatsbyJs, @GatsbyChangelog or me, @PaulieScanlon a follow on Twitter, and keep an eye out for updates.

You choose Gatsby because of your need for speed, and we want to make the fast thing, the easiest thing.

Until next time, Party On, Wayne! Party On, Garth! 🎉




Share on TwitterShare on LinkedInShare on FacebookShare via Email

After all is said and done, structure + order = fun! Senior Software Engineer (Developer Relations) for Gatsby

Follow Paul Scanlon on Twitter

Tagged with analytics, Website PerformanceView all Tags

Talk to our team of Gatsby Experts to supercharge your website performance.

Contact Gatsby Now
© 2023 Gatsby, Inc.