Single-page apps
How client-side navigations are counted, and what hash routing needs.
Single-page apps change the URL without loading a new document, so a naive tag counts one pageview per session. Ours does not: it wraps the History API and counts the navigations your framework performs.
This is on by default. React Router, Next.js, Vue Router, SvelteKit and anything else built on pushState work with no configuration at all.
Hash routing
Apps that route on the fragment (#/dashboard) never touch the History API, so add data-hash="true". The fragment then becomes part of the tracked URL.
<script defer data-domain="example.com" data-hash="true"
src="https://causalit.fr/js/s.js"></script>Duplicate pageviews
Consecutive navigations to the same URL are collapsed into one. Frameworks that call replaceState on every render would otherwise inflate your numbers — an inflated number is worse than no number.
Turning it off
Set data-spa="off" if you would rather emit pageviews yourself, then call the tag manually at the moments that count as a page in your product.