MeasureSchool logo

Track Single Page Applications with GA4 & GTM

Last Updated: September 15, 2023

Many websites have adopted the Single Page Application structure to provide a responsive and smooth user experience and more will join their ranks in the future.

But this can make tracking a bit more complex compared to traditional websites. Now that the date of Universal Analytics’s retirement draws closer, it’s even more important to figure out how to track single page applications (SPAs).

In this post, we will look at what SPAs are, why they need to be set up differently, and explore how GA4 and GTM can be used to effectively track SPAs. 

We will also cover some common challenges that arise when tracking SPAs. Additionally, we will provide some best practices for optimizing your SPA tracking setup.

Here’s a quick overview of what you’ll learn:

Let’s get started!

What are Single Page Applications?

A single page application or website is one where each page of the content is not required to be loaded every time you navigate to different pages because it loads everything in the first instance.

Now, you might see that the URLs change when you click on different links, buttons, and pages, but they are just to give you an idea that a new page has been loaded when technically it does not as the content is served dynamically.

So if there’s no refresh then it means the tracking code only loads and fires once regardless of what other content you see. 

Logically, that also means you would see only one session for that user because the page never reloads, which has been the case with UA.

Another important thing to note is that Single Page Applications can be confused with Single Page Websites, but they are different.

Single page websites have all the content on one page where you scroll through different sections to get the information you want. There’s often a sticky navigation bar that follows you around.

Clicking on the links/buttons often leads you to that section on the same page, as they are anchor links without reloading the page.

GA4 came with Enhanced Measurement which can be helpful to track SPAs in general. However, for some SPAs, you might need to do additional work with GTM to correctly track them.

But if it is such a problem, why do SPA websites exist? Here are some reasons:

  1. They load very fast as all the resources like HTML, CSS, and Scripts in the backend load simultaneously. This also makes it easier for SPAs to provide smooth transitions while providing all the information quickly.
  1. SPAs can cache data effectively as they send a single request to the server and save all the data which can also be used if the users go offline or have a bad internet connection.
  1. They are easy to debug with the browser’s developer tools because it’s easier for the devs to go through the rendered JS vs so many lines of code.
  1. Development of SPAs can be much faster compared to traditional websites because the front end and back end can be separated. As a result, more developers can work at the same time, and making changes to one end doesn’t affect the other.
  1. They are easy to convert to iOS and/or Android apps as the same backend web app code can be used to develop the apps.

Some major examples of SPAs are Netflix, Facebook, Twitter, and Gmail, so they are not as problematic as you might think.

How to Track SPAs?

There are generally three widely used methods to track SPAs. These are:

  1. GA4’s Enhanced measurement to track pageviews
  2. GTM’s History Change trigger
  3. Data layer Push and GTM

So let’s see how you can use each.

GA4’s Enhanced Measurement to Track Pageviews

To do this, we need to go to the Stream settings. Click on the Admin cog in the bottom left → Data Streams under the property column → Select the stream.

Data streams in GA4 admin settings

You will now see the Web stream details, so click on the settings cog under Enhanced measurement.

Webstream details with enhanced measurement

Here click on the Show advanced settings

GA4’s Enhanced measurement page views with advanced settings hidden

Check the Page changes based on browser history events.

GA4’s Enhanced measurement page views with advanced settings shown

Other Enhanced measurement events like Scrolls, Outbound clicks, and Site search might not work as expected as they will understate or overstate their numbers. Therefore it’s better to turn them off or set them up with GTM to ensure they work properly.

Enhanced measurement settings in GA4

Once all is done, you can click on the Save button in the top right corner.

To verify whether it’s working properly or not, we can go to GTM’s preview mode. Log into GTM and click on the Preview button in the top right corner.

Preview button in GTM

This should open another window where you can enter the URL of your website and click on the Connect button. Once connected, this page will refresh and show tracking information about your website.

GTM preview mode website URL interface

Now you should be seeing the history change event, aka, gtm.historyChange-v2, when you’ve selected the GTM container on the top.

GTM preview mode showing history change event

Next, you can click on GA4’s measurement ID on the top to see if the pageview event is being sent or not.

GTM preview mode showing page view event sent to GA4

What if you don’t see the events being sent to GA4? Then, it’s time to try the second method.

GTM’s History Change Trigger

As you may have noticed, this method also tries to listen to changes in the website’s history as GA4’s built-in enhanced measurement does.

This history change event can then be used to send page view events to GA4. How? 

Let’s start by logging into GTM. Next, go into Triggers and click on the New button.

GTM interface to create a new trigger

Here, scroll down and choose History Change as the trigger type.

Screenshot of History change trigger in GTM

Next, set it to fire on All History Changes and Save it.

History change settings in GTM

It should work now, but let’s test it. Let’s go into GTM’s preview mode as we did in the first method.

GTM preview mode screenshot showing history change events

As you can see, we have the GA4 config tag firing, but we also have multiple History events, which can happen with some SPA websites.

🚨 Note: The GA4 configuration tag has been replaced with the new Google Tag.

If this happens, then you should investigate and set triggers based on some changes vs all changes, so that the data is not being polluted.

Data layer Push and GTM

The third method works when the first two methods fail and involve using a developer to push a data layer into the code which you can use to store values and trigger pageviews. 

Here’s an example of how the code could look:

 window.dataLayer = window.dataLayer || [];
 'event': 'virtualPageview',
 'pageUrl': ',
 'pageTitle': 'Learn GA4' //Some name for the page/content to differentiate

Values for pageUrl and pageTitle should be populated dynamically as they will change for every page and/or content type.

Ideally, this will be sorted by the developer along with any hashtags, question marks, and other query parameters in the URLs.

Once the data layer has been pushed, we can complete the setup in GTM in the following three steps:

  1. Setting up two data layer variables
  2. A custom event trigger
  3. GA4 page_view event tag to send the data to GA4

Let’s begin by setting up the data layer variables, one for the pageUrl and one for the pageTitle. 

  1. Go into Variables → Click on New → Select the Data Layer Variable type and set up the variables like this:
Page Url data layer variable in GTM
Page title data layer variable in GTM

Now we can store the values of the page URL and page title in data layer variables.

  1. Next, we want to set up a trigger based on the custom event that is mentioned in the data layer above, i.e., virtualPageview. Go to Triggers New → Select Custom Event as trigger type and set up as follows:
Custom event trigger for virtual pageview event in GTM
  1. Go to Tags → Click on New → Select GA4 Event as the tag type and set up as shown below:
    1. Event Name: page_view
    2. Event Parameters and Value
      1. page_location value of DLV – pageUrl variable
      2. page_title value of DLV – pageTitle variable
    3. Trigger Type: whenever there’s a virtualPageview custom event detected
GA4 event tag for virtual page view event with page location and page title as event parameters

Don’t forget to test the third method in GTM’s preview mode as well as GA4’s DebugView, to ensure that you’re receiving the correct data, especially for the page_location (URL) and page_title parameters.

Why didn’t we add these parameters to the GA4’s Configuration Tag? This is because GA4 looks at the parameters only when the page loads, which means only once for an SPA website.

So, you don’t get to see the later values that keep changing, you only get the values sent the first time when the page loads.

Some of these methods can be somewhat tricky, but they are doable for the most part.

Common Challenges with Tracking SPAs

Knowing the challenges with SPAs isn’t necessary but it will help you to deal with them better. Let’s learn about some of the common ones:

  1. You won’t be able to track anything if Javascript is not enabled, as SPAs don’t work without JS. That’s something that cannot be bypassed easily. However, there are solutions like doing server-side rendering, even though it can still get complicated as other functions might not work properly.
  1. If the URL has different parameters and fragments like hashtags or question marks, then it won’t be tracked by default. So, you will have to store the full URL in the Javascript variable using the window.location.href value and then override the page_location parameter’s value with this variable for every GA4 event tag.
Javascript variable to store full URL
  1. If several history change events show up in GTM preview mode, they should be looked into to eradicate duplicate data, by adjusting the trigger to fire on some specific history change events.
  1. When using the data layer method you see the virtualPageview event every time you load the website, then you should disable the Send a page view event when this configuration loads option. 
GA4 config tag with a check to send a pageview event whenever it loads
  1. When there is a rogue referral issue, i.e., when Google attributes paid traffic as organic traffic, this should be handled. You can read more about the rogue referral issue in Simo Ahava’s article. Unfortunately, this fix doesn’t work with GA4 at the moment. 

This is not an exhaustive list and there could be other challenges based on your website’s setup, but these should help you to know what to expect.

Best Practices to Track SPAs

Here are some best practices to keep in mind when you’re tracking SPAs:

  1. Use the developer’s help if it’s available and go through the data layer method.
  1. Test and verify your setup with GTM’s preview mode and GA4’s DebugView, to ensure there are no duplicate or wrong data captured.
  1. If your website has URLs with fragments, i.e., #, then ensure you’re storing the full URL in the Javascript variable and overriding the page_location parameter with the value of that variable for all the GA4 event tags.
  1. Don’t add page_location and page_title parameters in the GA4 configuration tag. Create a separate GA4 event page_view event tag to override these parameters.
  1. Check if you need to use the Send a page view event when this configuration loads option with the GA4 configuration tag or not.

These best practices should be helpful enough to avoid common data collection issues.


What are the three widely used methods for tracking SPAs using GA4 and GTM?

1. GA4’s Enhanced Measurement to track pageviews.
2. GTM’s History Change Trigger, which listens for history change events to track pageview events.
3. Data Layer Push and GTM, where developers push data into the data layer to trigger pageview events.

What are some best practices for tracking SPAs?

Here are some best practices to consider:

1. Involve developers and utilize the data layer method if possible.
2. Test and verify the tracking setup using GTM’s preview mode and GA4’s DebugView.
3. Handle URLs with fragments by storing the full URL in a JavaScript variable and overriding the page_location parameter.
4. Create a separate GA4 event tag for the page_view event to override page_location and page_title parameters.
5. Evaluate the need for the “Send a page view event when this configuration loads” option in the GA4 configuration tag.

Why is tracking single page applications (SPAs) more complex compared to traditional websites?

SPAs load content dynamically without full page reloads, which makes tracking more challenging as traditional tracking methods rely on page refreshes. SPAs require different tracking approaches to capture user interactions effectively.


We have learned 3 different methods, with their nuances, to track SPAs. If you want to know what’s the best method, then it’s the one using available resources and activating the data layer.

However, if you don’t have access to a developer, then you can use either of the other methods – whichever works!

We then looked at some common challenges you can face when tracking SPAs and some best practices to help you collect useful data. All of this information can set you up to track your SPA website.

As more and more websites are moving towards SPA architecture, it will be very helpful to know how to track them.

But there are still tons of websites with multi-page application (MPA) architecture like blogs with a lot of content, like Measureschool’s and e-com stores. So, it’s still super helpful to know how to set up Google Analytics 4 e-commerce tracking.

Any challenges or best practices for tracking SPAs that we missed here? Please feel free to share with our readers in the comments!



Master Data & Analytics with MeasureMasters

Exclusive Courses & Workshops | Ongoing Troubleshooting | Support Resources, Tools & much more

Don't miss it!!!

50% OFF

on Google Tag Manager Essentials

+3 BONUS Courses

Don't miss it!!!

50% OFF

on Google Tag Manager Essentials

+3 BONUS Courses

Related Posts

Notify of
Inline Feedbacks
View all comments

Want to find the Best Sources for Learning GTM? Subscribe & Get our FREE Resource Guide

Google Tag Manager FREE Resource Guide

Get a FREE Complete Google Analytics 4 Audit Checklist

GA4 Audit Checklist

now it's time to

Start measuring like a master

Itching to jump into the world of MeasureMasters? This is what you have to look forward to.

Ready to take your digital marketing to the next level?

Subscribe to our newsletter and stay ahead with our latest tips and strategies.