How to set up GA4 for a single-page app (React, Vue, Next.js)
In a single-page app, navigating between views never reloads the page. GA4's default page-view tracking fires once, on first load, and then goes silent, so your reports show one page view per visit and nothing else.
Why the default breaks
Standard GA4 tracking counts a page view on page load. A SPA built in React, Vue or Next.js swaps content via the router without a full reload, so there is no second load to trigger a page view. The app feels like many pages to the user but looks like one to GA4. It is also why page title and path show (not set) on these apps.
Send virtual page views on route change
- Hook into your router's navigation event (for example Next.js route change, or React Router's location change).
- On each change, push a page view to GA4 with the new path and title, usually via a
page_viewevent through Google Tag Manager and the data layer. - Turn off GA4's automatic page-view on history changes if it is double-firing, or you will double-count.
Mind the timing
Set the title before you send the page view, or GA4 records the old title or none at all. The same applies to events: fire them after the new view's data layer is populated. SPAs reward careful sequencing, which is exactly where most of their tracking bugs come from.
Want us to check your tracking in 10 seconds?
Pop in your domain and we will show you what is firing, what is not, and where data is leaking. Free, no signup.
Check my tracking freeGet a plain-English audit
We check your live GA4, Google Tag Manager and consent setup by hand and tell you exactly what is wrong. The audit comes off any build.
See how it works & pricingDatahound are analytics and ad-tracking specialists. We fix broken GA4, Google Tag Manager and server-side tracking so every sale, form and call gets counted. Back to datahound.agency · All tracking guides · Why GA4 shows (not set)