Skip to main content

JavaScript API

Consent snapshot

Read a snapshot

kernel.getSnapshot(), consent.getSnapshot() from @c15t/browser, and every subscribe listener give you the same frozen object. It describes the visitor's permissions, what they recorded, the policy that applies and the surface to show.

A field keeps the same object when its value did not change, so compare with === to skip work:

let previous = kernel.getSnapshot();
kernel.subscribe((next) => {
	if (next.effectivePermissions !== previous.effectivePermissions) {
		updateGates(next.effectivePermissions);
	}
	previous = next;
});

updateGates stands for your own code.

May this run now?

FieldTypeWhat it holds
effectivePermissionsRecord<category, boolean>Whether each category is allowed now. Scripts, iframes and network rules follow this. Under an opt-out policy an optional category can be true before any choice.
restrictionsper category, a list of 'explicit-denial', 'strict-scope' or 'gpc'Why a category is denied.
privacySignals.gpc{ detected, override, active }The browser's Global Privacy Control signal, a test override, and the one c15t honors.
nextDeadlinenumber | nullThe next time, in epoch milliseconds, when a choice or notice expires and permissions or the prompt can change.

What did the visitor decide?

FieldTypeWhat it holds
explicitChoice{ version, categories } | nullThe visitor's recorded decision per category, each with value and confirmedAt. Only accept, reject and save write it. null when they never chose.
noticeDismissal{ dismissedAt, fingerprint } | nullWhen the visitor acknowledged the current notice. Not a grant.
vendorChoice{ denied, confirmedAt } | nullVendors the visitor turned off, outside IAB.
subject{ subjectId?, externalId?, identityProvider? } | nullThe consent subject the backend knows.

Read permissions to gate code and recorded choices to report decisions. How consent works explains why.

What does the policy require?

FieldTypeWhat it holds
promptRequirement{ kind: 'choice' | 'notice', reason } | { kind: 'none' }The interaction still owed. reason is missing, expired or policy-changed.
resolution{ status, policy }How the policy resolved: matched, no-match, failed or unconfigured. policy is set only when matched.
policyPendingbooleantrue until the transport's first answer. The UI stays hidden while it is true.
policyRuleresolved ruleThe rule c15t evaluates with: the matched rule, or a strict opt-in fallback. Has id, model, prompt, scope, preselectedCategories, actions, rights and validity.
model'opt-in' | 'opt-out' | 'iab' | 'none'The permission model in force.
consentCategoriescategory list or nullCategories configured or discovered on the page. null means the policy's full scope.
evaluationPolicyobjectThe validated projection c15t evaluated. For DevTools and debugging.

Check resolution.status === 'matched' before you trust policyRule as the visitor's real policy. While the policy loads or after it fails, policyRule is the strict fallback.

What should the UI show?

FieldTypeWhat it holds
activeUI'banner' | 'dialog' | 'none' | nullThe surface to render. Derived from the prompt, and changed by set.activeUI.
translations{ language, translations } | nullThe copy for the resolved language.
branding'c15t' | 'inth' | 'consent' | nullThe brand for the "Secured by" tag.
hosting'inth' | 'self-hosted' | nullWho runs the backend, as /init reported it. Separate from branding. null before init, for offline() and custom() transports that do not send it, and for backends older than the field. Not verified.

Context and bookkeeping

FieldWhat it holds
overridesThe country, region, language and GPC inputs you set.
locationThe country and region the backend reported.
userThe identified user, if any.
policySnapshotTokenA signed token sent back with saves so the backend can check the policy.
iabThe IAB state under an IAB policy: vendor list, TC string and purpose and vendor choices. null otherwise.
vendorsDeclared vendors, or null.
revisionA counter that increases on every change.
evaluatedAtWhen the snapshot was last evaluated, in epoch milliseconds.

Check it works

  1. Log getSnapshot() after ready() resolves. resolution.status is matched, policyPending is false, and explicitChoice is null for a new visitor.
  2. Accept all and log it again. explicitChoice.categories has an entry per category and promptRequirement.kind is none.