c15t
Next.jsReactJavaScript
All frameworks

Tag managers

Google Tag Manager

Measurement

Google TagDatabuddyMixpanelPostHogAhrefs AnalyticsAdobe AnalyticsAmplitudeCloudflare Web AnalyticsMicrosoft ClarityFathom AnalyticsHeapMatomo AnalyticsOOneDollarStatsHotjarHightouchLogRocketPlausible AnalyticsPromptwatchPirschRudderStackSegmentRybbit AnalyticsUmami AnalyticsVercel Analytics

Marketing

Microsoft UETClearbitMeta PixelPPinterest TagReddit PixelTikTok PixelLinkedIn Insight TagSnapchat PixelX PixelYouTube

Functionality

CrispFFront ChatIntercomGoogle Maps
All integrations
Changelog
GitHub1.9kDeploy on Inth
Deploy on Inth
Quickstart
Optimization
AI Agents
Concepts
Initialization Flow
Client Modes
Consent Models
Policy Packs
Consent Categories
Cookie Management
Glossary
Guides
Script Loader
Iframe Blocking
Network Blocker
Callbacks
Internationalization
Policy Packs
Store API
Store API Overview
Checking Consent
Setting Consent
Location & Identity
Building Framework Libraries
Building UI
Troubleshooting
IAB TCF
IAB TCF
IAB TCF 2.4

Store API

Store API Overview

Entry Points

getOrCreateConsentRuntime(options)

The recommended entry point. Creates both a consent client and a Zustand vanilla store in one call, with built-in caching — calling it again with the same options returns the same instance.

import { getOrCreateConsentRuntime } from 'c15t';

const { consentManager, consentStore, cacheKey } = getOrCreateConsentRuntime({
  mode: 'hosted',
  backendURL: 'https://your-instance.c15t.dev',
  consentCategories: ['necessary', 'measurement', 'marketing'],
  scripts: [
    { id: 'analytics', src: 'https://cdn.example.com/analytics.js', category: 'measurement' },
  ],
  callbacks: {
    onConsentChanged: ({ allowedCategories, deniedCategories }) => {
      console.log('Allowed:', allowedCategories);
      console.log('Denied:', deniedCategories);
    },
  },
  debug: true,
});

Returns: { consentManager, consentStore, cacheKey }

  • consentManager — The low-level client instance
  • consentStore — Zustand vanilla store with all state and actions
  • cacheKey — Cache key for this runtime instance

configureConsentManager(options)

Lower-level API that creates only the client (no store). Use this when you need full control over store creation.

import { configureConsentManager, createConsentManagerStore } from 'c15t';

const manager = configureConsentManager({
  mode: 'hosted',
  backendURL: 'https://your-instance.c15t.dev',
});

const store = createConsentManagerStore(manager, {
  initialConsentCategories: ['necessary', 'measurement'],
  scripts: [{ id: 'analytics', src: '...', category: 'measurement' }],
  callbacks: {
    onConsentChanged: ({ allowedCategories }) => console.log(allowedCategories),
  },
});

createConsentManagerStore(manager, options)

Creates a Zustand vanilla store from a client instance. Accepts all store configuration options.

import { createConsentManagerStore } from 'c15t';

const store = createConsentManagerStore(manager, {
  initialConsentCategories: ['necessary', 'measurement', 'marketing'],
  debug: true,
  reloadOnConsentRevoked: true,
});

Legal Links

Configure legal policy URLs in store options via legalLinks:

const { consentStore } = getOrCreateConsentRuntime({
  mode: 'offline',
  legalLinks: {
    privacyPolicy: {
      href: '/privacy',
      target: '_self',
    },
    cookiePolicy: {
      href: '/cookies',
      target: '_self',
    },
    termsOfService: {
      href: 'https://example.com/terms',
      target: '_blank',
      rel: 'noopener noreferrer',
      label: 'Terms of Service',
    },
  },
});

Notes:

  • Omitting a key (for example termsOfService) hides that link.
  • label overrides the translated text for that single link.
  • Use _self for internal pages and _blank + rel="noopener noreferrer" for external pages.
  • The c15t package is headless; these links are used by your UI layer (custom UI or @c15t/ui-based integrations).

Overrides

Set initial overrides to force location/language signals during runtime initialization:

const { consentStore } = getOrCreateConsentRuntime({
  mode: 'offline',
  overrides: {
    country: 'DE',
    region: 'BY',
    language: 'de-DE',
  },
});

You can also force Global Privacy Control behavior for testing:

const { consentStore } = getOrCreateConsentRuntime({
  mode: 'offline',
  overrides: {
    gpc: true,
  },
});

For runtime updates after initialization, call setOverrides().

Warning

Treat overrides as an environment/testing tool. Avoid hard-coding production overrides unless that behavior is intentional for your deployment.

Store Patterns

Reading State

const state = consentStore.getState();

// Consent state
state.consents          // { necessary: true, measurement: false, ... }
state.has('measurement') // false
state.hasConsented()     // false (no consent given yet)
state.model              // 'opt-in' | 'opt-out' | 'iab' | null

// UI state
state.activeUI           // 'banner' | 'dialog' | 'none'
state.consentTypes       // [{ name: 'necessary', ... }, ...]

// Location and info
state.locationInfo       // { countryCode: 'DE', regionCode: 'BY' }
state.hasFetchedBanner   // true (init complete)

Subscribing to Changes

Use subscribe() for UI state and other broad store updates:

// Subscribe to all state changes
const unsubscribe = consentStore.subscribe((state, prevState) => {
  console.log('State changed:', state);
});

// React to specific changes by comparing with previous state
consentStore.subscribe((state, prevState) => {
  if (state.activeUI !== prevState.activeUI) {
    console.log('Visible UI changed:', state.activeUI);
  }
});

// Unsubscribe when done
unsubscribe();

Use subscribeToConsentChanges() when you only want real saved preference changes:

const unsubscribeConsentChanges = consentStore
  .getState()
  .subscribeToConsentChanges(({ allowedCategories, deniedCategories }) => {
    analytics.syncConsent({ allowedCategories, deniedCategories });
  });

unsubscribeConsentChanges();

Info

Prefer subscribeToConsentChanges() or onConsentChanged for analytics SDKs and consent-mode integrations. Raw consentStore.subscribe() fires for every store update, including UI-only changes.

Window Namespace

The store is also exposed on the window object for debugging and direct access:

// Access from anywhere (e.g., browser console)
const state = window.c15tStore?.getState();
console.log(state?.consents);

The namespace defaults to c15tStore and can be configured via the namespace store option.

Options Reference

Warning: ExtractedTypeTable: Could not extract "ConsentRuntimeOptions" from "./packages/core/src/runtime/index.ts" using base path "/vercel/path0/apps/c15t-docs/.leadtype/c15t". Verify the path/name and that the file is included by your tsconfig.

Loading…
Previous: Policy Packs
Checking Consent
Next

On this page

  1. 01Entry Points
  2. getOrCreateConsentRuntime(options)
  3. configureConsentManager(options)
  4. createConsentManagerStore(manager, options)
  5. 02Legal Links
  6. 03Overrides
  7. 04Store Patterns
  8. Reading State
  9. Subscribing to Changes
  10. Window Namespace
  11. 05Options Reference

Hosted

Deploy c15t on Inth

Inth is designed to scale c15t and accelerate your privacy compliance.

Sign up
c15t logo

c15t gives your app a cookie banner, a preferences dialog and consent rules for scripts, as code you own. Hosted on Inth or self-hosted.

Frameworks

  • Next.js
  • React
  • JavaScript

Compare

  • OneTrust
  • Cookiebot
  • Usercentrics
  • Didomi
  • iubenda
  • Osano
  • All comparisons

Integrations

  • Google Tag Manager
  • Google Tag
  • Meta Pixel
  • PostHog
  • Segment
  • Microsoft Clarity
  • All integrations

Resources

  • Self-hosting
  • Changelog
  • Stats
  • About c15t
  • Contact

© 2026 Inth. All rights reserved.

  • c15t Privacy Resources
  • Privacy Policy
  • Terms and Conditions
Property
Types

No properties found matching your criteria.