@phantomstudios/ft-lib 0.5.2-rc1 → 0.5.2-rc3
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/lib/cmp/loadFtCmp.d.ts.map +1 -1
- package/lib/cmp/loadFtCmp.js +0 -5
- package/lib/cmp/loadFtCmp.js.map +1 -1
- package/lib/cmp/vendorConsent.d.ts +23 -0
- package/lib/cmp/vendorConsent.d.ts.map +1 -0
- package/lib/cmp/vendorConsent.js +33 -0
- package/lib/cmp/vendorConsent.js.map +1 -0
- package/lib/consentMonitor/index.d.ts +4 -0
- package/lib/consentMonitor/index.d.ts.map +1 -1
- package/lib/consentMonitor/index.js +26 -1
- package/lib/consentMonitor/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cmp/loadFtCmp.ts +0 -7
- package/src/cmp/vendorConsent.ts +66 -0
- package/src/consentMonitor/index.ts +28 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadFtCmp.d.ts","sourceRoot":"","sources":["../../src/cmp/loadFtCmp.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAoB/C;
|
|
1
|
+
{"version":3,"file":"loadFtCmp.d.ts","sourceRoot":"","sources":["../../src/cmp/loadFtCmp.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAoB/C;AAED,wBAAgB,YAAY,IAAI,IAAI,CAGnC;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAGvD"}
|
package/lib/cmp/loadFtCmp.js
CHANGED
|
@@ -22,11 +22,6 @@ function loadFtCmpScript() {
|
|
|
22
22
|
document.head.appendChild(script);
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
|
-
// export function enqueueCmpCallback(cb: () => void): void {
|
|
26
|
-
// if (!window._sp_) window._sp_ = {};
|
|
27
|
-
// if (!window._sp_queue) window._sp_queue = [];
|
|
28
|
-
// window._sp_queue!.push(cb);
|
|
29
|
-
// }
|
|
30
25
|
function initCmpQueue() {
|
|
31
26
|
window._sp_ = window._sp_ || {};
|
|
32
27
|
window._sp_queue = window._sp_queue || [];
|
package/lib/cmp/loadFtCmp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadFtCmp.js","sourceRoot":"","sources":["../../src/cmp/loadFtCmp.ts"],"names":[],"mappings":";;AAAA,0CAoBC;
|
|
1
|
+
{"version":3,"file":"loadFtCmp.js","sourceRoot":"","sources":["../../src/cmp/loadFtCmp.ts"],"names":[],"mappings":";;AAAA,0CAoBC;AAED,oCAGC;AAED,gDAGC;AA9BD,SAAgB,eAAe;IAC7B,IAAI,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,CAAC;QAC7C,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,IAAI,OAAO,CAAO,UAAC,OAAO,EAAE,MAAM;QACvC,IAAM,MAAM,GAAsB,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnE,MAAM,CAAC,EAAE,GAAG,eAAe,CAAC;QAC5B,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,MAAM,CAAC,GAAG,GAAG,sCAAsC,CAAC;QACpD,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;YAClE,CAAC,CAAC,EAAE,CAAC,mBAAmB;YACxB,CAAC,CAAC,4BAA4B,CAAC,CAAC,sBAAsB;QAExD,MAAM,CAAC,MAAM,GAAG,cAAM,OAAA,OAAO,EAAE,EAAT,CAAS,CAAC;QAChC,MAAM,CAAC,OAAO,GAAG;YACf,OAAA,MAAM,CAAC,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAA1D,CAA0D,CAAC;QAE7D,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,YAAY;IAC1B,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAChC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;AAC5C,CAAC;AAED,SAAgB,kBAAkB,CAAC,EAAc;IAC/C,YAAY,EAAE,CAAC;IACf,MAAM,CAAC,SAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface Window {
|
|
3
|
+
__tcfapi?: (command: string, version: number, callback: (tcData: TCFData | null, success: boolean) => void, parameter?: any) => void;
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
interface TCFData {
|
|
7
|
+
eventStatus: "tcloaded" | "useractioncomplete" | "cmpuishown";
|
|
8
|
+
listenerId: number;
|
|
9
|
+
purpose?: {
|
|
10
|
+
consents?: Record<number, boolean>;
|
|
11
|
+
};
|
|
12
|
+
vendor?: {
|
|
13
|
+
consents?: Record<number, boolean>;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface VendorConsentResults {
|
|
17
|
+
brandmetrics: boolean;
|
|
18
|
+
linkedIn: boolean;
|
|
19
|
+
purpose1: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function initVendorConsentListener(onConsentUpdate: (results: VendorConsentResults) => void): void;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=vendorConsent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vendorConsent.d.ts","sourceRoot":"","sources":["../../src/cmp/vendorConsent.ts"],"names":[],"mappings":"AACA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,QAAQ,CAAC,EAAE,CACT,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,EAC5D,SAAS,CAAC,EAAE,GAAG,KACZ,IAAI,CAAC;KACX;CACF;AAED,UAAU,OAAO;IACf,WAAW,EAAE,UAAU,GAAG,oBAAoB,GAAG,YAAY,CAAC;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,CAAC;IACF,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,yBAAyB,CACvC,eAAe,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GACvD,IAAI,CAkCN"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initVendorConsentListener = initVendorConsentListener;
|
|
4
|
+
function initVendorConsentListener(onConsentUpdate) {
|
|
5
|
+
if (typeof window.__tcfapi !== "function") {
|
|
6
|
+
console.warn("[CMP] window.__tcfapi is not defined on this page yet.");
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
window.__tcfapi("addEventListener", 2, function (tcData, success) {
|
|
10
|
+
var _a, _b, _c, _d, _e, _f;
|
|
11
|
+
if (!success || !tcData)
|
|
12
|
+
return;
|
|
13
|
+
// Handles BOTH returning visitors ('tcloaded') AND live banner updates ('useractioncomplete' / 'cmpuishown')
|
|
14
|
+
var isConsentReady = tcData.eventStatus === "tcloaded" ||
|
|
15
|
+
tcData.eventStatus === "useractioncomplete";
|
|
16
|
+
if (isConsentReady) {
|
|
17
|
+
// Brandmetrics (IAB Vendor ID: 422)
|
|
18
|
+
var brandmetrics = ((_b = (_a = tcData.vendor) === null || _a === void 0 ? void 0 : _a.consents) === null || _b === void 0 ? void 0 : _b[422]) === true;
|
|
19
|
+
// LinkedIn (IAB Vendor ID: 804)
|
|
20
|
+
var linkedIn = ((_d = (_c = tcData.vendor) === null || _c === void 0 ? void 0 : _c.consents) === null || _d === void 0 ? void 0 : _d[804]) === true;
|
|
21
|
+
// Purpose 1: Device storage/access (Cookies)
|
|
22
|
+
var purpose1 = ((_f = (_e = tcData.purpose) === null || _e === void 0 ? void 0 : _e.consents) === null || _f === void 0 ? void 0 : _f[1]) === true;
|
|
23
|
+
var results = {
|
|
24
|
+
brandmetrics: brandmetrics,
|
|
25
|
+
linkedIn: linkedIn,
|
|
26
|
+
purpose1: purpose1,
|
|
27
|
+
};
|
|
28
|
+
// Trigger your callback handler every time consent status updates
|
|
29
|
+
onConsentUpdate(results);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=vendorConsent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vendorConsent.js","sourceRoot":"","sources":["../../src/cmp/vendorConsent.ts"],"names":[],"mappings":";;AA6BA,8DAoCC;AApCD,SAAgB,yBAAyB,CACvC,eAAwD;IAExD,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;QACvE,OAAO;IACT,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,EAAE,UAAC,MAAM,EAAE,OAAO;;QACrD,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM;YAAE,OAAO;QAEhC,6GAA6G;QAC7G,IAAM,cAAc,GAClB,MAAM,CAAC,WAAW,KAAK,UAAU;YACjC,MAAM,CAAC,WAAW,KAAK,oBAAoB,CAAC;QAE9C,IAAI,cAAc,EAAE,CAAC;YACnB,oCAAoC;YACpC,IAAM,YAAY,GAAG,CAAA,MAAA,MAAA,MAAM,CAAC,MAAM,0CAAE,QAAQ,0CAAG,GAAG,CAAC,MAAK,IAAI,CAAC;YAE7D,gCAAgC;YAChC,IAAM,QAAQ,GAAG,CAAA,MAAA,MAAA,MAAM,CAAC,MAAM,0CAAE,QAAQ,0CAAG,GAAG,CAAC,MAAK,IAAI,CAAC;YAEzD,6CAA6C;YAC7C,IAAM,QAAQ,GAAG,CAAA,MAAA,MAAA,MAAM,CAAC,OAAO,0CAAE,QAAQ,0CAAG,CAAC,CAAC,MAAK,IAAI,CAAC;YAExD,IAAM,OAAO,GAAyB;gBACpC,YAAY,cAAA;gBACZ,QAAQ,UAAA;gBACR,QAAQ,UAAA;aACT,CAAC;YAEF,kEAAkE;YAClE,eAAe,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
+
import { VendorConsentResults } from "../cmp/vendorConsent";
|
|
1
2
|
export declare class ConsentMonitor {
|
|
2
3
|
private _consent;
|
|
3
4
|
private _devHosts;
|
|
4
5
|
private _isDevEnvironment;
|
|
5
6
|
private _isInitialized;
|
|
6
7
|
private _hostname;
|
|
8
|
+
private _vendorConsents;
|
|
7
9
|
get consent(): boolean;
|
|
8
10
|
get devHosts(): string[];
|
|
9
11
|
get isDevEnvironment(): boolean;
|
|
10
12
|
get isInitialized(): boolean;
|
|
11
13
|
get userHasConsented(): boolean;
|
|
14
|
+
get vendorConsents(): VendorConsentResults;
|
|
12
15
|
getCookieValue: (name: string) => string;
|
|
13
16
|
constructor(hostname?: string, devHosts?: string[] | string);
|
|
17
|
+
private attachVendorConsentListeners;
|
|
14
18
|
private attachCmpListeners;
|
|
15
19
|
private enablePermutive;
|
|
16
20
|
private disablePermutive;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/consentMonitor/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/consentMonitor/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,oBAAoB,EACrB,MAAM,sBAAsB,CAAC;AAwB9B,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAIG;IAE1B,IAAW,OAAO,IAAI,OAAO,CAE5B;IACD,IAAW,QAAQ,IAAI,MAAM,EAAE,CAE9B;IACD,IAAW,gBAAgB,IAAI,OAAO,CAErC;IACD,IAAW,aAAa,IAAI,OAAO,CAElC;IACD,IAAW,gBAAgB,IAAI,OAAO,CAErC;IACD,IAAW,cAAc,IAAI,oBAAoB,CAEhD;IAED,cAAc,GAAI,MAAM,MAAM,YACgD;gBAElE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM;IAoC3D,OAAO,CAAC,4BAA4B;IAWpC,OAAO,CAAC,kBAAkB;IAiC1B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,gBAAgB;IAQxB,iBAAiB,aAcf;IAEF,oBAAoB,aAMlB;CACH;AAED,OAAO,EAAE,cAAc,IAAI,cAAc,EAAE,CAAC"}
|
|
@@ -16,6 +16,7 @@ exports.consentMonitor = exports.ConsentMonitor = void 0;
|
|
|
16
16
|
var cmp_client_1 = require("@financial-times/cmp-client");
|
|
17
17
|
var debug_1 = __importDefault(require("debug"));
|
|
18
18
|
var loadFtCmp_1 = require("../cmp/loadFtCmp");
|
|
19
|
+
var vendorConsent_1 = require("../cmp/vendorConsent");
|
|
19
20
|
var debug = (0, debug_1.default)("@phantomstudios/ft-lib/consentMonitor");
|
|
20
21
|
var DEFAULT_DEV_HOSTS = ["localhost", "phq", ".app", "preview"];
|
|
21
22
|
var CMP_CHOICE_ACCEPT_ALL = 11;
|
|
@@ -26,6 +27,11 @@ var ConsentMonitor = /** @class */ (function () {
|
|
|
26
27
|
this._consent = false;
|
|
27
28
|
this._isDevEnvironment = false;
|
|
28
29
|
this._isInitialized = false;
|
|
30
|
+
this._vendorConsents = {
|
|
31
|
+
brandmetrics: false,
|
|
32
|
+
linkedIn: false,
|
|
33
|
+
purpose1: false,
|
|
34
|
+
};
|
|
29
35
|
this.getCookieValue = function (name) { var _a; return ((_a = document.cookie.match("(^|;)\\s*" + name + "\\s*=\\s*([^;]+)")) === null || _a === void 0 ? void 0 : _a.pop()) || ""; };
|
|
30
36
|
//check for FTConsent - cookiesOnSite to trigger custom consent_update event for GTM tags (banner updated)
|
|
31
37
|
this.cookieConsentTest = function () {
|
|
@@ -65,7 +71,9 @@ var ConsentMonitor = /** @class */ (function () {
|
|
|
65
71
|
this._isDevEnvironment = this._devHosts.some(function (h) {
|
|
66
72
|
return _this._hostname.includes(h);
|
|
67
73
|
});
|
|
68
|
-
this.
|
|
74
|
+
this.attachVendorConsentListeners(); // listen to existing consent data fetch
|
|
75
|
+
this.attachCmpListeners(); // listen to banner interaction
|
|
76
|
+
// load banner
|
|
69
77
|
(0, loadFtCmp_1.loadFtCmpScript)()
|
|
70
78
|
.then(function () {
|
|
71
79
|
var propertyConfig = window.location.hostname.endsWith(".ft.com")
|
|
@@ -115,6 +123,23 @@ var ConsentMonitor = /** @class */ (function () {
|
|
|
115
123
|
enumerable: false,
|
|
116
124
|
configurable: true
|
|
117
125
|
});
|
|
126
|
+
Object.defineProperty(ConsentMonitor.prototype, "vendorConsents", {
|
|
127
|
+
get: function () {
|
|
128
|
+
return this._vendorConsents;
|
|
129
|
+
},
|
|
130
|
+
enumerable: false,
|
|
131
|
+
configurable: true
|
|
132
|
+
});
|
|
133
|
+
// Added for required brandmetrics image pixels and linkedin script consent (CMP specific vendor consents integration)
|
|
134
|
+
ConsentMonitor.prototype.attachVendorConsentListeners = function () {
|
|
135
|
+
(0, vendorConsent_1.initVendorConsentListener)(function (vendorConsents) {
|
|
136
|
+
var vendorConsentEvent = new CustomEvent("cmp_vendorConsent", {
|
|
137
|
+
detail: vendorConsents,
|
|
138
|
+
});
|
|
139
|
+
window.dispatchEvent(vendorConsentEvent);
|
|
140
|
+
debug("[CMP Consent lookup Event", vendorConsents);
|
|
141
|
+
});
|
|
142
|
+
};
|
|
118
143
|
ConsentMonitor.prototype.attachCmpListeners = function () {
|
|
119
144
|
var _this = this;
|
|
120
145
|
(0, loadFtCmp_1.enqueueCmpCallback)(function () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/consentMonitor/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,0DAIqC;AACrC,gDAA0B;AAE1B,8CAAuE;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/consentMonitor/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phantomstudios/ft-lib",
|
|
3
3
|
"description": "A collection of Javascript UI & tracking utils for FT sites",
|
|
4
|
-
"version": "0.5.2-
|
|
4
|
+
"version": "0.5.2-rc3",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
7
7
|
"homepage": "https://github.com/phantomstudios/ft-lib#readme",
|
package/src/cmp/loadFtCmp.ts
CHANGED
|
@@ -20,13 +20,6 @@ export function loadFtCmpScript(): Promise<void> {
|
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
// export function enqueueCmpCallback(cb: () => void): void {
|
|
24
|
-
// if (!window._sp_) window._sp_ = {};
|
|
25
|
-
// if (!window._sp_queue) window._sp_queue = [];
|
|
26
|
-
|
|
27
|
-
// window._sp_queue!.push(cb);
|
|
28
|
-
// }
|
|
29
|
-
|
|
30
23
|
export function initCmpQueue(): void {
|
|
31
24
|
window._sp_ = window._sp_ || {};
|
|
32
25
|
window._sp_queue = window._sp_queue || [];
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// 1. Declare Global Window Types for TCF API
|
|
2
|
+
declare global {
|
|
3
|
+
interface Window {
|
|
4
|
+
__tcfapi?: (
|
|
5
|
+
command: string,
|
|
6
|
+
version: number,
|
|
7
|
+
callback: (tcData: TCFData | null, success: boolean) => void,
|
|
8
|
+
parameter?: any,
|
|
9
|
+
) => void;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface TCFData {
|
|
14
|
+
eventStatus: "tcloaded" | "useractioncomplete" | "cmpuishown";
|
|
15
|
+
listenerId: number;
|
|
16
|
+
purpose?: {
|
|
17
|
+
consents?: Record<number, boolean>;
|
|
18
|
+
};
|
|
19
|
+
vendor?: {
|
|
20
|
+
consents?: Record<number, boolean>;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface VendorConsentResults {
|
|
25
|
+
brandmetrics: boolean;
|
|
26
|
+
linkedIn: boolean;
|
|
27
|
+
purpose1: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function initVendorConsentListener(
|
|
31
|
+
onConsentUpdate: (results: VendorConsentResults) => void,
|
|
32
|
+
): void {
|
|
33
|
+
if (typeof window.__tcfapi !== "function") {
|
|
34
|
+
console.warn("[CMP] window.__tcfapi is not defined on this page yet.");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
window.__tcfapi("addEventListener", 2, (tcData, success) => {
|
|
39
|
+
if (!success || !tcData) return;
|
|
40
|
+
|
|
41
|
+
// Handles BOTH returning visitors ('tcloaded') AND live banner updates ('useractioncomplete' / 'cmpuishown')
|
|
42
|
+
const isConsentReady =
|
|
43
|
+
tcData.eventStatus === "tcloaded" ||
|
|
44
|
+
tcData.eventStatus === "useractioncomplete";
|
|
45
|
+
|
|
46
|
+
if (isConsentReady) {
|
|
47
|
+
// Brandmetrics (IAB Vendor ID: 422)
|
|
48
|
+
const brandmetrics = tcData.vendor?.consents?.[422] === true;
|
|
49
|
+
|
|
50
|
+
// LinkedIn (IAB Vendor ID: 804)
|
|
51
|
+
const linkedIn = tcData.vendor?.consents?.[804] === true;
|
|
52
|
+
|
|
53
|
+
// Purpose 1: Device storage/access (Cookies)
|
|
54
|
+
const purpose1 = tcData.purpose?.consents?.[1] === true;
|
|
55
|
+
|
|
56
|
+
const results: VendorConsentResults = {
|
|
57
|
+
brandmetrics,
|
|
58
|
+
linkedIn,
|
|
59
|
+
purpose1,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Trigger your callback handler every time consent status updates
|
|
63
|
+
onConsentUpdate(results);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -6,6 +6,10 @@ import {
|
|
|
6
6
|
import Debug from "debug";
|
|
7
7
|
|
|
8
8
|
import { enqueueCmpCallback, loadFtCmpScript } from "../cmp/loadFtCmp";
|
|
9
|
+
import {
|
|
10
|
+
initVendorConsentListener,
|
|
11
|
+
VendorConsentResults,
|
|
12
|
+
} from "../cmp/vendorConsent";
|
|
9
13
|
|
|
10
14
|
const debug = Debug("@phantomstudios/ft-lib/consentMonitor");
|
|
11
15
|
|
|
@@ -35,6 +39,11 @@ export class ConsentMonitor {
|
|
|
35
39
|
private _isDevEnvironment = false;
|
|
36
40
|
private _isInitialized = false;
|
|
37
41
|
private _hostname: string;
|
|
42
|
+
private _vendorConsents = {
|
|
43
|
+
brandmetrics: false,
|
|
44
|
+
linkedIn: false,
|
|
45
|
+
purpose1: false,
|
|
46
|
+
} as VendorConsentResults;
|
|
38
47
|
|
|
39
48
|
public get consent(): boolean {
|
|
40
49
|
return this._consent;
|
|
@@ -48,10 +57,12 @@ export class ConsentMonitor {
|
|
|
48
57
|
public get isInitialized(): boolean {
|
|
49
58
|
return this._isInitialized;
|
|
50
59
|
}
|
|
51
|
-
|
|
52
60
|
public get userHasConsented(): boolean {
|
|
53
61
|
return this._consent;
|
|
54
62
|
}
|
|
63
|
+
public get vendorConsents(): VendorConsentResults {
|
|
64
|
+
return this._vendorConsents;
|
|
65
|
+
}
|
|
55
66
|
|
|
56
67
|
getCookieValue = (name: string) =>
|
|
57
68
|
document.cookie.match("(^|;)\\s*" + name + "\\s*=\\s*([^;]+)")?.pop() || "";
|
|
@@ -71,7 +82,10 @@ export class ConsentMonitor {
|
|
|
71
82
|
this._hostname.includes(h),
|
|
72
83
|
);
|
|
73
84
|
|
|
74
|
-
this.
|
|
85
|
+
this.attachVendorConsentListeners(); // listen to existing consent data fetch
|
|
86
|
+
this.attachCmpListeners(); // listen to banner interaction
|
|
87
|
+
|
|
88
|
+
// load banner
|
|
75
89
|
loadFtCmpScript()
|
|
76
90
|
.then(() => {
|
|
77
91
|
const propertyConfig = window.location.hostname.endsWith(".ft.com")
|
|
@@ -88,6 +102,18 @@ export class ConsentMonitor {
|
|
|
88
102
|
.catch((err) => console.error(err));
|
|
89
103
|
}
|
|
90
104
|
|
|
105
|
+
// Added for required brandmetrics image pixels and linkedin script consent (CMP specific vendor consents integration)
|
|
106
|
+
private attachVendorConsentListeners(): void {
|
|
107
|
+
initVendorConsentListener((vendorConsents: VendorConsentResults) => {
|
|
108
|
+
const vendorConsentEvent = new CustomEvent("cmp_vendorConsent", {
|
|
109
|
+
detail: vendorConsents,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
window.dispatchEvent(vendorConsentEvent);
|
|
113
|
+
debug("[CMP Consent lookup Event", vendorConsents);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
91
117
|
private attachCmpListeners(): void {
|
|
92
118
|
enqueueCmpCallback(() => {
|
|
93
119
|
const onReady: ConsentReadyHandler = (_l, _u, _t, info) => {
|