@phantomstudios/ft-lib 0.5.2-rc1 → 0.5.2-rc10

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.
@@ -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;AASD,wBAAgB,YAAY,IAAI,IAAI,CAGnC;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAGvD"}
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"}
@@ -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 || [];
@@ -1 +1 @@
1
- {"version":3,"file":"loadFtCmp.js","sourceRoot":"","sources":["../../src/cmp/loadFtCmp.ts"],"names":[],"mappings":";;AAAA,0CAoBC;AASD,oCAGC;AAED,gDAGC;AArCD,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,6DAA6D;AAC7D,wCAAwC;AACxC,kDAAkD;AAElD,gCAAgC;AAChC,IAAI;AAEJ,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"}
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,9 @@
1
+ export interface VendorConsentResults {
2
+ brandmetrics: boolean;
3
+ linkedIn: boolean;
4
+ purpose1: boolean;
5
+ gdprApplies: boolean;
6
+ usnatApplies: boolean;
7
+ }
8
+ export declare function initVendorConsentListener(onConsentUpdate: (results: VendorConsentResults) => void): void;
9
+ //# sourceMappingURL=vendorConsent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vendorConsent.d.ts","sourceRoot":"","sources":["../../src/cmp/vendorConsent.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,yBAAyB,CACvC,eAAe,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GACvD,IAAI,CAqDN"}
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initVendorConsentListener = initVendorConsentListener;
4
+ function initVendorConsentListener(onConsentUpdate) {
5
+ // --- Path 1: Check TCF API First ---
6
+ if (typeof window.__tcfapi === "function") {
7
+ window.__tcfapi("addEventListener", 2, function (tcData, success) {
8
+ var _a, _b, _c, _d, _e, _f, _g, _h;
9
+ if (!success || !tcData)
10
+ return;
11
+ var isConsentReady = tcData.eventStatus === "tcloaded" ||
12
+ tcData.eventStatus === "useractioncomplete";
13
+ if (isConsentReady) {
14
+ // If GDPR actually applies, process TCF consents (Opt-In model)
15
+ if (tcData.gdprApplies !== false) {
16
+ var results = {
17
+ brandmetrics: ((_b = (_a = tcData.vendor) === null || _a === void 0 ? void 0 : _a.consents) === null || _b === void 0 ? void 0 : _b[422]) === true,
18
+ linkedIn: ((_d = (_c = tcData.vendor) === null || _c === void 0 ? void 0 : _c.consents) === null || _d === void 0 ? void 0 : _d[804]) === true,
19
+ purpose1: ((_f = (_e = tcData.purpose) === null || _e === void 0 ? void 0 : _e.consents) === null || _f === void 0 ? void 0 : _f[1]) === true,
20
+ gdprApplies: true,
21
+ usnatApplies: false,
22
+ };
23
+ onConsentUpdate(results);
24
+ // Clean up TCF listener
25
+ if (typeof tcData.listenerId === "number") {
26
+ (_g = window.__tcfapi) === null || _g === void 0 ? void 0 : _g.call(window, "removeEventListener", 2, function () { }, tcData.listenerId);
27
+ }
28
+ return;
29
+ }
30
+ // --- Path 2: TCF explicitly returned gdprApplies: false -> Fall back to USNat ---
31
+ evaluateUSNatConsent(onConsentUpdate);
32
+ // Clean up TCF listener since GDPR does not apply
33
+ if (typeof tcData.listenerId === "number") {
34
+ (_h = window.__tcfapi) === null || _h === void 0 ? void 0 : _h.call(window, "removeEventListener", 2, function () { }, tcData.listenerId);
35
+ }
36
+ }
37
+ });
38
+ }
39
+ else {
40
+ // If __tcfapi doesn't exist at all, try evaluating USNat directly
41
+ evaluateUSNatConsent(onConsentUpdate);
42
+ }
43
+ }
44
+ /**
45
+ * Helper to evaluate USNat / US Privacy consent (Opt-Out model)
46
+ */
47
+ function evaluateUSNatConsent(onConsentUpdate) {
48
+ var _a, _b;
49
+ // Option A: Preferred Sourcepoint SDK method
50
+ if (typeof ((_b = (_a = window._sp_) === null || _a === void 0 ? void 0 : _a.usnat) === null || _b === void 0 ? void 0 : _b.getUserConsents) === "function") {
51
+ window._sp_.usnat.getUserConsents(function (consents) {
52
+ // US Privacy is OPT-OUT by default.
53
+ // If the user has NOT opted out, consent is considered granted for all vendors/purposes.
54
+ var isOptedOut = (consents === null || consents === void 0 ? void 0 : consents.optedOut) === true ||
55
+ (Array.isArray(consents === null || consents === void 0 ? void 0 : consents.rejectedCategories) &&
56
+ consents.rejectedCategories.length > 0);
57
+ var isConsented = !isOptedOut;
58
+ onConsentUpdate({
59
+ brandmetrics: isConsented,
60
+ linkedIn: isConsented,
61
+ purpose1: isConsented,
62
+ gdprApplies: false,
63
+ usnatApplies: true,
64
+ });
65
+ });
66
+ return;
67
+ }
68
+ // Option B: Fallback to GPP standard API
69
+ if (typeof window.__gpp === "function") {
70
+ window.__gpp("getGPPData", function (gppData, success) {
71
+ var _a;
72
+ if (!success || !gppData)
73
+ return;
74
+ var usnat = (_a = gppData.parsedSections) === null || _a === void 0 ? void 0 : _a.usnat;
75
+ // GPP USNat spec: 1 = Opted Out / Yes
76
+ var isOptedOut = (usnat === null || usnat === void 0 ? void 0 : usnat.SharingOptOut) === 1 ||
77
+ (usnat === null || usnat === void 0 ? void 0 : usnat.TargetedAdvertisingOptOut) === 1 ||
78
+ (usnat === null || usnat === void 0 ? void 0 : usnat.SaleOptOut) === 1;
79
+ var isConsented = !isOptedOut;
80
+ onConsentUpdate({
81
+ brandmetrics: isConsented,
82
+ linkedIn: isConsented,
83
+ purpose1: isConsented,
84
+ gdprApplies: false,
85
+ usnatApplies: true,
86
+ });
87
+ });
88
+ }
89
+ }
90
+ //# sourceMappingURL=vendorConsent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vendorConsent.js","sourceRoot":"","sources":["../../src/cmp/vendorConsent.ts"],"names":[],"mappings":";;AAQA,8DAuDC;AAvDD,SAAgB,yBAAyB,CACvC,eAAwD;IAExD,sCAAsC;IACtC,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC1C,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,EAAE,UAAC,MAAM,EAAE,OAAO;;YACrD,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM;gBAAE,OAAO;YAEhC,IAAM,cAAc,GAClB,MAAM,CAAC,WAAW,KAAK,UAAU;gBACjC,MAAM,CAAC,WAAW,KAAK,oBAAoB,CAAC;YAE9C,IAAI,cAAc,EAAE,CAAC;gBACnB,gEAAgE;gBAChE,IAAI,MAAM,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;oBACjC,IAAM,OAAO,GAAyB;wBACpC,YAAY,EAAE,CAAA,MAAA,MAAA,MAAM,CAAC,MAAM,0CAAE,QAAQ,0CAAG,GAAG,CAAC,MAAK,IAAI;wBACrD,QAAQ,EAAE,CAAA,MAAA,MAAA,MAAM,CAAC,MAAM,0CAAE,QAAQ,0CAAG,GAAG,CAAC,MAAK,IAAI;wBACjD,QAAQ,EAAE,CAAA,MAAA,MAAA,MAAM,CAAC,OAAO,0CAAE,QAAQ,0CAAG,CAAC,CAAC,MAAK,IAAI;wBAChD,WAAW,EAAE,IAAI;wBACjB,YAAY,EAAE,KAAK;qBACpB,CAAC;oBAEF,eAAe,CAAC,OAAO,CAAC,CAAC;oBAEzB,wBAAwB;oBACxB,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;wBAC1C,MAAA,MAAM,CAAC,QAAQ,uDACb,qBAAqB,EACrB,CAAC,EACD,cAAO,CAAC,EACR,MAAM,CAAC,UAAU,CAClB,CAAC;oBACJ,CAAC;oBACD,OAAO;gBACT,CAAC;gBAED,mFAAmF;gBACnF,oBAAoB,CAAC,eAAe,CAAC,CAAC;gBAEtC,kDAAkD;gBAClD,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;oBAC1C,MAAA,MAAM,CAAC,QAAQ,uDACb,qBAAqB,EACrB,CAAC,EACD,cAAO,CAAC,EACR,MAAM,CAAC,UAAU,CAClB,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,kEAAkE;QAClE,oBAAoB,CAAC,eAAe,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAC3B,eAAwD;;IAExD,6CAA6C;IAC7C,IAAI,OAAO,CAAA,MAAA,MAAA,MAAM,CAAC,IAAI,0CAAE,KAAK,0CAAE,eAAe,CAAA,KAAK,UAAU,EAAE,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,UAAC,QAAQ;YACzC,oCAAoC;YACpC,yFAAyF;YACzF,IAAM,UAAU,GACd,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,QAAQ,MAAK,IAAI;gBAC3B,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,kBAAkB,CAAC;oBAC1C,QAAQ,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAE5C,IAAM,WAAW,GAAG,CAAC,UAAU,CAAC;YAEhC,eAAe,CAAC;gBACd,YAAY,EAAE,WAAW;gBACzB,QAAQ,EAAE,WAAW;gBACrB,QAAQ,EAAE,WAAW;gBACrB,WAAW,EAAE,KAAK;gBAClB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,yCAAyC;IACzC,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,UAAC,OAAY,EAAE,OAAgB;;YACxD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO;gBAAE,OAAO;YAEjC,IAAM,KAAK,GAAG,MAAA,OAAO,CAAC,cAAc,0CAAE,KAAK,CAAC;YAE5C,sCAAsC;YACtC,IAAM,UAAU,GACd,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,aAAa,MAAK,CAAC;gBAC1B,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,yBAAyB,MAAK,CAAC;gBACtC,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,UAAU,MAAK,CAAC,CAAC;YAE1B,IAAM,WAAW,GAAG,CAAC,UAAU,CAAC;YAEhC,eAAe,CAAC;gBACd,YAAY,EAAE,WAAW;gBACzB,QAAQ,EAAE,WAAW;gBACrB,QAAQ,EAAE,WAAW;gBACrB,WAAW,EAAE,KAAK;gBAClB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;AACH,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":"AA+BA,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;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;IAED,IAAW,gBAAgB,IAAI,OAAO,CAErC;IAED,cAAc,GAAI,MAAM,MAAM,YACgD;gBAElE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM;IAgC3D,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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/consentMonitor/index.ts"],"names":[],"mappings":"AAIA,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,CAMG;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;IA4B3D,OAAO,CAAC,4BAA4B;IAapC,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,13 @@ 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
+ gdprApplies: false,
35
+ usnatApplies: false,
36
+ };
29
37
  this.getCookieValue = function (name) { var _a; return ((_a = document.cookie.match("(^|;)\\s*" + name + "\\s*=\\s*([^;]+)")) === null || _a === void 0 ? void 0 : _a.pop()) || ""; };
30
38
  //check for FTConsent - cookiesOnSite to trigger custom consent_update event for GTM tags (banner updated)
31
39
  this.cookieConsentTest = function () {
@@ -65,16 +73,11 @@ var ConsentMonitor = /** @class */ (function () {
65
73
  this._isDevEnvironment = this._devHosts.some(function (h) {
66
74
  return _this._hostname.includes(h);
67
75
  });
68
- this.attachCmpListeners();
76
+ this.attachVendorConsentListeners(); // listen to existing consent data fetch
77
+ this.attachCmpListeners(); // listen to banner interaction
78
+ // load banner
69
79
  (0, loadFtCmp_1.loadFtCmpScript)()
70
80
  .then(function () {
71
- var propertyConfig = window.location.hostname.endsWith(".ft.com")
72
- ? cmp_client_1.properties["FT_DOTCOM_PROD"]
73
- : cmp_client_1.properties["FT_DOTCOM_TEST"];
74
- // initialize CMP
75
- (0, cmp_client_1.initSourcepointCmp)({ propertyConfig: propertyConfig });
76
- // use cmp client lib to intercept footer 'Manage Cookies' links (opens privacy modal)
77
- // Note, function requires very specific link: text = 'Manage Cookies' and href = 'https://ft.com/preferences/manage-cookies'
78
81
  (0, cmp_client_1.interceptManageCookiesLinks)();
79
82
  _this._isInitialized = true;
80
83
  })
@@ -115,6 +118,25 @@ var ConsentMonitor = /** @class */ (function () {
115
118
  enumerable: false,
116
119
  configurable: true
117
120
  });
121
+ Object.defineProperty(ConsentMonitor.prototype, "vendorConsents", {
122
+ get: function () {
123
+ return this._vendorConsents;
124
+ },
125
+ enumerable: false,
126
+ configurable: true
127
+ });
128
+ // Added for required brandmetrics image pixels and linkedin script consent (CMP specific vendor consents integration)
129
+ ConsentMonitor.prototype.attachVendorConsentListeners = function () {
130
+ (0, loadFtCmp_1.enqueueCmpCallback)(function () {
131
+ (0, vendorConsent_1.initVendorConsentListener)(function (vendorConsents) {
132
+ var vendorConsentEvent = new CustomEvent("cmp_vendorConsent", {
133
+ detail: vendorConsents,
134
+ });
135
+ window.dispatchEvent(vendorConsentEvent);
136
+ debug("[CMP Consent lookup Event", vendorConsents);
137
+ });
138
+ });
139
+ };
118
140
  ConsentMonitor.prototype.attachCmpListeners = function () {
119
141
  var _this = this;
120
142
  (0, loadFtCmp_1.enqueueCmpCallback)(function () {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/consentMonitor/index.ts"],"names":[],"mappings":"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"}
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-rc1",
4
+ "version": "0.5.2-rc10",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "homepage": "https://github.com/phantomstudios/ft-lib#readme",
@@ -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,119 @@
1
+ export interface VendorConsentResults {
2
+ brandmetrics: boolean;
3
+ linkedIn: boolean;
4
+ purpose1: boolean;
5
+ gdprApplies: boolean;
6
+ usnatApplies: boolean;
7
+ }
8
+
9
+ export function initVendorConsentListener(
10
+ onConsentUpdate: (results: VendorConsentResults) => void,
11
+ ): void {
12
+ // --- Path 1: Check TCF API First ---
13
+ if (typeof window.__tcfapi === "function") {
14
+ window.__tcfapi("addEventListener", 2, (tcData, success) => {
15
+ if (!success || !tcData) return;
16
+
17
+ const isConsentReady =
18
+ tcData.eventStatus === "tcloaded" ||
19
+ tcData.eventStatus === "useractioncomplete";
20
+
21
+ if (isConsentReady) {
22
+ // If GDPR actually applies, process TCF consents (Opt-In model)
23
+ if (tcData.gdprApplies !== false) {
24
+ const results: VendorConsentResults = {
25
+ brandmetrics: tcData.vendor?.consents?.[422] === true,
26
+ linkedIn: tcData.vendor?.consents?.[804] === true,
27
+ purpose1: tcData.purpose?.consents?.[1] === true,
28
+ gdprApplies: true,
29
+ usnatApplies: false,
30
+ };
31
+
32
+ onConsentUpdate(results);
33
+
34
+ // Clean up TCF listener
35
+ if (typeof tcData.listenerId === "number") {
36
+ window.__tcfapi?.(
37
+ "removeEventListener",
38
+ 2,
39
+ () => {},
40
+ tcData.listenerId,
41
+ );
42
+ }
43
+ return;
44
+ }
45
+
46
+ // --- Path 2: TCF explicitly returned gdprApplies: false -> Fall back to USNat ---
47
+ evaluateUSNatConsent(onConsentUpdate);
48
+
49
+ // Clean up TCF listener since GDPR does not apply
50
+ if (typeof tcData.listenerId === "number") {
51
+ window.__tcfapi?.(
52
+ "removeEventListener",
53
+ 2,
54
+ () => {},
55
+ tcData.listenerId,
56
+ );
57
+ }
58
+ }
59
+ });
60
+ } else {
61
+ // If __tcfapi doesn't exist at all, try evaluating USNat directly
62
+ evaluateUSNatConsent(onConsentUpdate);
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Helper to evaluate USNat / US Privacy consent (Opt-Out model)
68
+ */
69
+ function evaluateUSNatConsent(
70
+ onConsentUpdate: (results: VendorConsentResults) => void,
71
+ ): void {
72
+ // Option A: Preferred Sourcepoint SDK method
73
+ if (typeof window._sp_?.usnat?.getUserConsents === "function") {
74
+ window._sp_.usnat.getUserConsents((consents) => {
75
+ // US Privacy is OPT-OUT by default.
76
+ // If the user has NOT opted out, consent is considered granted for all vendors/purposes.
77
+ const isOptedOut =
78
+ consents?.optedOut === true ||
79
+ (Array.isArray(consents?.rejectedCategories) &&
80
+ consents.rejectedCategories.length > 0);
81
+
82
+ const isConsented = !isOptedOut;
83
+
84
+ onConsentUpdate({
85
+ brandmetrics: isConsented,
86
+ linkedIn: isConsented,
87
+ purpose1: isConsented,
88
+ gdprApplies: false,
89
+ usnatApplies: true,
90
+ });
91
+ });
92
+ return;
93
+ }
94
+
95
+ // Option B: Fallback to GPP standard API
96
+ if (typeof window.__gpp === "function") {
97
+ window.__gpp("getGPPData", (gppData: any, success: boolean) => {
98
+ if (!success || !gppData) return;
99
+
100
+ const usnat = gppData.parsedSections?.usnat;
101
+
102
+ // GPP USNat spec: 1 = Opted Out / Yes
103
+ const isOptedOut =
104
+ usnat?.SharingOptOut === 1 ||
105
+ usnat?.TargetedAdvertisingOptOut === 1 ||
106
+ usnat?.SaleOptOut === 1;
107
+
108
+ const isConsented = !isOptedOut;
109
+
110
+ onConsentUpdate({
111
+ brandmetrics: isConsented,
112
+ linkedIn: isConsented,
113
+ purpose1: isConsented,
114
+ gdprApplies: false,
115
+ usnatApplies: true,
116
+ });
117
+ });
118
+ }
119
+ }
@@ -1,11 +1,11 @@
1
- import {
2
- initSourcepointCmp,
3
- interceptManageCookiesLinks,
4
- properties,
5
- } from "@financial-times/cmp-client";
1
+ import { interceptManageCookiesLinks } from "@financial-times/cmp-client";
6
2
  import Debug from "debug";
7
3
 
8
4
  import { enqueueCmpCallback, loadFtCmpScript } from "../cmp/loadFtCmp";
5
+ import {
6
+ initVendorConsentListener,
7
+ VendorConsentResults,
8
+ } from "../cmp/vendorConsent";
9
9
 
10
10
  const debug = Debug("@phantomstudios/ft-lib/consentMonitor");
11
11
 
@@ -35,6 +35,13 @@ export class ConsentMonitor {
35
35
  private _isDevEnvironment = false;
36
36
  private _isInitialized = false;
37
37
  private _hostname: string;
38
+ private _vendorConsents = {
39
+ brandmetrics: false,
40
+ linkedIn: false,
41
+ purpose1: false,
42
+ gdprApplies: false,
43
+ usnatApplies: false,
44
+ } as VendorConsentResults;
38
45
 
39
46
  public get consent(): boolean {
40
47
  return this._consent;
@@ -48,10 +55,12 @@ export class ConsentMonitor {
48
55
  public get isInitialized(): boolean {
49
56
  return this._isInitialized;
50
57
  }
51
-
52
58
  public get userHasConsented(): boolean {
53
59
  return this._consent;
54
60
  }
61
+ public get vendorConsents(): VendorConsentResults {
62
+ return this._vendorConsents;
63
+ }
55
64
 
56
65
  getCookieValue = (name: string) =>
57
66
  document.cookie.match("(^|;)\\s*" + name + "\\s*=\\s*([^;]+)")?.pop() || "";
@@ -71,23 +80,32 @@ export class ConsentMonitor {
71
80
  this._hostname.includes(h),
72
81
  );
73
82
 
74
- this.attachCmpListeners();
83
+ this.attachVendorConsentListeners(); // listen to existing consent data fetch
84
+ this.attachCmpListeners(); // listen to banner interaction
85
+
86
+ // load banner
75
87
  loadFtCmpScript()
76
88
  .then(() => {
77
- const propertyConfig = window.location.hostname.endsWith(".ft.com")
78
- ? properties["FT_DOTCOM_PROD"]
79
- : properties["FT_DOTCOM_TEST"];
80
-
81
- // initialize CMP
82
- initSourcepointCmp({ propertyConfig });
83
- // use cmp client lib to intercept footer 'Manage Cookies' links (opens privacy modal)
84
- // Note, function requires very specific link: text = 'Manage Cookies' and href = 'https://ft.com/preferences/manage-cookies'
85
89
  interceptManageCookiesLinks();
86
90
  this._isInitialized = true;
87
91
  })
88
92
  .catch((err) => console.error(err));
89
93
  }
90
94
 
95
+ // Added for required brandmetrics image pixels and linkedin script consent (CMP specific vendor consents integration)
96
+ private attachVendorConsentListeners(): void {
97
+ enqueueCmpCallback(() => {
98
+ initVendorConsentListener((vendorConsents: VendorConsentResults) => {
99
+ const vendorConsentEvent = new CustomEvent("cmp_vendorConsent", {
100
+ detail: vendorConsents,
101
+ });
102
+
103
+ window.dispatchEvent(vendorConsentEvent);
104
+ debug("[CMP Consent lookup Event", vendorConsents);
105
+ });
106
+ });
107
+ }
108
+
91
109
  private attachCmpListeners(): void {
92
110
  enqueueCmpCallback(() => {
93
111
  const onReady: ConsentReadyHandler = (_l, _u, _t, info) => {
package/src/types.d.ts CHANGED
@@ -15,17 +15,44 @@ declare module "@financial-times/cmp-client" {
15
15
  propertyConfig?: any;
16
16
  }): Promise<void>;
17
17
  }
18
+
19
+ interface TCFData {
20
+ eventStatus: "tcloaded" | "useractioncomplete" | "cmpuishown";
21
+ listenerId: number;
22
+ purpose?: {
23
+ consents?: Record<number, boolean>;
24
+ };
25
+ vendor?: {
26
+ consents?: Record<number, boolean>;
27
+ };
28
+ gdprApplies?: boolean | undefined;
29
+ }
18
30
  interface SourcepointCmpAPI {
19
31
  queue?: Array<() => void>;
20
32
  addEventListener?: (
21
33
  eventName: string,
22
-
23
34
  callback: (...args: any[]) => void,
24
35
  ) => void;
36
+ usnat?: {
37
+ getUserConsents: (callback: (consents: any) => void) => void;
38
+ };
25
39
  }
40
+
26
41
  interface Window {
27
42
  _sp_: SourcepointCmpAPI;
28
43
  _sp_queue?: Array<() => void>;
44
+ __tcfapi?: (
45
+ command: string,
46
+ version: number,
47
+ callback: (tcData: TCFData | null, success: boolean) => void,
48
+ parameter?: any,
49
+ ) => void;
50
+ __gpp?: (
51
+ command: string,
52
+ callback?: (data: any, success: boolean) => void,
53
+ parameter?: any,
54
+ ) => void;
55
+
29
56
  dataLayer: any;
30
57
  gtag: any;
31
58
  permutive: {