What the __gpp() Function Actually Is
The Global Privacy Platform gives you one JavaScript entry point, window.__gpp, that ad tech vendors call to read a user's privacy choices. It replaced the older __uspapi (US Privacy) function and sits alongside the TCF's __tcfapi. One transport, many jurisdictions: a US National section, per-state sections, TCF Europe, and TCF Canada all travel inside a single encoded GPP string that __gpp() exposes.
If you've implemented the TCF CMP API before, the shape will feel familiar. You call a global function with a command name and a callback, and the CMP answers. The differences are in the command set and the object it returns. This guide walks the API surface as defined in the IAB Tech Lab GPP specification, then shows how CookieBeam's GPP runtime maps onto it.
The Six Generic Commands
Every compliant CMP has to answer six generic commands, and the spec is strict about one thing: they all run synchronously. Each call invokes the callback immediately, with no promises, no timeouts, no waiting on network. That constraint is what lets a vendor script call __gpp('ping', cb) and branch on the result in the same tick.
- ping reports the CMP's state so a caller can decide whether the real signal is ready yet.
- addEventListener registers a callback that fires every time the CMP's state changes.
- removeEventListener tears a listener down by its id.
- hasSection answers whether a named section (say
usnat) is present. - getSection returns the parsed fields of a section.
- getField returns a single field value from a section.
The call signature is __gpp(command, callback, parameter). Commands that aren't generic (there aren't many) get queued for the full CMP to handle once it loads.
Reading the PingReturn Object
The ping command is where most integrations start, because its return object tells you everything about the CMP's readiness. The fields you'll actually branch on:
- gppVersion: the protocol version, currently
"1.1". - cmpStatus: one of
"stub","loading","loaded", or"error". If it's still"stub", the real CMP hasn't taken over yet. - cmpDisplayStatus:
"visible","hidden","disabled", or null, telling you whether the consent UI is on screen. - signalStatus:
"not ready"or"ready". This is the one that matters for vendors. Don't act on the GPP string until it reads"ready". - supportedAPIs: an array like
["2:tcfeuv2", "7:usnat", "8:usca"]. - cmpId: the IAB-assigned CMP id, which is
0while the stub is still in charge. - sectionList, applicableSections, gppString, and parsedSections.
A vendor's correct pattern is to check signalStatus, and if it isn't ready, register an addEventListener and wait for the change rather than polling.
supportedAPIs and applicableSections
These two arrays confuse people because they look similar and mean different things. supportedAPIs lists every section your CMP can encode, in the format "[SectionID]:[APIprefix]", for example "7:usnat". It's a capability list. It doesn't say anything about the current user.
applicableSections is the runtime answer: which section id (or ids) is in force for this specific visitor. In most cases it holds a single id. The value [-1] is the one to handle deliberately: it means no section applies to this user, which is the correct state for, say, a visitor outside every jurisdiction your CMP covers. Treating [-1] as an error is a common bug. It isn't an error, it's a valid outcome.
The Stub Has to Load First
All six generic commands must be answerable the instant any script on the page might call __gpp. Since the full CMP loads asynchronously, that's impossible unless a lightweight stub defines window.__gpp first and either answers generic commands directly or queues everything for replay. The stub also creates a hidden iframe named __gppLocator so scripts running inside nested iframes can discover that a CMP exists in a parent frame.
Put the stub in the document head, before any vendor tag, prebid, or ad library that might race it. If a vendor calls __gpp('ping', cb) before the stub runs, the function simply doesn't exist and the call throws. Ordering is the whole game. For the deeper mechanics of buffering and replay, see the TCF and GPP stub loading guide.
Listeners, Not Polling
The consent state changes at least once on a normal page: the visitor arrives with no decision, then accepts or rejects, and the CMP re-encodes the GPP string. Vendors that grabbed gppString once at ping time will hold a stale value. The spec's answer is addEventListener, which returns immediately and then fires your callback on every change, handing you a fresh pingData object each time.
The event object carries an eventName (values include listenerRegistered, signalStatus, cmpStatus, and sectionChange), a listenerId you can pass to removeEventListener, a data payload, and the current pingData. Register once, react to signalStatus becoming "ready", and read the string then.
How CookieBeam Implements It
CookieBeam's GPP runtime is built on the official @iabgpp/cmpapi toolkit, so the encoded strings come from IAB's own encoder rather than a homegrown one. It reports gppVersion "1.1" and advertises the sections it has actually implemented and tested (TCF EU, TCF Canada, US Privacy, and the US National and per-state sections) in supportedAPIs, rather than every section the underlying library theoretically supports. That distinction matters: advertising a section you haven't wired up produces strings a vendor can't trust.
The stub is generated code, injected inline ahead of the full runtime, and it answers ping, addEventListener, and removeEventListener directly while queueing the rest. A production deployment still needs a registered IAB CMP id before its strings should be treated as authoritative by downstream vendors, which is a certification step, not a code change.
Mistakes to Avoid
- Making a generic command async. If your
pinghandler awaits anything, you've broken the contract and callers will misbehave. - Reading gppString before signalStatus is ready. You'll serialize a half-formed or default state.
- Treating applicableSections [-1] as a failure. It means no section applies, which is a legitimate state.
- Loading the CMP without a stub. Every early
__gppcall throws until the real function exists. - Advertising sections you don't encode.
supportedAPIsis a promise; keep it honest.