# Single-page apps

Page views, Web Vitals, and errors during client-side navigation.

The [tracking script](https://docs.kogut.dev/web-apps/tracking-script/) follows client-side navigation by itself.

## Navigation detection

The script listens for the Navigation API's `currententrychange`. In other browsers, it
wraps `history.pushState` and `history.replaceState` and listens for `popstate`.

Only a path change counts as a new page view. Query changes, fragments, and state
replacements on the same path do not count. A back/forward cache restore counts again,
even on the same path.

Only the first page view has a referrer.

## Per-route measurements

On a path change, the script sends the previous route's Web Vitals and starts a new
page view. CLS and INP reset. The new route has no LCP, FCP, or TTFB because no document
loads. The [error limit](https://docs.kogut.dev/web-apps/javascript-errors/#limits-in-the-browser) also resets.

A back/forward cache restore resets the same measurements. Browsers stop reporting LCP
after the initial document load.

## Paths with ids

`/orders/1042` and `/orders/1043` are two pages, not one route pattern.

## Hash routing

Fragment routes such as `/#/orders` share a path and count as one page. History API
routing gives each path its own page view.
