<!-- 2026-09-23T11:44:35.2699618Z -->
<style>.shoplift-hide { opacity: 0 !important; }</style>
<style id="sl-preview-bar-hide">#preview-bar-iframe, #PBarNextFrameWrapper { display: none !important; }</style>
<script type="text/javascript">(function(rootPath, template, themeRole, themeId, isThemePreview){ /* Generated on 2026-10-06T19:45:04.1689954Z */(function(){"use strict";var se=document.createElement("style");se.textContent=`#shoplift-preview-control{position:fixed;max-width:332px;height:56px;background-color:#141414;z-index:9999;bottom:20px;display:flex;border-radius:8px;box-shadow:13px 22px 7px #0000,9px 14px 7px #00000003,5px 8px 6px #0000000d,2px 4px 4px #00000017,1px 1px 2px #0000001a,0 0 #0000001a;align-items:center;margin:0 auto;left:16px;right:16px;opacity:0;transform:translateY(20px);visibility:hidden;transition:opacity .4s ease-in-out,transform .4s ease-in-out,visibility 0s .4s}#shoplift-preview-control.visible{opacity:1;transform:translateY(0);visibility:visible;transition:opacity .4s ease-in-out,transform .4s ease-in-out,visibility 0s 0s}#shoplift-preview-control *{font-family:Inter,sans-serif;color:#fff;box-sizing:border-box;font-size:16px}#shoplift-preview-variant-title{font-weight:400;line-height:140%;font-size:16px;text-align:start;letter-spacing:-.16px;flex-grow:1;text-wrap:nowrap;overflow:hidden;text-overflow:ellipsis}#shoplift-preview-variant-selector{position:relative;display:block;padding:6px 0;height:100%;min-width:0;flex:1 1 auto}#shoplift-preview-variant-menu-trigger{border:none;cursor:pointer;width:100%;background-color:transparent;padding:0 16px;border-left:1px solid #333;border-right:1px solid #333;height:100%;display:flex;align-items:center;justify-content:start;gap:8px}#shoplift-preview-variant-selector .menu-variant-label{width:24px;height:24px;border-radius:50%;padding:6px;display:flex;justify-content:center;align-items:center;font-size:12px;font-style:normal;font-weight:600;line-height:100%;letter-spacing:-.12px;flex-shrink:0}#shoplift-preview-variant-selector .preview-variant-menu{position:absolute;bottom:110%;transform:translate3d(0,20px,0);visibility:hidden;pointer-events:none;opacity:0;cursor:pointer;background-color:#141414;border:1px solid #141414;border-radius:6px;width:100%;max-height:156px;overflow-y:auto;box-shadow:0 8px 16px #0003;z-index:1;transition:opacity .3s ease-in-out,transform .3s ease-in-out,visibility 0s .3s}#shoplift-preview-variant-selector .preview-variant-menu.preview-variant-menu__visible{visibility:visible;pointer-events:auto;opacity:100;transform:translateZ(0);transition:opacity .3s ease-in-out,transform .3s ease-in-out,visibility 0s 0s}@media screen and (max-width:400px){#shoplift-preview-variant-selector .preview-variant-menu{position:fixed;left:0;right:0;width:auto;bottom:110%}}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item{padding:12px 16px;display:flex;overflow:hidden}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item .menu-variant-label{margin-right:6px}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item span{overflow:hidden;text-overflow:ellipsis;text-wrap:nowrap;white-space:nowrap;color:#f6f6f6;font-size:14px;font-style:normal;font-weight:500}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item:hover{background-color:#545454}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item:last-of-type{border-bottom-left-radius:6px;border-bottom-right-radius:6px}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item:first-of-type{border-top-left-radius:6px;border-top-right-radius:6px}#shoplift-preview-control div:has(#shoplift-exit-preview-button){padding:0 16px}#shoplift-exit-preview-button{padding:6px 8px;font-weight:500;line-height:75%;border-radius:4px;background-color:transparent;border:none;text-decoration:none}#shoplift-exit-preview-button:hover{cursor:pointer;background-color:#333}#shoplift-preview-subscription-warning{position:relative;display:flex;align-items:center;gap:6px;padding:6px 10px;margin:0 4px;border-left:1px solid #333;cursor:help;outline:none}#shoplift-preview-subscription-warning__icon{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;background-color:#f59e0b;color:#141414!important;font-weight:700;font-size:12px!important;line-height:1;flex-shrink:0}#shoplift-preview-subscription-warning__label{font-size:13px!important;font-weight:500;color:#fbbf24!important;text-wrap:nowrap;white-space:nowrap}#shoplift-preview-subscription-warning__tooltip{position:absolute;bottom:calc(100% + 8px);right:0;max-width:320px;width:max-content;padding:10px 12px;border-radius:6px;background-color:#1f1f1f;color:#fff!important;font-size:12px!important;line-height:1.4!important;box-shadow:0 8px 16px #0000004d;z-index:10000;opacity:0;visibility:hidden;transform:translateY(4px);transition:opacity .2s ease-in-out,transform .2s ease-in-out,visibility 0s .2s;pointer-events:none}#shoplift-preview-subscription-warning__tooltip.shoplift-preview-subscription-warning__tooltip--visible{opacity:1;visibility:visible;transform:translateY(0);transition:opacity .2s ease-in-out,transform .2s ease-in-out,visibility 0s 0s}#shoplift-preview-subscription-warning:focus-visible{box-shadow:inset 0 0 0 2px #f59e0b;border-radius:4px}#shoplift-preview-control:has(#shoplift-preview-subscription-warning){max-width:480px}/*$vite$:1*/`,document.head.appendChild(se);var ge=" daum[ /]| deusu/|(?:^|[^g])news(?!sapphire)|(?<! channel/|google/)google(?!(?:wv|app|/google| pixel))|(?<! cu)bots?(?:\\b|_)|(?<!cam)scan|(?<!lib)http|24x7|;\\s\\w+;$|@[a-z][\\w-]+\\.|\\(\\)|\\.com\\b|\\b\\w+/1\\.0;|\\bbw/|\\bdlc\\b|\\bort/|\\bperl\\b|\\btime/|\\||^[<\\(;]|^[\\w \\.\\-\\(?:\\):%]+(?:/v?\\d+(?:\\.\\d+)?(?:\\.\\d{1,10})*?)?(?:,|$)|^[\\w\\-]+/[\\w]+$|^[^ ]{50,}$|^\\d+\\b|^\\w*search\\b|^\\w+/[\\w\\(\\)]*$|^\\w+/\\d\\.\\d\\s\\([\\w@]+\\)$|^active|^ad muncher|^amaya|^apache/|^avsdevicesdk/|^azure|^biglotron|^blackbox exporter|^bot|^clamav[ /]|^claude-code/|^client/|^cobweb/|^custom|^ddg[_-]android|^discourse|^dispatch/\\d|^downcast/|^duckduckgo|^email|^exodusmovement|^facebook|^getright/|^gozilla/|^hobbit|^hotzonu|^hwcdn/|^igetter/|^jeode/|^jetty/|^jigsaw|^microsoft bits|^movabletype|^mozilla/\\d\\.\\d\\s[\\w\\.-]+$|^mozilla/\\d\\.\\d\\s\\((?:compatible;)?(?:\\s?[\\w\\d-.]+\\/\\d+\\.\\d+)?\\)$|^navermailapp|^netsurf|^offline|^openai/|^owler|^php|^postman|^ps_daily/|^python|^rank|^read|^reed|^remove\\.bg/|^rest|^rss|^snapchat|^sora |^space bison|^stape/|^svn|^swcd |^taringa|^thumbor/|^track|^w3c|^webbandit/|^webcopier|^wget|^whatsapp|^wordpress|^xenu link sleuth|^yahoo|^yandex|^zdm/\\d|^zoom marketplace/|abuse|advisor|agent\\b|analyzer|archive|ask jeeves/teoma|attracta|audit|bluecoat drtr|browsex|burpcollaborator|capture|catch|check\\b|checker|chrome-lighthouse|chromeframe|classifier|cloudflare|collapsify\\b|convertify|cookiehubverify/|crawl|cursor/|cypress/|dareboost|datanyze|dejaclick|detect|discovery|dmbrowser|download|exaleadcloudview|feed|firephp|foregenix|functionize|grab|hardenize\\b|headless|hotjar|httrack|hubspot marketing grader|ibisbrowser|infrawatch|insight|inspect|iplabel|java(?!;)|library|linkcheck|linktiger|mail\\.ru/|manager|manus-user/|marketgoo/|measure|monitor\\b|neustar wpm|node\\b|nutch|offbyone|openvas|optimize|pageburst|pagespeed|parser|phantomjs|pingdom|playwright|powermarks|preview|productfinder|prospectingstudio|proxy|ptst[ /]\\d|radar|readable/|retriever|rexx;|rigor|rss\\b|scrape|securityheaders|selenium|server|silktide|sindup/|sogou|sparkler/|speedcurve|spider|splash|statuscake|supercleaner|synapse|synthetic|testlocally|tools|torrent|transcoder|url|validator|virtuoso|wappalyzer|watchtowr|webglance|webkit2png|whatcms/|xtate/",me=/bot|crawl|http|lighthouse|scan|search|spider/i,z;function ye(){if(z instanceof RegExp)return z;try{z=new RegExp(ge,"i")}catch{z=me}return z}var ve=a=>typeof a=="string"&&a!=="";function we(a){return ve(a)&&ye().test(a)}var be=we;class ee{timestamp;constructor(){this.timestamp=new Date}}class Se extends ee{type;testId;hypothesisId;constructor(e,t,i){super(),this.type=3,this.testId=e,this.hypothesisId=t,this.timestamp=i}}class Ce extends ee{type;path;constructor(e){super(),this.type=4,this.path=e}}class Te extends ee{type;cart;constructor(e){super(),this.type=5,this.cart=e}}class G extends Error{isBot;constructor(){super(),this.isBot=!0}}function Ie(a,e,t){for(const i of e.selectors){const s=a.querySelectorAll(i.cssSelector);for(let r=0;r<s.length;r++)t(e.testId,e.hypothesisId)}ne(a,e,(i,s,r,n,o)=>o(s,r),t)}function U(a,e,t){for(const i of e.selectors)oe(a,e.testId,e.hypothesisId,i,t??(()=>{}));ne(a,e,oe,t??(()=>{}))}function re(a){return a.urlPatterns.reduce((e,t)=>{switch(t.operator){case"contains":return e+`.*${t}.*`;case"endsWith":return e+`.*${t}`;case"startsWith":return e+`${t}.*`}},"")}function ne(a,e,t,i){new MutationObserver(()=>{for(const r of e.selectors)t(a,e.testId,e.hypothesisId,r,i)}).observe(a.documentElement,{childList:!0,subtree:!0})}function oe(a,e,t,i,s){const r=a.querySelectorAll(i.cssSelector);for(let n=0;n<r.length;n++){let o=r.item(n);if(o instanceof HTMLElement&&o.dataset.shoplift!==""){o.dataset.shoplift="";for(const l of i.actions.sort(De))o=Pe(a,i.cssSelector,o,l)}}return r.length>0&&s?(s(e,t),!0):!1}function Pe(a,e,t,i){switch(i.type){case"innerHtml":t.innerHTML=i.value;break;case"attribute":Ae(t,i.scope,i.value);break;case"css":ke(a,e,i.value);break;case"js":Ee(a,t,i);break;case"copy":return xe(t);case"remove":_e(t);break;case"move":Re(t,parseInt(i.value));break}return t}function Ae(a,e,t){a.setAttribute(e,t)}function ke(a,e,t){const i=a.createElement("style");i.innerHTML=`${e} { ${t} }`,a.getElementsByTagName("head")[0]?.appendChild(i)}function Ee(a,e,t){Function("document","element",`"use strict"; ${t.value}`)(a,e)}function xe(a){const e=a.cloneNode(!0);if(!a.parentNode)throw"Can't copy node outside of DOM";return a.parentNode.insertBefore(e,a.nextSibling),e}function _e(a){a.remove()}function Re(a,e){if(e===0)return;const t=Array.prototype.slice.call(a.parentElement.children).indexOf(a),i=Math.min(Math.max(t+e,0),a.parentElement.children.length-1);a.parentElement.children.item(i).insertAdjacentElement(e>0?"afterend":"beforebegin",a)}function De(a,e){return ae(a)-ae(e)}function ae(a){return a.type==="copy"||a.type==="remove"?0:1}const M={Template:0,UrlRedirect:2,Script:3,Price:5},Oe="data:image/svg+xml,%3csvg%20width='12'%20height='12'%20viewBox='0%200%2012%2012'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M9.96001%207.90004C9.86501%207.90004%209.77001%207.86504%209.69501%207.79004L6.43501%204.53004C6.19501%204.29004%205.80501%204.29004%205.56501%204.53004L2.30501%207.79004C2.16001%207.93504%201.92001%207.93504%201.77501%207.79004C1.63001%207.64504%201.63001%207.40504%201.77501%207.26004L5.03501%204.00004C5.56501%203.47004%206.43001%203.47004%206.96501%204.00004L10.225%207.26004C10.37%207.40504%2010.37%207.64504%2010.225%207.79004C10.15%207.86004%2010.055%207.90004%209.96001%207.90004Z'%20fill='white'/%3e%3c/svg%3e",Ve="data:image/svg+xml,%3csvg%20width='14'%20height='24'%20viewBox='0%200%2014%2024'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M12.3976%2014.5255C12.2833%2013.8788%2012.0498%2013.3024%2011.6952%2012.7961C11.3416%2012.2898%2010.9209%2011.8353%2010.4353%2011.4317C9.94868%2011.0291%209.43546%2010.6488%208.89565%2010.292C8.48487%2010.049%208.09577%209.78565%207.72637%209.50402C7.35697%209.2224%207.08016%208.89503%206.89694%208.51987C6.71273%208.14471%206.67826%207.69533%206.79055%207.1697C6.86345%206.83216%206.97476%206.54647%207.12351%206.31162C7.27324%206.07778%207.47124%205.89986%207.7175%205.77684C7.96377%205.65483%208.21989%205.59383%208.48389%205.59383C8.88087%205.59383%209.17639%205.7016%209.3734%205.91714C9.56943%206.13268%209.68271%206.42345%209.71424%206.78946C9.74576%207.15547%209.72015%207.55401%209.63839%207.98509C9.55663%208.41617%209.43645%208.84724%209.27687%209.27934L13.5127%208.80149C13.9638%207.52656%2014.1017%206.42447%2013.9264%205.49725C13.751%204.56901%2013.2664%203.85122%2012.4724%203.34491C12.239%203.19648%2011.9779%203.07041%2011.6893%202.96569L12.0026%201.50979L9.86397%200L7.3875%201.50979L7.11169%202.78878C6.65166%202.8874%206.21724%203.01957%205.8114%203.19038C4.85292%203.594%204.06684%204.15115%203.45117%204.86385C2.83452%205.57655%202.42571%206.40108%202.22378%207.33847C2.06616%208.06947%202.04942%208.70796%202.17551%209.25087C2.30061%209.7948%202.52028%2010.2828%202.8355%2010.7139C3.14974%2011.145%203.51816%2011.5344%203.93977%2011.881C4.36039%2012.2288%204.782%2012.5521%205.20164%2012.851C5.68334%2013.1702%206.13844%2013.5169%206.56497%2013.8921C6.99052%2014.2672%207.31954%2014.7125%207.55004%2015.228C7.78055%2015.7445%207.81502%2016.3769%207.65347%2017.1262C7.56482%2017.5389%207.43676%2017.8765%207.27028%2018.1388C7.10381%2018.4011%206.89596%2018.5983%206.64772%2018.7295C6.3985%2018.8606%206.12071%2018.9267%205.8114%2018.9267C5.21641%2018.9267%204.79776%2018.6034%204.62833%2018.1632C4.4589%2017.7229%204.47367%2017.2583%204.60075%2016.5639C4.72782%2015.8705%205.05092%2015.1395%205.37107%2014.3699H1.17665C1.17665%2014.3699%200.207341%2016.1115%200.0310135%2017.6762C-0.0655232%2018.5302%200.0635208%2019.2653%200.41519%2019.8844C0.76686%2020.5036%201.33032%2020.9814%202.10655%2021.319C2.39222%2021.443%202.7104%2021.5447%203.05813%2021.623L2.54589%2024H7.17473L7.7047%2021.5386C8.08493%2021.442%208.43857%2021.3231%208.76562%2021.1787C9.73985%2020.7476%2010.52%2020.1427%2011.1071%2019.3649C11.6932%2018.5871%2012.0873%2017.7291%2012.2892%2016.7917C12.4744%2015.9295%2012.5099%2015.1741%2012.3966%2014.5275L12.3976%2014.5255Z'%20fill='white'/%3e%3c/svg%3e";async function Le(a){let e=a.replace(/-/g,"+").replace(/_/g,"/");for(;e.length%4;)e+="=";const t=atob(e),i=Uint8Array.from(t,n=>n.charCodeAt(0)),s=new Blob([i]).stream().pipeThrough(new DecompressionStream("gzip")),r=await new Response(s).text();return JSON.parse(r)}function F(a,e){return typeof e=="string"&&/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+(?:Z|[+-]\d+)/.test(e)?new Date(e):e}function te(a,e){return e}function q(a,e=!1,t=!1,i=","){const s=a/100;if(t){const n=Math.round(s).toLocaleString("en-US");return i!==","?n.replace(/,/g,i):n}else{const r=e?",":".",n=s.toFixed(2).split("."),o=parseInt(n[0],10),l=n[1]??"00",c=o.toLocaleString("en-US");return i!==","?`${c.replace(/,/g,i)}${r}${l}`:e?`${c.replace(/,/g,".")}${r}${l}`:`${c}${r}${l}`}}function H(a,e,t,i){const s=e.replace("{{amount}}",q(a,!1,!1)).replace("{{amount_no_decimals}}",q(a,!1,!0)).replace("{{amount_with_comma_separator}}",q(a,!0,!1)).replace("{{amount_no_decimals_with_comma_separator}}",q(a,!0,!0)).replace("{{amount_with_space_separator}}",q(a,!1,!1," ")).replace("{{amount_no_decimals_with_space_separator}}",q(a,!1,!0," ")).replace("{{amount_with_apostrophe_separator}}",q(a,!1,!1,"'")).replace("{{amount_no_decimals_with_apostrophe_separator}}",q(a,!1,!0,"'")).replace("{{amount_with_period_and_space_separator}}",q(a,!1,!1,". ")).replace("{{amount_no_decimals_with_period_and_space_separator}}",q(a,!1,!0,". "));return i?`${s} ${t}`:s}function le(a){return a.replace(/[^\d.,\s-]/g,"").trim()}function j(a){const e=new Map;for(const[t,i,s]of a.variants)e.set(t,{priceInCents:i,compareAtPriceInCents:s});return e}function $e(a,e,t,i){const{priceInCents:s,compareAtPriceInCents:r}=t,{moneyFormat:n,currency:o,currencyCodeEnabled:l}=i;if(a.getAttribute("data-sl-attribute-p")===e)a.innerHTML=H(s,n,o,l);else if(a.getAttribute("data-sl-attribute-cap")===e)r<=0||r<=s?a.remove():a.innerHTML=H(r,n,o,l);else if(a.getAttribute("data-sl-attribute-discount")===e&&!(r<=0||r<=s)){const d=Math.round((r-s)/r*100),p=le(H(r-s,n,o,!1)),h=a.getAttribute("data-sl-format")||"percent";h==="percent"?a.textContent=`-${d}%`:h==="amount"?a.textContent=`-${p}`:h==="both"&&(a.textContent=`-${d}% (-${p})`)}}function Me(a){const e=[],t={id:"url-pattern",operator:"contains",value:"/"};for(const[i,s,r]of a.variants){e.push({id:`p-${i}`,cssSelector:`[data-sl-attribute-p="${i}"]`,urlPatterns:[t],actions:[{id:`p-action-${i}`,type:"innerHtml",scope:"price",value:H(s,a.moneyFormat,a.currency,a.currencyCodeEnabled)}]});const n=r<=0||r<=s;if(e.push({id:`cap-${i}`,cssSelector:`[data-sl-attribute-cap="${i}"]`,urlPatterns:[t],actions:[{id:`cap-action-${i}`,type:n?"remove":"innerHtml",scope:"compare-at-price",value:n?"":H(r,a.moneyFormat,a.currency,a.currencyCodeEnabled)}]}),!n&&r>s){const o=Math.round((r-s)/r*100),l=le(H(r-s,a.moneyFormat,a.currency,!1));e.push({id:`d-${i}`,cssSelector:`[data-sl-attribute-discount="${i}"]`,urlPatterns:[t],actions:[{id:`d-action-${i}`,type:"js",scope:null,value:`var format = element.getAttribute('data-sl-format') || 'percent'; if (format === 'percent') { element.textContent = '-${o}%'; } else if (format === 'amount') { element.textContent = '-${l}'; } else if (format === 'both') { element.textContent = '-${o}% (-${l})'; }`}]})}}return e}const qe=a=>{let e=5381;for(let t=0;t<a.length;t++)e=(e*33^a.charCodeAt(t))>>>0;return e.toString(36)},He=()=>Math.random().toString(36).slice(2,10)+Date.now().toString(36).slice(-4),Ne=a=>btoa(JSON.stringify(a)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,""),J=a=>a.replace(/#slr-[a-z0-9]+$/,""),Ue=/^[A-Za-z0-9._=~+/-]{1,256}$/,ie=a=>typeof a=="string"&&Ue.test(a)?a:null,Fe=a=>{if(!a)return null;try{const t=JSON.parse(atob(decodeURIComponent(a)))?.$exchange_id;return typeof t=="string"&&t.length>0?t:null}catch{return null}},rt="modulepreload",nt=function(a){return"/"+a},ot={},Be=function(e,t,i){let s=Promise.resolve();function r(n){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=n,window.dispatchEvent(o),!o.defaultPrevented)throw n}return s.then(n=>{for(const o of n||[])o.status==="rejected"&&r(o.reason);return e().catch(r)})};function ce(a,e,t){const i=t?a.plans.filter(c=>!c.variantId||c.variantId===t):a.plans,s=[],r=[];for(const c of i)c.direction==="decrease"?(s.push(c.existingShopifyPlanId),r.push(c.createdShopifyPlanId)):(s.push(c.createdShopifyPlanId),r.push(c.existingShopifyPlanId));const n=e?s:r,o=e?r:s;if(t)for(const c of a.plans)for(const d of[c.existingShopifyPlanId,c.createdShopifyPlanId])d&&!n.includes(d)&&!o.includes(d)&&o.push(d);const l={};for(let c=0;c<o.length;c++){const d=o[c],p=n[c];d&&p&&(l[d]=p)}return{showPlanIds:n,hidePlanIds:o,swapMap:l}}function de(a,e,t){const i=e?a.plans.find(r=>r.variantId===e):void 0;if(i)return i.direction;if(t){const r=a.plans.find(n=>n.productId===t);if(r)return r.direction}return a.plans.find(r=>!r.variantId)?.direction??null}function Y(a,e){const t=e?a.plans.filter(r=>!r.productId||r.productId===e):a.plans,i={};for(const r of t)i[r.existingShopifyPlanId]=r.existingDiscountAmount,i[r.createdShopifyPlanId]=r.existingDiscountAmount;const s=Math.max(...Object.values(i),0);return{discountMap:i,maxDiscount:s}}function W(a){const e=document.querySelector('form[action*="/cart/add"] input[name="product-id"]')?.value;if(e)return e;if(a){for(const r of Array.from(document.querySelectorAll("[data-sl-attribute-p]"))){const n=r.getAttribute("data-sl-attribute-p");if(!n)continue;const o=a.variants.find(l=>l[0]===n);if(o?.[3])return o[3]}const s=document.querySelector('form[action*="/cart/add"] input[name="id"]')?.value;if(s){const r=a.variants.find(n=>n[0]===s);if(r?.[3])return r[3]}}const t=window,i=t.ShopifyAnalytics?.meta?.product?.id??t.meta?.product?.id;return i!=null?String(i):null}function D(a,e){return a.widget.selectors[e]??[]}function N(a,e){return a.replace(/[\d.]+%/,`${e}%`)}function $(a,e){const t=document.createTreeWalker(a,NodeFilter.SHOW_TEXT);let i=t.nextNode();for(;i;){if(i.nodeValue!==null){const s=e(i.nodeValue);if(s!==i.nodeValue){i.nodeValue=s;return}}i=t.nextNode()}}function pe(a,e){return a===null?!1:a==="decrease"?!e:e}async function ze(a){if(a.subscriptionSwapDone)return;const e=a.getActiveAssignment();if(!e)return;const t=a.getHypothesis(e.hypothesisId);if(!t?.subscriptionData)return;a.subscriptionSwapDone=!0;const i=t.subscriptionData,s=t.isControl,r=[...new Set(i.plans.map(d=>d.direction))].join(",");a.log(`[SUB-SWAP] ${s?"A":"B"} side, directions=${r}`);const n=i.plans.some(d=>d.variantId);let o=!1,l=!1;function c(){if(!l){l=!0;try{const d=n?document.querySelector("select[name='id'], input[name='id']")?.value:void 0,{showPlanIds:p,hidePlanIds:h,swapMap:u}=ce(i,s,d);a.swapMap=u;const b=D(i,"widgetParent"),E=D(i,"subscriptionPlans"),S=D(i,"subscriptionInput");if(!b.length||!E.length||!S.length)return;const C=document.querySelector(b[0].selector);if(!C?.shadowRoot)return;const _=C.shadowRoot.querySelector(E[0].selector);if(!_?.shadowRoot)return;const T=S[0].selector;let m=null;if(i.widget.widgetType==="buttons"||i.widget.widgetType==="radio"){const y=Array.from(_.shadowRoot.querySelectorAll(T));if(!y.length)return;for(const v of y){const g=v.closest("label");g&&(p.includes(v.value)?g.style.display="":h.includes(v.value)&&(g.style.display="none"))}const w=y.some(v=>p.includes(v.value)&&v.checked),I=y.some(v=>h.includes(v.value)&&v.checked);if((w||I)&&(o=!1),!w&&!o){o=!0;for(const v of y)if(p.includes(v.value)){v.closest("label")?.click(),v.dispatchEvent(new Event("change",{bubbles:!0}));break}}const f=y.find(v=>v.checked);m=f&&p.includes(f.value)?f.value:p[0]??null}else if(i.widget.widgetType==="dropdown"){const y=_.shadowRoot.querySelector("select");if(!y)return;for(const w of Array.from(y.options))h.includes(w.value)&&(w.style.display="none",w.disabled=!0);if(h.includes(y.value)){const w=Array.from(y.options).find(I=>p.includes(I.value));w&&(y.value=w.value,y.dispatchEvent(new Event("change",{bubbles:!0})))}m=p.includes(y.value)?y.value:p[0]??null}if(m){const y=Array.from(document.querySelectorAll('input[name="selling_plan"]'));for(const w of y)w.value!==m&&(w.value=m)}}finally{l=!1}}}if(a.subscriptionHideWrongPlans=c,a.swapMap=ce(i,s).swapMap,c(),n){const d=document.querySelector("select[name='id'], input[name='id']");d&&d.addEventListener("change",c)}}function B(a){const e=D(a,"widgetParent");return e.length?document.querySelector(e[0].selector)?.shadowRoot??null:null}function Z(a,e){const t=D(a,"subscriptionPlans");return t.length?e.querySelector(t[0].selector)?.shadowRoot??null:null}function X(a,e){const t=new URLSearchParams(window.location.search).get("variant");if(t)return t;{const i=document.querySelector('form[action*="/cart/add"] input[name="id"]')?.value;if(i)return i}return a.size>0?[...a.keys()][0]:void 0}function K(a,e){return H(a,e.moneyFormat,e.currency,e.currencyCodeEnabled)}function We({originalFetch:a,swapMap:e,slptValue:t,getSelectedPlanId:i,log:s}){if(window.fetch.__shoplift_intercepted)return s("[SUB-INTERCEPT] already installed — skipping"),()=>{};function r(o){if(i){const l=i();if(l)return e[l]??l}return e[o]??o}const n=function(o,l){if((typeof o=="string"?o:o instanceof URL?o.href:o.url).includes("/cart/add")&&l?.body)try{if(l.body instanceof FormData){const d=l.body.get("selling_plan");d?l.body.set("selling_plan",r(String(d))):(!d||d==="")&&t&&l.body.set("properties[_slpt]",t)}else if(typeof l.body=="string"){const d=JSON.parse(l.body);if(d.items)for(const p of d.items){const h=String(p.selling_plan??"");h?p.selling_plan=r(h):!p.selling_plan&&t&&(p.properties||(p.properties={}),p.properties._slpt=t)}else if(d.id){const p=String(d.selling_plan??"");p?d.selling_plan=r(p):!d.selling_plan&&t&&(d.properties||(d.properties={}),d.properties._slpt=t)}l.body=JSON.stringify(d)}}catch(d){s("[SUB-INTERCEPT] body parse failed; cart-add proceeds with un-swapped plan",d)}return a.call(window,o,l)};return n.__shoplift_intercepted=!0,window.fetch=n,function(){window.fetch===n&&(window.fetch=a)}}function Ke({log:a}){if(window.fetch.__shoplift_intercepted)return a("[SUB-PREVIEW-BLOCK] already installed — skipping"),()=>{};const e=window.fetch,t=function(i,s){const r=typeof i=="string"?i:i instanceof URL?i.href:i.url;return r.includes("/cart/add")?(a("[SUB-PREVIEW-BLOCK] cart-add blocked in preview mode",{url:r}),Promise.resolve(new Response(JSON.stringify({id:0,properties:{},quantity:0,variant_id:0,key:"preview",title:"Preview — cart-add blocked",price:0,original_price:0,line_price:0,original_line_price:0,total_discount:0,discounts:[],preview:!0}),{status:200,headers:{"Content-Type":"application/json"}}))):e.call(window,i,s)};return t.__shoplift_intercepted=!0,window.fetch=t,function(){window.fetch===t&&(window.fetch=e)}}function ue({data:a,runUpdates:e,debounceMs:t=150}){let i=null;function s(){i&&clearTimeout(i),e(),i=setTimeout(e,t)}let r=null;const n=[],o={childList:!0,subtree:!0,characterData:!0,attributes:!0};function l(h){for(const u of n)u.disconnect();n.length=0;for(const u of Array.from(h.querySelectorAll("*")))if(u.shadowRoot){const b=new MutationObserver(s);b.observe(u.shadowRoot,o),n.push(b)}}function c(){const h=B(a);return h?(r&&r.disconnect(),l(h),r=new MutationObserver(u=>{u.some(b=>b.type==="childList"&&b.addedNodes.length>0)&&l(h),s()}),r.observe(h,o),!0):!1}const d=document.body||document.documentElement,p=new MutationObserver(()=>{c()&&s()});return p.observe(d,{childList:!0,subtree:!0}),c()&&s(),e(),function(){i&&(clearTimeout(i),i=null),p.disconnect(),r&&(r.disconnect(),r=null);for(const u of n)u.disconnect();n.length=0}}async function Ge(a){if(a.subscriptionPriceDone)return;const e=a.getActiveAssignment(),t=e?a.getHypothesis(e.hypothesisId):void 0,i=t?.subscriptionData?null:a.findActiveSubscriptionTestControl(),s=t?.subscriptionData?t:i?.hypothesis;if(!s?.subscriptionData)return;const r=t?.subscriptionData?e.testId:i.testId;a.subscriptionPriceDone=!0;const n=s.subscriptionData,o=s.isControl,l=s.priceData,c=n.widget.widgetType;let d=W(l),p=Y(n,d),h=p.discountMap,u=p.maxDiscount;function b(){const g=W(l);g!==d&&(d=g,p=Y(n,d),h=p.discountMap,u=p.maxDiscount,a.log(`[SUB-PRICE] scope refreshed side=${o?"A":"B"}, currentProductId=${d??"n/a"}, maxDiscount=${u}`))}a.log(`[SUB-PRICE] side=${o?"A":"B"}, currentProductId=${d??"n/a"}, maxDiscount=${u}`),a.updatePriceTestHiddenInputs(r,o?"control":"variant",!1);function E(){if(!l)return null;const g=j(l),P=X(g),A=de(n,P,d);if(!pe(A,o))return null;const k=P?g.get(P):void 0;return k?{formattedVariantPrice:K(k.priceInCents,l),formattedDiscounted:K(k.priceInCents*(1-u/100),l)}:null}We({originalFetch:a.fetch,swapMap:a.swapMap??{},slptValue:a.slptValue??void 0,log:a.log,getSelectedPlanId:()=>{const g=B(n);if(!g)return null;const P=Z(n,g);if(!P)return null;const A=D(n,"subscriptionInput"),k=A.length?A[0].selector:'input[name="rc_plan"]';return P.querySelector(`${k}:checked`)?.value??null}});function S(g){const P=D(n,"subscriptionDiscount");for(const A of P)if(A.selector.includes("badge")||A.selector.includes("__badge")){const k=g.querySelector(A.selector);k?.textContent&&!k.textContent.includes(`${u}%`)&&$(k,x=>N(x,u))}}function C(g){const P=E();if(!P)return;const A=D(n,"subscriptionCompareAt");for(const k of A){const x=g.querySelector(k.selector)||g.querySelector(`[part~="${k.selector}"]`);x?.textContent&&!x.textContent.includes(P.formattedVariantPrice)&&$(x,R=>/\d/.test(R)?P.formattedVariantPrice:R)}}function _(g,P){const A=D(n,"subscriptionCompareAt"),k=P===0?"none":"";for(const x of A){const R=g.querySelector(x.selector)||g.querySelector(`[part~="${x.selector}"]`);R&&(k==="none"?R.style.display!=="none"&&(R.style.display="none"):R.style.display==="none"&&(R.style.display=""))}}function T(g){const P=D(n,"subscriptionInput"),A=P.length?P[0].selector:'input[name="rc_plan"]',k=D(n,"subscriptionPlanDiscount"),x=k.length?k[0].selector:".rc-plans-button__discount";for(const R of Array.from(g.querySelectorAll("label"))){const V=R.querySelector(A),O=R.querySelector(x);if(V&&O){const L=h[V.value];if(L!==void 0){if(L===0)O.style.display!=="none"&&(O.style.display="none");else if(O.style.display==="none"&&(O.style.display=""),O.textContent){const Q=O.textContent.match(/[\d.]+%/)?.[0];Q&&Q!==`${L}%`&&$(O,st=>N(st,L))}}}}}function m(g){const P=g.querySelector("select");if(P)for(const A of Array.from(P.options)){const k=h[A.value];if(k!==void 0&&A.textContent){const x=A.textContent.match(/[\d.]+%/)?.[0];x&&x!==`${k}%`&&(A.textContent=N(A.textContent,k))}}}function y(g,P){const k=D(n,"subscriptionDiscount").filter(x=>x.selector.includes("benefit")||x.selector==="rc-benefits");for(const x of k){const R=g.querySelector(x.selector);if(R?.shadowRoot){for(const V of Array.from(R.shadowRoot.querySelectorAll("li")))if(V.textContent?.includes("Save")){const O=V;if(P===0)O.style.display!=="none"&&(O.style.display="none");else{O.style.display==="none"&&(O.style.display="");const L=V.textContent.match(/[\d.]+%/)?.[0];L&&L!==`${P}%`&&$(V,Q=>N(Q,P))}}}}}let w=!1;function I(){if(!w){w=!0;try{if(b(),d!==null&&Object.keys(h).length===0)return;const g=B(n);if(!g)return;S(g),l&&C(g);const P=Z(n,g);let A=u;if(P){const k=D(n,"subscriptionInput"),x=k.length?k[0].selector:'input[name="rc_plan"]',R=P.querySelector(`${x}:checked`);if(R){const V=h[R.value];V!==void 0&&(A=V)}c==="buttons"||c==="radio"?T(P):m(P)}_(g,A),y(g,A)}finally{w=!1}}}function f(){const g=E();if(!g)return;const P=B(n);if(!P)return;const A=D(n,"onetimeToggle"),k=A.length?A[0].selector:'input[value="onetime"]';if(!P.querySelector(k)?.checked)return;const R=D(n,"subscriptionPrice");for(const V of R){const O=P.querySelector(V.selector)||P.querySelector(`[part~="${V.selector}"]`);O?.textContent&&!O.textContent.includes(g.formattedDiscounted)&&$(O,L=>/\d/.test(L)?g.formattedDiscounted:L)}}function v(){a.subscriptionHideWrongPlans&&a.subscriptionHideWrongPlans(),I(),a.subscriptionUpdateOneTime&&a.subscriptionUpdateOneTime(),f()}ue({data:n,runUpdates:v})}async function je(a){if(a.subscriptionOneTimeDone)return;const e=a.getActiveAssignment(),t=e?a.getHypothesis(e.hypothesisId):void 0,i=!!(t?.subscriptionData&&t.priceData),s=i?null:a.findActiveSubscriptionTestControl(),r=i?t:s?.hypothesis;if(!r?.subscriptionData||!r.priceData)return;const n=i?e.testId:s.testId;a.subscriptionOneTimeDone=!0;const o=r.subscriptionData,l=r.priceData,c=j(l),d=r.isControl,p=d?"control":"variant";a.slptValue=`${n}:${p}:f`,a.updatePriceTestHiddenInputs(n,p,!1);function h(){const u=B(o);if(!u)return;const b=X(c);if(!b)return;const E=W(l),S=de(o,b,E);if(!pe(S,d))return;const C=c.get(b);if(!C)return;const _=H(C.priceInCents,l.moneyFormat,l.currency,l.currencyCodeEnabled),T=D(o,"onetimePrice");if(!T.length)return;const m=D(o,"onetimeContainer"),y=m.length?m[0].selector:'[part~="rc-purchase-option__onetime"]',I=u.querySelector(y)??u;for(const f of T){let v=null;try{v=I.querySelector(f.selector)}catch{v=null}v??=I.querySelector(`[part~="${f.selector}"]`),v&&v.textContent&&!v.textContent.includes(_)&&$(v,g=>/\d/.test(g)?_:g)}}a.subscriptionUpdateOneTime=h,h()}async function Je(a,e){const{subscriptionPreviewRender:t}=await Be(async()=>{const{subscriptionPreviewRender:i}=await Promise.resolve().then(()=>it);return{subscriptionPreviewRender:i}},void 0);return t(a.subscriptionData,a.priceData,a.isControl,e)}function Ye(a,e){const t=a.widget.selectors.widgetParent??[],i=a.widget.selectors.subscriptionPlans??[],s=a.widget.selectors.subscriptionInput??[];if(!t.length||!i.length||!s.length){e("[SUB-GLOBAL-HIDE] Missing required selectors — skipping");return}const r=t[0].selector,n=i[0].selector,o=s[0].selector;let l=!1,c=null,d=!1;function p(){if(!d){d=!0;try{h()}finally{d=!1}}}function h(){const C=document.querySelector(r);if(!C?.shadowRoot)return;const _=C.shadowRoot.querySelector(n);if(!_?.shadowRoot)return;_.shadowRoot!==c&&(c=_.shadowRoot,l=!1);let T=0;if(a.widget.widgetType==="buttons"||a.widget.widgetType==="radio"){const m=Array.from(_.shadowRoot.querySelectorAll(o));for(const f of m)if(a.planIds.includes(f.value)){f.disabled||(f.disabled=!0);const v=f.closest("label");v&&v.style.display!=="none"&&(v.style.display="none",T++)}const y=m.filter(f=>!a.planIds.includes(f.value));if(!y.some(f=>f.checked)&&!l&&y.length>0){l=!0;const f=y[0];f.closest("label")?.click(),f.dispatchEvent(new Event("change",{bubbles:!0})),e(`[SUB-GLOBAL-HIDE] Preselected first visible plan input=${f.value}`)}const I=y.find(f=>f.checked)??y[0];if(I){const f=Array.from(document.querySelectorAll('input[name="selling_plan"]'));for(const v of f)v.value!==I.value&&(v.value=I.value,e(`[SUB-GLOBAL-HIDE] Mirrored plan id ${I.value} to form selling_plan input`))}}else if(a.widget.widgetType==="dropdown"){const m=_.shadowRoot.querySelector("select");if(!m)return;for(const I of Array.from(m.options))a.planIds.includes(I.value)&&(I.style.display!=="none"&&(I.style.display="none"),I.disabled||(I.disabled=!0),T++);const y=Array.from(m.options).filter(I=>!a.planIds.includes(I.value)),w=y.some(I=>I.value===m.value);y.length>0&&!w&&!l&&(l=!0,m.value=y[0].value,m.dispatchEvent(new Event("change",{bubbles:!0})),e(`[SUB-GLOBAL-HIDE] Preselected first visible option=${y[0].value}`))}T>0&&e(`[SUB-GLOBAL-HIDE] Hidden ${T} B-side plan buttons`)}const u={childList:!0,subtree:!0,characterData:!0};let b=null;function E(C){b?.disconnect(),b=new MutationObserver(()=>p()),b.observe(C,u)}function S(){const C=document.querySelector(r);if(!C?.shadowRoot)return!1;p(),new MutationObserver(()=>{p();const m=C.shadowRoot.querySelector(n);m?.shadowRoot&&E(m.shadowRoot)}).observe(C.shadowRoot,u);const T=C.shadowRoot.querySelector(n);return T?.shadowRoot&&E(T.shadowRoot),!0}if(!S()){e("[SUB-GLOBAL-HIDE] Widget not in DOM yet — waiting via MutationObserver");const C=new MutationObserver(()=>{S()&&C.disconnect()});C.observe(document.body??document.documentElement,{childList:!0,subtree:!0})}}const he="Limited preview",Ze="Add-to-cart and checkout prices won't reflect this test until it launches — test selling plans are not created in your subscription app until after a test is launched.",Xe=5e3;function Qe(){const a=document.createElement("div");a.id="shoplift-preview-subscription-warning";const e=document.createElement("span");e.id="shoplift-preview-subscription-warning__icon",e.setAttribute("aria-hidden","true"),e.textContent="!";const t=document.createElement("span");t.id="shoplift-preview-subscription-warning__label",t.textContent=he;const i=document.createElement("div");i.id="shoplift-preview-subscription-warning__tooltip",i.setAttribute("role","tooltip"),i.textContent=Ze,a.appendChild(e),a.appendChild(t),a.appendChild(i),a.setAttribute("tabindex","0"),a.setAttribute("aria-describedby",i.id),a.setAttribute("aria-label",he);let s=null;function r(){s!==null&&(clearTimeout(s),s=null)}function n(){i.classList.add("shoplift-preview-subscription-warning__tooltip--visible")}function o(){i.classList.remove("shoplift-preview-subscription-warning__tooltip--visible")}function l(){n(),r(),s=setTimeout(()=>{o(),s=null},Xe)}function c(){r(),n()}function d(){s===null&&o()}a.addEventListener("mouseenter",c),a.addEventListener("mouseleave",d),a.addEventListener("focus",c),a.addEventListener("blur",d);function p(u){try{const b=u.target;if(!(b instanceof Element))return;(b.closest('form[action*="/cart/add"] button[type="submit"], form[action*="/cart/add"] input[type="submit"]')!==null||b.closest('[name="add"], button[name="add"], [data-add-to-cart], button[data-add-to-cart]')!==null)&&l()}catch{}}document.addEventListener("click",p,!0);function h(){r(),document.removeEventListener("click",p,!0),a.removeEventListener("mouseenter",c),a.removeEventListener("mouseleave",d),a.removeEventListener("focus",c),a.removeEventListener("blur",d),a.remove()}return{root:a,tooltip:i,cleanup:h}}let fe=!1;class et{DATA_SL_ATTRIBUTE_P="data-sl-attribute-p";DATA_SL_TEST_ID="data-sl-test-id";VIEWPORT_TRACK_THRESHOLD=.5;temporarySessionKey="Shoplift_Session";essentialSessionKey="Shoplift_Essential";analyticsSessionKey="Shoplift_Analytics";priceSelectorsSessionKey="Shoplift_PriceSelectors_v2";shop;host;eventHost;disableReferrerOverride;legacySessionKey;cssHideClass;testConfigs;inactiveTestConfigs;hiddenSubscriptionPlans;testsFilteredByAudience;sendPageView;shopliftDebug;gaConfig;telemetryEnabled;getCountryTimeout;klaviyoGateTimeout=1e3;geoViaShopify;resolvedRegion=null;klaviyoMembership=null;state;subscriptionPreviewWarningCleanup=null;shopifyAnalyticsId;cookie=document.cookie;isSyncing=!1;isSyncingGA=!1;fetch;localStorageSet;localStorageGet;sessionStorageSet=window.sessionStorage.setItem.bind(window.sessionStorage);sessionStorageGet=window.sessionStorage.getItem.bind(window.sessionStorage);urlParams=new URLSearchParams(window.location.search);device;logHistory;activeViewportObservers=new Map;clientIdRetryCount=0;constructor(e,t,i,s,r,n,o,l,c,d,p,h,u,b=!1){this.shop=e,this.host=t,this.eventHost=i,this.disableReferrerOverride=l,this.logHistory=[],this.legacySessionKey=`SHOPLIFT_SESSION_${this.shop}`,this.cssHideClass=s?"shoplift-hide":"",this.testConfigs=p.map(S=>({...S,startAt:new Date(S.startAt),statusHistory:S.statusHistory.map(C=>({...C,createdAt:new Date(C.createdAt)}))})),this.inactiveTestConfigs=h,this.hiddenSubscriptionPlans=u,this.sendPageView=!!r,this.shopliftDebug=n===!0,this.telemetryEnabled=c===!0,this.geoViaShopify=b===!0,this.gaConfig=o!=={"sendEvents":false,"mode":"gtag"}?o:{sendEvents:!1},this.fetch=window.fetch.bind(window),this.localStorageSet=window.localStorage.setItem.bind(window.localStorage),this.localStorageGet=window.localStorage.getItem.bind(window.localStorage);const E=this.getDeviceType();this.device=E!=="tablet"?E:"mobile",this.state=this.loadState(),this.shopifyAnalyticsId=this.getShopifyAnalyticsId(),this.testsFilteredByAudience=p.filter(S=>S.status=="active"),this.getCountryTimeout=d===1000?1e3:d,window.__slReadCookie=S=>{const C=this.getCookie(S);if(C===null)return null;try{return decodeURIComponent(C)}catch{return C}},this.log("State Loaded",JSON.stringify(this.state))}deriveCategoryFromExistingTests(){if(!this.state.temporary.testCategory&&this.state.essential.visitorTests.length>0){const e=this.state.essential.visitorTests.some(t=>{if(!t.hypothesisId)return!1;const i=this.getHypothesis(t.hypothesisId);return i&&["theme","basicScript","price"].includes(i.type)});this.state.temporary.testCategory=e?"global":"conditional",this.persistTemporaryState(),this.log("Derived test category from existing visitorTests: %s",this.state.temporary.testCategory)}}async init(){try{if(this.log("Shoplift script initializing"),window.Shopify&&window.Shopify.designMode){this.log("Skipping script for design mode");return}if(window.location.href.includes("slScreenshot=true")){this.log("Skipping script for screenshot");return}if(window.location.hostname.endsWith(".edgemesh.com")){this.log("Skipping script for preview");return}if(window.location.href.includes("isShopliftMerchant")){const n=this.urlParams.get("isShopliftMerchant")==="true";this.log("Setting merchant session to %s",n),this.state.temporary.isMerchant=n,this.persistTemporaryState()}if(this.state.temporary.isMerchant){this.log("Setting up preview for merchant"),typeof window.shoplift!="object"&&this.setShopliftStub(),this.state.temporary.previewConfig||this.hidePage(),await this.initPreview(),document.querySelector("#sl-preview-bar-hide")?.remove();return}if(this.state.temporary.previewConfig=void 0,be(navigator.userAgent))return;const e=Date.now(),t=!this.state.temporary.lastSeen||e-this.state.temporary.lastSeen>1800*1e3;(!this.state.temporary.entryPage||t)&&(this.state.temporary.entryPage=J(window.location.href)),this.state.temporary.lastSeen=e,this.persistTemporaryState(),window.__slEntryPage=this.state.temporary.entryPage??"";const i=this.state.essential.visitorTests.filter(n=>n.hypothesisId&&+n.createdAt>Date.now()-6e4);if(i.length===0)this.sendDiagnosticTelemetry("page-landed",null);else for(const n of i)this.sendDiagnosticTelemetry("page-landed",n.testId,{hypothesisId:n.hypothesisId,isControl:n.assignedTo==="control",testType:n.testType??"unknown"});if(navigator.userAgent.includes("Chrome/118")){this.log("Random: %o",[Math.random(),Math.random(),Math.random()]);const n=await this.makeRequest({url:`${this.eventHost}/api/v0/events/ip`,method:"get"}).then(o=>o?.json());this.log(`IP: ${n}`),this.makeRequest({url:`${this.eventHost}/api/v0/logs`,method:"post",data:JSON.stringify(this.debugState(),te)}).catch()}if(this.shopifyAnalyticsId=this.getShopifyAnalyticsId(),this.monitorConsentChange(),this.checkForThemePreview())return;if(!this.disableReferrerOverride&&this.state.temporary.originalReferrer!=null){this.log(`Overriding referrer from '${document.referrer}' to '${this.state.temporary.originalReferrer}'`);const n=this.state.temporary.originalReferrer;delete this.state.temporary.originalReferrer,this.persistTemporaryState(),Object.defineProperty(document,"referrer",{get:()=>n,enumerable:!0,configurable:!0})}if(this.needsKlaviyo(this.testConfigs,this.state.essential.visitorTests,this.state.analytics.visitor??this.buildBaseVisitor())&&this.ensureKlaviyoMembership(),await this.refreshVisitor(this.shopifyAnalyticsId),await this.handleVisitorTest()){this.log("Redirecting for visitor test");return}this.setShoplift(),this.showPage(),this.ensureCartAttributesForExistingPriceTests(!1);const r=this.state.essential.visitorTests.some(n=>(n.hypothesisId?this.getHypothesis(n.hypothesisId):void 0)?.subscriptionData!=null)||Object.values(this.state.temporary.testReservations??{}).some(n=>this.getHypothesis(n.hypothesisId)?.subscriptionData!=null);this.hiddenSubscriptionPlans&&!r&&(this.log(`[SUB-GLOBAL] Visitor not in subscription test — hiding ${this.hiddenSubscriptionPlans.planIds.length} B-side plans`),Ye(this.hiddenSubscriptionPlans,n=>this.log(n))),await this.subscriptionSwap(),await this.subscriptionOneTimePrice(),await this.subscriptionPriceChange(),await this.finalize(),console.log("SHOPLIFT SCRIPT INITIALIZED!")}catch(e){if(e instanceof G)return;throw e}finally{typeof window.shoplift!="object"&&this.setShopliftStub()}}getVariantColor(e){switch(e){case"a":return{text:"#141414",bg:"#E2E2E2"};case"b":return{text:"rgba(255, 255, 255, 1)",bg:"rgba(37, 99, 235, 1)"}}}getDefaultVariantTitle(e){return e.title?e.title:e.type==="price"?e.isControl?"Original prices":"Variant prices":e.isControl?"Original":"Untitled variant "+e.label.toUpperCase()}async initPreview(){const e=this.urlParams.get("previewConfig");if(e){this.state.temporary.previewConfig=void 0,this.log("Setting up the preview"),this.log("Found preview config, writing to temporary state");const t=await Le(e);if(this.state.temporary.previewConfig=t,this.state.temporary.previewConfig.testTypeCategory===M.Price){this.hidePage(!0);const s=this.state.temporary.previewConfig;let r=`${this.host}/api/dom-selectors/${s.storeId}/${s.testId}/${s.isDraft||!1}`;s.shopifyProductId&&(r+=`?productId=${s.shopifyProductId}`);const n=await this.makeJsonRequest({method:"get",url:r}).catch(o=>(this.log("Error getting domSelectors",o),null));if(s.variants.forEach(o=>o.domSelectors=n[o.id]?.domSelectors),s.isDraft){const o=`${this.host}/api/dom-selectors/${s.storeId}/${s.testId}/subscription-preview`,l=await this.makeJsonRequest({method:"get",url:o}).catch(c=>(this.log("No subscription preview data for draft (test may not have a subscription widget)",c),null));l?.subscriptionData&&s.variants.forEach(c=>{c.subscriptionData=l.subscriptionData,c.priceData=l.priceData})}}this.persistTemporaryState();const i=new URL(window.location.toString());i.searchParams.delete("previewConfig"),this.queueRedirect(i)}else if(this.state.temporary.previewConfig){this.showPage();const t=this.state.temporary.previewConfig;if(t.testTypeCategory===M.Template&&this.handleTemplatePreview(t)&&this.initPreviewControls(t),t.testTypeCategory===M.UrlRedirect&&this.handleUrlPreview(t)&&this.initPreviewControls(t),t.testTypeCategory===M.Script&&this.handleScriptPreview(t)&&this.initPreviewControls(t),t.testTypeCategory===M.Price){const i=await this.handlePricePreview(t);t.isDraft?await this.handleSubscriptionPricePreview(t):await this.handleSubscriptionLivePreview(t),i&&this.initPreviewControls(t)}}}initPreviewControls(e){document.addEventListener("DOMContentLoaded",()=>{const t=e.variants.find(b=>b.id===e.currentVariant),i=t?.label||"a",s=e.variants,r=document.createElement("div");r.id="shoplift-preview-control";const n=document.createElement("div"),o=document.createElement("img");o.src=Ve,o.height=24,o.width=14,n.style.padding="0 16px",n.style.lineHeight="100%",n.appendChild(o),r.appendChild(n);const l=document.createElement("div");l.id="shoplift-preview-variant-selector";const c=document.createElement("button");c.id="shoplift-preview-variant-menu-trigger";const d=document.createElement("div");d.className="menu-variant-label",d.style.backgroundColor=this.getVariantColor(i).bg,d.style.color=this.getVariantColor(i).text,d.innerText=i.toUpperCase(),c.appendChild(d);const p=document.createElement("span");if(p.id="shoplift-preview-variant-title",p.innerText=t?this.getDefaultVariantTitle(t):"Untitled variant "+i.toUpperCase(),c.appendChild(p),s.length>1){const b=document.createElement("img");b.src=Oe,b.width=12,b.height=12,b.style.height="12px",b.style.width="12px",c.appendChild(b);const E=document.createElement("div");E.className="preview-variant-menu";for(const S of e.variants.filter(C=>C.id!==e.currentVariant)){const C=document.createElement("div");C.className="preview-variant-menu--item";const _=document.createElement("div");_.className="menu-variant-label",_.style.backgroundColor=this.getVariantColor(S.label).bg,_.style.color=this.getVariantColor(S.label).text,_.style.flexShrink="0",_.innerText=S.label.toUpperCase(),C.appendChild(_);const T=document.createElement("span");T.innerText=this.getDefaultVariantTitle(S),C.appendChild(T),C.addEventListener("click",()=>{this.pickVariant(S.id)}),E.appendChild(C)}l.appendChild(E),c.addEventListener("click",()=>{E.className!=="preview-variant-menu preview-variant-menu__visible"?E.classList.add("preview-variant-menu__visible"):E.classList.remove("preview-variant-menu__visible")}),document.addEventListener("click",S=>{S.target instanceof Element&&!c.contains(S.target)&&E.className==="preview-variant-menu preview-variant-menu__visible"&&E.classList.remove("preview-variant-menu__visible")})}else c.style.pointerEvents="none",d.style.margin="0";if(l.appendChild(c),r.appendChild(l),e.hasSubscription){this.subscriptionPreviewWarningCleanup?.();const b=Qe();r.appendChild(b.root),this.subscriptionPreviewWarningCleanup=b.cleanup}const h=document.createElement("div"),u=document.createElement("button");u.id="shoplift-exit-preview-button",u.innerText="Exit",h.appendChild(u),u.addEventListener("click",()=>{this.exitPreview()}),r.appendChild(h),document.body.appendChild(r),requestAnimationFrame(()=>{r.classList.add("visible")})}),this.ensureCartAttributesForExistingPriceTests(!0)}pickVariant(e){if(this.state.temporary.previewConfig){const t=this.state.temporary.previewConfig,i=new URL(window.location.toString());if(t.testTypeCategory===M.UrlRedirect){const s=t.variants.find(r=>r.id===t.currentVariant)?.redirectUrl;if(i.pathname===s){const r=t.variants.find(n=>n.id===e)?.redirectUrl;r&&(i.pathname=r)}}if(t.testTypeCategory===M.Template){const s=t.variants.find(r=>r.id===t.currentVariant)?.pathName;if(s&&i.pathname===s){const r=t.variants.find(n=>n.id===e)?.pathName;r&&r!==s&&(i.pathname=r)}}t.currentVariant=e,this.persistTemporaryState(),this.queueRedirect(i)}}exitPreview(){const e=new URL(window.location.toString());if(this.state.temporary.previewConfig?.testTypeCategory===M.Template&&e.searchParams.delete("view"),this.state.temporary.previewConfig?.testTypeCategory===M.Script&&e.searchParams.delete("slVariant"),this.state.temporary.previewConfig?.testTypeCategory===M.UrlRedirect){const i=this.state.temporary.previewConfig.variants.filter(r=>!r.isControl&&r.redirectUrl!==null).map(r=>r.redirectUrl),s=this.state.temporary.previewConfig.variants.find(r=>r.label==="a")?.redirectUrl;i.includes(e.pathname)&&s&&(e.pathname=s)}this.state.temporary.isMerchant=!1,e.searchParams.delete("isShopliftMerchant"),this.state.temporary.previewConfig=void 0,this.persistTemporaryState(),this.subscriptionPreviewWarningCleanup?.(),this.subscriptionPreviewWarningCleanup=null,this.hidePage(),this.queueRedirect(e)}handleTemplatePreview(e){const t=e.currentVariant,i=e.variants.find(l=>l.id===t);if(!i)return!1;const s=e.variants.find(l=>l.isControl);if(!s)return!1;this.log("Setting up template preview for type",s.type);const r=new URL(window.location.toString()),n=r.searchParams.get("view"),o=i.type===s.type;return!o&&!i.isControl&&template.suffix===s.affix&&this.typeFromTemplate()===s.type&&i.pathName!==null?(this.log("Hit control template type, redirecting to the variant url"),this.hidePage(),r.pathname=i.pathName,this.queueRedirect(r),!0):(!i.isControl&&this.typeFromTemplate()==i.type&&template.suffix===s.affix&&o&&n!==(i.affix||"__DEFAULT__")&&(this.log("Template type and affix match control, updating the view param"),r.searchParams.delete("view"),this.log("Setting the new viewParam to",i.affix||"__DEFAULT__"),this.hidePage(),r.searchParams.set("view",i.affix||"__DEFAULT__"),this.queueRedirect(r)),n!==null&&n!==(i.affix||"__DEFAULT__")&&(r.searchParams.delete("view"),this.hidePage(),this.queueRedirect(r)),!0)}handleUrlPreview(e){const t=e.currentVariant,i=e.variants.find(n=>n.id===t),s=e.variants.find(n=>n.isControl)?.redirectUrl;if(!i)return!1;this.log("Setting up URL redirect preview");const r=new URL(window.location.toString());return r.pathname===s&&!i.isControl&&i.redirectUrl!==null&&(this.log("Url matches control, redirecting"),this.hidePage(),r.pathname=i.redirectUrl,this.queueRedirect(r)),!0}handleScriptPreview(e){const t=e.currentVariant,i=e.variants.find(n=>n.id===t);if(!i)return!1;this.log("Setting up script preview");const s=new URL(window.location.toString());return s.searchParams.get("slVariant")!==i.id&&(this.log("current id doesn't match the variant, redirecting"),s.searchParams.delete("slVariant"),this.log("Setting the new slVariantParam"),this.hidePage(),s.searchParams.set("slVariant",i.id),this.queueRedirect(s)),!0}async handlePricePreview(e){const t=e.currentVariant,i=e.variants.find(s=>s.id===t);return i?(this.log("Setting up price preview"),i.domSelectors&&i.domSelectors.length>0&&(U(document,{testId:e.testId,hypothesisId:i.id,selectors:i.domSelectors}),this.ensureCartAttributesForExistingPriceTests(!0)),!0):!1}async handleSubscriptionPricePreview(e){const t=e.variants.find(i=>i.id===e.currentVariant);t?.subscriptionData&&(this.log("Setting up subscription price preview"),await Je({id:t.id,isControl:t.isControl,subscriptionData:t.subscriptionData,priceData:t.priceData},(i,...s)=>this.log(i,...s)))}async handleSubscriptionLivePreview(e){this.testConfigs.find(s=>s.id===e.testId)?.hypotheses.find(s=>s.id===e.currentVariant)?.subscriptionData&&(this.log("Setting up subscription live preview"),this.subscriptionSwapDone=!1,this.subscriptionOneTimeDone=!1,this.subscriptionPriceDone=!1,await this.subscriptionSwap(),await this.subscriptionOneTimePrice(),await this.subscriptionPriceChange())}async finalize(){const e=await this.getCartState();e!==null&&this.queueCartUpdate(e),this.pruneStateAndSave(),await this.syncAllEvents()}setShoplift(){this.log("Setting up public API");const t=this.urlParams.get("slVariant")==="true",i=t?null:this.urlParams.get("slVariant");window.shoplift={isHypothesisActive:async s=>{if(this.log("Script checking variant for hypothesis '%s'",s),t)return this.log("Forcing variant for hypothesis '%s'",s),!0;if(i!==null)return this.log("Forcing hypothesis '%s'",i),s===i;const r=this.testConfigs.find(o=>o.hypotheses.some(l=>l.id===s));if(!r)return this.log("No test found for hypothesis '%s'",s),!1;const n=this.state.essential.visitorTests.find(o=>o.testId===r.id);return n?(this.log("Active visitor test found",s),n.hypothesisId===s):(await this.manuallySplitVisitor(r),this.testConfigs.some(o=>o.hypotheses.some(l=>l.id===s&&this.state.essential.visitorTests.some(c=>c.hypothesisId===l.id))))},setAnalyticsConsent:async s=>{await this.onConsentChange(s,!0)},getVisitorData:()=>({visitor:this.state.analytics.visitor,visitorTests:this.state.essential.visitorTests.filter(s=>!s.isInvalid).map(s=>{const{shouldSendToGa:r,savedAt:n,...o}=s;return o})})}}setShopliftStub(){this.log("Setting up stubbed public API");const t=this.urlParams.get("slVariant")==="true",i=t?null:this.urlParams.get("slVariant");window.shoplift={isHypothesisActive:s=>Promise.resolve(t||s===i),setAnalyticsConsent:()=>Promise.resolve(),getVisitorData:()=>({visitor:null,visitorTests:[]})}}async manuallySplitVisitor(e){this.log("Starting manual split for test '%s'",e.id),await this.handleVisitorTest([e])||this.showPage();const i=this.getReservationForTest(e.id);i&&!i.isRealized&&i.entryCriteriaKey&&(this.log("Realizing manual API reservation for test '%s'",e.id),this.realizeReservationForCriteria(i.entryCriteriaKey)),this.saveState(),this.syncAllEvents()}async handleVisitorTest(e){await this.filterTestsByAudience(this.testConfigs,this.state.analytics.visitor??this.buildBaseVisitor(),this.state.essential.visitorTests),this.pruneStaleVisitorTests(),this.deriveCategoryFromExistingTests(),this.clearStaleReservations();let t=e?e.filter(i=>this.testsFilteredByAudience.some(s=>s.id===i.id)):[...this.testsForUrl(this.testsFilteredByAudience),...this.domTestsForUrl(this.testsFilteredByAudience)];try{if(t.length===0)return this.log("No tests found"),!1;this.log("Checking for existing visitor test on page");const i=this.getCurrentVisitorHypothesis(t);if(i){this.log("Found current visitor test");const l=this.considerRedirect(i);return l&&(this.log("Redirecting for current visitor test"),this.redirect(i)),l}const s=this.getReservationForCurrentPage();if(s){this.log("Found matching reservation for current page: %s",s.testId);const l=this.getHypothesis(s.hypothesisId);if(l){l.type!=="price"&&this.realizeReservationForCriteria(s.entryCriteriaKey);const c=this.considerRedirect(l);return c&&this.redirect(l),c}}this.log("No active test relation for test page");const r=this.testsForUrl(this.inactiveTestConfigs.filter(l=>this.testIsPaused(l)&&l.hypotheses.some(c=>this.state.essential.visitorTests.some(d=>d.hypothesisId===c.id)))).map(l=>l.id);if(r.length>0)return this.log("Visitor has paused tests for test page, skipping test assignment: %o",r),!1;if(!this.state.temporary.testCategory){const l=this.testsFilteredByAudience.filter(d=>this.isGlobalEntryCriteria(this.getEntryCriteriaKey(d))),c=this.testsFilteredByAudience.filter(d=>!this.isGlobalEntryCriteria(this.getEntryCriteriaKey(d)));if(this.log("Category dice roll - global tests: %o, conditional tests: %o",l.map(d=>({id:d.id,title:d.title,criteria:this.getEntryCriteriaKey(d)})),c.map(d=>({id:d.id,title:d.title,criteria:this.getEntryCriteriaKey(d)}))),l.length>0&&c.length>0){const d=l.length,p=c.length,h=d+p,u=Math.random()*h;this.state.temporary.testCategory=u<d?"global":"conditional",this.log("Category dice roll: rolled %.2f of %d (global weight: %d, conditional weight: %d), selected '%s'",u,h,d,p,this.state.temporary.testCategory)}else l.length>0?(this.state.temporary.testCategory="global",this.log("Only global tests available, setting category to global")):(this.state.temporary.testCategory="conditional",this.log("Only conditional tests available, setting category to conditional"));this.persistTemporaryState()}const n=this.state.temporary.testCategory;if(this.log("Visitor test category: %s",n),n==="global"){const l=this.testsFilteredByAudience.filter(c=>!this.isGlobalEntryCriteria(this.getEntryCriteriaKey(c)));for(const c of l)this.markTestAsBlocked(c,"category:global");t=t.filter(c=>this.isGlobalEntryCriteria(this.getEntryCriteriaKey(c)))}else{const l=this.testsFilteredByAudience.filter(c=>this.isGlobalEntryCriteria(this.getEntryCriteriaKey(c)));for(const c of l)this.markTestAsBlocked(c,"category:conditional");t=t.filter(c=>!this.isGlobalEntryCriteria(this.getEntryCriteriaKey(c)))}if(t.length===0)return this.log("No tests remaining after category filter"),!1;this.createReservations(t);const o=this.getReservationForCurrentPage();if(o&&!o.isRealized){const l=this.getHypothesis(o.hypothesisId);if(l){l.type!=="price"&&this.realizeReservationForCriteria(o.entryCriteriaKey);const c=this.considerRedirect(l);return c&&(this.log("Redirecting for new test"),this.redirect(l)),c}}return!1}finally{this.includeInDomTests(),this.saveState()}}includeInDomTests(){this.applyControlForAudienceFilteredPriceTests();const e=this.getDomTestsForCurrentUrl(),t=this.getVisitorDomHypothesis(e);for(const i of e){this.log("Evaluating dom test '%s'",i.id);const s=i.hypotheses.some(u=>u.type==="price");if(this.state.essential.visitorTests.find(u=>u.testId===i.id&&u.isInvalid&&!u.hypothesisId)){if(this.log("Visitor is blocked from test '%s', applying control prices if price test",i.id),s){const u=i.hypotheses.find(b=>b.isControl);u?.priceData&&(this.applyPriceTestWithMapLookup(i.id,u,[u],()=>{this.log("Control prices applied for blocked visitor, no metrics tracked")}),this.updatePriceTestHiddenInputs(i.id,"control",!1))}continue}const n=this.getReservationForTest(i.id);let o=null,l=!1;const c=t.find(u=>i.hypotheses.some(b=>u.id===b.id));if(n)o=this.getHypothesis(n.hypothesisId)??null,this.log("Using reserved hypothesis '%s' for test '%s'",n.hypothesisId,i.id);else if(c)o=c,this.log("Using existing hypothesis assignment for test '%s'",i.id);else if(s){const u=this.visitorActiveTestTypeWithReservations();u?(l=!0,this.log("Visitor already in test type '%s', treating as non-test for price test '%s'",u,i.id)):o=this.pickHypothesis(i)}else o=this.pickHypothesis(i);if(l&&s){const u=i.hypotheses.find(b=>b.isControl);u?.priceData&&(this.log("Applying control prices for non-test visitor on price test '%s' (Map-based)",i.id),this.applyPriceTestWithMapLookup(i.id,u,[u],()=>{this.log("Control prices applied for non-test visitor, no metrics tracked")}),this.updatePriceTestHiddenInputs(i.id,"control",!1));continue}if(!o){this.log("Failed to pick hypothesis for test");continue}this.sendDiagnosticTelemetry("assignment",i.id,{hypothesisId:o.id,isControl:o.isControl,testType:o.type});const d=i.bayesianRevision??4,p=o.type==="price",h=d>=5;if(p&&h){if(this.log(`Price test with Map-based lookup (v${d}): ${i.id}`),!o.priceData){this.log("No price data for hypothesis '%s', skipping",o.id);continue}const u=o.isControl?"control":"variant";this.log(`Setting up Map-based price test for ${u} (test: ${i.id})`),this.applyPriceTestWithMapLookup(i.id,o,i.hypotheses,b=>{const E=this.getReservationForTest(b);E&&!E.isRealized&&E.entryCriteriaKey?this.realizeReservationForCriteria(E.entryCriteriaKey):this.queueAddVisitorToTest(b,o),this.saveState(),this.queuePageView(window.location.pathname),this.syncAllEvents()});continue}if(p&&!h){this.log(`Price test without viewport tracking (v${d}): ${i.id}`);const u=this.getDomSelectorsForHypothesis(o);if(u.length===0)continue;U(document,{testId:i.id,hypothesisId:o.id,selectors:u},b=>{this.queueAddVisitorToTest(b,o),this.saveState(),this.queuePageView(window.location.pathname),this.syncAllEvents()});continue}if(!o.domSelectors||o.domSelectors.length===0){this.log("No selectors found, skipping hypothesis");continue}U(document,{testId:i.id,hypothesisId:o.id,selectors:o.domSelectors},u=>{this.queueAddVisitorToTest(u,o),this.saveState(),this.queuePageView(window.location.pathname),this.syncAllEvents()})}}considerRedirect(e){if(this.log("Considering redirect for hypothesis '%s'",e.id),e.isControl)return this.log("Skipping redirect for control"),!1;if(e.type==="basicScript"||e.type==="manualScript")return this.log("Skipping redirect for script test"),!1;const t=this.state.essential.visitorTests.find(n=>n.hypothesisId===e.id),i=new URL(window.location.toString()),r=new URLSearchParams(window.location.search).get("view");if(e.type==="theme"){if(!(e.themeId===themeId)){if(this.log("Theme id '%s' is not hypothesis theme ID '%s'",e.themeId,themeId),this.isAppProxyPath())return this.log("On App Proxy path, skipping theme redirect to avoid infinite loop"),!1;if(t&&t.themeId!==e.themeId&&(t.themeId===themeId||!this.isThemePreview()))this.log("On old theme, redirecting and updating local visitor"),t.themeId=e.themeId;else if(this.isThemePreview())return this.log("On non-test theme, skipping redirect"),!1;return this.log("Hiding page to redirect for theme test"),this.hidePage(),!0}return!1}else if(e.type!=="dom"&&e.type!=="price"&&e.affix!==template.suffix&&e.affix!==r||e.redirectPath&&!i.pathname.endsWith(e.redirectPath))return this.log("Hiding page to redirect for template test"),this.hidePage(),!0;return this.log("Not redirecting"),!1}redirect(e){if(this.log("Redirecting to hypothesis '%s'",e.id),e.isControl)return;const t=new URL(window.location.toString());if(t.searchParams.delete("view"),e.redirectPath){const o=RegExp("^(/w{2}-w{2})/").exec(t.pathname);if(o&&o.length>1){const l=o[1];t.pathname=`${l}${e.redirectPath}`}else t.pathname=e.redirectPath}else e.type==="theme"?(t.searchParams.set("_ab","0"),t.searchParams.set("_fd","0"),t.searchParams.set("_sc","1"),t.searchParams.set("preview_theme_id",e.themeId.toString())):e.type!=="urlRedirect"&&t.searchParams.set("view",e.affix);const i=this.state.essential.visitorTests.find(o=>o.hypothesisId===e.id)?.testId,s=t.pathname+t.search,r=window.location.pathname+window.location.search,n=J(t.hash);if(i&&s!==r&&!n){const o=He(),l=Ne({v:2,t:i,n:o,fh:qe(window.location.pathname+window.location.search)});t.hash=`slr-${o}`;const c=new Date(Date.now()+3e4).toUTCString();document.cookie=`shoplift_redirect=${l};domain=.${window.location.hostname};path=/;SameSite=Strict;expires=${c}`}s===r&&this.showPage(),this.queueRedirect(t)}async refreshVisitor(e){if(e===null||!this.state.essential.isFirstLoad||!this.testConfigs.some(i=>i.visitorOption!=="all"))return;this.log("Refreshing visitor"),this.hidePage();const t=await this.getVisitor(e);t&&t.id&&this.updateLocalVisitor(t)}buildBaseVisitor(){return{shopifyAnalyticsId:this.shopifyAnalyticsId,device:this.device,country:null,...this.state.essential.initialState}}getInitialState(){const e=this.getUTMValue("utm_source")??"",t=this.getUTMValue("utm_medium")??"",i=this.getUTMValue("utm_campaign")??"",s=this.getUTMValue("utm_content")??"",r=window.document.referrer,n=this.device;return{createdAt:new Date,utmSource:e,utmMedium:t,utmCampaign:i,utmContent:s,referrer:r,device:n}}checkForThemePreview(){return this.log("Checking for theme preview"),window.location.hostname.endsWith(".shopifypreview.com")?(this.log("on shopify preview domain"),this.clearThemeBar(!0,!1,this.state),document.querySelector("#sl-preview-bar-hide")?.remove(),!1):this.isThemePreview()?this.state.essential.visitorTests.some(e=>e.isThemeTest&&e.hypothesisId!=null&&this.getHypothesis(e.hypothesisId)&&e.themeId===themeId)?(this.log("On active theme test, removing theme bar"),this.clearThemeBar(!1,!0,this.state),!1):this.state.essential.visitorTests.some(e=>e.isThemeTest&&e.hypothesisId!=null&&!this.getHypothesis(e.hypothesisId)&&e.themeId===themeId)?(this.log("Visitor is on an inactive theme test, redirecting to main theme"),this.redirectToMainTheme(),!0):this.state.essential.isFirstLoad?(this.log("No visitor found on theme preview, redirecting to main theme"),this.redirectToMainTheme(),!0):this.inactiveTestConfigs.some(e=>e.hypotheses.some(t=>t.themeId===themeId))?(this.log("Current theme is an inactive theme test, redirecting to main theme"),this.redirectToMainTheme(),!0):this.testConfigs.some(e=>e.hypotheses.some(t=>t.themeId===themeId))?(this.log("Falling back to clearing theme bar"),this.clearThemeBar(!1,!0,this.state),!1):(this.log("No tests on current theme, skipping script"),this.clearThemeBar(!0,!1,this.state),document.querySelector("#sl-preview-bar-hide")?.remove(),!0):(this.log("Not on theme preview"),this.clearThemeBar(!0,!1,this.state),!1)}redirectToMainTheme(){this.hidePage();const e=new URL(window.location.toString());e.searchParams.set("preview_theme_id",""),this.queueRedirect(e)}testsForUrl(e){const t=new URL(window.location.href),i=this.typeFromTemplate();return e.filter(s=>s.hypotheses.some(r=>r.type!=="dom"&&r.type!=="price"&&(r.isControl&&r.type===i&&r.affix===template.suffix||r.type==="theme"||r.isControl&&r.type==="urlRedirect"&&r.redirectPath&&t.pathname.endsWith(r.redirectPath)||r.type==="basicScript"))&&(s.ignoreTestViewParameterEnforcement||!t.searchParams.has("view")||s.hypotheses.map(r=>r.affix).includes(t.searchParams.get("view")??"")))}domTestsForUrl(e){const t=new URL(window.location.href);return e.filter(i=>i.hypotheses.some(s=>s.type!=="dom"&&s.type!=="price"?!1:s.type==="price"&&s.priceData&&s.priceData.variants.length>0?!0:s.domSelectors&&s.domSelectors.some(r=>new RegExp(re(r)).test(J(t.toString())))))}needsKlaviyo(e,t,i){return e.some(s=>s.requiresKlaviyo&&!t.some(r=>r.testId===s.id)&&this.matchesTestSettings(s,i,this.visitorCreatedDuringTestActive(s.statusHistory)))}getKlaviyoIdentity(){const e=ie(Fe(this.getCookie("__kla_id",document.cookie)));return{kx:ie(this.urlParams.get("_kx"))??(e?null:ie(new URL(this.state.temporary.entryPage??"",window.location.href).searchParams.get("_kx"))),exchangeId:e}}ensureKlaviyoMembership(){return this.klaviyoMembership??=this.resolveKlaviyoMembership().catch(e=>(this.log("Error resolving Klaviyo membership",e),{groups:[],known:!1})),this.klaviyoMembership}async resolveKlaviyoMembership(){const{kx:e,exchangeId:t}=this.getKlaviyoIdentity();if(!(e??t))return{groups:[],known:!1};this.log("Hiding page to resolve Klaviyo membership"),this.hidePage();const s=new URLSearchParams;e&&s.append("kx",e),t&&s.append("exchangeId",t);let r={groups:[],known:!1};try{const n=await this.makeJsonRequest({method:"get",url:`${this.host}/api/v1/storefront/klaviyo-groups/${encodeURIComponent(this.shop)}?${s}`,signal:AbortSignal.timeout(this.klaviyoGateTimeout)});r={groups:n?.groups??[],known:n?.known===!0}}catch(n){if(n instanceof G)return n;this.log("Error getting Klaviyo groups",n)}return r}async filterTestsByAudience(e,t,i){const s=[],r=e.some(l=>(l.requiresRegion||this.geoViaShopify&&l.requiresCountry)&&!i.some(c=>c.testId===l.id));this.resolvedRegion===null&&r&&(this.log("Hiding page to wait for Shopify region resolution"),this.hidePage(),await this.waitForResolvedRegion()),window.__slRegion=this.resolvedRegion??"";let n=t.country;this.geoViaShopify?n=this.resolvedRegion?this.resolvedRegion.slice(0,2):n:!n&&e.some(l=>l.requiresCountry&&!i.some(c=>c.testId===l.id))&&(this.log("Hiding page to check geoip"),this.hidePage(),n=await this.makeJsonRequest({method:"get",url:`${this.eventHost}/api/v0/visitors/get-country`,signal:AbortSignal.timeout(this.getCountryTimeout)}).catch(l=>(this.log("Error getting country",l),null)));let o={groups:[],known:!1};if(this.needsKlaviyo(e,i,t)){const l=await this.ensureKlaviyoMembership();if(l instanceof G)throw l;o=l}window.__slKlaviyoGroups=o.groups,window.__slKlaviyoKnown=o.known;for(const l of e){if(this.log("Checking audience for test '%s'",l.id),this.state.essential.visitorTests.some(p=>p.testId===l.id&&p.hypothesisId==null)){console.log(`Skipping blocked test '${l.id}'`);continue}const c=this.visitorCreatedDuringTestActive(l.statusHistory);(i.some(p=>p.testId===l.id&&(l.device==="all"||l.device===t.device&&l.device===this.device))||this.isTargetAudience(l,t,c,n))&&(this.log("Visitor is in audience for test '%s'",l.id),s.push(l))}this.testsFilteredByAudience=s}async waitForResolvedRegion(e=1500,t=50){const i=Date.now();for(;this.resolvedRegion===null&&Date.now()-i<e;)await new Promise(s=>window.setTimeout(s,t))}isTargetAudience(e,t,i,s){const r=this.getChannel(t);return this.matchesTestSettings(e,t,i)&&(e.targetAudiences.length===0||e.targetAudiences.reduce((n,o)=>n||o.reduce((l,c)=>l&&c(t,i,r,s),!0),!1))}matchesTestSettings(e,t,i){return(e.device==="all"||e.device===t.device&&e.device===this.device)&&(e.visitorOption==="all"||e.visitorOption==="new"&&i||e.visitorOption==="returning"&&!i)}visitorCreatedDuringTestActive(e){let t="";for(const i of e){if(this.state.analytics.visitor!==null&&this.state.analytics.visitor.createdAt<i.createdAt||this.state.essential.initialState.createdAt<i.createdAt)break;t=i.status}return t==="active"}getDomTestsForCurrentUrl(){return this.domTestsForUrl(this.testsFilteredByAudience)}getCurrentVisitorHypothesis(e){return e.flatMap(t=>t.hypotheses).find(t=>t.type!=="dom"&&t.type!=="price"&&this.state.essential.visitorTests.some(i=>i.hypothesisId===t.id))}getVisitorDomHypothesis(e){return e.flatMap(t=>t.hypotheses).filter(t=>(t.type==="dom"||t.type==="price")&&this.state.essential.visitorTests.some(i=>i.hypothesisId===t.id))}getHypothesis(e){return this.testConfigs.filter(t=>t.hypotheses.some(i=>i.id===e)).map(t=>t.hypotheses.find(i=>i.id===e))[0]}getActiveAssignment(){if(this.state.temporary.isMerchant&&this.state.temporary.previewConfig){const t=this.state.temporary.previewConfig;return t.currentVariant&&t.testId?{testId:t.testId,hypothesisId:t.currentVariant}:null}const e=this.state.essential.visitorTests.find(t=>t.hypothesisId);return e?.hypothesisId?{testId:e.testId,hypothesisId:e.hypothesisId}:null}findActiveSubscriptionTestControl(){for(const e of this.testConfigs){const t=e.hypotheses.find(i=>i.isControl);if(t?.subscriptionData)return{testId:e.id,hypothesis:t}}return null}getDomSelectorsForHypothesis(e){if(!e)return[];if(e.domSelectors&&e.domSelectors.length>0)return e.domSelectors;if(e.priceData){const t=`${this.priceSelectorsSessionKey}_${e.id}`;try{const s=sessionStorage.getItem(t);if(s){const r=JSON.parse(s);return e.domSelectors=r,this.log("Loaded %d price selectors from cache for hypothesis '%s'",r.length,e.id),r}}catch{}const i=Me(e.priceData);e.domSelectors=i;try{sessionStorage.setItem(t,JSON.stringify(i)),this.log("Generated and cached %d price selectors for hypothesis '%s'",i.length,e.id)}catch{this.log("Generated %d price selectors for hypothesis '%s' (cache unavailable)",i.length,e.id)}return i}return[]}hasThemeTest(e){return e.some(t=>t.hypotheses.some(i=>i.type==="theme"))}hasTestThatIsNotThemeTest(e){return e.some(t=>t.hypotheses.some(i=>i.type!=="theme"&&i.type!=="dom"&&i.type!=="price"))}hasThemeAndOtherTestTypes(e){return this.hasThemeTest(e)&&this.hasTestThatIsNotThemeTest(e)}testIsPaused(e){return e.status==="paused"||e.status==="incompatible"||e.status==="suspended"}visitorActiveTestType(){const e=this.state.essential.visitorTests.filter(t=>this.testConfigs.some(i=>i.hypotheses.some(s=>s.id==t.hypothesisId)));return e.length===0?null:e.some(t=>t.isThemeTest)?"theme":"templateOrUrlRedirect"}getReservationType(e){return e==="price"||this.isTemplateTestType(e)?"deferred":"immediate"}isTemplateTestType(e){return["product","collection","landing","index","cart","search","blog","article","collectionList"].includes(e)}getEntryCriteriaKey(e){const t=e.hypotheses.find(i=>i.isControl);if(!t)return`unknown:${e.id}`;switch(t.type){case"theme":return"global:theme";case"basicScript":return"global:autoApi";case"price":return"global:price";case"manualScript":return`conditional:manualApi:${e.id}`;case"urlRedirect":return`conditional:url:${t.redirectPath||"unknown"}`;default:return`conditional:template:${t.type}`}}isGlobalEntryCriteria(e){return e.startsWith("global:")}groupTestsByEntryCriteria(e){const t=new Map;for(const i of e){const s=this.getEntryCriteriaKey(i),r=t.get(s)||[];r.push(i),t.set(s,r)}return t}doesCurrentPageMatchEntryCriteria(e){if(this.isGlobalEntryCriteria(e))return!0;if(e==="conditional:manualApi")return!1;if(e.startsWith("conditional:url:")){const t=e.replace("conditional:url:","");return window.location.pathname.endsWith(t)}if(e.startsWith("conditional:template:")){const t=e.replace("conditional:template:","");return this.typeFromTemplate()===t}return!1}hasActiveReservation(){const e=this.getActiveReservations();return Object.values(e).some(t=>!t.isRealized)}getActiveReservation(){const e=this.getActiveReservations();return Object.values(e).find(t=>!t.isRealized)??null}clearStaleReservations(){const e=this.state.temporary.testReservations;if(!e)return;let t=!1;for(const[i,s]of Object.entries(e)){const r=this.testConfigs.find(o=>o.id===s.testId);if(!r){this.log("Test '%s' no longer in config, clearing reservation for criteria '%s'",s.testId,i),delete e[i],t=!0;continue}if(r.status!=="active"){this.log("Test '%s' status is '%s', clearing reservation for criteria '%s'",s.testId,r.status,i),delete e[i],t=!0;continue}this.testsFilteredByAudience.some(o=>o.id===s.testId)||(this.log("Visitor no longer passes audience for test '%s', clearing reservation for criteria '%s'",s.testId,i),delete e[i],t=!0)}t&&this.persistTemporaryState()}createReservations(e){if(this.state.temporary.testReservations||(this.state.temporary.testReservations={}),this.state.temporary.rolledEntryCriteria||(this.state.temporary.rolledEntryCriteria=[]),this.state.temporary.testCategory==="global"){this.createSingleReservation(e,"global");return}const i=e.filter(o=>this.doesCurrentPageMatchEntryCriteria(this.getEntryCriteriaKey(o))),s=e.filter(o=>!this.doesCurrentPageMatchEntryCriteria(this.getEntryCriteriaKey(o)));this.log("Conditional tests split - matching current page: %d, not matching: %d",i.length,s.length),i.length>0&&this.log("Tests matching current page (same pool): %o",i.map(o=>({id:o.id,title:o.title,criteria:this.getEntryCriteriaKey(o)})));const r=`conditional:current-page:${this.typeFromTemplate()}`;if(i.length>0&&!this.state.temporary.rolledEntryCriteria.includes(r)){this.createSingleReservation(i,r);for(const o of i){const l=this.getEntryCriteriaKey(o);this.state.temporary.rolledEntryCriteria.includes(l)||this.state.temporary.rolledEntryCriteria.push(l)}}const n=this.groupTestsByEntryCriteria(s);for(const[o,l]of n){if(this.state.temporary.rolledEntryCriteria.includes(o)){this.log("Already rolled for criteria '%s', skipping",o);continue}if(l.some(S=>this.state.essential.visitorTests.some(C=>C.testId===S.id))){this.log("Visitor already has VT for criteria '%s', skipping",o),this.state.temporary.rolledEntryCriteria.push(o);continue}const d=[...l].sort((S,C)=>S.id.localeCompare(C.id));this.log("Test dice roll for criteria '%s' - available tests: %o",o,d.map(S=>({id:S.id,title:S.title})));const p=Math.floor(Math.random()*d.length),h=d[p];this.log("Test dice roll: picked index %d of %d, selected test '%s' (%s)",p+1,l.length,h.id,h.title);const u=this.pickHypothesis(h);if(!u){this.log("No hypothesis picked for test '%s'",h.id);continue}this.sendDiagnosticTelemetry("assignment",h.id,{hypothesisId:u.id,isControl:u.isControl,testType:u.type});const b=this.getReservationType(u.type),E={testId:h.id,hypothesisId:u.id,testType:u.type,reservationType:b,isThemeTest:u.type==="theme",themeId:u.themeId,createdAt:new Date,isRealized:!1,entryCriteriaKey:o};this.state.temporary.testReservations[o]=E,this.state.temporary.rolledEntryCriteria.push(o),this.log("Created %s reservation for test '%s' (criteria: %s)",b,h.id,o);for(const S of l)S.id!==h.id&&this.markTestAsBlocked(S,o)}this.persistTemporaryState()}createSingleReservation(e,t){if(this.state.temporary.rolledEntryCriteria.includes(t)){this.log("Already rolled for pool '%s', skipping",t);return}if(e.some(p=>this.state.essential.visitorTests.some(h=>h.testId===p.id&&!h.isInvalid))){this.log("Visitor already has VT for pool '%s', skipping",t),this.state.temporary.rolledEntryCriteria.push(t);return}if(e.length===0){this.log("No tests in pool '%s'",t);return}const s=[...e].sort((p,h)=>p.id.localeCompare(h.id));this.log("Test dice roll for pool '%s' - available tests: %o",t,s.map(p=>({id:p.id,title:p.title,criteria:this.getEntryCriteriaKey(p)})));const r=Math.floor(Math.random()*s.length),n=s[r];this.log("Test dice roll: picked index %d of %d, selected test '%s' (%s)",r,e.length,n.id,n.title);const o=this.pickHypothesis(n);if(!o){this.log("No hypothesis picked for test '%s'",n.id);return}this.sendDiagnosticTelemetry("assignment",n.id,{hypothesisId:o.id,isControl:o.isControl,testType:o.type});const l=this.getReservationType(o.type),c=this.getEntryCriteriaKey(n),d={testId:n.id,hypothesisId:o.id,testType:o.type,reservationType:l,isThemeTest:o.type==="theme",themeId:o.themeId,createdAt:new Date,isRealized:!1,entryCriteriaKey:c};this.state.temporary.testReservations[c]=d,this.state.temporary.rolledEntryCriteria.push(t),this.log("Created %s reservation for test '%s' from pool '%s' (criteria: %s)",l,n.id,t,c);for(const p of e)p.id!==n.id&&this.markTestAsBlocked(p,`pool:${t}`);this.persistTemporaryState()}markTestAsBlocked(e,t){this.state.essential.visitorTests.some(i=>i.testId===e.id)||(this.log("Blocking visitor from test '%s' (reason: %s)",e.id,t),this.state.essential.visitorTests.push({createdAt:new Date,testId:e.id,hypothesisId:null,isThemeTest:e.hypotheses.some(i=>i.type==="theme"),shouldSendToGa:!1,isSaved:!0,isInvalid:!0,themeId:void 0}))}realizeReservationForCriteria(e){const t=this.state.temporary.testReservations?.[e];if(!t)return this.log("No reservation found for criteria '%s'",e),!1;if(t.isRealized)return this.log("Reservation already realized for criteria '%s'",e),!1;if(this.state.essential.visitorTests.some(s=>s.testId===t.testId&&!s.isInvalid))return this.log("Visitor already assigned to test '%s'",t.testId),!1;const i=this.getHypothesis(t.hypothesisId);return i?(t.isRealized=!0,this.persistTemporaryState(),this.queueAddVisitorToTest(t.testId,i),this.saveState(),this.log("Realized reservation for test '%s' (criteria: %s)",t.testId,e),!0):(this.log("Hypothesis '%s' not found",t.hypothesisId),!1)}getActiveReservations(){return this.state.temporary.testReservations??{}}getReservationForCurrentPage(){const e=this.getActiveReservations();for(const[t,i]of Object.entries(e)){if(i.isRealized)continue;const s=this.testConfigs.find(r=>r.id===i.testId);if(!(!s||s.status!=="active")&&this.doesCurrentPageMatchEntryCriteria(t))return i}return null}getReservationForTest(e){const t=this.getActiveReservations();return Object.values(t).find(i=>i.testId===e)??null}getReservationTestType(){const e=this.getActiveReservations(),t=Object.values(e);if(t.length===0)return null;for(const i of t)if(i.isThemeTest)return"theme";for(const i of t)if(i.testType==="price")return"price";return t.some(i=>!i.isRealized)?"templateOrUrlRedirect":null}hasPriceTests(e){return e.some(t=>t.hypotheses.some(i=>i.type==="price"))}_priceTestProductIds=null;getPriceTestProductIds(){if(this._priceTestProductIds)return this._priceTestProductIds;const e=new Set;for(const t of this.testConfigs)for(const i of t.hypotheses)if(i.type==="price"){for(const s of i.domSelectors||[]){const r=s.cssSelector.match(/data-sl-attribute-(?:p|cap)="(\d+)"/);r?.[1]&&e.add(r[1])}if(i.priceData?.variants)for(const[s]of i.priceData.variants)e.add(s)}return this._priceTestProductIds=e,this.log("Built price test product ID cache with %d products",e.size),e}isProductInAnyPriceTest(e){return this.getPriceTestProductIds().has(e)}visitorActiveTestTypeWithReservations(){const e=this.getActiveReservations();for(const r of Object.values(e)){if(r.isThemeTest)return"theme";if(r.testType==="price")return"price"}if(Object.values(e).some(r=>!r.isRealized)){if(this.state.temporary.testCategory==="global")for(const n of Object.values(e)){if(n.testType==="theme")return"theme";if(n.testType==="price")return"price";if(n.testType==="basicScript")return"theme"}return"templateOrUrlRedirect"}const i=this.state.essential.visitorTests.filter(r=>!r.isInvalid&&this.testConfigs.some(n=>n.hypotheses.some(o=>o.id===r.hypothesisId)));return i.length===0?null:i.some(r=>this.getHypothesis(r.hypothesisId)?.type==="price")?"price":i.some(r=>r.isThemeTest)?"theme":"templateOrUrlRedirect"}applyControlForAudienceFilteredPriceTests(){const e=this.testConfigs.filter(s=>s.status==="active"&&s.hypotheses.some(r=>r.type==="price"));if(e.length===0)return;const t=this.testsFilteredByAudience.filter(s=>s.hypotheses.some(r=>r.type==="price")),i=e.filter(s=>!t.some(r=>r.id===s.id));if(i.length!==0){this.log("Found %d price tests filtered by audience, applying control selectors",i.length);for(const s of i){const r=s.hypotheses.find(c=>c.isControl),n=this.getDomSelectorsForHypothesis(r);if(n.length===0){this.log("No control selectors for audience-filtered price test '%s'",s.id);continue}const o=new URL(window.location.href);n.some(c=>{try{return new RegExp(re(c)).test(J(o.toString()))}catch{return!1}})&&(this.log("Applying control selectors for audience-filtered price test '%s'",s.id),U(document,{testId:s.id,hypothesisId:r.id,selectors:n},()=>{}),this.updatePriceTestHiddenInputs(s.id,"control",!1))}}}pickHypothesis(e){let t=Math.random();const i=e.hypotheses.reduce((r,n)=>r+n.visitorCount,0);return e.hypotheses.sort((r,n)=>r.isControl?n.isControl?0:-1:n.isControl?1:0).reduce((r,n)=>{if(r!==null)return r;const l=e.hypotheses.reduce((c,d)=>c&&d.visitorCount>20,!0)?n.visitorCount/i-n.trafficPercentage:0;return t<=n.trafficPercentage-l?n:(t-=n.trafficPercentage-l,null)},null)}typeFromTemplate(){switch(template.type){case"list-collections":return"collectionList";case"page":return"landing";case"article":case"blog":case"cart":case"collection":case"index":case"product":case"search":return template.type;default:return null}}queueRedirect(e){this.saveState(),this.disableReferrerOverride||(this.log(`Saving temporary referrer override '${document.referrer}'`),this.state.temporary.originalReferrer=document.referrer,this.persistTemporaryState()),window.setTimeout(()=>window.location.assign(e),0),window.setTimeout(()=>{this.syncAllEvents()},2e3)}scheduleRetrySync(){this.clientIdRetryCount>=5||(this.clientIdRetryCount++,window.setTimeout(()=>{this.syncAllEvents()},500))}async syncAllEvents(){const e=async()=>{if(this.isSyncing){window.setTimeout(()=>{(async()=>await e())()},500);return}try{if(this.isSyncing=!0,this.syncGAEvents(),this.shopifyAnalyticsId||(this.shopifyAnalyticsId=this.getShopifyAnalyticsId()),!this.shopifyAnalyticsId){this.scheduleRetrySync();return}await this.syncEvents()}finally{this.isSyncing=!1}};await e()}async syncEvents(){if(!this.state.essential.consentApproved||!this.shopifyAnalyticsId||this.state.analytics.queue.length===0)return;const e=this.state.analytics.queue.length,t=this.state.analytics.queue.splice(0,e);this.log("Syncing %s events",e);try{const i={shop:this.shop,visitorDetails:{shopifyAnalyticsId:this.shopifyAnalyticsId,device:this.state.analytics.visitor?.device??this.device,country:this.state.analytics.visitor?.country??null,...this.state.essential.initialState},events:this.state.essential.visitorTests.filter(r=>!r.isInvalid&&!r.isSaved&&r.hypothesisId!=null).map(r=>new Se(r.testId,r.hypothesisId,r.createdAt)).concat(t)};await this.sendEvents(i);for(const r of this.state.essential.visitorTests.filter(n=>!n.isInvalid&&!n.isSaved&&n.hypothesisId!=null))this.sendDiagnosticTelemetry("event-delivered",r.testId,{hypothesisId:r.hypothesisId,isControl:r.assignedTo==="control",testType:r.testType??"unknown"});const s=await this.getVisitor(this.shopifyAnalyticsId);s!==null&&this.updateLocalVisitor(s);for(const r of this.state.essential.visitorTests.filter(n=>!n.isInvalid&&!n.isSaved))r.isSaved=!0,r.savedAt=Date.now()}catch{this.state.analytics.queue.splice(0,0,...t)}finally{this.saveState()}}syncGAEvents(){if(!this.gaConfig.sendEvents){if(fe)return;fe=!0,this.log("UseGtag is false — skipping GA Events");return}if(this.isSyncingGA){this.log("Already syncing GA - skipping GA events");return}const e=this.state.essential.visitorTests.filter(t=>t.shouldSendToGa);e.length!==0&&(this.isSyncingGA=!0,this.log("Syncing %s GA Events",e.length),Promise.allSettled(e.map(t=>this.sendGAEvent(t))).then(()=>this.log("All gtag events sent")).finally(()=>this.isSyncingGA=!1))}sendGAEvent(e){return new Promise(t=>{this.log("Sending GA Event for test %s, hypothesis %s",e.testId,e.hypothesisId);const i=()=>{this.log("GA acknowledged event for hypothesis %s",e.hypothesisId),e.shouldSendToGa=!1,this.persistEssentialState(),t()},s={exp_variant_string:`SL-${e.testId}-${e.hypothesisId}`};this.shopliftDebug&&Object.assign(s,{debug_mode:!0});function r(n,o,l){window.dataLayer=window.dataLayer||[],window.dataLayer.push(arguments)}this.gaConfig.mode==="gtag"?r("event","experience_impression",{...s,event_callback:i}):(window.dataLayer=window.dataLayer||[],window.dataLayer.push({event:"experience_impression",...s,eventCallback:i}))})}updateLocalVisitor(e){let t;({visitorTests:t,...this.state.analytics.visitor}=e),this.log("updateLocalVisitor - server returned %d tests: %o",t.length,t.map(s=>({testId:s.testId,hypothesisId:s.hypothesisId,isInvalid:s.isInvalid}))),this.log("updateLocalVisitor - local has %d tests: %o",this.state.essential.visitorTests.length,this.state.essential.visitorTests.map(s=>({testId:s.testId,hypothesisId:s.hypothesisId,isSaved:s.isSaved,isInvalid:s.isInvalid})));const i=300*1e3;for(const s of this.state.essential.visitorTests.filter(r=>r.isSaved&&(!r.savedAt||Date.now()-r.savedAt>i)&&!t.some(n=>n.testId===r.testId)))this.log("updateLocalVisitor - marking LOCAL test as INVALID (isSaved && not in server): testId=%s, hypothesisId=%s",s.testId,s.hypothesisId),s.isInvalid=!0;for(const s of t){const r=this.state.essential.visitorTests.findIndex(o=>o.testId===s.testId);if(!(r!==-1))this.log("updateLocalVisitor - ADDING server test (not found locally): testId=%s, hypothesisId=%s",s.testId,s.hypothesisId),this.state.essential.visitorTests.push(s);else{const o=this.state.essential.visitorTests.at(r);this.log("updateLocalVisitor - REPLACING local test with server test: testId=%s, local hypothesisId=%s -> server hypothesisId=%s, local isInvalid=%s -> false",s.testId,o?.hypothesisId,s.hypothesisId,o?.isInvalid),s.isInvalid=!1,s.shouldSendToGa=o?.shouldSendToGa??!1,s.testType=o?.testType,s.assignedTo=o?.assignedTo,s.testTitle=o?.testTitle,this.state.essential.visitorTests.splice(r,1,s)}}this.log("updateLocalVisitor - FINAL local tests: %o",this.state.essential.visitorTests.map(s=>({testId:s.testId,hypothesisId:s.hypothesisId,isSaved:s.isSaved,isInvalid:s.isInvalid}))),this.state.analytics.visitor.storedAt=new Date}async getVisitor(e){try{return await this.makeJsonRequest({method:"get",url:`${this.eventHost}/api/v0/visitors/by-key/${this.shop}/${e}`})}catch{return null}}async sendEvents(e){await this.makeRequest({method:"post",url:`${this.eventHost}/api/v0/events`,data:JSON.stringify(e)})}sendDiagnosticTelemetry(e,t,i){if(!this.telemetryEnabled||!navigator.sendBeacon)return;const s=this.state.essential.consentApproved,r=JSON.stringify({shop:this.shop,testId:t,checkpoint:e,device:this.device,...s?{visitorId:this.shopifyAnalyticsId??"unknown"}:{},clientTimestamp:Date.now(),consentApproved:s,hasConsentInteraction:this.state.essential.hasConsentInteraction,...i});navigator.sendBeacon(`${this.eventHost}/api/v0/telemetry`,new Blob([r],{type:"text/plain"}))}getUTMValue(e){return new URLSearchParams(window.location.search).get(e)||null}hidePage(e){this.log("Hiding page"),this.cssHideClass&&!window.document.documentElement.classList.contains(this.cssHideClass)&&(window.document.documentElement.classList.add(this.cssHideClass),e||setTimeout(this.removeAsyncHide(this.cssHideClass),2e3))}showPage(){this.cssHideClass&&this.removeAsyncHide(this.cssHideClass)()}getDeviceType(){function e(){let i=!1;return(function(s){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(s)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(s.substr(0,4)))&&(i=!0)})(navigator.userAgent||navigator.vendor),i}function t(){let i=!1;return(function(s){(/android|ipad|playbook|silk/i.test(s)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(s.substr(0,4)))&&(i=!0)})(navigator.userAgent||navigator.vendor),i}return e()?"mobile":t()?"tablet":"desktop"}removeAsyncHide(e){return()=>{e&&window.document.documentElement.classList.remove(e)}}async getCartState(){try{let e=await this.makeJsonRequest({method:"get",url:`${window.location.origin}/cart.js`});return e===null||(e.note===null&&(e=await this.makeJsonRequest({method:"post",url:`${window.location.origin}/cart/update.js`,data:JSON.stringify({note:""})})),e==null)?null:{token:e.token,total_price:e.total_price,total_discount:e.total_discount,currency:e.currency,items_subtotal_price:e.items_subtotal_price,items:e.items.map(t=>({quantity:t.quantity,variant_id:t.variant_id,key:t.key,price:t.price,final_line_price:t.final_line_price,sku:t.sku,product_id:t.product_id}))}}catch(e){return this.log("Error sending cart info",e),null}}ensureCartAttributesForExistingPriceTests(e){try{if(this.log("Checking visitor assignments for active price tests"),e&&this.state.temporary.previewConfig){const t=this.state.temporary.previewConfig;this.log("Using preview config for merchant:",t.testId);let i="variant";if(t.variants&&t.variants.length>0){const s=t.variants.find(r=>r.id===t.currentVariant);s&&s.isControl&&(i="control")}this.log("Merchant preview - updating hidden inputs:",t.testId,i),this.updatePriceTestHiddenInputs(t.testId,i,!0);return}for(const t of this.state.essential.visitorTests){const i=this.testConfigs.find(n=>n.id===t.testId);if(!i){this.log("Test config not found:",t.testId);continue}const s=i.hypotheses.find(n=>n.id===t.hypothesisId);if(!s||s.type!=="price")continue;const r=s.isControl?"control":"variant";this.log("Updating hidden inputs for price test:",t.testId,r),this.updatePriceTestHiddenInputs(t.testId,r,e)}}catch(t){this.log("Error ensuring cart attributes for existing price tests:",t)}}subscriptionSwapDone=!1;subscriptionHideWrongPlans=null;subscriptionPriceDone=!1;subscriptionUpdateOneTime=null;subscriptionOneTimeDone=!1;swapMap=null;slptValue=null;async subscriptionSwap(){await ze(this)}async subscriptionPriceChange(){await Ge(this)}async subscriptionOneTimePrice(){await je(this)}updatePriceTestHiddenInputs(e,t,i){try{this.cleanupPriceTestObservers();const s=`${e}:${t}:${i?"t":"f"}`,r=T=>{const m=T.getAttribute("data-sl-pid");if(!m)return!0;if(i&&this.state.temporary.previewConfig){const w=this.state.temporary.previewConfig,I=t==="control"?"a":"b",f=w.variants.find(v=>v.label===I);if(!f)return!1;for(const v of f.domSelectors||[]){const g=v.cssSelector.match(/data-sl-attribute-(?:p|cap)="(\d+)"/);if(g){const P=g[1];if(this.log(`Extracted ID from selector: ${P}, comparing to: ${m}`),P===m)return this.log("Product ID match found in preview config:",m,"variant:",f.label),!0}else this.log(`Could not extract ID from selector: ${v.cssSelector}`)}return this.log("No product ID match in preview config for:",m,"variant:",I),!1}const y=this.testConfigs.find(w=>w.id===e);if(!y)return this.log("Test config not found for testId:",e),!1;for(const w of y.hypotheses||[]){for(const I of w.domSelectors||[]){const f=I.cssSelector.match(/data-sl-attribute-(?:p|cap)="(\d+)"/);if(f&&f[1]===m)return this.log("Product ID match found in domSelectors:",m,"for test:",e),!0}if(w.priceData?.variants){for(const I of w.priceData.variants)if(I[0]===m)return this.log("Product ID match found in priceData:",m,"for test:",e),!0}}return this.log("No product ID match for:",m,"in test:",e),!1},n=new Set;let o=!1,l=null;const c=(T,m)=>{if(document.querySelectorAll("[data-sl-attribute-p]").forEach(w=>{if(w instanceof Element&&w.nodeType===Node.ELEMENT_NODE&&w.isConnected&&document.contains(w))try{T.observe(w,{childList:!0,subtree:!0,characterData:!0,characterDataOldValue:!0,attributes:!1})}catch(I){this.log(`Failed to observe element (${m}):`,I)}}),document.body&&document.body.isConnected)try{T.observe(document.body,{childList:!0,subtree:!0,characterData:!0,characterDataOldValue:!0,attributes:!1})}catch(w){this.log(`Failed to observe document.body (${m}):`,w)}},d=(T,m,y,w)=>{const I=T.filter(f=>{const v=f.cssSelector.match(/data-sl-attribute-(?:p|cap)="(\d+)"/);return v&&v[1]===w});this.log(`Applying ${y} DOM selectors, total: ${T.length}, filtered: ${I.length}`),I.length>0&&U(document,{testId:e,hypothesisId:m,selectors:I})},p=(T,m)=>{this.log(`Applying DOM selector changes for product ID: ${T}`),m.disconnect(),o=!0;try{if(i&&this.state.temporary.previewConfig){const y=t==="control"?"a":"b",w=this.state.temporary.previewConfig.variants.find(I=>I.label===y);if(!w?.domSelectors){this.log(`No DOM selectors found for preview variant: ${y}`);return}d(w.domSelectors,w.id,"preview config",T)}else{const y=this.testConfigs.find(I=>I.id===e);if(!y){this.log(`No test config found for testId: ${e}`);return}const w=y.hypotheses.find(I=>t==="control"?I.isControl:!I.isControl);if(!w?.domSelectors){this.log(`No DOM selectors found for assignment: ${t}`);return}d(w.domSelectors,w.id,"live config",T)}}finally{l!==null&&clearTimeout(l),l=window.setTimeout(()=>{o=!1,l=null,c(m,"reconnection"),this.log("Re-established innerHTML observer after DOM changes")},50)}},h=new MutationObserver(T=>{if(!o)for(const m of T){if(m.type!=="childList"&&m.type!=="characterData")continue;let y=m.target;m.type==="characterData"&&(y=m.target.parentElement||m.target.parentNode);let w=y,I=w.getAttribute("data-sl-attribute-p");for(;!I&&w.parentElement;)w=w.parentElement,I=w.getAttribute("data-sl-attribute-p");if(!I)continue;const f=w.innerHTML||w.textContent||"";let v="";m.type==="characterData"&&m.oldValue!==null&&(v=m.oldValue),this.log(`innerHTML changed on element with data-sl-attribute-p="${I}"`),v&&this.log(`Previous content: "${v}"`),this.log(`Current content: "${f}"`),p(I,h)}});c(h,"initial setup"),n.add(h);const u=new MutationObserver(T=>{T.forEach(m=>{m.addedNodes.forEach(y=>{if(y.nodeType===Node.ELEMENT_NODE){const w=y;E(w);const I=w.matches('input[name="properties[_slpt]"]')?[w]:w.querySelectorAll('input[name="properties[_slpt]"]');I.length>0&&this.log(`MutationObserver found ${I.length} new hidden input(s)`),I.forEach(f=>{const v=f.getAttribute("data-sl-pid");if(this.log(`MutationObserver checking new input with data-sl-pid="${v}"`),r(f))f.value!==s&&(f.value=s,this.log("Updated newly added hidden input:",s)),S(f);else{const g=f.getAttribute("data-sl-pid");g&&this.isProductInAnyPriceTest(g)?this.log("Preserving hidden input for product ID '%s' - belongs to a different price test",g):(f.remove(),this.log("Removed newly added non-matching hidden input for product ID:",g))}})}})})});n.add(u);const b=new MutationObserver(T=>{T.forEach(m=>{if(m.type==="attributes"&&m.attributeName==="data-sl-pid"){const y=m.target;if(this.log("AttributeObserver detected data-sl-pid attribute change on:",y.tagName),y.matches('input[name="properties[_slpt]"]')){const w=y,I=m.oldValue,f=w.getAttribute("data-sl-pid");this.log(`data-sl-pid changed from "${I}" to "${f}" - triggering payment placement updates`),r(w)?(w.value!==s&&(w.value=s,this.log("Updated hidden input after data-sl-pid change:",s)),f&&p(f,h),this.log("Re-running payment placement updates after variant change"),E(document.body)):f&&this.isProductInAnyPriceTest(f)?this.log("Preserving hidden input for product ID '%s' - belongs to a different price test",f):(w.remove(),this.log("Removed non-matching hidden input after data-sl-pid change:",f))}}})});n.add(b);const E=T=>{T.tagName==="SHOPIFY-PAYMENT-TERMS"&&(this.log("MutationObserver found new shopify-payment-terms element"),this.updateShopifyPaymentTerms(e,t));const m=T.querySelectorAll("shopify-payment-terms");m.length>0&&(this.log(`MutationObserver found ${m.length} shopify-payment-terms in added node`),this.updateShopifyPaymentTerms(e,t)),T.tagName==="AFTERPAY-PLACEMENT"&&(this.log("MutationObserver found new afterpay-placement element"),this.updateAfterpayPlacements(e,t,"afterpay"));const y=T.querySelectorAll("afterpay-placement");y.length>0&&(this.log(`MutationObserver found ${y.length} afterpay-placement in added node`),this.updateAfterpayPlacements(e,t,"afterpay")),T.tagName==="SQUARE-PLACEMENT"&&(this.log("MutationObserver found new square-placement element"),this.updateAfterpayPlacements(e,t,"square"));const w=T.querySelectorAll("square-placement");w.length>0&&(this.log(`MutationObserver found ${w.length} square-placement in added node`),this.updateAfterpayPlacements(e,t,"square")),T.tagName==="KLARNA-PLACEMENT"&&(this.log("MutationObserver found new klarna-placement element"),this.updateKlarnaPlacements(e,t));const I=T.querySelectorAll("klarna-placement");I.length>0&&(this.log(`MutationObserver found ${I.length} klarna-placement in added node`),this.updateKlarnaPlacements(e,t))},S=T=>{b.observe(T,{attributes:!0,attributeFilter:["data-sl-pid"],attributeOldValue:!0,subtree:!1});const m=T.getAttribute("data-sl-pid");this.log(`Started AttributeObserver on specific input with data-sl-pid="${m}"`)},C=()=>{const T=document.querySelectorAll('input[name="properties[_slpt]"]');this.log(`Found ${T.length} existing hidden inputs to check`),T.forEach(m=>{const y=m.getAttribute("data-sl-pid");this.log(`Checking existing input with data-sl-pid="${y}"`),r(m)?(m.value=s,this.log("Updated existing hidden input:",s),y&&(this.log("Applying initial DOM selector changes for existing product"),p(y,h)),S(m)):y&&this.isProductInAnyPriceTest(y)?this.log("Preserving hidden input for product ID '%s' - belongs to a different price test",y):(m.remove(),this.log("Removed non-matching hidden input for product ID:",y))})},_=()=>{document.body?(u.observe(document.body,{childList:!0,subtree:!0}),this.log("Started MutationObserver on document.body"),C(),E(document.body)):document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{document.body&&(u.observe(document.body,{childList:!0,subtree:!0}),this.log("Started MutationObserver after DOMContentLoaded"),C(),E(document.body))}):(this.log("Set timeout on observer"),setTimeout(_,10))};_(),window.__shopliftPriceTestObservers=n,window.__shopliftPriceTestValue=s,this.log("Set up DOM observer for price test hidden inputs")}catch(s){this.log("Error updating price test hidden inputs:",s)}}updateKlarnaPlacements(e,t){this.updatePlacementElements(e,t,"klarna-placement",(i,s)=>{i.setAttribute("data-purchase-amount",s.toString())})}cleanupPriceTestObservers(){const e=window.__shopliftPriceTestObservers;e&&(e.forEach(t=>{t.disconnect()}),e.clear(),this.log("Cleaned up existing price test observers")),delete window.__shopliftPriceTestObservers,delete window.__shopliftPriceTestValue}updateAfterpayPlacements(e,t,i="afterpay"){const s=i==="square"?"square-placement":"afterpay-placement";if(document.querySelectorAll(s).length===0){this.log(`No ${s} elements found on page - early return`);return}this.updatePlacementElements(e,t,s,(n,o)=>{if(i==="afterpay"){const l=(o/100).toFixed(2);n.setAttribute("data-amount",l)}else n.setAttribute("data-amount",o.toString())}),this.log("updateAfterpayPlacements completed")}updatePlacementElements(e,t,i,s){const r=document.querySelectorAll(i);if(r.length===0){this.log(`No ${i} elements found - early return`);return}let n;if(this.state.temporary.isMerchant&&this.state.temporary.previewConfig){const l=t==="control"?"a":"b",c=this.state.temporary.previewConfig.variants.find(d=>d.label===l);if(!c?.domSelectors){this.log(`No variant found for label ${l} in preview config for ${i}`);return}n=c.domSelectors,this.log(`Using preview config for ${i} in merchant mode, variant: ${l}`)}else{const l=this.testConfigs.find(d=>d.id===e);if(!l){this.log(`No testConfig found for id: ${e} - early return`);return}const c=l.hypotheses.find(d=>t==="control"?d.isControl:!d.isControl);if(!c?.domSelectors){this.log(`No hypothesis or domSelectors found for assignment: ${t} - early return`);return}n=c.domSelectors}const o=new RegExp(`${this.DATA_SL_ATTRIBUTE_P}=["'](\\d+)["']`);r.forEach(l=>{let c=null;const d=l.parentElement;if(d&&(c=d.querySelector('input[name="properties[_slpt]"]')),c||(c=l.querySelector('input[name="properties[_slpt]"]')),!c){this.log(`No hidden input found for ${i} element`);return}const p=c.getAttribute("data-sl-pid");if(!p){this.log("Hidden input has no data-sl-pid attribute - skipping");return}const h=n.find(S=>{const C=S.cssSelector.match(o);return C&&C[1]===p});if(!h){this.log(`No matching selector found for productId: ${p} - skipping element`);return}const u=h.actions.find(S=>S.scope==="price");if(!u?.value){this.log("No price action or value found - skipping element");return}const b=parseFloat(u.value.replace(/[^0-9.]/g,""));if(Number.isNaN(b)){this.log(`Invalid price "${u.value}" for product ${p} - skipping`);return}const E=Math.round(b*100);s(l,E)}),this.log(`updatePlacementElements completed for ${i}`)}updateShopifyPaymentTerms(e,t){const i=document.querySelectorAll("shopify-payment-terms");if(i.length===0)return;this.log("Store using shopify payments");let s;if(this.state.temporary.isMerchant&&this.state.temporary.previewConfig){const n=t==="control"?"a":"b",o=this.state.temporary.previewConfig.variants.find(l=>l.label===n);if(!o||!o.domSelectors){this.log(`No variant found for label ${n} in preview config`);return}s=o.domSelectors,this.log(`Using preview config for shopify-payment-terms in merchant mode, variant: ${n}`)}else{const n=this.testConfigs.find(l=>l.id===e);if(!n)return;const o=n.hypotheses.find(l=>t==="control"?l.isControl===!0:l.isControl===!1);if(!o||!o.domSelectors)return;s=o.domSelectors}const r=new RegExp(`${this.DATA_SL_ATTRIBUTE_P}=["'](\\d+)["']`);i.forEach(n=>{const o=n.getAttribute("variant-id");if(!o)return;const l=s.find(c=>{const d=c.cssSelector.match(r);return d&&d[1]===o});if(l){const c=l.actions.find(d=>d.scope==="price");if(c&&c.value){const d=n.getAttribute("shopify-meta");if(d)try{const p=JSON.parse(d);if(p.variants&&Array.isArray(p.variants)){const h=p.variants.find(u=>u.id?.toString()===o);if(h){h.full_price=c.value;const u=parseFloat(c.value.replace(/[^0-9.]/g,""));if(h.number_of_payment_terms&&h.number_of_payment_terms>1){const b=u/h.number_of_payment_terms;h.price_per_term=`$${b.toFixed(2)}`}n.setAttribute("shopify-meta",JSON.stringify(p))}}}catch(p){this.log("Error parsing/updating shoplift-meta:",p)}}}})}async makeJsonRequest(e){const t=await this.makeRequest(e);return t===null?null:JSON.parse(await t.text(),F)}async makeRequest(e){const{url:t,method:i,headers:s,data:r,signal:n}=e,o=new Headers;if(s)for(const c in s)o.append(c,s[c]);(!s||!s.Accept)&&o.append("Accept","application/json"),r!==void 0&&(!s||!s["Content-Type"])&&o.append("Content-Type","application/json"),(this.eventHost.includes("ngrok.io")||this.eventHost.includes("ngrok-free.app"))&&o.append("ngrok-skip-browser-warning","1234");const l=await this.fetch(t,{method:i,headers:o,body:r,signal:n});if(!l.ok){if(l.status===204)return null;if(l.status===422){const c=await l.json();if(typeof c<"u"&&c.isBot)throw new G}throw new Error(`Error sending shoplift request ${l.status}`)}return l}queueAddVisitorToTest(e,t){if(this.state.essential.visitorTests.some(s=>s.testId===e))return;const i=this.testConfigs.find(s=>s.id===e);if(this.state.essential.visitorTests.push({createdAt:new Date,testId:e,hypothesisId:t.id,isThemeTest:t.type==="theme",themeId:t.themeId,isSaved:!1,isInvalid:!1,shouldSendToGa:!0,testType:t.type,assignedTo:t.isControl?"control":"variant",testTitle:i?.title}),t.type==="price"){const s=t.isControl?"control":"variant";this.log("Price test assignment detected, updating cart attributes:",e,s),this.updatePriceTestHiddenInputs(e,s,!1)}}queueCartUpdate(e){this.queueEvent(new Te(e))}queuePageView(e){this.queueEvent(new Ce(e))}queueEvent(e){!this.state.essential.consentApproved&&this.state.essential.hasConsentInteraction||this.state.analytics.queue.length>10||this.state.analytics.queue.push(e)}legacyGetLocalStorageVisitor(){const e=this.localStorageGet(this.legacySessionKey);if(e)try{return JSON.parse(e,F)}catch{}return null}pruneStaleVisitorTests(){this.state.essential.visitorTests=this.state.essential.visitorTests.filter(e=>this.testConfigs.some(t=>t.id==e.testId)||this.inactiveTestConfigs.filter(t=>this.testIsPaused(t)).some(t=>t.id===e.testId))}pruneStateAndSave(){this.pruneStaleVisitorTests(),this.saveState()}saveState(){this.persistEssentialState(),this.persistAnalyticsState()}loadState(){const e=this.loadAnalyticsState(),t={analytics:e,essential:this.loadEssentialState(e),temporary:this.loadTemporaryState()},i=this.legacyGetLocalStorageVisitor(),s=this.legacyGetCookieVisitor(),r=[i,s].filter(n=>n!==null).sort((n,o)=>+o.storedAt-+n.storedAt)[0];return t.analytics.visitor===null&&r&&({visitorTests:t.essential.visitorTests,...t.analytics.visitor}=r,t.essential.isFirstLoad=!1,t.essential.initialState={createdAt:r.createdAt,referrer:r.referrer,utmCampaign:r.utmCampaign,utmContent:r.utmContent,utmMedium:r.utmMedium,utmSource:r.utmSource,device:r.device},this.deleteCookie("SHOPLIFT"),this.deleteLocalStorage(this.legacySessionKey)),!t.essential.consentApproved&&t.essential.hasConsentInteraction&&this.deleteLocalStorage(this.analyticsSessionKey),t}loadEssentialState(e){const t=this.loadLocalStorage(this.essentialSessionKey),i=this.loadCookie(this.essentialSessionKey),s=this.getInitialState();e.visitor?.device&&(s.device=e.visitor.device);const r={timestamp:new Date,consentApproved:!1,hasConsentInteraction:!1,debugMode:!1,initialState:s,visitorTests:[],isFirstLoad:!0},n=[t,i].filter(o=>o!==null).sort((o,l)=>+l.timestamp-+o.timestamp)[0]??r;return n.initialState||(e.visitor!==null?n.initialState=e.visitor:(n.initialState=s,n.initialState.createdAt=n.timestamp)),n}loadAnalyticsState(){const e=this.loadLocalStorage(this.analyticsSessionKey),t=this.loadCookie(this.analyticsSessionKey),i={timestamp:new Date,visitor:null,queue:[]},s=[e,t].filter(r=>r!==null).sort((r,n)=>+n.timestamp-+r.timestamp)[0]??i;return s.queue.length===0&&e&&e.queue.length>1&&(s.queue=e.queue),s}loadTemporaryState(){const e=this.sessionStorageGet(this.temporarySessionKey),t=e?JSON.parse(e,F):null,i=this.loadCookie(this.temporarySessionKey);return t??i??{isMerchant:!1,timestamp:new Date}}persistEssentialState(){this.log("Persisting essential state"),this.state.essential.isFirstLoad=!1,this.state.essential.timestamp=new Date,this.persistLocalStorageState(this.essentialSessionKey,this.state.essential),this.persistCookieState(this.essentialSessionKey,this.state.essential)}persistAnalyticsState(){this.log("Persisting analytics state"),this.state.essential.consentApproved&&(this.state.analytics.timestamp=new Date,this.persistLocalStorageState(this.analyticsSessionKey,this.state.analytics),this.persistCookieState(this.analyticsSessionKey,{...this.state.analytics,queue:[]}))}persistTemporaryState(){this.log("Setting temporary session state"),this.state.temporary.timestamp=new Date,this.sessionStorageSet(this.temporarySessionKey,JSON.stringify(this.state.temporary)),this.persistCookieState(this.temporarySessionKey,this.state.temporary,!0)}loadLocalStorage(e){const t=this.localStorageGet(e);if(t===null)return null;try{return JSON.parse(t,F)}catch{return null}}loadCookie(e){const t=this.getCookie(e);if(t===null)return null;try{return JSON.parse(t,F)}catch{return null}}persistLocalStorageState(e,t){this.localStorageSet(e,JSON.stringify(t))}persistCookieState(e,t,i=!1){const s=JSON.stringify(t),r=i?"":`expires=${new Date(new Date().getTime()+864e5*365).toUTCString()};`;document.cookie=`${e}=${s};domain=.${window.location.hostname};path=/;SameSite=Strict;${r}`}deleteCookie(e){const t=new Date(0).toUTCString();document.cookie=`${e}=;domain=.${window.location.hostname};path=/;expires=${t};`}deleteLocalStorage(e){window.localStorage.removeItem(e)}getChannel(e){return[{"name":"cross-network","test":(v) => new RegExp(".*cross-network.*", "i").test(v.utmCampaign)},{"name":"direct","test":(v) => v.utmSource === "" && v.utmMedium === ""},{"name":"paid-shopping","test":(v) => (new RegExp("^(?:Google|IGShopping|aax-us-east\.amazon-adsystem\.com|aax\.amazon-adsystem\.com|alibaba|alibaba\.com|amazon|amazon\.co\.uk|amazon\.com|apps\.shopify\.com|checkout\.shopify\.com|checkout\.stripe\.com|cr\.shopping\.naver\.com|cr2\.shopping\.naver\.com|ebay|ebay\.co\.uk|ebay\.com|ebay\.com\.au|ebay\.de|etsy|etsy\.com|m\.alibaba\.com|m\.shopping\.naver\.com|mercadolibre|mercadolibre\.com|mercadolibre\.com\.ar|mercadolibre\.com\.mx|message\.alibaba\.com|msearch\.shopping\.naver\.com|nl\.shopping\.net|no\.shopping\.net|offer\.alibaba\.com|one\.walmart\.com|order\.shopping\.yahoo\.co\.jp|partners\.shopify\.com|s3\.amazonaws\.com|se\.shopping\.net|shop\.app|shopify|shopify\.com|shopping\.naver\.com|shopping\.yahoo\.co\.jp|shopping\.yahoo\.com|shopzilla|shopzilla\.com|simplycodes\.com|store\.shopping\.yahoo\.co\.jp|stripe|stripe\.com|uk\.shopping\.net|walmart|walmart\.com)$", "i").test(v.utmSource) || new RegExp("^(.*(([^a-df-z]|^)shop|shopping).*)$", "i").test(v.utmCampaign)) && new RegExp("^(.*cp.*|ppc|retargeting|paid.*)$", "i").test(v.utmMedium)},{"name":"paid-search","test":(v) => new RegExp("^(?:360\.cn|alice|aol|ar\.search\.yahoo\.com|ask|at\.search\.yahoo\.com|au\.search\.yahoo\.com|auone|avg|babylon|baidu|biglobe|biglobe\.co\.jp|biglobe\.ne\.jp|bing|br\.search\.yahoo\.com|ca\.search\.yahoo\.com|centrum\.cz|ch\.search\.yahoo\.com|cl\.search\.yahoo\.com|cn\.bing\.com|cnn|co\.search\.yahoo\.com|comcast|conduit|daum|daum\.net|de\.search\.yahoo\.com|dk\.search\.yahoo\.com|dogpile|dogpile\.com|duckduckgo|ecosia\.org|email\.seznam\.cz|eniro|es\.search\.yahoo\.com|espanol\.search\.yahoo\.com|exalead\.com|excite\.com|fi\.search\.yahoo\.com|firmy\.cz|fr\.search\.yahoo\.com|globo|go\.mail\.ru|google|google-play|hk\.search\.yahoo\.com|id\.search\.yahoo\.com|in\.search\.yahoo\.com|incredimail|it\.search\.yahoo\.com|kvasir|lens\.google\.com|lite\.qwant\.com|lycos|m\.baidu\.com|m\.naver\.com|m\.search\.naver\.com|m\.sogou\.com|mail\.rambler\.ru|mail\.yandex\.ru|malaysia\.search\.yahoo\.com|msn|msn\.com|mx\.search\.yahoo\.com|najdi|naver|naver\.com|news\.google\.com|nl\.search\.yahoo\.com|no\.search\.yahoo\.com|ntp\.msn\.com|nz\.search\.yahoo\.com|onet|onet\.pl|pe\.search\.yahoo\.com|ph\.search\.yahoo\.com|pl\.search\.yahoo\.com|play\.google\.com|qwant|qwant\.com|rakuten|rakuten\.co\.jp|rambler|rambler\.ru|se\.search\.yahoo\.com|search-results|search\.aol\.co\.uk|search\.aol\.com|search\.google\.com|search\.smt\.docomo\.ne\.jp|search\.ukr\.net|secureurl\.ukr\.net|seznam|seznam\.cz|sg\.search\.yahoo\.com|so\.com|sogou|sogou\.com|sp-web\.search\.auone\.jp|startsiden|startsiden\.no|suche\.aol\.de|terra|th\.search\.yahoo\.com|tr\.search\.yahoo\.com|tut\.by|tw\.search\.yahoo\.com|uk\.search\.yahoo\.com|ukr|us\.search\.yahoo\.com|virgilio|vn\.search\.yahoo\.com|wap\.sogou\.com|webmaster\.yandex\.ru|websearch\.rakuten\.co\.jp|yahoo|yahoo\.co\.jp|yahoo\.com|yandex|yandex\.by|yandex\.com|yandex\.com\.tr|yandex\.fr|yandex\.kz|yandex\.ru|yandex\.ua|yandex\.uz|zen\.yandex\.ru)$", "i").test(v.utmSource) && new RegExp("^(.*cp.*|ppc|retargeting|paid.*)$", "i").test(v.utmMedium)},{"name":"paid-social","test":(v) => new RegExp("^(?:43things|43things\.com|51\.com|5ch\.net|Hatena|ImageShack|academia\.edu|activerain|activerain\.com|activeworlds|activeworlds\.com|addthis|addthis\.com|airg\.ca|allnurses\.com|allrecipes\.com|alumniclass|alumniclass\.com|ameba\.jp|ameblo\.jp|americantowns|americantowns\.com|amp\.reddit\.com|ancestry\.com|anobii|anobii\.com|answerbag|answerbag\.com|answers\.yahoo\.com|aolanswers|aolanswers\.com|apps\.facebook\.com|ar\.pinterest\.com|artstation\.com|askubuntu|askubuntu\.com|asmallworld\.com|athlinks|athlinks\.com|away\.vk\.com|awe\.sm|b\.hatena\.ne\.jp|baby-gaga|baby-gaga\.com|babyblog\.ru|badoo|badoo\.com|bebo|bebo\.com|beforeitsnews|beforeitsnews\.com|bharatstudent|bharatstudent\.com|biip\.no|biswap\.org|bit\.ly|blackcareernetwork\.com|blackplanet|blackplanet\.com|blip\.fm|blog\.com|blog\.feedspot\.com|blog\.goo\.ne\.jp|blog\.naver\.com|blog\.yahoo\.co\.jp|blogg\.no|bloggang\.com|blogger|blogger\.com|blogher|blogher\.com|bloglines|bloglines\.com|blogs\.com|blogsome|blogsome\.com|blogspot|blogspot\.com|blogster|blogster\.com|blurtit|blurtit\.com|bookmarks\.yahoo\.co\.jp|bookmarks\.yahoo\.com|br\.pinterest\.com|brightkite|brightkite\.com|brizzly|brizzly\.com|business\.facebook\.com|buzzfeed|buzzfeed\.com|buzznet|buzznet\.com|cafe\.naver\.com|cafemom|cafemom\.com|camospace|camospace\.com|canalblog\.com|care\.com|care2|care2\.com|caringbridge\.org|catster|catster\.com|cbnt\.io|cellufun|cellufun\.com|centerblog\.net|chat\.zalo\.me|chegg\.com|chicagonow|chicagonow\.com|chiebukuro\.yahoo\.co\.jp|classmates|classmates\.com|classquest|classquest\.com|co\.pinterest\.com|cocolog-nifty|cocolog-nifty\.com|copainsdavant\.linternaute\.com|couchsurfing\.org|cozycot|cozycot\.com|cross\.tv|crunchyroll|crunchyroll\.com|cyworld|cyworld\.com|cz\.pinterest\.com|d\.hatena\.ne\.jp|dailystrength\.org|deluxe\.com|deviantart|deviantart\.com|dianping|dianping\.com|digg|digg\.com|diigo|diigo\.com|discover\.hubpages\.com|disqus|disqus\.com|dogster|dogster\.com|dol2day|dol2day\.com|doostang|doostang\.com|dopplr|dopplr\.com|douban|douban\.com|draft\.blogger\.com|draugiem\.lv|drugs-forum|drugs-forum\.com|dzone|dzone\.com|edublogs\.org|elftown|elftown\.com|epicurious\.com|everforo\.com|exblog\.jp|extole|extole\.com|facebook|facebook\.com|faceparty|faceparty\.com|fandom\.com|fanpop|fanpop\.com|fark|fark\.com|fb|fb\.me|fc2|fc2\.com|feedspot|feministing|feministing\.com|filmaffinity|filmaffinity\.com|flickr|flickr\.com|flipboard|flipboard\.com|folkdirect|folkdirect\.com|foodservice|foodservice\.com|forums\.androidcentral\.com|forums\.crackberry\.com|forums\.imore\.com|forums\.nexopia\.com|forums\.webosnation\.com|forums\.wpcentral\.com|fotki|fotki\.com|fotolog|fotolog\.com|foursquare|foursquare\.com|free\.facebook\.com|friendfeed|friendfeed\.com|fruehstueckstreff\.org|fubar|fubar\.com|gaiaonline|gaiaonline\.com|gamerdna|gamerdna\.com|gather\.com|geni\.com|getpocket\.com|glassboard|glassboard\.com|glassdoor|glassdoor\.com|godtube|godtube\.com|goldenline\.pl|goldstar|goldstar\.com|goo\.gl|gooblog|goodreads|goodreads\.com|google\+|googlegroups\.com|googleplus|govloop|govloop\.com|gowalla|gowalla\.com|gree\.jp|groups\.google\.com|gulli\.com|gutefrage\.net|habbo|habbo\.com|hi5|hi5\.com|hootsuite|hootsuite\.com|houzz|houzz\.com|hoverspot|hoverspot\.com|hr\.com|hu\.pinterest\.com|hubculture|hubculture\.com|hubpages\.com|hyves\.net|hyves\.nl|ibibo|ibibo\.com|id\.pinterest\.com|identi\.ca|ig|imageshack\.com|imageshack\.us|imvu|imvu\.com|in\.pinterest\.com|insanejournal|insanejournal\.com|instagram|instagram\.com|instapaper|instapaper\.com|internations\.org|interpals\.net|intherooms|intherooms\.com|irc-galleria\.net|is\.gd|italki|italki\.com|jammerdirect|jammerdirect\.com|jappy\.com|jappy\.de|kaboodle\.com|kakao|kakao\.com|kakaocorp\.com|kaneva|kaneva\.com|kin\.naver\.com|l\.facebook\.com|l\.instagram\.com|l\.messenger\.com|last\.fm|librarything|librarything\.com|lifestream\.aol\.com|line|line\.me|linkedin|linkedin\.com|listal|listal\.com|listography|listography\.com|livedoor\.com|livedoorblog|livejournal|livejournal\.com|lm\.facebook\.com|lnkd\.in|m\.blog\.naver\.com|m\.cafe\.naver\.com|m\.facebook\.com|m\.kin\.naver\.com|m\.vk\.com|m\.yelp\.com|mbga\.jp|medium\.com|meetin\.org|meetup|meetup\.com|meinvz\.net|meneame\.net|menuism\.com|messages\.google\.com|messages\.yahoo\.co\.jp|messenger|messenger\.com|mix\.com|mixi\.jp|mobile\.facebook\.com|mocospace|mocospace\.com|mouthshut|mouthshut\.com|movabletype|movabletype\.com|mubi|mubi\.com|my\.opera\.com|myanimelist\.net|myheritage|myheritage\.com|mylife|mylife\.com|mymodernmet|mymodernmet\.com|myspace|myspace\.com|netvibes|netvibes\.com|news\.ycombinator\.com|newsshowcase|nexopia|ngopost\.org|niconico|nicovideo\.jp|nightlifelink|nightlifelink\.com|ning|ning\.com|nl\.pinterest\.com|odnoklassniki\.ru|odnoklassniki\.ua|okwave\.jp|old\.reddit\.com|oneworldgroup\.org|onstartups|onstartups\.com|opendiary|opendiary\.com|oshiete\.goo\.ne\.jp|out\.reddit\.com|over-blog\.com|overblog\.com|paper\.li|partyflock\.nl|photobucket|photobucket\.com|pinboard|pinboard\.in|pingsta|pingsta\.com|pinterest|pinterest\.at|pinterest\.ca|pinterest\.ch|pinterest\.cl|pinterest\.co\.kr|pinterest\.co\.uk|pinterest\.com|pinterest\.com\.au|pinterest\.com\.mx|pinterest\.de|pinterest\.es|pinterest\.fr|pinterest\.it|pinterest\.jp|pinterest\.nz|pinterest\.ph|pinterest\.pt|pinterest\.ru|pinterest\.se|pixiv\.net|pl\.pinterest\.com|playahead\.se|plurk|plurk\.com|plus\.google\.com|plus\.url\.google\.com|pocket\.co|posterous|posterous\.com|pro\.homeadvisor\.com|pulse\.yahoo\.com|qapacity|qapacity\.com|quechup|quechup\.com|quora|quora\.com|qzone\.qq\.com|ravelry|ravelry\.com|reddit|reddit\.com|redux|redux\.com|renren|renren\.com|researchgate\.net|reunion|reunion\.com|reverbnation|reverbnation\.com|rtl\.de|ryze|ryze\.com|salespider|salespider\.com|scoop\.it|screenrant|screenrant\.com|scribd|scribd\.com|scvngr|scvngr\.com|secondlife|secondlife\.com|serverfault|serverfault\.com|shareit|sharethis|sharethis\.com|shvoong\.com|sites\.google\.com|skype|skyrock|skyrock\.com|slashdot\.org|slideshare\.net|smartnews\.com|snapchat|snapchat\.com|social|sociallife\.com\.br|socialvibe|socialvibe\.com|spaces\.live\.com|spoke|spoke\.com|spruz|spruz\.com|ssense\.com|stackapps|stackapps\.com|stackexchange|stackexchange\.com|stackoverflow|stackoverflow\.com|stardoll\.com|stickam|stickam\.com|studivz\.net|suomi24\.fi|superuser|superuser\.com|sweeva|sweeva\.com|t\.co|t\.me|tagged|tagged\.com|taggedmail|taggedmail\.com|talkbiznow|talkbiznow\.com|taringa\.net|techmeme|techmeme\.com|tencent|tencent\.com|tiktok|tiktok\.com|tinyurl|tinyurl\.com|toolbox|toolbox\.com|touch\.facebook\.com|tr\.pinterest\.com|travellerspoint|travellerspoint\.com|tripadvisor|tripadvisor\.com|trombi|trombi\.com|trustpilot|tudou|tudou\.com|tuenti|tuenti\.com|tumblr|tumblr\.com|tweetdeck|tweetdeck\.com|twitter|twitter\.com|twoo\.com|typepad|typepad\.com|unblog\.fr|urbanspoon\.com|ushareit\.com|ushi\.cn|vampirefreaks|vampirefreaks\.com|vampirerave|vampirerave\.com|vg\.no|video\.ibm\.com|vk\.com|vkontakte\.ru|wakoopa|wakoopa\.com|wattpad|wattpad\.com|web\.facebook\.com|web\.skype\.com|webshots|webshots\.com|wechat|wechat\.com|weebly|weebly\.com|weibo|weibo\.com|wer-weiss-was\.de|weread|weread\.com|whatsapp|whatsapp\.com|wiki\.answers\.com|wikihow\.com|wikitravel\.org|woot\.com|wordpress|wordpress\.com|wordpress\.org|xanga|xanga\.com|xing|xing\.com|yahoo-mbga\.jp|yammer|yammer\.com|yelp|yelp\.co\.uk|yelp\.com|youroom\.in|za\.pinterest\.com|zalo|zoo\.gr|zooppa|zooppa\.com)$", "i").test(v.utmSource) && new RegExp("^(.*cp.*|ppc|retargeting|paid.*)$", "i").test(v.utmMedium)},{"name":"paid-video","test":(v) => new RegExp("^(?:blog\.twitch\.tv|crackle|crackle\.com|curiositystream|curiositystream\.com|d\.tube|dailymotion|dailymotion\.com|dashboard\.twitch\.tv|disneyplus|disneyplus\.com|fast\.wistia\.net|help\.hulu\.com|help\.netflix\.com|hulu|hulu\.com|id\.twitch\.tv|iq\.com|iqiyi|iqiyi\.com|jobs\.netflix\.com|justin\.tv|m\.twitch\.tv|m\.youtube\.com|music\.youtube\.com|netflix|netflix\.com|player\.twitch\.tv|player\.vimeo\.com|ted|ted\.com|twitch|twitch\.tv|utreon|utreon\.com|veoh|veoh\.com|viadeo\.journaldunet\.com|vimeo|vimeo\.com|wistia|wistia\.com|youku|youku\.com|youtube|youtube\.com)$", "i").test(v.utmSource) && new RegExp("^(.*cp.*|ppc|retargeting|paid.*)$", "i").test(v.utmMedium)},{"name":"display","test":(v) => new RegExp("^(?:display|banner|expandable|interstitial|cpm)$", "i").test(v.utmMedium)},{"name":"paid-other","test":(v) => new RegExp("^(.*cp.*|ppc|retargeting|paid.*)$", "i").test(v.utmMedium)},{"name":"organic-shopping","test":(v) => new RegExp("^(?:360\.cn|alice|aol|ar\.search\.yahoo\.com|ask|at\.search\.yahoo\.com|au\.search\.yahoo\.com|auone|avg|babylon|baidu|biglobe|biglobe\.co\.jp|biglobe\.ne\.jp|bing|br\.search\.yahoo\.com|ca\.search\.yahoo\.com|centrum\.cz|ch\.search\.yahoo\.com|cl\.search\.yahoo\.com|cn\.bing\.com|cnn|co\.search\.yahoo\.com|comcast|conduit|daum|daum\.net|de\.search\.yahoo\.com|dk\.search\.yahoo\.com|dogpile|dogpile\.com|duckduckgo|ecosia\.org|email\.seznam\.cz|eniro|es\.search\.yahoo\.com|espanol\.search\.yahoo\.com|exalead\.com|excite\.com|fi\.search\.yahoo\.com|firmy\.cz|fr\.search\.yahoo\.com|globo|go\.mail\.ru|google|google-play|hk\.search\.yahoo\.com|id\.search\.yahoo\.com|in\.search\.yahoo\.com|incredimail|it\.search\.yahoo\.com|kvasir|lens\.google\.com|lite\.qwant\.com|lycos|m\.baidu\.com|m\.naver\.com|m\.search\.naver\.com|m\.sogou\.com|mail\.rambler\.ru|mail\.yandex\.ru|malaysia\.search\.yahoo\.com|msn|msn\.com|mx\.search\.yahoo\.com|najdi|naver|naver\.com|news\.google\.com|nl\.search\.yahoo\.com|no\.search\.yahoo\.com|ntp\.msn\.com|nz\.search\.yahoo\.com|onet|onet\.pl|pe\.search\.yahoo\.com|ph\.search\.yahoo\.com|pl\.search\.yahoo\.com|play\.google\.com|qwant|qwant\.com|rakuten|rakuten\.co\.jp|rambler|rambler\.ru|se\.search\.yahoo\.com|search-results|search\.aol\.co\.uk|search\.aol\.com|search\.google\.com|search\.smt\.docomo\.ne\.jp|search\.ukr\.net|secureurl\.ukr\.net|seznam|seznam\.cz|sg\.search\.yahoo\.com|so\.com|sogou|sogou\.com|sp-web\.search\.auone\.jp|startsiden|startsiden\.no|suche\.aol\.de|terra|th\.search\.yahoo\.com|tr\.search\.yahoo\.com|tut\.by|tw\.search\.yahoo\.com|uk\.search\.yahoo\.com|ukr|us\.search\.yahoo\.com|virgilio|vn\.search\.yahoo\.com|wap\.sogou\.com|webmaster\.yandex\.ru|websearch\.rakuten\.co\.jp|yahoo|yahoo\.co\.jp|yahoo\.com|yandex|yandex\.by|yandex\.com|yandex\.com\.tr|yandex\.fr|yandex\.kz|yandex\.ru|yandex\.ua|yandex\.uz|zen\.yandex\.ru)$", "i").test(v.utmSource) || new RegExp("^(.*(([^a-df-z]|^)shop|shopping).*)$", "i").test(v.utmCampaign)},{"name":"organic-social","test":(v) => new RegExp("^(?:43things|43things\.com|51\.com|5ch\.net|Hatena|ImageShack|academia\.edu|activerain|activerain\.com|activeworlds|activeworlds\.com|addthis|addthis\.com|airg\.ca|allnurses\.com|allrecipes\.com|alumniclass|alumniclass\.com|ameba\.jp|ameblo\.jp|americantowns|americantowns\.com|amp\.reddit\.com|ancestry\.com|anobii|anobii\.com|answerbag|answerbag\.com|answers\.yahoo\.com|aolanswers|aolanswers\.com|apps\.facebook\.com|ar\.pinterest\.com|artstation\.com|askubuntu|askubuntu\.com|asmallworld\.com|athlinks|athlinks\.com|away\.vk\.com|awe\.sm|b\.hatena\.ne\.jp|baby-gaga|baby-gaga\.com|babyblog\.ru|badoo|badoo\.com|bebo|bebo\.com|beforeitsnews|beforeitsnews\.com|bharatstudent|bharatstudent\.com|biip\.no|biswap\.org|bit\.ly|blackcareernetwork\.com|blackplanet|blackplanet\.com|blip\.fm|blog\.com|blog\.feedspot\.com|blog\.goo\.ne\.jp|blog\.naver\.com|blog\.yahoo\.co\.jp|blogg\.no|bloggang\.com|blogger|blogger\.com|blogher|blogher\.com|bloglines|bloglines\.com|blogs\.com|blogsome|blogsome\.com|blogspot|blogspot\.com|blogster|blogster\.com|blurtit|blurtit\.com|bookmarks\.yahoo\.co\.jp|bookmarks\.yahoo\.com|br\.pinterest\.com|brightkite|brightkite\.com|brizzly|brizzly\.com|business\.facebook\.com|buzzfeed|buzzfeed\.com|buzznet|buzznet\.com|cafe\.naver\.com|cafemom|cafemom\.com|camospace|camospace\.com|canalblog\.com|care\.com|care2|care2\.com|caringbridge\.org|catster|catster\.com|cbnt\.io|cellufun|cellufun\.com|centerblog\.net|chat\.zalo\.me|chegg\.com|chicagonow|chicagonow\.com|chiebukuro\.yahoo\.co\.jp|classmates|classmates\.com|classquest|classquest\.com|co\.pinterest\.com|cocolog-nifty|cocolog-nifty\.com|copainsdavant\.linternaute\.com|couchsurfing\.org|cozycot|cozycot\.com|cross\.tv|crunchyroll|crunchyroll\.com|cyworld|cyworld\.com|cz\.pinterest\.com|d\.hatena\.ne\.jp|dailystrength\.org|deluxe\.com|deviantart|deviantart\.com|dianping|dianping\.com|digg|digg\.com|diigo|diigo\.com|discover\.hubpages\.com|disqus|disqus\.com|dogster|dogster\.com|dol2day|dol2day\.com|doostang|doostang\.com|dopplr|dopplr\.com|douban|douban\.com|draft\.blogger\.com|draugiem\.lv|drugs-forum|drugs-forum\.com|dzone|dzone\.com|edublogs\.org|elftown|elftown\.com|epicurious\.com|everforo\.com|exblog\.jp|extole|extole\.com|facebook|facebook\.com|faceparty|faceparty\.com|fandom\.com|fanpop|fanpop\.com|fark|fark\.com|fb|fb\.me|fc2|fc2\.com|feedspot|feministing|feministing\.com|filmaffinity|filmaffinity\.com|flickr|flickr\.com|flipboard|flipboard\.com|folkdirect|folkdirect\.com|foodservice|foodservice\.com|forums\.androidcentral\.com|forums\.crackberry\.com|forums\.imore\.com|forums\.nexopia\.com|forums\.webosnation\.com|forums\.wpcentral\.com|fotki|fotki\.com|fotolog|fotolog\.com|foursquare|foursquare\.com|free\.facebook\.com|friendfeed|friendfeed\.com|fruehstueckstreff\.org|fubar|fubar\.com|gaiaonline|gaiaonline\.com|gamerdna|gamerdna\.com|gather\.com|geni\.com|getpocket\.com|glassboard|glassboard\.com|glassdoor|glassdoor\.com|godtube|godtube\.com|goldenline\.pl|goldstar|goldstar\.com|goo\.gl|gooblog|goodreads|goodreads\.com|google\+|googlegroups\.com|googleplus|govloop|govloop\.com|gowalla|gowalla\.com|gree\.jp|groups\.google\.com|gulli\.com|gutefrage\.net|habbo|habbo\.com|hi5|hi5\.com|hootsuite|hootsuite\.com|houzz|houzz\.com|hoverspot|hoverspot\.com|hr\.com|hu\.pinterest\.com|hubculture|hubculture\.com|hubpages\.com|hyves\.net|hyves\.nl|ibibo|ibibo\.com|id\.pinterest\.com|identi\.ca|ig|imageshack\.com|imageshack\.us|imvu|imvu\.com|in\.pinterest\.com|insanejournal|insanejournal\.com|instagram|instagram\.com|instapaper|instapaper\.com|internations\.org|interpals\.net|intherooms|intherooms\.com|irc-galleria\.net|is\.gd|italki|italki\.com|jammerdirect|jammerdirect\.com|jappy\.com|jappy\.de|kaboodle\.com|kakao|kakao\.com|kakaocorp\.com|kaneva|kaneva\.com|kin\.naver\.com|l\.facebook\.com|l\.instagram\.com|l\.messenger\.com|last\.fm|librarything|librarything\.com|lifestream\.aol\.com|line|line\.me|linkedin|linkedin\.com|listal|listal\.com|listography|listography\.com|livedoor\.com|livedoorblog|livejournal|livejournal\.com|lm\.facebook\.com|lnkd\.in|m\.blog\.naver\.com|m\.cafe\.naver\.com|m\.facebook\.com|m\.kin\.naver\.com|m\.vk\.com|m\.yelp\.com|mbga\.jp|medium\.com|meetin\.org|meetup|meetup\.com|meinvz\.net|meneame\.net|menuism\.com|messages\.google\.com|messages\.yahoo\.co\.jp|messenger|messenger\.com|mix\.com|mixi\.jp|mobile\.facebook\.com|mocospace|mocospace\.com|mouthshut|mouthshut\.com|movabletype|movabletype\.com|mubi|mubi\.com|my\.opera\.com|myanimelist\.net|myheritage|myheritage\.com|mylife|mylife\.com|mymodernmet|mymodernmet\.com|myspace|myspace\.com|netvibes|netvibes\.com|news\.ycombinator\.com|newsshowcase|nexopia|ngopost\.org|niconico|nicovideo\.jp|nightlifelink|nightlifelink\.com|ning|ning\.com|nl\.pinterest\.com|odnoklassniki\.ru|odnoklassniki\.ua|okwave\.jp|old\.reddit\.com|oneworldgroup\.org|onstartups|onstartups\.com|opendiary|opendiary\.com|oshiete\.goo\.ne\.jp|out\.reddit\.com|over-blog\.com|overblog\.com|paper\.li|partyflock\.nl|photobucket|photobucket\.com|pinboard|pinboard\.in|pingsta|pingsta\.com|pinterest|pinterest\.at|pinterest\.ca|pinterest\.ch|pinterest\.cl|pinterest\.co\.kr|pinterest\.co\.uk|pinterest\.com|pinterest\.com\.au|pinterest\.com\.mx|pinterest\.de|pinterest\.es|pinterest\.fr|pinterest\.it|pinterest\.jp|pinterest\.nz|pinterest\.ph|pinterest\.pt|pinterest\.ru|pinterest\.se|pixiv\.net|pl\.pinterest\.com|playahead\.se|plurk|plurk\.com|plus\.google\.com|plus\.url\.google\.com|pocket\.co|posterous|posterous\.com|pro\.homeadvisor\.com|pulse\.yahoo\.com|qapacity|qapacity\.com|quechup|quechup\.com|quora|quora\.com|qzone\.qq\.com|ravelry|ravelry\.com|reddit|reddit\.com|redux|redux\.com|renren|renren\.com|researchgate\.net|reunion|reunion\.com|reverbnation|reverbnation\.com|rtl\.de|ryze|ryze\.com|salespider|salespider\.com|scoop\.it|screenrant|screenrant\.com|scribd|scribd\.com|scvngr|scvngr\.com|secondlife|secondlife\.com|serverfault|serverfault\.com|shareit|sharethis|sharethis\.com|shvoong\.com|sites\.google\.com|skype|skyrock|skyrock\.com|slashdot\.org|slideshare\.net|smartnews\.com|snapchat|snapchat\.com|social|sociallife\.com\.br|socialvibe|socialvibe\.com|spaces\.live\.com|spoke|spoke\.com|spruz|spruz\.com|ssense\.com|stackapps|stackapps\.com|stackexchange|stackexchange\.com|stackoverflow|stackoverflow\.com|stardoll\.com|stickam|stickam\.com|studivz\.net|suomi24\.fi|superuser|superuser\.com|sweeva|sweeva\.com|t\.co|t\.me|tagged|tagged\.com|taggedmail|taggedmail\.com|talkbiznow|talkbiznow\.com|taringa\.net|techmeme|techmeme\.com|tencent|tencent\.com|tiktok|tiktok\.com|tinyurl|tinyurl\.com|toolbox|toolbox\.com|touch\.facebook\.com|tr\.pinterest\.com|travellerspoint|travellerspoint\.com|tripadvisor|tripadvisor\.com|trombi|trombi\.com|trustpilot|tudou|tudou\.com|tuenti|tuenti\.com|tumblr|tumblr\.com|tweetdeck|tweetdeck\.com|twitter|twitter\.com|twoo\.com|typepad|typepad\.com|unblog\.fr|urbanspoon\.com|ushareit\.com|ushi\.cn|vampirefreaks|vampirefreaks\.com|vampirerave|vampirerave\.com|vg\.no|video\.ibm\.com|vk\.com|vkontakte\.ru|wakoopa|wakoopa\.com|wattpad|wattpad\.com|web\.facebook\.com|web\.skype\.com|webshots|webshots\.com|wechat|wechat\.com|weebly|weebly\.com|weibo|weibo\.com|wer-weiss-was\.de|weread|weread\.com|whatsapp|whatsapp\.com|wiki\.answers\.com|wikihow\.com|wikitravel\.org|woot\.com|wordpress|wordpress\.com|wordpress\.org|xanga|xanga\.com|xing|xing\.com|yahoo-mbga\.jp|yammer|yammer\.com|yelp|yelp\.co\.uk|yelp\.com|youroom\.in|za\.pinterest\.com|zalo|zoo\.gr|zooppa|zooppa\.com)$", "i").test(v.utmSource) || new RegExp("^(?:social|social-network|social-media|sm|social network|social media)$", "i").test(v.utmMedium)},{"name":"organic-video","test":(v) => new RegExp("^(?:blog\.twitch\.tv|crackle|crackle\.com|curiositystream|curiositystream\.com|d\.tube|dailymotion|dailymotion\.com|dashboard\.twitch\.tv|disneyplus|disneyplus\.com|fast\.wistia\.net|help\.hulu\.com|help\.netflix\.com|hulu|hulu\.com|id\.twitch\.tv|iq\.com|iqiyi|iqiyi\.com|jobs\.netflix\.com|justin\.tv|m\.twitch\.tv|m\.youtube\.com|music\.youtube\.com|netflix|netflix\.com|player\.twitch\.tv|player\.vimeo\.com|ted|ted\.com|twitch|twitch\.tv|utreon|utreon\.com|veoh|veoh\.com|viadeo\.journaldunet\.com|vimeo|vimeo\.com|wistia|wistia\.com|youku|youku\.com|youtube|youtube\.com)$", "i").test(v.utmSource) || new RegExp("^(.*video.*)$", "i").test(v.utmMedium)},{"name":"organic-search","test":(v) => new RegExp("^(?:360\.cn|alice|aol|ar\.search\.yahoo\.com|ask|at\.search\.yahoo\.com|au\.search\.yahoo\.com|auone|avg|babylon|baidu|biglobe|biglobe\.co\.jp|biglobe\.ne\.jp|bing|br\.search\.yahoo\.com|ca\.search\.yahoo\.com|centrum\.cz|ch\.search\.yahoo\.com|cl\.search\.yahoo\.com|cn\.bing\.com|cnn|co\.search\.yahoo\.com|comcast|conduit|daum|daum\.net|de\.search\.yahoo\.com|dk\.search\.yahoo\.com|dogpile|dogpile\.com|duckduckgo|ecosia\.org|email\.seznam\.cz|eniro|es\.search\.yahoo\.com|espanol\.search\.yahoo\.com|exalead\.com|excite\.com|fi\.search\.yahoo\.com|firmy\.cz|fr\.search\.yahoo\.com|globo|go\.mail\.ru|google|google-play|hk\.search\.yahoo\.com|id\.search\.yahoo\.com|in\.search\.yahoo\.com|incredimail|it\.search\.yahoo\.com|kvasir|lens\.google\.com|lite\.qwant\.com|lycos|m\.baidu\.com|m\.naver\.com|m\.search\.naver\.com|m\.sogou\.com|mail\.rambler\.ru|mail\.yandex\.ru|malaysia\.search\.yahoo\.com|msn|msn\.com|mx\.search\.yahoo\.com|najdi|naver|naver\.com|news\.google\.com|nl\.search\.yahoo\.com|no\.search\.yahoo\.com|ntp\.msn\.com|nz\.search\.yahoo\.com|onet|onet\.pl|pe\.search\.yahoo\.com|ph\.search\.yahoo\.com|pl\.search\.yahoo\.com|play\.google\.com|qwant|qwant\.com|rakuten|rakuten\.co\.jp|rambler|rambler\.ru|se\.search\.yahoo\.com|search-results|search\.aol\.co\.uk|search\.aol\.com|search\.google\.com|search\.smt\.docomo\.ne\.jp|search\.ukr\.net|secureurl\.ukr\.net|seznam|seznam\.cz|sg\.search\.yahoo\.com|so\.com|sogou|sogou\.com|sp-web\.search\.auone\.jp|startsiden|startsiden\.no|suche\.aol\.de|terra|th\.search\.yahoo\.com|tr\.search\.yahoo\.com|tut\.by|tw\.search\.yahoo\.com|uk\.search\.yahoo\.com|ukr|us\.search\.yahoo\.com|virgilio|vn\.search\.yahoo\.com|wap\.sogou\.com|webmaster\.yandex\.ru|websearch\.rakuten\.co\.jp|yahoo|yahoo\.co\.jp|yahoo\.com|yandex|yandex\.by|yandex\.com|yandex\.com\.tr|yandex\.fr|yandex\.kz|yandex\.ru|yandex\.ua|yandex\.uz|zen\.yandex\.ru)$", "i").test(v.utmSource) || v.utmMedium.toLowerCase() === "organic"},{"name":"referral","test":(v) => new RegExp("^(?:referral|app|link)$", "i").test(v.utmMedium)},{"name":"email","test":(v) => new RegExp("^(?:email|e-mail|e_mail|e mail)$", "i").test(v.utmMedium) || new RegExp("^(?:email|e-mail|e_mail|e mail)$", "i").test(v.utmSource)},{"name":"affiliate","test":(v) => v.utmMedium.toLowerCase() === "affiliate"},{"name":"audio","test":(v) => v.utmMedium.toLowerCase() === "audio"},{"name":"sms","test":(v) => v.utmSource.toLowerCase() === "sms" || v.utmMedium.toLowerCase() === "sms"},{"name":"mobile-push-notification","test":(v) => v.utmSource.toLowerCase() === "firebase" || new RegExp("(?:.*mobile.*|.*notification.*|push$)", "i").test(v.utmMedium)}].find(i=>i.test(e))?.name??"other"}getShopifyAnalyticsId(){const e=this.getCookie("_shopify_y");if(e)return e;try{const t=this.localStorageGet("Shoplift_ClientId");if(t)return t}catch{}return null}legacyGetCookieVisitor(){const e=this.getCookie("SHOPLIFT");return e===null?null:JSON.parse(e,F)}getCookie(e,t=this.cookie){const i=t.split("; ").filter(s=>s.split("=").at(0)===e).at(0);return i===void 0?null:i.split("=").slice(1).join("=")}monitorConsentChange(){document.addEventListener("visitorConsentCollected",e=>{(async()=>await this.onConsentChange(e.detail.analyticsAllowed,!0))()}),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.loadShopifyConsentApiWithRetry()):this.loadShopifyConsentApiWithRetry()}loadShopifyConsentApiWithRetry(){let e=0;const t=()=>{this.loadShopifyConsentApi()||e++<10&&window.setTimeout(t,100)};t()}loadShopifyConsentApi(){if(window.Shopify){this.log("Loading Shopify features");const e=async()=>{if(!window.Shopify){this.log("Shopify object missing... suddenly?");return}if(window.Shopify.customerPrivacy===void 0){this.log("Shopify CustomerPrivacy api still missing, trying again in 1000ms"),t=window.setTimeout(()=>{(async()=>await e())()},1e3);return}if(this.geoViaShopify){const s=window.Shopify.customerPrivacy.getRegion?.();this.resolvedRegion=typeof s=="string"?s.replace(/-/g,""):""}const i=window.Shopify.customerPrivacy.getTrackingConsent();await this.onConsentChange(window.Shopify.customerPrivacy.analyticsProcessingAllowed(),i==="yes")};let t=window.setTimeout(()=>{(async()=>await e())()},5e3);return window.Shopify.loadFeatures([{name:"consent-tracking-api",version:"0.1"}],i=>{(async()=>{if(window.clearTimeout(t),i){this.log("Error loading consent tracking",i);return}await e()})()}),!0}return!1}async onConsentChange(e,t){try{if(this.log("Consent change detected",e,t),this.state.essential.consentApproved=e,this.state.essential.hasConsentInteraction=t,!this.state.essential.consentApproved){this.state.essential.hasConsentInteraction&&(this.state.analytics.queue.length=0),this.saveState();return}this.cookie=document.cookie,this.shopifyAnalyticsId=this.getShopifyAnalyticsId(),this.saveState(),await this.syncAllEvents()}catch(i){this.log("Error syncing on consent change",i)}}isThemePreview(){return isThemePreview||themeRole!=="main"}isAppProxyPath(){const e=["/apps/","/tools/","/a/"],t=window.location.pathname;return e.some(i=>t.startsWith(i))}clearThemeBar(e,t,i){const s=structuredClone(i);this.log("Looking for theme bar"),this.waitForElement(null,"body").then(r=>this.waitForElement(r,"#preview-bar-iframe, #PBarNextFrameWrapper").then(n=>(this.log("Found theme bar"),t&&(this.log("Removing theme bar"),n.remove()),e?this.makeRequest({url:`${this.eventHost}/api/v0/logs`,method:"post",data:JSON.stringify({...this.debugState(),stateAtEvaluation:s},te)}):Promise.resolve(null)))).catch(r=>console.error(r))}waitForElement(e,t){return new Promise(i=>{const s=document.querySelector(t);if(s){i(s);return}const r=new MutationObserver(n=>{const o=document.querySelector(t);if(o){r.disconnect(),i(o);return}});r.observe(e??document.documentElement,{childList:!0})})}setDebug(e){this.state.essential.debugMode=e,this.saveState()}log(e,...t){let i=0;const s=e.replace(/%[sdoOfF]/g,r=>{if(i>=t.length)return r;const n=t[i++];return r==="%o"||r==="%O"?JSON.stringify(n):String(n)});this.logHistory.push(`[${new Date().toISOString()}][SL] ${s}`),!(!this.state.essential.debugMode&&!this.shopliftDebug)&&console.debug(`[SL] ${e}`,...t)}debugState(){return{state:this.state,storage:{essential:this.loadLocalStorage(this.essentialSessionKey),analytics:this.loadLocalStorage(this.analyticsSessionKey)},params:{shop:this.shop,host:this.host,eventHost:this.eventHost,cssHideClass:this.cssHideClass,testConfigs:this.testConfigs,inactiveTestConfigs:this.inactiveTestConfigs,sendPageView:this.sendPageView,isShopifyMerchantCookie:this.getCookie("is_shopify_merchant"),themeId,url:window.location.href,isThemePreview,themeRole,gaConfig:this.gaConfig},logHistory:this.logHistory}}createViewportObserver(e,t={}){const{threshold:i=this.VIEWPORT_TRACK_THRESHOLD,triggerOnce:s=!0}=t,r=new Set;return new IntersectionObserver(n=>{n.forEach(o=>{if(o.isIntersecting&&!r.has(o.target)){const l=o.target,c=l.getAttribute(this.DATA_SL_TEST_ID);c&&(e(c,l),s&&r.add(l))}})},{threshold:i})}applyChangesWithViewport(e,t,i,s){const r=t.selectorsForViewportTracking??t.selectors,n=o=>{if(this.state.essential.visitorTests.some(h=>h.testId===o)||this.activeViewportObservers.has(o))return;const l=[];if(r.forEach(h=>{e.querySelectorAll(h.cssSelector).forEach(b=>l.push(b))}),l.length===0)return;let c=!1;const d=()=>{c||(c=!0,i(o),p.disconnect(),this.activeViewportObservers.delete(o))},p=this.createViewportObserver(()=>{d()},{triggerOnce:!0,...s});this.activeViewportObservers.set(o,p),this.log(`Created viewport observer for test ${o}, observing ${l.length} elements`),l.forEach(h=>{h.setAttribute(this.DATA_SL_TEST_ID,String(o)),p.observe(h)}),setTimeout(()=>{c||l.forEach(h=>{const u=h.getBoundingClientRect(),b=s?.threshold??this.VIEWPORT_TRACK_THRESHOLD,E=Math.min(u.bottom,window.innerHeight)-Math.max(u.top,0),S=Math.min(u.right,window.innerWidth)-Math.max(u.left,0);u.top<window.innerHeight&&u.bottom>0&&u.left<window.innerWidth&&u.right>0&&E>0&&S>0&&E>=u.height*b&&(this.log(`Price element already visible in viewport for test ${o}:`,h),d())})},100)};t.selectors.length>0&&U(e,t,()=>{}),Ie(e,{testId:t.testId,hypothesisId:t.hypothesisId,selectors:r},o=>{n(o)})}applyPriceTestWithMapLookup(e,t,i,s){if(!t.priceData){this.log("No price data for hypothesis '%s'",t.id);return}this.log("Hypothesis '%s' isControl=%s, priceData has %d variants",t.id,t.isControl,t.priceData.variants.length);const r=t.priceData.variants.slice(0,3);for(const[S,C,_]of r)this.log(" Sample priceData: variant=%s, price=%d, compareAt=%d",S,C,_);const n=j(t.priceData),o=new Set;for(const S of i)if(S.priceData)for(const[C]of S.priceData.variants)o.add(C);this.log("Price test Map lookup: %d products in hypothesis, %d total products to track",n.size,o.size);const l=t.priceData,c=new WeakSet;let d=!1;const p="[data-sl-attribute-p], [data-sl-attribute-cap], [data-sl-attribute-discount]",h=S=>{if(c.has(S))return;const C=S.getAttribute("data-sl-attribute-p"),_=S.getAttribute("data-sl-attribute-cap"),T=S.getAttribute("data-sl-attribute-discount"),m=C||_||T;if(!m||!o.has(m))return;c.add(S);const y=n.get(m);y&&(this.log("Applying price for product %s: %d cents (compare at: %d cents)",m,y.priceInCents,y.compareAtPriceInCents),$e(S,m,y,l),this.log("Applied price to element for product %s",m)),!d&&!this.state.essential.visitorTests.some(w=>w.testId===e)&&(S.setAttribute(this.DATA_SL_TEST_ID,String(e)),this.setupElementViewportTracking(S,e,()=>{d||(d=!0,s(e))}))},u=()=>{const S=document.querySelectorAll(p);this.log("Scanning for price elements, found: %d",S.length),S.forEach(h)},b=new MutationObserver(S=>{for(const C of S)C.type==="childList"&&C.addedNodes.forEach(_=>{if(_.nodeType===Node.ELEMENT_NODE){const T=_;(T.hasAttribute("data-sl-attribute-p")||T.hasAttribute("data-sl-attribute-cap")||T.hasAttribute("data-sl-attribute-discount"))&&h(T),T.querySelectorAll(p).forEach(h)}}),C.type==="attributes"&&C.target instanceof Element&&h(C.target)}),E=document.body||document.documentElement;b.observe(E,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-sl-attribute-p","data-sl-attribute-cap","data-sl-attribute-discount"]}),this.log("MutationObserver started for price elements"),u(),document.readyState==="loading"&&document.addEventListener("DOMContentLoaded",()=>{this.log("DOMContentLoaded - rescanning for price elements"),u()}),setTimeout(()=>{this.log("Delayed rescan for price elements"),u()},100),setTimeout(()=>{this.log("Final rescan for price elements"),u()},500)}setupElementViewportTracking(e,t,i){const s=this.VIEWPORT_TRACK_THRESHOLD,r=e.getBoundingClientRect(),n=Math.min(r.bottom,window.innerHeight)-Math.max(r.top,0),o=Math.min(r.right,window.innerWidth)-Math.max(r.left,0);if(r.top<window.innerHeight&&r.bottom>0&&r.left<window.innerWidth&&r.right>0&&n>0&&o>0&&n>=r.height*s){this.log("Price element already visible for test %s",t),i();return}const c=new IntersectionObserver(d=>{for(const p of d)if(p.isIntersecting&&p.intersectionRatio>=s){this.log("Price element entered viewport for test %s",t),c.disconnect(),i();break}},{threshold:s});c.observe(e)}debug(){const e=this.debugState();console.log(JSON.stringify(e,te,2))}}(async function(){window.shopliftInstance||(window.shopliftInstance=new et("contractor-training-center.myshopify.com","https://app.shoplift.ai","https://events.shoplift.ai",false,false,false,{"sendEvents":false,"mode":"gtag"},false,false,1000,[],[],null,false),await window.shopliftInstance.init())})();async function tt(a,e,t,i){const s=Ke({log:i});if(t)return i("[SUB-PREVIEW] A side — no overlay applied; widget renders naturally"),s;const r=a.widget.widgetType,n=e?j(e):null;let o=W(e),l=Y(a,o),c=l.discountMap,d=l.maxDiscount;function p(){const f=W(e);f!==o&&(o=f,l=Y(a,o),c=l.discountMap,d=l.maxDiscount,i(`[SUB-PREVIEW] scope refreshed currentProductId=${o??"n/a"}, maxDiscount=${d}`))}i(`[SUB-PREVIEW] side=B, currentProductId=${o??"n/a"}, maxDiscount=${d}`);function h(f){if(!e||!n)return null;const v=X(n),g=v?n.get(v):void 0;return g?{formattedVariantPrice:K(g.priceInCents,e),formattedDiscounted:K(g.priceInCents*(1-f/100),e)}:null}function u(f){const v=Z(a,f);if(!v)return d;const g=D(a,"subscriptionInput"),P=g.length?g[0].selector:'input[name="rc_plan"]',A=v.querySelector(`${P}:checked`);if(A){const k=c[A.value];if(k!==void 0)return k}return d}function b(f){const v=D(a,"subscriptionDiscount");for(const g of v)if(g.selector.includes("badge")||g.selector.includes("__badge")){const P=f.querySelector(g.selector);P?.textContent&&!P.textContent.includes(`${d}%`)&&$(P,A=>N(A,d))}}function E(f,v){const g=h(v);if(!g)return;const P=D(a,"subscriptionCompareAt");for(const A of P){const k=f.querySelector(A.selector)||f.querySelector(`[part~="${A.selector}"]`);k?.textContent&&!k.textContent.includes(g.formattedVariantPrice)&&$(k,x=>/\d/.test(x)?g.formattedVariantPrice:x)}}function S(f,v){const g=h(v);if(!g)return;const P=D(a,"subscriptionPrice");for(const A of P){const k=f.querySelector(A.selector)||f.querySelector(`[part~="${A.selector}"]`);k?.textContent&&!k.textContent.includes(g.formattedDiscounted)&&$(k,x=>/\d/.test(x)?g.formattedDiscounted:x)}}function C(f){const v=D(a,"subscriptionInput"),g=v.length?v[0].selector:'input[name="rc_plan"]',P=D(a,"subscriptionPlanDiscount"),A=P.length?P[0].selector:".rc-plans-button__discount";for(const k of Array.from(f.querySelectorAll("label"))){const x=k.querySelector(g),R=k.querySelector(A);if(x&&R?.textContent){const V=c[x.value];if(V!==void 0){const O=R.textContent.match(/[\d.]+%/)?.[0];O&&O!==`${V}%`&&$(R,L=>N(L,V))}}}}function _(f){const v=f.querySelector("select");if(v)for(const g of Array.from(v.options)){const P=c[g.value];if(P!==void 0&&g.textContent){const A=g.textContent.match(/[\d.]+%/)?.[0];A&&A!==`${P}%`&&(g.textContent=N(g.textContent,P))}}}function T(f){const v=D(a,"onetimePrice");if(!v.length||!e||!n)return;const g=X(n),P=g?n.get(g):void 0;if(!P)return;const A=K(P.priceInCents,e),k=D(a,"onetimeContainer"),x=k.length?k[0].selector:'[part~="rc-purchase-option__onetime"]',R=f.querySelector(x);if(R)for(const V of v){const O=R.querySelector(`[part~="${V.selector}"]`);O?.textContent&&!O.textContent.includes(A)&&$(O,L=>/\d/.test(L)?A:L)}}function m(f,v){const P=D(a,"subscriptionDiscount").filter(A=>A.selector.includes("benefit")||A.selector==="rc-benefits");for(const A of P){const k=f.querySelector(A.selector);if(k?.shadowRoot){for(const x of Array.from(k.shadowRoot.querySelectorAll("li")))if(x.textContent?.includes("Save")){const R=x.textContent.match(/[\d.]+%/)?.[0];R&&R!==`${v}%`&&$(x,V=>N(V,v))}}}}let y=!1;function w(){if(!y){y=!0;try{p();const f=B(a);if(!f)return;const v=u(f);b(f),E(f,v),S(f,v),T(f);const g=Z(a,f);g&&(r==="buttons"||r==="radio"?C(g):_(g)),m(f,v)}finally{y=!1}}}const I=ue({data:a,runUpdates:w});return function(){I(),s()}}const it=Object.freeze(Object.defineProperty({__proto__:null,subscriptionPreviewRender:tt},Symbol.toStringTag,{value:"Module"}))})(); })("/", { suffix: "sticky-nav", type: "article" }, "main", 164995498061, false)</script>
Thinking about pursuing a contractor license, or wondering if it's worth adding another credential to your name? Here's the reality: contractors who are Certified Construction Managers average nearly $300K a year, while those without any certification average closer to $166K.
The difference comes down to a few key factors, especially your license level, certifications, and how you structure your business.
In this guide, we'll break down:
The average contractor salary in 2025
How income varies by license level and certification
The fastest ways to increase your earning potential
On average, construction professionals earned $170,790 in total income in 2025, according to CTC's 2026 State of the Construction Profession & Salary Guide, a nationwide survey of 131 past CTC customers conducted between June and July of 2026.
That number climbed for nearly half the workforce: 47% earned more in 2025 than they did in 2024, and 54% expect to earn even more in 2026.
But the average only tells part of the story. Income varies significantly based on license level, and licensing is the single biggest predictor of what a contractor actually takes home.
Licensed contractors averaged $188,156 per year in 2025, about $68,000 more than journeyman-level license holders, and roughly $28,000 more than the average across all respondents. Moving from a journeyman license to a full contractor license is the highest-value step most tradespeople can take.
Why the Gap Exists
Licensing income gaps show up because a contractor license changes what kind of work you're allowed to do. It opens the door to running your own jobs, bidding independently, and setting your own rates instead of working under someone else's license. That single change explains most of the difference between the tiers above.
As the industry shifts, and it is shifting, unlicensed competition, labor shortages, and an aging workforce are among the top concerns contractors flagged for the year ahead, the professionals with a license and a certification behind their name are the ones positioned to keep winning work.
Key takeaway: Your earning potential is tied directly to your license level, your certifications, and how you structure your business.
Want to move into a higher income bracket? Explore CTC's licensing exam prep for your state and trade.
Why Some Contractors Earn More Than Others
Salary in construction isn't just about how many hours you put in or how many projects you take on. It's about credentials, ownership, and specialization. Here are the biggest factors that move the needle.
1. Certifications (the fastest lever you can pull)
A single credential can outweigh a decade of additional experience. Certified Construction Manager (CCM) holders average $295,307, nearly $125,000 above professionals with no certifications at all.
Every certification tier earns more than the ones below it, from OSHA credentials to project management to full CCM status. Adding even one certification is one of the fastest ways to move up the pay scale, and 72% of contractors surveyed said they plan to pursue additional licensing, most commonly a general contractor license.
2. Experience and Age (peak earnings hit mid-career, not late-career)
Earnings peak in the middle of a career, not at the end of it. Contractors ages 45 to 54 average $212,820, and those with 21 to 25 years in the trade average $232,620, the highest of any experience tier.
Notice that income doesn't rise in a straight line with age or tenure. It climbs, peaks, and gently tapers, which suggests that the credentials and business decisions made mid-career matter more than simply staying in the field longer.
3. Ownership Structure
Who you work for matters almost as much as what you're licensed to do. Self-employed professionals average $188,086, compared to $135,499 for those employed by a construction company they don't own, a gap of about $53,000.
A contractor license is what makes that kind of ownership possible in the first place.
4. Specialty
Once you're licensed and working for yourself, the niche you choose adds another layer of earning potential. Coastal and waterfront work leads the pack at $209,000 on average, followed closely by hospitality and industrial facilities.
Single-family residential, the most common specialty among respondents, still averages a respectable $154,000, but the top-earning niches show what's possible once you've built a specialty on top of your license.
How to Increase Your Contractor Income
There's no single path to earning more as a contractor, but the professionals who move up the pay scale tend to focus on the same few strategies:
Get licensed, then keep going. Moving from journeyman to contractor is the single largest jump on the pay scale, and it's a prerequisite for most of the other strategies below.
Add a certification. CCM, OSHA 30, project management, or a specialty trade certification. Every tier helps you earn more.
Consider going self-employed. Ownership carries real income upside once you have the license and reputation to support it.
Pick a specialty. Coastal, hospitality, and industrial work pay above the average, but even a well-chosen residential niche can outperform working general jobs.
Don't just chase more hours. The data shows 31 to 40 hours a week is actually the top-earning band, ahead of contractors working 60+ hours. Margin and project selection beat raw volume: 1 to 3 projects a month outearns 26 to 30 projects a month by a wide margin.
Is Contracting a Good Career?
For the right person, yes. The 2026 survey found real optimism across the trades:
76% of respondents are optimistic about the future of the industry
78% report career satisfaction
72% report satisfaction with their income
That optimism isn't unfounded. Demand for skilled labor is high, and nearly half the workforce earned more in 2025 than the year before. But like any trade, income depends on how far you take your credentials and how deliberately you position yourself.
Contractors who invest in licensing and certification are the ones seeing the biggest financial returns, and the ones best positioned to compete as unlicensed competition grows.
Take the Next Step Toward a Higher Income
Now that you know what contractors actually earn, the next step is building your own path toward the top of that pay scale. Here's how to get started:
Explore Contractor Training Center's licensing and certification exam prep courses for your state and trade
Consider what's next after your current license: a contractor license, a specialty certification, or both
With a 90% first-time pass rate and more than 60,000 professionals trained, Contractor Training Center helps you get there with exam prep built specifically for the license you're pursuing.
Source: 2026 State of the Construction Profession & Salary Guide, a nationwide survey of past Contractor Training Center customers, conducted June 8 to July 1, 2026.
See What Contractors Are Earning
Download the 2026 State of the Construction Profession & Salary Guide for the full breakdown of contractor income by license level, certification, experience, employment structure, and specialty.
Apprentices and trainees average around $160,000 in total income, though this varies by trade and region. Entry-level income climbs quickly as workers move toward journeyman and contractor licensure.
What license level pays the most?
Licensed contractors report the highest average income among license tiers, at $188,156. Adding a certification like CCM on top of a contractor license pushes average income well past $290,000.
Do I need to specialize to earn more?
No, but it helps. Specialties like coastal, hospitality, and industrial work pay above the survey average, while single-family residential, the most common specialty, still pays a solid living wage.
What's the fastest way to increase my income?
Advancing your license and adding a certification are the two most effective levers.Certifications in particular can add tens of thousands of dollars in average income without requiring years of additional experience.
Does working more hours actually pay more?
Not necessarily. The survey found that contractors working 31 to 40 hours a week out earned those working 60 or more hours. Responsibility and project selection matter more than raw hours logged.
Build your knowledge and sharpen your skills—get contractor tips, tools, and updates straight to your inbox. Sign up today!
By providing my personal information, including phone number, I consent to receive email messages, auto-dialed calls, texts, and prerecorded messages from Contractor Training Center with information and offers, including current and possible future services, customer service and billing and agree to the Terms of Service & Privacy Policy. If, at any time, you wish to opt out of electronic or text communications, reply STOP to cancel, HELP for help. Msg & data rates may apply. To opt out of email, follow the unsubscribe process on the email communication. I understand that my consent is not required to purchase, and that cancellation of purchase does not automatically revoke this consent.
Choosing a selection results in a full page refresh.