---
title: IAB GPP
description: Add the IAB Global Privacy Platform API (__gpp) to a plain HTML
  page with the c15t.gpp.js script tag, so ad tech can read US state opt-outs
  and the TCF EU consent string.
group: frameworks
lastModified: "2026-10-10T16:01:45+01:00"
---
## What GPP does

`c15t.gpp.js` installs `window.__gpp`, the GPP 1.1 CMP API, and keeps its GPP
string in step with the visitor's choices. Prebid.js, Google Ad Manager and
other ad tech read US privacy signals from it.

## Load the GPP script

Add `c15t.gpp.js` next to the c15t script. It works with `c15t.js`,
`c15t.offline.js`, `c15t.headless.js` and `c15t.iab.js`:

```html
<script src="https://cdn.jsdelivr.net/npm/@c15t/browser@alpha/dist/c15t.gpp.js"></script>
<script
  src="https://your-project.inth.app/c15t.js"
  defer
></script>
```

Loading the script turns GPP on with the defaults. It installs a `__gpp`
stub as soon as it runs, so ad tags that call `__gpp` before c15t starts
are queued rather than lost. Load it without `defer`, before your ad tags,
to get that. The order relative to `c15t.js` does not matter.

Use the same version for both files. Pages that do not load `c15t.gpp.js`
download none of the GPP code. It also carries the TCF decoder that fills in
`parsedSections.tcfeuv2`, which makes it about 15 kB gzipped.

## Change the GPP options

Queue a `gpp` object with the rest of your configuration:

```html
<script>
  window.c15t = window.c15t || [];
  c15t.push(['config', {
    gpp: { usFallback: 'none' },
  }]);
</script>
```

`gpp: false` keeps GPP off on a page that loads the script, and removes its
stub. `c15t.dispose()` removes `__gpp`.

To add the TCF EU section for visitors under an `iab` policy, load
`c15t.iab.js` instead of `c15t.js`; see [IAB TCF](/docs/frameworks/html/iab).

## How the policy decides the section

The policy rule c15t matched for the visitor decides whether a section
applies. The visitor's location only picks which US section carries it.

|Matched rule and visitor|Section in the GPP string|
|--|--|
|`iab` rule, with IAB TCF set up|`tcfeuv2` (ID 2): the TC String the CMP confirmed, unchanged|
|`iab` rule, any visitor, with `tcf: false`|None; `applicableSections` is `[-1]`|
|Any other rule with the `preferences` or `opt-out` right, US visitor in a state with a section|That state's section, such as `usca` (ID 8)|
|The same rule, US visitor whose region is unknown or whose state has no section|`usnat` (ID 7), MSPA US National version 2; none with `usFallback: 'none'`|
|The same rule, `usApproach: 'national'`|`usnat` for every US visitor|
|A rule without those rights, such as `none`|None|
|A visitor outside the US under any rule other than `iab`|None|

Every `opt-in` and `opt-out` rule has the `preferences` right, and every
`opt-out` rule also has `opt-out`. A `none` rule has them only if you add
them. A rule that gives the visitor no way to opt out produces no US
section, even when the visitor sends a GPC signal.

State sections exist for California, Colorado, Connecticut, Delaware, Florida,
Iowa, Minnesota, Montana, Nebraska, New Hampshire, New Jersey, Oregon,
Tennessee, Texas, Utah and Virginia. Indiana, Kentucky, Maryland and Rhode
Island are not encoded yet: their published specifications start the section
with a header that the IAB reference implementation does not encode. Visitors
there get the fallback, `usnat` by default. So does a US visitor whose region
the geo headers did not supply.

The MSPA US National specification describes `usnat` for MSPA signatories
that chose the national approach. Without `mspaMode`, c15t reports the
fallback as a transaction the MSPA does not cover (`MspaCoveredTransaction: 2`), which still carries the opt-outs to vendors such as Prebid.js. If you
reserve `usnat` for the national approach, set `usFallback: 'none'`; those
visitors then get no section until their state resolves.

## What the US sections report

* `SaleOptOut`, `SharingOptOut` and `TargetedAdvertisingOptOut`: `1` (opted
  out) when the `marketing` category is not permitted, otherwise `2`. A
  refusal, a GPC signal the rule maps to `marketing` through
  `privacySignals.gpc`, and an opt-in rule without a grant all count.
* The opt-out notices: `1` (given), since the rule offers an opt-out.
* The sharing or processing notice: `1` when the rule has the `disclosure`
  right, otherwise `2`.
* `Gpc`: the browser's Global Privacy Control signal, in sections that have a
  GPC subsection. It is reported even when the rule does not map GPC to a
  category, so give US rules a `privacySignals.gpc` mapping if the opt-outs
  should follow it too.
* Sensitive data and known-child consents: `0` (not applicable). c15t has no
  category for them, so the string states that you do not process sensitive
  data or knowingly process children's data. If you do, GPP from c15t does
  not describe your processing; collect and signal that consent separately.
* `MspaCoveredTransaction`: `2` (not covered) unless you set `mspaMode`.

The notice fields are your attestation, made through the rule's rights:
c15t cannot see whether your privacy notice is on the page. Show the notices
the rule promises, including a persistent opt-out control.

## GPP options

Every field is optional. Pass them in the `gpp` option, where `gpp: true`
uses the defaults, as props on `ConsentGPP` in React, or to `mountGPP()` in
`@c15t/browser`.

|Option|Default|Effect|
|--|--|--|
|`cmpId`|the IAB CMP ID c15t holds, else `1`|CMP ID reported by `ping`. The GPP specification has string creators without a registered ID, including MSPA US National creators, use `1`. A TCF EU section needs the registered ID its TC String names.|
|`usApproach`|`'state'`|`'state'` uses the visitor's state section. `'national'` reports `usnat` for every US visitor; the MSPA reserves it for signatories that chose the national approach.|
|`usFallback`|`'usnat'`|Under the state approach, the section for a US visitor whose state is unknown or has no section: `'usnat'` or `'none'`.|
|`mspaMode`|unset|`'opt-out-option'` or `'service-provider'`. Set it only if you signed the IAB Multi-State Privacy Agreement; the transaction is then reported as covered. In service provider mode the opt-outs are reported as not applicable.|
|`optOutCategories`|`['marketing']`|Categories whose refusal reports an opt-out of sale, sharing and targeted advertising.|
|`tcf`|`true`|Include the `tcfeuv2` section under an `iab` policy. It needs IAB TCF set up as well.|

## Check the signal

Open the browser console on a page with GPP on and call:

```js
__gpp('ping', (data) => console.log(data));
```

For a California visitor who has not opted out, the result includes
`applicableSections: [8]`, `signalStatus: 'ready'` and
`parsedSections.usca[0].SaleOptOut === 2`. After the visitor refuses
`marketing`, `SaleOptOut` is `1`. `__gpp('getField', cb, 'usca.SaleOptOut')`
returns the same value. Scripts in iframes reach the API through the
`__gppLocator` frame and `postMessage`.

Under an `iab` rule, `parsedSections.tcfeuv2` uses the field names of the
IAB Europe TCF section, such as `PurposeConsent`, `VendorConsent` and
`PubRestrictions`. `getSection` and `getField` answer `null` for `tcfeuv2`,
as the IAB reference implementation does: TCF vendors read consent from
events, not on demand.

`signalStatus` stays `'not ready'` while the policy is pending, while the
banner or dialog is open, while an `iab` rule has no confirmed TC String,
and while a new TC String is decoded. Listeners added with
`addEventListener` get `signalStatus: 'not ready'`, then `cmpDisplayStatus`
and `sectionChange` events, then `signalStatus: 'ready'`.

## Ad tags that load before c15t

c15t installs `__gpp` in the browser once consent starts, after it loads the
GPP code. Vendor scripts that call `__gpp` earlier need a stub. c15t takes over
the calls and listeners a stub queued, whether the stub keeps listeners on
`__gpp.events`, as the GPP specification's sample does, or returns them from
`__gpp('events')`, as `@iabgpp/stub` does. Call `initializeGPPStub()` from
`@c15t/iab/gpp` in your first script, or use the IAB's own stub snippet.
When another stub already answers iframes, c15t leaves that to it, so each
iframe call gets one reply.

If a CMP that has already loaded owns `__gpp`, c15t leaves it in place.
The `gpp` option reports the conflict to the `onError` callback,
`ConsentGPP` logs it, and `mountGPP()` and `createGPP()` throw. Run one GPP
CMP per page.

GPP signals what the visitor chose; it does not block scripts. Gate vendor
scripts with c15t's script loading as well.
