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.
- Demo w/Plugin: https://gatsbygtagpartytown.gatsbyjs.io/
- Repo w/Plugin: https://github.com/PaulieScanlon/gatsby-gtag-partytown
- Demo w/Partytown: https://gatsbygtagpartytown-feataddpartytown.gtsb.io/
- Repo w/Partytown PR: https://github.com/PaulieScanlon/gatsby-gtag-partytown/pull/1/files
Partytown 🎉
— 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.
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! 🤢
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! 😲
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.
- Integrations:
https://partytown.builder.io/gatsby - Proxying Requests:
https://partytown.builder.io/proxying-requests
Using Partytown with Gatsby
Uninstall Google Analytics Plugins
Install Partytown 🎉
Copy Partytown library files to static
onPreBuild
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
.
.gitignore
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
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
onRouteUpdate
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! 🥳
Partytime!
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! 🎉
Paul