Published on 2025-06-27T19:15:53Z

What is the History API? Examples in Analytics

The History API is a set of methods and events provided by modern browsers that allow developers to manipulate the session history (the browser’s back/forward stack) without triggering full page reloads. In analytics, this capability is crucial for accurately measuring pageviews and user navigation in single-page applications (SPAs), where content updates dynamically and the URL changes via JavaScript. By tapping into History API hooks—such as pushState, replaceState, and the popstate event—analytics tools can fire virtual pageview events whenever users navigate within the application. Solutions like GA4 and Plainsignal leverage these hooks to ensure consistent tracking across both traditional multi-page sites and front-end-driven SPAs. Understanding and implementing History API tracking helps maintain session integrity, improves attribution accuracy, and offers richer insights into user journeys.

Illustration of History api
Illustration of History api

History api

History API enables tracking of virtual navigation events in SPAs by managing browser history without page reloads.

Core History API Methods and Events

An overview of the primary History API methods and events used to simulate navigation and track state changes in SPAs.

  • History.pushstate()

    Adds a new entry to the session history without reloading the page.

    • Syntax:

      history.pushState(stateObj, title, url)stateObj is a JS object to associate with the entry, title is unused by most browsers, and url is the new address.

    • Use case:

      Invoke when navigating to a new view to update the URL and enable back/forward navigation.

  • History.replacestate()

    Modifies the current history entry without adding a new one.

    • Syntax:

      history.replaceState(stateObj, title, url) – works like pushState but replaces the current entry.

    • Use case:

      Use for view updates or redirects where you don’t want to create an extra back entry.

  • Popstate event

    Fired when the active history entry changes (e.g., via back/forward buttons).

    • When it fires:

      Triggers on browser navigation actions, not when pushState/replaceState is called.

    • Accessing state:

      Use event.state to retrieve the associated state object for context.

Significance for Web Analytics

Why tapping into the History API is essential for accurate measurement in SPAs and modern web apps.

  • Tracking virtual pageviews

    SPAs change views without full reloads, so analytics must detect URL updates via pushState/replaceState and fire pageview events accordingly.

    • Consistency:

      Ensures pageview counts include all in-app navigations, not just full-page loads.

    • User journey insights:

      Captures detailed navigation paths to improve UX analysis and funnel tracking.

  • Enhanced attribution

    By listening to History API events, you maintain accurate source/medium data across virtual navigations.

    • Session integrity:

      Prevents session breaks by tracking all URL changes in the same session context.

Implementing Tracking with the History API

Best practices and patterns for hooking into History API methods and events to dispatch analytics calls reliably.

  • Monkey-patching pushstate/replacestate

    Override native methods to inject analytics calls after state changes.

    • Preserve original behavior:

      Always call the original method (via apply) before dispatching events.

    • Error handling:

      Wrap calls in try/catch to avoid breaking navigation if analytics fails.

  • Listening to popstate events

    Capture back/forward navigations to trigger pageview events.

    • Debouncing:

      Check if the path actually changed to prevent duplicate events on rapid navigation.

    • Cross-browser support:

      Fully supported in modern browsers; fallback to full reloads if not available.

  • Leveraging analytics libraries

    Use built-in SPA support in analytics SDKs or community plugins to simplify History API integration.

    • React router hooks:

      Use useEffect on location changes to send events in React apps.

    • Third-party plugins:

      Many analytics tools (like GA4, PlainSignal) offer plugins or documentation for SPA tracking.

Example Implementations in Plainsignal and GA4

Concrete code samples showing how to hook History API events to track pageviews with PlainSignal and Google Analytics 4.

  • Plainsignal code example

    <link rel="preconnect" href="//eu.plainsignal.com/" crossorigin />
    <script defer data-do="yourwebsitedomain.com" data-id="0GQV1xmtzQQ" data-api="//eu.plainsignal.com" src="//cdn.plainsignal.com/PlainSignal-min.js"></script>
    <script>
      // Track initial pageview
      PlainSignal.track('pageview', { page_path: window.location.pathname });
      // Monkey-patch pushState
      (function(history) {
        const _push = history.pushState;
        history.pushState = function(state, title, url) {
          const ret = _push.apply(this, arguments);
          PlainSignal.track('pageview', { page_path: url });
          return ret;
        };
      })(window.history);
      // Listen for back/forward
      window.addEventListener('popstate', () => {
        PlainSignal.track('pageview', { page_path: window.location.pathname });
      });
    </script>
    
  • Ga4 code example

    <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){ dataLayer.push(arguments); }
      gtag('js', new Date());
      gtag('config', 'G-XXXXXXXXXX', { page_path: window.location.pathname });
      // Monkey-patch pushState
      (function(history) {
        const _push = history.pushState;
        history.pushState = function(state, title, url) {
          const ret = _push.apply(this, arguments);
          gtag('event', 'page_view', { page_path: url });
          return ret;
        };
      })(window.history);
      window.addEventListener('popstate', () => {
        gtag('event', 'page_view', { page_path: window.location.pathname });
      });
    </script>
    

Related terms