Documentation Index
Fetch the complete documentation index at: https://docs.cookiechimp.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
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>:
<script is:inline>
function runCookieChimp() {
document.getElementById("cookiechimp-js")?.remove();
var script = document.createElement("script");
script.src = "https://cookiechimp.com/widget/YOUR_ACCOUNT_ID.js";
script.id = "cookiechimp-js";
document.head.appendChild(script);
}
// Fires on first load AND after every Astro view transition.
document.addEventListener("astro:page-load", runCookieChimp);
</script>
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):
import { createRouter, createWebHistory } from "vue-router";
const router = createRouter({
history: createWebHistory(),
routes: [/* ... */],
});
let isInitial = true;
router.afterEach(() => {
if (isInitial) {
isInitial = false;
return;
}
document.getElementById("cookiechimp-js")?.remove();
const script = document.createElement("script");
script.src = "https://cookiechimp.com/widget/YOUR_ACCOUNT_ID.js";
script.id = "cookiechimp-js";
document.head.appendChild(script);
});
export default router;
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:
// src/components/CookieChimpReinit.tsx
import { useEffect, useRef } from "react";
import { useLocation } from "react-router-dom";
export default function CookieChimpReinit() {
const { pathname } = useLocation();
const isFirstRender = useRef(true);
useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
document.getElementById("cookiechimp-js")?.remove();
const script = document.createElement("script");
script.src = "https://cookiechimp.com/widget/YOUR_ACCOUNT_ID.js";
script.id = "cookiechimp-js";
document.head.appendChild(script);
}, [pathname]);
return null;
}
// src/main.tsx
<BrowserRouter>
<CookieChimpReinit />
<App />
</BrowserRouter>
SvelteKit
Add the script to src/app.html inside <head> for the initial load, then re-inject on subsequent navigations from your root layout:
<!-- src/routes/+layout.svelte -->
<script>
import { afterNavigate } from "$app/navigation";
import { browser } from "$app/environment";
let isInitial = true;
afterNavigate(() => {
if (!browser) return;
if (isInitial) {
isInitial = false;
return;
}
document.getElementById("cookiechimp-js")?.remove();
const script = document.createElement("script");
script.src = "https://cookiechimp.com/widget/YOUR_ACCOUNT_ID.js";
script.id = "cookiechimp-js";
document.head.appendChild(script);
});
</script>
<slot />
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:
<script>
function runCookieChimp() {
document.getElementById("cookiechimp-js")?.remove();
var script = document.createElement("script");
script.src = "https://cookiechimp.com/widget/YOUR_ACCOUNT_ID.js";
script.id = "cookiechimp-js";
document.head.appendChild(script);
}
// Patch pushState/replaceState so we get notified on client-side navigation.
["pushState", "replaceState"].forEach((method) => {
var original = history[method];
history[method] = function () {
var result = original.apply(this, arguments);
window.dispatchEvent(new Event("locationchange"));
return result;
};
});
window.addEventListener("popstate", () => window.dispatchEvent(new Event("locationchange")));
window.addEventListener("locationchange", runCookieChimp);
// First load.
runCookieChimp();
</script>
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:
<div id="cookiechimp-container"></div>
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:
<!-- Astro (View Transitions) -->
<div id="cookiechimp-container" transition:persist></div>
<!-- Hotwire Turbo -->
<div id="cookiechimp-container" data-turbo-permanent></div>
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).
window.addEventListener("cc:onConsented", function (event) {
if (CookieChimp.acceptedCategory("analytics")) {
// "analytics" category enabled
}
if (CookieChimp.acceptedService("Google Analytics", "analytics")) {
// "Google Analytics" service enabled
}
});
The cc:onUpdate event fires when the user changes their consent from the preferences modal.
window.addEventListener("cc:onUpdate", function (event) {
var detail = event.detail;
/**
* detail.cookie
* detail.changedCategories
* detail.changedServices
*/
if (detail.changedCategories.includes("analytics")) {
if (CookieChimp.acceptedCategory("analytics")) {
// "analytics" category was just enabled
} else {
// "analytics" category was just disabled
}
if (detail.changedServices["analytics"].includes("Google Analytics")) {
if (CookieChimp.acceptedService("Google Analytics", "analytics")) {
// "Google Analytics" service was just enabled
} else {
// "Google Analytics" service was just disabled
}
}
}
});
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.