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,
});

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().

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…