Skip to main content
Back to Guides
Compliance10 min read

How to Add Cookie Consent to a React App: The 2026 Developer Guide

A practical guide to implementing cookie consent in React applications. Covers script loading strategies, consent state management with React Context, conditional rendering of tracking scripts, Google Consent Mode v2 integration, and one-line CookieBeam setup.

React dominates front-end development, but the framework itself has no opinion about cookie consent. That means the responsibility falls on you: loading the consent banner at the right time, blocking scripts until the visitor agrees, and sending accurate consent signals to Google, Meta, and your analytics stack.

This guide walks through the full implementation. It starts with the fundamentals (where to load the banner, how to manage consent state) and builds up to advanced patterns like conditional script loading and Consent Mode v2 integration. All examples use TypeScript and functional components.

If you want to skip the manual work entirely, the final section shows how CookieBeam handles all of this with a single script tag.

What this guide covers

  • Where to place your consent banner in the React component tree
  • Managing consent state with React Context
  • Conditionally loading analytics and marketing scripts
  • Google Consent Mode v2 integration
  • Testing consent flows in development
  • One-line CookieBeam setup for React apps

Why React apps need special handling

A static HTML site can block scripts by simply not including them until consent is given. React apps are different. The entire application is JavaScript, which means:

  • Script timing matters. Third-party scripts loaded via <script> tags in index.html fire before React hydrates. If your consent banner is a React component, there is a window where scripts run without consent.
  • State is ephemeral. React state resets on page refresh unless you persist consent to localStorage or cookies. A visitor who consented on the previous page load sees the banner again if you only store consent in React state.
  • SPAs do not reload. In a single-page app, navigation between routes does not trigger new script loads. Scripts loaded on consent must stay active across route changes, and scripts blocked before consent must not retroactively fire when consent is later given on a different route.

These constraints shape every decision below.

Step 1: Place the consent banner at the root

Your consent banner must render outside of route-level components. It needs to be visible on every page and persist across navigations. The standard pattern is to place it in your root layout component, alongside your router.

App.tsx
Copy to clipboard

The ConsentProvider wraps the entire app so any component can read the current consent state. The ConsentBanner sits outside the Routes so it stays mounted during navigation.

Step 2: Manage consent state with React Context

You need a consent context that does three things: reads persisted consent from storage on mount, exposes the current state to the rest of the app, and writes consent decisions back to storage when the visitor interacts with the banner.

consent/ConsentProvider.tsx
Copy to clipboard

Always force necessary: true

The necessary category covers cookies that the site needs to function (session tokens, CSRF tokens, load balancers). Never let a visitor disable it. The example above forces necessary: true on every update, regardless of what the banner sends.

Step 3: Conditionally load third-party scripts

With the consent context in place, you can gate script loading on specific consent categories. The key principle: do not render the script tag at all until consent is given.

consent/ConsentScript.tsx
Copy to clipboard

Use this component anywhere in your tree to conditionally load a script:

App.tsx (usage)
Copy to clipboard
<ConsentScript
  category="analytics"
  src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"
/>
<ConsentScript
  category="marketing"
  src="https://connect.facebook.net/en_US/fbevents.js"
/>

Step 4: Integrate Google Consent Mode v2

Google requires Consent Mode v2 signals for EEA traffic if you use Google Ads or GA4. The consent defaults must be set before the Google tag loads, and updated when the visitor makes a choice.

The correct order is:

  1. Set default consent state (denied for EEA visitors)
  2. Load the Google tag
  3. Update consent state when the visitor interacts with the banner
consent/GoogleConsentMode.tsx
Copy to clipboard

Why wait_for_update matters

The wait_for_update: 500 parameter tells Google tags to wait up to 500ms for a consent update before processing hits. This gives your React app time to hydrate, read stored consent, and fire the update call. Without it, the first pageview fires with denied consent even if the visitor previously consented.

Step 5: Build the consent banner component

The banner reads from the consent context and calls update() with the visitor's choices. Here is a minimal implementation:

consent/ConsentBanner.tsx
Copy to clipboard

Step 6: Test the consent flow

Before deploying, verify these scenarios:

Testing checklist

  • Banner appears on first visit

    Clear localStorage and reload. The banner should appear.

  • Banner disappears after consent

    Click Accept All. The banner should vanish and not reappear on refresh.

  • Scripts load only after consent

    Open the Network tab. Verify analytics/marketing scripts are absent before consent and present after.

  • Consent persists across sessions

    Close the browser, reopen, and navigate to the site. The banner should not appear if consent was previously given.

  • Reject All blocks everything

    Click Reject All. Verify no analytics or marketing scripts load on any page.

  • Consent Mode defaults fire first

    In the dataLayer, verify the consent default event appears before any config or event tags.

  • Settings button works

    A returning visitor should be able to change their consent by clicking a settings button (floating widget or footer link).

The easy way: use CookieBeam

The code above works, but you are building and maintaining consent infrastructure from scratch. You need to handle edge cases (cookie expiry, regional detection, TCF compliance, consent logging for auditors) that the examples above do not cover.

CookieBeam replaces all of the code above with a single script tag:

index.html
Copy to clipboard
<script src="https://cdn.cookiebeam.com/banner/YOUR_BANNER_ID/default/loader.js" async></script>

That single line handles:

  • Automatic consent state management with cookie-based persistence (works across tabs and sessions)
  • Google Consent Mode v2 defaults and updates, including ad_user_data and ad_personalization
  • Microsoft Consent Mode for Clarity and Bing Ads
  • Meta Pixel consent signals
  • Regional detection so visitors in different jurisdictions see the legally correct banner (GDPR opt-in for the EEA, opt-out for US states, no banner where not required)
  • Cookie scanning and classification to keep your cookie declaration accurate
  • Consent logging with timestamps, exportable for audits
  • Script blocking that prevents third-party scripts from firing until the right category is consented to

If you are using a framework like React, Vite, or Create React App, the script tag goes in your index.html before the closing </head> tag. For server-side rendered frameworks, check our Next.js guide.

React-specific gotchas

A few issues that are unique to React apps:

  • StrictMode double-mounts. In development, React 18+ mounts components twice in StrictMode. Your script injection code must be idempotent (check for existing script elements before injecting). The ConsentScript example above handles this with an ID check.
  • Hydration mismatches in SSR. If you server-render your app (Remix, Gatsby SSR), the consent state on the server is always "undecided" because there is no localStorage. The banner must render client-side only to avoid a hydration mismatch.
  • Context not available in head. The <head> section is not inside your React tree, so you cannot use useConsent() there. Load Google Consent Mode defaults via a plain <script> tag in index.html instead, and handle updates from inside the React tree.
  • Lazy-loaded routes. If a route is code-split and loads its own analytics script, the consent check must happen inside that route component, not at the root. The ConsentScript pattern works for this because it checks consent on mount.

Frequently asked questions

Do I need a cookie consent banner for a React SPA?

Yes, if your React app sets cookies or uses tracking scripts (Google Analytics, Meta Pixel, Hotjar) and serves visitors in the EU, UK, or US states with privacy laws. The legal requirement is tied to the cookies and tracking, not the framework.

Can I use a React cookie consent library instead of building my own?

You can, but most open-source React consent libraries only show a banner and store a boolean. They do not handle Google Consent Mode v2, regional detection, script blocking, or consent logging. If you need compliance-grade consent (not just a banner), a dedicated consent management platform is the better choice.

Where should I store consent state in a React app?

localStorage is the simplest option and works for most cases. For cross-subdomain support, use a first-party cookie instead. Do not store consent only in React state, because it resets on page refresh.

How does CookieBeam work with React Router?

CookieBeam loads as a standalone script outside your React tree, so it works with any router (React Router, TanStack Router, or plain browser navigation). It persists consent in a first-party cookie, monitors for new scripts injected during SPA navigation, and blocks them if the required consent category has not been granted.

Does the consent banner affect my Core Web Vitals?

A well-implemented banner has minimal impact. CookieBeam loads asynchronously and does not block rendering. The banner itself uses CSS transforms for animation, which avoids layout shifts (CLS). Loading it with the async attribute keeps it off the critical rendering path.

Summary

Adding cookie consent to a React app requires three pieces: a consent state manager (Context + localStorage), conditional script loading, and Consent Mode v2 integration. You can build this yourself with the code above, or use CookieBeam to handle everything with a single script tag.

For related guides, see Next.js Cookie Consent with App Router, Google Consent Mode v2, and Complete Banner Setup Guide.

React Cookie Consent Guide 2026: Implementation for Developers | CookieBeam