If you need some visuals to help you to implement our CMP, please check our tutorial video :
Be careful to insert correctly your script in the <body>
, otherwise you can have some loader.js issues as : core.bundle.js:1 Uncaught (in promise) undefined
In the left menu, click on "Notices".
Find the line of the notice you want to implement.
A window appears with the matching appKey
Use the copy icon on the right to copy your AppKey
The IAB STUB is a common block of code that rules some mandatories behaviors for CMP.
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Your Website</title><!-- MANDATORY: BEGIN IAB STUB --><script type="text/javascript">"use strict";!function(){var e=function(){var e,t="__tcfapiLocator",a=[],n=window;for(;n;){try{if(n.frames[t]){e=n;break}}catch(e){}if(n===window.top)break;n=n.parent}e||(!function e(){var a=n.document,r=!!n.frames[t];if(!r)if(a.body){var s=a.createElement("iframe");s.style.cssText="display:none",s.name=t,a.body.appendChild(s)}else setTimeout(e,5);return!r}(),n.__tcfapi=function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return a;if("setGdprApplies"===n[0])n.length>3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0));else if("ping"===n[0]){var s={gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"};"function"==typeof n[2]&&n[2](s)}else a.push(n)},n.addEventListener("message",(function(e){var t="string"==typeof e.data,a={};try{a=t?JSON.parse(e.data):e.data}catch(e){}var n=a.__tcfapiCall;n&&window.__tcfapi(n.command,n.version,(function(a,r){var s={__tcfapiReturn:{returnValue:a,success:r,callId:n.callId}};t&&(s=JSON.stringify(s)),e&&e.source&&e.source.postMessage&&e.source.postMessage(s,"*")}),n.parameter)}),!1))};"undefined"!=typeof module?module.exports=e:e()}();</script><!-- MANDATORY: END IAB STUB -->
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Your Website</title><!-- MANDATORY: BEGIN IAB STUB --><script type="text/javascript">"use strict";!function(){var e=function(){var e,t="__tcfapiLocator",a=[],n=window;for(;n;){try{if(n.frames[t]){e=n;break}}catch(e){}if(n===window.top)break;n=n.parent}e||(!function e(){var a=n.document,r=!!n.frames[t];if(!r)if(a.body){var s=a.createElement("iframe");s.style.cssText="display:none",s.name=t,a.body.appendChild(s)}else setTimeout(e,5);return!r}(),n.__tcfapi=function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return a;if("setGdprApplies"===n[0])n.length>3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0));else if("ping"===n[0]){var s={gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"};"function"==typeof n[2]&&n[2](s)}else a.push(n)},n.addEventListener("message",(function(e){var t="string"==typeof e.data,a={};try{a=t?JSON.parse(e.data):e.data}catch(e){}var n=a.__tcfapiCall;n&&window.__tcfapi(n.command,n.version,(function(a,r){var s={__tcfapiReturn:{returnValue:a,success:r,callId:n.callId}};t&&(s=JSON.stringify(s)),e&&e.source&&e.source.postMessage&&e.source.postMessage(s,"*")}),n.parameter)}),!1))};"undefined"!=typeof module?module.exports=e:e()}();</script><!-- MANDATORY: END IAB STUB --></head><body><!-- AppConsent CMP script --><script src="https://cdn.appconsent.io/loader.js" defer async></script><!-- AppConsent CMP script -->
You can give a better look to your CMP with Bootstraps
<script type="text/javascript">__tcfapi('init', 2, console.log, {appKey: 'YOUR_APPKEY_HERE',})</script><!-- Replace with YOUR appKey got from the Backoffice -->
You can put this part underneath your CMP script :
<script type="text/javascript">__tcfapi('show', 2, console.log, {lazy: true,})</script>
Congratulation ! You have now finished to implementing the CMP, your code must look like that:
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Your Website</title><!-- MANDATORY: BEGIN IAB STUB --><script type="text/javascript">"use strict";!function(){var e=function(){var e,t="__tcfapiLocator",a=[],n=window;for(;n;){try{if(n.frames[t]){e=n;break}}catch(e){}if(n===window.top)break;n=n.parent}e||(!function e(){var a=n.document,r=!!n.frames[t];if(!r)if(a.body){var s=a.createElement("iframe");s.style.cssText="display:none",s.name=t,a.body.appendChild(s)}else setTimeout(e,5);return!r}(),n.__tcfapi=function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return a;if("setGdprApplies"===n[0])n.length>3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0));else if("ping"===n[0]){var s={gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"};"function"==typeof n[2]&&n[2](s)}else a.push(n)},n.addEventListener("message",(function(e){var t="string"==typeof e.data,a={};try{a=t?JSON.parse(e.data):e.data}catch(e){}var n=a.__tcfapiCall;n&&window.__tcfapi(n.command,n.version,(function(a,r){var s={__tcfapiReturn:{returnValue:a,success:r,callId:n.callId}};t&&(s=JSON.stringify(s)),e&&e.source&&e.source.postMessage&&e.source.postMessage(s,"*")}),n.parameter)}),!1))};"undefined"!=typeof module?module.exports=e:e()}();</script><!-- MANDATORY: END IAB STUB --></head><body><!-- AppConsent CMP script --><script src="https://cdn.appconsent.io/loader.js" defer async></script><!-- AppConsent CMP script --><!-- BEGIN Trigger the CMP --><script type="text/javascript">__tcfapi('init', 2, console.log, {appKey: 'YOUR_APPKEY_HERE',})</script><script type="text/javascript">__tcfapi('show', 2, console.log, {lazy: true,})</script><!-- Replace with YOUR appKey got from the Backoffice --><!-- END Trigger the CMP --></body></html>
Now that you have implemented your CMP you can put some extra commands or settings by reading the following instructions.
Passing commands in URL
You can pass commands to the CMP through the querystring. Querystring commands are evaluated on init.
?ac_cmd=show
The above link would show the CMP on init.
You can also pass parameters to the command with the same mechanism. Parameters are passed as is from the querystring. Consider the following example:
?ac_cmd=show&jumpAt=banner
CMP can be controlled through iAB's __tcfApi
global function, as documented.
Custom calls are providen to operate the CMP, like displaying it, activating programmatic consent and so on. All Custom calls are asynchronous functions receiving an error-first callback and optional arguments, as follow:
Init the CMP with AppConsent credentials and additionnal configurations.
argument name | type | optional | value |
command | string | |
|
version | number | |
|
callback | function | |
|
parameter | Object | | Configuration |
Callback returns the CMP's state, retrieved from either LocalStorage or server. State contains Consent and Vendorlist. This command performs at most one server call.
Basic Example
__tcfapi('init', 2, console.log, {appKey: 'YOUR_APPKEY',})
__tcfapi('init', 2, console.log, {appKey: '123',i18n: {buttons_acceptAll: { values: { en: 'ALL THE STUFF MAN' } },},})
__tcfapi('init', 2, console.log, {appKey: 'appKey',uuid: 'YOUR_ID_ABCD12345678',debug: true,storage: true,i18n: {banner_title: { values: { fr: 'Démo i18n' } },buttons_acceptAll: { values: { fr: 'Démo i18n Accept' } },},})
/*** Configuration holds settings for the current CMP instance* Can be overriden by passing it to the init custom command*/export var configuration = {/*** string - 🛂 MANDATORY credentials for the AppConsent API*/appKey: null,/*** true - activate verbose logging in the browser's console*/debug: false,/*** true - show keys instead of traductions for i18n keys*/debugI18n: false,/*** true - Force static fallback, bypassing the AppConsent API.*/forceStatic: false,/*** true - Force iAB global mode operation. Consent is stored on .consensu.org*/global: false,/*** Object - Overrides translation keys*/i18n: {},/*** string - URL to the static fallback of the AppConsent Vendorlist.*/"static": null,/*** true - Use the localstorage (default)* false - localstorage is ignored* Function - retrieve a Storage object from this function* TODO see the section: "No section here"*/storage: true,/*** string - domain of the AppConsent API*/url: '',/*** string - overrides AppConsent's uuid generation*/uuid: null};
Static mode
A static example file can be found here: collector-fr.json
Displays the CMP for collecting user consents.
argument name | type | optional | value |
command | string | |
|
version | number | |
|
callback | function | |
|
parameter | Object | | ShowOption |
ShowOption = {/*** true - If a consent if present, won't bother the user* false (default) - Show the banner no matter what*/lazy: Boolean,/*** null, 'banner'* 'privacy'*/jumpAt: string}
Example:
__tcfapi('show', 2, console.log, {lazy: false,})
Example:
__tcfapi('show', 2, console.log, {jumpAt: 'privacy',})
Registers a full consent on the CMP, as the user would have clicked on the "accept everyhting" button. The default behavior is to prevent overwriting any existing consent. You can force overwriting by specifying a special force
parameter.
Note that no matter the outcome, this call will hide the UI.
argument name | type | optional | value |
command | string | |
|
version | number | |
|
callback | function | |
|
parameter | Object | | AcceptOption |
AcceptOption = {/*** true - Overwrite any consent by an "accept all" one* false (default) - "accept all" unless a consent is already defined*/force: Boolean,}
Example:
__tcfapi('accept', 2, console.log)
argument name | type | optional | value |
command | string | |
|
version | number | |
|
callback | function | |
|
parameter | | | |
Example:
__tcfapi('deny', 2, console.log)
Forge a deny consentstring and return it to all vendors, without saving it as a user legitimate consent. This is useful to prevent unhonorable vendors from assuming lack of consent is one. This WONT hide the UI.
argument name | type | optional | value |
command | string | |
|
version | number | |
|
callback | function | |
|
parameter | | | |
Example:
__tcfapi('fakedeny', 2, console.log)
We're leveraging chunking to alleviate bandwith. Code for the UI is only downloaded when user interaction is needed. Beside, we do have a nice size report.
We've decided to not support directly tag managers, as implementation and usages varies. We strongly encourage you to use the standard TCF v2 API to achieve consent resolution for your tags. But it's very easy to interract with them.
For example, a GTM implementation could look like this, provided we only strive for a full consent:
__tcfapi('getTCData', 2, (tcData, ok) => {if(ok) {for (var c in tcData.purpose.consents) {if (tcData.purpose.consents[c]) {// Push events to GTMwindow.dataLayer.push({ event: 'purpose_' + c })}}}});
Or for Tag Commander:
__tcfapi('getTCData', 2, (tcData, ok) => {if(ok) {var tcVars = {}for (var c in tcData.purpose.consents) {if (tcData.purpose.consents[c]) {// Build a TagCommander events objecttcVars['purpose_' + c] = '1'}}// Push events to Tag Commanderwindow.tcEvents(null, 'sfbx_consent_action', tcVars)}});
Very simple exemple :
__tcfapi('getTCData', 2, (tcData, success) => {if(success) {console.log(tcData.tcString)} else {// do something else}});
Will output your tcString V2 in your console :
CO3czkfO3czkfACAGAFRArCgAL_AAD_AAAqIGBtX_T5eb2vje3Zdt9tkaYwf55y3o-wjhgaIse8NwIeH7BoGL2MwvBX4JiQCGBAEEiKBAQdlHGBcCQAAgIgBiTKMYk2MCzNKJLJAilMbc0NYCC1mnsHTmZCY7068O__zv3eBghBJgqXgEiQthASTZpRCmACEcQFSDgEoIQgIFLDQAEBOwKAj1AAAAQGAAEAAAAIIICAQACAABIRAAAAICAUAEQCAAEAI0BCAAiQIBYASJAEAAqBoSAEUQQgCEHBgFHKIEBQAAAAA.YAAAAAAAAAAA
More information in the official IAB Documentation : https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#how-does-the-cmp-provide-the-api