I am a...
Learn more
How it worksPricingFAQ
Account
May 14, 2026 · 12 min read · Cadence Editorial

How to set up a Cookie banner the right way

cookie banner setup — How to set up a Cookie banner the right way
Photo by [Dan Nelson](https://www.pexels.com/@dan-nelson-1667453) on [Pexels](https://www.pexels.com/photo/woman-using-macbook-pro-3949100/)

How to set up a Cookie banner the right way

To set up a cookie banner the right way, block all non-essential cookies until the visitor opts in (for EU traffic) or gives an easy opt-out path (for California traffic), pick a consent management platform like Cookiebot, CookieYes, or the open-source Klaro, and wire Google Consent Mode v2 if you run Google Analytics or Ads. Skip pre-checked boxes, scroll-to-accept, and any layout where Reject is harder to find than Accept.

That is the whole job in one paragraph. The rest of this post is the founder playbook: which laws apply, how to audit what your stack already sets, which tool to pick at which stage, working code, and the dark patterns regulators actually fine for.

This is implementation advice, not legal advice. If you are in health, finance, EU B2C at scale, or processing kids' data, retain a privacy lawyer before you ship.

What a compliant cookie banner actually has to do

Three regimes set the rules: GDPR (EU/UK), CCPA/CPRA (California), and the ePrivacy Directive (EU, sits on top of GDPR for cookies specifically).

GDPR requires prior, explicit, granular, freely-given opt-in consent before any non-essential cookie loads. Consent must be as easy to withdraw as to give. Pre-ticked boxes do not count. Silence does not count. Continued browsing does not count.

CCPA/CPRA is opt-out, not opt-in, but California's 2026 update tightened the screws. You need a clearly posted "Do Not Sell or Share My Personal Information" link, you must honor the Global Privacy Control browser signal automatically, and Reject must be as visible as Accept. Closing a banner without clicking Accept no longer counts as consent.

ePrivacy says the banner must show before any non-essential cookie fires. Strictly necessary cookies (auth session, CSRF, load balancer) are allowed without consent. Everything else (analytics, marketing, personalization, A/B test) needs a click first.

The fines are real. GDPR can hit 4% of global annual revenue or EUR 20 million, whichever is larger. The French CNIL alone has fined Google EUR 150 million and Meta EUR 60 million for asymmetric reject paths. CCPA caps at $7,500 per intentional violation, but "per violation" is per consumer, which adds up fast.

Step 1: Audit what your stack already sets

Most founders are surprised by how many cookies their app sets before any user interaction. A typical Next.js app with Stripe Checkout, PostHog, Sentry, and Vercel Analytics drops eight to fifteen cookies on first paint. You cannot ship a banner that lies about what you are setting.

Open Chrome DevTools, go to Application, then Cookies, and load your homepage in an incognito window. Document every cookie: name, domain, expiration, purpose, and whether it is first or third party. The free Cookiebot scanner or CookieServe will do this automatically, but eyeballing it once teaches you what your stack actually does.

Then categorize:

  • Strictly necessary: session auth, CSRF token, Stripe __stripe_mid for fraud prevention. These load by default.
  • Functional: language preference, theme, layout state. Load on consent or by default depending on jurisdiction.
  • Analytics: PostHog, Mixpanel, GA4, Plausible (cookie mode). Block until consent in EU.
  • Marketing: Meta Pixel, Google Ads, LinkedIn Insight, TikTok Pixel, retargeting. Block until consent everywhere except where opt-out applies.

Write this list down. The CMP setup screen will ask you for it.

Step 2: Pick the right CMP for your stage

There is no universal best CMP. There is a best one for your traffic shape and team. Here is the honest pricing landscape:

ToolTypePriceBest forTrade-off
CookiebotSaaS$11-69/moEU-heavy traffic, Google Consent Mode v2 nativePricier as monthly visitors scale
CookieYesSaaS$8-29/moSmall SaaS, fast setup, multi-domainBranding on free tier
IubendaSaaS$5-29/moPrivacy policy + cookie policy + terms in one bundleGeneric templates need editing
TermlyFreemium SaaSFree-$25/moSolo founders pre-revenueFree tier limits domains and scans
OneTrustEnterpriseCustom (5-figure)Series B+ or regulated industriesOverkill and slow to deploy
KlaroOSSFreePrivacy-first teams who self-hostYou own updates, audits, and consent storage
Vanilla Cookie ConsentOSSFreeTiny landing pages with one analytics tagNo consent log, no CMP audit trail

Pick by stage, not by feature list:

  • Pre-revenue, US-only landing page with GA4: Termly free tier. Done in 20 minutes.
  • Seed stage with mixed US/EU traffic, GA4 + Meta Pixel: CookieYes or Cookiebot. Both are Google-certified CMPs.
  • Series A SaaS with self-serve EU customers: Cookiebot or Iubenda for the all-in-one privacy bundle.
  • Privacy-first dev shop, refuses to ship third-party JS: Klaro, self-hosted. Your engineering team owns the audit log.
  • Series B+ regulated (fintech, healthtech): OneTrust or a peer at that tier. The lawyer will demand it.

The Google-certified status matters. Google maintains a list of CMPs whose default integration covers Consent Mode v2 correctly. If your CMP is not on that list, you are wiring it manually and risking gaps.

Step 3: Wire Google Consent Mode v2

Since March 2024, any site serving Google Ads or Analytics to EU/EEA users must implement Google Consent Mode v2 or those tags stop returning data. EU conversions vanish from GA4. Smart Bidding loses signal. Remarketing audiences shrink to zero.

Consent Mode v2 introduced two parameters on top of the original four: ad_user_data (consent to send user data to Google for ads) and ad_personalization (consent to personalized advertising). All four (analytics_storage, ad_storage, ad_user_data, ad_personalization) default to denied and flip to granted when the user opts in.

The default-denied snippet goes in the <head> before any Google tag:

<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('consent', 'default', {
    'ad_storage': 'denied',
    'ad_user_data': 'denied',
    'ad_personalization': 'denied',
    'analytics_storage': 'denied',
    'wait_for_update': 500
  });
</script>

Then on consent, the CMP fires gtag('consent', 'update', {...}) with the user's choices. Google's tags backfill modeled conversions for the denied users using machine-learned aggregates, which is most of the point of v2.

Most certified CMPs handle this for you. If you self-host with Klaro or write your own banner, you are responsible for emitting the update event correctly and testing it with Google's Tag Assistant.

Step 4: Geolocate and conditionally show

A founder mistake we see all the time: shipping a hard EU-style opt-in banner to US visitors who do not need it. You hurt conversion for no compliance gain. Or the inverse: shipping a US-style notice to EU visitors and getting fined.

Use IP geolocation to decide which banner variant to show:

  • EU/EEA/UK visitor: full opt-in banner, scripts blocked until consent, granular categories.
  • California visitor: notice + Do Not Sell or Share link + GPC honored automatically.
  • Rest of US: light notice (most states are catching up: Virginia VCDPA, Colorado CPA, Connecticut CTDPA all have similar opt-out rules).
  • Rest of world: minimal notice, opt-out link.

Cloudflare exposes the country code as CF-IPCountry for free on every request. Vercel does the same with request.geo.country. Both let you pick the banner variant server-side before the page hydrates, so the right banner shows on first paint with no flash.

If you are non-technical and not sure how this gets wired, the founders who ship this fastest are usually pairing with someone who has done it before. Most CMPs have a one-click region rule, but an engineer needs to pre-block scripts with the right data-cookieconsent or type="text/plain" attributes for the CMP to do its job. Founders who interview a developer when they cannot code tend to skip this kind of integration debt entirely by asking the right questions in the call.

Working code: a vanilla integration

For a tiny landing page with GA4 only, you can ship a working banner in about 40 lines without a CMP. Here is the skeleton:

<!-- 1. Default consent denied, BEFORE any analytics -->
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('consent', 'default', {
    'ad_storage': 'denied',
    'ad_user_data': 'denied',
    'ad_personalization': 'denied',
    'analytics_storage': 'denied'
  });
</script>

<!-- 2. Banner DOM -->
<div id="cookie-banner" hidden>
  <p>We use cookies for analytics. You can accept, reject, or customize.</p>
  <button id="cc-accept">Accept all</button>
  <button id="cc-reject">Reject all</button>
  <a href="/privacy">Cookie policy</a>
</div>

<!-- 3. Show + handle choice -->
<script>
  const stored = localStorage.getItem('cc-choice');
  if (!stored) document.getElementById('cookie-banner').hidden = false;
  if (stored === 'granted') loadAnalytics();

  function setConsent(state) {
    gtag('consent', 'update', {
      'ad_storage': state,
      'ad_user_data': state,
      'ad_personalization': state,
      'analytics_storage': state
    });
    localStorage.setItem('cc-choice', state);
    document.getElementById('cookie-banner').hidden = true;
    if (state === 'granted') loadAnalytics();
  }

  function loadAnalytics() {
    const s = document.createElement('script');
    s.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXX';
    s.async = true;
    document.head.appendChild(s);
  }

  document.getElementById('cc-accept').onclick = () => setConsent('granted');
  document.getElementById('cc-reject').onclick = () => setConsent('denied');
</script>

This is the minimum that satisfies GDPR for a single-tag site. Real apps need granular per-category toggles, a "withdraw consent" link in the footer, a consent log (so you can prove a given user opted in), GPC detection, and CCPA-specific UI. That is exactly why most teams reach for a CMP after the second analytics tool lands.

The dark patterns regulators actually fine for

These look reasonable. They are illegal, and the EU has the case law to prove it.

  • Pre-checked boxes. Defaulting analytics to "on" with a checkbox the user must uncheck. The CJEU ruled this out in Planet49 (2019). Banner builders still ship this template.
  • Cookie wall. Blocking site access until the user accepts. The European Data Protection Board explicitly bans this. A paywall is fine; a consent wall is not.
  • Scroll-to-accept. Treating page scroll as consent. As of the 2026 CCPA update this is now also banned in California, matching GDPR.
  • Asymmetric buttons. "Accept all" as a bright primary button and "Reject all" hidden behind "Manage preferences" two clicks deep. CNIL fined Google EUR 150 million and Facebook EUR 60 million in 2022 for exactly this layout.
  • Color and contrast tricks. Reject in light gray on white, Accept in solid blue. Same problem as above.
  • Re-prompting. Re-asking on every page until the user gives in. Once a user has rejected, you cannot legally re-ask for at least 6 months in most EU jurisdictions and 12 months under CCPA.

The symmetry rule is the easy mental check: if a regulator screenshot would show "Reject" looking secondary to "Accept," you have a problem.

What to do if you already shipped without a banner

You are not the first founder to realize at month four that your SaaS has been quietly setting the Meta Pixel on EU visitors with no consent. Here is the triage:

  1. Today (1 hour): install Termly free tier or CookieYes free tier. Block GA4 and any pixels until consent. This stops the bleed.
  2. This week (2-3 hours): audit your actual cookies, set up granular categories, geolocate, and wire Google Consent Mode v2.
  3. This month (half-day): backfill a real privacy policy and cookie policy. The same CMP usually generates these. A founder-friendly walk-through of the privacy doc lives in our SaaS privacy policy guide.
  4. This quarter: if you handle EU customer data at any scale, run through our GDPR SaaS compliance checklist and decide whether you need a Data Processing Addendum, a Standard Contractual Clauses appendix, and a named EU representative.

For most pre-seed and seed teams, this is a one-afternoon job once someone who has done it before owns the work. The trap is treating it as a "we'll get to it" item until a customer asks about your DPA in a deal.

If you want to hand the implementation off, every engineer on Cadence is AI-native by default (Cursor, Claude Code, Copilot fluency vetted in a voice interview), and a mid-tier engineer at $1,000/week typically ships a compliant banner with Consent Mode v2 and per-region detection in two to three days. You can book a Cadence engineer with a 48-hour free trial and not pay if the implementation does not land.

Common founder mistakes

  • Trusting the default CMP template without auditing your stack. The template assumes a generic site. Yours has Stripe, PostHog, Sentry, Vercel, and an embedded Calendly that all set their own cookies.
  • Skipping Consent Mode v2 because you "do not run ads in the EU." If GA4 is installed and a single EU user lands, your conversion data is wrong. The fix takes 20 minutes.
  • Hand-rolling the banner without a consent log. When a user files a GDPR access request asking what consent they gave and when, you need a record. Free CMPs handle this.
  • Forgetting the withdraw flow. A "Manage cookies" link in the footer that re-opens the banner is required. Most teams build the banner and forget the off ramp.

Try it: pick one CMP from the table above, install it on a staging branch tonight, and run our ship-or-skip audit against your live site to see what cookies fire pre-consent.

Steps

  1. Audit your cookies. Open DevTools > Application > Cookies in incognito. Document name, domain, purpose, and category for each one. Use a free scanner like Cookiebot's if you have more than 20 cookies.
  2. Pick a CMP. Use the pricing table above. Termly free or CookieYes for pre-seed; Cookiebot or Iubenda for seed-and-up; Klaro if you self-host.
  3. Set default consent denied. Add the Google Consent Mode v2 default snippet in <head> before any analytics or pixel tags load.
  4. Tag your scripts for blocking. Add data-cookieconsent="statistics" (or your CMP's equivalent attribute) to every analytics, marketing, and personalization script tag.
  5. Geolocate and route. Use Cloudflare or Vercel geo headers to pick the EU opt-in banner, the California opt-out notice, or the global light notice.
  6. Honor GPC. If the visitor's browser sends Sec-GPC: 1, treat it as an opt-out for sale/share automatically without showing the banner choice.
  7. Add a withdraw link. Footer link labeled "Manage cookies" that re-opens the preference center. Required under both GDPR and CCPA.
  8. Test rejection. Open the live site in incognito, click Reject, and confirm in DevTools Network that no analytics or pixel requests fire.
  9. Backfill the privacy policy. Most CMPs generate a draft; edit for your actual data flows.
  10. Re-audit quarterly. Every new vendor (a new analytics tool, a chat widget, a survey embed) sets new cookies. Re-scan after each major release.

FAQ

Do I need a cookie banner if I have no EU users?

If you serve any California traffic and use analytics or ads, you still need a CCPA notice with a Do Not Sell or Share link. Most US founders need a banner the day they install Google Analytics, even with zero EU traffic. Virginia, Colorado, Connecticut, and a growing list of states are converging on the same opt-out model.

Can I skip the banner if I only use first-party analytics?

If your analytics tool stores cookies or fingerprints users, you still need consent under GDPR. PostHog, Mixpanel, and Plausible's cookie mode all qualify. Plausible's cookieless mode and Fathom are two of the few real exemptions, since they do not set cookies and aggregate before storage.

What happens to my Google Ads data if I don't implement Consent Mode v2?

EU/EEA conversions disappear from your reports because Google will not accept tag fires without consent signals. Your remarketing audiences shrink, Smart Bidding loses signal, and CPA reporting becomes unreliable. The fix is the default-denied snippet plus your CMP's update event.

Is a free CMP good enough for a pre-seed startup?

Yes, if your traffic is low and your stack is simple. Termly's free tier or Klaro OSS handles most early-stage SaaS. Upgrade when you cross 10,000 monthly visitors, add more than two analytics tools, or sign your first EU enterprise customer who asks for a consent log.

Should I get a privacy lawyer to review this?

For high-risk verticals (health, finance, kids' data, EU B2C at scale, anything regulated), yes, before you launch. For a B2B SaaS landing page with one analytics tool and a Stripe checkout, a Google-certified CMP plus a generated privacy policy is usually enough at pre-seed and seed. The lawyer becomes worth the hourly rate the moment a real EU enterprise customer sends a DPA.

All posts