UNPKG

c15t

Version:

Headless JavaScript consent management platform for cookie banners, privacy preferences, consent storage, and script gating.

164 lines (127 loc) 5.85 kB
--- title: Callbacks description: React to consent lifecycle events — initialization, consent changes, errors, and revocation reloads. group: frameworks --- Callbacks let you run custom code at key points in the consent lifecycle. Define them in the provider or runtime `callbacks` option, or register them dynamically after initialization. For analytics SDKs and other change-only integrations, prefer `subscribeToConsentChanges()` or `onConsentChanged`. Use `onConsentSet` when you want the broader lifecycle signal, including initialization, automatic defaults, and replay-aware registration. > ℹ️ **Info:** > consentStore.getState().subscribeToConsentChanges() is the recommended API for analytics SDKs and consent-mode integrations. It only emits future saves that actually changed persisted preferences. ## Configuration Define callbacks in the runtime options: ```ts import { getOrCreateConsentRuntime } from 'c15t'; const { consentStore } = getOrCreateConsentRuntime({ mode: 'hosted', backendURL: 'https://your-instance.c15t.dev', callbacks: { onBannerFetched: ({ jurisdiction, location, translations }) => { console.log('Jurisdiction:', jurisdiction); console.log('Country:', location.countryCode); console.log('Language:', translations.language); }, onConsentSet: ({ preferences }) => { console.log('Consent lifecycle event:', preferences); }, onConsentChanged: ({ allowedCategories, deniedCategories }) => { analytics.syncConsent({ allowedCategories, deniedCategories }); }, onError: ({ error }) => { errorReporter.captureMessage(error); }, onBeforeConsentRevocationReload: ({ preferences }) => { // Flush pending analytics before page reloads analytics.flush(); }, }, }); ``` ## Choose the Right Surface |Surface|Replays when registered late?|Fires on init / hydration / auto-grants?|Best for| |--|--|--|--| |`onBannerFetched`|Yes, via `setCallback('onBannerFetched', ...)` after init|Yes|Logging resolved policy, location, and translations| |`onConsentSet`|Yes, via `setCallback('onConsentSet', ...)`|Yes|Broad lifecycle hooks, debugging, and integrations that want the latest full state regardless of how it was reached| |`onConsentChanged`|No|No|Declarative change-only integrations| |`subscribeToConsentChanges()`|No|No|Canonical change-only subscriptions after mount| > ℹ️ **Info:** > Script.onConsentChange is a script-scoped lifecycle hook. It is not the global consent change API for analytics SDKs or other app-wide integrations. ## Available Callbacks ### `onBannerFetched` Called when the consent banner data is fetched from the backend (or loaded from SSR data). The payload includes jurisdiction info, location data, and resolved translations. ```tsx onBannerFetched: ({ jurisdiction, location, translations }) => { // jurisdiction: 'GDPR' | 'CCPA' | { code: 'GDPR', message: '...' } | ... // location: { countryCode: 'DE', regionCode: 'BY' } // translations: { language: 'de', translations: {...} } } ``` ### `onConsentSet` Called whenever c15t broadly settles consent state: store initialization, automatic defaults during init, explicit saves, and replay via `setCallback('onConsentSet', ...)`. ```tsx onConsentSet: ({ preferences }) => { // preferences: { necessary: true, measurement: true, marketing: false, ... } console.log('Latest consent state:', preferences); } ``` ### `onConsentChanged` Called only after an explicit `saveConsents()` or `setConsent()` that actually changes the saved consent state. It never fires on store creation, hydration, automatic grants, unchanged saves, or `setCallback('onConsentChanged', ...)`. ```tsx onConsentChanged: ({ preferences, previousPreferences, allowedCategories, deniedCategories, previousAllowedCategories, previousDeniedCategories, }) => { analytics.syncConsent({ allowedCategories, deniedCategories, previousAllowedCategories, previousDeniedCategories, }); } ``` ### `onError` Called when an error occurs during consent operations (e.g., API request failure). If no `onError` callback is provided, errors are logged to `console.error`. ```tsx onError: ({ error }) => { // error: string describing what went wrong Sentry.captureMessage(`Consent error: ${error}`); } ``` ### `onBeforeConsentRevocationReload` Called synchronously before the page reloads due to consent revocation. This is your last chance to run cleanup before the reload. Keep this callback fast - avoid async operations. ```tsx onBeforeConsentRevocationReload: ({ preferences }) => { // Flush any pending data navigator.sendBeacon('/api/flush', JSON.stringify({ session: sessionId })); } ``` ## Change-Only Subscriptions Use `subscribeToConsentChanges()` when you want a listener for real preference changes after runtime creation: ```ts const unsubscribe = consentStore .getState() .subscribeToConsentChanges(({ allowedCategories, deniedCategories }) => { analytics.syncConsent({ allowedCategories, deniedCategories }); }); // Later, when you're done listening: unsubscribe(); ``` ## Runtime Callback Registration Register or update callbacks at runtime using `setCallback()`: ```ts const state = consentStore.getState(); state.setCallback('onBannerFetched', ({ jurisdiction, location }) => { console.log('Resolved init data:', { jurisdiction, location }); }); state.setCallback('onConsentSet', ({ preferences }) => { console.log('Broad consent lifecycle event:', preferences); }); // Remove callbacks again when no longer needed state.setCallback('onBannerFetched', undefined); state.setCallback('onConsentSet', undefined); ``` `setCallback('onConsentSet', ...)` immediately replays the current consent state. For change-only logic, prefer `subscribeToConsentChanges()` or `onConsentChanged`.