window.history exposes the tab's session history: length, back(), forward(), go(n), scrollRestoration and state. pushState(state, unused, url) adds an entry and changes the address bar without loading anything, and replaceState() edits the current entry; single-page routers are built on them. The middle argument is ignored, and a cross-origin URL throws a SecurityError. The listing ran at /product/7.
addEventListener('popstate', (e) => console.log('popstate:', location.pathname, e.state));
history.pushState({ tab: 'reviews' }, '', '/product/7/reviews'); // no request, no event
console.log(JSON.stringify(history.state), location.pathname);
history.back(); // same as history.go(-1)Output
{"tab":"reviews"} /product/7/reviews
popstate: /product/7 nullpopstate fires only when history is traversed, never on pushState(). States are structured-cloned and Firefox 555 caps their size, so store bulky data in sessionStorage. The Navigation API, Baseline since January 2026, fixes most rough edges (History and Navigation).