Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## [2.1.1](https://github.com/openmail/system1-cmp/compare/2.1.0...2.1.1) (2020-09-30)

### Fix

- [x] auto-detect `config.language` and auto-load relevant language files during CMP initialization
- [x] configurable `config.theme.maxWidthModal`

## [2.1.0](https://github.com/openmail/system1-cmp/compare/2.0.4...2.1.0) (2020-09-23)

### Refactor
Expand Down
65 changes: 34 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Feel free to fork this CMP and submit to IAB for private use.
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->


- [SDK / Package Details](#sdk--package-details)
- [Installation / Use](#installation--use)
- [API](#api)
Expand Down Expand Up @@ -44,7 +45,7 @@ Feel free to fork this CMP and submit to IAB for private use.
See a [working example in codepen](https://codepen.io/potench/pen/GRZZprw).

```html
<script src="https://s.flocdn.com/cmp/2.1.0/tcf-2.0-loader.js"></script>
<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;
Expand All @@ -68,10 +69,10 @@ See a [working example in codepen](https://codepen.io/potench/pen/GRZZprw).
canLog: true,
canDebug: true,
isServiceSpecific: true, // on service-specific use supported right now
baseUrl: 'https://s.flocdn.com/cmp/2.1.0/config/2.0', // base url
scriptSrc: 'https://s.flocdn.com/cmp/2.1.0/tcf-2.0-cmp.js', // cmp SDK
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: 'en', // default
// language: '', // empty string or unset to default to browser language
shouldUseStacks: true,
// narrowedVendors: [1, 2, 3, 4, 5, 6],
theme: {
Expand Down Expand Up @@ -200,38 +201,40 @@ __tcfapi('init', 2, () => {}, {
});
```

| 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] |
| `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 |
| `isServiceSpecific` | optional boolean | `true` | true uses publisher consent, false uses global consent |
| `shouldUseStacks` | optional boolean | `true` | true uses stacks on Layer1, TODO stacks need purposes/custom-features toggle to be compliant |
| 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](#theme) | 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 |
| `shouldUseStacks` | optional boolean | `true` | true uses stacks on Layer1, TODO stacks need purposes/custom-features toggle to be compliant |

### theme

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` |
| `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` |
| `featuresColor` | optional string | null | Example: `#d0d3d7` |
| 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)` |
| `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` |
| `featuresColor` | optional string | null | Example: `#d0d3d7` |

## Initialize With Euconsent String from URL Param

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "system1-cmp",
"version": "2.1.0",
"cmpVersion": 4,
"version": "2.1.1",
"cmpVersion": 5,
"description": "System1 Consent Management Platform for TCF 1.1 GDPR Compliance",
"scripts": {
"clean": "rimraf ./dist",
Expand Down
2 changes: 1 addition & 1 deletion src/s1/components/banner/banner.less
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
width: calc(100% - 50px);
max-width: 750px;
max-width: 1024px;
margin: auto;

@media @smartphone {
Expand Down
2 changes: 2 additions & 0 deletions src/s1/components/banner/bannerStacks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export default class BannerStacks extends Component {
const {
isBannerModal,
isBannerInline,
maxWidthModal,
// maxHeightModal, // handled in store
primaryColor,
primaryTextColor,
Expand All @@ -163,6 +164,7 @@ export default class BannerStacks extends Component {
style={{
backgroundColor,
color: textLightColor,
...(maxWidthModal ? { maxWidth: maxWidthModal } : {}),
}}
>
<div
Expand Down
3 changes: 2 additions & 1 deletion src/s1/lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const theme = {
// boxShadow: 'none',
// secondaryColor: '#869cc0',
// featuresColor: '#d0d3d7',
// maxWidthModal: '500px',
shouldAutoResizeModal: true,
maxHeightModal: '45vh',
};
Expand All @@ -34,7 +35,7 @@ export const config = {
gdprApplies: false,
gdprConsentUrlParam,
isServiceSpecific: true, // whether or not this cmp is configured to be service specific
language: 'en',
language: '', // empty to detect browser navigator language
narrowedVendors: [],
publisherCountryCode: 'US',
shouldAutoConsent: false, // deprecated feature
Expand Down
62 changes: 34 additions & 28 deletions src/s1/lib/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { TCModel, TCString } from '@iabtcf/core';
import cookie from './cookie';
import config from './config';
import debug from './debug';
import localize from './localize';
import { findLangage, localize } from './localize';
import logger, { EVENTS as LOG_EVENTS } from './logger';
import { CONSENT_SCREENS, CUSTOM_EVENTS, LANGUAGES } from '../constants';

Expand Down Expand Up @@ -40,27 +40,28 @@ export default class Store {
...options,
theme,
shouldAutoResizeModal: theme.shouldAutoResizeModal,
maxHeightModal: theme.shouldAutoResizeModal ? 0 : theme.maxHeightModal,
});

const { language } = this.config;
const { tcfApi, gvl } = options;
const { readyPromise } = gvl;
const localizePromise = localize(language);
localizePromise.then((translations) => {
this.setState({
translations,
});
});

Promise.all([readyPromise, localizePromise])
.then(this.onReady.bind(this))
readyPromise
.then(() => {
// synchronous localization because iabtcf-es core lib requires initialization first
this.toggleLanguage(language)
.then(this.onReady.bind(this))
.catch((e) => {
logger(LOG_EVENTS.CMPError, {
message: `storeReadyError: toggleLanguage: ${e}`,
});
});
})
.catch((e) => {
logger(LOG_EVENTS.CMPError, {
message: `storeReadyError: ${e}`,
});
});

tcfApi('addEventListener', 2, this.onEvent.bind(this));
}

Expand Down Expand Up @@ -252,7 +253,7 @@ export default class Store {
const isSaveShowing = shouldShowSave !== undefined ? shouldShowSave : this.isSaveShowing;
const encodedTCString = TCString.encode(tcModelNew);
const shouldAutoResizeModal = isSaveShowing ? false : this.shouldAutoResizeModal;
const maxHeightModal = shouldAutoResizeModal ? this.maxHeightModal : this.theme.maxHeightModal;
const maxHeightModal = shouldShowSave ? this.theme.maxHeightModal : this.maxHeightModal;

const { vendorConsents, purposeConsents, specialFeatureOptins } = tcModelNew;
const { purposes, specialFeatures, vendors } = this.gvl;
Expand All @@ -274,8 +275,8 @@ export default class Store {
hasConsentedAll,
isSaveShowing,
hasSession,
shouldAutoResizeModal,
maxHeightModal,
shouldAutoResizeModal,
},
true
);
Expand Down Expand Up @@ -361,7 +362,7 @@ export default class Store {

save() {
// close the cmp and persist settings
this.updateCmp({ shouldShowModal: false, shouldSaveCookie: true, shouldShowSave: false, maxHeightModal: 0 });
this.updateCmp({ shouldShowModal: false, shouldSaveCookie: true, shouldShowSave: false });
}

toggleAll() {
Expand All @@ -372,7 +373,6 @@ export default class Store {
this.updateCmp({
tcModel,
shouldShowModal: false,
maxHeightModal: 0,
shouldSaveCookie: true,
shouldShowSave: false,
});
Expand Down Expand Up @@ -551,16 +551,20 @@ export default class Store {
}
}

toggleLanguage(language) {
toggleLanguage(langOpt, shouldLog) {
if (!this.gvl) {
return;
}

logger(LOG_EVENTS.CMPClick, {
action: 'click',
category: 'toggleLanguage',
label: language,
});
const { code: language } = findLangage(langOpt);

if (shouldLog) {
logger(LOG_EVENTS.CMPClick, {
action: 'click',
category: 'toggleLanguage',
label: language,
});
}

const localizePromise = localize(language);
localizePromise.then((translations) => {
Expand All @@ -570,13 +574,15 @@ export default class Store {
});

const gvlPromise = this.gvl.changeLanguage(language).then(() => {
const { language } = this.gvl;
const tcModel = this.tcModel.clone();
tcModel.consentLanguage = language;
this.updateCmp({
tcModel,
shouldShowModal: true,
});
if (this.tcModel) {
const { language } = this.gvl;
const tcModel = this.tcModel.clone();
tcModel.consentLanguage = language;
this.updateCmp({
tcModel,
shouldShowModal: true,
});
}
});

return Promise.all([gvlPromise, localizePromise]);
Expand Down
2 changes: 1 addition & 1 deletion src/s1/reference/tcf-2.0.html
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ <h3>TCFString</h3>
scriptSrc: './tcf-2.0-cmp.js', // cmp SDK
// polyfillSrc: './polyfills.js',
publisherCountryCode: 'US',
language: 'en', // default
// language: '', // default
shouldUseStacks: shouldUseStacks(),
// narrowedVendors: [1, 2, 3, 4, 5, 6],
};
Expand Down
2 changes: 1 addition & 1 deletion src/s1/tcf-2.0-cmp.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const setup = (configOpt) => {
},

[CHANGE_LANGUAGE]: (callback, language) => {
store.toggleLanguage(language).finally((result) => {
store.toggleLanguage(language, true).finally((result) => {
callback(store, result);
});
},
Expand Down