System1's implementation of IAB's Transparency and Consent 2.0 Consent Management Platform. A TCF 2.0 compliant CMP that passes all IAB compliance checks and has been validated to participate as a CMP for private use as CMP 38.
This CMP passes technical and policy compliance checks, but that does not necessarily guarantee legal compliance. Each organisation must make their own assessment of whether they are compliant with the law.
Feel free to fork this CMP and submit to IAB for private use.
- SDK / Package Details
- Installation / Use
- API
- Configuration / Config
- Initialize With Euconsent String from URL Param
- Background and Resources
- TODO
- Support Matrix
- Contributing
tcf-2.0-loader.js
is < 1kb. It loads the CMP sdk and dynamically checks compatibility and loads the polyfill if necessary.tcf-2.0-cmp.js
is < 50kb. It contains the TCF 2.0 framework (core/api), UI layer for interacting with the CMP, and custom store for persisting choices.polyfills.js
is < 15kb. It contains polyfills required for the CMP to function in IE11.
See a working example in codepen.
<script src="https://s.flocdn.com/cmp/2.1.1/tcf-2.0-loader.js"></script>
<script>
__tcfapi('onConsentAllChanged', 2, function (store) {
const hasConsented = document.cookie.indexOf('gdpr_opt_in=1') >= 0;
if (hasConsented) {
console.log('cmp:onConsentAllChanged: all consent achieved', store.tcData.tcString);
} else {
console.log('cmp:onConsentAllChanged: only some consent achieved', store.tcData.tcString);
}
});
__tcfapi(
'init',
2,
function (store, error) {
console.log('initialization complete', store, error);
},
{
business: 'business:unit',
gdprApplies: true, // true for EU false for CA
ccpaApplies: false, // true for CA false for EU
canLog: true,
canDebug: true,
isServiceSpecific: true, // on service-specific use supported right now
baseUrl: 'https://s.flocdn.com/cmp/2.1.1/config/2.0', // base url
scriptSrc: 'https://s.flocdn.com/cmp/2.1.1/tcf-2.0-cmp.js', // cmp SDK
publisherCountryCode: 'US',
// language: '', // empty string or unset to default to browser language
shouldUseStacks: true,
isSlimMode: true,
// narrowedVendors: [1, 2, 3, 4, 5, 6],
theme: {
boxShadow: 'none',
featuresColor: '#d0d3d7',
maxHeightModal: '40vh',
primaryColor: '#0099ff',
secondaryColor: '#869cc0',
shouldAutoResizeModal: true, // resizes modal on stacks screen to push stacks below fold
textLinkColor: '#0099ff',
isFullWidth: false,
},
}
);
</script>
Read more about __tcfapi built-in API
- ping
- addEventListener
- removeEventListener
- getTCData
- getInAppTCData
- getVendorList
Calling __tcfapi('init', 2, (store) => {})
will trigger the seed-file or loader to async load the larger CMP UI application. Once loaded, the cmp library calls init
function to load additional dependencies and render the application.
init
callback should be called regardless of internal errors as errors need to be handled gracefully internally to not disrupt the parent website.
/**
* @param 'init' // required string command
* @param apiVersion // required number, 2, version of api in use,
* @param callback // required function, called when init completes, called with `store`
* @param configurationOptions // optional object, used customize the CMP
* @return void
*/
__tcfapi('init', apiVersion, callback, configurationOptions);
Calling __tcfapi('onConsentAllChanged', 2, (store) => {})
triggers the callback whenever the gdpr_opt_in
cookie changes.
We track an all-or-nothing hasConsentedAll
mode so you can more easily toggle an anonymous mode on your website.
/**
* @param 'onConsentAllChanged' // required string command
* @param apiVersion // required number, 2, version of api in use,
* @param callback // required function, called when gdpr_opt_in value changes from undefined (no consent yet), 1 (contented all), 0 (declined anything)
* @return cachedListener // cache the callback if you need to remove this listener later
*/
const cachedListener = __tcfapi('onConsentAllChanged', apiVersion, callback);
Calling __tcfapi('offConsentAllChanged', 2, cachedListener)
removes the listener setup in __tcfapi('onConsentAllChanged')
.
/**
* @param 'onConsentAllChanged' // required string command
* @param apiVersion // required number, 2, version of api in use,
* @param cachedListener // optional function, include to remove a specific listener that was setup with `onConsentAllChanged`
* @return void
*/
const cachedListener = __tcfapi('onConsentAllChanged', apiVersion, callback);
__tcfapi('offConsentAllChanged', apiVersion, cachedListener); // remove a specific event listener
__tcfapi('offConsentAllChanged', apiVersion); // remove all `onConsentAllChanged` event listeners
Calling __tcfapi('showConsentTool', 2, () => {})
will display the CMP UI.
/**
* @param 'showConsentTool' // required string command
* @param apiVersion // required number 2
* @param callback // required function, called when showConsentTool complete, called with `store`
*/
__tcfapi('showConsentTool', 2, (store) => {});
Calling __tcfapi('changeLanguage', 2, () => {}, language)
will use cached version or load language dependencies and re-render the application in the desired language
/**
* @param 'changeLanguage' // required string command
* @param apiVersion // required number 2
* @param callback // required function, called when changeLanguage completes, called with `store` and result
* @param language // required string, 2-letter language-code en,bg,ca,cs,da,de... etc. See constants.js file for supported languages
*/
__tcfapi('changeLanguage', 2, (store) => {}, 'pt'); // changes to Portuguese
Calling __tcfapi('changeConfig', 2, () => {}, {isSlimMode: true, theme: {isInlineMode: false}})
will update config values and rerender CMP UI
/**
* @param 'changeConfig' // required string command
* @param apiVersion // required number 2
* @param callback // required function, called when changeLanguage completes, called with `store` and result
* @param config // required object, merges with existing config object providing during `init()`
*/
__tcfapi('changeConfig', 2, (store) => {}, { theme: { isInlineMode: false } }); // changes config to use inline-mode
Set configuration for your CMP during the init
phase.
__tcfapi('init', 2, () => {}, {
theme: {
maxHeightModal: '50vh',
shouldAutoResizeModal: true,
primaryColor: '#0099ff',
},
canLog: true, // pixel logging for monitoring and alerting
canDebug: false, // console.logs for dev debugging
narrowedVendors: [1, 2, 3, 4, 5], // only show a select vendors
cookieDomain: '', // which domain to set the euconsent and gdpr_opt_in cookie on
});
Config Property | Type | Default | Detail |
---|---|---|---|
canLog |
optional boolean | false |
true enables DPL logging for health monitoring. Add #s1&debug=true to URL for easy DPL debugging |
canDebug |
optional boolean | false |
true enables internal console logging for debugging |
baseUrl |
optional string | ./config/2.0 |
relative or absolute url to load the global vendor list. Combines with versionedFilename to load vendorlist. |
versionedFilename |
optional string | vendor-list.json |
file name of the global vendor list. |
narrowedVendors |
optional array | [] |
Only show select vendors. Example [1,4,5,19] |
language |
optional string | null | 2-character language code to initialize CMP with. If no language matches, CMP boots with en Ex 'en', 'ja', 'it' |
languageFilename |
optional string | purposes/purposes-[LANG].json |
file name template for gvl localized purpose json files |
translationFilename |
optional string | translations/translations-[LANG].json |
file name template for custom localized json files for UI layer |
cookieDomain |
optional string | null | manage consent across subdomains. Example .mysite.com |
gdprApplies |
optional boolean | false |
Please pass true if being used on EU traffic where active consent is required |
ccpaApplies |
optional boolean | false |
Please pass true if being used on USA:CA traffic where "Do Not Sell" initiates CMP passively |
experimentId |
optional string | control |
use to indicate changes / upgrades in your CMP implementation for reporting / monitoring purposes. |
business |
optional string | dev |
used to correlate CMP events for monitoring across a businessline. |
theme |
optional object | details below | Override styling choices using the following properties. |
publisherCountryCode |
optional string | US |
String representing country code of parent website business |
isServiceSpecific |
optional boolean | true |
true uses publisher consent, false uses global consent |
shouldAutoShowModal |
optional boolean | true |
true will automatically display UI modal after init, false will not |
shouldAlwaysShowSaveButton |
optional boolean | false |
true will always show the save button on the UI. False will only display the save button when a change is made |
shouldUseStacks |
optional boolean | true |
true uses stacks on Layer1, TODO stacks need purposes/custom-features toggle to be compliant |
isSlimMode |
optional boolean | false |
If true , initial banner is low profile, full width banner v2.1.4+ |
shouldShowCloseX |
optional boolean | false |
If true , a × icon will appear in the upper right on layers to accept-all and close v2.1.4+ |
insertionNode |
optional string | <body> |
UI will be appended to this element using querySelector . Default behavior appends to body v2.2.0+ |
Themeing is a bit limited right now. Pass in a config.theme
object during initialization. Use the following to override styling choices:
Theme Property | Type | Default | Detail |
---|---|---|---|
maxHeightModal |
optional string | 45vh |
CSS style for max height of the CMP UI. Example: 45vh , 50% , 350px |
maxWidthModal |
optional string | 1024px |
CSS style for max width of the CMP UI. Example: 1024px , calc(90% - 100px) |
maxHeightInline |
optional string | 200px |
CSS style to force max-height of CMP UI while in isBannerInline mode only. |
shouldAutoResizeModal |
optional boolean | true | Auto detects Layer1 height to minimize UI. UI resizes to maxHeightModal upon interaction |
primaryColor |
optional string | null | Example: #0099ff |
textLinkColor |
optional string | null | Example: #0099ff |
secondaryColor |
optional string | null | Example: #869cc0 |
featuresColor |
optional string | null | Example: #d0d3d7 |
backgroundColor |
optional string | null | Example: #d0d3d7 Sets the background color of the banners. v2.1.4+ |
isFullWidth |
optional boolean | false | Removes rounded corners and makes banners full width - matching style layout slimMode v2.1.4+ |
isBannerInline |
optional boolean | false | Renders CMP inline instead of overlaying layout. Subsequent CMP views open in modal v2.2.0+ |
shouldShowDropShadow |
optional boolean | true | When set to true , displays the drop shadoq on banners v2.1.4+ |
We can leverage the spec provided for URL-based services to process the TC String when it can't execute JavaScript to pass along consent when domains are owned by the same entity.
Using a URLParam gdpr_consent
you can pass consent to another domain that is using this CMP.
?gdpr_consent=${TC_STRING}
The CMP will use ?gdpr_consent
URLParam to automatically persist consent and trigger consent change-events if there is not already an existing consent signal stored in the EUConsent cookie.
The UI layer is inspired by this IAB TCF CMP UI Webinar presentation.
This CMP leverages the core, cmpapi, and stub modules from IAB's official TCF 2.0 JS SDK iabtcf-es.
The component library was forked and edited from the original TCF 1.0 CMP by AppNexus.
Following Google's Additional Consent Mode and Interoperability guidance for vendors this CMP provides cached versions of the vendor-list-test-google and standard vendor-list vendor list.
- Write Unit Tests and Integration Tests
- Improve Theming
- Implement global-scope and group-scope
- Updated hosted iframe for TCF 2.0
- Delete unused TCF 1.1 and reorganize
✔ Level 1
: Tested and fully supported, all functional and visual bugs should be fixed.✢ Level 2
: Untested or Partially tested, functional bugs reported are fixed, visual appearance may differ.✳ Level 3
: A separate solution or codebase exists to support this browser✘ Not Supported
: Untested tested, functional bugs expected and not fixed.
Browser | ✔ Level 1 | ✢ Level 2 | ✳ Level 3 | ✘ Not Supported |
---|---|---|---|---|
Chrome | ✔ Latest | ✢ Latest - 2 | ||
Safari | ✔ Latest | ✢ Latest - 2 | ||
Edge | ✔ Latest | ✢ Latest - 2 (Win10) | ||
IE | ✔ IE11 (Win8.1) | ✢ IE11(Win7 / Metro) | ✘ IE10, IE9,... | |
Firefox | ✔ Latest | ✢ Latest - 2 | ||
iOS Safari | ✔ Latest | ✢ Latest - 2 | ||
Android Chrome | ✔ Latest | ✢ Latest - 2 | ||
Android Browser | ✘ Default Browser | |||
Opera | ✘ |
For now the TCF 1.1 and TCF 2.0 CMPs both live in this repository. We will deprecate and remove TCF 1.1 and update all tests against the new 2.0 package. To contribute, make updates to the files in src/s1
.
yarn
yarn dev
# browse to http://localhost:8080/tcf-2.0.html
IAB updates the vendor list every Friday. Use the included to script to automatically upgrade all vendor-lists. Commit, merge, publish the changes to take effect.
yarn upgrade-vendor-list