Lesson 10 of 17
SPA Virtual Pageviews
① Connect your GTM container
Paste your container ID to load it into this page. It only ever runs here.
Advanced: use a specific environment
A single-page app swaps views without ever reloading the browser. It rewrites the URL with history.pushState, so the classic Page View trigger, which only fires on a real page load, never sees the second, third or fourth screen. Your analytics would record one pageview for an entire session.
GTM solves this with the History Change trigger. It listens for pushState, hashchange and the back and forward buttons, then fires a virtual page_view tag for each, so an SPA gets counted like a normal multi-page site.
Goal
Fire a virtual page_view tag on every in-app navigation using a History Change trigger.
Build it in GTM
Create the History Change trigger
Go to Triggers → New and choose History Change. Leave it on All History Changes so it fires on everypushState, hash change and back/forward. This is what replaces the Page View trigger inside an SPA.Read the new Page Path
The built-inPage Pathvariable already reflects the URL after each history change, so enable it under Variables → Configure if it is off. You will send this with your tag so each virtual pageview records the view the user landed on.Fire a virtual page_view tag on it
Create your tag and set the History Change trigger as its firing trigger. On a real site this is a GA4 Event tag with event namepage_view, sending the newPage Path. Here a Custom HTML tag namedCustom HTML - Testcontaining<script></script>is a fine stand-in.
Debug in Tag Assistant
Copy this lesson's live URL and paste it into GTM Preview, that is the page Tag Assistant connects to. It has the clickable elements, so this page stays clean for reading.
- In your GTM, click Preview.
- Paste the live URL above and click Connect.
- Interact with the live page and watch your tag fire in Tag Assistant.
What you should expect to see
gtm.historyChange), and your virtual page_view tag appears under Tags Fired on every one, with the new Page Path attached.Verify your container
Built it? Export your container, Admin → Export Container, choose your workspace, then drop the JSON here to check it against this lesson.
Drop your container .json here
or browse · checked in your browser, nothing is uploaded