JavaScript API
@c15t/browser API
Entry points
| Import | What it gives you |
|---|---|
@c15t/browser | init, createConsentClient and mountConsentUI, with the stock banner, dialog and trigger. mode is required: a factory from manifest(), hosted(), offline() or custom(). |
@c15t/browser/hosted | The stock UI and client for hosted mode only. Requires a backend URL or a hosted transport factory. |
@c15t/browser/offline | The stock UI and client for offline mode only, with bundled policy rules and presets. |
@c15t/browser/headless | The same client with no UI and no CSS. mountUI() throws. |
@c15t/browser/iab | The client with the IAB TCF CMP and the IAB banner and dialog. See IAB TCF. |
@c15t/browser/devtools | mountDevTools(client, options). See DevTools. |
@c15t/browser/styles.css, @c15t/browser/iab/styles.css | The stylesheets, for ui: { shadow: false, styles: false }. |
Install it with:
In the ES module build the preference dialog code is a separate chunk. It starts loading in idle time once the banner or trigger is on screen, and at the latest when the dialog opens. Idle preloading can download it even when the visitor never opens preferences.
The script-tag files c15t.js, c15t.offline.js and c15t.iab.js each carry
their complete stylesheet in one file. The default c15t.js uses the hosted
client and requires a backend URL or hosted factory. c15t.offline.js uses
the offline client. For manifest or custom mode with the stock UI, use the
ES module root @c15t/browser, which takes any mode factory.
@c15t/browser is not part of the c15t package. Use one entry per page.
Each creates its own client, and two clients on one page would each run the
script loader and blockers.
Choose a bundle for one mode
Use @c15t/browser/hosted when Inth or a self-hosted backend supplies the
policy. It excludes offline policy presets, offline resolution and manifest
transport code. Hosted mode already resolves the visitor's policy on the
server through /init; this entry removes unused client code without
changing that request.
Use @c15t/browser/offline when the browser resolves bundled rules. It
excludes hosted and manifest transport code. The default offline transport
keeps choices in the browser's consent cookie and localStorage, with no
consent backend requests or server records. Not recommended for production
environments.
Both entries keep the banner, preference dialog, page hooks, script gating,
blockers, callbacks and persistence. Their init() and
createConsentClient() methods have the same lifecycle as the general entry.
| Entry | Accepted configuration | Configuration that throws |
|---|---|---|
@c15t/browser/hosted | backendURL, optional mode: 'hosted', or a factory from hosted(). policyRules accepts authored PolicyRule objects. | Missing backend URL without a hosted factory; a different mode; manifest or manifestURL; preset-name strings in policyRules. |
@c15t/browser/offline | Optional mode: 'offline' or a factory from offline(). policyRules accepts authored rules and preset names, or defaults to the recommended rules. | backendURL, manifest or manifestURL; a different mode. |
Use @c15t/browser for manifest or custom mode, or when an application
chooses its mode at runtime. Use @c15t/browser/iab for IAB TCF. The general
entry imports no transport itself, so a bundle keeps only the factory it
imports. It takes mode as a factory only: backendURL, manifest,
manifestURL, policyRules and mode names such as 'hosted' are options of
the /hosted and /offline entries and the script-tag builds.
Start the client
init(options) creates the client and starts it:
createConsentClient(options) creates the client without starting it.
Construction reads no storage, sends no request and touches no DOM, so a
module can create it at import time and call client.start() later:
start() reads stored choices, requests the policy, starts the script loader,
the iframe blocker and any network blocker, listens for page hooks and mounts
the UI. It mounts on DOMContentLoaded when <body> does not exist yet. A
second start() does nothing. Options
lists everything init and createConsentClient accept.
Read state
| Member | Returns | Use it for |
|---|---|---|
ready() | Promise<ConsentSnapshot> | Wait until the policy has resolved. For a returning visitor, hasConsented() is reliable after it. |
has(condition) | boolean | Whether a category, or a condition such as { or: ['measurement', 'marketing'] }, is allowed right now. |
hasConsented() | boolean | Whether the visitor has answered the choice prompt. |
getSnapshot() | ConsentSnapshot | The full state. See the snapshot reference. |
subscribe(listener) | () => void | Call listener with each new snapshot. Returns an unsubscribe function. |
on(event, listener) | () => void | Listen for ready, consent, ui or error. |
consentCategories | AllConsentNames[] | The categories the dialog offers, in a fixed order: necessary, functionality, measurement, experience, marketing, limited to the policy's categories. The order of the consentCategories option doesn't change it. |
has() reads a permission, which says whether code may run now. Under an opt-out policy
it is true before the visitor does anything. hasConsented() and
getSnapshot().explicitChoice read the recorded choice, which says what the
visitor decided. Gate code on permissions; report on recorded choices.
How consent works
explains the difference.
Record a choice
Call these only from a visitor's click or key press.
| Method | Returns | What it records |
|---|---|---|
acceptAll() | Promise<SaveResult> | Without IAB, allows every category the dialog offers. Under an IAB policy it confirms the vendors' declared processing through the CMP. Optional categories without declared consent purposes remain denied. See categories under an IAB policy. |
rejectAll() | Promise<SaveResult> | Denies every optional category the dialog offers. |
save(consents) | Promise<SaveResult> | The categories you name, such as { measurement: true }. Categories the dialog does not offer are dropped. Under an IAB policy it resolves { ok: false } and emits error; use saveIAB(). |
saveIAB() | Promise<SaveResult> | The IAB purpose and vendor choices on runtime.iab. IAB entry only. |
dismissNotice() | Promise<NoticeDismissResult> | Acknowledges a notice. Grants nothing. { ok: false, reason: 'not-required' } when no notice is due. |
identify(user) | Promise<void> | Links the consent record to { externalId, identityProvider?, identityToken? }; the token verifies the link. Failures surface through error. |
Each save applies in the browser and closes the banner or dialog before the
backend request finishes. SaveResult.ok is false when the request failed;
the choice stays in effect and c15t retries the request later.
Control the UI
| Method | What it does |
|---|---|
showBanner(), openDialog(), closeDialog() | Change the surface c15t wants shown. Records nothing. |
setLanguage(code) | Sets the language and resolves the policy again, which fetches that language's copy from the backend. In offline mode the copy comes from the bundled translations and i18n.messages. See translations. |
setOverrides(overrides) | Merges into the country, region, language and GPC inputs to policy matching. A key you pass replaces its value, undefined clears it, and a key you leave out stays. |
mountUI(options?) | Removes the stock UI and mounts it again with new UI options. Throws in the headless entry. |
processIframes() | Pauses gated iframes that consent does not allow and restores the ones it allows. Needed only with iframeBlocker: { disableAutomaticBlocking: true }. See iframe blocker. |
ui | The mounted UI handle, with host, root, update() and destroy(), or null. |
Lifecycle and internals
| Member | What it is |
|---|---|
start() | Starts the client. init() calls it for you. |
started | Whether start() has run and the client is not disposed. |
dispose() | Removes the UI, page listeners, blockers and the scripts c15t added, then disposes the runtime. Code that already ran keeps running. |
options | The options the client was created with. |
mode | hosted, offline, manifest or custom. |
runtime | The consent runtime that owns the kernel and modules. runtime.iab is the CMP handle under IAB. |
kernel | The consent kernel: snapshot, commands and events. |
Do not attach a second script loader, network blocker or iframe blocker to
client.kernel. The client already runs one of each.
Events
on(event, listener) returns an unsubscribe function:
| Event | Payload | When it fires |
|---|---|---|
ready | the snapshot | The policy has resolved and the UI can render. For a returning visitor, hasConsented() is reliable from here. |
consent | the snapshot | Permissions, the recorded choice or the vendor switches changed. This includes a stored choice restored at start, a save, an expiry and a GPC change. |
ui | 'banner', 'dialog' or 'none' | The surface c15t wants shown changed. |
error | the error | A backend call failed, or an IAB step failed. |
A ready listener added after the policy resolved runs at once with the
snapshot from that moment. A ui listener added after that runs at once
with the current surface. consent and error listeners only hear later
changes.
Each event is also dispatched on document as c15t:ready, c15t:consent,
c15t:ui and c15t:error, with the payload in event.detail.
Callbacks compares events with the
callbacks option.
Page hooks
A started client also wires markup on the page, with no code:
| Markup | What it does |
|---|---|
<button data-c15t-action="…"> | Runs the action on click. Values below. |
A link whose href ends in #c15t-preferences | Opens the preference dialog. |
<script type="text/plain" data-c15t-category="…"> | Runs the script once that category is allowed, in page order. |
<iframe data-src="…" data-category="…"> | Sets src once that category is allowed. |
| Value | What a click does |
|---|---|
accept | Like the banner's accept button, allows every category the dialog offers without IAB. Under an IAB policy it confirms the vendors' declared processing through the CMP. Optional categories without declared consent purposes remain denied. See categories under an IAB policy. |
reject | Rejects every optional category the dialog offers. |
customize | Opens the preference dialog. Records nothing. |
dismiss | Dismisses a notice. This records an acknowledgement, not consent, and does nothing unless the policy shows a notice. |
banner | Shows the banner again. Records nothing. |
close | Closes the banner or dialog. Records nothing. |
Helper exports
The general @c15t/browser entry exports all the helpers below. The hosted
entry exports hosted; the offline entry exports offline and
resolveRules. Both include the page action constants, gated script
helpers, mountConsentUI and version.
| Export | What it does |
|---|---|
hosted, offline, manifest, custom | Transport factories for the mode option. See transports. |
manifestNeedsLocation(manifest) | Whether some location gets a different banner, or none, under this manifest, so a page knows it must supply a country to resolve it without /init. false when every country and region rule gives the same banner. |
resolveRules(rules) | Turns preset names such as 'europeOptIn' into policy rules. Throws on an unknown name. |
activateGatedScripts(snapshot, root?, options?) | Runs allowed text/plain scripts under root yourself, for a setup without a client. options.nonce runs only tags that carry that nonce. Returns how many ran. |
mountConsentUI(client, options?) | Mounts the stock UI for a client. mountUI() calls it. |
ACTION_ATTRIBUTE, PREFERENCES_HASH, CATEGORY_ATTRIBUTE, ACTIVATED_ATTRIBUTE | 'data-c15t-action', '#c15t-preferences', 'data-c15t-category' and 'data-c15t-activated'. |
version | The package version. |
The package also exports the ConsentClient, ConsentClientOptions,
ConsentUIOptions, ConsentBannerOptions, ConsentDialogOptions,
ConsentTriggerOptions, ConsentClientEventMap, ConsentSnapshot and
ConsentState types.
The hosted and offline entries export HostedConsentClientOptions and
OfflineConsentClientOptions, respectively. These types restrict connection
options to the entry's mode. Runtime validation also checks a supplied
transport factory's kind.
Check it works
- Start the app and run
await consent.ready()from code or a breakpoint. It resolves with a snapshot whoseresolution.statusismatched. - Click Reject All.
consent.hasConsented()istrueandconsent.has('measurement')isfalse. - Call
consent.openDialog(). The preference dialog opens with Analytics (themeasurementcategory) off.