Consent
Read and manage user consent. ChirpBack honors GDPR, CCPA, and Global Privacy Control out of the box.
ChirpBack is consent-first. Until consent is granted, the SDK runs in a minimal mode: no events fire, no surfaces show, no PII is sent. When consent is denied or revoked, the SDK tears down its runtime immediately and clears local state.
Two patterns
| Pattern | Use when |
|---|---|
Pass it inline to init — Chirp.init({ clientId, consent: { state: "granted" } }) | You've already got consent (your own banner, internal tool, or you handle it elsewhere). Surveys, announcements, and feedback work from the next call. |
Manage it via Chirp.consent — leave consent out of init, then call update / revoke | You use a CMP (OneTrust, Cookiebot, Iubenda, Osano), need GDPR / CCPA / GPC compliance, or want to react to user choices in a cookie banner. |
The rest of this page covers the second pattern — the consent API.
Read current consent
Chirp.consent.get(): ConsentSnapshotconst snap = Chirp.consent.get();
console.log(snap.state); // 'unknown' | 'denied' | 'essential_only' | 'granted'Snapshot shape
interface ConsentSnapshot {
state: "unknown" | "denied" | "essential_only" | "granted";
source: "default" | "host" | "cmp" | "gpc" | "tcf" | "user" | "revoke";
timestamp: number;
tcString?: string; // TCF v2 consent string
gpc?: boolean; // Global Privacy Control signal
categories?: string[]; // GDPR categories allowed
}Update consent
Chirp.consent.update(input: {
state: ConsentSnapshot["state"];
source?: ConsentSnapshot["source"];
gpc?: boolean;
tcString?: string;
categories?: string[];
}): ConsentSnapshotGrant consent
Chirp.consent.update({ state: "granted", source: "user" });Deny consent (essential only)
Chirp.consent.update({ state: "essential_only", source: "user" });Pass a TCF v2 consent string
Chirp.consent.update({
state: "granted",
source: "tcf",
tcString: "COwABEeowA...",
categories: ["analytics", "marketing"],
});Revoke consent
Chirp.consent.revoke(): ConsentSnapshotChirp.consent.revoke();Stronger than update({ state: 'denied' }):
- Tears down the runtime immediately
- Hides any open surfaces
- Clears the consent record from local storage entirely
Call revoke when the user explicitly opts out (e.g. clicks "Do not track" in your settings).
How consent gates the SDK
| State | Behavior |
|---|---|
unknown | SDK boots but stays passive. No events, no surfaces, no PII sent. |
denied | Runtime torn down. identify, survey.open, etc. are no-ops. |
essential_only | Frequency capping and core tracking work, but personalization is off. |
granted | Full SDK functionality. |
Global Privacy Control
If a user's browser sends the GPC header (Sec-GPC: 1), the SDK detects it on init and applies state: 'essential_only' automatically — unless your own CMP has already set a stronger consent.
You can read it at any time:
const { gpc } = Chirp.consent.get();
if (gpc) {
// honor the user's browser-level signal
}Wiring up a CMP
If you use a Consent Management Platform (OneTrust, Cookiebot, Iubenda, Osano, etc.), forward its decisions:
// Pseudo: react to your CMP's API
cmp.onChange((decision) => {
Chirp.consent.update({
state: decision.acceptedAll ? "granted" : "essential_only",
source: "cmp",
categories: decision.categories,
});
});Listen for changes
Chirp.on("consent:changed", ({ state, previous, source }) => {
console.log(`Consent went ${previous} → ${state} (${source})`);
});Gotchas
state: 'denied' and revoke() both stop tracking, but only revoke() purges
the saved consent record. If you want the user to see your consent prompt
again on the next visit, use revoke().
- Consent persists in
localStorageunder the keychirpback.consent. Chirp.reset()does not affect consent. To reset consent, callrevoke()explicitly.
Next steps
- Initialize — how consent state is read on init
- Events —
consent:changed