Consent in Single Page Apps: Why Route Changes Quietly Reset the Rules
A single page app loads once and then pretends. Each click swaps content, updates the URL, and fires a fresh set of page view events, all without the document reload that traditional consent tooling was built around. The banner did its job on the landing view. Nobody checked the fortieth.
The failure is quiet because nothing looks broken. Consent rates report fine, drawn from first views. The data problem sits in the routes after it: product pages, checkout steps, and account screens where tags fire on state captured at load, or on no state at all.
The three places SPA consent leaks
First, the virtual page view. Analytics and advertising tags listen for route changes and fire on each one, and if the consent check lives in a page load handler, it ran once, long ago. The tag fires because its trigger is the router event, not a consent verified event, and the two systems never meet.
Second, state caching. Framework code that reads consent once into a variable at startup keeps using that snapshot after the user opens settings and withdraws a purpose mid session. The banner updates its cookie. The app does not notice. Third, late consent: a user who arrives, navigates six routes quickly, and then refuses has already generated a session of tracking that the refusal cannot retract, which makes the timing of first route tag firing a legal question, not an optimisation.
Wire consent into the router, not around it
The workable pattern treats a consent change and a route change as the same category of event. Tag firing subscribes to a consent aware data layer: on every navigation, the current consent state is pushed first, and tags evaluate against that state for that route. Consent mode signals and their equivalents need re sending on route change where the platform expects per view state, not assuming the initial page value persists.
Withdrawal needs the same plumbing in reverse. When a user revokes a purpose, the app should stop the relevant tags from that point, clear or flag the cookies that purpose set where the platform supports it, and record the route and timestamp of the change. A withdrawal that only takes effect after a manual refresh is a withdrawal the product has not really implemented.
A test script you can actually run
Load the app with a fresh profile. Before touching the banner, navigate five routes by clicking around and watch the network panel: nothing non essential should fire. Refuse, navigate five more, and confirm the refusal held on every route, including routes reached by the back button, which SPAs handle in ways that regularly resurrect stale state.
Then change your mind mid session through the settings link, accept one purpose, and navigate again. The accepted purpose starts firing, the others do not, and no reload was involved. If any step needs a refresh to behave, you have found the bug your consent rate report was hiding.
Related reading
These earlier guides cover connected questions in more depth: Consent Banner Keyboard Focus: The Tab Order Audit Most Teams Never Run, First-Party Cookies Still Need a Consent Decision, and Consent Banner Dark Patterns Regulators Actually Flag.
Frequently asked questions
Why does my consent tool work on landing pages but not in the app?
Most consent tooling was designed around document loads. In a single page app, later views are router events, and tags triggered by those events may never pass through the consent check that ran at first load unless the integration is built for it.
Do I need to reshow the banner on every route?
No. The banner shows once. What must happen on every route is enforcement: the stored consent state is read and applied to that view's tags, so a refusal made on the landing view governs the checkout route too.
What happens when a user withdraws consent mid session?
Tags for the withdrawn purpose should stop firing from that point in the session, and the change should be recorded with its time and context. Continuing to fire until the next full page load means the withdrawal was not honoured when it was made.
How do consent mode signals work in an SPA?
The defaults should be set before tags load, and updates pushed whenever consent changes and, where the platform requires it, refreshed on virtual page views. Treat route changes as page views for consent purposes, because your analytics platform already does.