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
| Router | Integration needed |
|---|---|
| Next.js (App and Pages Router) | None |
| React Router, TanStack Router | None |
Vue Router (createWebHistory) | None |
| Nuxt, SvelteKit, Remix | None — they use the History API |
Hash-only routers that only assign location.hash | Check 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.