Date | Version | Comments |
June 2023 | 1.1 |
Removal of return values in favor of callback functions. Removal of getGPPData command |
Sept 28, 2022 | 1.0 |
Published final public version |
This is one of the IAB Tech Lab Global Privacy Platform Specifications. It defines the API for Consent Management Platforms (CMPs). The CMP API is the interface a CMP provides to callers (web and in-app) to access information regarding the privacy preferences disclosed and obtained from the end user by the CMP. Both required functionality that the CMP must provide and optional features are described.
The Global Privacy Platform (GPP) enables advertisers, publishers and technology vendors in the digital advertising industry to adapt to regulatory demands across markets. It is a single protocol designed to streamline transmitting privacy, consent, and consumer choice signals from sites and apps to ad tech providers. IAB Tech Lab stewards the development of these technical specifications.
Global Privacy Platform technical specifications governed by the IAB Tech Lab is licensed under a Creative Commons Attribution 3.0 License. To view a copy of this license, visit creativecommons.org/licenses/by/3.0/ or write to Creative Commons, 171 Second Street, Suite 300, San Francisco, CA 94105, USA.
Disclaimer
THE STANDARDS, THE SPECIFICATIONS, THE MEASUREMENT GUIDELINES, AND ANY OTHER MATERIALS OR SERVICES PROVIDED TO OR USED BY YOU HEREUNDER (THE “PRODUCTS AND SERVICES”) ARE PROVIDED “AS IS” AND “AS AVAILABLE,” AND IAB TECHNOLOGY LABORATORY, INC. (“TECH LAB”) MAKES NO WARRANTY WITH RESPECT TO THE SAME AND HEREBY DISCLAIMS ANY AND ALL EXPRESS, IMPLIED, OR STATUTORY WARRANTIES, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AVAILABILITY, ERROR-FREE OR UNINTERRUPTED OPERATION, AND ANY WARRANTIES ARISING FROM A COURSE OF DEALING, COURSE OF PERFORMANCE, OR USAGE OF TRADE. TO THE EXTENT THAT TECH LAB MAY NOT AS A MATTER OF APPLICABLE LAW DISCLAIM ANY IMPLIED WARRANTY, THE SCOPE AND DURATION OF SUCH WARRANTY WILL BE THE MINIMUM PERMITTED UNDER SUCH LAW. THE PRODUCTS AND SERVICES DO NOT CONSTITUTE BUSINESS OR LEGAL ADVICE. TECH LAB DOES NOT WARRANT THAT THE PRODUCTS AND SERVICES PROVIDED TO OR USED BY YOU HEREUNDER SHALL CAUSE YOU AND/OR YOUR PRODUCTS OR SERVICES TO BE IN COMPLIANCE WITH ANY APPLICABLE LAWS, REGULATIONS, OR SELF-REGULATORY FRAMEWORKS, AND YOU ARE SOLELY RESPONSIBLE FOR COMPLIANCE WITH THE SAME.
The IAB Technology Laboratory ("Tech Lab") is a non-profit research and development consortium that produces and provides standards, software, and services to drive growth of an effective and sustainable global digital media ecosystem. Comprised of digital publishers and ad technology firms, as well as marketers, agencies, and other companies with interests in the interactive marketing arena, IAB Tech Lab aims to enable brand and media growth via a transparent, safe, effective supply chain, simpler and more consistent measurement, and better advertising experiences for consumers, with a focus on mobile and "TV"/digital video channel enablement. The IAB Tech Lab portfolio includes the DigiTrust real-time standardized identity service designed to improve the digital experience for consumers, publishers, advertisers, and third-party platforms. Established in 2014, the IAB Tech Lab is headquartered in New York City with an office in San Francisco and representation in Seattle and London.
Learn more about IAB Tech Lab here: https://www.iabtechlab.com/
Consent Management Platforms (CMPs) provide a user interface to establish transparency to users, and obtain consent or register objections from end users, and capture their preferences in signals. These signals are packaged in a standardized, easily communicated payload called a GPP String. The CMP API provides a standardized means for parties, such as the hosting publisher or an advertising vendor, to access these preferences managed by the CMP.
Using the API, scripts may obtain the GPP String payload and the information it contains, which is ready to use without having to understand how to “unpack” the payload format. This makes it easy to make immediate data processing decisions based on the returned information.
This API allows for accessing signals across legislations, regulations, and standards. It provides a common interface that can be used to access underlying APIs such as the IAB TCF and USPrivacy.
In order to distinguish between the different underlying APIs, each API will be assigned a prefix. A complete list of available API prefixes can be found in the Section information.
Example API prefixes:
API | Prefix |
IAB TCF1 (EU) | tcfeuv1 (no longer used) |
IAB TCF v2 (EU) | tcfeuv2 |
IAB TCF v1 (Canada) | tcfcav1 |
IAB CCPA/USP v1 | uspv1 |
Every consent manager must provide the following API function:
__gpp(command, callback, parameter, [version])
Requirements for the interface:
- The
__gpp
function must always be a function and cannot be any other type, even if only temporarily on initialization – the API must be able to handle calls at all times. - The command must always be a string.
- The callback must always be a function.
- Parameter can be of mixed type depending on used command
- The
__gpp
function does not have a return value - If a CMP cannot immediately respond to a query, the CMP must queue all calls to the function and execute them later. The CMP must execute the commands in the same order in which the function was called.
- A CMP must support all generic commands. All generic commands must always be available when a
__gpp
function is present on the page. This means that “stub code” that supports all generic commands must be in place before/during CMP load.
All CMPs must support all generic commands. Generic commands are commands that can be used independent of section specifications. All generic commands must always be executed immediately without any asynchronous logic and call the supplied callback function immediately. The generic commands are: ‘ping’, ‘addEventListener’, ‘removeEventListener’, ‘hasSection’, ‘getSection’, and ‘getField’.
Regional section policy writers may require CMPs to register to operate within the policies for that section. In these cases, CMP IDs must be used if the CMP has an ID. For CMPs that are not registered, a value of 1 must be used by string creators who do not have a CMP ID and are not using a commercially available CMP.
Examples:
Publisher A looking to create a GPP string that will contain the section for the US National approach must use 1 as value for CMP ID since the MSPA does not have CMP registration requirements.
Publisher B looking to create a GPP string that will contain sections for the US National approach or the TCF EU must register themselves or work with a registered CMP and use the assigned CMP ID in accordance with the TCF Policies.
The ping
command can be used to determine the state of the CMP. The callback shall be called with a PingReturn object as the value of the data
parameter. A value of false
will be passed as the argument to the success
parameter if the CMP fails to process this command.
argument | type | value |
command |
string | "ping" |
callback |
function | function (data: PingReturn, success: boolean) |
parameter |
not used |
Example:
__gpp('ping', myFunction);
This object contains information about the loading status and configuration of the CMP.
PingReturn = {
gppVersion : String, // must be “Version.Subversion”, current: “1.1”
cmpStatus : String, // possible values: stub, loading, loaded, error
cmpDisplayStatus: String, // possible values: hidden, visible, disabled
signalStatus : String, // possible values: not ready, ready
// List of supported APIs (section ids and prefix strings).
// Example: ["2:tcfeuv2","6:uspv1"]
supportedAPIs : Array of string,
// IAB assigned CMP ID, may be 0 during stub/loading. Refer the above CMP ID section for additional information.
cmpId : Number,
sectionList : Array of Number, // may be empty during loading of the CMP
// Section ID considered to be in force for this transaction.
// In most cases, this field should have a single section ID. In rare occasions where such a single section ID
// can not be determined, the field may contain up to 2 values. During the transition period which ends on
// September 30, 2023, the legacy USPrivacy section may be determined as applicable along with another US section.
// In this case, the field may contain up to 3 values where one of the values is 6, representing the
// legacy USPrivacy section. The value can be 0 or a Section ID specified by the Publisher / Advertiser, during
// stub / load.
// When no section is applicable, the value will be [-1].
applicableSections: Array of Number,
gppString: String // the complete encoded GPP string, may be empty during CMP load
// The parsedSections property represents an object of all parsed sections of the gppString property that are supported
// by the API on this page (see supportedAPIs property). The object contains one property for each supported API with
// the name of the API as the property name and the value as a parsed representation of this section with exactly the
// same return as the getSection command, which may include subsections. If a section is supported but not represented
// in the gppString, it is omitted in the parsedSections object.
// Please refer to each section's spec for the exact field names and data types in JavaScript. The sections here should
// be consistent with the GPP string, not placeholder values.
parsedSections: Object
}
In JavaScript, a parsedSections
object should be a native JS object that maps from the section's API prefix names
enumerated here
to the section's JS representation according to its spec. Each section's is represented as an array of objects, and each
object corresponds to a sub-section (segment) in that section. Follow this table of data type mapping
to map each spec's GPP field types to JavaScript native data
types. Examples:
/* Example of a `parsedSections` that holds two sections: tcfcav1, tcfeuv2 */
{
/* See "GPPExtension: IAB Canada TCF.md". */
tcfcav1: [
/* Core Sub-section */
{
Version: 1,
Created: new Date ("Thu Apr 13 2023 18:07:12 GMT+0200"),
LastUpdated: new Date ("Thu Apr 13 2023 18:07:12 GMT+0200"),
CmpId: 31,
CmpVersion: 123,
ConsentScreen: 5,
...
},
/* Publisher Purposes Sub-section */
{
SubsectionType: 3,
PubPurposesExpressConsent: [1,2,3,4,5],
PubPurposesImpliedConsent: [6,7,8,9],
...
}
],
/* See "GPPExtension: IAB Europe TCF.md". */
tcfeuv2: [
/* Core Segment */
{
Version: 2,
Created: new Date ("Thu Nov 10 2024 12:08:22 GMT+0200"),
LastUpdated: new Date ("Thu Nov 10 2024 12:08:2 GMT+0200"),
CmpId: 10,
CmpVersion: 56,
ConsentScreen: 0,
VendorConsent: [1,2,4,6],
...
},
/* Disclosed Vendors Segment */
{
SegmentType: 1,
...
}
/* This example doesn't contain the optional Publisher Purposes Segment */
]
}
/* Example of a `parsedSections` that holds one section: usnat */
{
/* See "IAB Privacy's Multi-State Privacy Agreement (MSPA) US National Technical Specification.md". */
usnat: [
/* Core Segment */
{
Version: 1,
SharingNotice: 1,
KnownChildSensitiveDataConsents: [0, 0],
MspaCoveredTransaction: 2,
...
},
/* GPC Sub-section */
{
SubsectionType: 1,
Gpc: true
}
]
}
Ping Status Codes
Status Code | Applicable for | Description |
'stub' |
cmpStatus | CMP not yet loaded - stub still in place |
'loaded' |
cmpStatus | CMP is finished loading |
'error' |
cmpStatus | CMP is in an error state. A CMP shall not repsond to any other API requests if this cmpStatus is present. A CMP may set this status if, for any reason, it is unable to perform the operation. |
'visible' |
cmpDisplayStatus | User interface is currently displayed |
'hidden' |
cmpDisplayStatus | User interface is not yet or no longer displayed |
'disabled' |
cmpDisplayStatus | User interface will not show (no Sections apply or data is current and does not need renewal) |
Null / not set |
cmpDisplayStatus | Is NULL when there is no display layer. Display layer refers to a modal that the user may interact with to express their choices. When no such modal is present, the value is NULL, e.g. when there is only a Do Not Sell or Share Personal Data link on the page that when clicked does not launch a modal. In this example, vendors should rely solely on signalStatus and the cmpDisplayStatus will be NULL / not set. |
'not ready' |
signalStatus | The CMP is not ready to respond to any calling scripts with the corresponding GPP string and applicable section ids. |
'ready' |
signalStatus | The CMP is ready to respond to any calling scripts with the corresponding GPP string and applicable section ids. The ‘ready’ status should only be sent when the GPP string contains the section that is currently applicable with the user’s current choices reflected. E.g. the ‘ready’ status should be signaled when applicableSection == -1 or applicableSection != 1 and the GPP string contains the section corresponding to applicableSection reflecting the user’s current choices. |
The addEventListener
command can be used to define a callback function that can be used to detect changes in the CMP. The callback shall be called with an EventListener
object immediately. The GPP script will then call the callback function and return a new EventListener object every time the CMP detects a change (see events below). A value of false
will be passed as the argument to the success
parameter if the CMP fails to process this command.
argument | type | value |
command |
string | "addEventListener" |
callback |
function | function (data: EventListener, success: boolean) |
parameter |
not used |
Example:
__gpp('addEventListener', myFunction);
The EventListener object is defined as:
EventListener = {
eventName : String, // for possible values see events below
listenerId : Number, // Registered ID of the listener
data: mixed, // data supplied by the underlying API.
pingData : object // see PingReturn
}
A call to the addEventListener
command must always trigger an immediate call to the callback function. When registering new event listeners, the CMP (and stub) must therefore generate new listenerIds for each call to this command.
Event Name | Type of data property | Description |
listenerRegistered |
boolean | Only used within the return object to addEventListener command. The data property signals whether the event listener was registered successfully. If data equals true, a listenerId must be sent, otherwise the listenerId must be 0 (zero). |
listenerRemoved |
boolean | Only used within the return object to removeEventListener command. The data property signals whether the event listener was successfully removed. |
cmpStatus |
string | Event is called whenever the status of the CMP changes (e.g. the CMP has finished loading). The data property will contain the new status (e.g. “loaded”) |
cmpDisplayStatus |
string | Event is called whenever the display status of the CMP changes (e.g. the CMP shows the consent layer). The data property will contain the new display status (e.g. “visible”). Note that this is only applicable when a consent layer is displayed. |
signalStatus |
string | Event is called whenever the signalStatus changes. The data property will contain the new signalStatus value. |
error |
string | Event can be called by the CMP in case of an error. The data property will contain a human readable error message. |
sectionChange |
string | Event is called whenever the status or content of a section changes (e.g. consent is obtained). The data property will indicate the name (API prefix) of the changed section. |
[API.prefix] or [API-prefix].[Eventname] |
mixed | Event is called by the CMP depending on the specific API needs (e.g. IAB TCF EU may specify different events than IAB USP). If the API defines different event types, these can be used by combining API-prefix and eventname, If the API does not specify different event types (e.g. in IAB TCF v2.0), the API-prefix is used as name. The data property will contain mixed data depending on API. |
The “signalStatus” event shall always be the first (if applicable) and last in a chain of events being fired by the CMP.
A CMP must send all relevant events and it must send them in a specific order so that listeners (e.g. vendors) can understand when a task is completed. Whenever the CMP starts to change or is about to change any of the existing sections or is processing user input for an existing GPP string, it must always first set "signalStatus" to "not ready" and fire the corresponding event. It can then perform the tasks (e.g. change the sections along with firing the section change events). Only when all tasks are completed, the CMP can set the "signalStatus" to "ready" and fire the corresponding event.
Event Order Example 1:
The following example illustrates the events that are fired, and the other order in which they are fired, assuming support for IAB TCF Canada for a new user.
Event Order | Event Name | Data | Description |
1 | initial data of PingReturn is {gppVersion:1.1, cmpStatus: loading, cmpDisplayStatus: hidden, signalStatus: not ready, ...} | ||
2 | listenerRegistered | CMP has registered the event listener. Event is immediately fired after registering. | |
3 | cmpStatus | loaded | CMP is now loaded. Event is fired with name=cmpStatus and data=loaded. |
4 | cmpDisplayStatus | visible | CMP now displays the consent layer. Event is fired with name=cmpDisplayStatus and data = visible |
5 | User makes their choices and clicks on accept or reject or save | ||
6 | cmpDisplayStatus | hidden | CMP closed the consent layer and processes user input. Event is fired with name=cmpDisplayStatus and data=hidden |
7 | sectionChange | tcfcav1 | CMP changes the section based on user input. Event is fired with name=sectionChange and data=tcfcav1 Note: if multiple sections are present, multiple sectionChange events may occur after another |
8 | signalStatus | ready | CMP is done with the processing, vendors can use the data. Event is fired with name=signalStatus and data = ready. |
Event Order Example 2:
The following example illustrates the events that are fired, and the order in which they are fired, assuming support for IAB TCF Canada for a returning user with a preexisting choice.
Event Order | Event Name | Data | Description | ||
1 | initial data of PingReturn is {gppVersion:1.1, cmpStatus: loading, cmpDisplayStatus: hidden, signalStatus: not ready, ... } | ||||
2 | listenerRegistered | CMP has registered the event listener. Event is immediately fired after registering. | |||
3 | cmpStatus | loaded | CMP is now loaded. Event is fired with name=cmpStatus and data=loaded | ||
4 | signalStatus | ready | CMP is done with the processing (consent information is loaded, no further processing needed, consent layer will not be shown), vendors can use the data. Event is fired with name=signalStatus and data=ready | ||
5 | User clicks on a link or button to resurface the consent layer in order to change their choice | ||||
6 | signalStatus | Not ready | CMP is expecting changes, vendors should not use the data but wait and pause their processing. Event is fired with name=signalStatus and data=not ready | ||
7 | cmpDisplayStatus | visible | CMP now displays the consent layer. Event is fired with name=cmpDisplayStatus and data=visible | ||
8 | User makes their choices and clicks on accept or reject or save | ||||
9 | cmpDisplayStatus | hidden | CMP closed the consent layer and processes user input. Event is fired with name=cmpDisplayStatus and data=hidden | ||
10 | sectionChange | tcfcav1 | CMP changes the section based on user input. Event is fired with name=sectionChange and data=tcfcav1 Note: If multiple sections are present, multiple sectionChange events may occur after another | ||
11 | signalStatus | ready | CMP is done with the processing, vendors can use the data. Event is fired with name=signalStatus and data=ready |
The removeEventListener
command can be used to remove an existing event listener. The callback shall be called with false
as the argument for the data
parameter if the listener could not be removed (e.g. the CMP cannot find a registered listener corresponding to listenerId
). A value of false
will be passed as the argument to the success
parameter if the CMP fails to process this command.
argument | type | value |
command |
string | "removeEventListener" |
callback |
function | function (data: boolean, success: boolean) |
parameter |
number | ID of the listenerId property that was returned from addEventListener command |
Example:
__gpp('removeEventListener', myFunction, listenerId);
The hasSection
command can be used to detect if the CMP has generated a section of a certain specification. The callback shall be called with true
as the argument for the data
parameter if the CMP has generated a section for the requested API prefix string. The data
parameter may be null
when the CMP is not yet loaded. A value of false
will be passed as the argument to the success
parameter if the CMP fails to process this command.
argument | type | value |
command |
string | "hasSection" |
callback |
function | function (data: boolean, success: boolean) |
parameter |
string | API Prefix string |
Example:
A client wants to ask the CMP if there is data for IAB TCF CA v1.0:
__gpp('hasSection', myFunction, "tcfcav1");
The getSection
command can be used to receive the (parsed) representation of a section of a certain specification. The callback shall be called with the (parsed) representation as the argument for the data parameter. The parsed representation of a section is an array of objects, where each object represents one sub-section of this section in the order that is given by the section specification. For example, the data parameter for the TCF Canada will be an array with one or two objects (Core sub-section plus optional publisher purposes sub-section). Each object is composed of the fields defined by the section specification.
The data parameter may be null
for sections that don't allow accessing the section data object outside an event handler. It may also be null
when the CMP is not yet loaded.
argument | type | value |
command |
string | "getSection" |
callback |
function | function (data: array of objects or null, success: boolean) |
parameter |
string | API Prefix string |
For example, client can ask the CMP to get the IAB TCF CA v1.0 TCData:
__gpp('getSection', myFunction, "tcfcav1");
Example value of data passed to the callback, according to GPPExtension: IAB Canada TCF.md:
[
/* Core Sub-section */
{
Version: 1,
Created: new Date ("Thu Apr 13 2023 18:07:12 GMT+0200"),
LastUpdated: new Date ("Thu Apr 13 2023 18:07:12 GMT+0200"),
CmpId: 31,
CmpVersion: 123,
ConsentScreen: 5,
...
},
/* Publisher Purposes Sub-section (optional) */
{
SubsectionType: 3,
PubPurposesExpressConsent: [1,2,3,4,5],
PubPurposesImpliedConsent: [6,7,8,9],
...
}
]
The getField
command can be used to receive a specific field out of a certain section. The callback shall be called with the value of the requested field as the argument for the data
parameter. The data
parameter may be null
for fields in sections that don't allow accessing the section data object outside an event handler. It may also be null
when the CMP is not yet loaded.
argument | type | value |
command |
string | "getField" |
callback |
function | function (data: mixed or null, success) |
parameter |
string | API Prefix string + "." (dot) + fieldname |
For example, a client can ask the CMP to get the last updated field from the IAB TCF CA v1.0 TCData.
__gpp('getField', myFunction, "tcfcav1.LastUpdated");
In addition to the generic commands, a CMP can support other commands that are defined by any GPP section. See the non-generic commands by reviewing a specific sections’ specifications. Any GPP section that wants to make use of the GPP API spec should define a set of commands as follows:
Example command xyz
Command: prefix.command
Callback: function (…) or “not used”
Parameter: data type or “not used”
A description of the command, what it does, what it’s meant for, when to use it and how.
Using the IAB TCF CA v1.0 as an example, the getVendorList
command would be defined as:
getVendorList
Command: iabtcfcav1.getVendorList
Callback: function (gvl: GlobalVendorList, success: boolean)
Parameter: (optional) int or string
Calling with this command and a valid vendorListVersion parameter shall return a GlobalVendorList object to the callback function….
In the example above, a call to __gpp (‘iabtcfcav1.getVendorList’,myfunction)
will be treated in the same way as a call to __tcfapi(‘getVendorList’,2,myfunction)
by the CMP.
The GPP standardizes storage locations and naming for the content of the GPP data and GPP string so that ad tags embedded in mobile apps can find the GPP data and string in a consistent way.
The pre-parsed GPP data as well as the GPP string shall be stored under NSUserDefaults(iOS) or SharedPreferences (Android). This will allow:
- Vendors to easily access GPP data
- GPP data to persist across app sessions
- GPP data to be portable between CMPs to provide flexibility for a publisher to exchange one CMP SDK for another
- Vendors within an app to avoid code duplication by not being required to include a GPP string decoder while still enabling all typical use cases
Note: If a Publisher chooses to remove a CMP SDK from their app they are responsible for clearing all IABGPP_* vestigial values for users so that vendors do not continue to use the GPP data therein.
The key names are a combination of the “IABGPP_” prefix followed by the section prefix followed by an underline and then followed by the name of the value (field name from the corresponding specification) it represents. The relevant sections documented in this spec are HDR (header), TCFEU2 (tcfv2), TCFCA1 (Canadian TCF), USP1 (U.S. Privacy).
NSUserDefaults (iOS) or SharedPreferences (Android) values
Key Name | Data type | Description |
IABGPP_HDR_Version |
String | GPP Version |
IABGPP_HDR_Sections |
String | List of Section IDs |
IABGPP_HDR_GppString |
String | Full consent string in its encoded form |
IABGPP_GppSID |
String | Section ID(s) considered to be in force. Multiple IDs are separated by underscore, e.g. “2_3” |
IABGPP_[SectionID]_String |
String | String representaiton of each section. E.g. IAB TCF EU v2 String will be found at IABGPP_2_String |
The data stored in the in-app storage is not encoded or compressed because the storage is private to the application. However, the resulting string will follow the encoding rules as listed in this spec.
Valid data types are Integer and String. All other data types such as Boolean, Date and Array (Range, Bitfield, Fibonacci-Range, …) should be converted into an Integer or String representation as follows:
Input Data Type | In-app Data Type | Description |
Boolean |
Integer (0/1) | Convert True = 1, False = 0 |
Integer / Integer Fibonacci |
Integer | unchanged |
String |
String | unchanged |
Datetime |
Integer | Convert date to amount of milliseconds since 1.1.1970 00:00:00 UTC |
Bitfield / Vairable length Bitfield / Range / Range Fibonacci / Optimized Range |
String | Convert all included IDs into a string separated by underscore, e.g. “1_4_5_6_99” |
ArrayOfRanges |
String | The key name will be combined by a static name and the key of the record. If the input data contains multiple records, the CMP SDK will create multiple keys, each with a combination of name and key. The value consists of a sequence of "id:type"-pairs separated by underscore. E.g. "3:0_5:1_6:1_7:2_12:0" |
Example key names:
Below are example key names from existing APIs. For a complete list of key names for a specific section, see Sections.
Key Name | Description |
IABGPP_TCFEU2_Version |
IAB TCF EU v2 Version number (see IAB TCF EU v2 specification) |
IABGPP_TCFEU2_Created |
IAB TECF EU v2 creation date |
IABGPP_TCFEU2_LastUpdated |
IAB TCF EU v2 last update date |
IABGPP_TCFEU2_CmpId |
IAB TCF EU v2 CMP ID |
IABGPP_TCFEU2_CmpVersion |
IAB TCF EU v2 CMP Version |
IABGPP_TCFEU2_PurposesConsent |
IAB TCF EU v2 CMP Purpose consents list |
IABGPP_TCFEU2_VendorConsent |
IAB TCF EU v2 CMP Vendor consents list |
IABGPP_TCFEU2_... |
Other IAB TCF EU v2 fields according to IAB TCF UE specification |
IABGPP_TCFCA1_Version |
IAB TCF CA v1 Version number (see IAB TCF CA v1 specification) |
IABGPP_TCFCA1_Created |
IAB TCF CA v1 creation date |
IABGPP_TCFCA1_… |
Other IAB TCF CA v1 fields according to IAB TCF CA specification |
IABGPP_USP1_Version |
IAB US Privacy String Version number (see IAB US Privacy v1 specification) |
IABGPP_USP1_Notice |
IAB US Privacy notice has been provided |
IABGPP_USP1_OptOut |
IAB US Privacy opt out of sale |
IABGPP_USP1_LSPACovered |
IAB US Privacy publisher is signatory to the LSPA |
How do third-party SDKs (vendors) access the consent information in-app?
On both Android OS and iOS, the vendor can be notified when the values of the shared keys changes. See NSUserDefaultsDidChangeNotification and SharedPreferences.OnSharedPreferenceChangeListener.
On Android OS, the GPP data and GPP string shall be stored in the default Shared Preferences for the application context. This can be accessed using the getDefaultSharedPreferences
method from the android.preference.PreferenceManager class using the application context. The GPP data values can be retrieved from the application Shared Preferences by key name using the get methods on the android.content.SharedPreferences class.
How is a CMP used in the CTV context?
The context of the CTV application will determine the storage locations and naming of the GPP data.
Applications running in a web runtime environment that supports, at minimum, the Web Storage (Second Edition) specification shall follow all storage and naming conventions detailed in the Javascript section of this spec. Data is to be retrieved using the Generic and Non-generic API commands, offering a consistent interface for Vendors to access GPP information.
Should data not persist in Web Storage beyond the lifecycle of the application (application close, standby, or device shutdown), all data storage and naming conventions are to follow the specifications outlined in the CTV Native Private Storage section of this spec.
Native CTV applications are to follow the naming conventions of the GPP data and GPP String outlined in the How is GPP used in-app section of this spec. Data is to be limited to the context of the Application and inaccessible to external applications.
Application Preferences (Registry)
Application Preferences, also referred to as a Registry in certain CTV environments, shall be used in a Native CTV Application environment under the condition that the GPP data and GPP String fit within the device constraints. Private Storage is to be used if the GPP data and GPP String do not fit within the device constraints.
Private Storage
Private Storage shall be used under the condition that the CTV environment does not offer a Web Runtime that supports the Web Storage (Second Edition) specification, data does not persist beyond the lifecycle of the Application, or offer an Application Preferences (Registry) interface. The GPP data and GPP String are to be saved in a standardized and private storage space. Files are to follow the same naming convention as the key names detailed in the How is GPP used in-app section of this spec with the contents being the value of the corresponding key.
Note: CTV Applications require proper permission scopes to be configured to read and write to the virtual Application file system.
The following code represents an example stub code.
window.__gpp_addFrame = function (n)
{
if (!window.frames[n])
{
if (document.body)
{
var i = document.createElement('iframe');
i.style.cssText = 'display:none';
i.name = n;
document.body.appendChild(i);
}
else
{
window.setTimeout(window.__gppaddFrame, 10, n);
}
}
};
window.__gpp_stub = function ()
{
var b = arguments;
__gpp.queue = __gpp.queue || [];
if (!b.length){ return __gpp.queue; }
var cmd = b[0];
var clb = b.length > 1 ? b[1] : null;
var par = b.length > 2 ? b[2] : null;
if (cmd === 'ping')
{
return {
gppVersion : '1.1', // must be “Version.Subversion”, current: “1.1”
cmpStatus : 'stub', // possible values: stub, loading, loaded, error
cmpDisplayStatus : 'hidden', // possible values: hidden, visible, disabled
supportedAPIs : ['2:tcfeuv2', '5:tcfcav1', '6:uspv1'], // list of supported APIs
cmpId : 31, // IAB assigned CMP ID, may be 0 during stub/loading
sectionList : [],
applicableSections: [-1], //or 0 or ID set by publisher
gppString : ''
};
}
else if (cmd === 'addEventListener')
{
__gpp.events = __gpp.events || [];
if (!('lastId' in __gpp)){ __gpp.lastId = 0; }
__gpp.lastId++;
var lnr = __gpp.lastId;
__gpp.events.push({
'id' : lnr,
'callback' : clb,
'parameter': par
});
return {
eventName : 'listenerRegistered',
listenerId: lnr, // Registered ID of the listener
data : true, // positive signal
pingData: {
gppVersion : '1.1',
cmpStatus : 'stub',
cmpDisplayStatus : 'hidden',
supportedAPIs : ['2:tcfeuv2', '5:tcfcav1', '9:usva', '7:usnat'],
cmpId : 31,
sectionList : [],
applicableSections: [-1], //or 0 or ID set by publisher
gppString : ''
}
};
}
else if (cmd === 'removeEventListener')
{
var success = false;
__gpp.events = __gpp.events || [];
for(var i=0; i<__gpp.events.length; i++)
{
if(__gpp.events[i].id == par)
{
__gpp.events[i].splice(i,1);
success = true;
break;
}
}
return {
eventName : 'listenerRemoved',
listenerId: par, // Registered ID of the listener
data : success, // status info
pingData: {
gppVersion : '1.1',
cmpStatus : 'stub',
cmpDisplayStatus : 'hidden',
supportedAPIs : ['2:tcfeuv2', '5:tcfcav1', '9:usva', '7:usnat'],
cmpId : 31,
sectionList : [],
applicableSections: [-1], //or 0 or ID set by publisher
gppString : ''
}
};
}
//these commands must not be queued but may return null while in stub-mode
else if (cmd === 'hasSection' || cmd === 'getSection' || cmd === 'getField')
{
return null;
}
//queue all other commands
else
{
__gpp.queue.push([].slice.apply(b));
}
};
window.__gpp_msghandler = function (event)
{
var msgIsString = typeof event.data === 'string';
try{ var json = msgIsString ? JSON.parse(event.data) : event.data; }
catch (e){ var json = null; }
if (typeof (json) === 'object' && json !== null && '__gppCall' in json)
{
var i = json.__gppCall;
window.__gpp(i.command, function (retValue, success)
{
var returnMsg = {
'__gppReturn': {
'returnValue': retValue,
'success' : success,
'callId' : i.callId
}
};
event.source.postMessage(msgIsString ? JSON.stringify(returnMsg) : returnMsg, '*');
},'parameter' in i? i.parameter: null, 'version' in i ? i.version : '1.1');
}
};
if (!('__gpp' in window) || (typeof (window.__gpp) !== 'function'))
{
window.__gpp = window.__gpp_stub;
window.addEventListener('message', window.__gpp_msghandler, false);
window.__gpp_addFrame('__gppLocator');
}
Example of determining vendor consent under TCF Canada The following example demonstrates how a vendor can listen to changes for IAB TCF Canada and find out if consent is given for a specific vendor or purpose.
if(__gpp)
{
__gpp('addEventListener', function (evt, success)
{
//callback will receive all events, we only want to react on signalStatus ready events
if(evt.eventName !== 'signalStatus' || evt.data !== 'ready')
{return ;}
//if only the GPP String is needed, it can be taken directly from pingData.gppString
var gppString = evt.pingData.gppString;
//get the data from the TCF Canada section
//Note: You might also want to check if TCF Canada is in the pingData.applicableSections
if ('tcfcav1' in evt.pingData.parsedSections)
{
var data = evt.pingData.parsedSections.tcfcav1;
var vendorConsent = data[0].VendorExpressConsent;
var vendorImpConsent = data[0].VendorImpliedConsent;
var purposeConsent = data[0].PurposesExpressConsent;
// ... do something Canadian !
}
});
}
The window.postMessage()
method may be used from a child iframe to make requests from a parent or any ancestor frame's CMP API. To locate an ancestor frame capable of responding to postMessage() CMP API calls, search for an ancestor frame that has a child frame named '__gppLocator'
.
CMPs shall create an event listener to handle postMessage requests via the CMP “stub” API script so that postMessage events can be queued and processed by the full-implementation of the CMP API as soon as it is initialized.
The sent message shall follow the form outlined below. The command, parameter and version object properties correspond to their namesake parameters defined as method argument parameters for __gpp()
method. The “sent message” also requires a unique callId
property to help match the request with a response. The callId property shall be either a string or a number, but the calling script shall not use the two types interchangeably.
{
__gppCall: {
command: 'command',
parameter: 'parameter,
version: '1.1',
callId: 'randomID'
}
}
The event.data
object payload shall follow the form outlined below. The returnValue
object property shall be the corresponding TC data object for the command used upon sending the “sent message”. The success object property shall reflect the __gpp()
success callback argument and the callId will correspond to the “sent message” unique id passed in the callId property.
{
__gppReturn: {
returnValue: returnValue,
success: boolean,
callId: uniqueId
}
}