@financial-times/cmp-client 3.5.0-beta.1 → 4.0.0

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/README.md CHANGED
@@ -50,7 +50,7 @@ By default the source link integrates the latest version of the CMP client. If y
50
50
  import {
51
51
  initSourcepointCmp,
52
52
  properties,
53
- updateFooterLinkCMP,
53
+ interceptManageCookiesLinks,
54
54
  debug,
55
55
  } from "@financial-times/cmp-client";
56
56
 
@@ -72,9 +72,9 @@ initSourcepointCmp({
72
72
  useConsentStore: false, // Specialist Titles _must_ opt out of Single Consent Store
73
73
  });
74
74
  /**
75
- * Optionally enable "Manage Cookies" footer link util
75
+ * Optionally enable "Manage Cookies" link util
76
76
  */
77
- updateFooterLinkCMP(properties["YOUR_PROPERTY_CONFIG_KEY"]);
77
+ interceptManageCookiesLinks(properties["YOUR_PROPERTY_CONFIG_KEY"]);
78
78
  ```
79
79
 
80
80
  ### Usage on FT.com
@@ -83,7 +83,7 @@ updateFooterLinkCMP(properties["YOUR_PROPERTY_CONFIG_KEY"]);
83
83
  import {
84
84
  initSourcepointCmp,
85
85
  properties,
86
- updateFooterLinkCMP,
86
+ interceptManageCookiesLinks,
87
87
  debug,
88
88
  } from "@financial-times/cmp-client";
89
89
 
@@ -100,7 +100,7 @@ if (flagsClient.get("adsDisableInternalCMP")) {
100
100
  initSourcepointCmp({
101
101
  propertyConfig: FT_DOTCOM_TEST,
102
102
  });
103
- updateFooterLinkCMP();
103
+ interceptManageCookiesLinks();
104
104
  }
105
105
  ```
106
106
 
package/dist/index.cjs CHANGED
@@ -165,22 +165,42 @@ const properties = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
165
165
  SP_SUSTAINABLE_VIEWS,
166
166
  SP_THE_BANKER
167
167
  }, Symbol.toStringTag, { value: "Module" }));
168
- function updateFooterLinkCMP(propertyConfig = FT_DOTCOM_PROD) {
169
- const { privacyManagerId, manageCookiesLinkOverride, manageCookiesSelector } = propertyConfig._clientOptions || {};
170
- const footer = document.querySelector(manageCookiesSelector ?? "#site-footer");
171
- if (footer && manageCookiesLinkOverride) {
172
- footer.addEventListener("click", (event) => {
173
- var _a, _b, _c;
174
- const link = event.target.closest("a");
175
- if ((_a = link == null ? void 0 : link.getAttribute("href")) == null ? void 0 : _a.endsWith(manageCookiesLinkOverride)) {
176
- event.preventDefault();
177
- (_c = (_b = window._sp_) == null ? void 0 : _b.gdpr) == null ? void 0 : _c.loadPrivacyManagerModal(privacyManagerId);
178
- }
168
+ const onDomReady = new Promise((resolve) => {
169
+ if (typeof document === "undefined")
170
+ return resolve();
171
+ const isReady = () => ["interactive", "complete"].includes(document.readyState);
172
+ function onStateChange() {
173
+ if (isReady()) {
174
+ document.removeEventListener("readystatechange", onStateChange);
175
+ resolve();
176
+ }
177
+ }
178
+ if (isReady())
179
+ return resolve();
180
+ document.addEventListener("readystatechange", onStateChange);
181
+ });
182
+ function findAndUpdateLinks(_clientOptions, loadPrivacyManagerModal) {
183
+ const { privacyManagerId, manageCookiesLinkOverride } = _clientOptions ?? {};
184
+ if (!privacyManagerId || !manageCookiesLinkOverride) {
185
+ return console.warn("_clientOptions is missing privacyManagerId or manageCookiesLinkOverride");
186
+ }
187
+ const anchors = document.querySelectorAll(`a[href*="${manageCookiesLinkOverride}"]`);
188
+ for (const anchor of anchors) {
189
+ anchor.addEventListener("click", (event) => {
190
+ event.preventDefault();
191
+ loadPrivacyManagerModal == null ? void 0 : loadPrivacyManagerModal(+privacyManagerId);
179
192
  });
180
- } else {
181
- console.warn("No footer found for", manageCookiesSelector);
182
193
  }
183
194
  }
195
+ function interceptManageCookiesLinks({ _clientOptions } = FT_DOTCOM_PROD) {
196
+ onDomReady.then(() => {
197
+ window._sp_queue ?? (window._sp_queue = []);
198
+ window._sp_queue.push(() => {
199
+ var _a, _b;
200
+ findAndUpdateLinks(_clientOptions, (_b = (_a = window._sp_) == null ? void 0 : _a.gdpr) == null ? void 0 : _b.loadPrivacyManagerModal);
201
+ });
202
+ });
203
+ }
184
204
  const request = (url, { credentials = "omit" } = {}) => {
185
205
  return fetch(`https://session-next.ft.com${url}`, {
186
206
  credentials,
@@ -620,7 +640,7 @@ function setupPmTracking(trackingProps, cmpBaseEndpoint) {
620
640
  false
621
641
  );
622
642
  }
623
- const version = "3.5.0-beta.1";
643
+ const version = "4.0.0";
624
644
  async function initSourcepointCmp({
625
645
  propertyConfig = FT_DOTCOM_PROD,
626
646
  userId,
@@ -677,5 +697,5 @@ async function initSourcepointCmp({
677
697
  }
678
698
  exports.debug = debug;
679
699
  exports.initSourcepointCmp = initSourcepointCmp;
700
+ exports.interceptManageCookiesLinks = interceptManageCookiesLinks;
680
701
  exports.properties = properties;
681
- exports.updateFooterLinkCMP = updateFooterLinkCMP;
package/dist/index.js CHANGED
@@ -163,22 +163,42 @@ const properties = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
163
163
  SP_SUSTAINABLE_VIEWS,
164
164
  SP_THE_BANKER
165
165
  }, Symbol.toStringTag, { value: "Module" }));
166
- function updateFooterLinkCMP(propertyConfig = FT_DOTCOM_PROD) {
167
- const { privacyManagerId, manageCookiesLinkOverride, manageCookiesSelector } = propertyConfig._clientOptions || {};
168
- const footer = document.querySelector(manageCookiesSelector ?? "#site-footer");
169
- if (footer && manageCookiesLinkOverride) {
170
- footer.addEventListener("click", (event) => {
171
- var _a, _b, _c;
172
- const link = event.target.closest("a");
173
- if ((_a = link == null ? void 0 : link.getAttribute("href")) == null ? void 0 : _a.endsWith(manageCookiesLinkOverride)) {
174
- event.preventDefault();
175
- (_c = (_b = window._sp_) == null ? void 0 : _b.gdpr) == null ? void 0 : _c.loadPrivacyManagerModal(privacyManagerId);
176
- }
166
+ const onDomReady = new Promise((resolve) => {
167
+ if (typeof document === "undefined")
168
+ return resolve();
169
+ const isReady = () => ["interactive", "complete"].includes(document.readyState);
170
+ function onStateChange() {
171
+ if (isReady()) {
172
+ document.removeEventListener("readystatechange", onStateChange);
173
+ resolve();
174
+ }
175
+ }
176
+ if (isReady())
177
+ return resolve();
178
+ document.addEventListener("readystatechange", onStateChange);
179
+ });
180
+ function findAndUpdateLinks(_clientOptions, loadPrivacyManagerModal) {
181
+ const { privacyManagerId, manageCookiesLinkOverride } = _clientOptions ?? {};
182
+ if (!privacyManagerId || !manageCookiesLinkOverride) {
183
+ return console.warn("_clientOptions is missing privacyManagerId or manageCookiesLinkOverride");
184
+ }
185
+ const anchors = document.querySelectorAll(`a[href*="${manageCookiesLinkOverride}"]`);
186
+ for (const anchor of anchors) {
187
+ anchor.addEventListener("click", (event) => {
188
+ event.preventDefault();
189
+ loadPrivacyManagerModal == null ? void 0 : loadPrivacyManagerModal(+privacyManagerId);
177
190
  });
178
- } else {
179
- console.warn("No footer found for", manageCookiesSelector);
180
191
  }
181
192
  }
193
+ function interceptManageCookiesLinks({ _clientOptions } = FT_DOTCOM_PROD) {
194
+ onDomReady.then(() => {
195
+ window._sp_queue ?? (window._sp_queue = []);
196
+ window._sp_queue.push(() => {
197
+ var _a, _b;
198
+ findAndUpdateLinks(_clientOptions, (_b = (_a = window._sp_) == null ? void 0 : _a.gdpr) == null ? void 0 : _b.loadPrivacyManagerModal);
199
+ });
200
+ });
201
+ }
182
202
  const request = (url, { credentials = "omit" } = {}) => {
183
203
  return fetch(`https://session-next.ft.com${url}`, {
184
204
  credentials,
@@ -618,7 +638,7 @@ function setupPmTracking(trackingProps, cmpBaseEndpoint) {
618
638
  false
619
639
  );
620
640
  }
621
- const version = "3.5.0-beta.1";
641
+ const version = "4.0.0";
622
642
  async function initSourcepointCmp({
623
643
  propertyConfig = FT_DOTCOM_PROD,
624
644
  userId,
@@ -676,6 +696,6 @@ async function initSourcepointCmp({
676
696
  export {
677
697
  debug,
678
698
  initSourcepointCmp,
679
- properties,
680
- updateFooterLinkCMP
699
+ interceptManageCookiesLinks,
700
+ properties
681
701
  };
@@ -1 +1 @@
1
- (function(){"use strict";const T=(e,{credentials:n="omit"}={})=>fetch(`https://session-next.ft.com${e}`,{credentials:n,useCorsProxy:!0}).then(t=>t.ok?t.json():t.text().then(o=>{throw new Error(`Next session responded with "${o}" (${t.status})`)})).catch(t=>{document.body.dispatchEvent(new CustomEvent("oErrors.log",{bubbles:!0,detail:{error:t,info:{component:"next-session-client"}}}))});let d={};const _=(e,n)=>{if(typeof e=="object"){d=e;return}if(typeof e=="string"&&typeof n=="string"){d[e]=n;return}if(typeof e=="string"&&typeof n>"u")return d[e]||null;if(typeof e>"u"&&typeof n>"u")return d;throw new Error("Invalid arguments")};_.clear=()=>{d={}};const l={},k=()=>{const[,e]=/FTSession_s=([^;]+)/.exec(document.cookie)||[];return e},P=()=>{const e=_("uuid");if(e)return Promise.resolve({uuid:e});const n=k();return n?(l.uuid||(l.uuid=T(`/sessions/s/${n}`).then(({uuid:t}={})=>(delete l.uuid,t&&_("uuid",t),{uuid:t}))),l.uuid):Promise.resolve({uuid:void 0})},h="sourcepoint-cmp",N="FTPINK",M="FTConsent",L="sourcepointCmp/VngD.XycZut.595cp9fWdp5XYP9vlFvk",A=".ft.com",D="https://consent.ft.com",v={permutiveAds:{purposes:[2,4,8,9],iabVendors:[361],customVendors:[],specialFeatures:[]},demographicAds:{purposes:[3,4,7,9,10],iabVendors:[],customVendors:[],specialFeatures:[]},behaviouralAds:{purposes:[2,4,8,9],iabVendors:[],customVendors:[],specialFeatures:[]},programmaticAds:{purposes:[2],iabVendors:[],customVendors:[],specialFeatures:[]},personalisedMarketing:{purposes:[1,4,8,9,10],iabVendors:[],customVendors:[],specialFeatures:[]}},I=Object.keys(v),p={joinHref:!0,gdpr:{},ccpa:{}},E={...p,accountId:1906,baseEndpoint:"https://consent-manager.ft.com",propertyHref:"https://local.ft.com",_clientOptions:{privacyManagerId:827767,manageCookiesLinkOverride:"ft.com/preferences/manage-cookies"}},g={...p,accountId:1906,baseEndpoint:"https://consent-manager.ft.com",propertyId:31642,_clientOptions:{privacyManagerId:827767,manageCookiesLinkOverride:"ft.com/preferences/manage-cookies",rootDomain:"ft.com"}},R={...p,accountId:1906,baseEndpoint:"https://consent-manager.pwmnet.com",propertyId:33414,_clientOptions:{rootDomain:"pwmnet.com"}},F={...p,accountId:1906,baseEndpoint:"https://consent-manager.fdiintelligence.com",propertyId:34061,_clientOptions:{rootDomain:"fdiintelligence.com"}},V={...p,accountId:1906,baseEndpoint:"https://consent-manager.thebanker.com",propertyId:34060,_clientOptions:{rootDomain:"thebanker.com"}},j={...p,accountId:1906,baseEndpoint:"https://consent-manager.bankingriskandregulation.com",propertyId:34059,_clientOptions:{rootDomain:"bankingriskandregulation.com"}},H={...p,accountId:1906,baseEndpoint:"https://consent-manager.sustainableviews.com",propertyId:34058,_clientOptions:{rootDomain:"sustainableviews.com"}},U={...p,accountId:1906,baseEndpoint:"https://consent-manager.ftadviser.com",propertyId:33416,_clientOptions:{rootDomain:"ftadviser.com"}},x={...p,accountId:1906,baseEndpoint:"https://consent-manager.investorschronicle.co.uk",propertyId:33415,_clientOptions:{rootDomain:"investorschronicle.co.uk"}},$={...p,accountId:1906,baseEndpoint:"https://cdn.privacy-mgmt.com",propertyId:33947,_clientOptions:{rootDomain:"ignitesasia.com"}},q={...p,accountId:1906,baseEndpoint:"https://cdn.privacy-mgmt.com",propertyId:33946,_clientOptions:{rootDomain:"igniteseurope.com"}},G=Object.freeze(Object.defineProperty({__proto__:null,FT_DOTCOM_PROD:g,FT_DOTCOM_TEST:E,MM_IGNITES_ASIA:$,MM_IGNITES_EUROPE:q,SP_BANKING_RR:j,SP_FDI_INTELLIGENCE:F,SP_FT_ADVISER:U,SP_INVESTORS_CHRONICLE:x,SP_PWMNET:R,SP_SUSTAINABLE_VIEWS:H,SP_THE_BANKER:V},Symbol.toStringTag,{value:"Module"}));function w(e,n){const t=document.createElement("script");return t.dataset.cmpScript=e,t.innerHTML=n,t}function W(e){const n=document.createElement("script");return n.src=e,n}const K={cmpFrames:"https://consent-manager.ft.com/unified/wrapperMessagingWithoutDetection.js"},O={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",r.title = "__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()}();',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"; e.title = "__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) } })();'};function B(){const e=document.createDocumentFragment();return e.appendChild(w("tcf",O.tcfStub)),e.appendChild(w("usp",O.uspStub)),e.appendChild(W(K.cmpFrames)),e}function J(e){const{_clientOptions:n,...t}=e;window._sp_={config:t},window._sp_queue??(window._sp_queue=[]),document.head.appendChild(B())}function X(e,n,{formOfWordsId:t,cookieDomain:o}){const r=Object.keys(e).reduce((c,u)=>(c[u]={onsite:{status:e[u],lbi:!1,source:h,fow:t}},c),{});return n?{setConsentCookie:!0,formOfWordsId:t,consentSource:h,cookieDomain:o,data:r}:{data:r,cookieDomain:o}}function Y(e,{purpose:n,vendor:t,specialFeatureOptins:o}){const s=v[e],r=s.purposes.every(i=>(n==null?void 0:n.consents[i])||(n==null?void 0:n.legitimateInterests[i])),c=s.iabVendors.every(i=>(t==null?void 0:t.consents[i])||(t==null?void 0:t.legitimateInterests[i])),u=s.specialFeatures.every(i=>(o==null?void 0:o[i])===!0);return r&&c&&u}function z(e){const n=(e==null?void 0:e[2])==="N",t={};for(const o of I)t[o]=n;return t}async function Z(){const e=await new Promise((t,o)=>{var s;try{(s=window.__tcfapi)==null||s.call(window,"addEventListener",2,t)}catch(r){o(r)}}),n={};for(const t of I)n[t]=Y(t,e);return n}async function Q(e,n){return e==="ccpa"?z(n):await Z()}function ee(){const n=Object.fromEntries(document.cookie.split("; ").map(o=>o.split("=")))[M];if(!n)return{};const t=decodeURIComponent(n);return Object.fromEntries(t.split(",").map(o=>{const[s,r]=o.split(":");return[s,r==="on"]}))}function te(e,n){return Object.keys(e).some(o=>{const s=`${o.toLowerCase()}Onsite`;return e[o]!==n[s]})}function ne({userId:e,useConsentStore:n}){return!!e&&n===!0}function oe(e,n){return e?`${n.consentProxyHost}/__consent/consent-record/${N}/${n.userId}`:`${n.consentProxyHost}/__consent/consent-record-cookie?cookieDomain=${n.cookieDomain}`}async function se(e,n){try{const t=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),credentials:"include"});t.ok||console.error("Unable to save consent preferences",t.status)}catch(t){console.error("An error occurred while saving consent",t)}}function re(e){return async function(t,o,s,r){if(e.disableFTCookies)return;const c=r.applies?t:"gdpr";if(c!==t||!s)return;const u=await Q(c,s);if(!te(u,ee()))return;const a=ne(e),m=oe(a,e),ve=X(u,a,e);await se(m,ve),document.dispatchEvent(new CustomEvent("oCookieMessage.act",{bubbles:!0}))}}const y="cookie-message",ce="manage-cookies";let b=Object.freeze({activeComponent:y,messageId:0,privacyManagerId:0});function ae(e){return typeof e=="object"&&e!==null&&e.constructor===Object&&Object.prototype.toString.call(e)==="[object Object]"}const ie=()=>({...b}),C=e=>{if(!ae(e)){console.error("Invalid state changes");return}b={...b,...e}},ue=["adsDisableInternalCMP","pwm.cmp","messageSlotBottom"];function pe(e,n){const t=de(e.flags);window._sp_queue=window._sp_queue??[],window._sp_queue.push(()=>{var o,s;for(const[r,c]of Object.entries(fe))(s=(o=window._sp_).addEventListener)==null||s.call(o,r,c({...e,flags:t}))}),me({...e,flags:t},n)}function de(e){const n={};return typeof e=="object"&&ue.forEach(t=>{Object.prototype.hasOwnProperty.call(e,t)&&(n[t]=e[t])}),n}function le(e){if(!e)return;const n=document.body,t=new CustomEvent("oTracking.event",{bubbles:!0,cancelable:!0,detail:e.detail});n.dispatchEvent(t)}function f({trackingProps:e,action:n,triggerAction:t}){let o;const s=ie(),{product:r,app:c,flags:u}=e;s.activeComponent===y?o=s.messageId:o=s.privacyManagerId;const i={detail:{component:{id:o,name:s.activeComponent,type:"overlay",subtype:"cmp"},category:"component",action:n,...t&&{trigger_action:t},...r&&{product:r},...c&&{app:c},custom:[{cookie_toggle_flag:u}],url:window.document.location.href||null}};le(i)}const fe={onMessageChoiceSelect:e=>(n,t,o)=>{const r={11:"accept_all",12:"manage_cookies",13:"reject_all"}[o];r&&f({trackingProps:e,action:"click",triggerAction:r})},onMessageReady:e=>()=>{f({trackingProps:e,action:"view"})},onMessageReceiveData:()=>(e,n)=>{const{messageId:t}=n;t&&C({messageId:t})},onError:e=>(n,t)=>{f({trackingProps:e,action:"error",triggerAction:t})},onPMCancel:()=>()=>{C({activeComponent:y})}};function me(e,n){window.addEventListener("message",function(t){if(t.origin!==n)return;const o={1:"save_and_close",11:"accept_all",13:"reject_all"},{data:{fromPM:s,actionType:r,messageId:c="0"}={}}=t;s&&(+c&&C({activeComponent:ce,privacyManagerId:+c}),!(!r||!o[r])&&f({trackingProps:e,action:"click",triggerAction:o[r]}))},!1)}const _e="3.5.0-beta.1";async function ge({propertyConfig:e=g,userId:n,useFTSession:t=!0,consentProxyHost:o=D,cookieDomain:s=A,formOfWordsId:r=L,useConsentStore:c=!0,trackingContext:u={},disableFTCookies:i=!1}={}){if(typeof window>"u"){console.error("The CMP client can only be initialised in a browser context");return}if(window.FT_CMP_CLIENT_VERSION=_e,!n&&t)try{const a=await P();n=a==null?void 0:a.uuid}catch(a){console.error(a)}if(!(e!=null&&e.accountId))throw new Error("Please pass a valid property config");n&&(e.authId=n),e.events&&(console.warn("[cmp-client] Passing an events map in the config is not supported and will be ignored. Please use window._sp_.addEventListener() to listen for events"),delete e.events),J(e),window._sp_queue.push(()=>{var a,m;(m=(a=window._sp_)==null?void 0:a.addEventListener)==null||m.call(a,"onConsentReady",re({userId:n,consentProxyHost:o,cookieDomain:s,formOfWordsId:r,useConsentStore:c,disableFTCookies:i}))}),pe(u,e.baseEndpoint)}function ye(e=g){const{privacyManagerId:n,manageCookiesLinkOverride:t,manageCookiesSelector:o}=e._clientOptions||{},s=document.querySelector(o??"#site-footer");s&&t?s.addEventListener("click",r=>{var u,i,a;const c=r.target.closest("a");(u=c==null?void 0:c.getAttribute("href"))!=null&&u.endsWith(t)&&(r.preventDefault(),(a=(i=window._sp_)==null?void 0:i.gdpr)==null||a.loadPrivacyManagerModal(n))}):console.warn("No footer found for",o)}function be(e,n){if(!n||Number.isFinite(parseFloat(n))||!e.endsWith(n))return!1;const t=e.indexOf(n),o=e[t-1];return o==="."||o===void 0}function Ce(e){if(!e)throw new Error("Invalid hostname provided");let t=Object.values(G).find(o=>{var r;const s=(r=o._clientOptions)==null?void 0:r.rootDomain;return s&&be(e,s)});return t??(t=E),t}const he=new URL(window.location.href).hostname,S=Ce(he);ge({propertyConfig:S}),ye(S)})();
1
+ (function(){"use strict";var T,k;const N=(e,{credentials:t="omit"}={})=>fetch(`https://session-next.ft.com${e}`,{credentials:t,useCorsProxy:!0}).then(n=>n.ok?n.json():n.text().then(o=>{throw new Error(`Next session responded with "${o}" (${n.status})`)})).catch(n=>{document.body.dispatchEvent(new CustomEvent("oErrors.log",{bubbles:!0,detail:{error:n,info:{component:"next-session-client"}}}))});let l={};const g=(e,t)=>{if(typeof e=="object"){l=e;return}if(typeof e=="string"&&typeof t=="string"){l[e]=t;return}if(typeof e=="string"&&typeof t>"u")return l[e]||null;if(typeof e>"u"&&typeof t>"u")return l;throw new Error("Invalid arguments")};g.clear=()=>{l={}};const f={},L=()=>{const[,e]=/FTSession_s=([^;]+)/.exec(document.cookie)||[];return e},P=()=>{const e=g("uuid");if(e)return Promise.resolve({uuid:e});const t=L();return t?(f.uuid||(f.uuid=N(`/sessions/s/${t}`).then(({uuid:n}={})=>(delete f.uuid,n&&g("uuid",n),{uuid:n}))),f.uuid):Promise.resolve({uuid:void 0})},v="sourcepoint-cmp",M="FTPINK",A="FTConsent",R="sourcepointCmp/VngD.XycZut.595cp9fWdp5XYP9vlFvk",D=".ft.com",F="https://consent.ft.com",I={permutiveAds:{purposes:[2,4,8,9],iabVendors:[361],customVendors:[],specialFeatures:[]},demographicAds:{purposes:[3,4,7,9,10],iabVendors:[],customVendors:[],specialFeatures:[]},behaviouralAds:{purposes:[2,4,8,9],iabVendors:[],customVendors:[],specialFeatures:[]},programmaticAds:{purposes:[2],iabVendors:[],customVendors:[],specialFeatures:[]},personalisedMarketing:{purposes:[1,4,8,9,10],iabVendors:[],customVendors:[],specialFeatures:[]}},E=Object.keys(I),u={joinHref:!0,gdpr:{},ccpa:{}},w={...u,accountId:1906,baseEndpoint:"https://consent-manager.ft.com",propertyHref:"https://local.ft.com",_clientOptions:{privacyManagerId:827767,manageCookiesLinkOverride:"ft.com/preferences/manage-cookies"}},y={...u,accountId:1906,baseEndpoint:"https://consent-manager.ft.com",propertyId:31642,_clientOptions:{privacyManagerId:827767,manageCookiesLinkOverride:"ft.com/preferences/manage-cookies",rootDomain:"ft.com"}},V={...u,accountId:1906,baseEndpoint:"https://consent-manager.pwmnet.com",propertyId:33414,_clientOptions:{rootDomain:"pwmnet.com"}},j={...u,accountId:1906,baseEndpoint:"https://consent-manager.fdiintelligence.com",propertyId:34061,_clientOptions:{rootDomain:"fdiintelligence.com"}},H={...u,accountId:1906,baseEndpoint:"https://consent-manager.thebanker.com",propertyId:34060,_clientOptions:{rootDomain:"thebanker.com"}},U={...u,accountId:1906,baseEndpoint:"https://consent-manager.bankingriskandregulation.com",propertyId:34059,_clientOptions:{rootDomain:"bankingriskandregulation.com"}},x={...u,accountId:1906,baseEndpoint:"https://consent-manager.sustainableviews.com",propertyId:34058,_clientOptions:{rootDomain:"sustainableviews.com"}},q={...u,accountId:1906,baseEndpoint:"https://consent-manager.ftadviser.com",propertyId:33416,_clientOptions:{rootDomain:"ftadviser.com"}},$={...u,accountId:1906,baseEndpoint:"https://consent-manager.investorschronicle.co.uk",propertyId:33415,_clientOptions:{rootDomain:"investorschronicle.co.uk"}},G={...u,accountId:1906,baseEndpoint:"https://cdn.privacy-mgmt.com",propertyId:33947,_clientOptions:{rootDomain:"ignitesasia.com"}},K={...u,accountId:1906,baseEndpoint:"https://cdn.privacy-mgmt.com",propertyId:33946,_clientOptions:{rootDomain:"igniteseurope.com"}},W=Object.freeze(Object.defineProperty({__proto__:null,FT_DOTCOM_PROD:y,FT_DOTCOM_TEST:w,MM_IGNITES_ASIA:G,MM_IGNITES_EUROPE:K,SP_BANKING_RR:U,SP_FDI_INTELLIGENCE:j,SP_FT_ADVISER:q,SP_INVESTORS_CHRONICLE:$,SP_PWMNET:V,SP_SUSTAINABLE_VIEWS:x,SP_THE_BANKER:H},Symbol.toStringTag,{value:"Module"}));function O(e,t){const n=document.createElement("script");return n.dataset.cmpScript=e,n.innerHTML=t,n}function B(e){const t=document.createElement("script");return t.src=e,t}const J={cmpFrames:"https://consent-manager.ft.com/unified/wrapperMessagingWithoutDetection.js"},S={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",r.title = "__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()}();',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"; e.title = "__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) } })();'};function X(){const e=document.createDocumentFragment();return e.appendChild(O("tcf",S.tcfStub)),e.appendChild(O("usp",S.uspStub)),e.appendChild(B(J.cmpFrames)),e}function Y(e){const{_clientOptions:t,...n}=e;window._sp_={config:n},window._sp_queue??(window._sp_queue=[]),document.head.appendChild(X())}function z(e,t,{formOfWordsId:n,cookieDomain:o}){const c=Object.keys(e).reduce((r,p)=>(r[p]={onsite:{status:e[p],lbi:!1,source:v,fow:n}},r),{});return t?{setConsentCookie:!0,formOfWordsId:n,consentSource:v,cookieDomain:o,data:c}:{data:c,cookieDomain:o}}function Z(e,{purpose:t,vendor:n,specialFeatureOptins:o}){const s=I[e],c=s.purposes.every(i=>(t==null?void 0:t.consents[i])||(t==null?void 0:t.legitimateInterests[i])),r=s.iabVendors.every(i=>(n==null?void 0:n.consents[i])||(n==null?void 0:n.legitimateInterests[i])),p=s.specialFeatures.every(i=>(o==null?void 0:o[i])===!0);return c&&r&&p}function Q(e){const t=(e==null?void 0:e[2])==="N",n={};for(const o of E)n[o]=t;return n}async function ee(){const e=await new Promise((n,o)=>{var s;try{(s=window.__tcfapi)==null||s.call(window,"addEventListener",2,n)}catch(c){o(c)}}),t={};for(const n of E)t[n]=Z(n,e);return t}async function te(e,t){return e==="ccpa"?Q(t):await ee()}function ne(){const t=Object.fromEntries(document.cookie.split("; ").map(o=>o.split("=")))[A];if(!t)return{};const n=decodeURIComponent(t);return Object.fromEntries(n.split(",").map(o=>{const[s,c]=o.split(":");return[s,c==="on"]}))}function oe(e,t){return Object.keys(e).some(o=>{const s=`${o.toLowerCase()}Onsite`;return e[o]!==t[s]})}function se({userId:e,useConsentStore:t}){return!!e&&t===!0}function ce(e,t){return e?`${t.consentProxyHost}/__consent/consent-record/${M}/${t.userId}`:`${t.consentProxyHost}/__consent/consent-record-cookie?cookieDomain=${t.cookieDomain}`}async function re(e,t){try{const n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),credentials:"include"});n.ok||console.error("Unable to save consent preferences",n.status)}catch(n){console.error("An error occurred while saving consent",n)}}function ae(e){return async function(n,o,s,c){if(e.disableFTCookies)return;const r=c.applies?n:"gdpr";if(r!==n||!s)return;const p=await te(r,s);if(!oe(p,ne()))return;const a=se(e),_=ce(a,e),Oe=z(p,a,e);await re(_,Oe),document.dispatchEvent(new CustomEvent("oCookieMessage.act",{bubbles:!0}))}}const b="cookie-message",ie="manage-cookies";let h=Object.freeze({activeComponent:b,messageId:0,privacyManagerId:0});function ue(e){return typeof e=="object"&&e!==null&&e.constructor===Object&&Object.prototype.toString.call(e)==="[object Object]"}const pe=()=>({...h}),C=e=>{if(!ue(e)){console.error("Invalid state changes");return}h={...h,...e}},de=["adsDisableInternalCMP","pwm.cmp","messageSlotBottom"];function le(e,t){const n=fe(e.flags);window._sp_queue=window._sp_queue??[],window._sp_queue.push(()=>{var o,s;for(const[c,r]of Object.entries(_e))(s=(o=window._sp_).addEventListener)==null||s.call(o,c,r({...e,flags:n}))}),ge({...e,flags:n},t)}function fe(e){const t={};return typeof e=="object"&&de.forEach(n=>{Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])}),t}function me(e){if(!e)return;const t=document.body,n=new CustomEvent("oTracking.event",{bubbles:!0,cancelable:!0,detail:e.detail});t.dispatchEvent(n)}function m({trackingProps:e,action:t,triggerAction:n}){let o;const s=pe(),{product:c,app:r,flags:p}=e;s.activeComponent===b?o=s.messageId:o=s.privacyManagerId;const i={detail:{component:{id:o,name:s.activeComponent,type:"overlay",subtype:"cmp"},category:"component",action:t,...n&&{trigger_action:n},...c&&{product:c},...r&&{app:r},custom:[{cookie_toggle_flag:p}],url:window.document.location.href||null}};me(i)}const _e={onMessageChoiceSelect:e=>(t,n,o)=>{const c={11:"accept_all",12:"manage_cookies",13:"reject_all"}[o];c&&m({trackingProps:e,action:"click",triggerAction:c})},onMessageReady:e=>()=>{m({trackingProps:e,action:"view"})},onMessageReceiveData:()=>(e,t)=>{const{messageId:n}=t;n&&C({messageId:n})},onError:e=>(t,n)=>{m({trackingProps:e,action:"error",triggerAction:n})},onPMCancel:()=>()=>{C({activeComponent:b})}};function ge(e,t){window.addEventListener("message",function(n){if(n.origin!==t)return;const o={1:"save_and_close",11:"accept_all",13:"reject_all"},{data:{fromPM:s,actionType:c,messageId:r="0"}={}}=n;s&&(+r&&C({activeComponent:ie,privacyManagerId:+r}),!(!c||!o[c])&&m({trackingProps:e,action:"click",triggerAction:o[c]}))},!1)}const ye="4.0.0";async function be({propertyConfig:e=y,userId:t,useFTSession:n=!0,consentProxyHost:o=F,cookieDomain:s=D,formOfWordsId:c=R,useConsentStore:r=!0,trackingContext:p={},disableFTCookies:i=!1}={}){if(typeof window>"u"){console.error("The CMP client can only be initialised in a browser context");return}if(window.FT_CMP_CLIENT_VERSION=ye,!t&&n)try{const a=await P();t=a==null?void 0:a.uuid}catch(a){console.error(a)}if(!(e!=null&&e.accountId))throw new Error("Please pass a valid property config");t&&(e.authId=t),e.events&&(console.warn("[cmp-client] Passing an events map in the config is not supported and will be ignored. Please use window._sp_.addEventListener() to listen for events"),delete e.events),Y(e),window._sp_queue.push(()=>{var a,_;(_=(a=window._sp_)==null?void 0:a.addEventListener)==null||_.call(a,"onConsentReady",ae({userId:t,consentProxyHost:o,cookieDomain:s,formOfWordsId:c,useConsentStore:r,disableFTCookies:i}))}),le(p,e.baseEndpoint)}const he=new Promise(e=>{if(typeof document>"u")return e();const t=()=>["interactive","complete"].includes(document.readyState);function n(){t()&&(document.removeEventListener("readystatechange",n),e())}if(t())return e();document.addEventListener("readystatechange",n)});function Ce(e,t){const{privacyManagerId:n,manageCookiesLinkOverride:o}=e??{};if(!n||!o)return console.warn("_clientOptions is missing privacyManagerId or manageCookiesLinkOverride");const s=document.querySelectorAll(`a[href*="${o}"]`);for(const c of s)c.addEventListener("click",r=>{r.preventDefault(),t==null||t(+n)})}function ve({_clientOptions:e}=y){he.then(()=>{window._sp_queue??(window._sp_queue=[]),window._sp_queue.push(()=>{var t,n;Ce(e,(n=(t=window._sp_)==null?void 0:t.gdpr)==null?void 0:n.loadPrivacyManagerModal)})})}function Ie(e,t){if(!t||Number.isFinite(parseFloat(t))||!e.endsWith(t))return!1;const n=e.indexOf(t),o=e[n-1];return o==="."||o===void 0}function Ee(e){if(!e)throw new Error("Invalid hostname provided");let n=Object.values(W).find(o=>{var c;const s=(c=o._clientOptions)==null?void 0:c.rootDomain;return s&&Ie(e,s)});return n??(n=w),n}const we=new URL(window.location.href).hostname,d=Ee(we);be({propertyConfig:d}),(T=d==null?void 0:d._clientOptions)!=null&&T.privacyManagerId&&((k=d==null?void 0:d._clientOptions)!=null&&k.manageCookiesLinkOverride)&&ve(d)})();
@@ -0,0 +1,11 @@
1
+ import type { SPConfig } from "../../typings/types";
2
+ /**
3
+ * Uses the `manageCookiesLinkOverride` property from SPConfig
4
+ * as a querySelectorALL to match anchor-tag elements by href attribute.
5
+ * Adds a "click" eventListener to the anchor-tag(s)
6
+ * prevents default and call Sourcepoint loadPrivacyManagerModal function.
7
+
8
+ * @returns Returns true if the link was updated, false if not
9
+ */
10
+ export declare function interceptManageCookiesLinks({ _clientOptions }?: SPConfig): void;
11
+ //# sourceMappingURL=cmp-manage-cookies-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmp-manage-cookies-link.d.ts","sourceRoot":"","sources":["../../../src/html/cmp-manage-cookies-link.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAyB,MAAM,qBAAqB,CAAC;AAuC3E;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,EAAE,cAAc,EAAE,GAAE,QAAyB,QAOxF"}
@@ -1,5 +1,5 @@
1
1
  export * as debug from "./lib/debug.ts";
2
2
  export * as properties from "./lib/properties.ts";
3
- export { updateFooterLinkCMP } from "./html/cmp-footer-link.ts";
3
+ export { interceptManageCookiesLinks } from "./html/cmp-manage-cookies-link.ts";
4
4
  export { initSourcepointCmp } from "./client.ts";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,2BAA2B,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/cmp-client",
3
- "version": "3.5.0-beta.1",
3
+ "version": "4.0.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "files": [
@@ -6,6 +6,12 @@ export type SPLifecycleEvents = Partial<typeof events>;
6
6
 
7
7
  export type SPEventId = keyof SPLifecycleEvents;
8
8
 
9
+ export type SPConfigClientOptions = {
10
+ privacyManagerId?: number;
11
+ manageCookiesLinkOverride?: string;
12
+ rootDomain?: string;
13
+ };
14
+
9
15
  export interface SPConfig {
10
16
  accountId: number;
11
17
  baseEndpoint: string;
@@ -16,12 +22,7 @@ export interface SPConfig {
16
22
  joinHref?: boolean;
17
23
  events?: Partial<SPLifecycleEvents>;
18
24
  authId?: string;
19
- _clientOptions?: {
20
- rootDomain?: string;
21
- privacyManagerId?: number;
22
- manageCookiesSelector?: string;
23
- manageCookiesLinkOverride?: string;
24
- };
25
+ _clientOptions?: SPConfigClientOptions;
25
26
  }
26
27
 
27
28
  export type SPEventCallback = (
@@ -1,12 +0,0 @@
1
- import type { SPConfig } from "../../typings/types.d.ts";
2
- /**
3
- * Adds a "click" eventListener to the <footer> element
4
- * checks the event.target.closest anchor tag and
5
- * tests the anchor's href attribute against a target URL
6
- * if the URL is matched, prevent default and call Sourcepoint
7
- * loadPrivacyManagerModal function.
8
-
9
- * @returns {void} - Returns true if the link was updated, false if not
10
- */
11
- export declare function updateFooterLinkCMP(propertyConfig?: SPConfig): void;
12
- //# sourceMappingURL=cmp-footer-link.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cmp-footer-link.d.ts","sourceRoot":"","sources":["../../../src/html/cmp-footer-link.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,GAAE,QAAyB,GAAG,IAAI,CAgBnF"}