@financial-times/cmp-client 2.0.4 → 2.0.5-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +3 -63
- package/dist/client.d.ts.map +1 -0
- package/dist/consent-ready/index.d.ts +5 -0
- package/dist/consent-ready/index.d.ts.map +1 -0
- package/dist/consent-ready/utils/__fixtures__/strings.d.ts +9 -0
- package/dist/consent-ready/utils/__fixtures__/strings.d.ts.map +1 -0
- package/dist/consent-ready/utils/__tests__/check-consent.test.d.ts +2 -0
- package/dist/consent-ready/utils/__tests__/check-consent.test.d.ts.map +1 -0
- package/dist/consent-ready/utils/__tests__/get-parsed-consent.test.d.ts +2 -0
- package/dist/consent-ready/utils/__tests__/get-parsed-consent.test.d.ts.map +1 -0
- package/dist/consent-ready/utils/__tests__/validators.test.d.ts +2 -0
- package/dist/consent-ready/utils/__tests__/validators.test.d.ts.map +1 -0
- package/dist/consent-ready/utils/get-consent-payload.d.ts +18 -0
- package/dist/consent-ready/utils/get-consent-payload.d.ts.map +1 -0
- package/dist/consent-ready/utils/get-parsed-consent.d.ts +14 -0
- package/dist/consent-ready/utils/get-parsed-consent.d.ts.map +1 -0
- package/dist/consent-ready/utils/has-consent-changed.d.ts +3 -0
- package/dist/consent-ready/utils/has-consent-changed.d.ts.map +1 -0
- package/dist/consent-ready/utils/validators.d.ts +16 -0
- package/dist/consent-ready/utils/validators.d.ts.map +1 -0
- package/dist/html/__tests__/cmp-footer-links.test.d.ts +2 -0
- package/dist/html/__tests__/cmp-footer-links.test.d.ts.map +1 -0
- package/dist/html/cmp-footer-link.d.ts +8 -0
- package/dist/html/cmp-footer-link.d.ts.map +1 -0
- package/dist/html/cmp-scripts.d.ts +16 -0
- package/dist/html/cmp-scripts.d.ts.map +1 -0
- package/dist/{client.cjs → index.cjs} +409 -158
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/{client.js → index.js} +408 -157
- package/dist/lib/constants.d.ts +13 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/{debug.d.ts → lib/debug.d.ts} +12 -13
- package/dist/lib/debug.d.ts.map +1 -0
- package/dist/{properties.d.ts → lib/properties.d.ts} +17 -19
- package/dist/lib/properties.d.ts.map +1 -0
- package/dist/utils/dom.d.ts +3 -0
- package/dist/utils/dom.d.ts.map +1 -0
- package/package.json +20 -30
- package/typings/globals.d.ts +20 -0
- package/typings/modules.d.ts +1 -0
- package/typings/types.d.ts +88 -0
- package/dist/debug.cjs +0 -32
- package/dist/debug.js +0 -32
- package/dist/properties.cjs +0 -21
- package/dist/properties.js +0 -21
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __publicField = (obj, key, value) => {
|
|
5
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
|
+
return value;
|
|
7
|
+
};
|
|
8
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
2
9
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const properties = require("./properties.cjs");
|
|
4
10
|
const request = (url, { credentials = "omit" } = {}) => {
|
|
5
11
|
return fetch(`https://session-next.ft.com${url}`, {
|
|
6
12
|
credentials,
|
|
@@ -71,10 +77,68 @@ const getUuid = () => {
|
|
|
71
77
|
}
|
|
72
78
|
return requests.uuid;
|
|
73
79
|
};
|
|
80
|
+
const SOURCEPOINT_CONSENT_SOURCE = "sourcepoint-cmp";
|
|
81
|
+
const SOURCEPOINT_FOW_SCOPE = "FTPINK";
|
|
82
|
+
const CONSENT_COOKIE_NAME = "FTConsent";
|
|
83
|
+
const SOURCEPOINT_FOW_ID = "sourcepointCmp/VngD.XycZut.595cp9fWdp5XYP9vlFvk";
|
|
84
|
+
const FT_COOKIE_DOMAIN = ".ft.com";
|
|
85
|
+
const FT_CONSENT_PROXY_HOST = "https://consent.ft.com";
|
|
86
|
+
const legislation = {
|
|
87
|
+
CCPA: "ccpa",
|
|
88
|
+
GDPR: "gdpr"
|
|
89
|
+
};
|
|
90
|
+
const iabCustomCategories = {
|
|
91
|
+
permutiveAds: {
|
|
92
|
+
purposes: [2, 4, 8, 9],
|
|
93
|
+
iabVendors: [361],
|
|
94
|
+
customVendors: [],
|
|
95
|
+
specialFeatures: []
|
|
96
|
+
},
|
|
97
|
+
demographicAds: {
|
|
98
|
+
purposes: [3, 4, 7, 9, 10],
|
|
99
|
+
iabVendors: [],
|
|
100
|
+
customVendors: [],
|
|
101
|
+
specialFeatures: []
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const defaults = {
|
|
105
|
+
joinHref: true,
|
|
106
|
+
gdpr: {},
|
|
107
|
+
ccpa: {}
|
|
108
|
+
};
|
|
109
|
+
const FT_DOTCOM_LOCAL = {
|
|
110
|
+
...defaults,
|
|
111
|
+
accountId: 1906,
|
|
112
|
+
baseEndpoint: "https://cdn.privacy-mgmt.com",
|
|
113
|
+
propertyHref: "https://local.ft.com"
|
|
114
|
+
};
|
|
115
|
+
const FT_DOTCOM_PROD = {
|
|
116
|
+
...defaults,
|
|
117
|
+
accountId: 1906,
|
|
118
|
+
baseEndpoint: "https://cdn.privacy-mgmt.com",
|
|
119
|
+
propertyId: 31642
|
|
120
|
+
};
|
|
121
|
+
const properties = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
122
|
+
__proto__: null,
|
|
123
|
+
FT_DOTCOM_LOCAL,
|
|
124
|
+
FT_DOTCOM_PROD
|
|
125
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
126
|
+
function createContentScript(content) {
|
|
127
|
+
const s = document.createElement("script");
|
|
128
|
+
s.innerHTML = content;
|
|
129
|
+
return s;
|
|
130
|
+
}
|
|
131
|
+
function createSourceScript(src) {
|
|
132
|
+
const s = document.createElement("script");
|
|
133
|
+
s.src = src;
|
|
134
|
+
return s;
|
|
135
|
+
}
|
|
74
136
|
function encodeConfig(obj) {
|
|
75
137
|
let str = "";
|
|
138
|
+
if (!obj)
|
|
139
|
+
return str;
|
|
76
140
|
for (const [key, val] of Object.entries(obj)) {
|
|
77
|
-
switch (typeof
|
|
141
|
+
switch (typeof val) {
|
|
78
142
|
case "function":
|
|
79
143
|
str += `${key}:${val.toString().replace(/"/g, "'").replace(/\s/g, "")},`;
|
|
80
144
|
break;
|
|
@@ -102,13 +166,42 @@ const scriptContent = {
|
|
|
102
166
|
tcfStub: `"use strict";function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}!function(){var t=function(){var t,e,o=[],n=window,r=n;for(;r;){try{if(r.frames.__tcfapiLocator){t=r;break}}catch(t){}if(r===n.top)break;r=r.parent}t||(!function t(){var e=n.document,o=!!n.frames.__tcfapiLocator;if(!o)if(e.body){var r=e.createElement("iframe");r.style.cssText="display:none",r.name="__tcfapiLocator",e.body.appendChild(r)}else setTimeout(t,5);return!o}(),n.__tcfapi=function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return o;"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)):"ping"===n[0]?"function"==typeof n[2]&&n[2]({gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"}):o.push(n)},n.addEventListener("message",(function(t){var e="string"==typeof t.data,o={};if(e)try{o=JSON.parse(t.data)}catch(t){}else o=t.data;var n="object"===_typeof(o)&&null!==o?o.__tcfapiCall:null;n&&window.__tcfapi(n.command,n.version,(function(o,r){var a={__tcfapiReturn:{returnValue:o,success:r,callId:n.callId}};t&&t.source&&t.source.postMessage&&t.source.postMessage(e?JSON.stringify(a):a,"*")}),n.parameter)}),!1))};"undefined"!=typeof module?module.exports=t:t()}();`,
|
|
103
167
|
uspStub: `"use strict";(function () { var e = false; var c = window; var t = document; function r() { if (!c.frames["__uspapiLocator"]) { if (t.body) { var a = t.body; var e = t.createElement("iframe"); e.style.cssText = "display:none"; e.name = "__uspapiLocator"; a.appendChild(e) } else { setTimeout(r, 5) } } } r(); function p() { var a = arguments; __uspapi.a = __uspapi.a || []; if (!a.length) { return __uspapi.a } else if (a[0] === "ping") { a[2]({ gdprAppliesGlobally: e, cmpLoaded: false }, true) } else { __uspapi.a.push([].slice.apply(a)) } } function l(t) { var r = typeof t.data === "string"; try { var a = r ? JSON.parse(t.data) : t.data; if (a.__cmpCall) { var n = a.__cmpCall; c.__uspapi(n.command, n.parameter, function (a, e) { var c = { __cmpReturn: { returnValue: a, success: e, callId: n.callId } }; t.source.postMessage(r ? JSON.stringify(c) : c, "*") }) } } catch (a) { } } if (typeof __uspapi !== "function") { c.__uspapi = p; __uspapi.msgHandler = l; c.addEventListener("message", l, false) } })();`
|
|
104
168
|
};
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
169
|
+
function getCmpScripts(config) {
|
|
170
|
+
const fragment = document.createDocumentFragment();
|
|
171
|
+
fragment.appendChild(createContentScript(scriptContent.tcfStub));
|
|
172
|
+
fragment.appendChild(createContentScript(scriptContent.uspStub));
|
|
173
|
+
fragment.appendChild(createContentScript(scriptContent.getSPConfig(config)));
|
|
174
|
+
fragment.appendChild(createSourceScript(scriptSources.cmpFrames));
|
|
175
|
+
return fragment;
|
|
176
|
+
}
|
|
177
|
+
function getConsentPayload(parsedConsent, { shouldUpdateConsentStore, formOfWordsId, cookieDomain }) {
|
|
178
|
+
const categoryNames = Object.keys(parsedConsent);
|
|
179
|
+
const data = categoryNames.reduce(
|
|
180
|
+
(payload, categoryName) => {
|
|
181
|
+
payload[categoryName] = {
|
|
182
|
+
onsite: {
|
|
183
|
+
status: parsedConsent[categoryName],
|
|
184
|
+
lbi: false,
|
|
185
|
+
source: SOURCEPOINT_CONSENT_SOURCE,
|
|
186
|
+
fow: formOfWordsId
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
return payload;
|
|
190
|
+
},
|
|
191
|
+
{}
|
|
192
|
+
);
|
|
193
|
+
if (!shouldUpdateConsentStore) {
|
|
194
|
+
return { data };
|
|
195
|
+
} else {
|
|
196
|
+
return {
|
|
197
|
+
setConsentCookie: true,
|
|
198
|
+
formOfWordsId,
|
|
199
|
+
consentSource: SOURCEPOINT_CONSENT_SOURCE,
|
|
200
|
+
cookieDomain,
|
|
201
|
+
data
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
112
205
|
class DecodingError extends Error {
|
|
113
206
|
/**
|
|
114
207
|
* constructor - constructs an DecodingError
|
|
@@ -197,6 +290,10 @@ class Base64Url {
|
|
|
197
290
|
return result;
|
|
198
291
|
}
|
|
199
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Base 64 URL character set. Different from standard Base64 char set
|
|
295
|
+
* in that '+' and '/' are replaced with '-' and '_'.
|
|
296
|
+
*/
|
|
200
297
|
__publicField(Base64Url, "DICT", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
|
|
201
298
|
__publicField(Base64Url, "REVERSE_DICT", /* @__PURE__ */ new Map([
|
|
202
299
|
["A", 0],
|
|
@@ -264,26 +361,29 @@ __publicField(Base64Url, "REVERSE_DICT", /* @__PURE__ */ new Map([
|
|
|
264
361
|
["-", 62],
|
|
265
362
|
["_", 63]
|
|
266
363
|
]));
|
|
364
|
+
/**
|
|
365
|
+
* log2(64) = 6
|
|
366
|
+
*/
|
|
267
367
|
__publicField(Base64Url, "BASIS", 6);
|
|
268
368
|
__publicField(Base64Url, "LCM", 24);
|
|
269
|
-
const _ConsentLanguages = class
|
|
369
|
+
const _ConsentLanguages = class _ConsentLanguages {
|
|
270
370
|
has(key) {
|
|
271
|
-
return
|
|
371
|
+
return _ConsentLanguages.langSet.has(key);
|
|
272
372
|
}
|
|
273
373
|
parseLanguage(lang) {
|
|
274
374
|
lang = lang.toUpperCase();
|
|
275
375
|
const primaryLanguage = lang.split("-")[0];
|
|
276
376
|
if (lang.length >= 2 && primaryLanguage.length == 2) {
|
|
277
|
-
if (
|
|
377
|
+
if (_ConsentLanguages.langSet.has(lang)) {
|
|
278
378
|
return lang;
|
|
279
|
-
} else if (
|
|
379
|
+
} else if (_ConsentLanguages.langSet.has(primaryLanguage)) {
|
|
280
380
|
return primaryLanguage;
|
|
281
381
|
}
|
|
282
382
|
const fullPrimaryLang = primaryLanguage + "-" + primaryLanguage;
|
|
283
|
-
if (
|
|
383
|
+
if (_ConsentLanguages.langSet.has(fullPrimaryLang)) {
|
|
284
384
|
return fullPrimaryLang;
|
|
285
385
|
}
|
|
286
|
-
for (const supportedLang of
|
|
386
|
+
for (const supportedLang of _ConsentLanguages.langSet) {
|
|
287
387
|
if (supportedLang.indexOf(lang) !== -1 || supportedLang.indexOf(primaryLanguage) !== -1) {
|
|
288
388
|
return supportedLang;
|
|
289
389
|
}
|
|
@@ -292,10 +392,10 @@ const _ConsentLanguages = class _ConsentLanguages2 {
|
|
|
292
392
|
throw new Error(`unsupported language ${lang}`);
|
|
293
393
|
}
|
|
294
394
|
forEach(callback) {
|
|
295
|
-
|
|
395
|
+
_ConsentLanguages.langSet.forEach(callback);
|
|
296
396
|
}
|
|
297
397
|
get size() {
|
|
298
|
-
return
|
|
398
|
+
return _ConsentLanguages.langSet.size;
|
|
299
399
|
}
|
|
300
400
|
};
|
|
301
401
|
__publicField(_ConsentLanguages, "langSet", /* @__PURE__ */ new Set([
|
|
@@ -426,7 +526,7 @@ var RestrictionType;
|
|
|
426
526
|
RestrictionType2[RestrictionType2["REQUIRE_CONSENT"] = 1] = "REQUIRE_CONSENT";
|
|
427
527
|
RestrictionType2[RestrictionType2["REQUIRE_LI"] = 2] = "REQUIRE_LI";
|
|
428
528
|
})(RestrictionType || (RestrictionType = {}));
|
|
429
|
-
const _PurposeRestriction = class
|
|
529
|
+
const _PurposeRestriction = class _PurposeRestriction extends Cloneable {
|
|
430
530
|
/**
|
|
431
531
|
* constructor
|
|
432
532
|
*
|
|
@@ -449,7 +549,7 @@ const _PurposeRestriction = class _PurposeRestriction2 extends Cloneable {
|
|
|
449
549
|
}
|
|
450
550
|
static unHash(hash) {
|
|
451
551
|
const splitUp = hash.split(this.hashSeparator);
|
|
452
|
-
const purpRestriction = new
|
|
552
|
+
const purpRestriction = new _PurposeRestriction();
|
|
453
553
|
if (splitUp.length !== 2) {
|
|
454
554
|
throw new TCModelError("hash", hash);
|
|
455
555
|
}
|
|
@@ -461,7 +561,7 @@ const _PurposeRestriction = class _PurposeRestriction2 extends Cloneable {
|
|
|
461
561
|
if (!this.isValid()) {
|
|
462
562
|
throw new Error("cannot hash invalid PurposeRestriction");
|
|
463
563
|
}
|
|
464
|
-
return `${this.purposeId}${
|
|
564
|
+
return `${this.purposeId}${_PurposeRestriction.hashSeparator}${this.restrictionType}`;
|
|
465
565
|
}
|
|
466
566
|
/**
|
|
467
567
|
* @return {number} The purpose Id associated with a publisher
|
|
@@ -491,7 +591,15 @@ let PurposeRestriction = _PurposeRestriction;
|
|
|
491
591
|
class PurposeRestrictionVector extends Cloneable {
|
|
492
592
|
constructor() {
|
|
493
593
|
super(...arguments);
|
|
594
|
+
/**
|
|
595
|
+
* if this originatd from an encoded string we'll need a place to store the
|
|
596
|
+
* bit length; it can be set and got from here
|
|
597
|
+
*/
|
|
494
598
|
__publicField(this, "bitLength", 0);
|
|
599
|
+
/**
|
|
600
|
+
* a map indexed by a string which will be a 'hash' of the purpose and
|
|
601
|
+
* restriction type.
|
|
602
|
+
*/
|
|
495
603
|
__publicField(this, "map", /* @__PURE__ */ new Map());
|
|
496
604
|
__publicField(this, "gvl_");
|
|
497
605
|
}
|
|
@@ -728,6 +836,12 @@ var Segment;
|
|
|
728
836
|
})(Segment || (Segment = {}));
|
|
729
837
|
class SegmentIDs {
|
|
730
838
|
}
|
|
839
|
+
/**
|
|
840
|
+
* 0 = default - reserved for core string (does not need to be present in the core string)
|
|
841
|
+
* 1 = OOB vendors disclosed
|
|
842
|
+
* 2 = OOB vendors allowed
|
|
843
|
+
* 3 = PublisherTC
|
|
844
|
+
*/
|
|
731
845
|
__publicField(SegmentIDs, "ID_TO_KEY", [
|
|
732
846
|
Segment.CORE,
|
|
733
847
|
Segment.VENDORS_DISCLOSED,
|
|
@@ -743,6 +857,10 @@ __publicField(SegmentIDs, "KEY_TO_ID", {
|
|
|
743
857
|
class Vector extends Cloneable {
|
|
744
858
|
constructor() {
|
|
745
859
|
super(...arguments);
|
|
860
|
+
/**
|
|
861
|
+
* if this originatd from an encoded string we'll need a place to store the
|
|
862
|
+
* bit length; it can be set and got from here
|
|
863
|
+
*/
|
|
746
864
|
__publicField(this, "bitLength", 0);
|
|
747
865
|
__publicField(this, "maxId_", 0);
|
|
748
866
|
__publicField(this, "set_", /* @__PURE__ */ new Set());
|
|
@@ -1486,7 +1604,7 @@ class Json {
|
|
|
1486
1604
|
return this.absCall(url, null, sendCookies, timeout);
|
|
1487
1605
|
}
|
|
1488
1606
|
}
|
|
1489
|
-
const _GVL = class
|
|
1607
|
+
const _GVL = class _GVL extends Cloneable {
|
|
1490
1608
|
/**
|
|
1491
1609
|
* @param {VersionOrVendorList} [versionOrVendorList] - can be either a
|
|
1492
1610
|
* [[VendorList]] object or a version number represented as a string or
|
|
@@ -1495,31 +1613,94 @@ const _GVL = class _GVL2 extends Cloneable {
|
|
|
1495
1613
|
*/
|
|
1496
1614
|
constructor(versionOrVendorList) {
|
|
1497
1615
|
super();
|
|
1616
|
+
/**
|
|
1617
|
+
* @param {Promise} resolved when this GVL object is populated with the data
|
|
1618
|
+
* or rejected if there is an error.
|
|
1619
|
+
*/
|
|
1498
1620
|
__publicField(this, "readyPromise");
|
|
1621
|
+
/**
|
|
1622
|
+
* @param {number} gvlSpecificationVersion - schema version for the GVL that is used
|
|
1623
|
+
*/
|
|
1499
1624
|
__publicField(this, "gvlSpecificationVersion");
|
|
1625
|
+
/**
|
|
1626
|
+
* @param {number} incremented with each published file change
|
|
1627
|
+
*/
|
|
1500
1628
|
__publicField(this, "vendorListVersion");
|
|
1629
|
+
/**
|
|
1630
|
+
* @param {number} tcfPolicyVersion - The TCF MO will increment this value
|
|
1631
|
+
* whenever a GVL change (such as adding a new Purpose or Feature or a change
|
|
1632
|
+
* in Purpose wording) legally invalidates existing TC Strings and requires
|
|
1633
|
+
* CMPs to re-establish transparency and consent from users. If the policy
|
|
1634
|
+
* version number in the latest GVL is different from the value in your TC
|
|
1635
|
+
* String, then you need to re-establish transparency and consent for that
|
|
1636
|
+
* user. A version 1 format TC String is considered to have a version value
|
|
1637
|
+
* of 1.
|
|
1638
|
+
*/
|
|
1501
1639
|
__publicField(this, "tcfPolicyVersion");
|
|
1640
|
+
/**
|
|
1641
|
+
* @param {string | Date} lastUpdated - the date in which the vendor list
|
|
1642
|
+
* json file was last updated.
|
|
1643
|
+
*/
|
|
1502
1644
|
__publicField(this, "lastUpdated");
|
|
1645
|
+
/**
|
|
1646
|
+
* @param {IntMap<Purpose>} a collection of [[Purpose]]s
|
|
1647
|
+
*/
|
|
1503
1648
|
__publicField(this, "purposes");
|
|
1649
|
+
/**
|
|
1650
|
+
* @param {IntMap<Purpose>} a collection of [[Purpose]]s
|
|
1651
|
+
*/
|
|
1504
1652
|
__publicField(this, "specialPurposes");
|
|
1653
|
+
/**
|
|
1654
|
+
* @param {IntMap<Feature>} a collection of [[Feature]]s
|
|
1655
|
+
*/
|
|
1505
1656
|
__publicField(this, "features");
|
|
1657
|
+
/**
|
|
1658
|
+
* @param {IntMap<Feature>} a collection of [[Feature]]s
|
|
1659
|
+
*/
|
|
1506
1660
|
__publicField(this, "specialFeatures");
|
|
1661
|
+
/**
|
|
1662
|
+
* @param {boolean} internal reference of when the GVL is ready to be used
|
|
1663
|
+
*/
|
|
1507
1664
|
__publicField(this, "isReady_", false);
|
|
1665
|
+
/**
|
|
1666
|
+
* @param {IntMap<Vendor>} a collection of [[Vendor]]s
|
|
1667
|
+
*/
|
|
1508
1668
|
__publicField(this, "vendors_");
|
|
1509
1669
|
__publicField(this, "vendorIds");
|
|
1670
|
+
/**
|
|
1671
|
+
* @param {IntMap<Vendor>} a collection of [[Vendor]]. Used as a backup if a whitelist is sets
|
|
1672
|
+
*/
|
|
1510
1673
|
__publicField(this, "fullVendorList");
|
|
1674
|
+
/**
|
|
1675
|
+
* @param {ByPurposeVendorMap} vendors by purpose
|
|
1676
|
+
*/
|
|
1511
1677
|
__publicField(this, "byPurposeVendorMap");
|
|
1678
|
+
/**
|
|
1679
|
+
* @param {IDSetMap} vendors by special purpose
|
|
1680
|
+
*/
|
|
1512
1681
|
__publicField(this, "bySpecialPurposeVendorMap");
|
|
1682
|
+
/**
|
|
1683
|
+
* @param {IDSetMap} vendors by feature
|
|
1684
|
+
*/
|
|
1513
1685
|
__publicField(this, "byFeatureVendorMap");
|
|
1686
|
+
/**
|
|
1687
|
+
* @param {IDSetMap} vendors by special feature
|
|
1688
|
+
*/
|
|
1514
1689
|
__publicField(this, "bySpecialFeatureVendorMap");
|
|
1690
|
+
/**
|
|
1691
|
+
* @param {IntMap<Stack>} a collection of [[Stack]]s
|
|
1692
|
+
*/
|
|
1515
1693
|
__publicField(this, "stacks");
|
|
1694
|
+
/**
|
|
1695
|
+
* @param {IntMap<DataCategory>} a collection of [[DataCategory]]s
|
|
1696
|
+
*/
|
|
1516
1697
|
__publicField(this, "dataCategories");
|
|
1517
1698
|
__publicField(this, "lang_");
|
|
1518
1699
|
__publicField(this, "cacheLang_");
|
|
1519
1700
|
__publicField(this, "isLatest", false);
|
|
1520
|
-
let url =
|
|
1521
|
-
this.lang_ =
|
|
1522
|
-
this.cacheLang_ =
|
|
1701
|
+
let url = _GVL.baseUrl;
|
|
1702
|
+
this.lang_ = _GVL.DEFAULT_LANGUAGE;
|
|
1703
|
+
this.cacheLang_ = _GVL.DEFAULT_LANGUAGE;
|
|
1523
1704
|
if (this.isVendorList(versionOrVendorList)) {
|
|
1524
1705
|
this.populate(versionOrVendorList);
|
|
1525
1706
|
this.readyPromise = Promise.resolve();
|
|
@@ -1529,20 +1710,20 @@ const _GVL = class _GVL2 extends Cloneable {
|
|
|
1529
1710
|
}
|
|
1530
1711
|
if (versionOrVendorList > 0) {
|
|
1531
1712
|
const version = versionOrVendorList;
|
|
1532
|
-
if (
|
|
1533
|
-
this.populate(
|
|
1713
|
+
if (_GVL.CACHE.has(version)) {
|
|
1714
|
+
this.populate(_GVL.CACHE.get(version));
|
|
1534
1715
|
this.readyPromise = Promise.resolve();
|
|
1535
1716
|
} else {
|
|
1536
|
-
url +=
|
|
1717
|
+
url += _GVL.versionedFilename.replace("[VERSION]", String(version));
|
|
1537
1718
|
this.readyPromise = this.fetchJson(url);
|
|
1538
1719
|
}
|
|
1539
1720
|
} else {
|
|
1540
|
-
if (
|
|
1541
|
-
this.populate(
|
|
1721
|
+
if (_GVL.CACHE.has(_GVL.LATEST_CACHE_KEY)) {
|
|
1722
|
+
this.populate(_GVL.CACHE.get(_GVL.LATEST_CACHE_KEY));
|
|
1542
1723
|
this.readyPromise = Promise.resolve();
|
|
1543
1724
|
} else {
|
|
1544
1725
|
this.isLatest = true;
|
|
1545
|
-
this.readyPromise = this.fetchJson(url +
|
|
1726
|
+
this.readyPromise = this.fetchJson(url + _GVL.latestFilename);
|
|
1546
1727
|
}
|
|
1547
1728
|
}
|
|
1548
1729
|
}
|
|
@@ -1599,11 +1780,11 @@ const _GVL = class _GVL2 extends Cloneable {
|
|
|
1599
1780
|
*/
|
|
1600
1781
|
static emptyLanguageCache(lang) {
|
|
1601
1782
|
let result = false;
|
|
1602
|
-
if (lang == null &&
|
|
1603
|
-
|
|
1783
|
+
if (lang == null && _GVL.LANGUAGE_CACHE.size > 0) {
|
|
1784
|
+
_GVL.LANGUAGE_CACHE = /* @__PURE__ */ new Map();
|
|
1604
1785
|
result = true;
|
|
1605
1786
|
} else if (typeof lang === "string" && this.consentLanguages.has(lang.toUpperCase())) {
|
|
1606
|
-
|
|
1787
|
+
_GVL.LANGUAGE_CACHE.delete(lang.toUpperCase());
|
|
1607
1788
|
result = true;
|
|
1608
1789
|
}
|
|
1609
1790
|
return result;
|
|
@@ -1618,17 +1799,17 @@ const _GVL = class _GVL2 extends Cloneable {
|
|
|
1618
1799
|
static emptyCache(vendorListVersion) {
|
|
1619
1800
|
let retr = false;
|
|
1620
1801
|
if (Number.isInteger(vendorListVersion) && vendorListVersion >= 0) {
|
|
1621
|
-
|
|
1802
|
+
_GVL.CACHE.delete(vendorListVersion);
|
|
1622
1803
|
retr = true;
|
|
1623
1804
|
} else if (vendorListVersion === void 0) {
|
|
1624
|
-
|
|
1805
|
+
_GVL.CACHE = /* @__PURE__ */ new Map();
|
|
1625
1806
|
retr = true;
|
|
1626
1807
|
}
|
|
1627
1808
|
return retr;
|
|
1628
1809
|
}
|
|
1629
1810
|
cacheLanguage() {
|
|
1630
|
-
if (!
|
|
1631
|
-
|
|
1811
|
+
if (!_GVL.LANGUAGE_CACHE.has(this.cacheLang_)) {
|
|
1812
|
+
_GVL.LANGUAGE_CACHE.set(this.cacheLang_, {
|
|
1632
1813
|
purposes: this.purposes,
|
|
1633
1814
|
specialPurposes: this.specialPurposes,
|
|
1634
1815
|
features: this.features,
|
|
@@ -1678,25 +1859,25 @@ const _GVL = class _GVL2 extends Cloneable {
|
|
|
1678
1859
|
async changeLanguage(lang) {
|
|
1679
1860
|
let parsedLanguage = lang;
|
|
1680
1861
|
try {
|
|
1681
|
-
parsedLanguage =
|
|
1862
|
+
parsedLanguage = _GVL.consentLanguages.parseLanguage(lang);
|
|
1682
1863
|
} catch (e) {
|
|
1683
1864
|
throw new GVLError("Error during parsing the language: " + e.message);
|
|
1684
1865
|
}
|
|
1685
1866
|
const cacheLang = lang.toUpperCase();
|
|
1686
|
-
if (parsedLanguage.toLowerCase() ===
|
|
1867
|
+
if (parsedLanguage.toLowerCase() === _GVL.DEFAULT_LANGUAGE.toLowerCase() && !_GVL.LANGUAGE_CACHE.has(cacheLang)) {
|
|
1687
1868
|
return;
|
|
1688
1869
|
}
|
|
1689
1870
|
if (parsedLanguage !== this.lang_) {
|
|
1690
1871
|
this.lang_ = parsedLanguage;
|
|
1691
|
-
if (
|
|
1692
|
-
const cached =
|
|
1872
|
+
if (_GVL.LANGUAGE_CACHE.has(cacheLang)) {
|
|
1873
|
+
const cached = _GVL.LANGUAGE_CACHE.get(cacheLang);
|
|
1693
1874
|
for (const prop in cached) {
|
|
1694
1875
|
if (cached.hasOwnProperty(prop)) {
|
|
1695
1876
|
this[prop] = cached[prop];
|
|
1696
1877
|
}
|
|
1697
1878
|
}
|
|
1698
1879
|
} else {
|
|
1699
|
-
const url =
|
|
1880
|
+
const url = _GVL.baseUrl + _GVL.languageFilename.replace("[LANG]", this.lang_.toLowerCase());
|
|
1700
1881
|
try {
|
|
1701
1882
|
await this.fetchJson(url);
|
|
1702
1883
|
this.cacheLang_ = cacheLang;
|
|
@@ -1733,10 +1914,10 @@ const _GVL = class _GVL2 extends Cloneable {
|
|
|
1733
1914
|
this.mapVendors();
|
|
1734
1915
|
this.isReady_ = true;
|
|
1735
1916
|
if (this.isLatest) {
|
|
1736
|
-
|
|
1917
|
+
_GVL.CACHE.set(_GVL.LATEST_CACHE_KEY, this.getJson());
|
|
1737
1918
|
}
|
|
1738
|
-
if (!
|
|
1739
|
-
|
|
1919
|
+
if (!_GVL.CACHE.has(this.vendorListVersion)) {
|
|
1920
|
+
_GVL.CACHE.set(this.vendorListVersion, this.getJson());
|
|
1740
1921
|
}
|
|
1741
1922
|
}
|
|
1742
1923
|
this.cacheLanguage();
|
|
@@ -1899,8 +2080,8 @@ const _GVL = class _GVL2 extends Cloneable {
|
|
|
1899
2080
|
* @return {GVL}
|
|
1900
2081
|
*/
|
|
1901
2082
|
clone() {
|
|
1902
|
-
const result = new
|
|
1903
|
-
if (this.lang_ !==
|
|
2083
|
+
const result = new _GVL(this.getJson());
|
|
2084
|
+
if (this.lang_ !== _GVL.DEFAULT_LANGUAGE) {
|
|
1904
2085
|
result.changeLanguage(this.lang_);
|
|
1905
2086
|
}
|
|
1906
2087
|
return result;
|
|
@@ -1914,10 +2095,47 @@ __publicField(_GVL, "LANGUAGE_CACHE", /* @__PURE__ */ new Map());
|
|
|
1914
2095
|
__publicField(_GVL, "CACHE", /* @__PURE__ */ new Map());
|
|
1915
2096
|
__publicField(_GVL, "LATEST_CACHE_KEY", 0);
|
|
1916
2097
|
__publicField(_GVL, "DEFAULT_LANGUAGE", "EN");
|
|
2098
|
+
/**
|
|
2099
|
+
* Set of available consent languages published by the IAB
|
|
2100
|
+
*/
|
|
1917
2101
|
__publicField(_GVL, "consentLanguages", new ConsentLanguages());
|
|
1918
2102
|
__publicField(_GVL, "baseUrl_");
|
|
2103
|
+
/**
|
|
2104
|
+
* @static
|
|
2105
|
+
* @param {string} - the latest is assumed to be vendor-list.json because
|
|
2106
|
+
* that is what the iab uses, but it could be different... if you want
|
|
2107
|
+
*/
|
|
1919
2108
|
__publicField(_GVL, "latestFilename", "vendor-list.json");
|
|
2109
|
+
/**
|
|
2110
|
+
* @static
|
|
2111
|
+
* @param {string} - the versioned name is assumed to be
|
|
2112
|
+
* vendor-list-v[VERSION].json where [VERSION] will be replaced with the
|
|
2113
|
+
* specified version. But it could be different... if you want just make
|
|
2114
|
+
* sure to include the [VERSION] macro if you have a numbering scheme, it's a
|
|
2115
|
+
* simple string substitution.
|
|
2116
|
+
*
|
|
2117
|
+
* eg.
|
|
2118
|
+
* ```javascript
|
|
2119
|
+
* GVL.baseUrl = "http://www.mydomain.com/iabcmp/";
|
|
2120
|
+
* GVL.versionedFilename = "vendorlist?getVersion=[VERSION]";
|
|
2121
|
+
* ```
|
|
2122
|
+
*/
|
|
1920
2123
|
__publicField(_GVL, "versionedFilename", "archives/vendor-list-v[VERSION].json");
|
|
2124
|
+
/**
|
|
2125
|
+
* @param {string} - Translations of the names and descriptions for Purposes,
|
|
2126
|
+
* Special Purposes, Features, and Special Features to non-English languages
|
|
2127
|
+
* are contained in a file where attributes containing English content
|
|
2128
|
+
* (except vendor declaration information) are translated. The iab publishes
|
|
2129
|
+
* one following the scheme below where the LANG is the iso639-1 language
|
|
2130
|
+
* code. For a list of available translations
|
|
2131
|
+
* [please go here](https://register.consensu.org/Translation).
|
|
2132
|
+
*
|
|
2133
|
+
* eg.
|
|
2134
|
+
* ```javascript
|
|
2135
|
+
* GVL.baseUrl = "http://www.mydomain.com/iabcmp/";
|
|
2136
|
+
* GVL.languageFilename = "purposes?getPurposes=[LANG]";
|
|
2137
|
+
* ```
|
|
2138
|
+
*/
|
|
1921
2139
|
__publicField(_GVL, "languageFilename", "purposes-[LANG].json");
|
|
1922
2140
|
let GVL = _GVL;
|
|
1923
2141
|
class TCModel extends Cloneable {
|
|
@@ -1943,20 +2161,83 @@ class TCModel extends Cloneable {
|
|
|
1943
2161
|
__publicField(this, "cmpVersion_", 0);
|
|
1944
2162
|
__publicField(this, "vendorListVersion_", 0);
|
|
1945
2163
|
__publicField(this, "numCustomPurposes_", 0);
|
|
2164
|
+
// Member Variable for GVL
|
|
1946
2165
|
__publicField(this, "gvl_");
|
|
1947
2166
|
__publicField(this, "created");
|
|
1948
2167
|
__publicField(this, "lastUpdated");
|
|
2168
|
+
/**
|
|
2169
|
+
* The TCF designates certain Features as special, that is, a CMP must afford
|
|
2170
|
+
* the user a means to opt in to their use. These Special Features are
|
|
2171
|
+
* published and numbered in the GVL separately from normal Features.
|
|
2172
|
+
* Provides for up to 12 special features.
|
|
2173
|
+
*/
|
|
1949
2174
|
__publicField(this, "specialFeatureOptins", new Vector());
|
|
2175
|
+
/**
|
|
2176
|
+
* Renamed from `PurposesAllowed` in TCF v1.1
|
|
2177
|
+
* The user’s consent value for each Purpose established on the legal basis
|
|
2178
|
+
* of consent. Purposes are published in the Global Vendor List (see. [[GVL]]).
|
|
2179
|
+
*/
|
|
1950
2180
|
__publicField(this, "purposeConsents", new Vector());
|
|
2181
|
+
/**
|
|
2182
|
+
* The user’s permission for each Purpose established on the legal basis of
|
|
2183
|
+
* legitimate interest. If the user has exercised right-to-object for a
|
|
2184
|
+
* purpose.
|
|
2185
|
+
*/
|
|
1951
2186
|
__publicField(this, "purposeLegitimateInterests", new Vector());
|
|
2187
|
+
/**
|
|
2188
|
+
* The user’s consent value for each Purpose established on the legal basis
|
|
2189
|
+
* of consent, for the publisher. Purposes are published in the Global
|
|
2190
|
+
* Vendor List.
|
|
2191
|
+
*/
|
|
1952
2192
|
__publicField(this, "publisherConsents", new Vector());
|
|
2193
|
+
/**
|
|
2194
|
+
* The user’s permission for each Purpose established on the legal basis of
|
|
2195
|
+
* legitimate interest. If the user has exercised right-to-object for a
|
|
2196
|
+
* purpose.
|
|
2197
|
+
*/
|
|
1953
2198
|
__publicField(this, "publisherLegitimateInterests", new Vector());
|
|
2199
|
+
/**
|
|
2200
|
+
* The user’s consent value for each Purpose established on the legal basis
|
|
2201
|
+
* of consent, for the publisher. Purposes are published in the Global
|
|
2202
|
+
* Vendor List.
|
|
2203
|
+
*/
|
|
1954
2204
|
__publicField(this, "publisherCustomConsents", new Vector());
|
|
2205
|
+
/**
|
|
2206
|
+
* The user’s permission for each Purpose established on the legal basis of
|
|
2207
|
+
* legitimate interest. If the user has exercised right-to-object for a
|
|
2208
|
+
* purpose that is established in the publisher's custom purposes.
|
|
2209
|
+
*/
|
|
1955
2210
|
__publicField(this, "publisherCustomLegitimateInterests", new Vector());
|
|
2211
|
+
/**
|
|
2212
|
+
* set by a publisher if they wish to collect consent and LI Transparency for
|
|
2213
|
+
* purposes outside of the TCF
|
|
2214
|
+
*/
|
|
1956
2215
|
__publicField(this, "customPurposes");
|
|
2216
|
+
/**
|
|
2217
|
+
* Each [[Vendor]] is keyed by id. Their consent value is true if it is in
|
|
2218
|
+
* the Vector
|
|
2219
|
+
*/
|
|
1957
2220
|
__publicField(this, "vendorConsents", new Vector());
|
|
2221
|
+
/**
|
|
2222
|
+
* Each [[Vendor]] is keyed by id. Whether their Legitimate Interests
|
|
2223
|
+
* Disclosures have been established is stored as boolean.
|
|
2224
|
+
* see: [[Vector]]
|
|
2225
|
+
*/
|
|
1958
2226
|
__publicField(this, "vendorLegitimateInterests", new Vector());
|
|
2227
|
+
/**
|
|
2228
|
+
* The value included for disclosed vendors signals which vendors have been
|
|
2229
|
+
* disclosed to the user in the interface surfaced by the CMP. This section
|
|
2230
|
+
* content is required when writing a TC string to the global (consensu)
|
|
2231
|
+
* scope. When a CMP has read from and is updating a TC string from the
|
|
2232
|
+
* global consensu.org storage, the CMP MUST retain the existing disclosure
|
|
2233
|
+
* information and only add information for vendors that it has disclosed
|
|
2234
|
+
* that had not been disclosed by other CMPs in prior interactions with this
|
|
2235
|
+
* device/user agent.
|
|
2236
|
+
*/
|
|
1959
2237
|
__publicField(this, "vendorsDisclosed", new Vector());
|
|
2238
|
+
/**
|
|
2239
|
+
* Signals which vendors the publisher permits to use OOB legal bases.
|
|
2240
|
+
*/
|
|
1960
2241
|
__publicField(this, "vendorsAllowed", new Vector());
|
|
1961
2242
|
__publicField(this, "publisherRestrictions", new PurposeRestrictionVector());
|
|
1962
2243
|
if (gvl) {
|
|
@@ -2338,6 +2619,9 @@ class TCModel extends Cloneable {
|
|
|
2338
2619
|
this.lastUpdated = utcDate;
|
|
2339
2620
|
}
|
|
2340
2621
|
}
|
|
2622
|
+
/**
|
|
2623
|
+
* Set of available consent languages published by the IAB
|
|
2624
|
+
*/
|
|
2341
2625
|
__publicField(TCModel, "consentLanguages", GVL.consentLanguages);
|
|
2342
2626
|
class TCString {
|
|
2343
2627
|
/**
|
|
@@ -2391,20 +2675,6 @@ class TCString {
|
|
|
2391
2675
|
return tcModel;
|
|
2392
2676
|
}
|
|
2393
2677
|
}
|
|
2394
|
-
const iabCustomCategories = {
|
|
2395
|
-
permutiveAds: {
|
|
2396
|
-
purposes: [2, 4, 8, 9],
|
|
2397
|
-
iabVendors: [361],
|
|
2398
|
-
customVendors: [],
|
|
2399
|
-
specialFeatures: []
|
|
2400
|
-
},
|
|
2401
|
-
demographicAds: {
|
|
2402
|
-
purposes: [3, 4, 7, 9, 10],
|
|
2403
|
-
iabVendors: [],
|
|
2404
|
-
customVendors: [],
|
|
2405
|
-
specialFeatures: []
|
|
2406
|
-
}
|
|
2407
|
-
};
|
|
2408
2678
|
function isValidGdprValue(val) {
|
|
2409
2679
|
if (val === null) {
|
|
2410
2680
|
return true;
|
|
@@ -2446,10 +2716,6 @@ function validateIabConsentCategory(categoryName) {
|
|
|
2446
2716
|
throw new Error("Provided custom category identifier does not exist. Please check");
|
|
2447
2717
|
}
|
|
2448
2718
|
}
|
|
2449
|
-
const legislation = {
|
|
2450
|
-
CCPA: "ccpa",
|
|
2451
|
-
GDPR: "gdpr"
|
|
2452
|
-
};
|
|
2453
2719
|
function checkConsentFor(categoryName, consentState) {
|
|
2454
2720
|
validateIabConsentCategory(categoryName);
|
|
2455
2721
|
validateRawConsentState(consentState);
|
|
@@ -2479,47 +2745,29 @@ function getParsedConsent(rawConsentState) {
|
|
|
2479
2745
|
return parsedConsent;
|
|
2480
2746
|
}, {});
|
|
2481
2747
|
}
|
|
2482
|
-
function
|
|
2483
|
-
const
|
|
2484
|
-
"
|
|
2748
|
+
function getConsentCookieValue() {
|
|
2749
|
+
const cookies = Object.fromEntries(
|
|
2750
|
+
document.cookie.split("; ").map((cookie) => cookie.split("="))
|
|
2751
|
+
);
|
|
2752
|
+
const encodedValue = cookies[CONSENT_COOKIE_NAME];
|
|
2753
|
+
if (!encodedValue)
|
|
2754
|
+
return {};
|
|
2755
|
+
const decodedValue = decodeURIComponent(encodedValue);
|
|
2756
|
+
return Object.fromEntries(
|
|
2757
|
+
decodedValue.split(",").map((consent) => {
|
|
2758
|
+
const [category, value] = consent.split(":");
|
|
2759
|
+
const booleanConsent = [category, value === "on" ? true : false];
|
|
2760
|
+
return booleanConsent;
|
|
2761
|
+
})
|
|
2485
2762
|
);
|
|
2486
|
-
if (cookieLink) {
|
|
2487
|
-
cookieLink.href = "#";
|
|
2488
|
-
cookieLink.setAttribute("onclick", "window._sp_.gdpr.loadPrivacyManagerModal(827767);");
|
|
2489
|
-
cookieLink.dataset.cmpLink = "updated";
|
|
2490
|
-
return true;
|
|
2491
|
-
} else {
|
|
2492
|
-
console.warn("CMP Footer Link was not found and not updated");
|
|
2493
|
-
return false;
|
|
2494
|
-
}
|
|
2495
2763
|
}
|
|
2496
|
-
|
|
2497
|
-
const
|
|
2498
|
-
const
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
onsite: {
|
|
2504
|
-
status: parsedConsent[categoryName],
|
|
2505
|
-
lbi: false,
|
|
2506
|
-
source: SOURCEPOINT_CONSENT_SOURCE,
|
|
2507
|
-
fow: formOfWordsId
|
|
2508
|
-
}
|
|
2509
|
-
};
|
|
2510
|
-
return payload;
|
|
2511
|
-
}, {});
|
|
2512
|
-
if (!shouldUpdateConsentStore) {
|
|
2513
|
-
return { data };
|
|
2514
|
-
} else {
|
|
2515
|
-
return {
|
|
2516
|
-
setConsentCookie: true,
|
|
2517
|
-
formOfWordsId,
|
|
2518
|
-
consentSource: SOURCEPOINT_CONSENT_SOURCE,
|
|
2519
|
-
cookieDomain,
|
|
2520
|
-
data
|
|
2521
|
-
};
|
|
2522
|
-
}
|
|
2764
|
+
function hasConsentChanged(parsedConsent) {
|
|
2765
|
+
const categories = Object.keys(parsedConsent);
|
|
2766
|
+
const previousConsent = getConsentCookieValue();
|
|
2767
|
+
return categories.some((category) => {
|
|
2768
|
+
const adaptedCategoryName = `${category.toLowerCase()}Onsite`;
|
|
2769
|
+
return parsedConsent[category] !== previousConsent[adaptedCategoryName];
|
|
2770
|
+
});
|
|
2523
2771
|
}
|
|
2524
2772
|
async function saveConsent(consentEndpoint, payload) {
|
|
2525
2773
|
try {
|
|
@@ -2540,7 +2788,7 @@ async function saveConsent(consentEndpoint, payload) {
|
|
|
2540
2788
|
}
|
|
2541
2789
|
function consentReadyHandlerFn(props) {
|
|
2542
2790
|
const { userId, consentProxyHost, cookieDomain, formOfWordsId, useConsentStore } = props;
|
|
2543
|
-
return async (legislation2, _, consentString, consentMeta)
|
|
2791
|
+
return async function consentReadyHandler(legislation2, _, consentString, consentMeta) {
|
|
2544
2792
|
const activeLegislation = consentMeta.applies ? legislation2 : "gdpr";
|
|
2545
2793
|
if (activeLegislation !== legislation2 || !consentString) {
|
|
2546
2794
|
return;
|
|
@@ -2559,7 +2807,7 @@ function consentReadyHandlerFn(props) {
|
|
|
2559
2807
|
if (shouldUpdateConsentStore) {
|
|
2560
2808
|
consentEndpoint = `${consentProxyHost}/__consent/consent-record/${SOURCEPOINT_FOW_SCOPE}/${userId}`;
|
|
2561
2809
|
}
|
|
2562
|
-
const payload =
|
|
2810
|
+
const payload = getConsentPayload(parsedConsent, {
|
|
2563
2811
|
formOfWordsId,
|
|
2564
2812
|
cookieDomain,
|
|
2565
2813
|
shouldUpdateConsentStore
|
|
@@ -2568,53 +2816,8 @@ function consentReadyHandlerFn(props) {
|
|
|
2568
2816
|
document.dispatchEvent(new CustomEvent("oCookieMessage.act", { bubbles: true }));
|
|
2569
2817
|
};
|
|
2570
2818
|
}
|
|
2571
|
-
function hasConsentChanged(parsedConsent) {
|
|
2572
|
-
const categories = Object.keys(parsedConsent);
|
|
2573
|
-
const previousConsent = getConsentCookieValue();
|
|
2574
|
-
return categories.some((category) => {
|
|
2575
|
-
const adaptedCategoryName = `${category.toLowerCase()}Onsite`;
|
|
2576
|
-
return parsedConsent[category] !== previousConsent[adaptedCategoryName];
|
|
2577
|
-
});
|
|
2578
|
-
}
|
|
2579
|
-
function getConsentCookieValue() {
|
|
2580
|
-
const cookies = Object.fromEntries(
|
|
2581
|
-
document.cookie.split("; ").map((cookie) => cookie.split("="))
|
|
2582
|
-
);
|
|
2583
|
-
const encodedValue = cookies[CONSENT_COOKIE_NAME];
|
|
2584
|
-
if (!encodedValue)
|
|
2585
|
-
return {};
|
|
2586
|
-
const decodedValue = decodeURIComponent(encodedValue);
|
|
2587
|
-
return Object.fromEntries(
|
|
2588
|
-
decodedValue.split(",").map((consent) => {
|
|
2589
|
-
const [category, value] = consent.split(":");
|
|
2590
|
-
const booleanConsent = [category, value === "on" ? true : false];
|
|
2591
|
-
return booleanConsent;
|
|
2592
|
-
})
|
|
2593
|
-
);
|
|
2594
|
-
}
|
|
2595
|
-
const SOURCEPOINT_FOW_ID = "sourcepointCmp/VngD.XycZut.595cp9fWdp5XYP9vlFvk";
|
|
2596
|
-
const FT_COOKIE_DOMAIN = ".ft.com";
|
|
2597
|
-
const FT_CONSENT_PROXY_HOST = "https://consent.ft.com";
|
|
2598
|
-
function createContentScript(content) {
|
|
2599
|
-
const s = document.createElement("script");
|
|
2600
|
-
s.innerHTML = content;
|
|
2601
|
-
return s;
|
|
2602
|
-
}
|
|
2603
|
-
function createSourceScript(src) {
|
|
2604
|
-
const s = document.createElement("script");
|
|
2605
|
-
s.src = src;
|
|
2606
|
-
return s;
|
|
2607
|
-
}
|
|
2608
|
-
function getCmpScripts(config) {
|
|
2609
|
-
const fragment = document.createDocumentFragment();
|
|
2610
|
-
fragment.appendChild(createContentScript(scriptContent.tcfStub));
|
|
2611
|
-
fragment.appendChild(createContentScript(scriptContent.uspStub));
|
|
2612
|
-
fragment.appendChild(createContentScript(scriptContent.getSPConfig(config)));
|
|
2613
|
-
fragment.appendChild(createSourceScript(scriptSources.cmpFrames));
|
|
2614
|
-
return fragment;
|
|
2615
|
-
}
|
|
2616
2819
|
async function initSourcepointCmp({
|
|
2617
|
-
propertyConfig =
|
|
2820
|
+
propertyConfig = FT_DOTCOM_PROD,
|
|
2618
2821
|
userId,
|
|
2619
2822
|
useFTSession = true,
|
|
2620
2823
|
consentProxyHost = FT_CONSENT_PROXY_HOST,
|
|
@@ -2622,11 +2825,10 @@ async function initSourcepointCmp({
|
|
|
2622
2825
|
formOfWordsId = SOURCEPOINT_FOW_ID,
|
|
2623
2826
|
useConsentStore = true
|
|
2624
2827
|
}) {
|
|
2625
|
-
|
|
2626
|
-
if (!maybeUserId && useFTSession) {
|
|
2828
|
+
if (!userId && useFTSession) {
|
|
2627
2829
|
try {
|
|
2628
2830
|
const response = await getUuid();
|
|
2629
|
-
|
|
2831
|
+
userId = response == null ? void 0 : response.uuid;
|
|
2630
2832
|
} catch (error) {
|
|
2631
2833
|
console.error(error);
|
|
2632
2834
|
}
|
|
@@ -2634,8 +2836,8 @@ async function initSourcepointCmp({
|
|
|
2634
2836
|
if (!(propertyConfig == null ? void 0 : propertyConfig.accountId)) {
|
|
2635
2837
|
throw new Error("Please pass a valid property config");
|
|
2636
2838
|
}
|
|
2637
|
-
if (
|
|
2638
|
-
propertyConfig.authId =
|
|
2839
|
+
if (userId) {
|
|
2840
|
+
propertyConfig.authId = userId;
|
|
2639
2841
|
}
|
|
2640
2842
|
const scripts = getCmpScripts(propertyConfig);
|
|
2641
2843
|
document.head.appendChild(scripts);
|
|
@@ -2643,7 +2845,7 @@ async function initSourcepointCmp({
|
|
|
2643
2845
|
window._sp_.addEventListener(
|
|
2644
2846
|
"onConsentReady",
|
|
2645
2847
|
consentReadyHandlerFn({
|
|
2646
|
-
userId
|
|
2848
|
+
userId,
|
|
2647
2849
|
consentProxyHost,
|
|
2648
2850
|
cookieDomain,
|
|
2649
2851
|
formOfWordsId,
|
|
@@ -2652,6 +2854,55 @@ async function initSourcepointCmp({
|
|
|
2652
2854
|
);
|
|
2653
2855
|
});
|
|
2654
2856
|
}
|
|
2857
|
+
const events = {
|
|
2858
|
+
onMessageChoiceSelect: (...args) => {
|
|
2859
|
+
console.log("[event] onMessageChoiceSelect", args);
|
|
2860
|
+
},
|
|
2861
|
+
onMessageReady: (...args) => {
|
|
2862
|
+
console.log("[event] onMessageReady", args);
|
|
2863
|
+
},
|
|
2864
|
+
onMessageChoiceError: (...args) => {
|
|
2865
|
+
console.log("[event] onMessageChoiceError", args);
|
|
2866
|
+
},
|
|
2867
|
+
onPrivacyManagerAction: (...args) => {
|
|
2868
|
+
console.log("[event] onPrivacyManagerAction", args);
|
|
2869
|
+
},
|
|
2870
|
+
onPMCancel: (...args) => {
|
|
2871
|
+
console.log("[event] onPMCancel", args);
|
|
2872
|
+
},
|
|
2873
|
+
onMessageReceiveData: (...args) => {
|
|
2874
|
+
console.log("[event] onMessageReceiveData", args);
|
|
2875
|
+
},
|
|
2876
|
+
onSPPMObjectReady: (...args) => {
|
|
2877
|
+
console.log("[event] onSPPMObjectReady", args);
|
|
2878
|
+
},
|
|
2879
|
+
onConsentReady: (...args) => {
|
|
2880
|
+
console.log("[event] onConsentReady", args);
|
|
2881
|
+
},
|
|
2882
|
+
onError: (...args) => {
|
|
2883
|
+
console.log("[event] onError", args);
|
|
2884
|
+
}
|
|
2885
|
+
};
|
|
2886
|
+
const debug = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2887
|
+
__proto__: null,
|
|
2888
|
+
events
|
|
2889
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
2890
|
+
function updateFooterLinkCMP() {
|
|
2891
|
+
const cookieLink = document.querySelector(
|
|
2892
|
+
"[href='https://www.ft.com/preferences/manage-cookies']"
|
|
2893
|
+
);
|
|
2894
|
+
if (cookieLink) {
|
|
2895
|
+
cookieLink.href = "#";
|
|
2896
|
+
cookieLink.setAttribute("onclick", "window._sp_.gdpr.loadPrivacyManagerModal(827767);");
|
|
2897
|
+
cookieLink.dataset.cmpLink = "updated";
|
|
2898
|
+
return true;
|
|
2899
|
+
} else {
|
|
2900
|
+
console.warn("CMP Footer Link was not found and not updated");
|
|
2901
|
+
return false;
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
exports.debug = debug;
|
|
2655
2905
|
exports.getCmpScripts = getCmpScripts;
|
|
2656
2906
|
exports.initSourcepointCmp = initSourcepointCmp;
|
|
2907
|
+
exports.properties = properties;
|
|
2657
2908
|
exports.updateFooterLinkCMP = updateFooterLinkCMP;
|