Single-page apps
A single-page app changes the page without reloading, so a script that only counted on load would see one pageview per visit. Lynq watches navigation instead.
What counts as a pageview
The script patches history.pushState and history.replaceState and listens to popstate and hashchange. A pageview is recorded when the path, or an allow-listed query parameter, changes. A hash-only change is not a pageview, and neither is a replaceState to the same URL, which apps use to keep state in the address bar.
A page restored from the back/forward cache is a new pageview.
This covers Next.js, Astro with view transitions, React Router, Vue Router, SvelteKit and anything else built on the History API. There is nothing to call.
Engagement across navigations
Engaged time and scroll depth are kept per pageview. When the path changes, the previous page’s engagement is sent with the pageview that ends it, so time on page is right for each route.
Events after navigation
window.lynq is the same object for the life of the tab; call track() from anywhere. In a framework, call it from an event handler or an effect, not during render, so a re-render does not record the event twice.
Tabs
The session lives in the tab. A tab opened from a link with rel="opener" continues the session; a tab opened with target="_blank" starts a new one. See how Lynq counts.