<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.
reinitialize() API — script re-injection is the documented mechanism.
Astro
Astro’s View Transitions emit anastro: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>:
Vue (Vue Router)
Add the script tag in yourindex.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 yourindex.html <head> for the initial load, then mount a tiny component that re-injects on subsequent route changes:
SvelteKit
Add the script tosrc/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 forhistory.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:
<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:How do I run code based on consent?
Thecc:onConsented event fires once when the user has made an initial choice (and on subsequent page loads when consent is already stored).
cc:onUpdate event fires when the user changes their consent from the preferences modal.
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-containerdiv.
- 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.