Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"sourceMaps": true,
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-proposal-decorators", {"legacy": true}],
["@babel/plugin-transform-object-assign"],
["@babel/plugin-transform-react-jsx", {"pragma": "h"}],
["@babel/plugin-proposal-class-properties"],
["@babel/plugin-syntax-object-rest-spread"]
]
"sourceMaps": true,
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-transform-async-to-generator"],
["@babel/plugin-transform-object-assign"],
["@babel/plugin-transform-react-jsx", { "pragma": "h" }],
["@babel/plugin-proposal-class-properties"],
["@babel/plugin-syntax-object-rest-spread"]
]
}
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## [2.0.0](https://github.com/openmail/system1-cmp/compare/v1.5.6...v2.0.0) (2020-08-14)

### Refactor

- [x] Introduce new CMP based on TCF 2.0 framework

## [1.5.7](https://github.com/openmail/system1-cmp/compare/v1.5.6...v1.5.7) (2020-08-17)

### Fix

- [x] Default to hosted vendorlist since IAB removed their global v1 vendorlist
- [x] Check for IAB global vendor list location and remove if manually set
- [x] Add SameSite;secure cookie props for http and https

## [1.5.6](https://github.com/openmail/system1-cmp/compare/v1.5.5...v1.5.6) (2020-06-23)

### Translations
Expand Down
153 changes: 127 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
<img align="right" width="50" src="https://s.flocdn.com/@s1/ads-coordinator/reference/fa9924f562bd5be7831df8ca2d285b1f.gif" />

**Table of Contents** _generated with [DocToc](https://github.com/thlorenz/doctoc)_
# system1-cmp

- [system1-cmp](#system1-cmp)
- [Installation / Use](#installation--use)
- [API](#api)
- [Customized API](#customized-api)
- [init](#init)
- [showConsentTool](#showconsenttool)
- [changeLanguage](#changelanguage)
- [Background and Resources](#background-and-resources)
TCF 2.0 Consent Management Platform (CMP) UI tool. We are in the process of validating this CMP, we will update this repo once it passes TCF 2.0 validation.

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
[Reference Page and Demo](https://s.flocdn.com/cmp/test/tcf-2.0.html)

# system1-cmp
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

TCF 2.0 Consent Management Platform (CMP) UI tool. We are in the process of validating this CMP, we will update this repo once it passes TCF 2.0 validation. Use at your own risk.
- [Installation / Use](#installation--use)
- [API](#api)
- [Customized API](#customized-api)
- [init](#init)
- [onConsentAllChanged](#onconsentallchanged)
- [offConsentAllChanged](#offconsentallchanged)
- [showConsentTool](#showconsenttool)
- [changeLanguage](#changelanguage)
- [Configuration / Config](#configuration--config)
- [theme](#theme)
- [Background and Resources](#background-and-resources)
- [TODO](#todo)
- [Support Matrix](#support-matrix)
- [Contributing](#contributing)

[Reference Page and Demo](https://s.flocdn.com/cmp/test/tcf-2.0.html)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->

## Installation / Use

Expand All @@ -27,15 +33,15 @@ API signatures have changed from the CMP TCF 1.1, but we've tried to keep the co
```html
<script src="https://s.flocdn.com/cmp/test/tcf-2.0-loader.js"></script>
<script>
function onConsentUpdated(tcData, isSuccessful) {
var hasConsentedAll = document.cookie.indexOf('gdpr_opt_in=1') >= 0;
if (hasConsentedAll) {
console.log('cmp:onConsentUpdated: all consent achieved', tcData);
__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:onConsentUpdated: only some consent achieved', tcData);
console.log('cmp:onConsentAllChanged: only some consent achieved', store.tcData.tcString);
}
}
__tcfapi('addEventListener', 2, onConsentUpdated);
});

__tcfapi(
'init',
2,
Expand All @@ -44,7 +50,8 @@ API signatures have changed from the CMP TCF 1.1, but we've tried to keep the co
},
{
gdprApplies: true,
logging: true, // console logs
debugging: true, // console logs
logging: true, // pixel logs for monitoring
baseUrl: 'https://s.flocdn.com/cmp/test/config/2.0', // base url for vendor-lists
versionedFilename: 'vendor-list.json', // vendor list json
scriptSrc: 'https://s.flocdn.com/cmp/test/tcf-2.0-cmp.js', // cmp SDK
Expand All @@ -57,23 +64,30 @@ API signatures have changed from the CMP TCF 1.1, but we've tried to keep the co
secondaryColor: '#869cc0',
featuresColor: '#d0d3d7',
},
ccpaApplies: true,
gdprApplies: true,
consentRequired: true,
}
);
</script>
```

## API

Read more about [\_\_tcfapi built-in API](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/CMP%20JS%20API%20v1.1%20Final.md#what-api-will-need-to-be-provided-by-the-cmp-)
Read more about [\_\_tcfapi built-in API](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#cmp-api-v20)

- ping
- addEventListener
- removeEventListener
- getTCData
- getInAppTCData
- getVendorList

### Customized API

- [init](#init)
- [onConsentAllChanged](#onConsentAllChanged)
- [offConsentAllChanged](#offConsentAllChanged)
- [showConsentTool](#showConsentTool)
- [changeLanguage](#changeLanguage)

Expand All @@ -89,10 +103,42 @@ Calling `__tcfapi('init', 2, (store) => {})` will trigger the seed-file or loade
* @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);
```

### onConsentAllChanged

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.

```js
/**
* @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);
```

### offConsentAllChanged

Calling `__tcfapi('offConsentAllChanged', 2, cachedListener)` removes the listener setup in `__tcfapi('onConsentAllChanged')`.

```js
/**
* @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
```

### showConsentTool

Calling `__tcfapi('showConsentTool', 2, () => {})` will display the CMP UI.
Expand All @@ -108,17 +154,61 @@ __tcfapi('showConsentTool', 2, (store) => {});

### changeLanguage

Calling `__tcfapi('changeLanguage', 2, () => {})` will use cached version or load language dependencies and re-render the application in the desired language
Calling `__tcfapi('changeLanguage', 2, () => {}, language)` will use cached version or load language dependencies and re-render the application in the desired language

```js
/**
* @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) => {});
__tcfapi('changeLanguage', 2, (store) => {}, 'pt'); // changes to Portuguese
```

## Configuration / Config

Set configuration for your CMP during the `init` phase.

```js
__tcfapi('init', 2, () => {}, {
theme: {
maxHeightModal: '50vh',
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 numuber of 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. |
| `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 | empty | 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](#theme) | Override styling choices using the following properties. |
| `publisherCountryCode` | optional string | `US` | String representing country code of parent website business |

### theme

Override styling choices using the following properties:

- `maxHeightModal`: '50vh'
- `primaryColor`: '#0099ff'
- `textLinkColor`: '#0099ff'
- `secondaryColor`: '#869cc0'
- `featuresColor`: '#d0d3d7'

## Background and Resources

The UI layer is inspired by this [IAB TCF CMP UI Webinar presentation](https://iabeurope.eu/wp-content/uploads/2020/01/2020-01-21-TCF-v2.0-CMP-UI-Webinar.pdf).
Expand All @@ -141,6 +231,7 @@ Following Google's [Additional Consent Mode](https://support.google.com/admanage
- [ ] Auto-consent using [TC-string-passing](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20Consent%20string%20and%20vendor%20list%20formats%20v2.md#full-tc-string-passing)
- [ ] non-personalized performance and monitoring analytics
- [ ] Validate using the [TCF 2.0 validator extension](https://cmp-validator.consensu.org/chrome-extension/latest/IAB-Europe-CMP-Validator-User-Guide.pdf)
- [ ] Separate polyfill bundle, use babelrc instead of manually importing from core-js

## Support Matrix

Expand All @@ -160,3 +251,13 @@ Following Google's [Additional Consent Mode](https://support.google.com/admanage
| Android Chrome | ✔ Latest | ✢ Latest - 2 | | |
| Android Browser | | | | ✘ Default Browser |
| Opera | | | | ✘ |

## Contributing

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
```
4 changes: 2 additions & 2 deletions config/common.webpack.config.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import packageJson from '../package.json';

const ENV = process.env.NODE_ENV || 'development';
const CSS_MAPS = ENV !== 'production';
const { version } = packageJson;
const { name, version } = packageJson;

const uglifyPlugin = new webpack.optimize.UglifyJsPlugin({
output: {
Expand Down Expand Up @@ -168,4 +168,4 @@ const commonConfig = {
},
};

export { commonConfig, ENV, CSS_MAPS, version, uglifyPlugin };
export { commonConfig, ENV, CSS_MAPS, name, version, uglifyPlugin };
18 changes: 15 additions & 3 deletions config/s1.webpack.config.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import fs from 'fs';
import UglifyJS from 'uglify-es';
import HtmlWebpackPlugin from 'html-webpack-plugin';

import { commonConfig, uglifyPlugin, version } from './common.webpack.config.babel';
import { commonConfig, name, uglifyPlugin, version } from './common.webpack.config.babel';

const ENV = process.env.NODE_ENV || 'development';

Expand All @@ -29,14 +29,16 @@ module.exports = [
{
entry: {
cmp: './s1/cmp.js',
'tcf-2.0-loader': './s1/tcf-2.0-loader.js',
polyfills: './s1/polyfills.js',
// 'tcf-2.0-loader': './s1/tcf-2.0-loader.js',
'tcf-2.0-cmp': './s1/tcf-2.0-cmp.js',
},
...commonConfig,
output: {
path: path.resolve(__dirname, '../', `dist/${version}`),
publicPath: './',
filename: '[name].js',
publicPath: `https://s.flocdn.com/${name}/${version}/`,
// publicPath: './',
},
plugins: [
new webpack.DefinePlugin({
Expand Down Expand Up @@ -76,6 +78,16 @@ module.exports = [
},
},
]),
new CopyWebpackPlugin([
{
from: './s1/tcf-2.0-loader.js',
to: './tcf-2.0-loader.js',
transform(content) {
// Just want to uglify and copy this file over
return Promise.resolve(Buffer.from(UglifyJS.minify(content.toString()).code, 'utf8'));
},
},
]),
].concat(ENV === 'production' ? uglifyPlugin : []),
},
];
15 changes: 10 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "system1-cmp",
"version": "1.5.6",
"version": "2.0.0",
"description": "System1 Consent Management Platform for TCF 1.1 GDPR Compliance",
"scripts": {
"clean": "rimraf ./dist",
Expand All @@ -13,7 +13,7 @@
"deploy": "yarn clean && yarn deploy:original && yarn deploy:s1",
"build:original": "cross-env NODE_ENV=production webpack --progress --config config/webpack.config.babel.js",
"deploy:original": "yarn build:original && yarn upload:original",
"upload:original": "cross-var s3-deploy './dist/{*.?(js|html),docs/**}' --cwd './dist' --region us-west-2 --bucket s1-layout-cdn/cmp --gzip --cache 1440 --invalidate '/cmp/*.js /cmp/* /cmp/docs/*'",
"upload:original": "cross-var s3-deploy './dist/{*.?(js|html),docs/**}' --cwd './dist' --region us-west-2 --bucket s1-layout-cdn/cmp --gzip --cache 1440 --distId E5JQ1CRXXPTKM --invalidate '/cmp/*.js /cmp/* /cmp/docs/*'",
"build:s1": "cross-env NODE_ENV=production webpack --progress --config config/s1.webpack.config.babel.js",
"deploy:s1": "yarn build:s1 && yarn upload:s1",
"upload:s1": "cross-var s3-deploy './dist/$npm_package_version/**' --cwd './dist/$npm_package_version' --region us-west-2 --bucket s1-layout-cdn/cmp/$npm_package_version --gzip --preventUpdates --immutable",
Expand All @@ -28,7 +28,7 @@
},
"repository": {
"type": "git",
"url": "https://github.com/appnexus/cmp.git"
"url": "https://github.com/Openmail/system1-cmp.git"
},
"license": "Apache-2.0",
"author": "AppNexus",
Expand Down Expand Up @@ -59,6 +59,7 @@
"@babel/core": "^7.3.4",
"@babel/plugin-proposal-class-properties": "^7.3.4",
"@babel/plugin-proposal-decorators": "^7.3.0",
"@babel/plugin-transform-async-to-generator": "^7.10.4",
"@babel/plugin-transform-object-assign": "^7.2.0",
"@babel/plugin-transform-react-jsx": "^7.3.0",
"@babel/preset-env": "^7.3.4",
Expand Down Expand Up @@ -106,7 +107,7 @@
"dependencies": {
"@iabtcf/cmpapi": "^1.1.0-3",
"@iabtcf/core": "^1.1.0-3",
"@s1/dpl": "2.3.1",
"@s1/dpl": "3.0.15",
"classnames": "^2.2.5",
"codemirror": "^5.34.0",
"core-js": "^2.5.3",
Expand All @@ -129,11 +130,15 @@
"bundlesize": [
{
"path": "./dist/[0-9].[0-9].[0-9]/tcf-2.0-cmp.js",
"maxSize": "76.0 kB"
"maxSize": "50.0 kB"
},
{
"path": "./dist/[0-9].[0-9].[0-9]/tcf-2.0-loader.js",
"maxSize": "1.0 kB"
},
{
"path": "./dist/[0-9].[0-9].[0-9]/polyfills.js",
"maxSize": "15.0 kB"
}
]
}
Loading