@thg-agentic/hyper-personalisation-web 3.25.0 → 3.26.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.
@@ -179,4 +179,4 @@ hr{width:100%;margin:4px 0;border:0;border-top:1px solid var(--ln)}
179
179
  @keyframes hp-down{from{transform:translateY(-100%)}}
180
180
  @keyframes hp-out{to{opacity:0;transform:translateY(12px) scale(.98)}}
181
181
  @media (prefers-reduced-motion:reduce){.s .w,.s .ov,.f>*{animation:hp-fade .15s ease both!important}.btn{transition:none}}
182
- `;var $t=/^#(?:[0-9a-f]{3}){1,2}$/i,He=["popup","fullscreen"],_t=["ok","verify","already"],zt=["stack","split","overlay","image-only"],Be={bar:["bottom","top"],sheet:["bottom-right","bottom-left","bottom"],teaser:["bottom-left","bottom-right","left","right"]},Tt=["xs","sm","md","lg","xl","display"],Ge={xs:4,sm:8,md:16,lg:28,xl:44},Ve={sm:380,md:480,lg:880},Ct=["left","center","right"],Xe={secondary:" b2",link:" no"},Lt=220,Mt=["verify","already","held","fallback","success"],Ot=[500,1500],It=600,Pt=1800,A={email:"Enter a valid email address.",phone:"Enter a valid mobile number.",intl:"Enter a valid mobile number, starting with + and its country code.",consent:"Tick the box to sign up.",failed:"Something went wrong. Please try again.",busy:"Too many tries. Please wait a moment and try again.",spin:"Sign up first to spin.",yours:"Your code",held:"You\u2019re already on the list",resent:"We\u2019ve sent your code to your inbox again.",inbox:"Your code is in the email we sent when you first signed up.",shop:"Continue shopping",closeOffer:"Close offer",code:"We\u2019ll email your code to you.",claimed:"This email address has already claimed its code.",copied:"Copied",thanks:"Thanks, you\u2019re signed up",retry:"You\u2019re signed up, but we couldn\u2019t load your prize. Please try again.",unclaimed:"We couldn\u2019t load your prize right now.",unavailable:"Not available right now.",won:"You won"},P=i=>i!==null&&typeof i=="object"&&!Array.isArray(i),F=(i,o,a)=>i.includes(o)?o:a,I=(i,o,a)=>Number.isFinite(i)?Math.min(Math.max(i,o),a):null,ge=i=>i.type==="date"||i.type==="number",xe=()=>globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches===!0;function Ze(i){let o=P(i.layout)?i.layout:{},a=P(o.media)?o.media:null,l=F(zt,o.template,"stack"),f=a?.side==="right"?"right":"left";return!a&&P(o.image)&&o.image.side!=="none"&&(a=o.image,o.image.side!=="top"&&(l="split",f=o.image.side==="right"?"right":"left")),(!a||!G(a.asset))&&(a=null,l="stack"),{template:l,media:a,side:f,scrim:I(o.scrim,0,.9)??.45,padding:F(["none","sm","md","lg"],o.padding,"md")}}var Je=(i,o)=>F(["sm","md","lg","full"],i.size,null)??(o.template==="split"||o.template==="overlay"?"lg":"md"),Qe=(i,o,a=1)=>{if(i==="fullscreen"||o==="full")return"100vw";let l=i==="teaser"?220:i==="sheet"?400:Ve[o]??Ve.md;return`(max-width: 639px) 100vw, ${Math.round(l*a)}px`},et=(i,o,a)=>{if(!a||!Array.isArray(i.widths)||!o.endsWith(".webp"))return null;let l=i.widths.filter(f=>Number.isInteger(f)&&f>0&&f<a).sort((f,x)=>f-x);return l.length===0?null:[...l.map(f=>`${o.slice(0,-5)}-${f}w.webp ${f}w`),`${o} ${a}w`].join(",")},tt=(i,o)=>i.format==="inline"?"inline":o.format&&o.format!=="inline"?o.format:i.format,ve=i=>i.kind==="video"||i.t==="video",we={webm:"video/webm",mp4:"video/mp4",m4v:"video/mp4",mov:"video/quicktime",ogv:"video/ogg"},ke=i=>we[i.split(/[?#]/)[0].split(".").pop().toLowerCase()],Nt=(i,o)=>[...new Set([o,...Array.isArray(i.sources)?i.sources.map(G):[]])].filter(Boolean).sort((a,l)=>(ke(l)===we.webm)-(ke(a)===we.webm));function Ae(i,o,a,l=new Set){let f=o.steps.find(k=>k.id===a);if(!f)return Promise.resolve();let x=tt(i,o),m=Ze(f),v=x==="teaser"&&f===o.steps[0],h=x==="teaser"&&!v?"popup":x,T=Je(o.theme,m),E=v?[]:f.blocks.filter(k=>P(k)&&(k.t==="image"||k.t==="video")).map(k=>[k,1]);return m.media&&!(v&&m.template!=="image-only")&&E.push([m.media,m.template==="split"?.46:1]),Promise.all(E.map(([k,Z])=>{let C=G(ve(k)?k.poster:k.asset);if(!C)return null;let L=document.createElement("img"),U=!ve(k)&&et(k,C,I(k.width,1,8192));U&&(L.sizes=Qe(h,T,Z),L.srcset=U);let y=`${L.sizes} ${U||C}`;return l.has(y)?null:(l.add(y),L.src=C,L.decode?.().catch(()=>{}))}))}var jt=0,ye=i=>`hp-${i}-${++jt}`;function u(i,o,a){let l=document.createElement(i);return o&&(l.className=o),a!==void 0&&l.append(We(a)),l}var nt=i=>{let o=i.length===4?[...i.slice(1)].map(a=>a+a).join(""):i.slice(1);return[0,2,4].map(a=>Number.parseInt(o.slice(a,a+2),16))},K=i=>{let[o,a,l]=nt(i).map(f=>{let x=f/255;return x<=.04045?x/12.92:((x+.055)/1.055)**2.4});return .2126*o+.7152*a+.0722*l},Ke=(i,o=4.5)=>{let a=K(i)+.05,l=1.05/a;return l>=o?"#fff":a/(K("#111")+.05)>l?"#111":"#fff"};function qt(i,o){let a=(E,k)=>k&&i.style.setProperty(E,k),l=E=>$t.test(E??"")?E:null;a("--hp-accent",l(o.accent)),a("--hp-bg",l(o.background)),a("--hp-text",l(o.text));let f=I(o.radius,0,48);f!==null&&a("--hp-radius",`${f}px`),a("--hp-font",o.font==="site"?i.ownerDocument.defaultView.getComputedStyle(i.parentElement??i.ownerDocument.body).fontFamily:Object.hasOwn(he,o.font)?he[o.font]:null),l(o.accent)&&(a("--hp-on-accent",Ke(o.accent,3)),a("--hp-on-accent-text",Ke(o.accent))),l(o.background)&&K(o.background)<.18&&(a("--hp-field","#fff"),a("--hp-field-text","#111"));let x=P(o.overlay)?o.overlay:{},m=[l(o.text),l(o.background)].filter(Boolean).sort((E,k)=>K(E)-K(k))[0],[v,h,T]=nt(l(x.colour)??m??"#0b0b0f");a("--hp-ov",`rgb(${v} ${h} ${T} / ${I(x.opacity,0,1)??.6})`)}function Dt(i){try{let o=new CSSStyleSheet;o.replaceSync(be),i.adoptedStyleSheets=[o]}catch{let o=document.createElement("style");o.textContent=be,i.append(o)}}function it(i){let{form:o,creative:a,decision:l,access:f,client:x,api:m,counters:v}=i,h=i.preview??null,T=e=>{let t=e.blocks.find(r=>r?.t==="email"||r?.t==="phone");return t?.t==="phone"||!t&&!o.consent_text?o.sms_consent_text:o.consent_text},E=tt(o,a),k=a.theme,Z=F(Be[E]??[],k.position,Be[E]?.[0]),C=document.createElement("hp-onsite");h&&C.setAttribute("preview",""),qt(C,k);let L=C.attachShadow({mode:"open"});Dt(L);let U=E!=="inline"&&!h,y=u(U?"dialog":E==="inline"?"section":"div"),Se=u("div","ov"),$=u("div","w"),W=u("div","m");h&&(W.dataset.hpMedia="");let Ee=()=>{let e=u("form","f");return e.noValidate=!0,e.addEventListener("submit",gt),e.addEventListener("input",()=>{M.textContent&&S.getAttribute("aria-busy")!=="true"&&N(null)}),e},S=Ee(),M=u("p","e");M.id=ye("err"),M.setAttribute("aria-live","assertive");let re=u("div","hd");re.setAttribute("aria-hidden","true"),$.append(re,W,S),y.append(Se,$);let Y=E!=="inline"&&u("button","x");Y&&(Y.type="button",Y.addEventListener("click",()=>j("close")),$.append(Y),Se.addEventListener("click",()=>j("close"))),L.append(y);let n={step:null,mode:E,size:"md",modal:!1,mobile:h?.device==="mobile",answers:{},sent:new Set,receipt:null,claim:i.coupon?{code:i.coupon}:h?{code:"WELCOME15"}:null,claiming:null,touched:!1,toWarm:new Set,warmed:i.warmed??new Set,warming:!1,owed:!1,unclaimed:!1,misses:0,submitted:!1,pow:null,wheel:null,timers:[],codes:[],videos:[],closed:!1},J=o.locale||document.documentElement.lang,ot=o.questions.some(ge)&&i.loadAnswers().catch(()=>null),$e=new WeakMap,_e=()=>{let e=P(k.button)?k.button:{};y.className=`s ${n.mode}${Z?` p-${Z}`:""} b-${F(["pill","rounded","square"],e.shape,"rounded")}${n.mobile?" mob":""}${h?" pv":""}${e.style==="outline"?" bo":""}${k.caps===!0?" uc":""}`},X=h?null:globalThis.matchMedia?.("(max-width: 639px)"),ze=()=>{n.mobile=X?.matches===!0,le(),_e()};X&&(n.mobile=X.matches===!0,X.addEventListener?.("change",ze));let Q=(e,t)=>{h||!l.decision_id||!f.analytics()||x.slotEngaged({decision_id:l.decision_id,slot:l.slot,arm:l.arm??null,engagement:e,step:t??n.step?.id??null})},N=(e,t)=>{M.className="e",M.textContent=e??"";for(let s of S.querySelectorAll("[aria-invalid]"))s.removeAttribute("aria-invalid");let r=t?.closest("label,fieldset");r&&S.contains(r)?r.after(M):S.append(M),t&&(t.setAttribute("aria-invalid","true"),t.setAttribute("aria-describedby",M.id),t.focus(),t.scrollIntoView?.({block:"nearest"}))},H=e=>{S.setAttribute("aria-busy",String(e));for(let t of S.querySelectorAll("button"))t.disabled=e},Te=()=>h?Promise.resolve(null):(n.pow??(n.pow=m.challenge().then(e=>e.status===200?Ue(e.body):null).catch(()=>null)),n.pow),se=()=>{for(let e of n.videos)try{document.hidden||xe()?e.pause():e.play()?.catch?.(()=>{})}catch{}};document.addEventListener("visibilitychange",se);function Ce(e,t,r,s){let c=G(e.asset);if(!c)return null;let p=typeof e.alt=="string"?e.alt:"",d;if(ve(e)){d=u("video",t),d.muted=d.defaultMuted=d.loop=d.playsInline=!0;let w=G(e.poster);w&&(d.poster=w),p?d.setAttribute("aria-label",p):d.setAttribute("aria-hidden","true"),d.autoplay=!xe()&&!h,d.preload=d.autoplay?"auto":w?"none":"metadata";let _=Nt(e,c);if(_.length>1)for(let z of _){let O=u("source");O.src=z;let q=ke(z);q&&(O.type=q),d.append(O)}else d.src=c;n.videos.push(d)}else{d=u("img",t),d.alt=p,d.decoding="async",d.loading=r?"eager":"lazy",r&&(d.fetchPriority="high");let w=et(e,c,I(e.width,1,8192));w&&(d.sizes=Qe(n.mode,n.size,s),d.srcset=w),d.src=c}let b=I(e.width,1,8192),g=I(e.height,1,8192);return b&&g&&(d.width=b,d.height=g),P(e.focal)&&(d.style.objectPosition=`${I(e.focal.x,0,100)??50}% ${I(e.focal.y,0,100)??50}%`),d}function Le(e,t){let r=u("label","l");r.append(u("span","lt",e.label??(t==="email"?"Email":"Mobile number")));let s=u("input","i");if(s.type=t,s.name=t==="email"?"email":"phone",s.autocomplete=s.inputMode=t,s.required=!0,typeof e.placeholder=="string"&&(s.placeholder=e.placeholder),s.setAttribute("aria-describedby",M.id),s.addEventListener("focus",Te,{once:!0}),t!=="tel")return r.append(s),r;s.id=`${M.id}-p`,r.htmlFor=s.id;let c=fe(u,"Country code","+",Object.entries(ue).map(([d,b])=>[d,`${d} +${b}`]),(e.country||/-(\w\w)$/.exec(J)?.[1]||"").toUpperCase());c.classList.add("cc"),c.name="hp_cc";let p=u("span","ph");return p.append(c,s),r.append(p),r}function rt(e){let t=o.questions.find(b=>b.key===e.question);if(!t||!ge(t)&&!Array.isArray(t.options))return null;let r=u("fieldset");r.dataset.question=t.key,r.append(u("legend","",t.label??""));let s=n.answers[t.key]??[];if(ge(t))return ot.then(b=>{if(!b)return r.append(u("p","sm",A.unavailable));b.answerFields(r,t,u,s[0],J),$e.set(r,()=>b.answerOf(r,t,void 0,J))}),r;let c=t.type==="many",p=F(["list","dropdown"],e.display,"buttons"),d=t.options.filter(b=>P(b)&&typeof b.value=="string");if(p==="dropdown"&&!c)return r.append(fe(u,t.label??t.key,"\u2014",d.map(b=>[b.value,b.label??b.value]),s[0])),r;p!=="buttons"&&(r.className="ls");for(let b of d){let g=u("input");g.value=b.value,g.checked=s.includes(b.value),g.type=c?"checkbox":"radio",g.name=`q_${t.key}`;let w=u("label",p==="buttons"?"ch":"c");w.append(g,u("span","",b.label??b.value)),r.append(w)}return r}function ee(){for(let e of n.codes){if(e.replaceChildren(),!n.claim){n.unclaimed&&e.append(u("p","",A.unclaimed));continue}if(!n.claim.code){let s=n.claim.held?A.claimed:n.claim.fallback===!0?A.code:n.claim.prize?.label;s&&e.append(u("p","",s));continue}n.claim.prize?.label&&e.append(u("p","",n.claim.prize.label));let t=u("output");t.textContent=n.claim.code;let r=u("button","btn cp");r.type="button",r.textContent="Copy code",r.addEventListener("click",()=>{navigator.clipboard?.writeText(n.claim.code).then(()=>{r.textContent=A.copied}).catch(()=>{})}),e.append(t,r)}}function st(e){if(n.claim&&!n.claim.code)return null;let t=u("p","tm");t.setAttribute("role","timer");let r=Date.now()+Math.max(0,Number(e.minutes)||0)*6e4,s=()=>{let p=Math.max(0,Math.round((r-Date.now())/1e3));t.textContent=`${String(Math.floor(p/60)).padStart(2,"0")}:${String(p%60).padStart(2,"0")}`,p===0&&clearInterval(c)},c=setInterval(s,1e3);return n.timers.push(c),s(),t}function ae(e,t){return e.href=t,e.rel="noopener",e.addEventListener("click",r=>{h?r.preventDefault():Q("click")}),e}function at(e){let t=e.label??"Continue";if(e.action==="link"){let s=B(e.href);return s?ae(u("a",`btn${Xe[e.variant]??""}`,t),s):null}let r=u("button",`btn${Xe[e.variant]??""}`,t);return r.type=e.action==="submit"?"submit":"button",r.type==="button"?r.addEventListener("click",()=>ie(e)):r.dataset.submit="",r}let Me=(e,t,r)=>(e.classList.add(`x-${F(Tt,t.size,r)}`),Ct.includes(t.align)&&e.classList.add(`a-${t.align}`),e);function Oe(e){let t=Ce(e,"bi",n.step===a.steps[0]);if(!t)return null;t.style.objectFit=e.fit==="contain"?"contain":"cover";let r=I(e.radius,0,48);r!==null&&(t.style.borderRadius=`${r}px`);let s=I(e.max_height,40,800);if(s!==null&&(t.style.maxHeight=`${s}px`),!t.width&&e.fit!=="contain"&&(t.style.aspectRatio="16 / 9"),e.t==="video"||!B(e.href))return t;let c=ae(u("a","bl"),B(e.href));return c.append(t),c}function lt(e){let t=I(e.threshold,.01,1e7);if(!t)return null;let r=u("div","pg"),s=u("p"),c=u("div","tr"),p=u("i");c.append(p),c.setAttribute("role","progressbar"),c.setAttribute("aria-valuemin","0"),c.setAttribute("aria-valuemax",String(t)),r.append(s,c);let d=g=>g.toFixed(2);try{let g=new Intl.NumberFormat(J||void 0,{style:"currency",currency:e.currency});d=w=>g.format(w)}catch{}let b=()=>{let g=Math.max(0,Number(i.basket?.())||0),w=t-g;s.textContent=w>0?String(e.text??"").replace("{amount}",d(w)):e.done??"",p.style.transform=`scaleX(${Math.min(1,g/t)})`,c.setAttribute("aria-valuenow",String(Math.min(g,t))),s.id||(s.id=ye("pg")),c.setAttribute("aria-labelledby",s.id)};return b(),n.timers.push(setInterval(b,2e3)),r}let Ie={heading(e){let t=Me(u("h2","",e.text),e,"xl");return t.id=ye("h"),t.tabIndex=-1,y.hasAttribute("aria-labelledby")||(y.setAttribute("aria-labelledby",t.id),n.step===a.steps[0]&&He.includes(n.mode)&&!h&&(t.autofocus=!0)),t},text:e=>Me(u("p","",e.text),e,"md"),email:e=>Le(e,"email"),phone:e=>Le(e,"tel"),consent(e){let t=T(n.step)?.text;if(typeof t!="string")return null;if(e.required!==!0)return u("p","sm",t);let r=u("label","c"),s=u("input");return s.type="checkbox",s.name="hp_consent",s.required=!0,s.setAttribute("aria-describedby",M.id),r.append(s,u("span","",t)),r},question:rt,wheel(){let e=u("div","wh");return i.loadWheel().then(t=>{n.closed||(n.wheel=t.mountWheel(e,o.prizes))}).catch(()=>{}),e},code(){let e=u("div","k");return e.setAttribute("aria-live","polite"),n.codes.push(e),e},button:at,decline(e){let t=u("button","btn no",e.label??"No thanks");return t.type="button",t.addEventListener("click",()=>j("decline")),t},countdown:st,progress:lt,image:Oe,video:Oe,spacer(e){let t=u("div","sp");return t.style.height=`${Ge[e.size]??Ge.md}px`,t.setAttribute("aria-hidden","true"),t},divider:()=>u("hr")};function ct(e,t){W.replaceChildren();let r=e.media,s=!r||t&&e.template!=="image-only";if(n.size=Je(k,e),$.className=`w t-${e.template} z-${n.size}${e.side==="right"?" right":""}${k.text_align==="center"?" ta-center":""}${s?" nm":""}`,$.style.setProperty("--sc",String(e.scrim)),S.className=`f pd-${e.padding}`,W.hidden=s,W.hidden)return;let c=Ce(r,"",n.step===a.steps[0],e.template==="split"?.46:1);if(!c)return;if(c.width?$.style.setProperty("--ar",`${c.width} / ${c.height}`):$.style.removeProperty("--ar"),e.template!=="image-only"){c.tagName==="IMG"&&e.template==="overlay"&&(c.alt=""),W.append(c);return}let p=B(r.href),d=p?ae(u("a","io"),p):u("button","io");p||(d.type="button",d.addEventListener("click",()=>ie({action:"next"}))),d.append(c),W.append(d)}function dt(e){let t=e.blocks.find(c=>c?.t==="heading"),r=e.blocks.find(c=>c?.t==="button"&&c.action==="next"),s=u("button","tb");return s.textContent=t?u("b","",t.text).textContent:r?.label??"Open",s.type="button",s.addEventListener("click",()=>ie(r??{action:"next"})),s}function D(e,t=new Set){let r=a.steps.find(z=>z.id===e);if(!r)return j("done");if(r.kind==="question"&&!h&&!f.analytics()&&!t.has(r.id))return D(V(r,n.answers),t.add(r.id));let s=n.step!==null,c=s&&(L.activeElement||document.activeElement===document.body),p=s&&!h?{mode:n.mode,w:$.offsetWidth,h:$.offsetHeight,top:$.offsetTop}:null;n.step=r,n.touched=!1;for(let z of n.timers.splice(0))clearInterval(z);n.codes=[],n.videos=[],n.wheel=null;let d=E==="teaser"&&r===a.steps[0];if(n.mode=E==="teaser"&&!d?"popup":E,E==="teaser"&&v.tab?.(o.slot,d),Y&&Y.setAttribute("aria-label",d?A.closeOffer:"Close"),_e(),y.removeAttribute("aria-labelledby"),p){let z=Ee();S.replaceWith(z),S=z}let b=Ze(r);ct(b,d);let g=p?.mode==="popup"&&n.mode==="popup";if(le(),p?.mode===n.mode&&p.h>0&&!g&&($.style.setProperty("--lw",`${p.w}px`),$.style.setProperty("--lh",`${p.h}px`),$.classList.add("lk")),S.replaceChildren(),d&&b.template!=="image-only")S.append(dt(r));else for(let[z,O]of r.blocks.entries()){let q=P(O)&&Object.hasOwn(Ie,O.t)?Ie[O.t](O):null;q&&(h&&(q.dataset.hpBlock=String(z)),S.append(q))}let w=S.querySelector("[data-submit]"),_=S.querySelector("[name=hp_consent]")?.parentNode;w&&_&&w.before(_),S.hidden=S.childElementCount===0,N(null),ee(),y.hasAttribute("aria-labelledby")?y.removeAttribute("aria-label"):y.setAttribute("aria-label",b.media?.alt?.trim?.()||"Sign up"),g&&p.h>0&&pt(p),s&&Pe(),se(),h||ut(r),c&&S.querySelector("h2")?.focus()}function le(){$.classList.remove("lk","an"),$.style.removeProperty("--tp")}function pt(e){let t=$.offsetHeight;$.classList.add("an");let r=$.offsetTop,s=Math.max(0,e.top-r);if(s+t>y.clientHeight-2*r)return le();$.style.setProperty("--tp",`${s}px`)}function ut(e){let t=e.next??{};for(let c of[t.default,...Object.values(P(t.answers)?t.answers:{}),...e.blocks.map(p=>p?.next),...Mt])typeof c=="string"&&n.toWarm.add(c);if(n.warming)return;n.warming=!0;let r=()=>{if(n.warming=!1,!n.closed&&C.isConnected)for(let c of n.toWarm)Ae(o,a,c,n.warmed);n.toWarm.clear()},s=()=>globalThis.requestIdleCallback?requestIdleCallback(r,{timeout:2e3}):setTimeout(r,200);document.readyState==="complete"?s():window.addEventListener("load",s,{once:!0})}function Pe(){if(!U)return;let e=He.includes(n.mode);if(!(y.open&&n.modal===e)){try{y.open&&y.close()}catch{}if(n.modal=e,y.setAttribute("aria-modal",String(e)),e&&typeof y.showModal=="function")y.showModal();else if(typeof y.show=="function"){let t=document.activeElement;y.show(),t&&t!==document.body?t.focus?.({preventScroll:!0}):C.blur()}else y.setAttribute("open","");!e||typeof y.showModal!="function"?y.setAttribute("role","dialog"):y.removeAttribute("role")}}function ft(){for(let e of S.querySelectorAll("fieldset[data-question]")){let t=e.dataset.question,r=$e.get(e)?.()??{};if(r.error)return r;let s=[r.value,...[...e.querySelectorAll("input:checked,select:not([name])")].map(c=>c.value)].filter(Boolean);s.length?n.answers[t]=s:delete n.answers[t]}}function mt(){let e=[];for(let[r,s]of Object.entries(n.answers)){let c=`${r}=${s.join(",")}`;n.sent.has(c)||(n.sent.add(c),e.push({question:r,values:s}))}let t=n.step.id;if(n.signedUp&&e.length)return void m.answers({anonymousId:f.anonymousId(),sessionId:f.sessionId()??void 0,slot:l.slot,arm:l.arm??void 0,decision_id:l.decision_id??void 0,step:t,...n.signedUp,answers:e,context:Ne()});if(f.analytics())for(let r of e)x.preferencesStated({...r,source:"onsite",slot:l.slot,arm:l.arm??null,decision_id:l.decision_id??null,step:t})}let Ne=()=>({page:{url:f.pageUrl()},locale:f.locale()??void 0,consent:f.consent()}),te=e=>{n.receipt&&!h&&mt(),D(V(n.step,n.answers,e))};async function ht(e){let t=n.step,r=S.querySelector("input[name=email],input[name=phone]");if(!r)return te(e.next);let s=r.name==="email"?"email":"sms",c=S.querySelector("select[name=hp_cc]")?.value,p=s==="email"?Ye(r.value.trim())?r.value.trim():null:Fe(r.value,c);if(!p)return N(s==="email"?A.email:c?A.phone:A.intl,r);let d=S.querySelector("input[name=hp_consent]");if(d&&!d.checked)return N(A.consent,d);N(null),H(!0);let b=await Te();n.pow=null;let g=Object.entries(n.answers).map(([R,de])=>({question:R,values:de})),w=s==="sms"?o.sms_consent_text:o.consent_text,_=await m.capture({anonymousId:f.anonymousId(),sessionId:f.sessionId()??void 0,slot:l.slot,arm:l.arm??void 0,decision_id:l.decision_id??void 0,step:t.id,channel:s,[s==="email"?"email":"phone"]:p,...s==="sms"&&n.signedUp,consent_text:w?{id:w.id,version:w.version}:void 0,...g.length?{answers:g}:{},...b?{altcha:b}:{},context:Ne()}),z=_.body?.status,O=(_.status===202||_.status===200)&&_t.includes(z);if(n.closed&&!O)return;O||H(!1);let q=_.status===400?_.body?.field:null;if(q==="email"||q==="phone")return N(A[q],r);if(!O)return N(_.status===429?A.busy:A.failed,r);r.value="";for(let[R,de]of Object.entries(n.answers))n.sent.add(`${R}=${de.join(",")}`);n.receipt=typeof _.body.receipt=="string"?_.body.receipt:null,s==="email"&&(n.signedUp={email:p,email_receipt:n.receipt}),n.submitted=!0,v.submitted(o.slot),Q("submit",t.id),n.owed=s==="email"&&o.prizes.length>0;let oe=n.owed?ce([]):null;oe||i.emit?.("submitted",{coupon:null});let yt=oe&&await Promise.race([oe,new Promise(R=>setTimeout(R,It))]);if(n.closed)return;if(H(!1),yt?.held)return D(ne("held"));let vt=z!=="ok"&&a.steps.some(R=>R.id===z);D(vt?z:V(t,n.answers,e.next));let wt=n.step;oe?.then(R=>{R?.held&&!n.closed&&n.step===wt&&!n.touched&&D(ne("held"))})}function ne(e){if(a.steps.some(s=>s.id===e))return e;let t={t:"button",label:A.shop,action:"close"},r=e==="unclaimed"?[{t:"heading",text:A.thanks},{t:"text",text:A.unclaimed},t]:e==="fallback"||n.claim?.code?[{t:"heading",text:e==="fallback"?A.thanks:A.yours},{t:"code"}]:[{t:"heading",text:A.held},{t:"text",text:o.code_relayed===!0?A.resent:A.inbox},t];return a.steps.push({id:e,blocks:r}),e}function je(e){n.owed&&(n.owed=!1,i.emit?.("submitted",{coupon:e?{code:e.code??null,prize:e.prize?.key}:null}))}function ce(e=Ot){let t=n.receipt;return n.claiming??(n.claiming=(async()=>{n.unclaimed=!1;let r;for(let d of[0,...e])if(d&&await new Promise(b=>setTimeout(b,d)),r=await m.claim({slot:l.slot,decision_id:l.decision_id??void 0,receipt:t}),r.status!==503)break;let s=r.body,c=s?.fallback===!0&&!s.code;if(r.status!==200||!(P(s?.prize)||c))return n.claiming=null,!e.length&&r.status===503?ce():(je(null),n.unclaimed=!0,n.closed||ee(),null);let p=s.held&&!s.code?v.code?.():null;return p&&(s={...s,code:p}),n.claim=s,typeof s.code=="string"&&v.code?.(s.code),je(s),n.closed||ee(),s})()),n.claiming}async function bt(e){if(!n.receipt)return N(A.spin);H(!0);let t=await ce();if(n.closed)return;if(!t)return H(!1),n.misses+=1,n.misses<2?N(A.retry):D(ne("unclaimed"));let r=t.fallback===!0&&!t.code,s=t.held?-1:o.prizes.findIndex(d=>d.key===t.prize?.key&&d.label===t.prize?.label);if(n.wheel&&s>=0&&!r){if(await n.wheel.spinTo(s),n.closed)return;M.className="e won",M.textContent=`${A.won} ${t.prize.label}`,await new Promise(d=>setTimeout(d,Pt))}if(n.closed)return;H(!1);let c=r?"fallback":s<0?"held":null,p=c?ne(c):V(n.step,n.answers,e.next);p?D(p):ee()}function ie(e){if(e.action==="close")return j("close");let t=ft();return h?te(e.next):t?N(t.error,t.input):e.action==="apply"?(i.emit?.("apply",{coupon:n.claim?.code?{code:n.claim.code}:null}),Q("click"),V(n.step,n.answers,e.next)?te(e.next):j("done")):e.action==="submit"?ht(e):e.action==="spin"?bt(e):te(e.next)}function gt(e){if(e.preventDefault(),S.getAttribute("aria-busy")==="true")return;let t=n.step.blocks.find(r=>r?.t==="button"&&r.action==="submit");ie(t??{action:"next"})}function qe(){n.closed=!0;for(let t of n.timers.splice(0))clearInterval(t);document.removeEventListener("visibilitychange",se),X?.removeEventListener?.("change",ze);let e=()=>{try{y.open&&y.close()}catch{}C.remove()};if(!U||xe())return e();y.classList.add("out"),setTimeout(e,Lt)}function j(e){n.closed||h||(!n.submitted&&e!=="done"&&Q("dismiss"),v.closed(o.slot),v.tab?.(o.slot,!1),qe(),i.onClose?.(e))}for(let e of["pointerdown","keydown","input"])y.addEventListener(e,()=>{n.touched=!0});y.addEventListener("cancel",e=>{e.preventDefault(),j("esc")}),y.addEventListener("keydown",e=>{e.key==="Escape"&&!n.modal&&E!=="inline"&&j("esc"),e.key==="Tab"&&n.modal&&xt(e)});function xt(e){let t=[...L.querySelectorAll("input[type=radio]:checked")],r=new Set,s=[...L.querySelectorAll("a[href],button,input,select,textarea")].filter(g=>{if(g.disabled||!g.getClientRects().length)return!1;if(g.type!=="radio")return!0;let w=t.find(_=>_.name===g.name);return(w?g!==w:r.has(g.name))?!1:(r.add(g.name),!0)});if(!s.length)return;let c=e.shiftKey,p=L.activeElement;p?.type==="radio"&&(p=s.find(g=>g.type==="radio"&&g.name===p.name)??p);let d=s.indexOf(p),b=null;if(d<0){let g=w=>p&&p.compareDocumentPosition(w)&4;b=c?s.findLast(w=>!g(w))??s.at(-1):s.find(g)??s[0]}else(c?d===0:d===s.length-1)&&(b=s.at(c?-1:0));b&&(e.preventDefault(),b.focus())}return re.addEventListener("pointerdown",e=>{if(!n.mobile||n.mode!=="sheet")return;let t=e.clientY,r=0,s=p=>{r=Math.max(0,p.clientY-t),$.style.transform=`translateY(${r}px)`},c=()=>{document.removeEventListener("pointermove",s),document.removeEventListener("pointerup",c),$.style.transform="",r>80&&j("close")};document.addEventListener("pointermove",s),document.addEventListener("pointerup",c)}),D(h?.step&&a.steps.some(e=>e.id===h.step)?h.step:a.steps[0].id),(i.container??document.body).append(C),Pe(),{close:j,root:L,host:C,show:D,step:()=>n.step?.id??null,modal:()=>!n.closed&&n.modal,destroy:()=>!n.closed&&qe()}}window[Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.render")]={mountForm:it,warm:Ae};})();
182
+ `;var _t=/^#(?:[0-9a-f]{3}){1,2}$/i,He=["popup","fullscreen"],$t=["ok","verify","already"],zt=["stack","split","overlay","image-only"],Be={bar:["bottom","top"],sheet:["bottom-right","bottom-left","bottom"],teaser:["bottom-left","bottom-right","left","right"]},Tt=["xs","sm","md","lg","xl","display"],Ge={xs:4,sm:8,md:16,lg:28,xl:44},Ve={sm:380,md:480,lg:880},Ct=["left","center","right"],Xe={secondary:" b2",link:" no"},Lt=220,Mt=["verify","already","held","fallback","success"],Ot=[500,1500],It=600,Pt=1800,A={email:"Enter a valid email address.",phone:"Enter a valid mobile number.",intl:"Enter a valid mobile number, starting with + and its country code.",consent:"Tick the box to sign up.",failed:"Something went wrong. Please try again.",busy:"Too many tries. Please wait a moment and try again.",spin:"Sign up first to spin.",yours:"Your code",held:"You\u2019re already on the list",resent:"We\u2019ve sent your code to your inbox again.",inbox:"Your code is in the email we sent when you first signed up.",shop:"Continue shopping",closeOffer:"Close offer",code:"We\u2019ll email your code to you.",claimed:"This email address has already claimed its code.",copied:"Copied",thanks:"Thanks, you\u2019re signed up",retry:"You\u2019re signed up, but we couldn\u2019t load your prize. Please try again.",unclaimed:"We couldn\u2019t load your prize right now.",unavailable:"Not available right now.",won:"You won"},P=i=>i!==null&&typeof i=="object"&&!Array.isArray(i),F=(i,o,a)=>i.includes(o)?o:a,I=(i,o,a)=>Number.isFinite(i)?Math.min(Math.max(i,o),a):null,ge=i=>i.type==="date"||i.type==="number",xe=()=>globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches===!0;function Ze(i){let o=P(i.layout)?i.layout:{},a=P(o.media)?o.media:null,l=F(zt,o.template,"stack"),f=a?.side==="right"?"right":"left";return!a&&P(o.image)&&o.image.side!=="none"&&(a=o.image,o.image.side!=="top"&&(l="split",f=o.image.side==="right"?"right":"left")),(!a||!G(a.asset))&&(a=null,l="stack"),{template:l,media:a,side:f,scrim:I(o.scrim,0,.9)??.45,padding:F(["none","sm","md","lg"],o.padding,"md")}}var Je=(i,o)=>F(["sm","md","lg","full"],i.size,null)??(o.template==="split"||o.template==="overlay"?"lg":"md"),Qe=(i,o,a=1)=>{if(i==="fullscreen"||o==="full")return"100vw";let l=i==="teaser"?220:i==="sheet"?400:Ve[o]??Ve.md;return`(max-width: 639px) 100vw, ${Math.round(l*a)}px`},et=(i,o,a)=>{if(!a||!Array.isArray(i.widths)||!o.endsWith(".webp"))return null;let l=i.widths.filter(f=>Number.isInteger(f)&&f>0&&f<a).sort((f,x)=>f-x);return l.length===0?null:[...l.map(f=>`${o.slice(0,-5)}-${f}w.webp ${f}w`),`${o} ${a}w`].join(",")},tt=(i,o)=>i.format==="inline"?"inline":o.format&&o.format!=="inline"?o.format:i.format,ve=i=>i.kind==="video"||i.t==="video",we={webm:"video/webm",mp4:"video/mp4",m4v:"video/mp4",mov:"video/quicktime",ogv:"video/ogg"},ke=i=>we[i.split(/[?#]/)[0].split(".").pop().toLowerCase()],Nt=(i,o)=>[...new Set([o,...Array.isArray(i.sources)?i.sources.map(G):[]])].filter(Boolean).sort((a,l)=>(ke(l)===we.webm)-(ke(a)===we.webm));function Ae(i,o,a,l=new Set){let f=o.steps.find(k=>k.id===a);if(!f)return Promise.resolve();let x=tt(i,o),m=Ze(f),v=x==="teaser"&&f===o.steps[0],h=x==="teaser"&&!v?"popup":x,T=Je(o.theme,m),E=v?[]:f.blocks.filter(k=>P(k)&&(k.t==="image"||k.t==="video")).map(k=>[k,1]);return m.media&&!(v&&m.template!=="image-only")&&E.push([m.media,m.template==="split"?.46:1]),Promise.all(E.map(([k,Z])=>{let C=G(ve(k)?k.poster:k.asset);if(!C)return null;let L=document.createElement("img"),U=!ve(k)&&et(k,C,I(k.width,1,8192));U&&(L.sizes=Qe(h,T,Z),L.srcset=U);let y=`${L.sizes} ${U||C}`;return l.has(y)?null:(l.add(y),L.src=C,L.decode?.().catch(()=>{}))}))}var jt=0,ye=i=>`hp-${i}-${++jt}`;function u(i,o,a){let l=document.createElement(i);return o&&(l.className=o),a!==void 0&&l.append(We(a)),l}var nt=i=>{let o=i.length===4?[...i.slice(1)].map(a=>a+a).join(""):i.slice(1);return[0,2,4].map(a=>Number.parseInt(o.slice(a,a+2),16))},K=i=>{let[o,a,l]=nt(i).map(f=>{let x=f/255;return x<=.04045?x/12.92:((x+.055)/1.055)**2.4});return .2126*o+.7152*a+.0722*l},Ke=(i,o=4.5)=>{let a=K(i)+.05,l=1.05/a;return l>=o?"#fff":a/(K("#111")+.05)>l?"#111":"#fff"};function qt(i,o){let a=(E,k)=>k&&i.style.setProperty(E,k),l=E=>_t.test(E??"")?E:null;a("--hp-accent",l(o.accent)),a("--hp-bg",l(o.background)),a("--hp-text",l(o.text));let f=I(o.radius,0,48);f!==null&&a("--hp-radius",`${f}px`),a("--hp-font",o.font==="site"?i.ownerDocument.defaultView.getComputedStyle(i.parentElement??i.ownerDocument.body).fontFamily:Object.hasOwn(he,o.font)?he[o.font]:null),l(o.accent)&&(a("--hp-on-accent",Ke(o.accent,3)),a("--hp-on-accent-text",Ke(o.accent))),l(o.background)&&K(o.background)<.18&&(a("--hp-field","#fff"),a("--hp-field-text","#111"));let x=P(o.overlay)?o.overlay:{},m=[l(o.text),l(o.background)].filter(Boolean).sort((E,k)=>K(E)-K(k))[0],[v,h,T]=nt(l(x.colour)??m??"#0b0b0f");a("--hp-ov",`rgb(${v} ${h} ${T} / ${I(x.opacity,0,1)??.6})`)}function Dt(i){try{let o=new CSSStyleSheet;o.replaceSync(be),i.adoptedStyleSheets=[o]}catch{let o=document.createElement("style");o.textContent=be,i.append(o)}}function it(i){let{form:o,creative:a,decision:l,access:f,client:x,api:m,counters:v}=i,h=i.preview??null,T=e=>{let t=e.blocks.find(r=>r?.t==="email"||r?.t==="phone");return t?.t==="phone"||!t&&!o.consent_text?o.sms_consent_text:o.consent_text},E=tt(o,a),k=a.theme,Z=F(Be[E]??[],k.position,Be[E]?.[0]),C=document.createElement("hp-onsite");h&&C.setAttribute("preview",""),qt(C,k);let L=C.attachShadow({mode:"open"});Dt(L);let U=E!=="inline"&&!h,y=u(U?"dialog":E==="inline"?"section":"div"),Se=u("div","ov"),_=u("div","w"),W=u("div","m");h&&(W.dataset.hpMedia="");let Ee=()=>{let e=u("form","f");return e.noValidate=!0,e.addEventListener("submit",gt),e.addEventListener("input",()=>{M.textContent&&S.getAttribute("aria-busy")!=="true"&&N(null)}),e},S=Ee(),M=u("p","e");M.id=ye("err"),M.setAttribute("aria-live","assertive");let re=u("div","hd");re.setAttribute("aria-hidden","true"),_.append(re,W,S),y.append(Se,_);let Y=E!=="inline"&&u("button","x");Y&&(Y.type="button",Y.addEventListener("click",()=>j("close")),_.append(Y),Se.addEventListener("click",()=>j("close"))),L.append(y);let n={step:null,mode:E,size:"md",modal:!1,mobile:h?.device==="mobile",answers:{},sent:new Set,receipt:null,claim:i.coupon?{code:i.coupon}:h?{code:"WELCOME15"}:null,claiming:null,touched:!1,toWarm:new Set,warmed:i.warmed??new Set,warming:!1,owed:!1,unclaimed:!1,misses:0,submitted:!1,pow:null,wheel:null,timers:[],codes:[],videos:[],closed:!1},J=o.locale||document.documentElement.lang,ot=o.questions.some(ge)&&i.loadAnswers().catch(()=>null),_e=new WeakMap,$e=()=>{let e=P(k.button)?k.button:{};y.className=`s ${n.mode}${Z?` p-${Z}`:""} b-${F(["pill","rounded","square"],e.shape,"rounded")}${n.mobile?" mob":""}${h?" pv":""}${e.style==="outline"?" bo":""}${k.caps===!0?" uc":""}`},X=h?null:globalThis.matchMedia?.("(max-width: 639px)"),ze=()=>{n.mobile=X?.matches===!0,le(),$e()};X&&(n.mobile=X.matches===!0,X.addEventListener?.("change",ze));let Q=(e,t)=>{h||!l.decision_id||!f.analytics()||x.slotEngaged({decision_id:l.decision_id,slot:l.slot,arm:l.arm??null,engagement:e,step:t??n.step?.id??null})},N=(e,t)=>{M.className="e",M.textContent=e??"";for(let s of S.querySelectorAll("[aria-invalid]"))s.removeAttribute("aria-invalid");let r=t?.closest("label,fieldset");r&&S.contains(r)?r.after(M):S.append(M),t&&(t.setAttribute("aria-invalid","true"),t.setAttribute("aria-describedby",M.id),t.focus(),t.scrollIntoView?.({block:"nearest"}))},H=e=>{S.setAttribute("aria-busy",String(e));for(let t of S.querySelectorAll("button"))t.disabled=e},Te=()=>h?Promise.resolve(null):(n.pow??(n.pow=m.challenge().then(e=>e.status===200?Ue(e.body):null).catch(()=>null)),n.pow),se=()=>{for(let e of n.videos)try{document.hidden||xe()?e.pause():e.play()?.catch?.(()=>{})}catch{}};document.addEventListener("visibilitychange",se);function Ce(e,t,r,s){let c=G(e.asset);if(!c)return null;let p=typeof e.alt=="string"?e.alt:"",d;if(ve(e)){d=u("video",t),d.muted=d.defaultMuted=d.loop=d.playsInline=!0;let w=G(e.poster);w&&(d.poster=w),p?d.setAttribute("aria-label",p):d.setAttribute("aria-hidden","true"),d.autoplay=!xe()&&!h,d.preload=d.autoplay?"auto":w?"none":"metadata";let $=Nt(e,c);if($.length>1)for(let z of $){let O=u("source");O.src=z;let q=ke(z);q&&(O.type=q),d.append(O)}else d.src=c;n.videos.push(d)}else{d=u("img",t),d.alt=p,d.decoding="async",d.loading=r?"eager":"lazy",r&&(d.fetchPriority="high");let w=et(e,c,I(e.width,1,8192));w&&(d.sizes=Qe(n.mode,n.size,s),d.srcset=w),d.src=c}let b=I(e.width,1,8192),g=I(e.height,1,8192);return b&&g&&(d.width=b,d.height=g),P(e.focal)&&(d.style.objectPosition=`${I(e.focal.x,0,100)??50}% ${I(e.focal.y,0,100)??50}%`),d}function Le(e,t){let r=u("label","l");r.append(u("span","lt",e.label??(t==="email"?"Email":"Mobile number")));let s=u("input","i");if(s.type=t,s.name=t==="email"?"email":"phone",s.autocomplete=s.inputMode=t,s.required=!0,typeof e.placeholder=="string"&&(s.placeholder=e.placeholder),s.setAttribute("aria-describedby",M.id),s.addEventListener("focus",Te,{once:!0}),t!=="tel")return r.append(s),r;s.id=`${M.id}-p`,r.htmlFor=s.id;let c=fe(u,"Country code","+",Object.entries(ue).map(([d,b])=>[d,`${d} +${b}`]),(e.country||/-(\w\w)$/.exec(J)?.[1]||"").toUpperCase());c.classList.add("cc"),c.name="hp_cc";let p=u("span","ph");return p.append(c,s),r.append(p),r}function rt(e){let t=o.questions.find(b=>b.key===e.question);if(!t||!ge(t)&&!Array.isArray(t.options))return null;let r=u("fieldset");r.dataset.question=t.key,r.append(u("legend","",t.label??""));let s=n.answers[t.key]??[];if(ge(t))return ot.then(b=>{if(!b)return r.append(u("p","sm",A.unavailable));b.answerFields(r,t,u,s[0],J),_e.set(r,()=>b.answerOf(r,t,void 0,J))}),r;let c=t.type==="many",p=F(["list","dropdown"],e.display,"buttons"),d=t.options.filter(b=>P(b)&&typeof b.value=="string");if(p==="dropdown"&&!c)return r.append(fe(u,t.label??t.key,"\u2014",d.map(b=>[b.value,b.label??b.value]),s[0])),r;p!=="buttons"&&(r.className="ls");for(let b of d){let g=u("input");g.value=b.value,g.checked=s.includes(b.value),g.type=c?"checkbox":"radio",g.name=`q_${t.key}`;let w=u("label",p==="buttons"?"ch":"c");w.append(g,u("span","",b.label??b.value)),r.append(w)}return r}function ee(){for(let e of n.codes){if(e.replaceChildren(),!n.claim){n.unclaimed&&e.append(u("p","",A.unclaimed));continue}if(!n.claim.code){let s=n.claim.held?A.claimed:n.claim.fallback===!0?A.code:n.claim.prize?.label;s&&e.append(u("p","",s));continue}n.claim.prize?.label&&e.append(u("p","",n.claim.prize.label));let t=u("output");t.textContent=n.claim.code;let r=u("button","btn cp");r.type="button",r.textContent="Copy code",r.addEventListener("click",()=>{navigator.clipboard?.writeText(n.claim.code).then(()=>{r.textContent=A.copied}).catch(()=>{})}),e.append(t,r)}}function st(e){if(n.claim&&!n.claim.code)return null;let t=u("p","tm");t.setAttribute("role","timer");let r=Date.now()+Math.max(0,Number(e.minutes)||0)*6e4,s=()=>{let p=Math.max(0,Math.round((r-Date.now())/1e3));t.textContent=`${String(Math.floor(p/60)).padStart(2,"0")}:${String(p%60).padStart(2,"0")}`,p===0&&clearInterval(c)},c=setInterval(s,1e3);return n.timers.push(c),s(),t}function ae(e,t){return e.href=t,e.rel="noopener",e.addEventListener("click",r=>{h?r.preventDefault():Q("click")}),e}function at(e){let t=e.label??"Continue";if(e.action==="link"){let s=B(e.href);return s?ae(u("a",`btn${Xe[e.variant]??""}`,t),s):null}let r=u("button",`btn${Xe[e.variant]??""}`,t);return r.type=e.action==="submit"?"submit":"button",r.type==="button"?r.addEventListener("click",()=>ie(e)):r.dataset.submit="",r}let Me=(e,t,r)=>(e.classList.add(`x-${F(Tt,t.size,r)}`),Ct.includes(t.align)&&e.classList.add(`a-${t.align}`),e);function Oe(e){let t=Ce(e,"bi",n.step===a.steps[0]);if(!t)return null;t.style.objectFit=e.fit==="contain"?"contain":"cover";let r=I(e.radius,0,48);r!==null&&(t.style.borderRadius=`${r}px`);let s=I(e.max_height,40,800);if(s!==null&&(t.style.maxHeight=`${s}px`),!t.width&&e.fit!=="contain"&&(t.style.aspectRatio="16 / 9"),e.t==="video"||!B(e.href))return t;let c=ae(u("a","bl"),B(e.href));return c.append(t),c}function lt(e){let t=I(e.threshold,.01,1e7);if(!t)return null;let r=u("div","pg"),s=u("p"),c=u("div","tr"),p=u("i");c.append(p),c.setAttribute("role","progressbar"),c.setAttribute("aria-valuemin","0"),c.setAttribute("aria-valuemax",String(t)),r.append(s,c);let d=g=>g.toFixed(2);try{let g=new Intl.NumberFormat(J||void 0,{style:"currency",currency:e.currency});d=w=>g.format(w)}catch{}let b=()=>{let g=Math.max(0,Number(i.basket?.())||0),w=t-g;s.textContent=w>0?String(e.text??"").replace("{amount}",d(w)):e.done??"",p.style.transform=`scaleX(${Math.min(1,g/t)})`,c.setAttribute("aria-valuenow",String(Math.min(g,t))),s.id||(s.id=ye("pg")),c.setAttribute("aria-labelledby",s.id)};return b(),n.timers.push(setInterval(b,2e3)),r}let Ie={heading(e){let t=Me(u("h2","",e.text),e,"xl");return t.id=ye("h"),t.tabIndex=-1,y.hasAttribute("aria-labelledby")||(y.setAttribute("aria-labelledby",t.id),n.step===a.steps[0]&&He.includes(n.mode)&&!h&&(t.autofocus=!0)),t},text:e=>Me(u("p","",e.text),e,"md"),email:e=>Le(e,"email"),phone:e=>Le(e,"tel"),consent(e){let t=T(n.step)?.text;if(typeof t!="string")return null;if(e.required!==!0)return u("p","sm",t);let r=u("label","c"),s=u("input");return s.type="checkbox",s.name="hp_consent",s.required=!0,s.setAttribute("aria-describedby",M.id),r.append(s,u("span","",t)),r},question:rt,wheel(){let e=u("div","wh");return i.loadWheel().then(t=>{n.closed||(n.wheel=t.mountWheel(e,o.prizes))}).catch(()=>{}),e},code(){let e=u("div","k");return e.setAttribute("aria-live","polite"),n.codes.push(e),e},button:at,decline(e){let t=u("button","btn no",e.label??"No thanks");return t.type="button",t.addEventListener("click",()=>j("decline")),t},countdown:st,progress:lt,image:Oe,video:Oe,spacer(e){let t=u("div","sp");return t.style.height=`${Ge[e.size]??Ge.md}px`,t.setAttribute("aria-hidden","true"),t},divider:()=>u("hr")};function ct(e,t){W.replaceChildren();let r=e.media,s=!r||t&&e.template!=="image-only";if(n.size=Je(k,e),_.className=`w t-${e.template} z-${n.size}${e.side==="right"?" right":""}${k.text_align==="center"?" ta-center":""}${s?" nm":""}`,_.style.setProperty("--sc",String(e.scrim)),S.className=`f pd-${e.padding}`,W.hidden=s,W.hidden)return;let c=Ce(r,"",n.step===a.steps[0],e.template==="split"?.46:1);if(!c)return;if(c.width?_.style.setProperty("--ar",`${c.width} / ${c.height}`):_.style.removeProperty("--ar"),e.template!=="image-only"){c.tagName==="IMG"&&e.template==="overlay"&&(c.alt=""),W.append(c);return}let p=B(r.href),d=p?ae(u("a","io"),p):u("button","io");p||(d.type="button",d.addEventListener("click",()=>ie({action:"next"}))),d.append(c),W.append(d)}function dt(e){let t=e.blocks.find(c=>c?.t==="heading"),r=e.blocks.find(c=>c?.t==="button"&&c.action==="next"),s=u("button","tb");return s.textContent=t?u("b","",t.text).textContent:r?.label??"Open",s.type="button",s.addEventListener("click",()=>ie(r??{action:"next"})),s}function D(e,t=new Set){let r=a.steps.find(z=>z.id===e);if(!r)return j("done");if(r.kind==="question"&&!h&&!f.analytics()&&!t.has(r.id))return D(V(r,n.answers),t.add(r.id));let s=n.step!==null,c=s&&(L.activeElement||document.activeElement===document.body),p=s&&!h?{mode:n.mode,w:_.offsetWidth,h:_.offsetHeight,top:_.offsetTop}:null;n.step=r,n.touched=!1;for(let z of n.timers.splice(0))clearInterval(z);n.codes=[],n.videos=[],n.wheel=null;let d=E==="teaser"&&r===a.steps[0];if(n.mode=E==="teaser"&&!d?"popup":E,E==="teaser"&&v.tab?.(o.slot,d),Y&&Y.setAttribute("aria-label",d?A.closeOffer:"Close"),$e(),y.removeAttribute("aria-labelledby"),p){let z=Ee();S.replaceWith(z),S=z}let b=Ze(r);ct(b,d);let g=p?.mode==="popup"&&n.mode==="popup";if(le(),p?.mode===n.mode&&p.h>0&&!g&&(_.style.setProperty("--lw",`${p.w}px`),_.style.setProperty("--lh",`${p.h}px`),_.classList.add("lk")),S.replaceChildren(),d&&b.template!=="image-only")S.append(dt(r));else for(let[z,O]of r.blocks.entries()){let q=P(O)&&Object.hasOwn(Ie,O.t)?Ie[O.t](O):null;q&&(h&&(q.dataset.hpBlock=String(z)),S.append(q))}let w=S.querySelector("[data-submit]"),$=S.querySelector("[name=hp_consent]")?.parentNode;w&&$&&w.before($),S.hidden=S.childElementCount===0,N(null),ee(),y.hasAttribute("aria-labelledby")?y.removeAttribute("aria-label"):y.setAttribute("aria-label",b.media?.alt?.trim?.()||"Sign up"),g&&p.h>0&&pt(p),s&&Pe(),se(),h||ut(r),c&&S.querySelector("h2")?.focus()}function le(){_.classList.remove("lk","an"),_.style.removeProperty("--tp")}function pt(e){let t=_.offsetHeight;_.classList.add("an");let r=_.offsetTop,s=Math.max(0,e.top-r);if(s+t>y.clientHeight-2*r)return le();_.style.setProperty("--tp",`${s}px`)}function ut(e){let t=e.next??{};for(let c of[t.default,...Object.values(P(t.answers)?t.answers:{}),...e.blocks.map(p=>p?.next),...Mt])typeof c=="string"&&n.toWarm.add(c);if(n.warming)return;n.warming=!0;let r=()=>{if(n.warming=!1,!n.closed&&C.isConnected)for(let c of n.toWarm)Ae(o,a,c,n.warmed);n.toWarm.clear()},s=()=>globalThis.requestIdleCallback?requestIdleCallback(r,{timeout:2e3}):setTimeout(r,200);document.readyState==="complete"?s():window.addEventListener("load",s,{once:!0})}function Pe(){if(!U)return;let e=He.includes(n.mode);if(!(y.open&&n.modal===e)){try{y.open&&y.close()}catch{}if(n.modal=e,y.setAttribute("aria-modal",String(e)),e&&typeof y.showModal=="function")y.showModal();else if(typeof y.show=="function"){let t=document.activeElement;y.show(),t&&t!==document.body?t.focus?.({preventScroll:!0}):C.blur()}else y.setAttribute("open","");!e||typeof y.showModal!="function"?y.setAttribute("role","dialog"):y.removeAttribute("role")}}function ft(){for(let e of S.querySelectorAll("fieldset[data-question]")){let t=e.dataset.question,r=_e.get(e)?.()??{};if(r.error)return r;let s=[r.value,...[...e.querySelectorAll("input:checked,select:not([name])")].map(c=>c.value)].filter(Boolean);s.length?n.answers[t]=s:delete n.answers[t]}}function mt(){let e=[];for(let[r,s]of Object.entries(n.answers)){let c=`${r}=${s.join(",")}`;n.sent.has(c)||(n.sent.add(c),e.push({question:r,values:s}))}let t=n.step.id;if(n.signedUp&&e.length)return void m.answers({anonymousId:f.anonymousId(),sessionId:f.sessionId()??void 0,slot:l.slot,arm:l.arm??void 0,decision_id:l.decision_id??void 0,step:t,...n.signedUp,answers:e,context:Ne()});if(f.analytics())for(let r of e)x.preferencesStated({...r,source:"onsite",slot:l.slot,arm:l.arm??null,decision_id:l.decision_id??null,step:t})}let Ne=()=>({page:{url:f.pageUrl()},locale:f.locale()??void 0,consent:f.consent()}),te=e=>{n.receipt&&!h&&mt(),D(V(n.step,n.answers,e))};async function ht(e){let t=n.step,r=S.querySelector("input[name=email],input[name=phone]");if(!r)return te(e.next);let s=r.name==="email"?"email":"sms",c=S.querySelector("select[name=hp_cc]")?.value,p=s==="email"?Ye(r.value.trim())?r.value.trim():null:Fe(r.value,c);if(!p)return N(s==="email"?A.email:c?A.phone:A.intl,r);let d=S.querySelector("input[name=hp_consent]");if(d&&!d.checked)return N(A.consent,d);N(null),H(!0);let b=await Te();n.pow=null;let g=Object.entries(n.answers).map(([R,de])=>({question:R,values:de})),w=s==="sms"?o.sms_consent_text:o.consent_text,$=await m.capture({anonymousId:f.anonymousId(),sessionId:f.sessionId()??void 0,slot:l.slot,arm:l.arm??void 0,decision_id:l.decision_id??void 0,step:t.id,channel:s,[s==="email"?"email":"phone"]:p,...s==="sms"&&n.signedUp,consent_text:w?{id:w.id,version:w.version}:void 0,...g.length?{answers:g}:{},...b?{altcha:b}:{},context:Ne()}),z=$.body?.status,O=($.status===202||$.status===200)&&$t.includes(z);if(n.closed&&!O)return;O||H(!1);let q=$.status===400?$.body?.field:null;if(q==="email"||q==="phone")return N(A[q],r);if(!O)return N($.status===429?A.busy:A.failed,r);r.value="";for(let[R,de]of Object.entries(n.answers))n.sent.add(`${R}=${de.join(",")}`);n.receipt=typeof $.body.receipt=="string"?$.body.receipt:null,s==="email"&&(n.signedUp={email:p,email_receipt:n.receipt}),n.submitted=!0,v.submitted(o.slot),Q("submit",t.id),n.owed=s==="email"&&o.prizes.length>0;let oe=n.owed?ce([]):null;oe||i.emit?.("submitted",{coupon:null});let yt=oe&&await Promise.race([oe,new Promise(R=>setTimeout(R,It))]);if(n.closed)return;if(H(!1),yt?.held)return D(ne("held"));let vt=z!=="ok"&&a.steps.some(R=>R.id===z);D(vt?z:V(t,n.answers,e.next));let wt=n.step;oe?.then(R=>{R?.held&&!n.closed&&n.step===wt&&!n.touched&&D(ne("held"))})}function ne(e){if(a.steps.some(s=>s.id===e))return e;let t={t:"button",label:A.shop,action:"close"},r=e==="unclaimed"?[{t:"heading",text:A.thanks},{t:"text",text:A.unclaimed},t]:e==="fallback"||n.claim?.code?[{t:"heading",text:e==="fallback"?A.thanks:A.yours},{t:"code"}]:[{t:"heading",text:A.held},{t:"text",text:o.code_relayed===!0?A.resent:A.inbox},t];return a.steps.push({id:e,blocks:r}),e}function je(e){n.owed&&(n.owed=!1,i.emit?.("submitted",{coupon:e?{code:e.code??null,prize:e.prize?.key}:null}))}function ce(e=Ot){let t=n.receipt;return n.claiming??(n.claiming=(async()=>{n.unclaimed=!1;let r;for(let d of[0,...e])if(d&&await new Promise(b=>setTimeout(b,d)),r=await m.claim({slot:l.slot,decision_id:l.decision_id??void 0,receipt:t}),r.status!==503)break;let s=r.body,c=s?.fallback===!0&&!s.code;if(r.status!==200||!(P(s?.prize)||c))return n.claiming=null,!e.length&&r.status===503?ce():(je(null),n.unclaimed=!0,n.closed||ee(),null);let p=s.held&&!s.code?v.code?.():null;return p&&(s={...s,code:p}),n.claim=s,typeof s.code=="string"&&v.code?.(s.code),je(s),n.closed||ee(),s})()),n.claiming}async function bt(e){if(!n.receipt)return N(A.spin);H(!0);let t=await ce();if(n.closed)return;if(!t)return H(!1),n.misses+=1,n.misses<2?N(A.retry):D(ne("unclaimed"));let r=t.fallback===!0&&!t.code,s=t.held?-1:o.prizes.findIndex(d=>d.key===t.prize?.key&&d.label===t.prize?.label);if(n.wheel&&s>=0&&!r){if(await n.wheel.spinTo(s),n.closed)return;M.className="e won",M.textContent=`${A.won} ${t.prize.label}`,await new Promise(d=>setTimeout(d,Pt))}if(n.closed)return;H(!1);let c=r?"fallback":s<0?"held":null,p=c?ne(c):V(n.step,n.answers,e.next);p?D(p):ee()}function ie(e){if(e.action==="close")return j("close");let t=ft();return h?te(e.next):t?N(t.error,t.input):e.action==="apply"?(i.emit?.("apply",{coupon:n.claim?.code?{code:n.claim.code}:null}),Q("click"),V(n.step,n.answers,e.next)?te(e.next):j("done")):e.action==="submit"?ht(e):e.action==="spin"?bt(e):te(e.next)}function gt(e){if(e.preventDefault(),S.getAttribute("aria-busy")==="true")return;let t=n.step.blocks.find(r=>r?.t==="button"&&r.action==="submit");ie(t??{action:"next"})}function qe(){n.closed=!0;for(let t of n.timers.splice(0))clearInterval(t);document.removeEventListener("visibilitychange",se),X?.removeEventListener?.("change",ze);let e=()=>{try{y.open&&y.close()}catch{}C.remove()};if(!U||xe())return e();y.classList.add("out"),setTimeout(e,Lt)}function j(e){n.closed||h||(!n.submitted&&e!=="done"&&Q("dismiss"),v.closed(o.slot),v.tab?.(o.slot,!1),qe(),i.onClose?.(e))}for(let e of["pointerdown","keydown","input"])y.addEventListener(e,()=>{n.touched=!0});y.addEventListener("cancel",e=>{e.preventDefault(),j("esc")}),y.addEventListener("keydown",e=>{e.key==="Escape"&&!n.modal&&E!=="inline"&&j("esc"),e.key==="Tab"&&n.modal&&xt(e)});function xt(e){let t=[...L.querySelectorAll("input[type=radio]:checked")],r=new Set,s=[...L.querySelectorAll("a[href],button,input,select,textarea")].filter(g=>{if(g.disabled||!g.getClientRects().length)return!1;if(g.type!=="radio")return!0;let w=t.find($=>$.name===g.name);return(w?g!==w:r.has(g.name))?!1:(r.add(g.name),!0)});if(!s.length)return;let c=e.shiftKey,p=L.activeElement;p?.type==="radio"&&(p=s.find(g=>g.type==="radio"&&g.name===p.name)??p);let d=s.indexOf(p),b=null;if(d<0){let g=w=>p&&p.compareDocumentPosition(w)&4;b=c?s.findLast(w=>!g(w))??s.at(-1):s.find(g)??s[0]}else(c?d===0:d===s.length-1)&&(b=s.at(c?-1:0));b&&(e.preventDefault(),b.focus())}return re.addEventListener("pointerdown",e=>{if(!n.mobile||n.mode!=="sheet")return;let t=e.clientY,r=0,s=p=>{r=Math.max(0,p.clientY-t),_.style.transform=`translateY(${r}px)`},c=()=>{document.removeEventListener("pointermove",s),document.removeEventListener("pointerup",c),_.style.transform="",r>80&&j("close")};document.addEventListener("pointermove",s),document.addEventListener("pointerup",c)}),D(h?.step&&a.steps.some(e=>e.id===h.step)?h.step:a.steps[0].id),(i.container??document.body).append(C),Pe(),{close:j,root:L,host:C,show:D,step:()=>n.step?.id??null,modal:()=>!n.closed&&n.modal,destroy:()=>!n.closed&&qe()}}window[Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.render")]={mountForm:it,warm:Ae};})();
@@ -1 +1 @@
1
- (()=>{function L(e,i,s=5){let n=360/i;return s*360+(360-(e+.5)*n)}var k="http://www.w3.org/2000/svg",z=4500,S=.22,O=.95,v=.105,w=.082,A=.062,I=.62,F=1.15,N="var(--hp-accent,#111)",C="var(--hp-on-accent,#fff)",g="var(--hp-bg,#fff)",T="var(--hp-text,#111)";function c(e,i={}){let s=document.createElementNS(k,e);for(let[n,o]of Object.entries(i))s.setAttribute(n,String(o));return s}function f(e,i,s,n=1){return e.style.fill=i,n<1&&(e.style.fillOpacity=String(n)),s&&(e.style.stroke=s),e}var j=()=>globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches===!0,$=(e,i=1)=>{let s=(e-90)*Math.PI/180;return`${(i*Math.cos(s)).toFixed(4)} ${(i*Math.sin(s)).toFixed(4)}`};function B(e,i){let s=O-S,n=2*.35*Math.sin(Math.min(Math.PI/i,Math.PI/2)),o=t=>Math.max(w,Math.min(v,n/(t*F))),a=t=>s/(Math.max(1,t.length)*I),r=[...e.matchAll(/ /g)].map(t=>t.index),u=e.length/2,p=r.length?r.reduce((t,l)=>Math.abs(l-u)<Math.abs(t-u)?l:t):-1,h=p<0?null:[e.slice(0,p),e.slice(p+1)];for(let t of[w,A]){let l=a(e);if(l>=t)return{lines:[e],size:Math.min(o(1),l)};if(h){let m=Math.min(o(2),...h.map(a));if(m>=t)return{lines:h,size:m}}}let d=Math.floor(s/(A*I));return{lines:[`${e.slice(0,d-1).trimEnd()}\u2026`],size:A}}function P(e){let i=O-S,s=n=>n.getComputedTextLength?.()??0;for(let n of e){let o=[...n.querySelectorAll("tspan")],a=Math.max(0,...o.map(s));if(!(a>i))continue;let r=Math.max(A,Number(n.getAttribute("font-size"))*i/a);n.setAttribute("font-size",r.toFixed(4)),o.forEach((u,p)=>{u.setAttribute("y",((p-(o.length-1)/2)*r*F).toFixed(4)),s(u)>i&&(u.setAttribute("textLength",i.toFixed(4)),u.setAttribute("lengthAdjust","spacingAndGlyphs"))})}}function R(e,i){let s=(Array.isArray(i)?i:[]).map(d=>String(d?.label??d?.key??"")),n=s.length;if(n<2)return null;let o=360/n,a=c("svg",{viewBox:"-1.2 -1.2 2.4 2.4",role:"img","aria-label":`Prize wheel: ${s.join(", ")}`}),r=c("g");r.style.transformBox="fill-box",r.style.transformOrigin="50% 50%";let u=[[1,C],[.14,T],[.72,C]];r.append(f(c("circle",{r:1}),g));let p=[],h=[];return s.forEach((d,t)=>{let[l,m]=u[n%2===1&&t===n-1?2:t%2];r.append(f(c("path",{d:`M0 0L${$(t*o)}A1 1 0 ${o>180?1:0} 1 ${$((t+1)*o)}Z`,"stroke-width":.012}),N,g,l));let b=(t+.5)*o-90,x=B(d,n),_=f(c("text",{transform:`rotate(${b}) translate(${(S+O)/2} 0)${b>90&&b<270?" rotate(180)":""}`,"text-anchor":"middle","dominant-baseline":"central","font-size":x.size.toFixed(4),"font-weight":700,"aria-hidden":"true"}),m);x.lines.forEach((M,E)=>{let y=c("tspan",{x:0,y:((E-(x.lines.length-1)/2)*x.size*F).toFixed(4)});y.textContent=M,_.append(y)}),r.append(_),h.push(_);for(let M of[t*o,(t+.5)*o]){let[E,y]=$(M,1.075).split(" ");p.push(f(c("circle",{cx:E,cy:y,r:.024}),g))}}),a.append(f(c("circle",{r:1.13}),T),...p,r,f(c("circle",{r:.17,"stroke-width":.035}),g,T),f(c("circle",{r:.065}),N),f(c("path",{d:"M-0.12 -1.2L0.12 -1.2L0 -0.86Z","stroke-width":.03,"stroke-linejoin":"round"}),N,g)),e.append(a),P(h),globalThis.requestAnimationFrame?.(()=>P(h)),{spinTo(d){let t=j();return r.style.transition=t?"none":`transform ${z}ms cubic-bezier(.15,.7,.1,1)`,r.style.transform=`rotate(${L(d,s.length,t?0:5)}deg)`,t?Promise.resolve():new Promise(l=>{let m=setTimeout(l,z+200);r.addEventListener("transitionend",()=>{clearTimeout(m),l()},{once:!0})})},remove:()=>a.remove()}}window[Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.wheel")]={mountWheel:R};})();
1
+ (()=>{function L(e,i,s=5){let n=360/i;return s*360+(360-(e+.5)*n)}var P="http://www.w3.org/2000/svg",z=4500,S=.22,F=.95,k=.105,v=.082,A=.062,I=.62,O=1.15,N="var(--hp-accent,#111)",R="var(--hp-on-accent,#fff)",g="var(--hp-bg,#fff)",T="var(--hp-text,#111)";function c(e,i={}){let s=document.createElementNS(P,e);for(let[n,o]of Object.entries(i))s.setAttribute(n,String(o));return s}function f(e,i,s,n=1){return e.style.fill=i,n<1&&(e.style.fillOpacity=String(n)),s&&(e.style.stroke=s),e}var j=()=>globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches===!0,$=(e,i=1)=>{let s=(e-90)*Math.PI/180;return`${(i*Math.cos(s)).toFixed(4)} ${(i*Math.sin(s)).toFixed(4)}`};function B(e,i){let s=F-S,n=2*.35*Math.sin(Math.min(Math.PI/i,Math.PI/2)),o=t=>Math.max(v,Math.min(k,n/(t*O))),a=t=>s/(Math.max(1,t.length)*I),r=[...e.matchAll(/ /g)].map(t=>t.index),u=e.length/2,p=r.length?r.reduce((t,l)=>Math.abs(l-u)<Math.abs(t-u)?l:t):-1,h=p<0?null:[e.slice(0,p),e.slice(p+1)];for(let t of[v,A]){let l=a(e);if(l>=t)return{lines:[e],size:Math.min(o(1),l)};if(h){let m=Math.min(o(2),...h.map(a));if(m>=t)return{lines:h,size:m}}}let d=Math.floor(s/(A*I));return{lines:[`${e.slice(0,d-1).trimEnd()}\u2026`],size:A}}function w(e){let i=F-S,s=n=>n.getComputedTextLength?.()??0;for(let n of e){let o=[...n.querySelectorAll("tspan")],a=Math.max(0,...o.map(s));if(!(a>i))continue;let r=Math.max(A,Number(n.getAttribute("font-size"))*i/a);n.setAttribute("font-size",r.toFixed(4)),o.forEach((u,p)=>{u.setAttribute("y",((p-(o.length-1)/2)*r*O).toFixed(4)),s(u)>i&&(u.setAttribute("textLength",i.toFixed(4)),u.setAttribute("lengthAdjust","spacingAndGlyphs"))})}}function C(e,i){let s=(Array.isArray(i)?i:[]).map(d=>String(d?.label??d?.key??"")),n=s.length;if(n<2)return null;let o=360/n,a=c("svg",{viewBox:"-1.2 -1.2 2.4 2.4",role:"img","aria-label":`Prize wheel: ${s.join(", ")}`}),r=c("g");r.style.transformBox="fill-box",r.style.transformOrigin="50% 50%";let u=[[1,R],[.14,T],[.72,R]];r.append(f(c("circle",{r:1}),g));let p=[],h=[];return s.forEach((d,t)=>{let[l,m]=u[n%2===1&&t===n-1?2:t%2];r.append(f(c("path",{d:`M0 0L${$(t*o)}A1 1 0 ${o>180?1:0} 1 ${$((t+1)*o)}Z`,"stroke-width":.012}),N,g,l));let b=(t+.5)*o-90,x=B(d,n),_=f(c("text",{transform:`rotate(${b}) translate(${(S+F)/2} 0)${b>90&&b<270?" rotate(180)":""}`,"text-anchor":"middle","dominant-baseline":"central","font-size":x.size.toFixed(4),"font-weight":700,"aria-hidden":"true"}),m);x.lines.forEach((E,M)=>{let y=c("tspan",{x:0,y:((M-(x.lines.length-1)/2)*x.size*O).toFixed(4)});y.textContent=E,_.append(y)}),r.append(_),h.push(_);for(let E of[t*o,(t+.5)*o]){let[M,y]=$(E,1.075).split(" ");p.push(f(c("circle",{cx:M,cy:y,r:.024}),g))}}),a.append(f(c("circle",{r:1.13}),T),...p,r,f(c("circle",{r:.17,"stroke-width":.035}),g,T),f(c("circle",{r:.065}),N),f(c("path",{d:"M-0.12 -1.2L0.12 -1.2L0 -0.86Z","stroke-width":.03,"stroke-linejoin":"round"}),N,g)),e.append(a),w(h),globalThis.requestAnimationFrame?.(()=>w(h)),{spinTo(d){let t=j();return r.style.transition=t?"none":`transform ${z}ms cubic-bezier(.15,.7,.1,1)`,r.style.transform=`rotate(${L(d,s.length,t?0:5)}deg)`,t?Promise.resolve():new Promise(l=>{let m=setTimeout(l,z+200);r.addEventListener("transitionend",()=>{clearTimeout(m),l()},{once:!0})})},remove:()=>a.remove()}}window[Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.wheel")]={mountWheel:C};})();
@@ -1 +1 @@
1
- (()=>{function P(e){let s=typeof document>"u"?null:document.currentScript?.src;return s?new URL(e,s).href:null}var Y=new Map;function O(e,s){return window[s]?Promise.resolve(window[s]):e?(Y.has(s)||Y.set(s,new Promise((n,r)=>{let d=document.createElement("script");d.src=e,d.async=!0,d.onload=()=>window[s]?n(window[s]):r(new Error(`${e} did not register`)),d.onerror=()=>r(new Error(`${e} did not load`)),document.head.append(d)}).finally(()=>Y.delete(s))),Y.get(s)):Promise.reject(new Error("the CDN script\u2019s own URL is unknown"))}var Ne=P("onsite-answers.min.js"),se=()=>O(Ne,Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.answers"));var ke="/v1/capture/challenge",De=e=>typeof e=="string"&&/^\/v1\/[\w/-]+$/.test(e)?e:ke;function oe(e,s={}){let n=s.fetch??globalThis.fetch?.bind(globalThis),r=s.servingHost??e.servingHost,d=s.gatewayHost??e.gatewayHost;async function o(l,{method:p="GET",body:i,consent:c=!1,timeoutMs:u}={}){if(!n)return{status:0,body:null};try{let w=await n(l,{method:p,credentials:"omit",signal:u&&AbortSignal.timeout?.(u),headers:{accept:"application/json",authorization:`Bearer ${e.writeKey}`,...i?{"content-type":"application/json"}:{},...c?e.headers():{}},...i?{body:JSON.stringify(i)}:{}}),b=null;try{b=await w.json()}catch{}return{status:w.status,body:b}}catch{return{status:0,body:null}}}return{decide:(l,p)=>o(`${r}/v1/decisions`,{method:"POST",consent:!0,body:{slots:[p?{key:l,pin:{experiment:p[0],arm:p[1],split:p[2]}}:l],identifier_value:e.anonymousId()??void 0,session_id:e.sessionId()??void 0,...e.preview?{preview:e.preview}:{}}}),challenge:()=>o(`${d}${De(s.challenge)}`),capture:l=>o(`${d}/v1/capture`,{method:"POST",body:l}),answers:l=>o(`${d}/v1/capture/answers`,{method:"POST",body:l}),claim:l=>o(`${r}/v1/offers/claim`,{method:"POST",consent:!0,body:l,timeoutMs:8e3})}}function ie(e,s){let n={},r=()=>{try{let o=JSON.parse(e().getItem(s));o&&typeof o=="object"&&(n=o)}catch{}return n};return{read:r,write:o=>{let l=r();o(l),n=l;try{e().setItem(s,JSON.stringify(l))}catch{}}}}function re(e,s=()=>!0){let n=ie(()=>sessionStorage,e),r=ie(()=>localStorage,e),d=()=>s()?r:n,o=()=>{let i=r.read();(i.sub!==void 0||i.k!==void 0)&&r.write(c=>{delete c.sub,delete c.k})},l=()=>s()?[n.read(),r.read()]:(o(),[n.read()]),p=(i,c)=>{var u;return i.f??(i.f={}),(u=i.f)[c]??(u[c]={}),i.f[c]};return{seen(i){let c=r.read().f?.[i]??{};return{session:n.read().f?.[i]?.n??0,lifetime:c.n??0,closedAt:c.c??null,submitted:c.s===1}},subscribed:()=>l().some(i=>i.sub===1),shown(i){n.write(c=>{let u=p(c,i);u.n=(u.n??0)+1}),r.write(c=>{let u=p(c,i);u.n=(u.n??0)+1})},closed(i,c=Date.now()){r.write(u=>{p(u,i).c=c})},tab(i,c){n.write(u=>{let w=p(u,i);c?w.t=1:delete w.t})},tabOut:i=>n.read().f?.[i]?.t===1,pin(i,c){if(c===void 0)return n.read().f?.[i]?.p??null;n.write(u=>{p(u,i).p=c})},coveredAt:()=>n.read().o??null,covered(i=Date.now()){n.write(c=>{c.o=i})},code(i,c=Date.now()){if(i===void 0){let[u]=l().flatMap(w=>w.k?[w.k]:[]).sort((w,b)=>b.at-w.at);return u&&c-u.at<14*864e5?u.c:null}return d().write(u=>{u.k={c:i,at:c}}),i},submitted(i){r.write(c=>{p(c,i).s=1}),d().write(c=>{c.sub=1})}}}var Le=P("onsite-render.min.js"),le=()=>O(Le,Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.render"));var de=["popup","sheet","bar","teaser","inline","fullscreen"],Fe=["entry","exit","scroll","time","idle","inline","manual"],q=e=>e!=="inline",pe=e=>e==="popup"||e==="sheet"||e==="fullscreen",S=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),D=e=>Array.isArray(e)?e.filter(s=>typeof s=="string"):[],ce=e=>Number.isInteger(e)&&e>=0?e:null;function fe(e){if(!S(e)||typeof e.slot!="string"||e.slot==="")return null;let s=S(e.trigger)?e.trigger:{};if(!de.includes(e.format)||!Fe.includes(s.type))return null;let n=S(e.caps)?e.caps:{};return{...e,trigger:s,priority:Number.isFinite(e.priority)?e.priority:0,pages:S(e.pages)?e.pages:{},devices:D(e.devices),aliases:D(e.aliases),audiences:D(e.audiences),caps:{per_session:ce(n.per_session),lifetime:ce(n.lifetime),after_close_days:Number.isFinite(n.after_close_days)?n.after_close_days:null},window:S(e.window)?e.window:{},questions:Array.isArray(e.questions)?e.questions.filter(S):[],prizes:Array.isArray(e.prizes)?e.prizes.filter(S):[]}}var We=/^[a-z][a-z0-9_-]{0,31}$/;function he(e){if(!S(e)||e.v!==1||!Array.isArray(e.steps))return null;let s=e.steps.filter(n=>S(n)&&We.test(n.id)&&Array.isArray(n.blocks));return s.length===0?null:{format:de.includes(e.format)?e.format:null,theme:S(e.theme)?e.theme:{},steps:s}}function ae(e,s){let n=String(e).split("*").map(r=>r.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${n}$`,"i").test(s)}function je(e,s){let n=D(e?.include);return(!n.length||n.some(r=>ae(r,s)))&&!D(e?.exclude).some(r=>ae(r,s))}function we(e){return e.matchMedia?.("(hover: none) and (pointer: coarse)")?.matches===!0||e.innerWidth<768?"mobile":"desktop"}var ue=e=>typeof e=="string"?Date.parse(e):Number.NaN,L=e=>e.trigger.type==="manual";function J(e,s){let n=[];je(e.pages,s.path)||n.push("page not included"),e.devices.length&&!e.devices.includes(s.device)&&n.push(`not on ${s.device}`);let r=ue(e.window.starts_at),d=ue(e.window.ends_at);if((s.now<r||s.now>=d)&&n.push("outside its dates"),e.audiences.length&&(s.personalisation?s.audiences&&!e.audiences.some(p=>s.audiences.includes(p))&&n.push("not in its audiences"):n.push("audiences need personalisation consent")),s.preview||s.asked||L(e))return n;let{seen:o}=s,{caps:l}=e;return o.submitted&&n.push("already submitted"),e.exclude_subscribed===!0&&s.subscribed&&n.push("already subscribed"),l.per_session!==null&&o.session>=l.per_session&&n.push("per_session cap"),l.lifetime!==null&&o.lifetime>=l.lifetime&&n.push("lifetime cap"),l.after_close_days!==null&&o.closedAt&&s.now-o.closedAt<l.after_close_days*864e5&&n.push("closed recently"),n}var ge=(e,s)=>s.priority-e.priority;var Ue=["mousemove","pointerdown","keydown","scroll","touchstart","wheel"];function Ke(){let e=[];return{on:(r,d,o,l={passive:!0})=>{r.addEventListener(d,o,l),e.push(()=>r.removeEventListener(d,o,l))},later:(r,d)=>{let o=setTimeout(r,d);e.push(()=>clearTimeout(o))},stop:()=>{for(let r of e.splice(0))r()}}}var ye=(e,s)=>{let n=s.documentElement.scrollHeight||0;return n>0?(e.scrollY+e.innerHeight)/n:0},Ye=e=>{let s=e.activeElement;return!!(s&&(/^(INPUT|TEXTAREA|SELECT)$/.test(s.tagName)||s.isContentEditable))};function He({on:e,later:s},n,r,d,o){let l=!1,p=!1,i=null,c=0;s(()=>{l=!0},r.delay_ms??5e3),e(o,"mousemove",u=>{u.clientY>d.innerHeight*.1&&(p=!0),i!==null&&(c=u.clientY-i),i=u.clientY}),e(o,"mouseout",u=>{l&&p&&!u.relatedTarget&&u.clientY<=0&&c<0&&!Ye(o)&&n("exit")})}function ze({on:e,later:s},n,r,d,o){let l=!1,p=0,i=d.scrollY,c=Date.now(),u=null,w=null;s(()=>{l=!0},r.delay_ms??5e3),e(d,"scroll",()=>{let b=d.scrollY,A=Date.now();if(p=Math.max(p,ye(d,o)),b<i){(!u||A-u.t>300)&&(u={y:i,t:c});let _=u.y-b;l&&p>=.3&&_>=120&&_/Math.max(1,A-u.t)>=.5&&n("exit_scroll")}else u=null;i=b,c=A}),e(o,"visibilitychange",()=>{o.visibilityState==="hidden"?w=Date.now():w!==null&&Date.now()-w>=1e4&&n("return"),o.visibilityState!=="hidden"&&(w=null)})}function me(e,s,{device:n,win:r=window,doc:d=document}){let o=Ke(),l=(e.seconds??30)*1e3;if(e.type==="entry"&&o.later(()=>s("entry"),e.delay_ms??0),e.type==="time"&&o.later(()=>s("time"),l),e.type==="exit"&&(n==="mobile"?ze:He)(o,s,e,r,d),e.type==="scroll"){let p=e.depth??.5;o.on(r,"scroll",()=>ye(r,d)>=p&&s("scroll"))}if(e.type==="idle"){let p=null,i=()=>{clearTimeout(p),p=setTimeout(()=>s("idle"),l)};i();for(let c of Ue)o.on(c==="scroll"?r:d,c,i);return o.on(d,"visibilitychange",i),()=>{clearTimeout(p),o.stop()}}return o.stop}var Xe=P("onsite-wheel.min.js"),be=()=>O(Xe,Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.wheel"));var _e=Symbol.for("@thg-agentic/hyper-personalisation-web.onsite-access"),F=Symbol.for("@thg-agentic/hyper-personalisation-web.onsite"),Be=Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.pending"),Ge=Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.listeners"),Se=Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.suppressed"),Ae={seen:()=>({session:0,lifetime:0,closedAt:null,submitted:!1}),subscribed:()=>!1,shown(){},closed(){},submitted(){},tab(){},tabOut:()=>!1,pin:()=>null,coveredAt:()=>null,covered(){},code:()=>null},Ve=50,qe=300,Je=()=>{try{return new URLSearchParams(location.search).get("hp_debug")==="onsite"}catch{return!1}};function Ee(e,s={}){if(typeof window>"u"||typeof document>"u")return null;if(window[F])return window[F];let n=typeof e?.[_e]=="function"?e[_e]():null;if(!n)return console.warn("[hp] onsite: startOnsite needs the client bootstrap or createAnalytics made"),null;let r=s.settings??n.settings??{},d=oe(n,{...s,challenge:r.capture?.challenge}),o=n.preview?Ae:re(n.storageKey,n.personalisation),l=new Map,p=()=>window[Se]?.size>0,i=(t,a)=>{for(let f of window[Ge]?.[t]??[])try{f(a)}catch(h){console.warn(`[hp] onsite ${t} listener failed:`,h)}},c=we(window),u=n.debug||s.debug===!0||Je(),w=new Map,b=new Map,A=[];for(let t of Array.isArray(r.forms)?r.forms:[]){let a=fe(t);a?A.push(a):w.set(String(t?.slot??`form ${w.size+1}`),{slot:String(t?.slot??""),state:"invalid",reasons:["not a form this SDK can show"]})}let _=new Map,W=new Map,x=null,Z=new Set,ve=t=>{for(let a of _.keys()){let f=l.get(a);if(!t||!f||f.modal?.())return a}return null},j=[],H=Number.isInteger(r.overlay_gap_minutes)?r.overlay_gap_minutes:0,xe=()=>{let t=o.coveredAt();if(!(H>0)||typeof t!="number")return null;let a=Math.max(0,Math.floor((Date.now()-t)/6e4));return a<H?`a popup showed ${a} min ago; ${H} min between them`:null},C=new Set,U=new Map,g=(t,a,f=[])=>(w.set(t.slot,{slot:t.slot,format:t.format,trigger:t.trigger.type,priority:t.priority,state:a,reasons:f}),u&&console.info(`[hp] onsite ${t.slot}: ${a}${f.length?` (${f.join("; ")})`:""}`),a),Te=()=>{try{let t=s.audiences?.();return Array.isArray(t)?t:null}catch{return null}},Q=t=>({path:location.pathname,device:c,now:Date.now(),seen:o.seen(t.slot),subscribed:o.subscribed()||s.subscribed?.()===!0,personalisation:n.personalisation(),preview:!!n.preview,audiences:Te()}),z=t=>{b.get(t.slot)?.(),b.delete(t.slot)};function R(t,a,f=!1,h=L(t)){return l.has(t.slot)?Promise.resolve("shown"):(W.has(t.slot)||W.set(t.slot,Ie(t,a,f,h).finally(()=>W.delete(t.slot))),W.get(t.slot))}async function Ie(t,a,f,h){if(p())return g(t,"not shown",[`suppressed: ${[...window[Se]].join(", ")}`]);let T=J(t,{...Q(t),...f?{seen:Ae.seen()}:{},asked:h});if(T.length)return g(t,"not eligible",T);let E=pe(t.format)&&!f,K=E&&!h&&xe();if(K)return g(t,"not shown",[K]);if(E&&!n.preview&&n.consentAnswered?.()===!1)return U.set(t,h),g(t,"not shown",["waiting for the consent banner"]);let v=q(t.format),k=v&&ve(h);if(k)return g(t,"not shown",[`${k} is showing`]);if(v&&x&&!h)return g(t,"not shown",[`${x} already showed on this page view`]);let I=null;if(!v){try{I=document.querySelector(t.trigger.selector??"")}catch{I=null}if(!I)return g(t,"not shown",["no element matches its selector"])}v&&_.set(t.slot,t),z(t),g(t,"asking for a decision",[a]);let Pe=le().catch(m=>(console.warn("[hp] onsite renderer not loaded:",m?.message??m),null)),$=await d.decide(t.slot,o.pin(t.slot)),y=$.status===200?$.body?.decisions?.find(m=>m?.slot===t.slot):null;y?.experiment&&y.arm&&y.split&&o.pin(t.slot,[y.experiment,y.arm,y.split]);let M=y&&y.holdout!==!0?he(y.payload):null,te=M?.steps[0].blocks??[],ne=y?.offer?.code??(n.preview?"PREVIEW":o.code()),Oe=n.basketValue?.()??null,B=te.some(m=>m?.t==="code")&&!ne&&"no code to remind of"||te.some(m=>m?.t==="progress")&&!(Oe>0)&&"the basket is empty";if(B)return _.delete(t.slot),B==="the basket is empty"&&C.add(t),g(t,"not shown",[B]);if(C.delete(t),!M)return y?.holdout===!0&&n.analytics()&&e.recordExposure($.body),_.delete(t.slot),v&&y?.holdout===!0&&(x??(x=t.slot)),y?.holdout===!0&&!h&&i("held",{slot:t.slot,arm:y.arm??null,format:t.format}),g(t,y?.holdout===!0?"held out":"no decision",[$.status===200?"no creative for this visitor":`decisions answered ${$.status}`]);let G=await Pe;if(!G)return _.delete(t.slot),g(t,"not shown",["the renderer did not load"]);if(await Promise.race([G.warm?.(t,M,M.steps[0].id,Z),new Promise(m=>setTimeout(m,qe))]),p())return _.delete(t.slot),g(t,"not shown",["suppressed"]);f||o.shown(t.slot),E&&o.covered(),v&&(x??(x=t.slot));let V=(m,Re={})=>i(m,{slot:t.slot,arm:y.arm??null,format:M.format??t.format,...Re}),Ce=G.mountForm({form:t,creative:M,decision:y,access:n,client:e,api:d,counters:o,loadWheel:be,loadAnswers:se,container:I,warmed:Z,coupon:ne,basket:()=>n.basketValue?.()??null,emit:V,onClose(m){l.delete(t.slot),_.delete(t.slot),g(t,"closed",[m]),V("closed",{reason:m})}});return l.set(t.slot,Ce),n.analytics()&&e.recordExposure($.body),g(t,"shown",[a]),V("shown"),"shown"}function X(t,a,f=L(t)){if(!q(t.format))return R(t,a,!1,f);j.push([t,a,f]),!(j.length>1)&&setTimeout(async()=>{let h=j.sort(([T],[E])=>ge(T,E));j=[];for(let[T,[E,K,v]]of h.entries()){let k=await R(E,K,!1,v);if(k==="shown"||k==="held out"){for(let[I]of h.slice(T+1))g(I,"not shown",[`${E.slot} has a higher priority`]);return}}},Ve)}for(let t of A){if(t.format==="teaser"&&o.tabOut(t.slot)){R(t,"tab kept from an earlier page",!0);continue}let a=J(t,Q(t));if(a.length){g(t,"not eligible",a);continue}let f=t.trigger.type;f==="manual"?g(t,"waiting for hp.onsite.open"):f==="inline"||t.format==="inline"?R(t,"inline"):ee(t)}function ee(t){z(t),b.set(t.slot,me(t.trigger,a=>{z(t),X(t,a)},{device:c})),g(t,"armed",[`${t.trigger.type} on ${c}`])}let $e=n.onConsentAnswered?.(()=>{let t=[...U];U.clear();for(let[a,f]of t)l.has(a.slot)||(f?X(a,"manual",f):ee(a))}),Me=n.onBasket?.(()=>{if(!((n.basketValue?.()??0)>0))return;let t=[...C];C.clear();for(let a of t)l.has(a.slot)||X(a,"the basket changed")}),N=Object.freeze({open(t){let a=A.find(h=>h.slot===t),f=a??A.find(h=>h.aliases.includes(t));return f?l.has(f.slot)?Promise.resolve(!0):R(f,"manual",!1,L(f)||!a).then(h=>h==="shown"):Promise.resolve(!1)},suppress(){for(let[t,a]of l){a.destroy(),l.delete(t),_.delete(t);let f=A.find(h=>h.slot===t);f&&g(f,"closed",["suppressed"])}},debug:()=>[...w.values()].map(t=>({...t,reasons:[...t.reasons]})),stop(){for(let t of b.values())t();b.clear(),Me?.(),$e?.(),C.clear(),U.clear(),window[F]===N&&delete window[F]}});window[F]=N;for(let{slot:t,resolve:a}of window[Be]?.splice(0)??[])a(N.open(t));return u&&console.table?.(N.debug()),N}window[Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.module")]={startOnsite:Ee};})();
1
+ (()=>{function T(e){let s=typeof document>"u"?null:document.currentScript?.src;return s?new URL(e,s).href:null}var H=new Map;function I(e,s){return window[s]?Promise.resolve(window[s]):e?(H.has(s)||H.set(s,new Promise((n,r)=>{let d=document.createElement("script");d.src=e,d.async=!0,d.onload=()=>window[s]?n(window[s]):r(new Error(`${e} did not register`)),d.onerror=()=>r(new Error(`${e} did not load`)),document.head.append(d)}).finally(()=>H.delete(s))),H.get(s)):Promise.reject(new Error("the CDN script\u2019s own URL is unknown"))}var Ke=T("onsite-answers.min.js"),ae=()=>I(Ke,Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.answers"));var Ye="/v1/capture/challenge",He=e=>typeof e=="string"&&/^\/v1\/[\w/-]+$/.test(e)?e:Ye;function ce(e,s={}){let n=s.fetch??globalThis.fetch?.bind(globalThis),r=s.servingHost??e.servingHost,d=s.gatewayHost??e.gatewayHost;async function o(a,{method:p="GET",body:i,consent:l=!1,timeoutMs:c}={}){if(!n)return{status:0,body:null};try{let w=await n(a,{method:p,credentials:"omit",signal:c&&AbortSignal.timeout?.(c),headers:{accept:"application/json",authorization:`Bearer ${e.writeKey}`,...i?{"content-type":"application/json"}:{},...l?e.headers():{}},...i?{body:JSON.stringify(i)}:{}}),b=null;try{b=await w.json()}catch{}return{status:w.status,body:b}}catch{return{status:0,body:null}}}return{decide:(a,p,{visitAudiences:i,visitCampaign:l}={})=>o(`${r}/v1/decisions`,{method:"POST",consent:!0,body:{slots:[p?{key:a,pin:{experiment:p[0],arm:p[1],split:p[2]}}:a],identifier_value:e.anonymousId()??void 0,session_id:e.sessionId()??void 0,identity_token:e.identityToken?.()??void 0,...e.preview?{preview:e.preview}:{},...i?{visit_audiences:i}:{},...l?{visit_campaign:l}:{}}}),datafile:()=>o(`${r}/v1/audiences/datafile`,{timeoutMs:1500}),challenge:()=>o(`${d}${He(s.challenge)}`),capture:a=>o(`${d}/v1/capture`,{method:"POST",body:a}),answers:a=>o(`${d}/v1/capture/answers`,{method:"POST",body:a}),claim:a=>o(`${r}/v1/offers/claim`,{method:"POST",consent:!0,body:a,timeoutMs:8e3})}}var Xe=T("onsite-audiences.min.js"),ue=()=>I(Xe,Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.audiences"));function de(e,s){let n={},r=()=>{try{let o=JSON.parse(e().getItem(s));o&&typeof o=="object"&&(n=o)}catch{}return n};return{read:r,write:o=>{let a=r();o(a),n=a;try{e().setItem(s,JSON.stringify(a))}catch{}}}}function pe(e,s=()=>!0){let n=de(()=>sessionStorage,e),r=de(()=>localStorage,e),d=()=>s()?r:n,o=()=>{let i=r.read();(i.sub!==void 0||i.k!==void 0)&&r.write(l=>{delete l.sub,delete l.k})},a=()=>s()?[n.read(),r.read()]:(o(),[n.read()]),p=(i,l)=>{var c;return i.f??(i.f={}),(c=i.f)[l]??(c[l]={}),i.f[l]};return{seen(i){let l=r.read().f?.[i]??{};return{session:n.read().f?.[i]?.n??0,lifetime:l.n??0,closedAt:l.c??null,submitted:l.s===1}},subscribed:()=>a().some(i=>i.sub===1),shown(i){n.write(l=>{let c=p(l,i);c.n=(c.n??0)+1}),r.write(l=>{let c=p(l,i);c.n=(c.n??0)+1})},closed(i,l=Date.now()){r.write(c=>{p(c,i).c=l})},tab(i,l){n.write(c=>{let w=p(c,i);l?w.t=1:delete w.t})},tabOut:i=>n.read().f?.[i]?.t===1,pin(i,l){if(l===void 0)return n.read().f?.[i]?.p??null;n.write(c=>{p(c,i).p=l})},coveredAt:()=>n.read().o??null,covered(i=Date.now()){n.write(l=>{l.o=i})},code(i,l=Date.now()){if(i===void 0){let[c]=a().flatMap(w=>w.k?[w.k]:[]).sort((w,b)=>b.at-w.at);return c&&l-c.at<14*864e5?c.c:null}return d().write(c=>{c.k={c:i,at:l}}),i},submitted(i){r.write(l=>{p(l,i).s=1}),d().write(l=>{l.sub=1})}}}var ze=T("onsite-render.min.js"),fe=()=>I(ze,Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.render"));var Ve=["source","medium","campaign","content","term"];var he=e=>String(e).trim().toLowerCase();function ge(e,s){return(Array.isArray(e)?e:[]).every(n=>{let r=s?.[n?.field];if(!Ve.includes(n?.field)||typeof r!="string")return!1;let d=he(r);return[].concat(n.values??[]).some(o=>{let a=he(o);return n.match==="is"?d===a:n.match==="contains"&&a!==""&&d.includes(a)})})}var be=["popup","sheet","bar","teaser","inline","fullscreen"],Ge=["entry","exit","scroll","time","idle","inline","manual"],Z=e=>e!=="inline",Se=e=>e==="popup"||e==="sheet"||e==="fullscreen",S=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),k=e=>Array.isArray(e)?e.filter(s=>typeof s=="string"):[],me=e=>Number.isInteger(e)&&e>=0?e:null,Be={field:null,match:null,values:[]},qe=e=>e==null?[]:Array.isArray(e)&&e.every(S)?e:[Be];function _e(e){if(!S(e)||typeof e.slot!="string"||e.slot==="")return null;let s=S(e.trigger)?e.trigger:{};if(!be.includes(e.format)||!Ge.includes(s.type))return null;let n=S(e.caps)?e.caps:{};return{...e,trigger:s,priority:Number.isFinite(e.priority)?e.priority:0,pages:S(e.pages)?e.pages:{},devices:k(e.devices),aliases:k(e.aliases),audiences:k(e.audiences),arrived_from:qe(e.arrived_from),caps:{per_session:me(n.per_session),lifetime:me(n.lifetime),after_close_days:Number.isFinite(n.after_close_days)?n.after_close_days:null},window:S(e.window)?e.window:{},questions:Array.isArray(e.questions)?e.questions.filter(S):[],prizes:Array.isArray(e.prizes)?e.prizes.filter(S):[]}}var Je=/^[a-z][a-z0-9_-]{0,31}$/;function Ae(e){if(!S(e)||e.v!==1||!Array.isArray(e.steps))return null;let s=e.steps.filter(n=>S(n)&&Je.test(n.id)&&Array.isArray(n.blocks));return s.length===0?null:{format:be.includes(e.format)?e.format:null,theme:S(e.theme)?e.theme:{},steps:s}}function we(e,s){let n=String(e).split("*").map(r=>r.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${n}$`,"i").test(s)}function Ze(e,s){let n=k(e?.include);return(!n.length||n.some(r=>we(r,s)))&&!k(e?.exclude).some(r=>we(r,s))}function ve(e){return e.matchMedia?.("(hover: none) and (pointer: coarse)")?.matches===!0||e.innerWidth<768?"mobile":"desktop"}var ye=e=>typeof e=="string"?Date.parse(e):Number.NaN,F=e=>e.trigger.type==="manual";function Q(e,s){let n=[];Ze(e.pages,s.path)||n.push("page not included"),e.devices.length&&!e.devices.includes(s.device)&&n.push(`not on ${s.device}`),ge(e.arrived_from,s.campaign)||n.push("not from its campaign");let r=ye(e.window.starts_at),d=ye(e.window.ends_at);if((s.now<r||s.now>=d)&&n.push("outside its dates"),e.audiences.length&&!s.preview&&(s.personalisation?s.audiences&&!e.audiences.some(p=>s.audiences.includes(p))&&n.push("not in its audiences"):n.push("audiences need personalisation consent")),s.preview||s.asked||F(e))return n;let{seen:o}=s,{caps:a}=e;return o.submitted&&n.push("already submitted"),e.exclude_subscribed===!0&&s.subscribed&&n.push("already subscribed"),a.per_session!==null&&o.session>=a.per_session&&n.push("per_session cap"),a.lifetime!==null&&o.lifetime>=a.lifetime&&n.push("lifetime cap"),a.after_close_days!==null&&o.closedAt&&s.now-o.closedAt<a.after_close_days*864e5&&n.push("closed recently"),n}var Ee=(e,s)=>s.priority-e.priority;var Qe=["mousemove","pointerdown","keydown","scroll","touchstart","wheel"];function et(){let e=[];return{on:(r,d,o,a={passive:!0})=>{r.addEventListener(d,o,a),e.push(()=>r.removeEventListener(d,o,a))},later:(r,d)=>{let o=setTimeout(r,d);e.push(()=>clearTimeout(o))},stop:()=>{for(let r of e.splice(0))r()}}}var xe=(e,s)=>{let n=s.documentElement.scrollHeight||0;return n>0?(e.scrollY+e.innerHeight)/n:0},tt=e=>{let s=e.activeElement;return!!(s&&(/^(INPUT|TEXTAREA|SELECT)$/.test(s.tagName)||s.isContentEditable))};function nt({on:e,later:s},n,r,d,o){let a=!1,p=!1,i=null,l=0;s(()=>{a=!0},r.delay_ms??5e3),e(o,"mousemove",c=>{c.clientY>d.innerHeight*.1&&(p=!0),i!==null&&(l=c.clientY-i),i=c.clientY}),e(o,"mouseout",c=>{a&&p&&!c.relatedTarget&&c.clientY<=0&&l<0&&!tt(o)&&n("exit")})}function st({on:e,later:s},n,r,d,o){let a=!1,p=0,i=d.scrollY,l=Date.now(),c=null,w=null;s(()=>{a=!0},r.delay_ms??5e3),e(d,"scroll",()=>{let b=d.scrollY,_=Date.now();if(p=Math.max(p,xe(d,o)),b<i){(!c||_-c.t>300)&&(c={y:i,t:l});let A=c.y-b;a&&p>=.3&&A>=120&&A/Math.max(1,_-c.t)>=.5&&n("exit_scroll")}else c=null;i=b,l=_}),e(o,"visibilitychange",()=>{o.visibilityState==="hidden"?w=Date.now():w!==null&&Date.now()-w>=1e4&&n("return"),o.visibilityState!=="hidden"&&(w=null)})}function Te(e,s,{device:n,win:r=window,doc:d=document}){let o=et(),a=(e.seconds??30)*1e3;if(e.type==="entry"&&o.later(()=>s("entry"),e.delay_ms??0),e.type==="time"&&o.later(()=>s("time"),a),e.type==="exit"&&(n==="mobile"?st:nt)(o,s,e,r,d),e.type==="scroll"){let p=e.depth??.5;o.on(r,"scroll",()=>xe(r,d)>=p&&s("scroll"))}if(e.type==="idle"){let p=null,i=()=>{clearTimeout(p),p=setTimeout(()=>s("idle"),a)};i();for(let l of Qe)o.on(l==="scroll"?r:d,l,i);return o.on(d,"visibilitychange",i),()=>{clearTimeout(p),o.stop()}}return o.stop}var ot=T("onsite-wheel.min.js"),Ie=()=>I(ot,Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.wheel"));var Me=Symbol.for("@thg-agentic/hyper-personalisation-web.onsite-access"),j=Symbol.for("@thg-agentic/hyper-personalisation-web.onsite"),it=Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.pending"),rt=Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.listeners"),Oe=Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.suppressed"),Ce={seen:()=>({session:0,lifetime:0,closedAt:null,submitted:!1}),subscribed:()=>!1,shown(){},closed(){},submitted(){},tab(){},tabOut:()=>!1,pin:()=>null,coveredAt:()=>null,covered(){},code:()=>null},lt=1500,at=50,ct=300,ut=()=>{try{return new URLSearchParams(location.search).get("hp_debug")==="onsite"}catch{return!1}};function Pe(e,s={}){if(typeof window>"u"||typeof document>"u")return null;if(window[j])return window[j];let n=typeof e?.[Me]=="function"?e[Me]():null;if(!n)return console.warn("[hp] onsite: startOnsite needs the client bootstrap or createAnalytics made"),null;let r=s.settings??n.settings??{},d=ce(n,{...s,challenge:r.capture?.challenge}),o=n.preview?Ce:pe(n.storageKey,n.personalisation),a=()=>n.campaign?.()??null,p=new Map,i=()=>window[Oe]?.size>0,l=(t,u)=>{for(let f of window[rt]?.[t]??[])try{f(u)}catch(g){console.warn(`[hp] onsite ${t} listener failed:`,g)}},c=ve(window),w=n.debug||s.debug===!0||ut(),b=new Map,_=new Map,A=[];for(let t of Array.isArray(r.forms)?r.forms:[]){let u=_e(t);u?A.push(u):b.set(String(t?.slot??`form ${b.size+1}`),{slot:String(t?.slot??""),state:"invalid",reasons:["not a form this SDK can show"]})}let ee=()=>ue().catch(t=>(console.warn("[hp] onsite audiences not loaded:",t?.message??t),null));n.personalisation()&&A.some(t=>t.audiences.length>0)&&ee().then(t=>t?.prefetch(d));let v=new Map,U=new Map,M=null,te=new Set,$e=t=>{for(let u of v.keys()){let f=p.get(u);if(!t||!f||f.modal?.())return u}return null},W=[],X=Number.isInteger(r.overlay_gap_minutes)?r.overlay_gap_minutes:0,Ne=()=>{let t=o.coveredAt();if(!(X>0)||typeof t!="number")return null;let u=Math.max(0,Math.floor((Date.now()-t)/6e4));return u<X?`a popup showed ${u} min ago; ${X} min between them`:null},N=new Set,K=new Map,m=(t,u,f=[])=>(b.set(t.slot,{slot:t.slot,format:t.format,trigger:t.trigger.type,priority:t.priority,state:u,reasons:f}),w&&console.info(`[hp] onsite ${t.slot}: ${u}${f.length?` (${f.join("; ")})`:""}`),u),ne=()=>{try{let t=s.audiences?.();return Array.isArray(t)?t:null}catch{return null}},se=t=>({path:location.pathname,device:c,campaign:a(),now:Date.now(),seen:o.seen(t.slot),subscribed:o.subscribed()||s.subscribed?.()===!0,personalisation:n.personalisation(),preview:!!n.preview,audiences:ne()}),z=t=>{_.get(t.slot)?.(),_.delete(t.slot)};function R(t,u,f=!1,g=F(t)){return p.has(t.slot)?Promise.resolve("shown"):(U.has(t.slot)||U.set(t.slot,Re(t,u,f,g).finally(()=>U.delete(t.slot))),U.get(t.slot))}async function Re(t,u,f,g){if(i())return m(t,"not shown",[`suppressed: ${[...window[Oe]].join(", ")}`]);let O=Q(t,{...se(t),...f?{seen:Ce.seen()}:{},asked:g});if(O.length)return m(t,"not eligible",O);let E=Se(t.format)&&!f,Y=E&&!g&&Ne();if(Y)return m(t,"not shown",[Y]);if(E&&!n.preview&&n.consentAnswered?.()===!1)return K.set(t,g),m(t,"not shown",["waiting for the consent banner"]);let x=Z(t.format),L=x&&$e(g);if(L)return m(t,"not shown",[`${L} is showing`]);if(x&&M&&!g)return m(t,"not shown",[`${M} already showed on this page view`]);let C=null;if(!x){try{C=document.querySelector(t.trigger.selector??"")}catch{C=null}if(!C)return m(t,"not shown",["no element matches its selector"])}x&&v.set(t.slot,t),z(t),m(t,"asking for a decision",[u]);let ke=fe().catch(h=>(console.warn("[hp] onsite renderer not loaded:",h?.message??h),null)),G=ne()??[],ie=[...new Set([...t.audiences,...G])].filter(h=>G.includes(h)).slice(0,100),Fe=t.audiences.length>0&&!n.preview&&n.personalisation()?await Promise.race([ee().then(h=>h?h.visitAudiences(d,n.sessionSignals,t.audiences,G):ie),new Promise(h=>setTimeout(h,lt,ie))]):null,P=await d.decide(t.slot,o.pin(t.slot),{visitAudiences:Fe,visitCampaign:t.arrived_from.length?a():null}),y=P.status===200?P.body?.decisions?.find(h=>h?.slot===t.slot):null;y?.experiment&&y.arm&&y.split&&o.pin(t.slot,[y.experiment,y.arm,y.split]);let $=y&&y.holdout!==!0?Ae(y.payload):null,re=$?.steps[0].blocks??[],le=y?.offer?.code??(n.preview?"PREVIEW":o.code()),je=n.basketValue?.()??null,B=re.some(h=>h?.t==="code")&&!le&&"no code to remind of"||re.some(h=>h?.t==="progress")&&!(je>0)&&"the basket is empty";if(B)return v.delete(t.slot),B==="the basket is empty"&&N.add(t),m(t,"not shown",[B]);if(N.delete(t),!$)return y?.holdout===!0&&n.analytics()&&e.recordExposure(P.body),v.delete(t.slot),x&&y?.holdout===!0&&(M??(M=t.slot)),y?.holdout===!0&&!g&&l("held",{slot:t.slot,arm:y.arm??null,format:t.format}),m(t,y?.holdout===!0?"held out":"no decision",[P.status===200?"no creative for this visitor":`decisions answered ${P.status}`]);let q=await ke;if(!q)return v.delete(t.slot),m(t,"not shown",["the renderer did not load"]);if(await Promise.race([q.warm?.(t,$,$.steps[0].id,te),new Promise(h=>setTimeout(h,ct))]),i())return v.delete(t.slot),m(t,"not shown",["suppressed"]);f||o.shown(t.slot),E&&o.covered(),x&&(M??(M=t.slot));let J=(h,We={})=>l(h,{slot:t.slot,arm:y.arm??null,format:$.format??t.format,...We}),Ue=q.mountForm({form:t,creative:$,decision:y,access:n,client:e,api:d,counters:o,loadWheel:Ie,loadAnswers:ae,container:C,warmed:te,coupon:le,basket:()=>n.basketValue?.()??null,emit:J,onClose(h){p.delete(t.slot),v.delete(t.slot),m(t,"closed",[h]),J("closed",{reason:h})}});return p.set(t.slot,Ue),n.analytics()&&e.recordExposure(P.body),m(t,"shown",[u]),J("shown"),"shown"}function V(t,u,f=F(t)){if(!Z(t.format))return R(t,u,!1,f);W.push([t,u,f]),!(W.length>1)&&setTimeout(async()=>{let g=W.sort(([O],[E])=>Ee(O,E));W=[];for(let[O,[E,Y,x]]of g.entries()){let L=await R(E,Y,!1,x);if(L==="shown"||L==="held out"){for(let[C]of g.slice(O+1))m(C,"not shown",[`${E.slot} has a higher priority`]);return}}},at)}for(let t of A){if(t.format==="teaser"&&o.tabOut(t.slot)){R(t,"tab kept from an earlier page",!0);continue}let u=Q(t,se(t));if(u.length){m(t,"not eligible",u);continue}let f=t.trigger.type;f==="manual"?m(t,"waiting for hp.onsite.open"):f==="inline"||t.format==="inline"?R(t,"inline"):oe(t)}function oe(t){z(t),_.set(t.slot,Te(t.trigger,u=>{z(t),V(t,u)},{device:c})),m(t,"armed",[`${t.trigger.type} on ${c}`])}let De=n.onConsentAnswered?.(()=>{let t=[...K];K.clear();for(let[u,f]of t)p.has(u.slot)||(f?V(u,"manual",f):oe(u))}),Le=n.onBasket?.(()=>{if(!((n.basketValue?.()??0)>0))return;let t=[...N];N.clear();for(let u of t)p.has(u.slot)||V(u,"the basket changed")}),D=Object.freeze({open(t){let u=A.find(g=>g.slot===t),f=u??A.find(g=>g.aliases.includes(t));return f?p.has(f.slot)?Promise.resolve(!0):R(f,"manual",!1,F(f)||!u).then(g=>g==="shown"):Promise.resolve(!1)},suppress(){for(let[t,u]of p){u.destroy(),p.delete(t),v.delete(t);let f=A.find(g=>g.slot===t);f&&m(f,"closed",["suppressed"])}},debug:()=>[...b.values()].map(t=>({...t,reasons:[...t.reasons]})),stop(){for(let t of _.values())t();_.clear(),Le?.(),De?.(),N.clear(),K.clear(),window[j]===D&&delete window[j]}});window[j]=D;for(let{slot:t,resolve:u}of window[it]?.splice(0)??[])u(D.open(t));return w&&console.table?.(D.debug()),D}window[Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.module")]={startOnsite:Pe};})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thg-agentic/hyper-personalisation-web",
3
- "version": "3.25.0",
3
+ "version": "3.26.0",
4
4
  "description": "Browser SDK for the THG Hyper-Personalisation event specification: event tracking from a write key and remote settings, strict CMP-agnostic consent, a GA4 dataLayer bridge and in-session audience evaluation. Dependency-free ESM on the Segment wire protocol, a CDN script (dist/hp.min.js), and an optional @segment/analytics-next plugin path.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -60,7 +60,8 @@
60
60
  "dist/onsite.min.js",
61
61
  "dist/onsite-render.min.js",
62
62
  "dist/onsite-wheel.min.js",
63
- "dist/onsite-answers.min.js"
63
+ "dist/onsite-answers.min.js",
64
+ "dist/onsite-audiences.min.js"
64
65
  ],
65
66
  "sideEffects": false,
66
67
  "license": "MIT",
@@ -90,7 +91,7 @@
90
91
  "esbuild": "^0.28.2",
91
92
  "jsdom": "^30.1.1",
92
93
  "typescript": "^7.0.2",
93
- "@thg-agentic/hyper-personalisation-spec": "1.18.0"
94
+ "@thg-agentic/hyper-personalisation-spec": "1.20.0"
94
95
  },
95
96
  "scripts": {
96
97
  "test": "node --test tests/*.test.mjs",
package/src/bootstrap.js CHANGED
@@ -57,7 +57,7 @@ import {
57
57
  readSettings,
58
58
  resolveApiHost,
59
59
  } from './settings.js';
60
- import { realId, uuid } from './shape.js';
60
+ import { realId, tokenOf, uuid } from './shape.js';
61
61
  import {
62
62
  configureStorageNames,
63
63
  migrateLegacyStorage,
@@ -195,8 +195,35 @@ function consentAdapter(consent, settings, preset) {
195
195
  return reportingPurposes(factory(options), settings.consentPurposes);
196
196
  }
197
197
 
198
- /** Who an identify named, as the session remembers it: `userId|email_sha256`. */
199
- const identifyMarker = (userId, email) => `${userId ?? ''}|${email ?? ''}`;
198
+ /**
199
+ * Who an identify named, as the session remembers it: `userId|email_sha256`, then `|v` once one for
200
+ * them carried an identity token (ADR 0067).
201
+ */
202
+ const identifyMarker = (userId, email, verified) =>
203
+ `${userId ?? ''}|${email ?? ''}${verified ? '|v' : ''}`;
204
+
205
+ /**
206
+ * Whether the session already sent this identify: for the same person, and verified, or not and
207
+ * this one has no token either. So a token is sent once, when it first appears for them, and a page
208
+ * without one (served from a shared cache) never sends them again.
209
+ */
210
+ const identifiedAlready = (stored, userId, email, verified) =>
211
+ stored === identifyMarker(userId, email, true) ||
212
+ (!verified && stored === identifyMarker(userId, email, false));
213
+
214
+ const withoutToken = (event) => {
215
+ if (event.context?.identity_token === undefined) return event;
216
+ const { identity_token: _, ...context } = event.context;
217
+ return { ...event, context };
218
+ };
219
+
220
+ const readIdentified = (key) => {
221
+ try {
222
+ return sessionStorage.getItem(key);
223
+ } catch {
224
+ return null;
225
+ }
226
+ };
200
227
 
201
228
  /** The traits to identify with on this page, or null when this session already identified them. */
202
229
  function pendingIdentify(propertyId, identity) {
@@ -204,13 +231,19 @@ function pendingIdentify(propertyId, identity) {
204
231
  const email = normaliseSha256(identity?.emailSha256);
205
232
  if (!userId && !email) return null;
206
233
 
207
- try {
208
- const key = storageKey(storageName('identified'), propertyId);
209
- if (sessionStorage.getItem(key) === identifyMarker(userId, email))
210
- return null;
211
- } catch {
212
- /* no session storage: identify on every page rather than never */
213
- }
234
+ // No session storage: identify on every page rather than never.
235
+ const stored = readIdentified(
236
+ storageKey(storageName('identified'), propertyId),
237
+ );
238
+ if (
239
+ identifiedAlready(
240
+ stored,
241
+ userId,
242
+ email,
243
+ userId !== null && tokenOf(identity?.token) !== null,
244
+ )
245
+ )
246
+ return null;
214
247
  return {
215
248
  ...(userId ? { userId } : {}),
216
249
  ...(email ? { email_sha256: email } : {}),
@@ -465,6 +498,7 @@ async function start(config, options, carry) {
465
498
  : undefined,
466
499
  // Every page carries the signed-in user; only the identify itself is once per session.
467
500
  getUserId: () => userId,
501
+ identityToken: identity?.token,
468
502
  beforeSend: options.beforeSend,
469
503
  ...options.extend,
470
504
  onConsentStatus(status) {
@@ -489,20 +523,22 @@ async function start(config, options, carry) {
489
523
  // arrives later in the session is still identified. Any identify counts, including one the
490
524
  // page sends itself at sign-in, so the next page of the session does not repeat it.
491
525
  if (event.type === 'identify') {
492
- const marker = identifyMarker(
493
- realId(event.userId),
494
- normaliseSha256(event.traits?.email_sha256),
495
- );
526
+ const key = storageKey(storageName('identified'), propertyId);
527
+ const user = realId(event.userId);
528
+ const email = normaliseSha256(event.traits?.email_sha256);
529
+ // One without a token never unsays an earlier verified one for the same person.
530
+ const verified =
531
+ Boolean(event.context?.identity_token) ||
532
+ readIdentified(key) === identifyMarker(user, email, true);
496
533
  try {
497
- sessionStorage.setItem(
498
- storageKey(storageName('identified'), propertyId),
499
- marker,
500
- );
534
+ sessionStorage.setItem(key, identifyMarker(user, email, verified));
501
535
  } catch {
502
536
  /* identify again next page */
503
537
  }
504
538
  }
505
- options.extend?.onEvent?.(event);
539
+ // The observer passed to bootstrap never sees the token: it vouches for the shopper until
540
+ // it expires. A host's own beforeSend sees the event as sent.
541
+ options.extend?.onEvent?.(withoutToken(event));
506
542
  },
507
543
  });
508
544
 
package/src/index.js CHANGED
@@ -50,6 +50,7 @@ import {
50
50
  getCookie,
51
51
  localeTag,
52
52
  perRequest,
53
+ readCampaign,
53
54
  scrubHref,
54
55
  } from './context.js';
55
56
  import { createDecisionMemory, servedDecisions } from './decisions.js';
@@ -82,6 +83,7 @@ import {
82
83
  PAGE_TYPES,
83
84
  pruneProperties,
84
85
  realId,
86
+ tokenOf,
85
87
  uuid,
86
88
  } from './shape.js';
87
89
  import {
@@ -96,6 +98,12 @@ import {
96
98
  byteLength as utf8Bytes,
97
99
  } from './transport.js';
98
100
  import { LIB, VERSION } from './version.js';
101
+ import {
102
+ clearVisitCampaign,
103
+ keepVisitCampaign,
104
+ readVisitCampaign,
105
+ visitCampaign,
106
+ } from './visit-campaign.js';
99
107
 
100
108
  /** The surfaces a `Personalisation Exposed` names, as the public API's exposures do. */
101
109
  const EXPOSURE_SURFACES = new Set([
@@ -426,6 +434,28 @@ export function createAnalytics(options) {
426
434
  storageName('preview'),
427
435
  cfg.consentCookieDomain ?? null,
428
436
  );
437
+ /** The session kept on the device (the host's, or the SDK's cookie); null while in memory only. */
438
+ const keptSession = () =>
439
+ realId(perRequest(hostSession, null)) ?? getCookie(storageName('session'));
440
+ /**
441
+ * The tags the page loaded with, read now so a later `replaceState` cannot take them away, and
442
+ * the visit's campaign kept from them when the visit has none (visit-campaign.js).
443
+ */
444
+ const landingCampaign = visitCampaign(
445
+ typeof location === 'undefined' ? null : readCampaign(location.search),
446
+ );
447
+ /**
448
+ * A page or an event of the visit, as it is collected whatever consent will say of sending it: the
449
+ * visit's campaign lasts as its session does. A trader's preview is not a shopper's visit: it
450
+ * reads its own URL's tags and keeps none.
451
+ */
452
+ const keepCampaign = (landing = null) => {
453
+ if (!previewing)
454
+ keepVisitCampaign(cfg.propertyId, landing, {
455
+ sessionId: keptSession(),
456
+ keepSession: granted(),
457
+ });
458
+ };
429
459
 
430
460
  /** Delivery problems, logged with `debug`. */
431
461
  const reportError = (message, err) =>
@@ -489,6 +519,12 @@ export function createAnalytics(options) {
489
519
  let identifiedUserId = null;
490
520
  /** The user bootstrap's `identity` option named, only to warn when the host names another form. */
491
521
  let optionsUserId = null;
522
+ /**
523
+ * The signed-in user's identity token (ADR 0067), the one copy of it: from the `identityToken`
524
+ * option for the user `getUserId` named, then whatever `identify` passes for its user. Another
525
+ * user, `reset()` or a sign-out clears it, so nobody else's token outlives their sign-in.
526
+ */
527
+ let identityToken = userId ? tokenOf(cfg.identityToken) : null;
492
528
 
493
529
  /** The call being replayed: its first event keeps the messageId and time it was made with. */
494
530
  let replaying = null;
@@ -521,6 +557,7 @@ export function createAnalytics(options) {
521
557
  /** Tracking never throws into the host: an event that fails to build or deliver is dropped. */
522
558
  function emit(partial, ctxOverrides, force = false) {
523
559
  noteBasket(partial);
560
+ keepCampaign();
524
561
  try {
525
562
  return compose(partial, ctxOverrides, force);
526
563
  } catch (err) {
@@ -665,6 +702,7 @@ export function createAnalytics(options) {
665
702
  exposedTokens.clear();
666
703
  device?.forget();
667
704
  forgetKeptVisit(true);
705
+ clearVisitCampaign();
668
706
  }
669
707
 
670
708
  function deliver(event, force) {
@@ -701,6 +739,8 @@ export function createAnalytics(options) {
701
739
  };
702
740
  };
703
741
 
742
+ // Before the gate starts, so a withdrawal it finds on this page clears the landing tags too.
743
+ keepCampaign(landingCampaign);
704
744
  if (strict) {
705
745
  gate = createConsentGate({
706
746
  adapter: cfg.consent,
@@ -758,7 +798,10 @@ export function createAnalytics(options) {
758
798
  if (state?.personalisation !== true)
759
799
  forgetKeptVisit(previous?.personalisation === true);
760
800
  // Events collected under the grant are not sent after it is withdrawn: only the withdrawal.
761
- if (withdrawal) transport.discardQueued?.();
801
+ if (withdrawal) {
802
+ transport.discardQueued?.();
803
+ clearVisitCampaign();
804
+ }
762
805
  emit(
763
806
  {
764
807
  type: 'track',
@@ -772,6 +815,8 @@ export function createAnalytics(options) {
772
815
  },
773
816
  });
774
817
  gate.start();
818
+ // Only what survived the gate: a visitor already granted keeps the session id with it.
819
+ keepCampaign();
775
820
  }
776
821
 
777
822
  /** The property's holdout split from the settings, as a serving response would state it. */
@@ -859,6 +904,7 @@ export function createAnalytics(options) {
859
904
  userId = null;
860
905
  identifiedUserId = null;
861
906
  optionsUserId = null;
907
+ identityToken = null;
862
908
  return event;
863
909
  }
864
910
 
@@ -903,8 +949,17 @@ export function createAnalytics(options) {
903
949
  identify(traits, ctx, source) {
904
950
  const { userId: id, ...rest } =
905
951
  traits && typeof traits === 'object' ? traits : {};
952
+ // The token the site's server signed for this user (ADR 0067): without it the identity graph
953
+ // records the sign-in and never joins this device to the user's others.
954
+ const passed = tokenOf(contextOverrides(ctx)?.identity_token);
906
955
  if (id !== undefined) {
907
956
  const next = realId(id);
957
+ // Another user's sign-in brings its own token or none; the same user's keeps the last.
958
+ identityToken = !next
959
+ ? null
960
+ : next === userId
961
+ ? (passed ?? identityToken)
962
+ : passed;
908
963
  if (source === IDENTITY_OPTION) {
909
964
  optionsUserId = next;
910
965
  } else if (identifiedUserId && next && next !== identifiedUserId) {
@@ -924,10 +979,12 @@ export function createAnalytics(options) {
924
979
  }
925
980
  userId = next;
926
981
  if (next && source !== IDENTITY_OPTION) identifiedUserId = next;
927
- }
982
+ } else if (passed && userId) identityToken = passed;
983
+ // Only the current user's token is sent: one passed with nobody to keep it for goes nowhere.
984
+ const { identity_token: _, ...context } = contextOverrides(ctx) ?? {};
928
985
  return emit(
929
986
  { type: 'identify', traits: identifyTraits(rest, cfg.debug) },
930
- ctx,
987
+ identityToken ? { ...context, identity_token: identityToken } : context,
931
988
  );
932
989
  },
933
990
 
@@ -941,6 +998,7 @@ export function createAnalytics(options) {
941
998
  userId = null;
942
999
  identifiedUserId = null;
943
1000
  optionsUserId = null;
1001
+ identityToken = null;
944
1002
  writeLastPageMessageId('');
945
1003
  },
946
1004
 
@@ -1120,6 +1178,8 @@ export function createAnalytics(options) {
1120
1178
  preview: previewing,
1121
1179
  anonymousId: () => realId(perRequest(cfg.getAnonymousId, null)),
1122
1180
  sessionId: () => realId(perRequest(cfg.getSessionId, null)),
1181
+ // Only where it is used: a reminder's code is answered with personalisation granted.
1182
+ identityToken: () => (personalisationGranted() ? identityToken : null),
1123
1183
  analytics: granted,
1124
1184
  personalisation: personalisationGranted,
1125
1185
  consent: () => cfg.getConsent(),
@@ -1129,6 +1189,11 @@ export function createAnalytics(options) {
1129
1189
  ? null
1130
1190
  : scrubHref(location.href, cfg),
1131
1191
  locale: () => localeTag(perRequest(cfg.getLocale, cfg.locale)),
1192
+ /** The visit's campaign for "arrived from"; a preview's is its own URL's. */
1193
+ campaign: () =>
1194
+ previewing
1195
+ ? landingCampaign
1196
+ : readVisitCampaign(cfg.propertyId, { sessionId: keptSession() }),
1132
1197
  /**
1133
1198
  * A basket bar's progress: the basket this page reported, else the last one this visit
1134
1199
  * kept (under personalisation consent), else null.
@@ -1137,6 +1202,12 @@ export function createAnalytics(options) {
1137
1202
  const value = getSessionSignals().basketValue;
1138
1203
  return pageBasket ?? (Number.isFinite(value) ? value : null);
1139
1204
  },
1205
+ /** This visit's session signals, kept only under personalisation consent; else null. */
1206
+ sessionSignals: () => {
1207
+ if (!personalisationGranted()) return null;
1208
+ scopeVisit();
1209
+ return getSessionSignals();
1210
+ },
1140
1211
  /** Calls `listener` whenever the page reports its basket; answers how to stop. */
1141
1212
  onBasket: (listener) => {
1142
1213
  basketListeners.add(listener);