Skip to main content

CMP & Browser Signals

The SDK reads three standard consent signals automatically: IAB TCF, IAB GPP and Global Privacy Control. All three are on by default. You can turn any of them off for a source in Configuration.

Each reader reports one of three answers for each purpose:

  • granted: the signal allows the purpose.
  • denied: the signal refuses it.
  • no-signal: the signal says nothing either way. This is never read as consent. It simply doesn't count towards the result.

Waiting for the CMP​

CMPs often load after the Surfside tag. The TCF and GPP readers wait for window.__tcfapi or window.__gpp to appear, checking every 100 ms for the first 10 seconds and then once a second. They stop after five minutes. If no CMP appears, the SDK keeps its current state: either a decision restored from an earlier page view, or the default.

When the CMP appears, the reader subscribes to it. It then reacts to every later change, including a shopper reopening the banner and changing their choice.

The readers only act on data the CMP has committed to. A CMP showing its banner, still loading, or reporting an error is ignored, so an unanswered banner is never read as a refusal.

IAB TCF v2​

Reads: window.__tcfapi('addEventListener', 2, …)

The SDK acts on TCF payloads whose eventStatus is tcloaded or useractioncomplete. It ignores cmpuishown, and any payload whose cmpStatus is stub, loading or error.

TCF is the only standard signal that can deny tracking. The SDK uses two TCF purposes:

TCF purposestrackingidentity
Purpose 1 (store and/or access information on a device) refuseddenieddenied
Purpose 1 granted, Purpose 3 (create profiles for personalised advertising) refusedgranteddenied
Purposes 1 and 3 both grantedgrantedgranted
gdprApplies is falseno-signalno-signal
purpose.consents missing or emptyno-signalno-signal

A few details:

  • Publisher consents narrow the result. If the payload's publisher.consents block grants at least one purpose, a purpose only counts as granted when both the purpose consent and the publisher consent grant it.
  • An empty block means no decision yet. TCF v2.2 requires purpose.consents on every payload, so a CMP that has only drawn its banner publishes it empty. A block that is filled in but refuses everything is treated as a genuine refusal.
  • Vendor consent is not read. The SDK uses purpose-level consent only. It does not look up a vendor consent bit.

IAB GPP (US sections)​

Reads: window.__gpp('addEventListener', …) and window.__gpp('ping', …)

The SDK acts on GPP data once the CMP reports signalStatus: 'ready'. It uses applicableSections to decide which sections apply to this shopper and reads only those. If applicableSections is [-1] ("no section applies"), GPP reports no-signal.

GPP only ever affects identity.

Supported sections​

The SDK reads the US National section and every US state section:

IDSectionIDSectionIDSection
7usnat14usmt21usnj
8usca15usor22ustn
9usva16ustx23usmn
10usco17usde24usmd
11usut18usia25usin
12usct19usne26usky
13usfl20usnh27usri

New US sections that IAB adds later are also honoured, as long as the CMP's payload makes the section unambiguous. Non-US sections (EU TCF, Canadian TCF, and the deprecated US Privacy string) are not read by the GPP reader.

How a section is read​

The opt-out fields use the GPP encoding: 0 = not applicable, 1 = opted out, 2 = did not opt out.

What the applicable sections containidentity
Any of SaleOptOut, SharingOptOut or TargetedAdvertisingOptOut is 1denied
The section's GPC sub-section (or Gpc field) is truedenied
MspaServiceProviderMode is 1denied
None of the above, and at least one opt-out field is 2granted
Only 0 values, or no opt-out fieldsno-signal

If several sections apply, any one opting out is enough to deny.

Opt-out fields differ by state

SaleOptOut is the only field every US section defines. SharingOptOut exists only in usnat and usca. Every other state uses TargetedAdvertisingOptOut, which usca does not define. A field that a state's section doesn't define is ignored, so a mock or CMP configuration that uses the wrong field reads as no-signal, not as a denial.

MspaCoveredTransaction is recorded but doesn't change the decision. The SDK does not currently act on GPP sensitive-data fields (such as SensitiveDataProcessing). If your CMP collects those and you need them to restrict identity, pass the result to setConsent.

Jurisdictions​

The sections that applied are recorded as jurisdictions (for example ["usca"]) on the consent state and on every event, even when the shopper didn't opt out. Which state's law applies is useful context in itself. At most two are recorded; when more apply, state sections are kept ahead of usnat. Every applicable section still counts towards the decision.

Global Privacy Control​

Reads: navigator.globalPrivacyControl

Valueidentity
truedenied
false or absentno-signal

GPC only ever affects identity. Collection continues with identity removed.

Some browser extensions set GPC a moment after the page loads. If GPC isn't present at first, the SDK keeps checking for it for up to five minutes and applies the opt-out as soon as it appears.

Within a page view GPC works in one direction only: it can switch on, but it won't switch off. If a shopper turns GPC off, their earlier GPC opt-out is lifted only once the SDK has confirmed GPC is really absent, which means a page view where GPC stays absent for the full five-minute check.

When a signal goes quiet​

A CMP that hasn't loaded yet looks the same as a CMP with nothing to report. So that a slow CMP can't accidentally reverse a shopper's earlier opt-out:

  • A no-signal from TCF or GPP does not clear an earlier denial from that same source. Only the CMP publishing an actual grant can lift it.
  • A no-signal from GPC (once the SDK has confirmed GPC is absent) does clear an earlier GPC denial, because the shopper really has turned it off.
  • A new setConsent call always replaces your previous setConsent decision for the purposes you pass.