For cookie consent in a Vue app, load the consent script in the <head> of index.html, before Vue mounts and before any analytics or marketing tag, then start each tracker only once the visitor accepts its category. A banner built as a Vue component is too late: tags that start in main.js or App.vue set their cookies before it renders. In Nuxt, the same script goes in the head and runs only in the browser.

Why Vue.js apps need a different approach to cookie consent

Vue.js applications run almost entirely in the browser. Unlike server-rendered pages, where each navigation is a fresh HTTP request, a Vue single-page application (SPA) loads once and then handles routing in the browser. That difference has real consequences for cookie consent.

Traditional cookie banners built for multi-page sites often assume scripts load per page view. In a Vue SPA, third-party scripts such as Google Analytics (which sets _ga) or the Meta Pixel (_fbp) may start once when the app boots and stay active across every route change. If those scripts run before a visitor consents, the site breaks Article 5(3) of the ePrivacy Directive, whether or not a banner appears a moment later.

The core rule is plain: non-essential cookies must not be set until the visitor gives explicit, informed consent. Getting that right in a reactive framework means paying attention to script order, state management and the line between server-side and browser-side code.

Cookie categories in a typical Vue application

Before configuring consent, find out which cookies your Vue app actually sets. Kukie.io's scanner can automate this, but knowing the usual categories helps you plan.

CategoryExamplesConsent needed?Notes
Strictly necessarySession cookies from your back end, a CSRF tokenNoNeeded for the site to work
FunctionalA locale or theme cookie your app setsDepends on purposeStores visitor preferences
Analytics_ga, _ga_<container-id>YesTracks page views and behaviour
Marketing_fbp, _gcl_au, li_fat_idYesUsed for ad targeting and retargeting

The distinction matters because your consent setup must block analytics and marketing cookies by default while strictly necessary cookies work immediately. Functional cookies sit in a grey area: a preference the visitor chose themselves is often treated as part of the service, while one set automatically usually needs consent.

A note on packages: vue-cookies describes itself as a simple Vue.js plugin for handling browser cookies. It reads and writes cookies but asks for no consent and blocks nothing, so it is a tool for your own cookies, not a consent solution.

Plain Vue 3: a cookie banner through a script tag

The most reliable integration for a Vue 3 app is a consent script in index.html. In a Vite project, that file sits at the project root. The script loads before Vue mounts, so the banner can hold non-essential cookies back from the first render.

<head>
  <script src="https://cdn.kukie.io/s/YOUR-SITE-KEY/c.js" async></script>
  <!-- analytics and marketing tags after this line -->
</head>

Place the consent script above any analytics or marketing script. The Vue.js installation guide in the Kukie.io Help Centre shows the exact placement. Because the banner runs outside your components, it is not affected by component lifecycle issues or hydration mismatches.

Loading scripts conditionally after consent

With a banner in place, the next step is making sure third-party scripts only load once the visitor accepts the relevant category. There are two approaches in plain Vue.

The first uses type="text/plain" on script tags in your HTML. With Kukie.io you add data-cc-category with the category slug, such as analytics, and the banner runs the script once that category is accepted. The second listens for the consent event in your Vue app and injects scripts dynamically when the category is accepted.

Both reach the same result. The HTML attribute keeps tracking scripts out of your Vue bundle. The event approach gives you finer control when an analytics library needs JavaScript calls rather than only a script tag.

Nuxt: server-side rendering adds a step

Nuxt renders pages on the server before the browser receives them, and the browser's cookie store does not exist there. Code that touches document.cookie during server rendering throws an error, and guarding it with typeof window !== 'undefined' can still cause hydration mismatches. The safe pattern is to load the consent script in the head through useHead, and to keep consent-dependent code in onMounted or inside <ClientOnly>.

The same pattern works in Nuxt 4 and in Nuxt 3, which received maintenance updates until the end of January 2026. Community consent modules for Nuxt are convenient but often lag behind regulatory changes, while an external consent script updates without a dependency bump and can apply region-specific rules. The Nuxt.js cookie consent guide covers useHead and module set-up in depth.

SPA route changes and consent persistence

A frequently overlooked issue in Vue SPAs is what happens after consent. On a multi-page site the consent cookie is read on every page load. In a Vue SPA, moving between routes loads no new page.

Your consent state must survive route changes and still respect the visitor's right to withdraw. Consent tools store the choice in a first-party cookie, read once when the app starts: Kukie.io's is _cc_consent. Kukie.io also fires a cc:consent-updated event on document whenever consent is applied, including when a returning visitor's choice is restored. Because that restore can fire before Vue mounts, catch it with a small inline script in index.html, placed before the banner script, and read it from a composable:

<!-- index.html, before the banner script -->
<script>
  document.addEventListener('cc:consent-updated', (e) => { window.__consentDetail = e.detail; });
</script>
// useConsent.js
import { ref, onMounted, onBeforeUnmount } from 'vue';
export function useConsent(category) {
  const granted = ref((window.__consentDetail?.categories ?? []).includes(category));
  const onUpdate = (e) => { granted.value = e.detail.categories.includes(category); };
  onMounted(() => document.addEventListener('cc:consent-updated', onUpdate));
  onBeforeUnmount(() => document.removeEventListener('cc:consent-updated', onUpdate));
  return granted;
}

A component can then watch useConsent('analytics') and start a tracker only when it turns true. The same value can live in a Pinia store if several components need it.

If a visitor withdraws consent mid-session, your app needs to react straight away: stop or disable scripts and clear cookies set under the withdrawn category. Kukie.io's banner deletes the cookies listed under a category when the visitor rejects it, and the consent callback API pattern covers what your own code should do.

Google Consent Mode and Vue.js

Google Consent Mode v2 matters for any Vue app that uses Google Analytics 4, Google Ads or Google Tag Manager with visitors from the EEA or the UK. It passes the visitor's consent to Google's tags, which adjust their behaviour to match.

You set default consent states, usually denied for analytics and advertising, before the Google tag loads, then update them when the visitor chooses. Google's developer guide says the default command must run before any command that sends measurement data, so it belongs in index.html before gtag.js, not inside a Vue component. The four parameters are ad_storage, analytics_storage, ad_user_data and ad_personalization, and a consent tool sends the consent('update', ...) call when the visitor makes a choice.

If you use Google Tag Manager, the same principle applies: Tag Manager must receive the default state before any tag fires.

Common mistakes in Vue cookie consent set-ups

Several problems come up again and again when Vue apps are checked for cookies.

Loading analytics in main.js or in the onMounted hook of App.vue. The script starts as soon as the app mounts, before the visitor can interact with the banner. Analytics start-up must sit behind a consent check.

Using Vue plugins that set cookies on install. Some Vue analytics plugins start tracking the moment you register them with app.use(). Registered unconditionally, they set cookies before consent, so delay the registration until consent is confirmed.

Focusing on the GDPR alone. The GDPR defines how consent must be collected, but Article 5(3) of the ePrivacy Directive is the rule that requires prior consent for storing cookies. Both apply at the same time.

Testing with an old browser state. Developers often test with consent already granted from an earlier session. Test in a private window to confirm that no analytics cookies are set before consent.

Testing and verifying your set-up

After adding cookie consent to your Vue app, check that it works. Open Chrome DevTools, go to the Application tab and clear all cookies and site data. Reload the page and, before touching the banner, look at the Cookies panel: only strictly necessary cookies should be there.

Accept all cookies through the banner and check again: analytics and marketing cookies should now appear. Then withdraw consent and confirm those cookies are removed. A cookie banner testing checklist covers each consent state, including private browsing.

Automated checks help too. A cookie audit of your deployed app catches scripts that run before consent, and Kukie.io's scanner lists every cookie your site sets, including those from third-party scripts inside your SPA. If part of your front end is built in React, the same rules apply there.

Questions about consent in Vue apps

Does a Vue.js SPA need a cookie banner?

Yes, if your Vue app sets any non-essential cookies, such as analytics or marketing cookies. Visitors in the EU and UK must consent first under the ePrivacy Directive and the GDPR, and the SPA architecture changes nothing about that.

Can I use a Vue component for cookie consent instead of a script tag?

You can, but a script tag in the HTML head is more reliable. It loads before Vue starts, so no tracking script runs first. A Vue component only mounts once the app is ready, which may be after other scripts have run.

How do I block Google Analytics in Vue until consent is given?

Set Google Consent Mode defaults to denied before gtag.js loads, or keep the tag as type text/plain until analytics is accepted. A consent tool then sends the update or releases the tag when the visitor chooses.

Is cookie consent different for Nuxt.js compared with plain Vue?

The legal requirements are the same. The technical set-up differs because Nuxt renders on the server, where document.cookie is unavailable, so consent logic must run only in the browser to avoid server errors and hydration mismatches.

What happens if a visitor withdraws cookie consent in a Vue SPA?

Your app must stop any tracking scripts and delete cookies set under the withdrawn category. Listen for the consent tool's change event and react, either by removing scripts or by calling their opt-out methods.

Do I need separate cookie consent for each Vue route?

No. Consent applies to the whole site, not to individual routes. Once a visitor grants or refuses consent, that choice covers every page in your SPA, and the consent cookie persists across route changes.

Check what your Vue app sets before the first click

The quickest test of a Vue consent set-up is the first page load with no choice made. The Cookie scanner opens your app in a real browser and lists every cookie it finds by name and category, so you can see whether anything starts before the banner.

Scan your website