cookie consent for Nuxt

Cookie consent for Nuxt,
one module

@cookiecrumbs/nuxt unshifts the tag into app.head.script with critical priority, ahead of the Nuxt entry chunk, and auto-imports a useConsent() composable.

What changes in a Nuxt page head once the runtime is first: nothing non-essential runs until its category is granted.

the rule

What the law asks of a Nuxt site

A Nuxt app with a GA or pixel plugin runs it on the client entry. Nothing asks first, and nothing can take it back.

The rule is the same everywhere in the EU and the UK: nothing beyond what is strictly necessary may be stored on or read from a visitor’s device before they have agreed. That is Article 5(3) of the ePrivacy Directive, and the agreement has to meet the GDPR’s definition of consent: freely given, specific, informed and unambiguous, with a refusal that is as easy as the acceptance. The UK keeps the same rule in PECR, with narrow exemptions for low-risk statistics since 5 February 2026. California and the other US state laws work the other way round: no opt-in, but an opt-out link and support for the Global Privacy Control signal.

Three things follow for a website. Analytics, advertising and social scripts have to wait for a choice. The choice has to be recorded in a way you can show later, because Article 7(1) puts the burden of proof on you. And withdrawing has to be as easy as agreeing, which means a control that reopens the banner on every page. A banner that shows two buttons and loads Google Analytics anyway fails the first test, and that is the failure regulators have been fining, from the CNIL’s decisions against Google and SHEIN to the Dutch and Belgian authorities’ sweeps.

how it works

How consent works in a Nuxt app

Nuxt manages the document head for you, which is exactly where a consent runtime has to sit. The module puts the tag into app.head.script with tagPriority: "critical", so it is rendered before the Nuxt entry chunk on every page, server-rendered or static. No layout edits, no per-page head calls.

Client plugins are the usual source of early trackers in Nuxt: a gtag plugin, a Pixel plugin, a third-party module that injects its own script. The useConsent() composable gives every one of them isGranted(category) and a way to subscribe to changes, so a plugin can wait and initialise the moment consent arrives. Third-party Nuxt modules that inject scripts get a category on their tag, or their host is neutralised by the block map from the scan.

Three components come with the module: ConsentGate for subtrees, CookieDeclaration for the privacy page, and ManageCookiesLink for the footer. Server routes and middleware can read the consent cookie through the same helpers, so a page can render a placeholder instead of an embed before hydration.

set-up

Set it up in Nuxt

Five steps. The CLI does most of them, and every one is also a click in the dashboard.

  1. Init from the repo

    Detects Nuxt, links the site, writes the config.

    npx cookiecrumbs login
    npx cookiecrumbs init
  2. Add the module

    The site key and environment go in nuxt.config.ts.

    npm i @cookiecrumbs/nuxt
    
    // nuxt.config.ts
    export default defineNuxtConfig({
      modules: ['@cookiecrumbs/nuxt'],
      cookiecrumbs: { site: 'pk_live_…', env: 'production' },
    });
  3. Use the composable

    useConsent() exposes status, consent, regime, country, language, version and the accept, reject, open and withdraw actions.

    const { isGranted, open } = useConsent();
    
    <ConsentGate category="analytics">
      <AnalyticsWidget />
    </ConsentGate>
  4. Make plugins wait

    A client plugin initialises its tracker only when the category is granted, and again if consent changes later.

    // plugins/pixel.client.ts
    export default defineNuxtPlugin(() => {
      const { isGranted, onChange } = useConsent();
      const start = () => { if (isGranted('marketing')) initPixel(); };
      start(); onChange(start);
    });
  5. Scan, sort, publish

    Scan, sort once per vendor, publish.

    npx cookiecrumbs scan --wait
    npx cookiecrumbs push --env production

watch out

Mistakes we see in Nuxt apps

Each one shows up in the first scan as a tracker that fired before consent.

  • A gtag plugin with mode: "client" and no gateIt runs on the entry chunk. Either gate it with the composable or let Consent Mode carry the defaults.
  • Using useHead in a page to add the runtimePage-level head runs after the app head. The module’s critical priority is what keeps the tag first.
  • Nitro routes that set tracking cookiesServer-side cookies for attribution are still cookies. Keep them strictly necessary or set them after consent.
  • Ignoring the preview environmentThe preview key on a staging deploy lets you test a new banner version without touching visitors.
  • No re-ask after adding a categoryAdd a new purpose and the runtime asks again. Do not suppress that; it is what keeps the consent valid.

before you ship

The compliance checklist

Eight lines. The dashboard ticks the last two from real data.

  • The tag is the first script in the headAnything above it can set a cookie the runtime cannot take back.
  • Every analytics, ads and social script waits for its categoryEither type="text/plain" with a category, or the host is in the block map from the scan.
  • Reject all is on the first layerSame size, same weight as Accept all. No “X” that counts as consent, no pre-ticked boxes.
  • Consent Mode defaults are denied before Google loadsCheck the seven signals in Tag Assistant with consent denied.
  • The imprint and privacy policy links are setPublishing is refused until both are there; the banner footer links to them.
  • A withdraw control is reachable on every pageThe persistent control or a “Manage cookies” link in your footer.
  • The first full scan ran and every vendor is filedThe verdict on Home says what fired before consent, dated.
  • The install check passedIt loads your page like a visitor and confirms the banner ran before any tracker.

what you get

What you get on the free plan

Two domains, 100 subpages scanned a month per domain, every regulation, the CLI, the SDKs and the MCP server.

A scanner that reads the rendered page

Every page, in each consent state, in a real browser. Cookies, pixels, iframes and storage keys, with the page and script that set them. Re-scanned on a schedule.

The cookie declaration writes itself from the result.

A banner that blocks first

Tags stay inert until their category is granted. Reject all is as visible as Accept all. Seven layouts, 25 languages, Consent Mode v2, and the right rule per region.

21 kB, one file, no third-party requests of its own.

Proof you can hand over

Each choice is stored with a timestamp, the banner version and a hash of the texts shown, chained to the record before it. Exports are signed. Hosted in Frankfurt.

Article 7(1), on the free plan.

free check

Check what your site loads right now

The homepage HTML, matched against the tracker database. No account, nothing stored. The full scan in the dashboard does the same for every page, in a real browser.

questions

Straight answers

Does the module keep the tag ahead of my plugins?
Yes. It is injected with tagPriority critical, before the Nuxt entry chunk, so the consent defaults exist before any plugin runs.
Which components come with the module?
ConsentGate, CookieDeclaration and ManageCookiesLink, plus the useConsent() composable with status, consent, regime, country, language, version, consentId and the accept, reject, set, open, close, withdraw and setLang actions.
Does it work with Nuxt Content or a static build?
Yes. Static generation writes the tag into every HTML file; SSR renders it per request.
Can I read the consent in a server route?
Yes. The cookie helpers work in Nitro, so an API route can skip a tracking call for a visitor who said no.
What about Google Tag Manager?
Keep the GTM module. The runtime sets the Consent Mode v2 defaults first and the GTM template adds the triggers.
Is there a Vue 3 version without Nuxt?
Use the script tag and the runtime API. The module is a thin wrapper around the same runtime.

next step

Ship the banner with the next deploy

Add the site, run npx cookiecrumbs init in your Nuxt repo, and the consent log starts recording in the EU.