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

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
@@ -1,6 +1,6 @@
1
1
  # CMP Client
2
2
 
3
- A client-side package to help you add a CMP (currently provided by Sourcepoint) to your application.
3
+ A client-side library to help you add a CMP (currently provided by Sourcepoint) to your application.
4
4
 
5
5
  <details>
6
6
  <summary>How it works</summary>
@@ -13,13 +13,31 @@ A client-side package to help you add a CMP (currently provided by Sourcepoint)
13
13
 
14
14
  ## Installation
15
15
 
16
- Install the package from npm:
16
+ Install as a \<script> tag (**recommended**):
17
+
18
+ ```copy
19
+ <script async src="https://consent-notice.ft.com/cmp.js"></script>
20
+ ```
21
+
22
+ Install the library from NPM:
17
23
 
18
24
  ```copy
19
25
  npm install @financial-times/cmp-client
20
26
  ```
21
27
 
22
- ## Usage
28
+ ## Using the script tag
29
+
30
+ The `src` attribute of the `script` tag points to an immediately invoked function expression (IIFE) that sets up the CMP client on the host page. When the CMP client is installed this way, no additional work needs to be done.
31
+
32
+ The primary benefit of using this integration method is that your users will automatically get new updates to the CMP client as soon as they are available, as opposed to requiring a version bump and application release. However, for this method to work successfully, the host page must be one of our [registered properties](#available-properties-constantly-being-updated). Please reach out to the Ads & Privacy team if you are not sure or you would like to register a property.
33
+
34
+ By default the source link integrates the latest version of the CMP client. If you would like to pin a different version, you can append a `version` query parameter to the source link as follows:
35
+
36
+ ```copy
37
+ <script async src="https://consent-notice.ft.com/cmp.js?version=4.0.0"></script>
38
+ ```
39
+
40
+ ## Using the NPM package
23
41
 
24
42
  > [!Note]
25
43
  > We will be adding new properties (i.e. websites under FT group) and their configs as we start rolling out.
@@ -124,6 +142,10 @@ if (flagsClient.get("adsDisableInternalCMP")) {
124
142
  <td><code>useConsentStore</code> (boolean)</td>
125
143
  <td>Specifies whether the user's consent record should also be backed by the Single Consent Store. Properties like Specialist titles will need to explicitly set this to <code>false</code> as <code>true</code> is the default behavior</td>
126
144
  </tr>
145
+ <tr>
146
+ <td><code>disableFTCookies</code> (boolean)</td>
147
+ <td>Specifies whether the user's consent record should be saved to FT Cookies. Properties like Specialist titles that don't utilize FT cookies will need to explicitly set this to <code>true</code> as <code>false</code> is the default behavior</td>
148
+ </tr>
127
149
  <tr>
128
150
  <td><code>events</code> (object)</td>
129
151
  <td>Used internally to define handlers for events emitted by the Vendor-supplied CMP module. See notes on "Responding to CMP events" below for details on how to define custom event handlers</td>
@@ -224,7 +246,7 @@ If everything's working then you'll see the CMP Module log its lifecycle events
224
246
  This can easily happen when you've made a previous consent choice and the CMP is now picking it up from local storage. For this reason we recommend running in an incognito window during development.
225
247
 
226
248
  > [!Note]
227
- > Please ensure that your app always uses the latest version of the CMP Client package.
249
+ > Please ensure that your app always uses the latest version of the CMP Client library.
228
250
  >
229
251
  > You can check the version your live app is using by running the following in the browser console:
230
252
  >
@@ -244,6 +266,6 @@ npm run dev -w src/examples/cmp-client
244
266
 
245
267
  Visit https://localhost:5173 (see setup details in `src/examples/cmp-client`) to interact with the banner and see how cookies are set accordingly
246
268
 
247
- ## Using the static integration script
269
+ #### Resources
248
270
 
249
- The `cmp-client` is now deployed as a static integration script that can be consumed via a `<script></script>` tag. More details on how to consume will be added as the delivery process is finalised and the static base URL is available. For more information on how it is deployed and delivered, here is the [design doc in Confluence](https://financialtimes.atlassian.net/wiki/spaces/ADS/pages/8261828634/Static+Deployment+and+Distribution+Proposal)
271
+ For a detailed deep-dive (internal only) of how the static deployment process works, the design is [documented here](https://financialtimes.atlassian.net/wiki/spaces/ADS/pages/8293711881/How+the+CMP+static+loader+works). If you need to be granted access, please reach out to the Ads & Privacy team.
package/dist/index.cjs CHANGED
@@ -438,6 +438,9 @@ async function saveConsent(consentEndpoint, payload) {
438
438
  }
439
439
  function consentReadyHandlerFn(props) {
440
440
  return async function consentReadyHandler(legislation, _consentUUID, consentString, consentMeta) {
441
+ if (props.disableFTCookies) {
442
+ return;
443
+ }
441
444
  const activeLegislation = consentMeta.applies ? legislation : "gdpr";
442
445
  if (activeLegislation !== legislation || !consentString) {
443
446
  return;
@@ -617,7 +620,7 @@ function setupPmTracking(trackingProps, cmpBaseEndpoint) {
617
620
  false
618
621
  );
619
622
  }
620
- const version = "3.4.0-beta.1";
623
+ const version = "3.5.0-beta.1";
621
624
  async function initSourcepointCmp({
622
625
  propertyConfig = FT_DOTCOM_PROD,
623
626
  userId,
@@ -626,7 +629,8 @@ async function initSourcepointCmp({
626
629
  cookieDomain = FT_COOKIE_DOMAIN,
627
630
  formOfWordsId = SOURCEPOINT_FOW_ID,
628
631
  useConsentStore = true,
629
- trackingContext = {}
632
+ trackingContext = {},
633
+ disableFTCookies = false
630
634
  } = {}) {
631
635
  if (typeof window === "undefined") {
632
636
  console.error("The CMP client can only be initialised in a browser context");
@@ -664,7 +668,8 @@ async function initSourcepointCmp({
664
668
  consentProxyHost,
665
669
  cookieDomain,
666
670
  formOfWordsId,
667
- useConsentStore
671
+ useConsentStore,
672
+ disableFTCookies
668
673
  })
669
674
  );
670
675
  });
package/dist/index.js CHANGED
@@ -436,6 +436,9 @@ async function saveConsent(consentEndpoint, payload) {
436
436
  }
437
437
  function consentReadyHandlerFn(props) {
438
438
  return async function consentReadyHandler(legislation, _consentUUID, consentString, consentMeta) {
439
+ if (props.disableFTCookies) {
440
+ return;
441
+ }
439
442
  const activeLegislation = consentMeta.applies ? legislation : "gdpr";
440
443
  if (activeLegislation !== legislation || !consentString) {
441
444
  return;
@@ -615,7 +618,7 @@ function setupPmTracking(trackingProps, cmpBaseEndpoint) {
615
618
  false
616
619
  );
617
620
  }
618
- const version = "3.4.0-beta.1";
621
+ const version = "3.5.0-beta.1";
619
622
  async function initSourcepointCmp({
620
623
  propertyConfig = FT_DOTCOM_PROD,
621
624
  userId,
@@ -624,7 +627,8 @@ async function initSourcepointCmp({
624
627
  cookieDomain = FT_COOKIE_DOMAIN,
625
628
  formOfWordsId = SOURCEPOINT_FOW_ID,
626
629
  useConsentStore = true,
627
- trackingContext = {}
630
+ trackingContext = {},
631
+ disableFTCookies = false
628
632
  } = {}) {
629
633
  if (typeof window === "undefined") {
630
634
  console.error("The CMP client can only be initialised in a browser context");
@@ -662,7 +666,8 @@ async function initSourcepointCmp({
662
666
  consentProxyHost,
663
667
  cookieDomain,
664
668
  formOfWordsId,
665
- useConsentStore
669
+ useConsentStore,
670
+ disableFTCookies
666
671
  })
667
672
  );
668
673
  });
@@ -1 +1 @@
1
- (function(){"use strict";const S=(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 m=(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")};m.clear=()=>{d={}};const l={},T=()=>{const[,e]=/FTSession_s=([^;]+)/.exec(document.cookie)||[];return e},k=()=>{const e=m("uuid");if(e)return Promise.resolve({uuid:e});const n=T();return n?(l.uuid||(l.uuid=S(`/sessions/s/${n}`).then(({uuid:t}={})=>(delete l.uuid,t&&m("uuid",t),{uuid:t}))),l.uuid):Promise.resolve({uuid:void 0})},h="sourcepoint-cmp",P="FTPINK",N="FTConsent",M="sourcepointCmp/VngD.XycZut.595cp9fWdp5XYP9vlFvk",L=".ft.com",A="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:[]}},C=Object.keys(v),u={joinHref:!0,gdpr:{},ccpa:{}},I={...u,accountId:1906,baseEndpoint:"https://consent-manager.ft.com",propertyHref:"https://local.ft.com",_clientOptions:{privacyManagerId:827767,manageCookiesLinkOverride:"ft.com/preferences/manage-cookies"}},_={...u,accountId:1906,baseEndpoint:"https://consent-manager.ft.com",propertyId:31642,_clientOptions:{privacyManagerId:827767,manageCookiesLinkOverride:"ft.com/preferences/manage-cookies",rootDomain:"ft.com"}},D={...u,accountId:1906,baseEndpoint:"https://consent-manager.pwmnet.com",propertyId:33414,_clientOptions:{rootDomain:"pwmnet.com"}},R={...u,accountId:1906,baseEndpoint:"https://consent-manager.fdiintelligence.com",propertyId:34061,_clientOptions:{rootDomain:"fdiintelligence.com"}},F={...u,accountId:1906,baseEndpoint:"https://consent-manager.thebanker.com",propertyId:34060,_clientOptions:{rootDomain:"thebanker.com"}},V={...u,accountId:1906,baseEndpoint:"https://consent-manager.bankingriskandregulation.com",propertyId:34059,_clientOptions:{rootDomain:"bankingriskandregulation.com"}},j={...u,accountId:1906,baseEndpoint:"https://consent-manager.sustainableviews.com",propertyId:34058,_clientOptions:{rootDomain:"sustainableviews.com"}},H={...u,accountId:1906,baseEndpoint:"https://consent-manager.ftadviser.com",propertyId:33416,_clientOptions:{rootDomain:"ftadviser.com"}},U={...u,accountId:1906,baseEndpoint:"https://consent-manager.investorschronicle.co.uk",propertyId:33415,_clientOptions:{rootDomain:"investorschronicle.co.uk"}},x={...u,accountId:1906,baseEndpoint:"https://cdn.privacy-mgmt.com",propertyId:33947,_clientOptions:{rootDomain:"ignitesasia.com"}},$={...u,accountId:1906,baseEndpoint:"https://cdn.privacy-mgmt.com",propertyId:33946,_clientOptions:{rootDomain:"igniteseurope.com"}},q=Object.freeze(Object.defineProperty({__proto__:null,FT_DOTCOM_PROD:_,FT_DOTCOM_TEST:I,MM_IGNITES_ASIA:x,MM_IGNITES_EUROPE:$,SP_BANKING_RR:V,SP_FDI_INTELLIGENCE:R,SP_FT_ADVISER:H,SP_INVESTORS_CHRONICLE:U,SP_PWMNET:D,SP_SUSTAINABLE_VIEWS:j,SP_THE_BANKER:F},Symbol.toStringTag,{value:"Module"}));function E(e,n){const t=document.createElement("script");return t.dataset.cmpScript=e,t.innerHTML=n,t}function G(e){const n=document.createElement("script");return n.src=e,n}const W={cmpFrames:"https://consent-manager.ft.com/unified/wrapperMessagingWithoutDetection.js"},w={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 K(){const e=document.createDocumentFragment();return e.appendChild(E("tcf",w.tcfStub)),e.appendChild(E("usp",w.uspStub)),e.appendChild(G(W.cmpFrames)),e}function B(e){const{_clientOptions:n,...t}=e;window._sp_={config:t},window._sp_queue??(window._sp_queue=[]),document.head.appendChild(K())}function J(e,n,{formOfWordsId:t,cookieDomain:o}){const r=Object.keys(e).reduce((a,i)=>(a[i]={onsite:{status:e[i],lbi:!1,source:h,fow:t}},a),{});return n?{setConsentCookie:!0,formOfWordsId:t,consentSource:h,cookieDomain:o,data:r}:{data:r,cookieDomain:o}}function X(e,{purpose:n,vendor:t,specialFeatureOptins:o}){const s=v[e],r=s.purposes.every(c=>(n==null?void 0:n.consents[c])||(n==null?void 0:n.legitimateInterests[c])),a=s.iabVendors.every(c=>(t==null?void 0:t.consents[c])||(t==null?void 0:t.legitimateInterests[c])),i=s.specialFeatures.every(c=>(o==null?void 0:o[c])===!0);return r&&a&&i}function Y(e){const n=(e==null?void 0:e[2])==="N",t={};for(const o of C)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 C)n[t]=X(t,e);return n}async function Z(e,n){return e==="ccpa"?Y(n):await z()}function Q(){const n=Object.fromEntries(document.cookie.split("; ").map(o=>o.split("=")))[N];if(!n)return{};const t=decodeURIComponent(n);return Object.fromEntries(t.split(",").map(o=>{const[s,r]=o.split(":");return[s,r==="on"]}))}function ee(e,n){return Object.keys(e).some(o=>{const s=`${o.toLowerCase()}Onsite`;return e[o]!==n[s]})}function te({userId:e,useConsentStore:n}){return!!e&&n===!0}function ne(e,n){return e?`${n.consentProxyHost}/__consent/consent-record/${P}/${n.userId}`:`${n.consentProxyHost}/__consent/consent-record-cookie?cookieDomain=${n.cookieDomain}`}async function oe(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 se(e){return async function(t,o,s,r){const a=r.applies?t:"gdpr";if(a!==t||!s)return;const i=await Z(a,s);if(!ee(i,Q()))return;const p=te(e),ve=ne(p,e),Ce=J(i,p,e);await oe(ve,Ce),document.dispatchEvent(new CustomEvent("oCookieMessage.act",{bubbles:!0}))}}const g="cookie-message",re="manage-cookies";let y=Object.freeze({activeComponent:g,messageId:0,privacyManagerId:0});function ce(e){return typeof e=="object"&&e!==null&&e.constructor===Object&&Object.prototype.toString.call(e)==="[object Object]"}const ae=()=>({...y}),b=e=>{if(!ce(e)){console.error("Invalid state changes");return}y={...y,...e}},ie=["adsDisableInternalCMP","pwm.cmp","messageSlotBottom"];function ue(e,n){const t=pe(e.flags);window._sp_queue=window._sp_queue??[],window._sp_queue.push(()=>{var o,s;for(const[r,a]of Object.entries(le))(s=(o=window._sp_).addEventListener)==null||s.call(o,r,a({...e,flags:t}))}),fe({...e,flags:t},n)}function pe(e){const n={};return typeof e=="object"&&ie.forEach(t=>{Object.prototype.hasOwnProperty.call(e,t)&&(n[t]=e[t])}),n}function de(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=ae(),{product:r,app:a,flags:i}=e;s.activeComponent===g?o=s.messageId:o=s.privacyManagerId;const c={detail:{component:{id:o,name:s.activeComponent,type:"overlay",subtype:"cmp"},category:"component",action:n,...t&&{trigger_action:t},...r&&{product:r},...a&&{app:a},custom:[{cookie_toggle_flag:i}],url:window.document.location.href||null}};de(c)}const le={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&&b({messageId:t})},onError:e=>(n,t)=>{f({trackingProps:e,action:"error",triggerAction:t})},onPMCancel:()=>()=>{b({activeComponent:g})}};function fe(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:a="0"}={}}=t;s&&(+a&&b({activeComponent:re,privacyManagerId:+a}),!(!r||!o[r])&&f({trackingProps:e,action:"click",triggerAction:o[r]}))},!1)}const me="3.4.0-beta.1";async function _e({propertyConfig:e=_,userId:n,useFTSession:t=!0,consentProxyHost:o=A,cookieDomain:s=L,formOfWordsId:r=M,useConsentStore:a=!0,trackingContext:i={}}={}){if(typeof window>"u"){console.error("The CMP client can only be initialised in a browser context");return}if(window.FT_CMP_CLIENT_VERSION=me,!n&&t)try{const c=await k();n=c==null?void 0:c.uuid}catch(c){console.error(c)}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),B(e),window._sp_queue.push(()=>{var c,p;(p=(c=window._sp_)==null?void 0:c.addEventListener)==null||p.call(c,"onConsentReady",se({userId:n,consentProxyHost:o,cookieDomain:s,formOfWordsId:r,useConsentStore:a}))}),ue(i,e.baseEndpoint)}function ge(e=_){const{privacyManagerId:n,manageCookiesLinkOverride:t,manageCookiesSelector:o}=e._clientOptions||{},s=document.querySelector(o??"#site-footer");s&&t?s.addEventListener("click",r=>{var i,c,p;const a=r.target.closest("a");(i=a==null?void 0:a.getAttribute("href"))!=null&&i.endsWith(t)&&(r.preventDefault(),(p=(c=window._sp_)==null?void 0:c.gdpr)==null||p.loadPrivacyManagerModal(n))}):console.warn("No footer found for",o)}function ye(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 be(e){if(!e)throw new Error("Invalid hostname provided");let t=Object.values(q).find(o=>{var r;const s=(r=o._clientOptions)==null?void 0:r.rootDomain;return s&&ye(e,s)});return t??(t=I),t}const he=new URL(window.location.href).hostname,O=be(he);_e({propertyConfig:O}),ge(O)})();
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)})();
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/index.test.ts"],"names":[],"mappings":""}
@@ -1,3 +1,3 @@
1
1
  import type { CMPInitOptions } from "../typings/types.d.ts";
2
- export declare function initSourcepointCmp({ propertyConfig, userId, useFTSession, consentProxyHost, cookieDomain, formOfWordsId, useConsentStore, trackingContext, }?: CMPInitOptions): Promise<void>;
2
+ export declare function initSourcepointCmp({ propertyConfig, userId, useFTSession, consentProxyHost, cookieDomain, formOfWordsId, useConsentStore, trackingContext, disableFTCookies, }?: CMPInitOptions): Promise<void>;
3
3
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAW5D,wBAAsB,kBAAkB,CAAC,EACvC,cAA+B,EAC/B,MAAM,EACN,YAAmB,EACnB,gBAAwC,EACxC,YAA+B,EAC/B,aAAkC,EAClC,eAAsB,EACtB,eAAoB,GACrB,GAAE,cAAmB,iBAgDrB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAW5D,wBAAsB,kBAAkB,CAAC,EACvC,cAA+B,EAC/B,MAAM,EACN,YAAmB,EACnB,gBAAwC,EACxC,YAA+B,EAC/B,aAAkC,EAClC,eAAsB,EACtB,eAAoB,EACpB,gBAAwB,GACzB,GAAE,cAAmB,iBAiDrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/consent-ready/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AA8B/E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,iBAAiB,iBAE7C,MAAM,gBACL,MAAM,iBACL,MAAM,eACR;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,mBAsBrC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/consent-ready/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AA8B/E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,iBAAiB,iBAE7C,MAAM,gBACL,MAAM,iBACL,MAAM,eACR;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,mBA0BrC"}
@@ -1,3 +1,4 @@
1
+ export declare function stubFetch(expectedResponse: unknown): void;
1
2
  export declare function stubTCFAPI(consents: {
2
3
  purpose: boolean;
3
4
  vendor: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../../src/consent-ready/utils/__fixtures__/helpers.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,QAAQ,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;EA4BzE"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../../src/consent-ready/utils/__fixtures__/helpers.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS,CAAC,gBAAgB,EAAE,OAAO,QAKlD;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;EA4BzE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/cmp-client",
3
- "version": "3.4.0-beta.1",
3
+ "version": "3.5.0-beta.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "files": [
@@ -40,6 +40,7 @@ export type CMPInitOptions = Partial<{
40
40
  formOfWordsId: string;
41
41
  useConsentStore: boolean;
42
42
  trackingContext?: TrackingContext;
43
+ disableFTCookies: boolean;
43
44
  }>;
44
45
 
45
46
  export interface ConsentPayloadOptions {