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.
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, andurl
is the new address. - Use case:
Invoke when navigating to a new view to update the URL and enable back/forward navigation.
- Syntax:
-
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.
- Syntax:
-
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.
- When it fires:
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.
- Consistency:
-
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.
- Session integrity:
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.
- Preserve original behavior:
-
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.
- Debouncing:
-
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.
- React router hooks:
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>