@financial-times/cmp-client 5.5.2 → 5.6.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/dist/index.cjs CHANGED
@@ -402,7 +402,7 @@ function bootstrapCmp(config, options) {
402
402
  window._sp_queue ?? (window._sp_queue = []);
403
403
  document.head.appendChild(getCmpScripts(options));
404
404
  }
405
- function getConsentPayload(parsedConsent, updateConsentStore, { formOfWordsId, cookieDomain }) {
405
+ function getConsentPayload(parsedConsent, updateConsentStore, isUserInitiated, { formOfWordsId, cookieDomain }) {
406
406
  const categoryNames = Object.keys(parsedConsent);
407
407
  const data = categoryNames.reduce(
408
408
  (payload, categoryName) => {
@@ -424,6 +424,7 @@ function getConsentPayload(parsedConsent, updateConsentStore, { formOfWordsId, c
424
424
  formOfWordsId,
425
425
  consentSource: SOURCEPOINT_CONSENT_SOURCE,
426
426
  cookieDomain,
427
+ skipDuplicateUpdates: !isUserInitiated,
427
428
  data
428
429
  };
429
430
  }
@@ -483,8 +484,9 @@ function parseUsNationalSection(sectionData) {
483
484
  parsedConsent[categoryName] = userHasNotOptedOut;
484
485
  }
485
486
  if (marketingOptOutStatus.usnat) {
486
- parsedConsent.personalisedMarketing = false;
487
- parsedConsent.behaviouralAds = false;
487
+ for (const categoryName of iabCategoryNames) {
488
+ parsedConsent[categoryName] = false;
489
+ }
488
490
  }
489
491
  return parsedConsent;
490
492
  }
@@ -492,8 +494,8 @@ const sectionParsers = {
492
494
  [sections.CALIFORNIA]: parseCaliforniaSection,
493
495
  [sections.US_NATIONAL]: parseUsNationalSection
494
496
  };
495
- async function parseGPPConsent() {
496
- const gppData = await new Promise((resolve, reject) => {
497
+ async function getGPPData() {
498
+ return new Promise((resolve, reject) => {
497
499
  try {
498
500
  if (window.__gpp) {
499
501
  window.__gpp("ping", resolve);
@@ -504,6 +506,9 @@ async function parseGPPConsent() {
504
506
  reject(error);
505
507
  }
506
508
  });
509
+ }
510
+ async function parseGPPConsent() {
511
+ const gppData = await getGPPData();
507
512
  const { parsedSections } = gppData;
508
513
  const applicableSection = getApplicableSection(gppData);
509
514
  if (!applicableSection || !parsedSections[applicableSection]) {
@@ -530,8 +535,8 @@ function checkConsentFor(categoryName, { purpose, vendor, specialFeatureOptins }
530
535
  );
531
536
  return requiredPurposesConsented && requiredIabVendorsConsented && requiredSpecialFeaturesConsented;
532
537
  }
533
- async function parseGDPRConsent() {
534
- const tcData = await new Promise((resolve, reject) => {
538
+ async function getTcData() {
539
+ return new Promise((resolve, reject) => {
535
540
  try {
536
541
  if (window.__tcfapi) {
537
542
  window.__tcfapi("addEventListener", 2, resolve);
@@ -542,6 +547,9 @@ async function parseGDPRConsent() {
542
547
  reject(error);
543
548
  }
544
549
  });
550
+ }
551
+ async function parseGDPRConsent() {
552
+ const tcData = await getTcData();
545
553
  const parsedConsent = {};
546
554
  for (const categoryName of iabCategoryNames) {
547
555
  parsedConsent[categoryName] = checkConsentFor(categoryName, tcData);
@@ -591,6 +599,50 @@ function getConsentEndpoint(updateConsentStore, props) {
591
599
  }
592
600
  return `${props.consentProxyHost}/__consent/consent-record-cookie?cookieDomain=${props.cookieDomain}`;
593
601
  }
602
+ const INITIAL_STATE$1 = {
603
+ gdpr: false,
604
+ usnat: false
605
+ };
606
+ const isWaitingForUserAction = Object.assign({}, INITIAL_STATE$1);
607
+ function setWaitingForUser(legislation) {
608
+ isWaitingForUserAction[legislation] = true;
609
+ }
610
+ function isWaitingForUser(legislation) {
611
+ return isWaitingForUserAction[legislation];
612
+ }
613
+ function completeWaitingForUser() {
614
+ Object.assign(isWaitingForUserAction, INITIAL_STATE$1);
615
+ }
616
+ async function isUserInitiatedUpdate(activeLegislation) {
617
+ if (!isWaitingForUser(activeLegislation)) {
618
+ return false;
619
+ }
620
+ if (activeLegislation === "gdpr") {
621
+ const tcData = await getTcData();
622
+ return tcData.eventStatus === "useractioncomplete";
623
+ }
624
+ if (activeLegislation === "usnat") {
625
+ const gppData = await getGPPData();
626
+ return gppData.cmpDisplayStatus === "hidden";
627
+ }
628
+ return false;
629
+ }
630
+ function initConsentSyncValidation() {
631
+ if (window.__tcfapi) {
632
+ window.__tcfapi("addEventListener", 2, (data) => {
633
+ if (data.eventStatus === "cmpuishown") {
634
+ setWaitingForUser("gdpr");
635
+ }
636
+ });
637
+ }
638
+ if (window.__gpp) {
639
+ window.__gpp("addEventListener", ({ pingData }) => {
640
+ if (pingData.cmpDisplayStatus === "visible") {
641
+ setWaitingForUser("usnat");
642
+ }
643
+ });
644
+ }
645
+ }
594
646
  async function saveConsent(consentEndpoint, payload) {
595
647
  try {
596
648
  const response = await fetch(consentEndpoint, {
@@ -637,10 +689,14 @@ function consentReadyHandlerFn(props) {
637
689
  if (!consentHasChanged) {
638
690
  return;
639
691
  }
692
+ const isUserInitiated = await isUserInitiatedUpdate(activeLegislation);
640
693
  const updateConsentStore = shouldUpdateConsentStore(props);
641
694
  const consentEndpoint = getConsentEndpoint(updateConsentStore, props);
642
- const payload = getConsentPayload(parsedConsent, updateConsentStore, props);
695
+ const payload = getConsentPayload(parsedConsent, updateConsentStore, isUserInitiated, props);
643
696
  await saveConsent(consentEndpoint, payload);
697
+ if (isUserInitiated) {
698
+ completeWaitingForUser();
699
+ }
644
700
  document.dispatchEvent(new CustomEvent("oCookieMessage.act", { bubbles: true }));
645
701
  };
646
702
  }
@@ -807,7 +863,7 @@ function setupPmTracking(trackingProps, cmpBaseEndpoint) {
807
863
  false
808
864
  );
809
865
  }
810
- const version = "5.5.2";
866
+ const version = "5.6.0";
811
867
  async function initSourcepointCmp(options) {
812
868
  const {
813
869
  useFTSession = true,
@@ -835,6 +891,7 @@ async function initSourcepointCmp(options) {
835
891
  }
836
892
  propertyConfig = validateAndCleanConfig(propertyConfig);
837
893
  bootstrapCmp(propertyConfig, { userId, includeUsNat });
894
+ initConsentSyncValidation();
838
895
  window._sp_queue.push(() => {
839
896
  var _a, _b;
840
897
  (_b = (_a = window._sp_) == null ? void 0 : _a.addEventListener) == null ? void 0 : _b.call(
package/dist/index.js CHANGED
@@ -400,7 +400,7 @@ function bootstrapCmp(config, options) {
400
400
  window._sp_queue ?? (window._sp_queue = []);
401
401
  document.head.appendChild(getCmpScripts(options));
402
402
  }
403
- function getConsentPayload(parsedConsent, updateConsentStore, { formOfWordsId, cookieDomain }) {
403
+ function getConsentPayload(parsedConsent, updateConsentStore, isUserInitiated, { formOfWordsId, cookieDomain }) {
404
404
  const categoryNames = Object.keys(parsedConsent);
405
405
  const data = categoryNames.reduce(
406
406
  (payload, categoryName) => {
@@ -422,6 +422,7 @@ function getConsentPayload(parsedConsent, updateConsentStore, { formOfWordsId, c
422
422
  formOfWordsId,
423
423
  consentSource: SOURCEPOINT_CONSENT_SOURCE,
424
424
  cookieDomain,
425
+ skipDuplicateUpdates: !isUserInitiated,
425
426
  data
426
427
  };
427
428
  }
@@ -481,8 +482,9 @@ function parseUsNationalSection(sectionData) {
481
482
  parsedConsent[categoryName] = userHasNotOptedOut;
482
483
  }
483
484
  if (marketingOptOutStatus.usnat) {
484
- parsedConsent.personalisedMarketing = false;
485
- parsedConsent.behaviouralAds = false;
485
+ for (const categoryName of iabCategoryNames) {
486
+ parsedConsent[categoryName] = false;
487
+ }
486
488
  }
487
489
  return parsedConsent;
488
490
  }
@@ -490,8 +492,8 @@ const sectionParsers = {
490
492
  [sections.CALIFORNIA]: parseCaliforniaSection,
491
493
  [sections.US_NATIONAL]: parseUsNationalSection
492
494
  };
493
- async function parseGPPConsent() {
494
- const gppData = await new Promise((resolve, reject) => {
495
+ async function getGPPData() {
496
+ return new Promise((resolve, reject) => {
495
497
  try {
496
498
  if (window.__gpp) {
497
499
  window.__gpp("ping", resolve);
@@ -502,6 +504,9 @@ async function parseGPPConsent() {
502
504
  reject(error);
503
505
  }
504
506
  });
507
+ }
508
+ async function parseGPPConsent() {
509
+ const gppData = await getGPPData();
505
510
  const { parsedSections } = gppData;
506
511
  const applicableSection = getApplicableSection(gppData);
507
512
  if (!applicableSection || !parsedSections[applicableSection]) {
@@ -528,8 +533,8 @@ function checkConsentFor(categoryName, { purpose, vendor, specialFeatureOptins }
528
533
  );
529
534
  return requiredPurposesConsented && requiredIabVendorsConsented && requiredSpecialFeaturesConsented;
530
535
  }
531
- async function parseGDPRConsent() {
532
- const tcData = await new Promise((resolve, reject) => {
536
+ async function getTcData() {
537
+ return new Promise((resolve, reject) => {
533
538
  try {
534
539
  if (window.__tcfapi) {
535
540
  window.__tcfapi("addEventListener", 2, resolve);
@@ -540,6 +545,9 @@ async function parseGDPRConsent() {
540
545
  reject(error);
541
546
  }
542
547
  });
548
+ }
549
+ async function parseGDPRConsent() {
550
+ const tcData = await getTcData();
543
551
  const parsedConsent = {};
544
552
  for (const categoryName of iabCategoryNames) {
545
553
  parsedConsent[categoryName] = checkConsentFor(categoryName, tcData);
@@ -589,6 +597,50 @@ function getConsentEndpoint(updateConsentStore, props) {
589
597
  }
590
598
  return `${props.consentProxyHost}/__consent/consent-record-cookie?cookieDomain=${props.cookieDomain}`;
591
599
  }
600
+ const INITIAL_STATE$1 = {
601
+ gdpr: false,
602
+ usnat: false
603
+ };
604
+ const isWaitingForUserAction = Object.assign({}, INITIAL_STATE$1);
605
+ function setWaitingForUser(legislation) {
606
+ isWaitingForUserAction[legislation] = true;
607
+ }
608
+ function isWaitingForUser(legislation) {
609
+ return isWaitingForUserAction[legislation];
610
+ }
611
+ function completeWaitingForUser() {
612
+ Object.assign(isWaitingForUserAction, INITIAL_STATE$1);
613
+ }
614
+ async function isUserInitiatedUpdate(activeLegislation) {
615
+ if (!isWaitingForUser(activeLegislation)) {
616
+ return false;
617
+ }
618
+ if (activeLegislation === "gdpr") {
619
+ const tcData = await getTcData();
620
+ return tcData.eventStatus === "useractioncomplete";
621
+ }
622
+ if (activeLegislation === "usnat") {
623
+ const gppData = await getGPPData();
624
+ return gppData.cmpDisplayStatus === "hidden";
625
+ }
626
+ return false;
627
+ }
628
+ function initConsentSyncValidation() {
629
+ if (window.__tcfapi) {
630
+ window.__tcfapi("addEventListener", 2, (data) => {
631
+ if (data.eventStatus === "cmpuishown") {
632
+ setWaitingForUser("gdpr");
633
+ }
634
+ });
635
+ }
636
+ if (window.__gpp) {
637
+ window.__gpp("addEventListener", ({ pingData }) => {
638
+ if (pingData.cmpDisplayStatus === "visible") {
639
+ setWaitingForUser("usnat");
640
+ }
641
+ });
642
+ }
643
+ }
592
644
  async function saveConsent(consentEndpoint, payload) {
593
645
  try {
594
646
  const response = await fetch(consentEndpoint, {
@@ -635,10 +687,14 @@ function consentReadyHandlerFn(props) {
635
687
  if (!consentHasChanged) {
636
688
  return;
637
689
  }
690
+ const isUserInitiated = await isUserInitiatedUpdate(activeLegislation);
638
691
  const updateConsentStore = shouldUpdateConsentStore(props);
639
692
  const consentEndpoint = getConsentEndpoint(updateConsentStore, props);
640
- const payload = getConsentPayload(parsedConsent, updateConsentStore, props);
693
+ const payload = getConsentPayload(parsedConsent, updateConsentStore, isUserInitiated, props);
641
694
  await saveConsent(consentEndpoint, payload);
695
+ if (isUserInitiated) {
696
+ completeWaitingForUser();
697
+ }
642
698
  document.dispatchEvent(new CustomEvent("oCookieMessage.act", { bubbles: true }));
643
699
  };
644
700
  }
@@ -805,7 +861,7 @@ function setupPmTracking(trackingProps, cmpBaseEndpoint) {
805
861
  false
806
862
  );
807
863
  }
808
- const version = "5.5.2";
864
+ const version = "5.6.0";
809
865
  async function initSourcepointCmp(options) {
810
866
  const {
811
867
  useFTSession = true,
@@ -833,6 +889,7 @@ async function initSourcepointCmp(options) {
833
889
  }
834
890
  propertyConfig = validateAndCleanConfig(propertyConfig);
835
891
  bootstrapCmp(propertyConfig, { userId, includeUsNat });
892
+ initConsentSyncValidation();
836
893
  window._sp_queue.push(() => {
837
894
  var _a, _b;
838
895
  (_b = (_a = window._sp_) == null ? void 0 : _a.addEventListener) == null ? void 0 : _b.call(
@@ -1,2 +1,2 @@
1
- (function(){"use strict";const L=(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 _={};const C=(e,n)=>{if(typeof e=="object"){_=e;return}if(typeof e=="string"&&typeof n=="string"){_[e]=n;return}if(typeof e=="string"&&typeof n>"u")return _[e]||null;if(typeof e>"u"&&typeof n>"u")return _;throw new Error("Invalid arguments")};C.clear=()=>{_={}};const v={},D=()=>{const[,e]=/FTSession_s=([^;]+)/.exec(document.cookie)||[];return e},R=()=>{const e=C("uuid");if(e)return Promise.resolve({uuid:e});const n=D();return n?(v.uuid||(v.uuid=L(`/sessions/s/${n}`).then(({uuid:t}={})=>(delete v.uuid,t&&C("uuid",t),{uuid:t}))),v.uuid):Promise.resolve({uuid:void 0})},O="sourcepoint-cmp",F="FTPINK",U="FTConsent",V="sourcepointCmp/VngD.XycZut.595cp9fWdp5XYP9vlFvk",x=".ft.com",j="https://consent.ft.com",E={permutiveAds:{purposes:[2,4,8,9],iabVendors:[361],customVendors:[],specialFeatures:[]},demographicAds:{purposes:[7,9,10],iabVendors:[],customVendors:[],specialFeatures:[]},behaviouralAds:{purposes:[2,4,8,9],iabVendors:[],customVendors:[],specialFeatures:[]},programmaticAds:{purposes:[2],iabVendors:[],customVendors:[],specialFeatures:[]},personalisedMarketing:{purposes:[2,7,8,9,10],iabVendors:[],customVendors:[],specialFeatures:[]}},I=Object.keys(E),d={joinHref:!0,gdpr:{}},k={...d,accountId:1906,baseEndpoint:"https://consent-manager.ft.com",propertyHref:"https://local.ft.com",_clientOptions:{privacyManagerId:827767,manageCookiesLinkOverride:"ft.com/preferences/manage-cookies",rootDomain:"ft.com"}},y={...d,accountId:1906,baseEndpoint:"https://consent-manager.ft.com",propertyId:31642,_clientOptions:{privacyManagerId:827767,usnatPrivacyManagerId:1143274,ccpaPrivacyManagerId:944882,manageCookiesLinkOverride:"ft.com/preferences/manage-cookies",rootDomain:"ft.com"}},H={...d,accountId:1906,baseEndpoint:"https://consent-manager.pwmnet.com",propertyId:33414,_clientOptions:{rootDomain:"pwmnet.com"}},q={...d,accountId:1906,baseEndpoint:"https://consent-manager.fdiintelligence.com",propertyId:34061,_clientOptions:{rootDomain:"fdiintelligence.com"}},G={...d,accountId:1906,baseEndpoint:"https://consent-manager.thebanker.com",propertyId:34060,_clientOptions:{rootDomain:"thebanker.com"}},$={...d,accountId:1906,baseEndpoint:"https://consent-manager.bankingriskandregulation.com",propertyId:34059,_clientOptions:{rootDomain:"bankingriskandregulation.com"}},W={...d,accountId:1906,baseEndpoint:"https://consent-manager.sustainableviews.com",propertyId:34058,_clientOptions:{rootDomain:"sustainableviews.com"}},J={...d,accountId:1906,baseEndpoint:"https://consent-manager.ftadviser.com",propertyId:33416,_clientOptions:{rootDomain:"ftadviser.com"}},K={...d,accountId:1906,baseEndpoint:"https://consent-manager.investorschronicle.co.uk",propertyId:33415,_clientOptions:{rootDomain:"investorschronicle.co.uk"}},B={...d,accountId:1906,baseEndpoint:"https://cdn.privacy-mgmt.com",propertyId:33947,_clientOptions:{rootDomain:"ignitesasia.com"}},X={...d,accountId:1906,baseEndpoint:"https://cdn.privacy-mgmt.com",propertyId:33946,_clientOptions:{rootDomain:"igniteseurope.com"}},Y={...d,accountId:1906,baseEndpoint:"https://consent-manager.mandatewire.com",propertyId:35490,_clientOptions:{rootDomain:"mandatewire.com"}},z=Object.freeze(Object.defineProperty({__proto__:null,FT_DOTCOM_PROD:y,FT_DOTCOM_TEST:k,MM_IGNITES_ASIA:B,MM_IGNITES_EUROPE:X,SP_BANKING_RR:$,SP_FDI_INTELLIGENCE:q,SP_FT_ADVISER:J,SP_INVESTORS_CHRONICLE:K,SP_MANDATE_WIRE:Y,SP_PWMNET:H,SP_SUSTAINABLE_VIEWS:W,SP_THE_BANKER:G},Symbol.toStringTag,{value:"Module"}));function P(e,n){const t=document.createElement("script");return t.dataset.cmpScript=e,t.innerHTML=n,t}function Z(e){const n=document.createElement("script");return n.src=e,n}const Q={cmpFrames:"https://consent-manager.ft.com/unified/wrapperMessagingWithoutDetection.js"},N={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()}();',gppStub:`window.__gpp_addFrame=function(e){if(!window.frames[e])if(document.body){var t=document.createElement("iframe");t.style.cssText="display:none",t.name=e,document.body.appendChild(t)}else window.setTimeout(window.__gpp_addFrame,10,e)},window.__gpp_stub=function(){var e=arguments;if(__gpp.queue=__gpp.queue||[],__gpp.events=__gpp.events||[],!e.length||1==e.length&&"queue"==e[0])return __gpp.queue;if(1==e.length&&"events"==e[0])return __gpp.events;var t=e[0],p=e.length>1?e[1]:null,s=e.length>2?e[2]:null;if("ping"===t)p({gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnatv1","8:uscav1","9:usvav1","10:uscov1","11:usutv1","12:usctv1"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}},!0);else if("addEventListener"===t){"lastId"in __gpp||(__gpp.lastId=0),__gpp.lastId++;var n=__gpp.lastId;__gpp.events.push({id:n,callback:p,parameter:s}),p({eventName:"listenerRegistered",listenerId:n,data:!0,pingData:{gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnatv1","8:uscav1","9:usvav1","10:uscov1","11:usutv1","12:usctv1"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}}},!0)}else if("removeEventListener"===t){for(var a=!1,i=0;i<__gpp.events.length;i++)if(__gpp.events[i].id==s){__gpp.events.splice(i,1),a=!0;break}p({eventName:"listenerRemoved",listenerId:s,data:a,pingData:{gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnatv1","8:uscav1","9:usvav1","10:uscov1","11:usutv1","12:usctv1"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}}},!0)}else"hasSection"===t?p(!1,!0):"getSection"===t||"getField"===t?p(null,!0):__gpp.queue.push([].slice.apply(e))},window.__gpp_msghandler=function(e){var t="string"==typeof e.data;try{var p=t?JSON.parse(e.data):e.data}catch(e){p=null}if("object"==typeof p&&null!==p&&"__gppCall"in p){var s=p.__gppCall;window.__gpp(s.command,(function(p,n){var a={__gppReturn:{returnValue:p,success:n,callId:s.callId}};e.source.postMessage(t?JSON.stringify(a):a,"*")}),"parameter"in s?s.parameter:null,"version"in s?s.version:"1.1")}},"__gpp"in window&&"function"==typeof window.__gpp||(window.__gpp=window.__gpp_stub,window.addEventListener("message",window.__gpp_msghandler,!1),window.__gpp_addFrame("__gppLocator"));
2
- `};function ee(e){const n=document.createDocumentFragment();return n.appendChild(P("tcf",N.tcfStub)),e.includeUsNat&&n.appendChild(P("gpp",N.gppStub)),n.appendChild(Z(Q.cmpFrames)),n}function te(e,n){const{userId:t,includeUsNat:o}=n;return t&&(e.authId=t),o&&(e.usnat=e.usnat||{}),e}function ne(e,n){const{_clientOptions:t,...o}=e,s=te(o,n);window._sp_={config:s},window._sp_queue??(window._sp_queue=[]),document.head.appendChild(ee(n))}function oe(e,n,{formOfWordsId:t,cookieDomain:o}){const r=Object.keys(e).reduce((a,i)=>(a[i]={onsite:{status:e[i],lbi:!1,source:O,fow:t}},a),{});return n?{setConsentCookie:!0,formOfWordsId:t,consentSource:O,cookieDomain:o,data:r}:{data:r,cookieDomain:o}}const m={CALIFORNIA:"uscav1",US_NATIONAL:"usnatv1"},T={[m.CALIFORNIA]:{excludedCategories:{personalisedMarketing:!0}},[m.US_NATIONAL]:{excludedCategories:{personalisedMarketing:!0}}};function se(e){const{applicableSections:n,supportedAPIs:t}=e,o=n[0];if(o===-1||typeof o>"u")return;const s=t.find(a=>a.startsWith(`${o}:`));return s==null?void 0:s.split(":")[1]}function re(e){const{SaleOptOut:n,SharingOptOut:t,Gpc:o}=e,{excludedCategories:s}=T[m.CALIFORNIA],r=n!==1&&t!==1&&!o,a={};for(const i of I){if(i in s){a[i]=!0;continue}a[i]=r}return a}function ae(e){const{SaleOptOut:n,SharingOptOut:t,TargetedAdvertisingOptOut:o}=e,{excludedCategories:s}=T[m.US_NATIONAL],r=JSON.parse(localStorage.getItem("ft_sp_marketing_optout")||"{}"),a=n!==1&&t!==1&&o!==1,i={};for(const c of I){if(c in s){i[c]=!0;continue}i[c]=a}return r.usnat&&(i.personalisedMarketing=!1,i.behaviouralAds=!1),i}const ie={[m.CALIFORNIA]:re,[m.US_NATIONAL]:ae};async function ce(){const e=await new Promise((a,i)=>{try{window.__gpp?window.__gpp("ping",a):i(new Error("GPP API is not available on page"))}catch(c){i(c)}}),{parsedSections:n}=e,t=se(e);if(!t||!n[t])throw new Error("GPP parser was called without an applicable section");const o=n[t],s=ie[t];if(!s||typeof s!="function")throw new Error(`No parser found for applicable GPP section: ${t}`);return s(o)}function pe(e,{purpose:n,vendor:t,specialFeatureOptins:o}){const s=E[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}async function ue(){const e=await new Promise((t,o)=>{try{window.__tcfapi?window.__tcfapi("addEventListener",2,t):o(new Error("TCF API is not available on page"))}catch(s){o(s)}}),n={};for(const t of I)n[t]=pe(t,e);return n}async function de(e){const t={gdpr:ue,usnat:ce}[e];if(!t)throw new Error("Unable to update user consent. Unsupported consent legislation.");return t()}function le(){const n=Object.fromEntries(document.cookie.split("; ").map(o=>o.split("=")))[U];if(!n)return{};const t=decodeURIComponent(n);return Object.fromEntries(t.split(",").map(o=>{const[s,r]=o.split(":");return[s,r==="on"]}))}function fe(e,n){return Object.keys(e).some(o=>{const s=`${o.toLowerCase()}Onsite`;return e[o]!==n[s]})}function ge({userId:e,useConsentStore:n}){return!!e&&n===!0}function me(e,n){return e?`${n.consentProxyHost}/__consent/consent-record/${F}/${n.userId}?updateFtConsentCookie=true`:`${n.consentProxyHost}/__consent/consent-record-cookie?cookieDomain=${n.cookieDomain}`}async function _e(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)}}const ve=()=>{document.dispatchEvent(new CustomEvent("onCmpConsentReady",{bubbles:!0}))};function ye(e){return async function(t,o,s,r){if(ve(),e.disableFTCookies||!e.includeUsNat&&t==="usnat")return;const a=r.applies?t:"gdpr";if(a!==t||!s)return;let i;try{i=await de(a)}catch(g){console.error(g)}if(!i||!fe(i,le()))return;const p=ge(e),f=me(p,e),u=oe(i,p,e);await _e(f,u),document.dispatchEvent(new CustomEvent("oCookieMessage.act",{bubbles:!0}))}}const b="cookie-message",we="manage-cookies";let S=Object.freeze({activeComponent:b,messageId:0,privacyManagerId:0});function Ce(e){return typeof e=="object"&&e!==null&&e.constructor===Object&&Object.prototype.toString.call(e)==="[object Object]"}const Ie=()=>({...S}),h=e=>{if(!Ce(e)){console.error("Invalid state changes");return}S={...S,...e}},be=["adsDisableInternalCMP","pwm.cmp","messageSlotBottom"];function Se(e,n){const t=he(e.flags);window._sp_queue=window._sp_queue??[],window._sp_queue.push(()=>{var o,s;for(const[r,a]of Object.entries(Ee))(s=(o=window._sp_).addEventListener)==null||s.call(o,r,a({...e,flags:t}))}),ke({...e,flags:t},n)}function he(e){const n={};return typeof e=="object"&&be.forEach(t=>{Object.prototype.hasOwnProperty.call(e,t)&&(n[t]=e[t])}),n}function Oe(e){if(!e)return;const n=document.body,t=new CustomEvent("oTracking.event",{bubbles:!0,cancelable:!0,detail:e.detail});n.dispatchEvent(t)}function w({trackingProps:e,action:n,triggerAction:t}){let o;const s=Ie(),{product:r,app:a,flags:i}=e;s.activeComponent===b?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}};Oe(c)}const Ee={onMessageChoiceSelect:e=>(n,t,o)=>{const r={11:"accept_all",12:"manage_cookies",13:"reject_all"}[o];r&&w({trackingProps:e,action:"click",triggerAction:r})},onMessageReady:e=>()=>{w({trackingProps:e,action:"view"})},onMessageReceiveData:()=>(e,n)=>{const{messageId:t}=n;t&&h({messageId:t})},onError:e=>(n,t)=>{w({trackingProps:e,action:"error",triggerAction:t})},onPMCancel:()=>()=>{h({activeComponent:b})}};function ke(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&&h({activeComponent:we,privacyManagerId:+a}),!(!r||!o[r])&&w({trackingProps:e,action:"click",triggerAction:o[r]}))},!1)}const Pe="5.5.2";async function Ne(e){const{useFTSession:n=!0,consentProxyHost:t=j,cookieDomain:o=x,formOfWordsId:s=V,useConsentStore:r=!0,trackingContext:a={},disableFTCookies:i=!1,includeUsNat:c=!1}=e||{};let{propertyConfig:p=y,userId:f}=e||{};if(typeof window>"u"){console.error("The CMP client can only be initialised in a browser context");return}if(window.FT_CMP_CLIENT_VERSION=Pe,!f&&n)try{const u=await R();f=u==null?void 0:u.uuid}catch(u){console.error(u)}p=Te(p),ne(p,{userId:f,includeUsNat:c}),window._sp_queue.push(()=>{var u,g;(g=(u=window._sp_)==null?void 0:u.addEventListener)==null||g.call(u,"onConsentReady",ye({userId:f,consentProxyHost:t,cookieDomain:o,formOfWordsId:s,useConsentStore:r,disableFTCookies:i,includeUsNat:c}))}),Se(a,p.baseEndpoint)}function Te(e){if(!(e!=null&&e.accountId))throw new Error("Please pass a valid property config");return 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),e}function M(e,n,t,o,s,r){const{text:a,onClick:i}=o[n],c=document.querySelectorAll(`a[href*="${r}"]`);for(const p of c)(t||e)&&(s.has(p)&&p.removeEventListener("click",s.get(p)),p.innerText=a,p.addEventListener("click",i),s.set(p,i))}function Me({_clientOptions:e}=y){const{privacyManagerId:n,ccpaPrivacyManagerId:t,usnatPrivacyManagerId:o,manageCookiesLinkOverride:s}=e??y._clientOptions,r={usnat:{text:"Do Not Sell My Personal Information",onClick:c=>{var p;c.preventDefault(),(p=window._sp_.usnat)==null||p.loadPrivacyManagerModal(o)}},ccpa:{text:"Do Not Sell My Personal Information",onClick:c=>{var p;c.preventDefault(),(p=window._sp_.ccpa)==null||p.loadPrivacyManagerModal(t)}},gdpr:{text:"Manage Cookies",onClick:c=>{var p;c.preventDefault(),(p=window._sp_.gdpr)==null||p.loadPrivacyManagerModal(n)}}},a=new Map,i=function(c,p,f,u){M(!1,c,u.applies,r,a,s),u.applies&&window._sp_queue.push(()=>{var g,A;(A=(g=window._sp_).removeEventListener)==null||A.call(g,"onConsentReady",i)})};M(!0,"gdpr",!1,r,a,s),window._sp_queue??(window._sp_queue=[]),window._sp_queue.push(()=>{var c,p;(p=(c=window._sp_).addEventListener)==null||p.call(c,"onConsentReady",i)})}function Ae(e){const n=document.querySelector(e);return n?JSON.parse(n.textContent||"{}"):{}}function Le(){return{flags:Ae("script#page-kit-flags-embed")}}function De(e){const{includeUsNat:n}=e._clientOptions||{},{flags:t}=Le();return t!=null&&t.adsEnableGpp||n?{includeUsNat:!0}:{}}const Re={"ft.com":De};function Fe(e){return new Promise((n,t)=>{const{rootDomain:o}=e._clientOptions||{};if(!o){n({});return}const s=Re[o];if(!s||typeof s!="function"){n({});return}const r=()=>{try{n(s(e))}catch(a){t(a)}};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",r):r()})}function Ue(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 Ve(e){if(!e)throw new Error("Invalid hostname provided");let t=Object.values(z).find(o=>{var r;if(o.propertyHref)return!1;const s=(r=o._clientOptions)==null?void 0:r.rootDomain;return s&&Ue(e,s)});return t??(t=k),t}const xe=new URL(window.location.href).hostname,l=Ve(xe);(async()=>{var e,n;try{const t=await Fe(l);Ne({propertyConfig:l,...t}),(e=l==null?void 0:l._clientOptions)!=null&&e.privacyManagerId&&((n=l==null?void 0:l._clientOptions)!=null&&n.manageCookiesLinkOverride)&&Me(l)}catch(t){console.error("Error: CMP package configure + initialise Sourcepoint failed.",t)}})()})();
1
+ (function(){"use strict";const V=(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 _={};const S=(e,t)=>{if(typeof e=="object"){_=e;return}if(typeof e=="string"&&typeof t=="string"){_[e]=t;return}if(typeof e=="string"&&typeof t>"u")return _[e]||null;if(typeof e>"u"&&typeof t>"u")return _;throw new Error("Invalid arguments")};S.clear=()=>{_={}};const y={},x=()=>{const[,e]=/FTSession_s=([^;]+)/.exec(document.cookie)||[];return e},j=()=>{const e=S("uuid");if(e)return Promise.resolve({uuid:e});const t=x();return t?(y.uuid||(y.uuid=V(`/sessions/s/${t}`).then(({uuid:n}={})=>(delete y.uuid,n&&S("uuid",n),{uuid:n}))),y.uuid):Promise.resolve({uuid:void 0})},k="sourcepoint-cmp",H="FTPINK",q="FTConsent",G="sourcepointCmp/VngD.XycZut.595cp9fWdp5XYP9vlFvk",$=".ft.com",W="https://consent.ft.com",T={permutiveAds:{purposes:[2,4,8,9],iabVendors:[361],customVendors:[],specialFeatures:[]},demographicAds:{purposes:[7,9,10],iabVendors:[],customVendors:[],specialFeatures:[]},behaviouralAds:{purposes:[2,4,8,9],iabVendors:[],customVendors:[],specialFeatures:[]},programmaticAds:{purposes:[2],iabVendors:[],customVendors:[],specialFeatures:[]},personalisedMarketing:{purposes:[2,7,8,9,10],iabVendors:[],customVendors:[],specialFeatures:[]}},v=Object.keys(T),d={joinHref:!0,gdpr:{}},N={...d,accountId:1906,baseEndpoint:"https://consent-manager.ft.com",propertyHref:"https://local.ft.com",_clientOptions:{privacyManagerId:827767,manageCookiesLinkOverride:"ft.com/preferences/manage-cookies",rootDomain:"ft.com"}},w={...d,accountId:1906,baseEndpoint:"https://consent-manager.ft.com",propertyId:31642,_clientOptions:{privacyManagerId:827767,usnatPrivacyManagerId:1143274,ccpaPrivacyManagerId:944882,manageCookiesLinkOverride:"ft.com/preferences/manage-cookies",rootDomain:"ft.com"}},J={...d,accountId:1906,baseEndpoint:"https://consent-manager.pwmnet.com",propertyId:33414,_clientOptions:{rootDomain:"pwmnet.com"}},K={...d,accountId:1906,baseEndpoint:"https://consent-manager.fdiintelligence.com",propertyId:34061,_clientOptions:{rootDomain:"fdiintelligence.com"}},B={...d,accountId:1906,baseEndpoint:"https://consent-manager.thebanker.com",propertyId:34060,_clientOptions:{rootDomain:"thebanker.com"}},X={...d,accountId:1906,baseEndpoint:"https://consent-manager.bankingriskandregulation.com",propertyId:34059,_clientOptions:{rootDomain:"bankingriskandregulation.com"}},Y={...d,accountId:1906,baseEndpoint:"https://consent-manager.sustainableviews.com",propertyId:34058,_clientOptions:{rootDomain:"sustainableviews.com"}},z={...d,accountId:1906,baseEndpoint:"https://consent-manager.ftadviser.com",propertyId:33416,_clientOptions:{rootDomain:"ftadviser.com"}},Z={...d,accountId:1906,baseEndpoint:"https://consent-manager.investorschronicle.co.uk",propertyId:33415,_clientOptions:{rootDomain:"investorschronicle.co.uk"}},Q={...d,accountId:1906,baseEndpoint:"https://cdn.privacy-mgmt.com",propertyId:33947,_clientOptions:{rootDomain:"ignitesasia.com"}},ee={...d,accountId:1906,baseEndpoint:"https://cdn.privacy-mgmt.com",propertyId:33946,_clientOptions:{rootDomain:"igniteseurope.com"}},te={...d,accountId:1906,baseEndpoint:"https://consent-manager.mandatewire.com",propertyId:35490,_clientOptions:{rootDomain:"mandatewire.com"}},ne=Object.freeze(Object.defineProperty({__proto__:null,FT_DOTCOM_PROD:w,FT_DOTCOM_TEST:N,MM_IGNITES_ASIA:Q,MM_IGNITES_EUROPE:ee,SP_BANKING_RR:X,SP_FDI_INTELLIGENCE:K,SP_FT_ADVISER:z,SP_INVESTORS_CHRONICLE:Z,SP_MANDATE_WIRE:te,SP_PWMNET:J,SP_SUSTAINABLE_VIEWS:Y,SP_THE_BANKER:B},Symbol.toStringTag,{value:"Module"}));function P(e,t){const n=document.createElement("script");return n.dataset.cmpScript=e,n.innerHTML=t,n}function oe(e){const t=document.createElement("script");return t.src=e,t}const se={cmpFrames:"https://consent-manager.ft.com/unified/wrapperMessagingWithoutDetection.js"},A={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()}();',gppStub:`window.__gpp_addFrame=function(e){if(!window.frames[e])if(document.body){var t=document.createElement("iframe");t.style.cssText="display:none",t.name=e,document.body.appendChild(t)}else window.setTimeout(window.__gpp_addFrame,10,e)},window.__gpp_stub=function(){var e=arguments;if(__gpp.queue=__gpp.queue||[],__gpp.events=__gpp.events||[],!e.length||1==e.length&&"queue"==e[0])return __gpp.queue;if(1==e.length&&"events"==e[0])return __gpp.events;var t=e[0],p=e.length>1?e[1]:null,s=e.length>2?e[2]:null;if("ping"===t)p({gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnatv1","8:uscav1","9:usvav1","10:uscov1","11:usutv1","12:usctv1"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}},!0);else if("addEventListener"===t){"lastId"in __gpp||(__gpp.lastId=0),__gpp.lastId++;var n=__gpp.lastId;__gpp.events.push({id:n,callback:p,parameter:s}),p({eventName:"listenerRegistered",listenerId:n,data:!0,pingData:{gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnatv1","8:uscav1","9:usvav1","10:uscov1","11:usutv1","12:usctv1"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}}},!0)}else if("removeEventListener"===t){for(var a=!1,i=0;i<__gpp.events.length;i++)if(__gpp.events[i].id==s){__gpp.events.splice(i,1),a=!0;break}p({eventName:"listenerRemoved",listenerId:s,data:a,pingData:{gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnatv1","8:uscav1","9:usvav1","10:uscov1","11:usutv1","12:usctv1"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}}},!0)}else"hasSection"===t?p(!1,!0):"getSection"===t||"getField"===t?p(null,!0):__gpp.queue.push([].slice.apply(e))},window.__gpp_msghandler=function(e){var t="string"==typeof e.data;try{var p=t?JSON.parse(e.data):e.data}catch(e){p=null}if("object"==typeof p&&null!==p&&"__gppCall"in p){var s=p.__gppCall;window.__gpp(s.command,(function(p,n){var a={__gppReturn:{returnValue:p,success:n,callId:s.callId}};e.source.postMessage(t?JSON.stringify(a):a,"*")}),"parameter"in s?s.parameter:null,"version"in s?s.version:"1.1")}},"__gpp"in window&&"function"==typeof window.__gpp||(window.__gpp=window.__gpp_stub,window.addEventListener("message",window.__gpp_msghandler,!1),window.__gpp_addFrame("__gppLocator"));
2
+ `};function ie(e){const t=document.createDocumentFragment();return t.appendChild(P("tcf",A.tcfStub)),e.includeUsNat&&t.appendChild(P("gpp",A.gppStub)),t.appendChild(oe(se.cmpFrames)),t}function ae(e,t){const{userId:n,includeUsNat:o}=t;return n&&(e.authId=n),o&&(e.usnat=e.usnat||{}),e}function re(e,t){const{_clientOptions:n,...o}=e,s=ae(o,t);window._sp_={config:s},window._sp_queue??(window._sp_queue=[]),document.head.appendChild(ie(t))}function ce(e,t,n,{formOfWordsId:o,cookieDomain:s}){const r=Object.keys(e).reduce((c,a)=>(c[a]={onsite:{status:e[a],lbi:!1,source:k,fow:o}},c),{});return t?{setConsentCookie:!0,formOfWordsId:o,consentSource:k,cookieDomain:s,skipDuplicateUpdates:!n,data:r}:{data:r,cookieDomain:s}}const m={CALIFORNIA:"uscav1",US_NATIONAL:"usnatv1"},M={[m.CALIFORNIA]:{excludedCategories:{personalisedMarketing:!0}},[m.US_NATIONAL]:{excludedCategories:{personalisedMarketing:!0}}};function pe(e){const{applicableSections:t,supportedAPIs:n}=e,o=t[0];if(o===-1||typeof o>"u")return;const s=n.find(r=>r.startsWith(`${o}:`));return s==null?void 0:s.split(":")[1]}function ue(e){const{SaleOptOut:t,SharingOptOut:n,Gpc:o}=e,{excludedCategories:s}=M[m.CALIFORNIA],i=t!==1&&n!==1&&!o,r={};for(const c of v){if(c in s){r[c]=!0;continue}r[c]=i}return r}function de(e){const{SaleOptOut:t,SharingOptOut:n,TargetedAdvertisingOptOut:o}=e,{excludedCategories:s}=M[m.US_NATIONAL],i=JSON.parse(localStorage.getItem("ft_sp_marketing_optout")||"{}"),r=t!==1&&n!==1&&o!==1,c={};for(const a of v){if(a in s){c[a]=!0;continue}c[a]=r}if(i.usnat)for(const a of v)c[a]=!1;return c}const le={[m.CALIFORNIA]:ue,[m.US_NATIONAL]:de};async function D(){return new Promise((e,t)=>{try{window.__gpp?window.__gpp("ping",e):t(new Error("GPP API is not available on page"))}catch(n){t(n)}})}async function fe(){const e=await D(),{parsedSections:t}=e,n=pe(e);if(!n||!t[n])throw new Error("GPP parser was called without an applicable section");const o=t[n],s=le[n];if(!s||typeof s!="function")throw new Error(`No parser found for applicable GPP section: ${n}`);return s(o)}function ge(e,{purpose:t,vendor:n,specialFeatureOptins:o}){const s=T[e],i=s.purposes.every(a=>(t==null?void 0:t.consents[a])||(t==null?void 0:t.legitimateInterests[a])),r=s.iabVendors.every(a=>(n==null?void 0:n.consents[a])||(n==null?void 0:n.legitimateInterests[a])),c=s.specialFeatures.every(a=>(o==null?void 0:o[a])===!0);return i&&r&&c}async function L(){return new Promise((e,t)=>{try{window.__tcfapi?window.__tcfapi("addEventListener",2,e):t(new Error("TCF API is not available on page"))}catch(n){t(n)}})}async function me(){const e=await L(),t={};for(const n of v)t[n]=ge(n,e);return t}async function _e(e){const n={gdpr:me,usnat:fe}[e];if(!n)throw new Error("Unable to update user consent. Unsupported consent legislation.");return n()}function ye(){const t=Object.fromEntries(document.cookie.split("; ").map(o=>o.split("=")))[q];if(!t)return{};const n=decodeURIComponent(t);return Object.fromEntries(n.split(",").map(o=>{const[s,i]=o.split(":");return[s,i==="on"]}))}function ve(e,t){return Object.keys(e).some(o=>{const s=`${o.toLowerCase()}Onsite`;return e[o]!==t[s]})}function we({userId:e,useConsentStore:t}){return!!e&&t===!0}function Ie(e,t){return e?`${t.consentProxyHost}/__consent/consent-record/${H}/${t.userId}?updateFtConsentCookie=true`:`${t.consentProxyHost}/__consent/consent-record-cookie?cookieDomain=${t.cookieDomain}`}const F={gdpr:!1,usnat:!1},b=Object.assign({},F);function R(e){b[e]=!0}function Ce(e){return b[e]}function Se(){Object.assign(b,F)}async function be(e){return Ce(e)?e==="gdpr"?(await L()).eventStatus==="useractioncomplete":e==="usnat"?(await D()).cmpDisplayStatus==="hidden":!1:!1}function he(){window.__tcfapi&&window.__tcfapi("addEventListener",2,e=>{e.eventStatus==="cmpuishown"&&R("gdpr")}),window.__gpp&&window.__gpp("addEventListener",({pingData:e})=>{e.cmpDisplayStatus==="visible"&&R("usnat")})}async function Oe(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)}}const Ee=()=>{document.dispatchEvent(new CustomEvent("onCmpConsentReady",{bubbles:!0}))};function ke(e){return async function(n,o,s,i){if(Ee(),e.disableFTCookies||!e.includeUsNat&&n==="usnat")return;const r=i.applies?n:"gdpr";if(r!==n||!s)return;let c;try{c=await _e(r)}catch(C){console.error(C)}if(!c||!ve(c,ye()))return;const p=await be(r),f=we(e),u=Ie(f,e),g=ce(c,f,p,e);await Oe(u,g),p&&Se(),document.dispatchEvent(new CustomEvent("oCookieMessage.act",{bubbles:!0}))}}const h="cookie-message",Te="manage-cookies";let O=Object.freeze({activeComponent:h,messageId:0,privacyManagerId:0});function Ne(e){return typeof e=="object"&&e!==null&&e.constructor===Object&&Object.prototype.toString.call(e)==="[object Object]"}const Pe=()=>({...O}),E=e=>{if(!Ne(e)){console.error("Invalid state changes");return}O={...O,...e}},Ae=["adsDisableInternalCMP","pwm.cmp","messageSlotBottom"];function Me(e,t){const n=De(e.flags);window._sp_queue=window._sp_queue??[],window._sp_queue.push(()=>{var o,s;for(const[i,r]of Object.entries(Fe))(s=(o=window._sp_).addEventListener)==null||s.call(o,i,r({...e,flags:n}))}),Re({...e,flags:n},t)}function De(e){const t={};return typeof e=="object"&&Ae.forEach(n=>{Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])}),t}function Le(e){if(!e)return;const t=document.body,n=new CustomEvent("oTracking.event",{bubbles:!0,cancelable:!0,detail:e.detail});t.dispatchEvent(n)}function I({trackingProps:e,action:t,triggerAction:n}){let o;const s=Pe(),{product:i,app:r,flags:c}=e;s.activeComponent===h?o=s.messageId:o=s.privacyManagerId;const a={detail:{component:{id:o,name:s.activeComponent,type:"overlay",subtype:"cmp"},category:"component",action:t,...n&&{trigger_action:n},...i&&{product:i},...r&&{app:r},custom:[{cookie_toggle_flag:c}],url:window.document.location.href||null}};Le(a)}const Fe={onMessageChoiceSelect:e=>(t,n,o)=>{const i={11:"accept_all",12:"manage_cookies",13:"reject_all"}[o];i&&I({trackingProps:e,action:"click",triggerAction:i})},onMessageReady:e=>()=>{I({trackingProps:e,action:"view"})},onMessageReceiveData:()=>(e,t)=>{const{messageId:n}=t;n&&E({messageId:n})},onError:e=>(t,n)=>{I({trackingProps:e,action:"error",triggerAction:n})},onPMCancel:()=>()=>{E({activeComponent:h})}};function Re(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:i,messageId:r="0"}={}}=n;s&&(+r&&E({activeComponent:Te,privacyManagerId:+r}),!(!i||!o[i])&&I({trackingProps:e,action:"click",triggerAction:o[i]}))},!1)}const Ue="5.6.0";async function Ve(e){const{useFTSession:t=!0,consentProxyHost:n=W,cookieDomain:o=$,formOfWordsId:s=G,useConsentStore:i=!0,trackingContext:r={},disableFTCookies:c=!1,includeUsNat:a=!1}=e||{};let{propertyConfig:p=w,userId:f}=e||{};if(typeof window>"u"){console.error("The CMP client can only be initialised in a browser context");return}if(window.FT_CMP_CLIENT_VERSION=Ue,!f&&t)try{const u=await j();f=u==null?void 0:u.uuid}catch(u){console.error(u)}p=xe(p),re(p,{userId:f,includeUsNat:a}),he(),window._sp_queue.push(()=>{var u,g;(g=(u=window._sp_)==null?void 0:u.addEventListener)==null||g.call(u,"onConsentReady",ke({userId:f,consentProxyHost:n,cookieDomain:o,formOfWordsId:s,useConsentStore:i,disableFTCookies:c,includeUsNat:a}))}),Me(r,p.baseEndpoint)}function xe(e){if(!(e!=null&&e.accountId))throw new Error("Please pass a valid property config");return 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),e}function U(e,t,n,o,s,i){const{text:r,onClick:c}=o[t],a=document.querySelectorAll(`a[href*="${i}"]`);for(const p of a)(n||e)&&(s.has(p)&&p.removeEventListener("click",s.get(p)),p.innerText=r,p.addEventListener("click",c),s.set(p,c))}function je({_clientOptions:e}=w){const{privacyManagerId:t,ccpaPrivacyManagerId:n,usnatPrivacyManagerId:o,manageCookiesLinkOverride:s}=e??w._clientOptions,i={usnat:{text:"Do Not Sell My Personal Information",onClick:a=>{var p;a.preventDefault(),(p=window._sp_.usnat)==null||p.loadPrivacyManagerModal(o)}},ccpa:{text:"Do Not Sell My Personal Information",onClick:a=>{var p;a.preventDefault(),(p=window._sp_.ccpa)==null||p.loadPrivacyManagerModal(n)}},gdpr:{text:"Manage Cookies",onClick:a=>{var p;a.preventDefault(),(p=window._sp_.gdpr)==null||p.loadPrivacyManagerModal(t)}}},r=new Map,c=function(a,p,f,u){U(!1,a,u.applies,i,r,s),u.applies&&window._sp_queue.push(()=>{var g,C;(C=(g=window._sp_).removeEventListener)==null||C.call(g,"onConsentReady",c)})};U(!0,"gdpr",!1,i,r,s),window._sp_queue??(window._sp_queue=[]),window._sp_queue.push(()=>{var a,p;(p=(a=window._sp_).addEventListener)==null||p.call(a,"onConsentReady",c)})}function He(e){const t=document.querySelector(e);return t?JSON.parse(t.textContent||"{}"):{}}function qe(){return{flags:He("script#page-kit-flags-embed")}}function Ge(e){const{includeUsNat:t}=e._clientOptions||{},{flags:n}=qe();return n!=null&&n.adsEnableGpp||t?{includeUsNat:!0}:{}}const $e={"ft.com":Ge};function We(e){return new Promise((t,n)=>{const{rootDomain:o}=e._clientOptions||{};if(!o)return t({});const s=$e[o];if(!s||typeof s!="function")return t({...e._clientOptions});const i=()=>{try{t(s(e))}catch(r){n(r)}};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",i):i()})}function Je(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 Ke(e){if(!e)throw new Error("Invalid hostname provided");let n=Object.values(ne).find(o=>{var i;if(o.propertyHref)return!1;const s=(i=o._clientOptions)==null?void 0:i.rootDomain;return s&&Je(e,s)});return n??(n=N),n}const Be=new URL(window.location.href).hostname,l=Ke(Be);(async()=>{var e,t;try{const n=await We(l);Ve({propertyConfig:l,...n}),(e=l==null?void 0:l._clientOptions)!=null&&e.privacyManagerId&&((t=l==null?void 0:l._clientOptions)!=null&&t.manageCookiesLinkOverride)&&je(l)}catch(n){console.error("Error: CMP package configure + initialise Sourcepoint failed.",n)}})()})();
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAY,MAAM,uBAAuB,CAAC;AAWtE,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,cAAc,iBAiD/D"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAY,MAAM,uBAAuB,CAAC;AAYtE,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,cAAc,iBAkD/D"}
@@ -1,3 +1,4 @@
1
- import type { ParsedConsentState } from "../../../typings/types";
1
+ import type { GPP, ParsedConsentState } from "../../../typings/types";
2
+ export declare function getGPPData(): Promise<GPP.PingData>;
2
3
  export declare function parseGPPConsent(): Promise<ParsedConsentState>;
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/consent-parsers/gpp/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAsFtE,wBAAsB,eAAe,gCA4BpC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/consent-parsers/gpp/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAsFtE,wBAAsB,UAAU,0BAY/B;AAED,wBAAsB,eAAe,gCAkBpC"}
@@ -6,5 +6,6 @@ import type { IabCustomCategoryName, ParsedConsentState, TCData } from "../../..
6
6
  * @returns {boolean} - Returns true if consent is granted, otherwise false.
7
7
  */
8
8
  export declare function checkConsentFor(categoryName: IabCustomCategoryName, { purpose, vendor, specialFeatureOptins }: Partial<TCData>): boolean;
9
+ export declare function getTcData(): Promise<TCData>;
9
10
  export declare function parseGDPRConsent(): Promise<ParsedConsentState>;
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/consent-parsers/tcfv2/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhG;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,qBAAqB,EACnC,EAAE,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,GACzD,OAAO,CAmBT;AAED,wBAAsB,gBAAgB,gCAqBrC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/consent-parsers/tcfv2/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhG;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,qBAAqB,EACnC,EAAE,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,GACzD,OAAO,CAmBT;AAED,wBAAsB,SAAS,oBAc9B;AAED,wBAAsB,gBAAgB,gCASrC"}
@@ -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;AAkC/E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,iBAAiB,iBAE7C,MAAM,gBACL,MAAM,iBACL,MAAM,eACR;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,mBA0CrC"}
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;AAoC/E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,iBAAiB,iBAE7C,MAAM,gBACL,MAAM,iBACL,MAAM,eACR;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,mBA8CrC"}
@@ -2,11 +2,12 @@ import type { ParsedConsentState, ConsentPayloadOptions, ConsentCategoryPayload
2
2
  /**
3
3
  * Build payload for updating user's consent
4
4
  */
5
- export declare function getConsentPayload(parsedConsent: ParsedConsentState, updateConsentStore: boolean, { formOfWordsId, cookieDomain }: Partial<ConsentPayloadOptions>): {
5
+ export declare function getConsentPayload(parsedConsent: ParsedConsentState, updateConsentStore: boolean, isUserInitiated: boolean, { formOfWordsId, cookieDomain }: Partial<ConsentPayloadOptions>): {
6
6
  setConsentCookie: boolean;
7
7
  formOfWordsId: string | undefined;
8
8
  consentSource: string;
9
9
  cookieDomain: string | undefined;
10
+ skipDuplicateUpdates: boolean;
10
11
  data: Record<string, ConsentCategoryPayload>;
11
12
  } | {
12
13
  data: Record<string, ConsentCategoryPayload>;
@@ -14,5 +15,6 @@ export declare function getConsentPayload(parsedConsent: ParsedConsentState, upd
14
15
  setConsentCookie?: undefined;
15
16
  formOfWordsId?: undefined;
16
17
  consentSource?: undefined;
18
+ skipDuplicateUpdates?: undefined;
17
19
  };
18
20
  //# sourceMappingURL=get-consent-payload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-consent-payload.d.ts","sourceRoot":"","sources":["../../../../src/consent-ready/utils/get-consent-payload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EAEvB,MAAM,wBAAwB,CAAC;AAIhC;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,kBAAkB,EACjC,kBAAkB,EAAE,OAAO,EAC3B,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC,qBAAqB,CAAC;;;;;;;;;;;;EA6BhE"}
1
+ {"version":3,"file":"get-consent-payload.d.ts","sourceRoot":"","sources":["../../../../src/consent-ready/utils/get-consent-payload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EAEvB,MAAM,wBAAwB,CAAC;AAIhC;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,kBAAkB,EACjC,kBAAkB,EAAE,OAAO,EAC3B,eAAe,EAAE,OAAO,EACxB,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;EA8BhE"}
@@ -0,0 +1,5 @@
1
+ import { Legislation } from "../../typings/types";
2
+ export declare function setWaitingForUser(legislation: Legislation): void;
3
+ export declare function isWaitingForUser(legislation: Legislation): boolean;
4
+ export declare function completeWaitingForUser(): void;
5
+ //# sourceMappingURL=cmp-user-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmp-user-state.d.ts","sourceRoot":"","sources":["../../../src/consent-validate/cmp-user-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASlD,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,WAAW,QAEzD;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,WAExD;AAED,wBAAgB,sBAAsB,SAErC"}
@@ -0,0 +1,4 @@
1
+ import { Legislation } from "../../typings/types";
2
+ export declare function isUserInitiatedUpdate(activeLegislation: Legislation): Promise<boolean>;
3
+ export declare function initConsentSyncValidation(): void;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/consent-validate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAU,MAAM,qBAAqB,CAAC;AAK1D,wBAAsB,qBAAqB,CAAC,iBAAiB,EAAE,WAAW,oBAgBzE;AAED,wBAAgB,yBAAyB,SAgBxC"}
@@ -1,3 +1,3 @@
1
- import { SPConfig } from "../../../typings/types";
2
- export declare function getRuntimeOptions(activeProperty: SPConfig): Promise<SPConfig>;
1
+ import { CMPInitOptions, SPConfig } from "../../../typings/types";
2
+ export declare function getRuntimeOptions(activeProperty: SPConfig): Promise<CMPInitOptions>;
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/configurators/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAWlE,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6B7E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/configurators/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAWlE,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,CA2BnF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/cmp-client",
3
- "version": "5.5.2",
3
+ "version": "5.6.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "files": [
@@ -15,6 +15,9 @@ declare global {
15
15
  };
16
16
  _sp_queue: (() => void)[];
17
17
  __tcfapi: (key: string, n: number, callback: (resp: TCData) => void) => void;
18
- __gpp: (key: string, callback: (resp: GPP.PingData) => void) => void;
18
+ __gpp: {
19
+ (command: "ping", callback: (resp: GPP.PingData) => void): void;
20
+ (command: "addEventListener", callback: (resp: { pingData: GPP.PingData }) => void): void;
21
+ };
19
22
  }
20
23
  }
@@ -6,13 +6,12 @@ export type SPLifecycleEvents = Partial<typeof events>;
6
6
 
7
7
  export type SPEventId = keyof SPLifecycleEvents;
8
8
 
9
- export type SPConfigClientOptions = {
9
+ export type SPConfigClientOptions = CMPInitOptions & {
10
10
  privacyManagerId?: number;
11
11
  usnatPrivacyManagerId?: number;
12
12
  ccpaPrivacyManagerId?: number;
13
13
  manageCookiesLinkOverride?: string;
14
14
  rootDomain?: string;
15
- includeUsNat?: boolean;
16
15
  };
17
16
 
18
17
  export interface SPConfig {