September 20, 2020
How to Track Virtual Pageviews when Multiple History Events Occur at the Same Time
Updated: September 20th, 2020
Note: In July 2023, Universal Analytics stops working. It is no longer recommended to do new implementations with Universal Analytics (GA3). Use Google Analytics 4 instead.
This is yet another post about Single Page Application tracking with Google Tag Manager. In my main blog post, I explored two options on how to track such websites. It’s either with the History Change trigger or with the developer’s input.
A more robust solution is to cooperate with a developer but, unfortunately, that is not always possible due to various reasons (e.g. developer’s busy schedule or maybe you’re working on a small project where the developer is not present at all).
Then your next option is a History Change trigger. But this has also some nuances. And in today’s article, we’ll take a look at one of them.
Table of contents
- Before We Continue
- The Problem
- Possible Solutions?
- Check the History Change Source
- Update the History Change Trigger
- Passing the correct Page URL
- Final test
- Final words
Before we continue
This blog post will not dive into the intricacies of the Single Page Application tracking with GTM. I have another in-depth article about it. So if you’re totally new to this topic, I suggest you read that one first.
In today’s blog post, I’ll just tackle one problem and possible solutions for it.
As you should already know, when a visitor browses SPA, the page does not actually reload. It just dynamically loads the content. So if you implement Google Analytics tracking the standard way, only the first pageview will be tracked.
A solution for that is called Virtual Pageviews. Every time a state/view of the SPA changes, a “fake pageview” hit is sent to Google Analytics.
If you’re managing your Google Analytics tracking tags via Google Tag Manager, you need to somehow figure out what is the “trigger” that sends those fake pageviews.
Let’s say that the developer is not available and we have to go with the History Change trigger.
Once you have created it, refresh the preview mode, then refresh the page you’re currently working on. Then start navigating the page. Every time a page URL dynamically changes, you should see the History event in the preview mode. If you have followed my main SPA tracking guide, you have configured your GA Pageview tag to fire every time that History event occurs. So it’s natural that you expect that event to appear only once when the URL changes.
And that’s where we reach today’s problem (sorry for quite a long introduction to it). In some Single Page Applications, multiple History events happen at the same time (even though the URL just changed once).
One of the solutions could be to ditch the History Change trigger and cooperate with the developer. Ask him/her to push a custom event to the Data Layer every time a URL actually changes. Together with that event, he/she should also send the actual URL and the page title. You can read more about that here.
But you’re probably looking for some other option, right? Well, there is one. I’m not sure whether it will work on all SPAs but it sure did on many I’ve worked with (that had this problem of multiple history events).
So the solution that I propose in today’s blog post is narrowing down the History Change Source.
Check the History Change Source
When you see those multiple History events in the GTM preview and debug mode, click the first one and go the Data Layer tab. Keep looking for the gtm.historyChangeSource. What is this value? Memorize it. In my case, it’s pushState.
Then click the next History event that happened almost at the same time. What is the value this time? In my case, it’s replaceState.
I’ve seen some apps that use 3 or 4 History events one every pageview. If that’s your case, check them all.
Your goal here is to answer this question: Is there one History event (of a “fake pageview”) that has a unique gtm.historyChangeSource value (compared to other History events that happened at the same time)?
For example, if you have 3 History Events happening at the same time, maybe only one of them uses pushState and all others are using the replaceState? (P.S. you can learn more about what each of these states means here).
In my case, I see two History events. One with the pushState and one with the replaceState. I’m still not sure which one to choose. So I keep navigating the Single Page App to see what is happening. P.S. If I saw 3 events (one of them was pushState, two – replaceState), then most likely, I’d have to go with the pushState.
But once again, since my case had only two History events at the same time, I’m not sure which state to pick.
The page that I was checking also had a slider where a visitor can answer a question by using a slider (from 1 to 10). Every time a slider was moved by 1 point, a new History event was pushed to the Data Layer.
After I checked them, ALL of them used the replaceState. Now, I definitely do NOT want to send a virtual pageview to GA every time someone moves a little slider. I want to fire a tag only when the page changes (e.g. I move to the next page, etc.).
So I’d say that replaceState is not a good option for me (because it fired too often). pushState, on the other hand, is (because it fires only once per page view when I actually navigate the SPA).
Just to make sure, you should continue navigating the Single Page Application to make sure that every time you move from one “page” to another, only one History event occurs in the Preview & Debug mode that uses the pushState.
Remember: carefully inspect how YOUR single page application works. In my example, tracking only pushState History events is the way to go. In your case, things might be different and you might end up using a different state. So always play around and verify which History Change Source should be chosen.
Update the History Trigger
So if things went well for you and you managed to find the proper gtm.historyChangeSource value (that is pushed once to the Data Layer only when a visitor/user actually navigates from one “page” of the SPA to another), it’s time to add it to the History Change trigger’s settings.
Go to your Google Tag Manager container > Triggers and open the History Change trigger you’ve already created. Add the following condition: History Source equals pushState
This is case-sensitive.
If you don’t see the History Source variable in the list, click Choose built-in variable and then pick the History Source.
If your GA pageview tag already uses this trigger, let’s test whether the tag actually fires when it’s supposed to (just on pushState History events).
Refresh the Preview and Debug mode (by clicking the Orange Banner in the GTM interface) and then refresh the browser window with your SPA. Start navigating it and see what happens.
IMPORTANT: you will continue seeing multiple History events in the Preview and Debug mode. However, if you click them, you should notice that your GA Pageview tag is firing only on those where the History Source variable equals to pushState.
There are two places in the preview mode where you check the value of the History Source:
- Variables tab of the Preview mode
- Or Data Layer tab
Passing the correct Page URL
If the URL of your SPA contains the # and all the important stuff that can help you distinguish one URL from another is available after the # in the URL (e.g. example.com/#/pages/contact-us), you need to do some additional configuration (because by default, Google Analytics does not display URL parts that come after the hashmark (#).
Read this part of my SPA tracking guide to learn more. There are several options so you should pick the one that fits your needs the best.
Here’s what the final result should look like (a quick test plan).
Verify how many times does your GA Pageview tag fire on a single transition between SPA pages
Every time a visitor navigates from one page of your SPA to another, multiple History events may appear in the preview console, BUT only one of them should fire your GA pageview. If you see, say, 3 History events after clicking all of them, you will see that only on one event your GA Pageview tag has fired.
Check the Real-time reports
Go to the real-time reports of Google Analytics and check whether you are actually getting only one pageview when you navigate from page A to page B of your SPA.
Is URL with # also changing in GA real-time reports?
If your SPA URL contains # and something afterward, you should still see those URL changes in the GA Real-time reports. You can read more about it here.
Tracking SPA with GTM when Multiple History Events Occur: Final Words
Single Page Application tracking is always tricky and this can be proven by a whole bunch of various blog posts on the web. In today’s article, I tried to tackle a not-so-rare situation when multiple History events are visible in the GTM preview and debug mode even though a visitor has navigated just between two pages.
So instead of one History event, there were two, three, or maybe even more. One of the possible solutions is, of course, cooperation with a developer. If that is not an option, you could try checking the following thing.
Is there one History event (among all those unwanted duplicates) that is using a different History Source? If yes, then you could update your History Change trigger to fire the GA Pageview tag only on that certain History Change.
This, of course, requires some time to play around with the SPA and make sure that you have chosen the correct History Change Source. If unfortunately, you were not able to do that, then you should go back to your developers and use custom events to track virtual pageviews of your SPA.