Skip to content

Latest commit

 

History

History
1155 lines (926 loc) · 45.8 KB

CMP API Specification.md

File metadata and controls

1155 lines (926 loc) · 45.8 KB

Consent Management Platform API

Version History

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

Introduction

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.

About the Global Privacy Platform

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.

License

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.

About IAB Tech Lab

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/

CMP API

What does the CMP API support?

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.

API Prefixes

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

How does the CMP provide the API?

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.

What required API commands must a CMP support?

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’.

What is CMP ID?

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.


ping

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);

PingReturn

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

supportedAPIs : Array of string, // list of supported APIs (section ids and prefix strings), e.g. used while loading. Example: ["2:tcfeuv2","6:uspv1"] 

cmpId : Number, // IAB assigned CMP ID, may be 0 during stub/loading. Reference the above CMP ID section for additional information.

sectionList : Array of Number, // may be empty during loading of the CMP

applicableSections: Array of Number, // 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].

gppString: String // the complete encoded GPP string, may be empty during CMP load

parsedSections: Object // 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 (similar to getSection command). If a section is supported but not represented in the gppString, it is omitted in the parsedSections object.

}

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.

addEventListener

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);

EventListener

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

removeEventListener

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);

hasSection

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");

getSection

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:

[
 /* Core Sub-section */
 {
  Version:1, 
  Created: Date (Thu Apr 13 2023 18:07:12 GMT+0200),
  LastUpdated: 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],
  ...
  } 
 ]

getField

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");

What are non-generic commands?

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 getVendorListcommand 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.


In-App Details

How is a CMP used in-app?

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.

In-App Key Names

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.

Connected TV (CTV) Details

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.

Web Runtime

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

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.

Using the CMP API

Examples

Example stub code

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 !
  }
 });
}

How can vendors that use iframes call the CMP API from an iframe?

Using postmessage

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.

Sent Message

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
  }
}