autoPageview will only fire once — on the initial load. This guide shows how to handle tracking correctly in React, Next.js, and Vue.
The key difference with SPAs
In a traditional website, every page navigation triggers a full browser reload, which re-runs the SDK and fires apageview. In a SPA:
- The page loads once
- Subsequent navigations are JavaScript-driven (the URL changes, but the page does not reload)
autoPageviewfires only on that first load- You must manually fire a
pageviewevent on each route change
General rules for all SPAs
- Load the SDK snippet once — in your root HTML file or root component, not in every page/route component
- Call
scanova('init', ...)once — in your app’s entry point - Disable
autoPageview— manage page view events yourself on route changes - Fire
scanova('track', 'pageview')on each route change — using your router’s navigation event or hook
React (Create React App / Vite)
public/index.html — load the SDK:
src/main.jsx or src/App.jsx — init once and track route changes:
Next.js (App Router)
In Next.js App Router, use a client component in your root layout.app/layout.tsx:
components/ScanovaTracker.tsx:
Next.js (Pages Router)
pages/_app.tsx:
pages/_document.tsx:
Vue 3 (Vue Router)
index.html — load the SDK:
src/main.ts:
Common mistakes
| Mistake | Result | Fix |
|---|---|---|
Calling scanova('init', ...) in every page/route component | Multiple init calls → duplicate auto-tracking listeners → doubled events | Call init once in the app root only |
Using autoPageview: true in a SPA | Only fires on first load, misses all navigations | Disable it, track manually on route change |
| Adding the SDK script to every page component | SDK loads multiple times | Load from root HTML or root layout once |
Not waiting for SDK to load before calling track | Silent failures | Use window.scanova?.() optional chaining, or the queue pattern (calls before SDK loads are queued automatically) |
Using autoScroll: true and expecting per-route scroll milestones | Milestones are not reset on route change — a user who scrolled 75% on /home will not re-trigger those milestones on /pricing | Disable autoScroll in SPAs and send scroll events manually if per-route scroll depth matters |