Single Page Applications (SPAs) update the URL and the visible page without a full page reload. Because of this, a script tag added to <head> only runs once — on the first load — and the CookieChimp widget can be torn down or lost when the user navigates between routes.
This page covers two things:
- How to load the CookieChimp script so it runs on every page, framework by framework.
- How to position the Privacy Trigger so the floating icon survives client-side navigation.
How do I install CookieChimp in an SPA?
The pattern is the same across all SPA frameworks:
- Inject the script into
<head> so it loads as early as possible — ideally before the framework hydrates.
- Re-initialize the widget on every client-side route change by listening to the framework’s navigation event.
The exact navigation event differs per framework. Pick yours below.
The reinit pattern is the same across frameworks: remove the existing CookieChimp script tag (if any) and append a fresh one. Loading the script again triggers CookieChimp to rescan the newly mounted DOM. There’s no public reinitialize() API — script re-injection is the documented mechanism.
Astro
Astro’s View Transitions emit an astro:page-load event after every navigation including the first, so this single handler covers both initial load and subsequent transitions — no separate static <script src> needed. Use is:inline so Astro doesn’t bundle the script.
Add this to your root layout — typically src/layouts/Layout.astro — inside <head>:
Replace YOUR_ACCOUNT_ID with your actual CookieChimp Account ID from your dashboard.
Not using View Transitions? If you haven’t enabled <ViewTransitions /> in your layout, Astro performs a full page reload on each navigation — the standard <script src="..."> install works without any re-initialization logic.
Vue (Vue Router)
Add the script tag in your index.html <head> for the initial load, then re-inject on every subsequent route change from your router config (src/router/index.js):
React (React Router v6+)
Add the script tag in your index.html <head> for the initial load, then mount a tiny component that re-injects on subsequent route changes:
SvelteKit
Add the script to src/app.html inside <head> for the initial load, then re-inject on subsequent navigations from your root layout:
Generic SPA (no router events)
If your framework doesn’t expose a router event you can hook into, listen for history.pushState and popstate — this fires on both programmatic navigation and back/forward:
How do I position the Privacy Trigger in an SPA?
The Privacy Trigger is the floating icon users click to update their consent preferences. By default it’s appended to <body>, which is fine for traditional pages — but in an SPA, you usually want it in a specific spot in your layout and you want it to survive route changes.
Place a <div> with the ID cookiechimp-container wherever you want the trigger rendered:
Put this in a part of your layout that doesn’t unmount on navigation — typically the root layout, just inside <body>.
Persisting across view transitions
Some frameworks tear down and recreate DOM nodes between routes, which would remove the Privacy Trigger. Use the framework’s “persistent element” attribute to keep it:
See the Astro docs on persisting components and the Turbo docs on persisting elements across page loads.
How do I run code based on consent?
The cc:onConsented event fires once when the user has made an initial choice (and on subsequent page loads when consent is already stored).
The cc:onUpdate event fires when the user changes their consent from the preferences modal.
For all available events, see Callbacks & Events.
Troubleshooting
- Banner shows on first load but not after navigation — your re-initialization listener isn’t firing. Double-check the framework-specific event name (
astro:page-load, router.afterEach, useLocation, afterNavigate).
- Privacy Trigger disappears after navigation — add the framework’s persistence attribute (
transition:persist, data-turbo-permanent) to your #cookiechimp-container div.
- Banner doesn't appear at all — confirm
localhost (or your domain) is in Additional Domains in Account Settings.
- Enable Debug mode in the CookieChimp dashboard and check the browser console for logs.