Google Analytics’ Site Speed reports are pretty darn great. They report automatically on various milestones in the process the browser undertakes when rendering content. These reports leverage the Navigation Timing API of the web browser, and they are (typically) collected on the first Page View hit of a page.
And this is all fine. As I said, it’s a great feature of Google Analytics, and lends itself handily to spotting issues in the quite complex client-server negotiation that goes on when your web browser requests content from the web server.
However, there’s a glitch. These automatic page timings are collected once per tracker instance per page, meaning if you have multiple trackers on the page, each set to collect site speed samples, you might inadvertently send the same page speed data multiple times. This will naturally inflate the numbers that Google Analytics reports on, and your data will be ruined, as deduplication is really difficult.
So if you have any of the following in place, you might be in the risk group:
-
Single-page site where you send “virtual” Page Views to Google Analytics
-
Multiple trackers on the page, each collecting to the same Universal Analytics property (UA-XXXXX-Y)
-
Manually set site speed sample rate (e.g. at 100%)
-
Google Tag Manager with a Page View Tag that has multiple Triggers attached to it
If any of these rang true, you might have a data quality issue that should be fixed immediately.
The Simmer Newsletter
Follow this link to subscribe to the Simmer Newsletter! Stay up-to-date with the latest content from Simo Ahava and the Simmer online course platform.
Framing the problem
By default, 1% of Page View hits are sampled for page timings. So if you have the following code on the site:
ga('send', 'pageview');
There’s a 1/100 chance that upon the first time command is executed, this particular request will grab the available Navigation Timing data and send it to Google Analytics. And, again, this is fine. That’s what we want. Now if you have the following code:
ga('send', 'pageview');
ga('send', 'pageview', {page: '/some-custom-page/'});
That’s two separate Page View hits firing on the same page, you’re still fine. Since they use the same tracker object (the default tracker), even if you win the odds and manage to hit the 1/100 twice on the same page, the page timing data is only sent once, since Universal Analytics only sends timing data once per tracker per page.
However, if you have this:
ga('send', 'pageview');
ga('secondTracker.send', 'pageview', {page: '/some-custom-page/'});
If both these trackers collect to the same Google Analytics property (UA-XXXXXX-Y), and if both trackers manage to somehow make the 1/100 cut, you will be sending the same page timing data twice, just for different page paths. And that will warp your data!
It gets worse…
The problem with Google Tag Manager
Google Tag Manager, for all the good it does, has one complication that makes a lot of things difficult: it assigns a unique tracker object for every single tag that fires - even if it’s the same tag firing multiple times.
Take another look at the image at the beginning of this article. There you have a Page View Tag which has the siteSpeedSampleRate
set to 100%, which means that every single time the Page View hit is sent, it should be used to sample page timing data. It also has a Trigger which fires whenever a Custom Event is pushed into dataLayer
. So this is your typical “virtual” Page View (man I hate that term - all Page Views are virtual!) Tag, set to fire with a custom page path whenever the event triggers.
Now, here’s the issue: because it has siteSpeedSampleRate
set to 100, and because it will fire multiple times on the page, and because each time it fires it will have a unique tracker name:
Every single time this Page View Tag fires, it will send the same page timing data to Google Analytics!
That’s multiplication on a grand level! It’s even more confusing since the same page timing data is sent to multiple page paths, making deduplication in the reports really difficult to do.
Fixes
Here are some obvious fixes to this issue.
1. Only sample a single tracker
This is pretty easy if you’re using the Universal Analytics snippet. Set siteSpeedSampleRate
to a proper value in only one tracker, and set all other trackers to 0.
ga('create', 'UA-12345-1', {siteSpeedSampleRate: 100});
ga('create', 'UA-12345-1', {name: 'secondTracker', siteSpeedSampleRate: 0});
This would ensure that only a single set of page timings is sent per page.
In GTM, by default, this would be impossible, because each tag has its own unique tracker name.
2. Only sample the first pageview
This is irrelevant in Universal Analytics, as only the first pageview per tracker is sampled anyway. In Google Tag Manager, however, this might just fix the issue for you.
For this to work, you need to fire the first Page View hit of a page using a unique trigger. Typically, you’d have the “All Pages” Trigger on the Page View Tag, and then another Trigger for the custom Page View. Thus, a single-page app might have the following Tag catering for all Page Views:
Now, this Tag will be problematic if left like this, since the Page Timing sample will be sent every single time the Tag fires - once for the All Pages Trigger, and each time the Custom Event Trigger fires.
To fix this, use this Custom JavaScript Variable as the value of the siteSpeedSampleRate
field:
function() {
return {{Event}} === 'gtm.js' ? 100 : 0;
}
So your Tag looks like this:
This JavaScript returns 100
for the All Pages Event (that’s the gtm.js event name), and 0
for all other Triggers.
In other words, only the All Pages Trigger will send the site speed sample, ensuring it is only sent once on the page.
If you don’t have the means to distinguish the first Page View from all the subsequent triggerings, you could also add hitCallback to your Page View Tag, which sets a global flag (or even a dataLayer
variable) to true
, indicating that the tag has fired (at least) once. Then you can use this flag as a condition for the siteSpeedSampleRate
field, only sending the 100
value if this flag is false.
3. Set the Tracker Name in your GTM Tag
This is the most risky but also the most effective way to fix it. Remember how GTM uses a unique tracker name for every instance of a Tag? Well you can always set the Tracker Name field with some value to make sure that every time the Tag fires it uses the same tracker object. Thus the page timing sample is only sent once. To do this, you’d have to configure one of the settings in the Page View Tag:
You can set it to whatever value you wish, though I advice against leaving it blank. If you do leave it blank, it uses the default Universal Analytics tracker and can lead to issues, unless you are really on top of your site’s GA implementation.
There are risks when setting the Tracker Name field, and I recommend you read my article on the topic before proceeding with the method.
Summary
The Site Speed reports are really great, but you might want to go over your Universal Analytics implementation to make sure you’re not involuntarily collecting bogus data.
As long as you keep in mind that the page speed sample is collected once per page per tracker, you should be able to identify if there are issues in your setup. In this article, I have outlined three different things you can try, but there are other methods you can employ too, with just a little creativity.