cookie consent for Astro

Cookie consent for Astro,
one integration

@cookiecrumbs/astro inserts the tag as the first element of every page’s head, at build time for prerendered pages and per request in SSR. A middleware fills the server-side cookie reader.

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

the rule

What the law asks of a Astro site

Astro islands hydrate analytics the moment they mount. Without a consent layer the first paint of a content site already carries a tracker.

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 Astro app

Astro sites are mostly static HTML with islands of interactivity, and that is good news for consent: the runtime can be written into the HTML at build time, first in the head of every page, with nothing to race against. The integration does exactly that for prerendered pages and repeats it per request for server-rendered ones, so a hybrid site behaves the same everywhere.

Islands are where trackers hide. A Partytown-loaded GTM, a client-only analytics island, a YouTube embed in a client:visible component: each of them either gets a category on its script tag or checks the consent state before mounting. The integration ships the shared components, and the middleware exposes the consent on Astro.locals so a page can decide server-side whether to render an embed or its placeholder.

Content sites tend to have hundreds of pages, and the scan crawls them in each consent state up to your plan’s budget. The result feeds the cookie declaration, which you can mount on your privacy page with CookieDeclaration and which updates itself when the next scan finds something new.

set-up

Set it up in Astro

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

  1. Init from the repo

    Detects Astro, links the site, writes the config.

    npx cookiecrumbs login
    npx cookiecrumbs init
  2. Add the integration

    One line in astro.config.mjs. With auto: false you place <CookieCrumbs /> in your layout yourself.

    npm i @cookiecrumbs/astro
    
    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    import cookiecrumbs from '@cookiecrumbs/astro';
    
    export default defineConfig({
      integrations: [cookiecrumbs({ site: 'pk_live_…', env: 'production' })],
    });
  3. Gate what needs consent

    Consent-bound tags get type="text/plain" and a category. Islands that load trackers can check the consent state before mounting.

    <script type="text/plain" data-cc-category="analytics"
            src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"></script>
  4. Read it on the server if you like

    The middleware sets the consent on locals, so a page can skip an embed entirely for visitors who said no.

    // src/pages/index.astro
    const { consent } = Astro.locals;
    const showVideo = consent?.isGranted('marketing');
  5. Scan, sort, publish

    The scan crawls the built site in each consent state. Sort once, publish.

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

watch out

Mistakes we see in Astro apps

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

  • Loading the runtime through PartytownThe runtime needs the main thread and has to run first. Partytown is for the trackers, not for the thing that gates them.
  • A YouTube or Maps island without a placeholderAn iframe sets cookies on load. Hold it with a category and show a placeholder until marketing is granted.
  • View transitions that re-fire analyticsA page view on every transition still needs consent. Check isGranted before sending.
  • Only tagging the layoutPages with their own head slots bypass the layout. The integration covers every page; hand-placed tags do not.
  • No withdraw linkStatic sites forget it most often. A ManageCookiesLink in the footer is enough.

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 it work with prerendered and server-rendered pages?
Both. The integration writes the tag at build time for static pages and per request for SSR, always as the first element of the head.
Can I position the tag myself?
Yes. Set auto: false and place the CookieCrumbs component from @cookiecrumbs/astro/CookieCrumbs.astro in your layout.
Does it work with Partytown?
Yes, for the trackers. The consent runtime itself runs on the main thread, first, and the Consent Mode defaults exist before the worker loads GTM.
How does the scan handle a large content site?
It crawls up to your plan’s monthly budget, 100 subpages a month per domain on Free and 10,000 on Pro, in each consent state, and re-scans on a schedule.
Can I show the cookie list on a page?
Mount CookieDeclaration on your privacy page. It renders the public list from the last scan in the visitor’s language.
Which adapters are supported?
Any adapter that produces HTML: Node, Vercel, Netlify, Cloudflare. The integration hooks into Astro’s head injection, not into the adapter.

next step

Ship the banner with the next deploy

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