Developing your site in a single-page application architecture – using frameworks like VUE, Angular, React, or Aurelia – makes your users’ experience easier and faster, but it is a little bit challenging from a tagging perspective.
A Single Page Application (SPA) is essentially a Web page that initially or dynamically loads all of the HTML, CSS, and JavaScript resources required to provide an end-user experience that emulates a complete desktop application rather than a single static Web page. As the user clicks links and interacts with the page, subsequent content is loaded dynamically via an AJAX call. The application will often update the URL in the address bar to mirror traditional page navigation, but another full page request is never made. The Angular site itself is actually an example of an SPA.
New content from the Web server may delivered in JSON (JavaScript Object Notation) format, which the initial Web page processes dynamically. The application will often update the URL in the address bar to emulate traditional page navigation, but another full page request is never made.
From a Web analytics standpoint, this means that you have to track subsequent pageviews manually, since new pages do not load and the tracking for “physical” pageviews is not reactivated.
Let’s reiterate the challenge: in traditional websites tracked into Google Analytics through Google Tag Manager, each page of content requires a round trip, so every time a page loads, a pageview gets sent to Google Analytics via GTM.
This does not happen in an SPA. In an SPA, a basic Google Analytics pageview tracker would record only the first pageview but not the subsequent screen refreshes.
In SPAs, the following URL modifications may take place:
Some of other SPAs update the URL in the address bar without using the hash. For example:
/guide/user-input
/guide/reactive-forms
/guide/dynamic-form
Some SPAs only update the hash portion of the URL when loading content dynamically. This practice can lead to situations where many different page paths point to the same resource. In such cases, it’s usually best to choose the best URL represent your page and only ever send that page value as a virtual pageview to Google Analytics. For example, consider a SPA has a “Contact Us” page portion that can be reached via any of the following URLS:
/contact-us.html
/#contact-us.html
/main.html#contact-us.html
Since the same portion of the SPA is accessible through multiple URLs, the challenge here is somewhat different from tracking URLs without hash. When tracking URLs without hash as above, we just need to make sure that we’re tracking each screen refresh.
When we’re tracking URLs with hash, we certainly still want to make sure to track each screen refresh, but we certainly should avoid sending different Page dimensions in virtual pageviews to represent the same screen. To avoid fragmenting the virtual pageviews in your GA reports for this example, it’s best to track all of these pages as /contact-us.html.
In all three URL scenarios outlined above – hash, no hash, or no change – you can opt to write entries to the browser history that correspond to the screen changes.
To write to the browser history, you can take advantage of the window.history.pushState() method alongside the JavaScript code that you and your developers are customizing within the SPA framework to make the actual page updates.
For the no-hash examples above, we could push each of the pages to the browser history of follows:
var serializableObj = {slug: “slug”};
window.history.pushState(serializableObj, “User Input”, “/guide/user-input”);
The method requires three arguments: a serializable object, a page title, and – most importantly for our tracking discussion – a page path, as highlighted above.
We could write to the browser history for all of the contact screens with hash above as:
var serializableObj = { slug: “slug” };
window.history.pushState(serializableObj, “Contact Us”, “/contact-us.html”);
Note that changing the browser history in an SPA will have an even more critical benefit than tracking: because the different screens of your SPA are recorded in the browser history, your end users will be able to use the browser back and forward arrows to navigate through their own viewing history.
Apart from this fundamental usability enhancement, the updates that we make to the browser history will also provide an additional option for tracking the SPA screen updates as virtual pageviews.
In the previous section, we reviewed how to update the browser history to correspond to the SPA screen refreshes. As we explained earlier, this in itself will not generate a regular, physical pageview because the page does not reload.
In many cases, the most suitable way to track SPA screen refreshes is through Google Analytics virtual pageviews. Virtual pageviews:
We can set up the virtual pageview tag in GTM. Apart from this, the main consideration will be:
Should I use browser history or the data layer for the trigger and variable(s) that the virtual pageview tag will need?
We outline both approaches below.
If you are writing to the browser history as outlined above, you’re generating the gtm.historyChange event in the GTM data layer, which can serve as the basis of your trigger as you take the following approach to generate a virtual pageview for each screen refresh.
These steps apply when the URL path is being rewritten:
In the case of URLs with hash, we can take advantage of the New History Fragment variable in GTM for both triggering the virtual pageview and populating the page dimension:
Note that we’re explicitly adding the page fragment – i.e., the portion of the URL after a #, which GA would not record by default.
If you have multiple URLs with hashes pointing to the same screen, the data layer approach described below would probably be a more straightforward approach for avoiding multiple Page dimensions for the same SPA screen.
You can use this approach whether or not you’re also updating the browser history. Whenever the user navigates from screen to screen in the SPA, you can push a custom event to the GTM Data Layer and use two of GTM Data Layer variables to add the value of the page path and page title.
dataLayer.push({
‘event’:’pageviewCustomEvent’,
‘pagePath’:’/Contact Us’,
‘pageTitle’ : ‘Contact Us’
});
SPAs use the HTML5 History API to modify a website’s URL without a full page reload. As the SPA uses the HTML5 History API to modify the website’s URL without, this change will trigger a GTM event called “gtm.historyChange”. You can listen to this event using the GTM history change trigger to send pageviews to GA. In the GTM interface, create a history change trigger and create a custom JS variable to get the page title. Use the trigger that you created to fire the pageview tag and the built-in Page Path variable to get the value of the page path and the custom JS variable you created to get the page title. Check the following screenshots.
Virtual Pageviews as Goal Funnel Steps
Every SPA framework has its own way to navigate and to fire events. Use the method that you see it suitable for your case. Tell us about your Front-end Framework and we will be happy to help 🙂
Happy Tagging!
As consumers become increasingly digitally savvy, and more and more brand touchpoints take place online,…
Marketers are on a constant journey to optimize the efficiency of paid search advertising. In…
Unassigned traffic in Google Analytics 4 (GA4) can be frustrating for data analysts to deal…
This website uses cookies.