# c15t Full Context
> All generated markdown documentation pages flattened into one file.
## Included Pages
- [Frameworks](https://c15t.com/docs/frameworks): Reference page for frameworks.
- [Quickstart](https://c15t.com/docs/frameworks/react/quickstart): Add consent management to your React app in under 5 minutes.
- [Optimization](https://c15t.com/docs/frameworks/react/optimization): Improve c15t startup performance in React with prefetching, proxy rewrites, and rendering tradeoffs.
- [AI Agents](https://c15t.com/docs/ai-agents): Integrate c15t with AI coding assistants using the docs bundled in each package and c15t agent skills. Give agents version-matched local docs for consent management, banners, script loading, callbacks, and integrations.
- [Initialization Flow](https://c15t.com/docs/frameworks/react/concepts/initialization-flow): What happens from provider mount to first render — the full consent lifecycle.
- [Client Modes](https://c15t.com/docs/frameworks/react/concepts/client-modes): Choose how c15t connects to its backend - full hosted integration, offline-only, or bring your own backend.
- [Consent Models](https://c15t.com/docs/frameworks/react/concepts/consent-models): How c15t determines consent behavior based on legal jurisdiction.
- [Policy Packs](https://c15t.com/docs/frameworks/react/concepts/policy-packs): How c15t resolves regional consent policies and what a policy pack controls.
- [Consent Categories](https://c15t.com/docs/frameworks/react/concepts/consent-categories): How c15t organizes tracking technologies into five consent categories.
- [Cookie Management](https://c15t.com/docs/frameworks/react/concepts/cookie-management): How c15t manages cookies through script, iframe, and network gating
- [Glossary](https://c15t.com/docs/frameworks/react/concepts/glossary): Key terms used throughout the c15t documentation.
- [Script Loader](https://c15t.com/docs/frameworks/react/script-loader): Gate third-party scripts behind consent in React — load Google Analytics, Meta Pixel, and other tracking scripts only when users grant permission.
- [Iframe Blocking](https://c15t.com/docs/frameworks/react/iframe-blocking): Block embedded content (YouTube, social widgets, maps) until users grant consent for the appropriate category.
- [Network Blocker](https://c15t.com/docs/frameworks/react/network-blocker): Block outgoing network requests to third-party domains until the user grants consent for the appropriate category.
- [Callbacks](https://c15t.com/docs/frameworks/react/callbacks): React to consent lifecycle events - initialization, consent changes, errors, and revocation reloads.
- [Internationalization](https://c15t.com/docs/frameworks/react/internationalization): Translate consent UI into 30+ languages with built-in translations, custom overrides, and automatic browser language detection.
- [Policy Packs](https://c15t.com/docs/frameworks/react/policy-packs): Configure regional consent policies in React — hosted mode, presets, and offline fallback.
- [Server-Side Utilities](https://c15t.com/docs/frameworks/react/server-side): Fetch consent data on the server for SSR hydration — eliminate the loading flash and improve performance.
- [ConsentManagerProvider](https://c15t.com/docs/frameworks/react/components/consent-manager-provider): The root provider component that initializes the consent system and makes consent state available to all child components.
- [ConsentBanner](https://c15t.com/docs/frameworks/react/components/consent-banner): A pre-built consent banner that appears when user consent is needed. Supports policy-aware layout, theming, and advanced composition when markup must change.
- [ConsentDialog](https://c15t.com/docs/frameworks/react/components/consent-dialog): A modal dialog where users can toggle individual consent categories.
- [ConsentWidget](https://c15t.com/docs/frameworks/react/components/consent-widget): An inline consent management widget for embedding in settings or privacy pages. Shows category toggles with accordion layout.
- [ConsentDialogTrigger](https://c15t.com/docs/frameworks/react/components/consent-dialog-trigger): A floating, draggable button that lets users re-open the consent dialog at any time.
- [ConsentDialogLink](https://c15t.com/docs/frameworks/react/components/consent-dialog-link): An inline trigger for opening the consent dialog from footers, legal pages, and account settings.
- [Frame](https://c15t.com/docs/frameworks/react/components/frame): A consent-gated content wrapper - children only mount when the required consent category is granted.
- [DevTools](https://c15t.com/docs/frameworks/react/components/dev-tools): A development tool for inspecting consent state, geolocation, loaded scripts, and consent events in real time.
- [Styling Overview](https://c15t.com/docs/frameworks/react/styling/overview): Customize every aspect of c15t's consent components using design tokens, component slots, and CSS variables.
- [Design Tokens](https://c15t.com/docs/frameworks/react/styling/tokens): The six base token categories that control colors, typography, spacing, radius, shadows, and motion, plus optional dark-mode overrides.
- [Component Slots](https://c15t.com/docs/frameworks/react/styling/slots): Target individual component parts with styles using the slot system - className strings or inline style objects.
- [Class Names](https://c15t.com/docs/frameworks/react/styling/classnames): Style consent components using className props and per-slot className targeting via the theme.
- [Tailwind CSS](https://c15t.com/docs/frameworks/react/styling/tailwind): Use Tailwind CSS utility classes to style consent components via the slot system.
- [Color Scheme](https://c15t.com/docs/frameworks/react/styling/color-scheme): Support light mode, dark mode, and system preference detection in consent components.
- [CSS Variables](https://c15t.com/docs/frameworks/react/styling/css-variables): Reference for all --c15t-* CSS custom properties generated by the theme system.
- [useConsentManager](https://c15t.com/docs/frameworks/react/hooks/use-consent-manager/overview): The primary hook for accessing consent state and actions. Returns the full consent store including all state properties and action methods.
- [Checking Consent](https://c15t.com/docs/frameworks/react/hooks/use-consent-manager/checking-consent): Use has() for flexible consent checks with AND, OR, and NOT logic. Check if any consent exists with hasConsented().
- [Setting Consent](https://c15t.com/docs/frameworks/react/hooks/use-consent-manager/setting-consent): Save, update, and reset consent preferences with setConsent(), setSelectedConsent(), and saveConsents().
- [Location Info](https://c15t.com/docs/frameworks/react/hooks/use-consent-manager/location-info): Access detected jurisdiction, country, and region. Override geolocation for testing.
- [useTranslations](https://c15t.com/docs/frameworks/react/hooks/use-translations): Access the current language's translations for building custom consent UI.
- [useFocusTrap](https://c15t.com/docs/frameworks/react/hooks/use-focus-trap): Trap keyboard focus within a container for accessible modal dialogs.
- [useColorScheme](https://c15t.com/docs/frameworks/react/hooks/use-color-scheme): Manage light/dark mode preferences for consent components.
- [useReducedMotion](https://c15t.com/docs/frameworks/react/hooks/use-reduced-motion): Detect the user's prefers-reduced-motion OS setting and reactively disable animations.
- [useTextDirection](https://c15t.com/docs/frameworks/react/hooks/use-text-direction): Manage RTL/LTR text direction based on the active language for consent UI.
- [useSSRStatus](https://c15t.com/docs/frameworks/react/hooks/use-ssr-status): Check whether server-side rendered consent data was used during initialization.
- [useDraggable](https://c15t.com/docs/frameworks/react/hooks/use-draggable): Make an element draggable between viewport corners with snapping, persistence, and animation support.
- [Troubleshooting](https://c15t.com/docs/frameworks/react/troubleshooting): Solutions for common issues with @c15t/react — provider errors, missing banners, consent persistence, and more.
- [Building Headless Components](https://c15t.com/docs/frameworks/react/building-headless-components): Build policy-aware custom consent components in React using the headless hooks and policy-pack tooling.
- [Headless Mode](https://c15t.com/docs/frameworks/react/headless): Build fully custom consent UI using only hooks - no pre-built components required.
- [IAB TCF 2.3](https://c15t.com/docs/frameworks/react/iab/overview): Implement IAB Transparency & Consent Framework 2.3 compliance for programmatic advertising in EU/EEA jurisdictions.
- [IABConsentBanner](https://c15t.com/docs/frameworks/react/iab/consent-banner): An IAB TCF 2.3 compliant consent banner that displays partner count, purpose summaries, and legitimate interest notices.
- [IABConsentDialog](https://c15t.com/docs/frameworks/react/iab/consent-dialog): An IAB TCF 2.3 compliant preference center with tabbed purpose and vendor management.
- [useGVLData (Internal)](https://c15t.com/docs/frameworks/react/iab/use-gvl-data): Status note for the internal GVL hook used by the built-in IAB dialog.
- [Quickstart](https://c15t.com/docs/frameworks/javascript/quickstart): Get started with c15t in vanilla JavaScript — framework-agnostic consent management with no UI dependencies.
- [Optimization](https://c15t.com/docs/frameworks/javascript/optimization): Improve c15t startup performance with prefetching and network tuning.
- [Initialization Flow](https://c15t.com/docs/frameworks/javascript/concepts/initialization-flow): What happens from runtime creation to first state update — the full consent lifecycle.
- [Client Modes](https://c15t.com/docs/frameworks/javascript/concepts/client-modes): Choose how c15t connects to its backend — full hosted integration, offline-only, or bring your own backend.
- [Consent Models](https://c15t.com/docs/frameworks/javascript/concepts/consent-models): How c15t determines consent behavior based on legal jurisdiction.
- [Policy Packs](https://c15t.com/docs/frameworks/javascript/concepts/policy-packs): How c15t resolves regional consent policies and what a policy pack controls.
- [Consent Categories](https://c15t.com/docs/frameworks/javascript/concepts/consent-categories): How c15t organizes tracking technologies into five consent categories.
- [Cookie Management](https://c15t.com/docs/frameworks/javascript/concepts/cookie-management): How c15t manages cookies through script, iframe, and network gating.
- [Glossary](https://c15t.com/docs/frameworks/javascript/concepts/glossary): Key terms used throughout the c15t documentation.
- [Script Loader](https://c15t.com/docs/frameworks/javascript/script-loader): Gate third-party scripts behind consent — load Google Analytics, Meta Pixel, and other tracking scripts only when users grant permission.
- [Iframe Blocking](https://c15t.com/docs/frameworks/javascript/iframe-blocking): Block embedded content (YouTube, social widgets, maps) until users grant consent for the appropriate category.
- [Network Blocker](https://c15t.com/docs/frameworks/javascript/network-blocker): Block outgoing network requests to third-party domains until the user grants consent for the appropriate category.
- [Callbacks](https://c15t.com/docs/frameworks/javascript/callbacks): React to consent lifecycle events — initialization, consent changes, errors, and revocation reloads.
- [Internationalization](https://c15t.com/docs/frameworks/javascript/internationalization): Translate consent UI into 30+ languages with built-in translations, custom overrides, and automatic browser language detection.
- [Policy Packs](https://c15t.com/docs/frameworks/javascript/policy-packs): Configure regional consent policies in the headless JavaScript runtime — hosted mode, presets, and offline fallback.
- [Store API Overview](https://c15t.com/docs/frameworks/javascript/api/overview): Core API entry points for JavaScript consent management — runtime creation, store access, and subscription patterns.
- [Checking Consent](https://c15t.com/docs/frameworks/javascript/api/checking-consent): Read consent state from the store — check individual categories, logical conditions, and the full consent object.
- [Setting Consent](https://c15t.com/docs/frameworks/javascript/api/setting-consent): Save, stage, and reset consent preferences using the store API.
- [Location & Identity](https://c15t.com/docs/frameworks/javascript/api/location-info): Access detected location, override geolocation, change language, and link user identity.
- [Building UI](https://c15t.com/docs/frameworks/javascript/building-ui): Build your own consent UI on top of the headless c15t store — with vanilla DOM, any framework, or the @c15t/ui theme system.
- [Troubleshooting](https://c15t.com/docs/frameworks/javascript/troubleshooting): Solutions for common issues with c15t in JavaScript — store access, missing banners, consent persistence, and more.
- [IAB TCF 2.3](https://c15t.com/docs/frameworks/javascript/iab/overview): Implement IAB Transparency & Consent Framework 2.3 compliance for programmatic advertising in EU/EEA jurisdictions.
- [Quickstart](https://c15t.com/docs/frameworks/next/quickstart): Add consent management to your Next.js app in under 5 minutes.
- [Optimization](https://c15t.com/docs/frameworks/next/optimization): Improve c15t startup performance in Next.js with same-origin rewrites, static prefetching, and dynamic-route SSR.
- [Initialization Flow](https://c15t.com/docs/frameworks/next/concepts/initialization-flow): What happens from provider mount to first render — the full consent lifecycle.
- [Client Modes](https://c15t.com/docs/frameworks/next/concepts/client-modes): Choose how c15t connects to its backend - full hosted integration, offline-only, or bring your own backend.
- [Consent Models](https://c15t.com/docs/frameworks/next/concepts/consent-models): How c15t determines consent behavior based on legal jurisdiction.
- [Policy Packs](https://c15t.com/docs/frameworks/next/concepts/policy-packs): How c15t resolves regional consent policies and what a policy pack controls.
- [Consent Categories](https://c15t.com/docs/frameworks/next/concepts/consent-categories): How c15t organizes tracking technologies into five consent categories.
- [Cookie Management](https://c15t.com/docs/frameworks/next/concepts/cookie-management): How c15t manages cookies through script, iframe, and network gating
- [Glossary](https://c15t.com/docs/frameworks/next/concepts/glossary): Key terms used throughout the c15t documentation.
- [Script Loader](https://c15t.com/docs/frameworks/next/script-loader): Gate third-party scripts behind consent in Next.js — load Google Analytics, Meta Pixel, and other tracking scripts only when users grant permission.
- [Iframe Blocking](https://c15t.com/docs/frameworks/next/iframe-blocking): Block embedded content (YouTube, social widgets, maps) until users grant consent for the appropriate category.
- [Network Blocker](https://c15t.com/docs/frameworks/next/network-blocker): Block outgoing network requests to third-party domains until the user grants consent for the appropriate category.
- [Callbacks](https://c15t.com/docs/frameworks/next/callbacks): React to consent lifecycle events - initialization, consent changes, errors, and revocation reloads.
- [Internationalization](https://c15t.com/docs/frameworks/next/internationalization): Translate consent UI into 30+ languages with built-in translations, custom overrides, and automatic browser language detection.
- [Policy Packs](https://c15t.com/docs/frameworks/next/policy-packs): Configure regional consent policies in Next.js — hosted mode, presets, and offline fallback.
- [Server-Side Data Fetching](https://c15t.com/docs/frameworks/next/server-side): Pre-fetch consent data in Server Components with fetchInitialData for dynamic Next.js routes.
- [ConsentManagerProvider](https://c15t.com/docs/frameworks/next/components/consent-manager-provider): The root provider component that initializes the consent system and makes consent state available to all child components.
- [ConsentBanner](https://c15t.com/docs/frameworks/next/components/consent-banner): A pre-built consent banner that appears when user consent is needed. Supports policy-aware layout, theming, and advanced composition when markup must change.
- [ConsentDialog](https://c15t.com/docs/frameworks/next/components/consent-dialog): A modal dialog where users can toggle individual consent categories.
- [ConsentWidget](https://c15t.com/docs/frameworks/next/components/consent-widget): An inline consent management widget for embedding in settings or privacy pages. Shows category toggles with accordion layout.
- [ConsentDialogTrigger](https://c15t.com/docs/frameworks/next/components/consent-dialog-trigger): A floating, draggable button that lets users re-open the consent dialog at any time.
- [ConsentDialogLink](https://c15t.com/docs/frameworks/next/components/consent-dialog-link): An inline trigger for opening the consent dialog from footers, legal pages, and account settings.
- [Frame](https://c15t.com/docs/frameworks/next/components/frame): A consent-gated content wrapper - children only mount when the required consent category is granted.
- [DevTools](https://c15t.com/docs/frameworks/next/components/dev-tools): A development tool for inspecting consent state, geolocation, loaded scripts, and consent events in real time.
- [Styling Overview](https://c15t.com/docs/frameworks/next/styling/overview): Five approaches for theming consent components — design tokens, component slots, CSS variables, className, and noStyle mode.
- [Design Tokens](https://c15t.com/docs/frameworks/next/styling/tokens): The six base token categories that control colors, typography, spacing, radius, shadows, and motion, plus optional dark-mode overrides.
- [Component Slots](https://c15t.com/docs/frameworks/next/styling/slots): Target individual component parts with styles using the slot system - className strings or inline style objects.
- [Class Names](https://c15t.com/docs/frameworks/next/styling/classnames): Style consent components using className props and per-slot className targeting via the theme.
- [Tailwind CSS](https://c15t.com/docs/frameworks/next/styling/tailwind): Use Tailwind CSS utility classes to style consent components via the slot system.
- [Color Scheme](https://c15t.com/docs/frameworks/next/styling/color-scheme): Support light mode, dark mode, and system preference detection in consent components.
- [CSS Variables](https://c15t.com/docs/frameworks/next/styling/css-variables): Reference for all --c15t-* CSS custom properties generated by the theme system.
- [useConsentManager](https://c15t.com/docs/frameworks/next/hooks/use-consent-manager/overview): The primary hook for accessing consent state and actions. Returns the full consent store including all state properties and action methods.
- [Checking Consent](https://c15t.com/docs/frameworks/next/hooks/use-consent-manager/checking-consent): Use has() for flexible consent checks with AND, OR, and NOT logic. Check if any consent exists with hasConsented().
- [Setting Consent](https://c15t.com/docs/frameworks/next/hooks/use-consent-manager/setting-consent): Save, update, and reset consent preferences with setConsent(), setSelectedConsent(), and saveConsents().
- [Location Info](https://c15t.com/docs/frameworks/next/hooks/use-consent-manager/location-info): Access detected jurisdiction, country, and region. Override geolocation for testing.
- [useTranslations](https://c15t.com/docs/frameworks/next/hooks/use-translations): Access the current language's translations for building custom consent UI.
- [useFocusTrap](https://c15t.com/docs/frameworks/next/hooks/use-focus-trap): Trap keyboard focus within a container for accessible modal dialogs.
- [useColorScheme](https://c15t.com/docs/frameworks/next/hooks/use-color-scheme): Manage light/dark mode preferences for consent components.
- [useReducedMotion](https://c15t.com/docs/frameworks/next/hooks/use-reduced-motion): Detect the user's prefers-reduced-motion OS setting and reactively disable animations.
- [useTextDirection](https://c15t.com/docs/frameworks/next/hooks/use-text-direction): Manage RTL/LTR text direction based on the active language for consent UI.
- [useSSRStatus](https://c15t.com/docs/frameworks/next/hooks/use-ssr-status): Check whether server-side rendered consent data was used during initialization.
- [useDraggable](https://c15t.com/docs/frameworks/next/hooks/use-draggable): Make an element draggable between viewport corners with snapping, persistence, and animation support.
- [Troubleshooting](https://c15t.com/docs/frameworks/next/troubleshooting): Solutions for common issues with @c15t/nextjs — provider errors, missing banners, consent persistence, and more.
- [Building Headless Components](https://c15t.com/docs/frameworks/next/building-headless-components): Build policy-aware custom consent components in Next.js using the headless hooks and policy-pack tooling.
- [Headless Mode](https://c15t.com/docs/frameworks/next/headless): Build fully custom consent UI using only hooks - no pre-built components required.
- [IAB TCF 2.3](https://c15t.com/docs/frameworks/next/iab/overview): Implement IAB Transparency & Consent Framework 2.3 compliance for programmatic advertising in EU/EEA jurisdictions.
- [IABConsentBanner](https://c15t.com/docs/frameworks/next/iab/consent-banner): An IAB TCF 2.3 compliant consent banner that displays partner count, purpose summaries, and legitimate interest notices.
- [IABConsentDialog](https://c15t.com/docs/frameworks/next/iab/consent-dialog): An IAB TCF 2.3 compliant preference center with tabbed purpose and vendor management.
- [useGVLData (Internal)](https://c15t.com/docs/frameworks/next/iab/use-gvl-data): Status note for the internal GVL hook used by the built-in IAB dialog.
- [Overview](https://c15t.com/docs/cli/overview): The c15t CLI scaffolds, migrates, and configures consent management in your project.
- [Quickstart](https://c15t.com/docs/cli/quickstart): Scaffold consent management into a React or Next.js app in under 2 minutes.
- [setup](https://c15t.com/docs/cli/commands/setup): Interactive scaffolder that installs packages and adds consent components to your project.
- [generate](https://c15t.com/docs/cli/commands/generate): Generate consent schema and code for your project.
- [codemods](https://c15t.com/docs/cli/commands/codemods): Migrate code between c15t versions automatically.
- [self-host](https://c15t.com/docs/cli/commands/self-host): Workflow commands for self-hosted @c15t/backend deployments.
- [skills](https://c15t.com/docs/cli/commands/skills): Install c15t agent skills for AI-assisted development.
- [login & logout](https://c15t.com/docs/cli/commands/auth): Authenticate the CLI with your hosted c15t account on inth.com.
- [Global flags](https://c15t.com/docs/cli/global-flags): Flags that work on every CLI command.
- [Telemetry](https://c15t.com/docs/cli/telemetry): What the CLI collects, why, and how to disable it.
- [Integrations](https://c15t.com/docs/integrations/overview): Load analytics, pixels, tag managers, and widgets through c15t so consent state controls when they run, update, and appear in your consent UI.
- [Build a Custom Script Integration](https://c15t.com/docs/integrations/building-integrations): Learn when to use a raw Script, when to build a reusable manifest-backed integration, and how to debug and test custom consent-aware scripts in c15t.
- [Google Maps](https://c15t.com/docs/integrations/google-maps): Render Google Maps only after consent with one shared Maps JavaScript API loader and independently managed map instances.
- [YouTube](https://c15t.com/docs/integrations/youtube): Keep YouTube iframes unmounted until consent with a privacy-enhanced, lazy-loaded React or Next.js embed.
- [Google Tag Manager](https://c15t.com/docs/integrations/google-tag-manager): Deploy and manage marketing tags centrally with automatic consent state synchronization.
- [GA4 + Google Ads (gtag.js)](https://c15t.com/docs/integrations/google-tag): Send data to Google Analytics 4 and Google Ads with automatic Consent Mode v2 support.
- [Ahrefs Analytics](https://c15t.com/docs/integrations/ahrefs-analytics): Cookieless web analytics from Ahrefs with a prebuilt helper that wires the project key into a c15t-managed script.
- [Adobe Analytics](https://c15t.com/docs/integrations/adobe-analytics): Adobe Analytics loaded through an Adobe Experience Platform Data Collection Tags embed URL.
- [Amplitude](https://c15t.com/docs/integrations/amplitude): Load Amplitude Browser SDK 2 with c15t and gate product analytics behind measurement consent.
- [Cloudflare Web Analytics](https://c15t.com/docs/integrations/cloudflare-web-analytics): Cookieless analytics from Cloudflare with a prebuilt helper that serializes the beacon config into the `data-cf-beacon` attribute.
- [Clearbit](https://c15t.com/docs/integrations/clearbit): Visitor and company enrichment loaded with Clearbit's account-keyed tags.js snippet.
- [Microsoft Clarity](https://c15t.com/docs/integrations/microsoft-clarity): Session replay and behavior analytics with a prebuilt helper that keeps Clarity consent synchronized with c15t measurement state.
- [Databuddy](https://c15t.com/docs/integrations/databuddy): Databuddy is a privacy-focused analytics platform that helps you understand user behavior and track events. It supports cookieless tracking and manages consent automatically through c15t's consent state synchronization.
- [Fathom Analytics](https://c15t.com/docs/integrations/fathom-analytics): Privacy-friendly cookieless analytics with a prebuilt helper that maps Fathom's data attributes into a c15t-managed script.
- [Heap](https://c15t.com/docs/integrations/heap): Load Heap with c15t and gate autocapture product analytics behind measurement consent.
- [Matomo Analytics](https://c15t.com/docs/integrations/matomo-analytics): Load Matomo with c15t and keep Matomo's queue aligned with measurement consent.
- [Mixpanel Analytics](https://c15t.com/docs/integrations/mixpanel-analytics): Load Mixpanel with c15t and let Mixpanel's own opt-in and opt-out APIs follow measurement consent.
- [Hotjar](https://c15t.com/docs/integrations/hotjar): Product analytics and behavior insights with a prebuilt helper that seeds Hotjar globals before loading the vendor bundle.
- [Hightouch](https://c15t.com/docs/integrations/hightouch): Load Hightouch Events with c15t and gate the browser SDK behind measurement consent.
- [LogRocket](https://c15t.com/docs/integrations/logrocket): Session replay and monitoring loaded after measurement consent with LogRocket's browser SDK.
- [Plausible Analytics](https://c15t.com/docs/integrations/plausible-analytics): Privacy-friendly cookieless analytics with a prebuilt helper that preserves Plausible's queue bootstrap and loader attributes.
- [PostHog](https://c15t.com/docs/integrations/posthog): PostHog is an open-source product analytics platform for tracking user behavior, session replays, feature flags, and A/B testing. It supports cookieless tracking, allowing analytics to continue even without cookie consent.
- [Promptwatch](https://c15t.com/docs/integrations/promptwatch): Promptwatch analyzes traffic on your site for Artificial Intelligence (AI) traffic and usage insights. Data is stored in the EU without user-identifiable information.
- [Pirsch](https://c15t.com/docs/integrations/pirsch): Privacy-friendly, cookieless analytics loaded with Pirsch's fixed script id and identification-code attributes.
- [RudderStack](https://c15t.com/docs/integrations/rudderstack): Load RudderStack's JavaScript SDK with c15t and gate the browser SDK behind measurement consent.
- [Segment](https://c15t.com/docs/integrations/segment): Load Segment Analytics.js with c15t and gate it behind measurement consent.
- [Rybbit Analytics](https://c15t.com/docs/integrations/rybbit-analytics): Privacy-friendly analytics with script-tag configuration via Rybbit's data attributes.
- [Umami Analytics](https://c15t.com/docs/integrations/umami-analytics): Open-source, cookieless analytics with a prebuilt helper that maps Umami's data attributes into a c15t-managed script.
- [Vercel Analytics](https://c15t.com/docs/integrations/vercel-analytics): Bootstrap Vercel Analytics with a declarative queue and script attributes.
- [Crisp](https://c15t.com/docs/integrations/crisp): Load Crisp live chat with website ID, runtime, cookie, and session options.
- [Intercom](https://c15t.com/docs/integrations/intercom): Bootstrap Intercom settings and load the messenger widget bundle.
- [Meta Pixel](https://c15t.com/docs/integrations/meta-pixel): Track conversions and build audiences for Facebook and Instagram advertising campaigns.
- [Reddit Pixel](https://c15t.com/docs/integrations/reddit-pixel): Track conversions and build retargeting audiences for Reddit advertising campaigns.
- [TikTok Pixel](https://c15t.com/docs/integrations/tiktok-pixel): Measure ad performance and build audiences for TikTok advertising campaigns.
- [LinkedIn Insights](https://c15t.com/docs/integrations/linkedin-insights): Track conversions and build matched audiences for LinkedIn advertising campaigns.
- [Microsoft UET](https://c15t.com/docs/integrations/microsoft-uet): Track conversions and measure performance for Microsoft Advertising and Bing Ads.
- [Snapchat Pixel](https://c15t.com/docs/integrations/snapchat-pixel): Measure Snapchat ad performance and build remarketing audiences with a prebuilt pixel helper.
- [X Pixel (Twitter Pixel)](https://c15t.com/docs/integrations/x-pixel): Track conversions and build audiences for advertising campaigns on X (formerly Twitter).
- [Quickstart](https://c15t.com/docs/self-host/quickstart): Self-host the c15t consent management backend in your own infrastructure.
- [Database Setup](https://c15t.com/docs/self-host/guides/database-setup): Configure a database adapter for your self-hosted c15t backend.
- [Framework Integration](https://c15t.com/docs/self-host/guides/framework-integration): Mount the c15t consent backend in any JavaScript framework or runtime.
- [Edge Deployment](https://c15t.com/docs/self-host/guides/edge-deployment): Run consent policy resolution at the edge for faster initial banner loads.
- [Caching](https://c15t.com/docs/self-host/guides/caching): Add a caching layer to your self-hosted c15t backend for production performance.
- [IAB TCF Support](https://c15t.com/docs/self-host/guides/iab-tcf): Enable IAB Transparency and Consent Framework (TCF) support in your self-hosted backend.
- [Policy Packs](https://c15t.com/docs/self-host/guides/policy-packs): Configure regional policy packs on the backend and return deterministic runtime policy decisions from /init.
- [Observability](https://c15t.com/docs/self-host/guides/observability): Add logging, metrics, and tracing to your self-hosted c15t backend.
- [API Endpoints](https://c15t.com/docs/self-host/api/endpoints): Full reference for every c15t consent backend endpoint.
- [Configuration Reference](https://c15t.com/docs/self-host/api/configuration): Complete reference for all c15t backend configuration options.
- [Contributing](https://c15t.com/docs/contributing): Entry point for Contributing documentation.
- [Docs Preview GitHub Action](https://c15t.com/docs/contributing/docs-preview-action): How our composite GitHub Action deploys the docs preview to Vercel and posts a sticky PR comment.
- [Documentation System Setup](https://c15t.com/docs/contributing/documentation-setup): Learn how to set up the unified documentation build system for local development and understand the production deployment process.
- [Building Privacy Tools in the Open](https://c15t.com/docs/oss/why-open-source): We believe great developer tools should be built in the open, with transparency and community collaboration at their core. This philosophy guides how we're building modern privacy infrastructure.
- [Contributing to c15t.com](https://c15t.com/docs/oss/contributing): Entry point for Contributing to c15t.com documentation.
- [c15t Community Code of Conduct](https://c15t.com/docs/oss/code-of-conduct): Guidelines for fostering an inclusive, respectful, and collaborative open-source community
- [License](https://c15t.com/docs/oss/license): Apache License 2.0 applies to c15t open source packages and this repository.
- [Cookie Policy](https://c15t.com/docs/legals/cookie-policy): Entry point for Cookie Policy documentation.
- [Privacy Policy](https://c15t.com/docs/legals/privacy-policy): Entry point for Privacy Policy documentation.
- [v2.2.0 - Consent-Aware Embeds, Configurable Controls, and More Integrations](https://c15t.com/changelog/2.2.0): Minor release adding consent-aware Google Maps and YouTube components, a configurable consent controls toolbar, eight script integrations, a reusable SDK hook, policy-aware action styling, CSP nonce support, reliability fixes, and new translations.
- [v1.1.1 — Bundle Reduction Update](https://c15t.com/changelog/2025-04-24-v1.1.1): Performance-focused release achieving a massive 58.9% bundle size reduction while introducing a new headless package for custom implementations. Removed framer-motion and Tailwind variants for faster load times with zero UX compromise.
- [v1.1.2 — Optimistic UI & Bundle Optimization](https://c15t.com/changelog/2025-04-24-v1.1.2): Performance-focused release introducing optimistic UI updates for instant user feedback, massive 58.9% bundle size reduction, and a new headless package for custom implementations with improved event handling.
- [v1.1.3 — Enhanced Theming & Callback Improvements](https://c15t.com/changelog/2025-04-29-v1.1.3): Major release introducing comprehensive theming support with dark/light/system detection, improved consent callbacks with structured data, and enhanced color scheme integration. Includes breaking changes for theme system and callback data structure.
- [v1.1.4 — Translation System Fixes & Core Improvements](https://c15t.com/changelog/2025-04-30-v1.1.4): Patch release addressing critical translation functionality issues across core and react packages. Introduces better modularity, improved fallback behavior, comprehensive test coverage, and enhanced translation utility functions.
- [v1.1.5 — Tailwind CSS v3 Compatibility & Style Fixes](https://c15t.com/changelog/2025-05-04-v1.1.5): Patch release fixing critical Tailwind CSS v3 compatibility issues by removing CSS layers and improving noStyle theme handling. Ensures proper style application and prevents conflicts with modern Tailwind configurations.
- [v1.2.0 — Backend Architecture Overhaul & Translation System Refactor](https://c15t.com/changelog/2025-05-12-v1.2.0): Major release introducing a complete backend refactor to oRPC client/server architecture with OpenAPI support, CORS middleware, and streamlined translation system with common strings consolidation. Includes breaking changes for translation structure.
- [v1.2.1 — API Architecture Hardening, Translations Cleanup, and Tailwind v3 Fix](https://c15t.com/changelog/2025-05-12-v1.2.1): Patch release refining the new API architecture with oRPC + OpenAPI, consolidating translations into common keys, fixing Tailwind v3 layer collision, and improving schema validation and configuration defaults. Introduces a type-safe Node.js SDK and centralized routing.
- [v1.3.0 — Translations Package, SSR Consent, CLI Telemetry, and Next.js Restructure](https://c15t.com/changelog/2025-06-09-v1.3.0): Minor release introducing the new @c15t/translations package with 8 languages, server-side consent initialization, CLI telemetry and onboarding upgrades, and a Next.js package restructuring that removes middleware exports. Includes backend translation support, improved schemas, and infrastructure/tooling updates.
- [v1.3.1 — Next.js Data Fetching Refinements, Docs Fixes, and zh Translations](https://c15t.com/changelog/2025-06-23-v1.3.1): Patch release refining Next.js initial data fetching in c15t mode, fixing quickstart links, improving core fallbacks, and adding Chinese (zh) translations. Includes dependency updates across packages.
- [v1.3.2 — Next.js Relative URL Fix](https://c15t.com/changelog/2025-06-23-v1.3.2): Patch release fixing a relative URL error in the Next.js integration.
- [v1.3.3 — GTM Support, CookieBanner Focus Toggle, Next.js URL Validation](https://c15t.com/changelog/2025-06-24-v1.3.3): Patch release adding Google Tag Manager support in core, allowing trapFocus={false} in CookieBanner, improving URL validation in Next.js, and updating React dependency.
- [v1.4.0 — Ignore Geo, Provider DX, Store Config, A11y, CLI Fixes](https://c15t.com/changelog/2025-06-26-v1.4.0): Minor release improving developer experience with ignoreGeoLocation and consentCategories, adding a debug-friendly store config prop, enhancing accessibility, and fixing CLI onboarding issues.
- [v1.4.1 — Next.js: Custom c15t Headers for Initial Fetch](https://c15t.com/changelog/2025-06-26-v1.4.1): Patch release adding custom c15t headers to Next.js initial data fetch, enabling backend provider overrides and more reliable initialization.
- [v1.4.2 — Indonesian Translations, Provider Render Fixes, URL Normalization](https://c15t.com/changelog/2025-06-26-v1.4.2): Patch release adding Bahasa Indonesia translations, improving provider rendering to prevent duplicate requests, normalizing URLs to remove trailing slashes, correcting consent logic, and refining banner animations. Includes dependency updates, caching improvements, and expanded tests.
- [v1.4.3 — Theme Inheritance Fixes for Provider-Scoped Themes](https://c15t.com/changelog/2025-06-26-v1.4.3): Patch release ensuring provider-level themes set in ConsentManagerProvider are correctly inherited by CookieBanner, ConsentManagerDialog, and ConsentManagerWidget for consistent styling.
- [v1.4.4 — Theme Inheritance Stability and Maintenance Updates](https://c15t.com/changelog/2025-06-26-v1.4.4): Patch release fixing theme inheritance in ConsentManager and related components, plus dependency updates and stronger tests to prevent regressions.
- [v1.5.0 — Next.js Pages Support, GDPR Button Order, Backend Enhancements](https://c15t.com/changelog/2025-06-27-v1.5.0): Minor release adding Next.js Pages Directory support and updating cookie banner button order for GDPR guidance, alongside backend and integration improvements.
- [v1.6.0 – New Docs, Rebuilt Self-Hosting Backend, Better Callbacks, and More](https://c15t.com/changelog/2025-09-09-v1.6.0): Minor release with a rebuilt self-hosting backend, a brand new docs site, improved consent checking, and callback improvements.
- [v1.6.1 - React Scroll Lock Fix](https://c15t.com/changelog/2025-09-18-v1.6.1): Patch release fixing a bug where the scroll lock persisted after the dialog has been dismissed.
- [v1.7.0 - Script Loader & iFrame Blocking](https://c15t.com/changelog/2025-10-11-v1.7.0): Minor release with a new approach to script loader and iFrame blocking.
- [v1.7.1 - CLI Improvements & Bug Fixes](https://c15t.com/changelog/2025-10-22-v1.7.1): Patch release with CLI improvements including bun support and bug fixes.
- [v1.8.0 - Cross-Subdomain Consent, Legal Links, User Identification & EU Languages](https://c15t.com/changelog/2025-10-27-v1.8.0): Feature release adding cross-subdomain consent persistence via cookies, configurable legal links in components, user identification tracking, and comprehensive language support with all 24 EU official languages.
- [v1.8.2 - React Bug Fixes](https://c15t.com/changelog/2025-12-12-v1.8.2): Patch release with bug fixes and improvements.
- [v1.8.3 - Experimental Global Privacy Control Support & Bug Fixes](https://c15t.com/changelog/2026-01-19-v1.8.3): Patch release with experimental Global Privacy Control support and bug fixes.
- [v2.0.0-rc.0 — New Styling System, IAB TCF, Dev Tools, Backend v2 & More](https://c15t.com/changelog/2026-02-12-v2.0.0-rc.0): Release candidate introducing a token-based styling system, IAB TCF 2.3 support, dev tools, backend v2, network blocker, GPC support and a complete documentation overhaul.
- [v2.0.0-rc.5 — Policy Packs, Per-Policy GPC, Fallback Policies & Dev-Tools Improvements](https://c15t.com/changelog/2026-03-11-v2.0.0-rc.5): Release candidate introducing policy packs for regional consent resolution, per-policy GPC support, fallback policies, policy inspection, and developer-experience improvements.
- [v2.0.0-rc.6 — Smaller Client Bundles, Modular IAB, UI Primitives, and Flexible Policy Actions](https://c15t.com/changelog/2026-04-06-v2.0.0-rc.6): Release candidate focused on smaller client bundles, extracted IAB support, shared UI primitives with framework adapters, flexible policy action layouts, and cleaner package styling/toolchain boundaries.
- [v2.0.0-rc.7 — Theming Fixes, Simpler Tailwind Setup, and Clearer Customization Guidance](https://c15t.com/changelog/2026-04-08-v2.0.0-rc.7): Release candidate focused on fixing theming regressions in the prebuilt UI, simplifying the Tailwind setup contract, clarifying the recommended customization ladder, and adding better manual coverage for CSS behavior across Tailwind 3, Tailwind 4, and plain CSS.
- [v2.0.0 - New Styling System, Policy Packs, Backend v2 & More](https://c15t.com/changelog/2026-04-14-v2.0.0): Stable release notes for c15t 2.0, covering the token-based styling system, policy packs, GPC, IAB TCF 2.3, bundled docs, c15t/skills, dev tools, backend v2, migration tooling, and the prebuilt UI.
- [v2.0.1 - TanStack Devtools Support & Tailwind Import Ordering](https://c15t.com/changelog/2026-04-19-v2.0.1): Patch release adding official TanStack Devtools support for @c15t/dev-tools and improving Tailwind v4 stylesheet import ordering in the c15t CLI.
- [v2.1.0 - Expanded Script Integrations and Provider Registry](https://c15t.com/changelog/2026-05-13-v2.1.0): Minor release expanding the consent-aware script loader with a registry-backed provider system, more prebuilt integrations, stronger lifecycle utilities, CLI discovery updates, and German translation refinements.
- [Compare c15t](https://c15t.com/docs/comparison): Compare c15t with open-source consent libraries, React banners, and hosted CMPs such as OneTrust, Cookiebot by Usercentrics, Didomi, Usercentrics, and Osano.
- [Compare c15t](https://c15t.com/docs/comparisons): Compare c15t with open-source consent libraries, React banners, and hosted CMPs such as OneTrust, Cookiebot by Usercentrics, Didomi, Usercentrics, and Osano.
- [c15t vs Cookiebot](https://c15t.com/docs/comparisons/cookiebot): Compare c15t with Cookiebot by Usercentrics for cookie blocking, consent records, hosted CMP workflows, and app-owned consent state.
- [c15t vs CookieConsent v3](https://c15t.com/docs/comparisons/cookieconsent-v3): Compare c15t with CookieConsent v3 for JavaScript consent, script gating, backend records, and framework-ready consent state.
- [c15t vs Didomi](https://c15t.com/docs/comparisons/didomi): Compare c15t with Didomi for consent proofs, hosted platform workflows, records, and developer-owned framework integration.
- [c15t vs Iubenda](https://c15t.com/docs/comparisons/iubenda): Compare c15t with Iubenda for cookie banners, CMP workflows, consent records, Google Consent Mode, and app-owned consent state.
- [c15t vs Klaro!](https://c15t.com/docs/comparisons/klaro): Compare c15t with Klaro! for service-based consent, Google Consent Mode, backend records, and framework integration.
- [c15t vs OneTrust](https://c15t.com/docs/comparisons/onetrust): Compare c15t with OneTrust for hosted CMP workflows, consent records, script control, and developer-owned app integration.
- [c15t vs Osano](https://c15t.com/docs/comparisons/osano): Compare c15t with Osano CookieConsent and Osano's hosted CMP for developer-owned consent, records, policy, and app integration.
- [c15t vs react-cookie-consent](https://c15t.com/docs/comparisons/react-cookie-consent): Compare c15t with react-cookie-consent for React banners, hooks, consent categories, script blocking, backend records, and app state.
- [c15t vs Silktide Consent Manager](https://c15t.com/docs/comparisons/silktide-consent-manager): Compare c15t with Silktide Consent Manager for client-side banners, Google Consent Mode, framework APIs, and backend policy resolution.
- [c15t vs tarteaucitron.js](https://c15t.com/docs/comparisons/tarteaucitron): Compare c15t with tarteaucitron.js for service catalogs, script loading, Consent Mode, backend records, and app-owned consent state.
- [c15t vs Usercentrics](https://c15t.com/docs/comparisons/usercentrics): Compare c15t with Usercentrics Web CMP for hosted consent workflows, auto-blocking, regional rules, and app-integrated consent state.
- [Client Modes](https://c15t.com/docs/shared/concepts/client-modes): Reference page for client modes.
- [Consent Categories](https://c15t.com/docs/shared/concepts/consent-categories): Reference page for consent categories.
- [Consent Models](https://c15t.com/docs/shared/concepts/consent-models): Reference page for consent models.
- [Cookie Management](https://c15t.com/docs/shared/concepts/cookie-management): Reference page for cookie management.
- [Glossary](https://c15t.com/docs/shared/concepts/glossary): Reference page for glossary.
- [Initialization Flow](https://c15t.com/docs/shared/concepts/initialization-flow): Reference page for initialization flow.
- [Policy Packs](https://c15t.com/docs/shared/concepts/policy-packs): Reference page for policy packs.
- [Consent Banner](https://c15t.com/docs/shared/react/components/consent-banner): Reference page for consent banner.
- [Consent Dialog](https://c15t.com/docs/shared/react/components/consent-dialog): Reference page for consent dialog.
- [Consent Dialog Link](https://c15t.com/docs/shared/react/components/consent-dialog-link): Reference page for consent dialog link.
- [Consent Dialog Trigger](https://c15t.com/docs/shared/react/components/consent-dialog-trigger): Reference page for consent dialog trigger.
- [Consent Manager Provider](https://c15t.com/docs/shared/react/components/consent-manager-provider): Reference page for consent manager provider.
- [Consent Widget](https://c15t.com/docs/shared/react/components/consent-widget): Reference page for consent widget.
- [Dev Tools](https://c15t.com/docs/shared/react/components/dev-tools): Reference page for dev tools.
- [Frame](https://c15t.com/docs/shared/react/components/frame): Reference page for frame.
- [Building Headless Components](https://c15t.com/docs/shared/react/guides/building-headless-components): Reference page for building headless components.
- [Callbacks](https://c15t.com/docs/shared/react/guides/callbacks): Reference page for callbacks.
- [Headless](https://c15t.com/docs/shared/react/guides/headless): Reference page for headless.
- [Iframe Blocking](https://c15t.com/docs/shared/react/guides/iframe-blocking): Reference page for iframe blocking.
- [Internationalization](https://c15t.com/docs/shared/react/guides/internationalization): Reference page for internationalization.
- [Network Blocker](https://c15t.com/docs/shared/react/guides/network-blocker): Reference page for network blocker.
- [Optimization](https://c15t.com/docs/shared/react/guides/optimization): Reference page for optimization.
- [Policy Packs](https://c15t.com/docs/shared/react/guides/policy-packs): Reference page for policy packs.
- [Script Loader](https://c15t.com/docs/shared/react/guides/script-loader): Reference page for script loader.
- [Use Color Scheme](https://c15t.com/docs/shared/react/hooks/use-color-scheme): Reference page for use color scheme.
- [Checking Consent](https://c15t.com/docs/shared/react/hooks/use-consent-manager/checking-consent): Reference page for checking consent.
- [Location Info](https://c15t.com/docs/shared/react/hooks/use-consent-manager/location-info): Reference page for location info.
- [Overview](https://c15t.com/docs/shared/react/hooks/use-consent-manager/overview): Reference page for overview.
- [Setting Consent](https://c15t.com/docs/shared/react/hooks/use-consent-manager/setting-consent): Reference page for setting consent.
- [Use Draggable](https://c15t.com/docs/shared/react/hooks/use-draggable): Reference page for use draggable.
- [Use Focus Trap](https://c15t.com/docs/shared/react/hooks/use-focus-trap): Reference page for use focus trap.
- [Use Reduced Motion](https://c15t.com/docs/shared/react/hooks/use-reduced-motion): Reference page for use reduced motion.
- [Use SSR Status](https://c15t.com/docs/shared/react/hooks/use-ssr-status): Reference page for use ssr status.
- [Use Text Direction](https://c15t.com/docs/shared/react/hooks/use-text-direction): Reference page for use text direction.
- [Use Translations](https://c15t.com/docs/shared/react/hooks/use-translations): Reference page for use translations.
- [Consent Banner](https://c15t.com/docs/shared/react/iab/consent-banner): Reference page for consent banner.
- [Consent Dialog](https://c15t.com/docs/shared/react/iab/consent-dialog): Reference page for consent dialog.
- [Overview](https://c15t.com/docs/shared/react/iab/overview): Reference page for overview.
- [Use GVL Data](https://c15t.com/docs/shared/react/iab/use-gvl-data): Reference page for use gvl data.
- [Classnames](https://c15t.com/docs/shared/react/styling/classnames): Reference page for classnames.
- [Color Scheme](https://c15t.com/docs/shared/react/styling/color-scheme): Reference page for color scheme.
- [CSS Variables](https://c15t.com/docs/shared/react/styling/css-variables): Reference page for css variables.
- [Overview](https://c15t.com/docs/shared/react/styling/overview): Reference page for overview.
- [Slots](https://c15t.com/docs/shared/react/styling/slots): Reference page for slots.
- [Stylesheet Entrypoint](https://c15t.com/docs/shared/react/styling/stylesheet-entrypoint): Reference page for stylesheet entrypoint.
- [Tailwind](https://c15t.com/docs/shared/react/styling/tailwind): Reference page for tailwind.
- [Tokens](https://c15t.com/docs/shared/react/styling/tokens): Reference page for tokens.
- [Troubleshooting](https://c15t.com/docs/shared/troubleshooting): Reference page for troubleshooting.
## Content
# Frameworks
URL: https://c15t.com/docs/frameworks
Reference page for frameworks.
* [React](/docs/frameworks/react/quickstart)
* [JavaScript](/docs/frameworks/javascript/quickstart)
* [Next.js](/docs/frameworks/next/quickstart)
# Quickstart
URL: https://c15t.com/docs/frameworks/react/quickstart
Add consent management to your React app in under 5 minutes.
## Via CLI
## Manual Installation
1. **Install package**
2. **Import styles** Import the prebuilt component stylesheet in your app-level CSS entrypoint. This is required for styled components to render correctly.
```css
@import "@c15t/react/styles.css";
```
Keeping the c15t stylesheet in your global CSS entrypoint makes layer and cascade order explicit. JS/TSX side-effect imports can load in a different order across framework and Tailwind tooling, which makes style regressions harder to debug.With Tailwind v4, keep c15t at the end of the top-level @import block so Fumadocs, tw-animate-css, and other preset imports do not override c15t theme tokens.
> ℹ️ Info:
> If you are using the headless API or fully custom styling, you can skip this import. src/main.tsx should keep importing ./index.css as usual.
3. **Create ConsentManager components** Create a provider component with the consent UI and a wrapper that re-exports it. This initializes the consent store and makes consent state available to all child components.
```tsx
'use client';
import { type ReactNode } from 'react';
import { ConsentManagerProvider, ConsentBanner, ConsentDialog } from '@c15t/react';
export default function ConsentManagerClient({ children }: { children: ReactNode }) {
return (
{children}
);
}
```
```tsx
import type { ReactNode } from 'react';
import ConsentManagerProvider from './provider';
export function ConsentManager({ children }: { children: ReactNode }) {
return {children};
}
```
> ℹ️ Info:
> Hosted mode is the recommended production setup because the backend resolves jurisdiction and policy, keeps durable consent records, and lets c15t recover from temporary network failures by re-syncing later.
>
> ⚠️ Warning:
> Don't have a backend yet? You can use mode: 'offline' for local-only consent storage, but it gives up backend audit history, server-side consent awareness, and automatic jurisdiction detection. Review the browser-only storage consequences before choosing it for production.
4. **Mount ConsentManager at the app root** Wrap your existing app tree with `ConsentManager` so all routes/components can access consent state.
```tsx
import { ConsentManager } from './components/consent-manager';
export default function App() {
return (
{/* your existing app */}
);
}
```
5. **Verify it works** Start your development server and confirm:
1. A **consent banner** appears at the bottom of the page
2. Clicking **"Customize"** opens a dialog with toggles for each consent category
3. After accepting or rejecting, the banner dismisses and your choice persists across page reloads
> ℹ️ **Info:**
> Want to improve startup performance? See Optimization for the decision guide, prefetch setup, and network tuning.
## Optional: Add DevTools
Install DevTools only if you want a runtime inspector while building and debugging:
Then add it inside your existing provider:
```tsx title="components/consent-manager/provider.tsx"
import { DevTools } from '@c15t/dev-tools/react';
// ...
{process.env.NODE_ENV !== 'production' && }
{children}
```
> ℹ️ **Info:**
> Want to understand what's happening under the hood? See Initialization Flow for the lifecycle and Cookie Management for script/cookie behavior and revocation handling.
## Optional: AI Agents
Install c15t agent skills to let AI agents help with styling, i18n, scripts & other configuration.
See [AI Agents](/docs/ai-agents) for bundled package docs and agent skills.
## Next steps
* [Optimization](/docs/frameworks/react/optimization)
* [Script Loader](/docs/frameworks/react/script-loader)
* [Styling](/docs/frameworks/react/styling/overview)
* [Consent Categories](/docs/frameworks/react/concepts/consent-categories)
* [Components](/docs/frameworks/react/components/consent-banner)
* [AI Agents](/docs/ai-agents)
# Optimization
URL: https://c15t.com/docs/frameworks/react/optimization
Improve c15t startup performance in React with prefetching, proxy rewrites, and rendering tradeoffs.
Use this guide when you care about banner visibility speed, route static-ness, and reducing backend round-trip cost.
## Start Here
Apply the optimizations in this order:
|Situation|Use|Why|Tradeoff|
|--|--|--|--|
|Any production app using hosted mode|Same-origin `/api/c15t` proxy|Lowers browser startup overhead and keeps the backend origin out of client config|Requires framework or platform proxy setup|
|Banner speed matters on cold loads|`buildPrefetchScript()`|Starts `/init` before your app hydrates|Still a browser-side fetch, not SSR|
|Your app navigates client-side|Keep the provider mounted at the app root|Avoids remounting and re-running init work|Requires provider placement discipline|
|You cannot proxy and must stay cross-origin|``|Starts DNS/TLS work earlier|Smaller gain than same-origin proxying|
|You are using Next.js and want SSR or static-route-specific guidance|Next.js optimization docs|Covers `C15tPrefetch`, `fetchInitialData()`, and rendering tradeoffs|Next-specific|
> ℹ️ **Info:**
> Treat same-origin proxying as the baseline optimization. The others are situational layers you add when startup timing or route behavior justifies them.
## 1) Prefer Same-Origin Proxy
Proxy c15t requests through your app server so the browser calls your own origin instead of a third-party domain.
How you configure this depends on your framework — Vite has `server.proxy`, Remix has resource routes, and most deployment platforms support rewrite rules.
Then use:
```tsx
```
Why this helps:
* Same-origin requests avoid extra DNS/TLS setup in many deployments
* Ad blockers are less likely to block your init endpoint
* You can change backend infrastructure without touching client code
If you can only do one optimization, do this one first.
## 2) Prefetch Init Data Early
Use `buildPrefetchScript()` from the `c15t` core package to start the `/init` request before your app hydrates. Inject the script as early as possible in your HTML ``.
In production benchmarks with a same-origin rewrite, prefetching strategies show measurable improvement over client-only init:
|Strategy|Scripts loaded|Data request starts|Banner visible|
|--|--|--|--|
|Client-only (no prefetch)|baseline|baseline|baseline|
|Browser prefetch|\~1.3x faster|\~2.6x earlier|\~1.25x faster|
|Server prefetch|\~2x faster|before page loads|\~1.9x faster|
Use this when:
* The app is client-rendered
* You want a faster first banner without introducing SSR complexity
* You control the HTML template or document ``
### Inline Script Prefetch
```tsx
import { buildPrefetchScript } from 'c15t';
const prefetchScript = buildPrefetchScript({
backendURL: '/api/c15t',
});
// In your HTML template or root component:
```
Then initialize your provider normally. Matching prefetched data is consumed automatically by the runtime during first store initialization:
```tsx
import {
ConsentManagerProvider,
ConsentBanner,
ConsentDialog,
} from '@c15t/react';
export default function App({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
```
> ℹ️ **Info:**
> If overrides.gpc conflicts with the browser's ambient GPC signal, the prefetched entry is not reused and c15t falls back to a normal client /init.
## Keep The Provider Mounted Across Navigation
Mount the consent provider at the app root so route transitions do not remount it.
Why this helps:
* Avoids re-running init work on client-side navigation
* Prevents extra callback churn from remount cycles
* Keeps banner/dialog state stable between route transitions
Mount `ConsentManagerProvider` as high in the tree as possible so route transitions do not recreate it.
## Animation Performance
The default motion tokens are tuned for speed-first product UI:
|Token|Duration|Used for|
|--|--|--|
|`fast`|80ms|Banner slide + overlay, card scale, button hover, widget entry/exit|
|`normal`|150ms|Accordion, switch toggle|
|`slow`|200ms|Dialog trigger snap, tab indicator|
These defaults follow the principle that product UI should be fast and purposeful — animations exist for spatial continuity, not decoration. In benchmarks, animation duration contributes a constant floor to "data fetched → banner visible" timing. The default tokens sit at the lower end of standard UI ranges (80-200ms) to minimize that floor.
To customize motion durations and easing, see [Styling](/docs/frameworks/react/styling/overview).
## Reduce Network Overhead
If your browser must call a cross-origin backend URL directly, add `preconnect` so the browser can warm up the connection earlier. This is a fallback optimization when same-origin proxying is not possible.
If you must use a cross-origin backend URL, add preconnect so the browser starts DNS/TLS early:
```tsx
```
## Next.js-Specific SSR And Static Routes
This page is intentionally React-generic. If you are using Next.js and need SSR or static-route-specific guidance:
* See [Next.js Optimization](/docs/frameworks/next/optimization) for the static-vs-dynamic decision guide
* See [Next.js Server-Side Data Fetching](/docs/frameworks/next/server-side) for `fetchInitialData()`
# AI Agents
URL: https://c15t.com/docs/ai-agents
Integrate c15t with AI coding assistants using the docs bundled in each package and c15t agent skills. Give agents version-matched local docs for consent management, banners, script loading, callbacks, and integrations.
## Bundled Docs
Every supported c15t package now ships docs inside the installed package itself.
### Where to find them
* `node_modules/c15t/docs/README.md`
* `node_modules/@c15t/react/docs/README.md`
* `node_modules/@c15t/nextjs/docs/README.md`
* `node_modules/@c15t/backend/docs/README.md`
Start with the package `README.md`, then follow its linked pages for the relevant workflow.
These docs are version-matched to the exact c15t package version in your project, including generated reference content like prop and type tables.
### Why use them
If your app uses multiple c15t packages, use the docs from each relevant installed package instead of relying on stale model knowledge.
### Agent philosophy
When an AI tool is helping with c15t behavior, it should read the installed c15t docs first and use model knowledge second. That keeps consent flows, script gating, banner behavior, and integrations aligned with the exact version you have installed.
### Customization ladder for agents
When an agent is working on consent UI, it should choose the lowest-power tool that solves the task:
1. Start with the pre-built component and its existing props or provider options
2. Use `theme` tokens for semantic visual changes
3. Use `theme.slots` for targeted styling of specific parts
4. Use CSS variables or className-level overrides only when integrating with external styles
5. Use compound components only when the markup order must change
6. Use `noStyle` only when c15t structure is still correct but all styling must be replaced
7. Use headless hooks only when markup and behavior both need to be rebuilt
For common tasks:
* Banner footer background -> `theme.colors.surfaceHover`
* Banner card background -> `theme.colors.surface`
* Banner card/footer/title tweaks -> banner slots
* Stock action styling -> `theme.consentActions`
* Copy changes -> `ConsentManagerProvider.options.i18n`
If a token appears not to work, the agent should verify the token-to-component mapping before suggesting CSS overrides, `!important`, `noStyle`, or headless mode.
***
## Agent Skills
c15t publishes agent skills that give AI coding assistants deep knowledge of c15t's APIs, components, and configuration. Skills are reusable workflows and tool-specific guidance, not version-matched local docs.
### Installation
Via the c15t CLI:
Or directly:
### What skills provide
* **Styling customization** — strict escalation guidance across props, tokens, slots, CSS variables, compound components, `noStyle`, and headless
* **Internationalization** — translation setup, locale routing integration
* **Script management** — configuring third-party scripts with consent categories
* **Component setup** — ConsentBanner, ConsentDialog, provider configuration
### Supported tools
* Claude Code
* Cursor
* GitHub Copilot (via `.github/skills`)
* Any agent that supports the skills format
***
## When to use which
Use bundled docs when:
* Your agent can read files in the local project
* You want version-matched docs from the installed c15t packages
* You want a package-local README that tells the agent which detailed docs to read first
* You want concrete guidance for consent management, cookie banners, consent dialogs, preference centers, script loading, callbacks, and integrations
Use agent skills when:
* Your tool supports the skills ecosystem
* You want reusable workflows and tool-specific guidance that can point back to the installed package README files
Use both when:
* Your tool supports both local file context and skills
* You want local package docs plus reusable setup and configuration help
* You want the bundled package docs as the source of truth plus a reusable decision tree for customization
# Initialization Flow
URL: https://c15t.com/docs/frameworks/react/concepts/initialization-flow
What happens from provider mount to first render — the full consent lifecycle.
When the consent provider mounts, it creates a cached consent runtime, reads any stored consent from the browser, fetches the resolved policy from the backend (or uses SSR/offline data), and decides whether to show the banner. This entire sequence completes before the first meaningful consent-aware render.
## Lifecycle Sequence
**Simplified**
1. **Provider mounts** — creates (or retrieves from cache) a consent runtime and store
2. **Check stored consent** — reads existing consent from cookies / localStorage; if found and the policy fingerprint hasn't changed, the banner stays hidden
3. **Fetch init data** — calls the backend `GET /init` (or uses SSR/offline data) for the resolved policy, location, and translations
4. **Apply resolved policy** — the backend resolves the policy from your [policy pack](/docs/frameworks/react/concepts/policy-packs) based on visitor geo (region → country → fallback → default). The response includes the consent model, categories, UI mode, and a material fingerprint. If no policy pack is configured, the legacy jurisdiction-to-model mapping is used instead.
5. **Decide banner visibility** — shows the banner only if no prior consent exists, the resolved policy requires it (`ui.mode` is `banner` or `dialog`), or the policy fingerprint changed since last consent
6. **Gating enforced** — scripts, iframes, and network requests tagged with a consent category are blocked until that category is granted
7. **User interacts** — choices are persisted to storage, synced to the backend (with `policySnapshotToken` if configured), and blocked scripts/iframes load immediately after consent is granted
**Sequence Diagram**
```mermaid
sequenceDiagram
participant Provider as ConsentManagerProvider
participant Store as Consent Store
participant Storage as localStorage / Cookie
participant API as c15t Backend
participant UI as Banner / Dialog
participant Scripts as Script Loader
Provider->>Store: getOrCreateConsentRuntime()
Store->>Storage: getStoredConsent()
alt Stored consent exists
Storage-->>Store: consentInfo + consents
Store->>Store: activeUI = 'none'
else No stored consent
Store->>Store: isLoadingConsentInfo = true
end
Store->>Store: initConsentManager()
Store->>Storage: Check pending consent sync
opt Pending sync from revocation reload
Store->>API: Deferred setConsent() (non-blocking)
end
alt SSR data provided
Store->>Store: tryUseSSRData()
else No SSR data
Store->>API: GET /init
API-->>Store: policy, policyDecision, location, translations
end
Store->>Store: Apply resolved policy (model, categories, ui.mode)
Store->>Store: Check fingerprint change → re-prompt if needed
Store->>Store: Set activeUI, auto-grant if opt-out/none
alt User has no prior consent or policy changed
UI->>UI: Banner / Dialog appears (per policy ui.mode)
UI->>Store: saveConsents({ type })
Store->>Storage: Persist consent + subjectId + fingerprint
Store->>Scripts: updateScripts(), updateIframes(), updateNetwork()
Store->>API: POST /subjects + policySnapshotToken (non-blocking)
end
```
## How It Works
**Mount** — When the provider renders, it creates (or retrieves from cache) a consent runtime and store. Any existing consent is read from localStorage/cookies immediately. If consent already exists and the policy fingerprint matches, the banner stays hidden and gating rules apply right away. See [Client Modes](/docs/frameworks/react/concepts/client-modes) for how the mode affects runtime creation.
**Init** — The store fetches the resolved policy, location, and translation data. In hosted mode this calls `GET /init` on your backend; in offline mode it resolves from `offlinePolicy.policyPacks` locally. If SSR data was passed to the provider, the network fetch is skipped entirely. See [Server-Side Utilities](/docs/frameworks/react/server-side) for SSR setup.
**Policy resolution** — When [policy packs](/docs/frameworks/react/concepts/policy-packs) are configured, the backend resolves the right policy for the visitor based on their geo-location (region → country → fallback → default). The resolved policy determines the consent model (`opt-in`, `opt-out`, `iab`, or `none`), which categories are in scope, and what UI to show. For `opt-out` and `none` models, all categories are auto-granted — unless the resolved policy has `consent.gpc: true` and the browser sends a Global Privacy Control signal, in which case `marketing` and `measurement` are denied. If no policy pack is configured, the legacy jurisdiction-to-model mapping is used instead. See [Consent Models](/docs/frameworks/react/concepts/consent-models) for details.
**Re-prompting** — If the resolved policy's material fingerprint differs from the fingerprint stored with the user's last consent, the banner is shown again. This happens automatically when you change consent-affecting fields (model, categories, scope mode, allowed actions). Presentation-only changes do not trigger re-prompts. See [Policy Packs — Re-Prompting](/docs/frameworks/react/concepts/policy-packs#re-prompting) for details.
**Save** — When the user interacts with the banner or dialog, their choices are persisted to localStorage/cookies and synced to the backend (along with the `policySnapshotToken` if snapshot signing is configured). Script, iframe, and network gating rules update immediately based on the new consent state. See the [Script Loader](/docs/frameworks/react/script-loader), [Iframe Blocking](/docs/frameworks/react/iframe-blocking), and [Network Blocker](/docs/frameworks/react/network-blocker) guides for gating details.
**Revocation** — If a user revokes a previously granted category, the page reloads by default to ensure a clean execution environment. The API sync is deferred to the fresh page load. See [Cookie Management](/docs/frameworks/react/concepts/cookie-management) for revocation and persistence details.
## When Does the Banner Show?
The banner appears when any of these conditions are true:
1. **No existing consent** — the user has never consented (or their consent was cleared), **and** the resolved policy requires a UI (`ui.mode` is `banner` or `dialog`, or the model is `opt-in` or `iab`)
2. **Policy changed** — the material policy fingerprint differs from the fingerprint stored with the user's last consent (re-prompting)
3. **Storage is accessible** — the browser allows localStorage (not blocked in private mode)
If the resolved model is `none` or `opt-out` (and `ui.mode` is `none`), consents are auto-granted and the banner never appears. See [Consent Models](/docs/frameworks/react/concepts/consent-models) and [Policy Packs](/docs/frameworks/react/concepts/policy-packs) for details.
## Debugging the Lifecycle
Use the DevTools panel and callbacks to inspect each step of the initialization flow. `onConsentSet` is the broad lifecycle signal; `onConsentChanged` and `subscribeToConsentChanges()` are the change-only signals for explicit post-init saves.
|Step|DevTools Panel|Callback|What to check|
|--|--|--|--|
|Init / SSR hydration|Location|`onBannerFetched`|jurisdiction, countryCode, regionCode populated?|
|Policy resolution|Policy|`onBannerFetched`|`policyId`, `matchedBy`, `fingerprint` in policyDecision|
|Model resolution|Location|`onBannerFetched`|`model` value matches the resolved policy|
|Banner visibility|Consents|—|`activeUI` in store state; does policy `ui.mode` require it?|
|Re-prompting|Policy|—|Fingerprint mismatch between stored and resolved policy?|
|Consent save|Consents + Events|`onConsentSet`|`preferences` object in callback payload|
|Change-only integrations|Events|`onConsentChanged` or `subscribeToConsentChanges()`|`allowedCategories`, `deniedCategories`, and previous values only when a real save changed preferences|
|Script loading|Scripts|`onConsentSet`|Script IDs and their load/blocked status|
|Reload on revocation|Events|`onBeforeConsentRevocationReload`|Fires before reload; check localStorage for `c15t:pending-consent-sync`|
|Deferred sync|Events|`onError` (if sync fails)|After reload, check Events panel for successful API call|
Configure callbacks in the provider to log lifecycle events, and add DevTools for a visual inspector:
```tsx
import { type ReactNode } from 'react';
import { ConsentManagerProvider, ConsentBanner, ConsentDialog } from '@c15t/react';
import { DevTools } from '@c15t/dev-tools/react';
export default function ConsentManager({ children }: { children: ReactNode }) {
return (
{
console.log('Init complete:', { jurisdiction, location });
},
onConsentSet: ({ preferences }) => {
console.log('Broad consent lifecycle event:', preferences);
},
onConsentChanged: ({ allowedCategories, deniedCategories }) => {
console.log('Explicit consent change:', {
allowedCategories,
deniedCategories,
});
},
onBeforeConsentRevocationReload: ({ preferences }) => {
console.log('Reloading due to revocation:', preferences);
},
onError: ({ error }) => {
console.error('Consent error:', error);
},
},
}}
>
{process.env.NODE_ENV !== 'production' && }
{children}
);
}
```
# Client Modes
URL: https://c15t.com/docs/frameworks/react/concepts/client-modes
Choose how c15t connects to its backend - full hosted integration, offline-only, or bring your own backend.
c15t supports three client modes that determine how consent data is stored and synchronized. Choose the mode that matches your infrastructure:
* **Hosted mode** - Recommended for production. Backend-backed consent with geolocation, centralized policy resolution, audit history, and offline fallback.
* **Offline mode** - Browser-only storage with no network requests. Best for local development, demos, static deployments, or controlled fallback scenarios.
* **Custom mode** - Bring your own backend with custom endpoint handlers
> ⚠️ **Warning:**
> If you need durable consent records, server-side enforcement, or automatic jurisdiction detection, use hosted mode. Offline mode cannot provide those guarantees because consent lives only in the browser.
## Hosted Mode (Recommended)
The default mode. Connects to a c15t backend for full consent lifecycle management. We recommend using [inth.com](https://inth.com) for a fully managed experience, but you can [self-host](/docs/self-host) as well.
> ℹ️ **Info:**
> mode: 'hosted' is the preferred value. The legacy alias mode: 'c15t' is still supported for backward compatibility.
**What happens:**
1. On page load, the client calls `/init` to fetch geolocation, jurisdiction, localized translation strings
2. When the user grants or changes consent, it is saved locally before being synced to the backend.
3. If the backend is unreachable, it falls back to Offline mode and re-syncs with the backend when it's available
**Configuration:**
* `backendURL` (required) - API endpoint path
**Why it is the default for production:**
* The backend stays the source of truth for policy, translations, and jurisdiction logic
* Consent decisions can be stored beyond the current browser session for audit and support workflows
* Server-side systems can preload consent-aware behavior instead of waiting for client-only storage
* If the backend is temporarily unavailable, c15t can fall back locally and re-sync later
**Best for:** Production apps that need geolocation-based jurisdiction detection, consent record storage, and compliance audit trails.
```tsx
import { type ReactNode } from 'react';
import { ConsentManagerProvider, ConsentBanner } from '@c15t/react';
export function ConsentManager({ children }: { children: ReactNode }) {
return (
{children}
);
}
```
## Offline Mode
No network requests. Consent is stored entirely in the browser using localStorage and cookies.
**What happens:**
1. Default jurisdiction is GDPR unless manually set via `overrides`
2. Consent preferences persist locally only
3. No server-side consent records or analytics
> ℹ️ **Info:**
> Important: Offline mode still stores consent locally (cookie + localStorage). It only skips backend storage and sync.
### Consequences of Browser-Only Storage
If consent is not stored at all (for example, storage is blocked or frequently cleared):
* Users are treated as new visitors and must re-consent repeatedly
* Preferences are lost across browser resets, private sessions, and device changes
* You have no reliable audit evidence to prove prior consent choices
* Support and compliance teams have no centralized visibility into consent history by default
* Server-side systems cannot apply prior consent decisions before client initialization
**Trade-offs:**
* No automatic geolocation or jurisdiction detection
* No consent audit trail
* No centralized policy or translation updates without shipping frontend changes
* No cross-device sync
* No server-side visibility before client initialization
* Works without any backend infrastructure
**Best for:** Local development, Storybook/static demos, resilience fallback, or simpler sites that explicitly accept browser-only consent storage.
```tsx
import { type ReactNode } from 'react';
import { ConsentManagerProvider, ConsentBanner } from '@c15t/react';
export function ConsentManager({ children }: { children: ReactNode }) {
return (
{children}
);
}
```
## Custom Mode
Bring your own backend. You provide handler functions for each consent endpoint, and c15t calls them instead of making HTTP requests.
**What happens:**
1. On page load, the client calls your endpoint handler to fetch geolocation, jurisdiction, localized translation strings
2. When the user grants or changes consent, it is saved locally before being synced to the backend.
3. If one of your handlers fails, c15t returns a handler error and keeps local consent state, but automatic offline fallback and retry queue behavior is not provided for custom handlers by default
This lets you integrate c15t with any existing API - your CRM, your own consent database, or a third-party compliance service.
**Best for:** Teams with existing consent infrastructure that want c15t's frontend without its backend.
```tsx
import { type ReactNode } from 'react';
import { ConsentManagerProvider, ConsentBanner } from '@c15t/react';
export function ConsentManager({ children }: { children: ReactNode }) {
return (
{children}
);
}
```
## Choosing a Mode
|Feature|Hosted|Offline|Custom|
|--|--|--|--|
|Geolocation|Automatic|Manual via overrides|Your implementation|
|Policy source of truth|Backend-managed|Bundled into the frontend|Your implementation|
|Consent sync|API|Local only|Your implementation|
|Audit trail|Backend records|Not available|Your implementation|
|Server-side consent awareness|Supported|Not available|Your implementation|
|SSR data|Supported|Not available|Your implementation|
|Analytics|Built-in|Not available|Your implementation|
|Infrastructure|c15t backend|None|Your backend|
|Setup effort|Minimal|Zero|Moderate|
# Consent Models
URL: https://c15t.com/docs/frameworks/react/concepts/consent-models
How c15t determines consent behavior based on legal jurisdiction.
c15t supports four consent models that control how consent defaults, banner visibility, and category gating behave:
|Model|Philosophy|Banner|Categories default to|
|--|--|--|--|
|`opt-in`|Explicit consent required|Blocking banner|`false` (except `necessary`)|
|`opt-out`|Processing allowed by default|Non-blocking notice|`true` (all granted)|
|`iab`|IAB TCF 2.3 for programmatic ads|TCF banner|Managed by TCF framework|
|`null`|No regulation detected|No banner|`true` (all auto-granted)|
There are two ways c15t determines which model applies:
1. **Policy packs** (recommended) — you explicitly set the model per region in a `PolicyConfig`. This gives you full control over which regions get which model. See [Policy Packs](/docs/frameworks/react/concepts/policy-packs).
2. **Automatic jurisdiction mapping** (legacy default) — when no policy pack is configured, c15t detects the visitor's jurisdiction via geolocation and maps it to a model using the table below. This still works but gives you less control over categories, UI, and scope.
> ℹ️ **Info:**
> When using policy packs, the consent.model field in each policy directly sets the model — the automatic jurisdiction mapping is bypassed for that request.
Read the current consent model from the hook:
```tsx
import { useConsentManager } from '@c15t/react';
function ConsentStatus() {
const { model, policy } = useConsentManager();
return (
);
}
```
## The Four Models
### Opt-in
The strictest consent model, used for GDPR and similar regulations that require explicit, affirmative consent before any non-essential data processing occurs. All consent categories except `necessary` default to `false`. A consent banner must be shown before any tracking scripts load.
Applies to: EU (GDPR), UK (UK GDPR), Switzerland, Brazil (LGPD), Japan (APPI), South Korea (PIPA), Quebec (Law 25). Also the fallback for unknown jurisdiction codes.
### Opt-out
Used for CCPA-style regulations where data processing is permitted by default until the user exercises their right to opt out. All consent categories default to `true`. A blocking banner is not required — the typical pattern is a non-intrusive notice or footer link.
Applies to: California (CCPA), Canada (PIPEDA), Australia.
When the policy has `consent.gpc: true`, the browser's Global Privacy Control signal (`Sec-GPC: 1` or `navigator.globalPrivacyControl`) is respected — `marketing` and `measurement` are denied while other categories remain granted. The built-in California presets enable this by default. See [Policy Packs — GPC](/docs/frameworks/react/concepts/policy-packs#gpc) for details.
### IAB
IAB Transparency and Consent Framework (TCF) 2.3 mode for programmatic advertising compliance. Only activates when two conditions are met: the jurisdiction is `GDPR` or `UK_GDPR`, and `iab.enabled` is `true` in your configuration.
When active, IAB mode generates TC strings, registers the `__tcfapi` CMP API, and works with the Global Vendor List (GVL) for machine-readable consent signals. If `iab.enabled` is not set, GDPR jurisdictions fall back to standard opt-in.
### null
Returned when no jurisdiction is detected (`NONE` or `null`). No banner is displayed. On first visit, all categories are auto-granted.
## Jurisdiction Mapping
When no policy pack is configured, c15t maps jurisdictions to models automatically:
|Jurisdiction Code|Region|Consent Model|
|--|--|--|
|`GDPR`|European Union|opt-in|
|`UK_GDPR`|United Kingdom|opt-in|
|`CH`|Switzerland|opt-in|
|`BR`|Brazil (LGPD)|opt-in|
|`APPI`|Japan|opt-in|
|`PIPA`|South Korea|opt-in|
|`PIPEDA`|Canada (excl. Quebec)|opt-out|
|`QC_LAW25`|Quebec, Canada|opt-in|
|`CCPA`|California, USA|opt-out|
|`AU`|Australia|opt-out|
|`NONE`|No jurisdiction|null|
|*(unknown)*|Any other|opt-in|
**IAB override:** If `iab.enabled: true` and the jurisdiction is `GDPR` or `UK_GDPR`, the model becomes `'iab'` instead of `'opt-in'`. This override only applies to those two jurisdictions.
> ℹ️ **Info:**
> With policy packs, you set the model explicitly per policy — the automatic mapping above is only used as a fallback when no policy pack is configured, or for non-policy-pack features like auto-granting in opt-out jurisdictions.
Override the detected jurisdiction for testing:
```tsx
import { useConsentManager } from '@c15t/react';
function JurisdictionTester() {
const { setOverrides } = useConsentManager();
return (
);
}
```
> ℹ️ **Info:**
> For full control over which model applies where — plus UI customization, category scoping, and re-prompting — see Policy Packs.
# Policy Packs
URL: https://c15t.com/docs/frameworks/react/concepts/policy-packs
How c15t resolves regional consent policies and what a policy pack controls.
Different countries need different consent experiences. Policy packs let you define those rules once — c15t picks the right one automatically based on where the visitor is.
A policy pack is an ordered array of policies. Each policy targets a region or country and controls the consent model, which categories are in scope, what UI is shown, and how consent is recorded.
There are three ways to configure policy packs:
1. **inth.com (recommended)** — use [inth.com](https://inth.com) as your hosted backend. Configure packs visually in the dashboard or via API — no code changes required. Works with any frontend, including static sites.
2. **Self-hosted backend** — define packs in code via `policyPacks` and resolve them from real request geo data. Full control over policy logic and storage.
3. **Offline fallback** — pass the same policy shapes to the frontend via `offlinePolicy.policyPacks`. Use this mainly for local development, demos, deterministic testing, or resilience when the backend is temporarily unreachable. If you omit `offlinePolicy.policyPacks`, c15t falls back to a synthetic worldwide opt-in banner instead of no-banner mode.
In both hosted and self-hosted modes, the **backend is always the source of truth**. Offline packs are a preview or fallback layer and never override a live backend decision.
## Quickstart
The fastest way to get started is with the built-in presets:
```ts
import { policyPackPresets } from 'c15t';
const policies = [
policyPackPresets.europeOptIn(), // GDPR opt-in banner
policyPackPresets.californiaOptOut(), // CCPA opt-out banner
policyPackPresets.worldNoBanner(), // No banner elsewhere
];
```
|Preset|Model|UI|Matches|
|--|--|--|--|
|`europeOptIn()`|`opt-in`|banner|EEA + UK countries + geo fallback|
|`europeIab()`|`iab`|banner|EEA + UK countries + geo fallback (TCF 2.3)|
|`californiaOptOut()`|`opt-out`|none|US-CA region|
|`quebecOptIn()`|`opt-in`|banner|CA-QC region|
|`worldNoBanner()`|`none`|none|default fallback|
Most apps only need these presets — pick the ones that match your regions, pass them to your backend config or provider, and you're done. Customize individual fields or write fully custom policies when you need more control.
For banner/dialog actions, policy packs can also control grouped button arrangement:
```ts
ui: {
mode: 'banner',
banner: {
allowedActions: ['reject', 'accept', 'customize'],
layout: [['reject', 'accept'], 'customize'],
direction: 'row',
primaryActions: ['accept', 'customize'],
},
}
```
That expresses arrangement only. Button appearance like `stroke`, `filled`, or `ghost` lives in the UI theme.
## What Users See
Each policy combination produces a different consent experience:
|Policy Config|User Experience|
|--|--|
|`model: 'opt-in'`, `ui.mode: 'banner'`|Banner appears, nothing loads until the user consents|
|`model: 'opt-out'`, `ui.mode: 'none'`|No banner, everything loads immediately — user opts out via a "Do Not Sell" link|
|`model: 'none'`, `ui.mode: 'none'`|No banner, all categories auto-granted silently|
|`model: 'opt-in'`, `ui.mode: 'dialog'`|Full-screen dialog, nothing loads until the user consents|
|`model: 'iab'`, `ui.mode: 'banner'`|IAB TCF 2.3 banner with vendor-level controls|
## How Policy Resolution Works
When a visitor arrives, c15t walks the policy pack in priority order:
1. **Match by region** — checks for a policy targeting the specific region (e.g., US-CA, CA-QC)
2. **Match by country** — if no region match, checks for a country-level policy (e.g., US, DE)
3. **Fallback (geo failure)** — if geo-location failed (no country detected), uses the policy marked with `match.fallback`
4. **Fall back to default** — if nothing matches, uses the policy marked as the default
5. **No match, no default** — resolves to no-banner mode (silent, no consent UI)
Within the same matcher type, the first policy in the array wins. Pack order matters when two policies target the same country or region.
The **fallback** step is distinct from **default**: `isDefault` is a catch-all for known locations that don't match any specific policy ("rest of world"), while `fallback` is a safety net for unknown locations when geo-headers are missing ("assume strictest"). The `europeOptIn()` and `europeIab()` presets include `fallback: true` by default so EU-level consent applies when geo fails.
> ⚠️ **Warning:**
> Only one default and one fallback policy are allowed. Use inspectPolicies() to surface overlapping matchers and other warnings before deployment.
Inspect the resolved policy at runtime with `useConsentManager()`:
```tsx
import { useConsentManager } from '@c15t/react';
function PolicyDebug() {
const { locationInfo, model, policy, policyDecision } = useConsentManager();
return (
);
}
```
## Common Patterns
**The 80% case** — strict in Europe, light in California, silent everywhere else:
```ts
const policies = [
{
id: 'eu',
match: { countries: ['DE', 'FR', 'IT'] },
consent: { model: 'opt-in', categories: ['necessary', 'measurement', 'marketing'] },
ui: { mode: 'banner' },
},
{
id: 'ca',
match: { regions: [{ country: 'US', region: 'CA' }] },
consent: { model: 'opt-out', gpc: true },
ui: { mode: 'none' },
},
{
id: 'default',
match: { isDefault: true },
consent: { model: 'none' },
ui: { mode: 'none' },
},
];
```
**Region overrides country** — stricter rules for California than the rest of the US:
```ts
const policies = [
{
id: 'us_ca',
match: { regions: [{ country: 'US', region: 'CA' }] },
consent: { model: 'opt-in', scopeMode: 'strict' },
ui: { mode: 'banner' },
},
{
id: 'us',
match: { countries: ['US'] },
consent: { model: 'opt-out' },
ui: { mode: 'banner' },
},
];
// US-CA → us_ca (region match wins)
// US-NY → us (country match)
```
**Different wording per region** — use `i18n.messageProfile` to vary copy without changing the consent model:
```ts
const c15t = c15tInstance({
i18n: {
defaultProfile: 'default',
messages: {
default: {
translations: {
en: { cookieBanner: { title: 'Privacy choices' } },
es: { cookieBanner: { title: 'Tus opciones de privacidad' } },
},
},
eu: {
fallbackLanguage: 'en',
translations: {
en: { cookieBanner: { title: 'EU GDPR Consent' } },
fr: { cookieBanner: { title: 'Consentement RGPD' } },
de: { cookieBanner: { title: 'GDPR-Einwilligung' } },
},
},
},
},
policyPacks: [
{
id: 'eu',
match: { countries: ['DE', 'FR', 'IT'] },
i18n: { messageProfile: 'eu' },
consent: { model: 'opt-in' },
ui: { mode: 'banner' },
},
],
});
```
In that setup, the `eu` policy uses only the `eu` language set. So Europe can
resolve to `en`, `fr`, or `de`, but not to `es` or any other locale defined
only in `default`. If the browser asks for an unsupported locale, c15t falls
back to the `eu` profile's `fallbackLanguage`.
## Re-Prompting on Policy Change
When you change a policy in a way that affects consent semantics — like adding a category, changing the consent model, or modifying allowed actions — c15t automatically re-prompts returning users.
This works through the **material policy fingerprint**: a hash of only the consent-affecting fields (model, categories, scope, allowed actions, grouped action layout, direction, proof settings). Presentation-only changes like copy, button styling, or scroll lock do not trigger re-prompts.
|Change|Re-prompts?|
|--|--|
|Add a consent category|Yes|
|Change `model` from `opt-out` to `opt-in`|Yes|
|Remove an `allowedAction`|Yes|
|Change `uiProfile` or button styling|No|
|Update translation copy|No|
|Change `scrollLock`|No|
## Design Guidelines
* **Start from presets.** Use `policyPackPresets` to get running, then customize for your needs.
* **Keep packs small.** A handful of regional policies is better than dozens of tiny fragments.
* **Think risk, not geography.** Geography is just a matcher — the real question is what consent behavior each region needs.
* **Always include a default.** Unless "no banner for unmatched traffic" is intentional.
* **Set a fallback for geo failures.** Mark your strictest policy with `match.fallback=true` so users in unknown locations still see a consent banner. The `europeOptIn()` and `europeIab()` presets do this automatically.
* **Keep policy IDs stable.** They appear in debugging output, snapshots, and audit records.
* **Use `inspectPolicies()` before deploying.** It catches overlapping matchers, missing defaults, and IAB misconfigurations.
> ℹ️ **Info:**
> For provider setup, see the React policy pack guide. For backend configuration, see the self-host guide.
# Consent Categories
URL: https://c15t.com/docs/frameworks/react/concepts/consent-categories
How c15t organizes tracking technologies into five consent categories.
c15t organizes tracking technologies into five consent categories that align with GDPR and ePrivacy Directive requirements. Rather than asking users to approve or deny individual cookies or scripts, each category groups related tracking purposes together so users can make meaningful, informed choices about how their data is used.
> ℹ️ **Info:**
> Why categories, not cookie lists? Many consent banners list individual cookie names like \_ga, \_gid, or \_fbp. This is counterproductive:Technical names are meaningless to users — nobody knows what \_gid does by reading its name.Information overload drives "accept all" — a wall of cookie names pushes users toward dismissing the banner as fast as possible, which is the opposite of informed consent.Purpose is what matters — privacy regulations (GDPR, ePrivacy) require clear information about the purposes of data processing, not a cookie-by-cookie inventory.Cookie lists go stale — third-party scripts change their cookie names across versions, creating a maintenance burden that provides no real transparency.c15t's category-based approach — "measurement", "marketing", "experience" — communicates purpose directly. Users understand why data is collected, not how it is stored.
Configure which categories your app supports in the provider:
```tsx
import { type ReactNode } from 'react';
import { ConsentManagerProvider } from '@c15t/react';
export function ConsentManager({ children }: { children: ReactNode }) {
return (
{children}
);
}
```
## The Five Categories
|Category|Default|Toggleable|Description|
|--|--|--|--|
|`necessary`|`true`|No|Strictly necessary to operate or deliver the service|
|`functionality`|`false`|Yes|Basic interactions and functionalities|
|`experience`|`false`|Yes|Improve quality of user experience|
|`measurement`|`false`|Yes|Measure traffic and analyze behavior|
|`marketing`|`false`|Yes|Deliver personalized ads or marketing content|
The `necessary` category has `disabled: true` set internally, which prevents the user from toggling it off in the consent UI. All other categories can be freely toggled by the user.
Note that all categories except `necessary` have `display: false` by default. A category appears in the consent UI only if you include it in `consentCategories`. Categories not listed are hidden from the UI, but they still exist in consent state and may be affected by model-level behavior (for example, auto-grant in `opt-out` or `null` model flows).
Check if a specific category has consent using the `has()` method:
```tsx
import { useConsentManager } from '@c15t/react';
function AnalyticsLoader() {
const { has } = useConsentManager();
if (has('measurement')) {
// Safe to load analytics scripts
}
return null;
}
```
## Configuring Categories
The `consentCategories` array controls which consent categories are presented to the user in the consent UI. Only categories you list in this array will appear as toggleable options in the consent banner or modal.
The `necessary` category is always implicitly included even if you do not add it to the array. You never need to worry about accidentally omitting it -- c15t ensures it is always present and always enabled.
For example, if you set:
```
consentCategories: ['necessary', 'measurement', 'marketing']
```
then only those three categories will show toggles in the consent UI. The `functionality` and `experience` categories will not appear as user-configurable toggles.
In `opt-in`/`iab` flows, hidden categories usually remain `false` unless you explicitly set them. In `opt-out`/`null` flows, categories may be auto-granted even when hidden.
This gives you precise control over which consent choices to present to your users. A simple blog that only runs an analytics script might only need `measurement`. A media site with ad integrations would include `marketing`. A SaaS application with personalization features might add `experience` and `functionality` as well. You choose what is relevant to your site and c15t handles the rest - storing consent state, exposing it through hooks, and ensuring the right categories are active based on the user's choices.
You can dynamically update which categories are active:
```tsx
import { useConsentManager } from '@c15t/react';
function CategoryManager() {
const { consentCategories, setConsentCategories } = useConsentManager();
const addExperienceCategory = () => {
setConsentCategories([...consentCategories, 'experience']);
};
return (
);
}
```
# Cookie Management
URL: https://c15t.com/docs/frameworks/react/concepts/cookie-management
How c15t manages cookies through script, iframe, and network gating
Cookie management is the most commonly misunderstood part of consent. A critical distinction: **c15t does not manage all cookies on your site.** It controls what scripts, iframes, and network requests are allowed to load - and those third-party resources are what set most cookies.
Understanding this distinction is key to building a compliant consent flow: c15t gates the sources of cookies, not the cookies themselves.
## What Actually Sets Cookies
There are four sources of cookies on a typical website:
**1. c15t itself**
c15t stores the user's consent state in a `c15t` cookie (and mirrors it to localStorage). This cookie records which categories the user consented to, when they consented, and their subject ID. This is a strictly necessary cookie - it exists so the site remembers the user's consent choice.
**2. Third-party scripts**
When you load a tracking script (Google Analytics, Meta Pixel, etc.), that script sets its own cookies. Google Analytics creates `_ga` and `_gid` cookies. Meta creates `_fbp` and `_fbc`. These cookies are set by the script's code running in the browser - c15t prevents them by not loading the script until the user consents.
**3. Embedded iframes**
YouTube embeds, social media widgets, and other iframes can set cookies via their embedded content. c15t's iframe blocker replaces iframes with placeholders until consent is granted, preventing these cookies from being set.
**4. Network requests**
Server responses can include `Set-Cookie` headers. If your page makes requests to third-party APIs or CDNs, those responses may set cookies. c15t's network blocker can intercept `fetch` and `XMLHttpRequest` calls to prevent these requests from happening without consent.
> ⚠️ **Warning:**
> Don't list these cookies in your banner. The cookie names above (\_ga, \_gid, \_fbp, \_fbc) are implementation details — they matter for developers understanding how tracking works, but they should not be exposed to end users in your consent UI. Users don't know what \_ga means, and listing it doesn't help them make an informed choice. Instead, use purpose-based consent categories like "measurement" or "marketing" that communicate why data is collected, not how it is stored.
## Why Revoking Consent Requires a Page Reload
When a user revokes consent for a category (e.g., turns off "measurement" after previously granting it), c15t reloads the page by default. This is not a limitation - it's the only reliable approach.
**Why you can't just delete third-party cookies from JavaScript:**
* **`httpOnly` cookies** - Many tracking cookies are set with the `httpOnly` flag, which prevents JavaScript from reading or deleting them. Only the server that set them can remove them.
* **Domain restrictions** - Cookies set on `.google.com` or `.facebook.com` can only be deleted by those domains. Your JavaScript running on `yourdomain.com` has no access.
* **Alternative storage** - Some scripts also write to `localStorage`, `sessionStorage`, `IndexedDB`, or even Web Workers. Cleaning up all possible storage locations is impractical.
* **In-memory state** - A loaded script has already executed. Its event listeners, timers, and in-memory data persist until the page unloads. You can't "unrun" JavaScript.
**The reliable solution: don't load the scripts in the first place.** A page reload creates a fresh execution context. On the fresh page, c15t reads the updated consent state and simply never loads the scripts that lost consent. No script means no cookies, no tracking, no in-memory state.
**When reload does NOT happen:**
* When a user is declining consent for the **first time** (no prior consent existed, so no scripts were loaded to clean up)
* When `reloadOnConsentRevoked` is set to `false`
* When the user is only **adding** consent (no revocations)
Configure reload behavior in the provider:
```tsx
import { type ReactNode } from 'react';
import { ConsentManagerProvider } from '@c15t/react';
function ConsentManager({ children }: { children: ReactNode }) {
return (
{
// Run cleanup before the page reloads
// e.g., flush pending analytics events
console.log('Reloading due to consent revocation:', preferences);
},
},
}}
>
{children}
);
}
```
> ℹ️ **Info:**
> The reload and deferred sync are part of the broader initialization flow. See Initialization Flow for the full sequence.
>
> ⚠️ **Warning:**
> Setting reloadOnConsentRevoked: false means previously-loaded scripts will continue running after consent is revoked. Only disable this if you have a specific strategy for handling script cleanup.
## The Revocation Flow
When a user revokes consent, the following sequence occurs:
**Simplified**
1. **User revokes consent** — e.g. turns off "measurement" in the consent dialog
2. **New consent saved** — updated preferences are written to cookies and localStorage
3. **Pending sync stored** — the API update is deferred to localStorage (`c15t:pending-consent-sync`)
4. **Page reloads** — a fresh execution context ensures revoked scripts never load
5. **Fresh init** — c15t reads updated consent; scripts without consent are never loaded
6. **Deferred API sync** — the pending consent change is sent to the backend and cleared from localStorage
**Sequence Diagram**
```mermaid
sequenceDiagram
participant User
participant UI as Consent UI
participant Store as Consent Store
participant Storage as Cookie + localStorage
participant API as c15t Backend
participant Browser
User->>UI: Revokes "measurement" consent
UI->>Store: saveConsents({ type: 'custom' })
Store->>Store: shouldReloadOnConsentChange() → true
Store->>Storage: Save new consent state
Store->>Storage: Store PendingConsentSync in localStorage
Store->>Browser: onBeforeConsentRevocationReload callback
Store->>Browser: window.location.reload()
Browser->>Browser: Fresh page load
Browser->>Storage: Read consent state
Browser->>Store: Initialize with updated consents
Note over Store: Scripts without consent are never loaded
Store->>Storage: Read PendingConsentSync
Store->>API: Sync consent to backend
Store->>Storage: Clear PendingConsentSync
```
**Key detail:** The API sync happens *after* the reload, not before. This ensures the page reloads as fast as possible. The pending sync data is stored in localStorage under the key `c15t:pending-consent-sync` and is picked up by the fresh page's initialization.
# Glossary
URL: https://c15t.com/docs/frameworks/react/concepts/glossary
Key terms used throughout the c15t documentation.
### Core Terms
|Term|Definition|
|--|--|
|`subjectId`|Client-generated device/browser identifier (`sub_xxx`). Stored in the `c15t` cookie. Created on first consent save.|
|`externalId`|Your authenticated user's ID (from Clerk, Auth0, etc.), linked via `identifyUser()`. Connects a device to a user account.|
|`consents`|The **saved** consent state — `Record` mapping categories to granted/denied. Used for gating scripts, iframes, and network requests.|
|`selectedConsents`|**Unsaved** toggle state — what the user has toggled in the dialog but hasn't submitted yet. Becomes `consents` after save.|
|`mode`|Client operating mode: `'hosted'` (full backend), `'offline'` (local only), or `'custom'` (bring your own handlers). Legacy alias: `'c15t'`. Set once in provider config. See [Client Modes](/docs/frameworks/react/concepts/client-modes).|
|`model`|Consent regulatory model derived from jurisdiction: `'opt-in'`, `'opt-out'`, `'iab'`, or `null`. See [Consent Models](/docs/frameworks/react/concepts/consent-models).|
### Regulatory Terms
|Term|Definition|
|--|--|
|`jurisdiction`|A privacy regulation code (e.g., `GDPR`, `CCPA`, `PIPEDA`, `QC_LAW25`) detected from the user's geolocation. Maps to a consent model. See [Consent Models](/docs/frameworks/react/concepts/consent-models) for the full mapping table.|
|GPC|Global Privacy Control — a browser signal (`Sec-GPC: 1`) indicating the user opts out of data sale/sharing. Honored when a policy sets `consent.gpc: true` (enabled by default in California presets).|
|TCF|IAB Transparency and Consent Framework (v2.3) — a standard for programmatic advertising consent in GDPR jurisdictions. See [IAB TCF](/docs/frameworks/react/iab/overview).|
|GVL|Global Vendor List — an IAB-maintained registry of ad-tech vendors and their declared purposes, used by the TCF consent flow.|
# Script Loader
URL: https://c15t.com/docs/frameworks/react/script-loader
Gate third-party scripts behind consent in React — load Google Analytics, Meta Pixel, and other tracking scripts only when users grant permission.
The script loader manages third-party JavaScript based on consent state. You declare scripts in your provider's `scripts` option, and c15t decides when each script should load, stay loaded, unload, or receive a consent update.
Use it for analytics, pixels, tag managers, product analytics, and other vendor snippets that should not run until the right consent condition is satisfied. Prebuilt helpers live in [`@c15t/scripts`](/docs/integrations/overview); custom scripts can be declared directly when the vendor is specific to your app.
> ℹ️ **Info:**
> Start with the integrations overview before writing your own script. Built-in helpers encode vendor boot order, consent updates, and common defaults so you do not have to.
>
> 📝 **Note:**
> If you need a vendor c15t does not ship yet, see the custom integration guide. It explains when a one-off Script is enough and when to build a reusable manifest-backed helper.
>
> ℹ️ **Info:**
> The script loader handles JavaScript tags and callback lifecycles. For iframe-only embeds, use the iframe blocking pattern. For UI components such as maps or video players, combine consent state with a component-level placeholder or a dedicated renderable integration.
## Basic Usage
Pass an array of scripts to `ConsentManagerProvider`. Built-in helpers from `@c15t/scripts` return plain `Script` objects, so they sit beside app-specific scripts:
```tsx
import { type ReactNode } from 'react';
import { ConsentManagerProvider } from '@c15t/react';
import { metaPixel } from '@c15t/scripts/meta-pixel';
export function ConsentManager({ children }: { children: ReactNode }) {
return (
{children}
);
}
```
The provider registers those scripts when the consent runtime starts. From that point on, c15t owns the lifecycle: it checks consent, injects eligible scripts, unloads them when consent is revoked, and runs `onConsentChange` for scripts that stay loaded.
## Recommended Structure
Define your script list once and keep it next to the consent provider so vendor setup stays declarative:
```tsx
import { type ReactNode } from 'react';
import { ConsentManagerProvider } from '@c15t/react';
import { gtag } from '@c15t/scripts/google-tag';
import { metaPixel } from '@c15t/scripts/meta-pixel';
const scripts = [
gtag({ id: 'G-XXXXXXX' }),
metaPixel({ pixelId: '123456' }),
];
export function ConsentProvider({ children }: { children: ReactNode }) {
return (
{children}
);
}
```
If an integration is route-specific or tenant-specific, use [dynamic script management](#dynamic-script-management) instead of conditionally building this list per render.
## Mental Model
Every script you register has the same lifecycle. c15t evaluates each script against the current consent state, then drives it through a small number of states:
1. **Pending** — registered but waiting for consent. Nothing is in the DOM yet.
2. **Loaded** — consent matched, c15t injected the script (or ran callbacks for callback-only scripts).
3. **Updated** — already loaded, consent state changed, `onConsentChange` ran so the SDK can react.
4. **Unloaded** — consent was revoked. c15t removed the script element unless you opted into persistence.
Four lifecycle callbacks let you hook into transitions: `onBeforeLoad`, `onLoad`, `onConsentChange`, and `onError`. Two flags — [`alwaysLoad`](#always-load) and [`persistAfterConsentRevoked`](#persist-after-revocation) — change how c15t treats consent boundaries. Everything else (DOM placement, ad-block evasion, dynamic management) is a refinement on top of this core model.
## Choose the Right Approach
Most projects mix more than one style. Pick the smallest one that keeps consent behavior obvious:
|Style|Use when|
|--|--|
|**Built-in helper** from `@c15t/scripts`|c15t already ships the vendor. See the [integrations overview](/docs/integrations/overview).|
|**Plain `Script`**|One-off app code with simple load and callback behavior.|
|**Callback-only `Script`**|Another package already loaded the SDK; c15t only synchronizes consent.|
|**Manifest-backed helper**|Reusable vendor integration with structured setup phases, queues, stubs, or a vendor consent API.|
|**Iframe / renderable integration**|Vendor exposes an iframe or React component, not just a `