Tracking single-page applications (SPAs) can be tricky since they don’t reload full pages, making standard tracking harder. The server-side Google Tag Manager (GTM) helps solve this by handling data on the server side and improving tracking accuracy and performance.
In this guide, we’ll walk you through setting up server-side GTM for SPAs and cover the best ways to manage pageviews, events, and interactions.
A single-page application (SPA) is a web app that initially loads one HTML page and updates its content dynamically as users interact instead of reloading new pages for each action or navigation.
SPAs became popular because they offer critical advantages over traditional multi-page websites:
Examples of SPAs include Gmail, where content updates without reloading the page; Facebook, allowing you to scroll, post, and comment without refreshing; and Trello, where tasks are managed within the same page. SPAs offer a fast, seamless experience for apps with heavy user interaction.
Tracking single-page applications (SPAs) using GA4 and GTM is more complex than tracking regular websites because of how SPAs work. We understand this complexity and are here to guide you through it.
Here's why:
- Unlike traditional websites, there are no full-page reloads, where each click loads a new page (and triggers GA4 "Pageviews"). SPAs load content dynamically. This means the standard "Pageview" trigger doesn’t work the same way.
- Custom event triggers are needed. Since there are no page reloads, you must create custom triggers that detect specific user interactions, like button clicks or changes in the URL, to track meaningful actions.
- Complexity in tracking user flows. With SPAs, users can stay on the same page while interacting with different sections. Tracking these interactions requires setting up more detailed event tracking to capture these page transitions.
- Potential data gaps. You risk missing out on crucial engagement data without proper tracking since GA4 doesn’t automatically track content changes on SPAs. Custom configurations in GTM are necessary to ensure nothing gets lost.
The complexity largely stems from the dynamic behavior of SPAs, which demands more manual setup to guarantee precise data collection. Although Google Analytics 4 includes built-in tracking for these pageviews, it doesn’t always function perfectly immediately. Additionally, certain websites can be complicated to track effectively.
To address this issue, extra configuration is required to track these websites or web apps effectively. But no need to worry — we will show you ways to track single-page applications using Google Analytics 4 and Google Tag Manager.
Here’s how you can effectively track SPAs using three common methods:
1. GA4’s enhanced measurement for pageviews
GA4 has a built-in feature that automatically tracks pageviews in SPAs. It works by detecting URL changes, but it might need some adjustments to track everything correctly, depending on how your site is set up. It's a good starting point but can be better for some sites.
2. GTM’s history change trigger
Google Tag Manager can track when users navigate through a SPA by using the history change trigger. This trigger listens for changes in the browser’s history (like when users move between sections), allowing you to track interactions even though the page doesn’t fully reload.
3. Data layer push with GTM
In this method, you push custom events or page changes to the data layer within your SPA. GTM can then detect these pushes and send the correct data to GA4. This approach gives you more control and lets you track specific interactions more accurately.
If you can implement all three tracking options, it's best to choose the last one, which uses developer assistance and the dataLayer.push. This method gives you the most control and flexibility, making it the most reliable solution. Pushing specific events directly to the data layer ensures that key interactions are captured accurately, even in more complex SPAs. While it may require some developer input, the precision and robustness of this approach make it worth the effort. On our blog, you can find an end-to-end guide on data layer in Google Tag Manager.
Let’s take a closer look at each of the options.
To track single-page applications using Google Analytics 4’s enhanced measurement for pageviews, follow these simple steps:
1. Go to Stream Settings.
Log into your GA4 account and find your data stream settings.
2. Open Data Streams in Admin.
Click on the Admin icon (bottom left), then under the Property section, choose Data Streams and select the stream you want to track.
This will help you set up pageview tracking for your SPA.
3. You'll see the Web stream details. Click the settings cog under enhanced measurement.
4. Click on the Show Advanced settings.
5. Check the Page changes based on browser history events.
Enhanced measurement events like Scrolls, Outbound Clicks, and Site Searches must be tracked accurately, leading to underreported or overstated data. To ensure accurate tracking, turning these off or configuring them using GTM is best.
6. When finished, click the Save button in the top right corner.
To check if everything is working correctly, use GTM's preview mode. Log into GTM, then click Preview in the top right corner.
This will open a new window where you can enter your website's URL. After clicking Connect, the page will refresh and display your site's tracking details.
When you select the GTM container at the top, you should see the history change event, aka gtm.historyChange-v2.
Next, click on your GA4 measurement ID at the top to check if the pageview event is being tracked and sent correctly.
If the events aren’t being sent to GA4, don’t worry—it might be a sign that the current setup isn’t capturing everything properly.
Moving on to the second tracking method is a good idea. This method can provide a more reliable way to record your pageview events and other interactions accurately. Sometimes, different setups work better for specific SPAs, so experimenting with other methods can help.
This method also monitors changes in the website’s history, similar to how GA4’s enhanced measurement feature works.
By detecting these history changes, you can use them to trigger pageview events and send them to GA4.
Here's how to track single-page applications using Google Tag Manager's history change trigger:
1. Log into Google Tag Manager.
2. Go to Triggers and click New to create a new trigger.
3. Scroll down and select History Change as the trigger type.
4. Set the trigger to fire on All History Changes, then click Save.
It should be set up now, but let's test it to ensure. Enter GTM's preview mode just like we did in the first method.
As you can see, the GA4 config tag is firing, but you might also notice multiple History events, which can occur with some SPAs.
🚨 Note: The new Google Tag has replaced the GA4 configuration tag.
If you encounter this issue, it's essential to review and adjust your triggers to fire on specific changes rather than all changes, ensuring the data remains clean and accurate.
The third method comes into play when the first two methods don’t work. This approach requires a developer to push a data layer into the website’s code. The data layer stores values and triggers pageviews within Google Tag Manager.
Here’s an example of how the script code might look:
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'virtualPageview',
'pageUrl': 'https://www.example.com/path/?example#example',
'pageTitle': 'Example title'
});
This lets you directly capture page views and other critical events by integrating them into the site's code.
The values for pageUrl and pageTitle should be dynamic, as they will change for each page or content type. Ideally, the developer will handle this and any hashtags, question marks, or other query parameters in the URLs.
Once the data layer is in place, you can complete the setup in GTM with these three steps:
1. Setting up two data layer variables.
2. Creating a custom event trigger.
3. Configuring a GA4 page_view event tag to send the data to GA4.
Let's start by creating the data layer variables for pageUrl and pageTitle:
1. Go to Variables.
2. Click New.
3. Select Data Layer Variable as the type, and configure the variables accordingly for pageUrl and pageTitle.
4. Now that we’ve stored the values for the page URL and page title in data layer variables, the next step is to create a trigger based on the custom event (virtualPageview) we defined earlier in the data layer.
Here’s how to set up the custom event trigger:
This trigger will activate whenever the virtualPageview event is pushed to the data layer.
5. Next, we’ll create the GA4 event tag to send the data to GA4. Here’s how to set it up:
Configure the tag as follows:
- Event Name: page_view
- Event Parameters and Values:
- Trigger: Set the trigger to fire whenever the virtualPageview custom event is detected
This will send the pageview data, including the dynamic URL and title, to GA4.
Be sure to test the third method in GTM’s preview mode and GA4’s DebugView to ensure the right data is being collected, particularly for the page_location (URL) and page_title parameters.
We didn’t add these parameters to the GA4 Configuration Tag because GA4 only reads them once during the initial page load. This means it would miss later changes on a SPA since the page doesn't fully reload.
Though some of these methods can be challenging, they’re generally doable with some careful setup.
Understanding the challenges of SPAs isn’t essential, but it can make it easier to handle tracking issues when they arise. Here are a couple of common challenges:
1. JavaScript dependency: SPAs rely heavily on JavaScript to function. If JavaScript is disabled, none of the interactions will be tracked, as the application won’t work. While server-side rendering can offer a workaround, it can complicate things, as other dynamic functions may not behave as expected.
2. Tracking URLs with parameters or fragments: URLs that contain parameters like hashtags or question marks aren’t automatically tracked. To handle this, you’ll need to capture the full URL using window.location.href in a JavaScript variable and override the page_location parameter with this value for every GA4 event tag, ensuring the entire URL is captured accurately.
3. If multiple history change events appear in GTM’s preview mode, it’s essential to investigate and eliminate any duplicate data. You can do this by adjusting the trigger to fire only on specific history change events rather than all of them.
4. If you're using the data layer method and notice that the virtualPageview event fires every time the website loads, you should disable the Send a page view event when this configuration loads option to prevent unnecessary page view events.virt
5. Addressing a rogue referral issue, where Google mistakenly attributes paid traffic as organic, is essential. For more details, refer to Simo Ahava’s article on the topic. Unfortunately, this specific fix isn't currently compatible with GA4.
Remember, this is a partial list of challenges, as others may arise depending on your website's setup. However, these points should give you a good idea of what to anticipate.
To effectively track SPAs, it's essential to follow these best practices:
Following these best practices can help you avoid common issues and collect accurate, reliable data when tracking SPAs with GA4 and GTM.
Tracking single-page applications (SPAs) can be tricky, but server-side Google Tag Manager (GTM) makes it much easier to get accurate data. Whether you use GA4’s tools, GTM’s history trigger, or the data layer method, these options help track your dynamic content correctly.
At Stape.io, we’re experts in server-side tracking and provide tools like data layer integration and preview mode to ensure your setup runs smoothly.
Want to improve your tracking? Sign up for Stape for free today and let us help you get the most accurate results for your SPAs! After signing up, you can use our detailed text and video guides on setting up server-side tracking with Stape.
Stape has lots of tags for server GTM! Click on Try for free to register and check them all.