Use Consent Manager

useConsentManager

useConsentManager() is the primary hook for interacting with the consent system. It returns the complete consent store state and all action methods.

import { useConsentManager } from '@c15t/react';

function MyComponent() {
  const {
    consents,
    model,
    has,
    saveConsents,
    // ... all state and actions
  } = useConsentManager();
}

State Properties

Warning: ExtractedTypeTable: Could not extract "StoreRuntimeState" from "./packages/core/src/store/type.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…

Action Methods

Warning: ExtractedTypeTable: Could not extract "StoreActions" from "./packages/core/src/store/type.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…

User Identification

You can link a consent subject to your own internal user ID or a non-secret anonymous visitor ID. c15t stores the identifier in the subject row's externalId field. Consent records remain associated with that subject through subjectId, so your backend can find the subject and its related consent records by external ID for GDPR Article 15 exports.

1. Providing the Current User ID

When using Clerk, wait for Clerk to load and prefer its authenticated userId. Before sign-in, you can fall back to a non-secret visitor ID from your application:

import { useAuth } from '@clerk/react';
import { ConsentManagerProvider } from '@c15t/react';

function ConsentApp() {
  // Render this component beneath your existing ClerkProvider.
  const { isLoaded, isSignedIn, userId } = useAuth();

  if (!isLoaded) {
    return null;
  }

  const visitorId = getVisitorId();
  const consentUser = isSignedIn && userId
    ? { id: userId, identityProvider: 'clerk' }
    : visitorId
      ? { id: visitorId, identityProvider: 'anonymous-visitor' }
      : undefined;

  return (
    <ConsentManagerProvider
      options={{
        mode: 'hosted',
        backendURL: 'https://your-instance.c15t.dev',
        consentCategories: ['necessary', 'measurement', 'marketing'],
        user: consentUser,
      }}
    >
      <ClerkConsentSync />
      <MyComponents />
    </ConsentManagerProvider>
  );
}

2. Synchronizing Clerk Sign-ins

Use a component inside ConsentManagerProvider to update the current consent subject when Clerk's authentication state changes:

import { useAuth } from '@clerk/react';
import { useConsentManager } from '@c15t/react';
import { useEffect } from 'react';

function ClerkConsentSync() {
  const { isLoaded, isSignedIn, userId } = useAuth();
  const { identifyUser } = useConsentManager();

  useEffect(() => {
    if (!isLoaded || !isSignedIn || !userId) {
      return;
    }

    void identifyUser({
      id: userId,
      identityProvider: 'clerk',
    }).then(() => {
      clearVisitorId();
    });
  }, [identifyUser, isLoaded, isSignedIn, userId]);

  return null;
}

identifyUser() replaces the subject's current externalId; it does not retain the anonymous ID as an alias. Once a visitor is linked to Clerk, clear the previous visitor ID from the application state or storage used by getVisitorId() so it cannot replace the Clerk ID later.

Info

Backend subject identification requires hosted mode (mode: 'hosted'). In offline mode, identifyUser() cannot update a backend subject. Identifiers supplied through options.user can still be held in client state and persisted with locally stored consent, so do not place sensitive values there.

Key Types

ConsentState

A record mapping consent category names to their boolean values:

type ConsentState = Record<AllConsentNames, boolean>;
// Example: { necessary: true, measurement: true, marketing: false }

ConsentInfo

Metadata about when and how consent was recorded:

interface ConsentInfo {
  time: number;                    // Epoch timestamp when consent was recorded
  subjectId?: string;              // Client-generated subject ID (sub_xxx format)
  externalId?: string;             // External user ID linked via identifyUser()
  identityProvider?: string;       // Identity provider (e.g. 'clerk', 'auth0')
}

LocationInfo

Detected geographic location from the c15t backend:

interface LocationInfo {
  countryCode: string;     // ISO 3166-1 alpha-2 (e.g. 'DE')
  regionCode: string;      // Region/state code (e.g. 'BY')
  jurisdiction: string;    // Applicable jurisdiction (e.g. 'GDPR', 'CCPA')
}

Model

The active consent model:

type Model = 'opt-in' | 'opt-out' | 'iab' | null;
  • 'opt-in' — Explicit consent required before tracking (GDPR)
  • 'opt-out' — Tracking allowed by default, user can opt out (CCPA)
  • 'iab' — IAB TCF 2.3 compliance mode
  • null — No jurisdiction detected yet