Data Layer Tracking on SPAs: React Angular Vue Challenges | Adslytics | Adslytics

GTM Data Layer How-To Guide

Data Layer Tracking on SPAs: React, Angular, and Vue Challenges

By Muhammad Farooq · March 21, 2026 · 6 min read
Data Layer Tracking on SPAs: React, Angular, and Vue Challenges

Why SPAs Break Standard GTM Tracking

Traditional websites load a new HTML page on each navigation — GTM fires on each page load, and Google Analytics registers a new page view automatically. Single-page applications (SPAs built with React, Angular, or Vue) navigate client-side, changing the URL via the browser history API without a full page reload. GTM's container does not re-initialise, so no page view is fired unless you explicitly push one to the data layer.

Detecting Route Changes

Each framework exposes route change events differently:

React (React Router)

// In a route-tracking component or layout
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

export default function RouteChangeTracker() {
  const location = useLocation();
  useEffect(() => {
    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({
      'event': 'virtual_page_view',
      'page_path': location.pathname + location.search,
      'page_title': document.title
    });
  }, [location]);
  return null;
}

Angular (Router Events)

// In AppComponent or a route tracking service
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs/operators';

constructor(private router: Router) {
  this.router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe((event: NavigationEnd) => {
    (window as any).dataLayer = (window as any).dataLayer || [];
    (window as any).dataLayer.push({
      'event': 'virtual_page_view',
      'page_path': event.urlAfterRedirects,
      'page_title': document.title
    });
  });
}

Vue (Vue Router)

// In main.js or App.vue
router.afterEach((to, from) => {
  if (typeof window !== 'undefined') {
    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({
      'event': 'virtual_page_view',
      'page_path': to.fullPath,
      'page_title': document.title  // Update document.title before this fires
    });
  }
});

GTM Configuration for SPA Page Views

In GTM:

  1. Create Data Layer Variables: DL - Page Path (reads page_path), DL - Page Title (reads page_title)
  2. Create a Custom Event trigger: event equals virtual_page_view
  3. Create a GA4 Configuration tag (or GA4 Event tag for page_view event) triggered by this custom event
  4. In the GA4 tag, override the page path with the DL - Page Path variable

History Change Trigger (Alternative)

GTM has a built-in "History Change" trigger type that fires when the browser history changes (pushState/replaceState). This works for SPAs without adding framework-specific code:

  1. Create a new trigger → History Change
  2. Trigger on all history changes, or filter by URL path pattern
  3. Use in combination with the built-in {{Page Path}} variable

Limitation: the History Change trigger fires before document.title updates in some frameworks — the data layer push approach gives more control over when the event fires relative to content rendering.

SPA-Specific Pitfalls

  • Document title not updated: push the virtual_page_view after the route renders, not just after the URL changes
  • Double counting on initial load: GTM fires a page view on initial load AND your virtual_page_view fires — filter out the initial state from history change tracking
  • Ecommerce data persistence: data layer values persist across route changes in SPAs — always push ecommerce: null on route change to clear stale product data

Summary

SPAs require explicit virtual_page_view events pushed to the data layer on each route change. Use framework router events (useLocation in React, NavigationEnd in Angular, afterEach in Vue) to push events. GTM's History Change trigger is a simpler alternative but offers less control over timing. Always clear the ecommerce object on route changes to prevent stale product data.

See our GTM Data Layer Implementation service for SPA tracking setup.

Need SPA analytics implemented correctly? Contact Adslytics.

Need expert tracking setup?

Our Google Tag Manager experts have delivered 500+ tracking setups with a 98% success rate.

Get a Free Consultation →
← Back to Blog
Muhammad Farooq

Author

Muhammad Farooq GTM & Analytics Expert · Adslytics Founder

Tracking specialist with 10+ years of experience in Google Tag Manager, GA4, Server-Side Tracking, and Google Ads. Founder of Adslytics — a dedicated analytics agency with a 98% success rate across 232+ projects on Upwork.

Top Rated Plus LinkedIn Visit the author's profile →