Skip to content
Docs menu · Single-page apps

Install — Web

Single-Page Apps and Route Changes

How AnyReplay records route changes in single-page apps: History API tracking, the $navigate marker, page counts, and sessions that continue across reloads.

In a single-page app the URL changes without a page load. rrweb records the DOM changes that come with it, but nothing in those changes says "this is a new page". The AnyReplay recorder adds that signal itself, so route changes show on the timeline and count as pages — with no router integration.

What is detected

  • history.pushState — a router moving to a new route.
  • history.replaceState — a router replacing the current entry.
  • popstate — the visitor pressing back or forward.

After each of these the recorder compares location.href with the last URL it saw. If it changed, it records a $navigate marker carrying { url, title }, adds one to the session's page count, and the player shows a route marker on the timeline. If the URL is the same — routers often call replaceState to save a scroll position — nothing is recorded.

Titles

The title in the marker is document.title at the moment the URL changes. Many routers update the title a moment after the URL, in which case the marker carries the previous page's title; the URL is always the new one.

Frameworks

RouterIntegration needed
Next.js (App and Pages Router)None
React Router, TanStack RouterNone
Vue Router (createWebHistory)None
Nuxt, SvelteKit, RemixNone — they use the History API
Hash-only routers that only assign location.hashCheck a test session for route markers; add track calls if they are missing

Reloads and full page loads

A full page load — a reload, or a link to another page on the same origin — continues the same session when the previous page was active in the last 30 minutes. The session id, chunk numbering and page count are kept in sessionStorage, so the recording picks up where it left off with a fresh snapshot. sessionStorage belongs to one tab: a link opened in a new tab starts a new session.

Marking things that are not routes

Modals, wizard steps and tabs that do not change the URL are not page views. If you want them on the timeline, tag them with custom events:

anyreplay('track', 'modal_opened', { modal: 'upgrade' });

Custom event names use [A-Za-z0-9_.:-], which has no $ — that is what reserves $navigate for the recorder. In the session list, Has event filters on either kind.