Launch Offer2 free audits with all 229 checks. No credit card required.Start free audit

SPA Tracking in GA4: React, Vue, Next.js, and Angular Without the Pageview Bugs (2026)

Intermediate

Why does GA4 underreport pageviews on my React/Vue/Next app?

Single-page apps don't trigger fresh page loads on navigation — the URL changes via the History API but no full page-load event fires. GA4's automatic page tracking listens for full page-load events, so route changes are missed. The fix: manually fire a virtualPageView event on every route change, capturing the new URL, title, and referrer.

Each framework has its own pattern: Next.js App Router uses usePathname() + useSearchParams() in a layout component; React Router v6+ uses useLocation() listener; Vue Router uses navigation guards (router.afterEach); Angular uses Router events. The timing gotcha: route events fire BEFORE the new page renders, so reading from DOM at that moment returns stale or empty values.

Read URL/title from the route configuration, not from the DOM.

What goes wrong by default

GA4's Enhanced Measurement listens for browser page-load events to fire automatic page_view events. In a traditional multi-page site, every navigation triggers a page-load event, GA4 fires page_view, all is well.

In a single-page app:

  • User clicks a link
  • Framework intercepts the click
  • URL changes via history.pushState()
  • Framework swaps content in the DOM
  • No page-load event fires — the page didn't actually reload
  • GA4's Enhanced Measurement misses the navigation
  • Only the initial app load is tracked as a page_view

Result: a 50-page SPA looks like a single page in GA4 reports. Sessions show 1 pageview per session even when users are clearly browsing extensively.

The fix: manual virtualPageView events

The pattern: detect route changes, manually push a page_view event with the new URL.

For GTM-based implementations:

In GTM, configure a trigger on virtualPageView event that fires the GA4 page_view tag.

For gtag-based implementations:

Either way, the key is firing on every route change. Implementation is framework-specific.

Framework-specific patterns

Next.js App Router (the 2026 default)

Create a Suspense-wrapped component that listens to pathname and search params:

Mount this component once in your root layout. It fires on every navigation.

React Router v6+

Call this hook in your top-level App component.

Vue Router

Note: read page_title from the route's meta config, not from document.title. The DOM title may not have updated yet when the navigation guard fires.

Angular Router

NavigationEnd fires after navigation completes. Earlier events (NavigationStart, ResolveStart) fire too soon.

The timing race condition

The trickiest SPA bug: route events fire BEFORE the new page renders. If your tracking code reads from document.title at that moment, you get the OLD title (the previous page's title), not the new one.

Want to see whether attribution loss is already distorting your channel data?

Symptoms:

  • Page titles in GA4 reports shifted by one navigation
  • New pages get titled with the previous page's title
  • Stakeholder reports show "everyone visits the homepage" because the homepage's title is the most common cached value

Three fixes:

Fix 1 — Read from route configuration

Each framework has a way to access the route's metadata (title, page name) without reading from DOM:

  • Next.js: metadata API in page/layout files
  • React Router: route config or component props
  • Vue Router: route.meta.title
  • Angular: route.data['title']

Use the framework's metadata, not document.title.

Fix 2 — Defer the push

Use setTimeout(..., 0) to push after the current event loop tick:

This delays the push until after React/Vue/Angular has updated the DOM. Less elegant than Fix 1 but simpler.

Fix 3 — Update title manually before pushing

In your route handlers, set document.title synchronously before pushing the event:

Works but requires discipline across the codebase.

The testing pattern

To validate SPA tracking before shipping:

Test 1 — Manual navigation in DevTools

Open DevTools → Network tab, filter for collect. Navigate through 5-10 routes in your SPA. Each navigation should produce one collect request with the correct page_path.

If you see no requests on navigation, route detection isn't working.

If you see multiple requests per navigation, you've got duplicate firing.

Test 2 — Tag Assistant verification

Install the Tag Assistant extension. Navigate through your SPA. Tag Assistant should show a virtualPageView event for each route change with correct parameters.

Test 3 — DebugView correlation

Open GA4 DebugView in a separate tab. Navigate your SPA. Each route change should produce a page_view event in DebugView within ~30 seconds with correct page_location, page_path, page_title.

Test 4 — Synthetic test

Use Playwright or Puppeteer to automate navigation through your app's main routes. Verify the resulting GA4 events match expected — automated regression testing for tracking.

FAQ: SPA Tracking in GA4: React, Vue, Next.js, and Angular Without the Pageview Bugs

What should a team validate first when spa tracking in ga4: react, vue, next.js, and angular without the pageview bugs appears?

Reproduce the problem in the live implementation, isolate whether it is scoped to one report or flow, and compare it against at least one secondary source before changing the setup.

How do I know whether the fix actually worked?

You need before-and-after evidence in the browser and in the downstream report. A clean-looking dashboard without validation is not enough.

When should this become a full GA4 audit instead of a quick fix?

If the issue touches attribution, consent, revenue, campaign quality, or data trust for more than one workflow, it is usually safer to audit the surrounding implementation than patch only the visible symptom.

Check SPA Tracking in GA4: React, Vue, Next.js, and Angular Without the Pageview Bugs before campaign reporting gets blamed for the wrong issue

Run a free GA4 audit to spot attribution breaks, UTM governance issues, self-referrals, and source/medium loss fast.

These findings come from auditing thousands of GA4 properties. See how your property compares

GA4 Audits Team

GA4 Audits Team

Analytics Engineering

Specialising in GA4 architecture, consent mode implementation, and multi-layer audit frameworks.

Share