How to add a cookie consent banner to a Vue 3 app
In a Vue 3 app built with Vite, put the snippet in index.html at the project root, in the head and above the script that loads src/main. Mark tracking tags in the same file, and read the visitor's choice in components with a small composable that listens to Cookiequiet's cq:consent event; send route-change page views from router.afterEach only when analytics is granted.Steps
Where does the snippet go in a Vue app?
A Vue 3 app created with create-vue uses Vite, whose entry point is index.html at the project root. Paste the snippet in its head, above the module script that loads your app:
html<!doctype html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><script src="https://cookiequiet.com/cq.js" data-site="%VITE_COOKIEQUIET_SITE%" data-consent-mode="1" data-auto-block="1" defer></script><title>My app</title></head><body><div id="app"></div><script type="module" src="/src/main.ts"></script></body></html>
Vite replaces %VITE_COOKIEQUIET_SITE% with the variable from your .env file and leaves the text unchanged when the variable is not defined, so check the built file or write the key directly. Module scripts run after parsing, in document order with deferred scripts, so cq.js above the entry script runs before your app.
The snippet stays in HTML: do not add it from a component or bundle it. It reads its settings from its own tag and must run before the tags it controls. If you use Nuxt rather than plain Vue, follow the Nuxt guide.
How do I block my tags until consent?
Paste tracking tags under the snippet in index.html and change their opening tag:
html<script type="text/plain" data-cq-category="analytics" src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"></script><script type="text/plain" data-cq-category="analytics">window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('config', 'G-XXXXXXX');</script>
Cookiequiet runs them when the category is granted, and at once on later visits where the stored choice includes it. To keep the Google tag loading under Consent Mode instead, see the Google Analytics 4 guide. Scripts and iframes that your code or a library creates at runtime are held by the auto-blocker when they come from one of the about 80 trackers it knows.
How do components read the choice?
Cookiequiet dispatches a cq:consent event on window each time it applies a choice: a stored one on load, a new one after a click, and every category in regions where geo-targeting does not show the banner. event.detail.categories lists the granted categories; window.Cookiequiet.get() returns the choice in force (categories in c, a: "geo" where no banner is shown) or null while no choice applies yet. A composable:
ts// src/composables/useConsent.tsimport { ref } from "vue";const cq = (window as any).Cookiequiet;const granted = ref<string[]>(cq?.get()?.c ?? []);window.addEventListener("cq:consent", (e) => {granted.value = (e as CustomEvent).detail.categories;});export function useConsent() {return granted;}
In a component:
vue<script setup lang="ts">import { useConsent } from "@/composables/useConsent";const granted = useConsent();const openPreferences = () => (window as any).Cookiequiet.showPreferences();</script><template><iframe v-if="granted.includes('marketing')" src="https://www.youtube-nocookie.com/embed/VIDEO_ID" title="Video"></iframe><button v-else @click="openPreferences">Allow videos</button></template>
What about route changes?
Vue Router changes the URL without reloading. The snippet runs once per full load, the choice stays applied and the banner does not reappear. Marked scripts are activated on load and after each choice, so keep them in index.html rather than in components. For page views per route, use a global after hook, which Vue Router calls after each navigation:
ts// src/router/index.tsimport { useConsent } from "@/composables/useConsent";const granted = useConsent();router.afterEach((to) => {if (granted.value.includes("analytics")) sendPageView(to.fullPath); // your analytics call});
How do I add the Cookie preferences link?
html<a href="#cq-preferences" data-cq-show-preferences>Cookie preferences</a>
Cookiequiet handles clicks on this link anywhere in the page and opens the preferences centre.
How do I test it?
- Run
vite buildandvite preview, then view the page source:cq.jsis the first script. - Open the app in a private window and click Reject all: the cookies are
cq_consentand your own. - Clear the cookies, click Accept all, reload: the marked tags run. Change routes and check the page views.
- Open the consent log in the dashboard.
A Content Security Policy must allow https://cookiequiet.com in script-src and connect-src. Cookiequiet is free for one website with geo-targeting; Starter is €3 per website per month, with no pageview limit on any plan.