@elevateab/sdk 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +365 -101
- package/dist/ElevateAnalytics-Cp5iR7dJ.d.cts +48 -0
- package/dist/ElevateAnalytics-Cp5iR7dJ.d.ts +48 -0
- package/dist/cartAttributes-4XA3JSEP.js +2 -0
- package/dist/cartAttributes-4XA3JSEP.js.map +1 -0
- package/dist/cartAttributes-NW2TWOYC.js +3 -0
- package/dist/cartAttributes-NW2TWOYC.js.map +1 -0
- package/dist/chunk-4D5I75NE.js +19 -0
- package/dist/chunk-4D5I75NE.js.map +1 -0
- package/dist/chunk-VUGOZ5MR.js +18 -0
- package/dist/chunk-VUGOZ5MR.js.map +1 -0
- package/dist/chunk-XXNIBCJ6.js +2 -0
- package/dist/chunk-XXNIBCJ6.js.map +1 -0
- package/dist/hydrogen.cjs +18 -0
- package/dist/hydrogen.cjs.map +1 -0
- package/dist/hydrogen.d.cts +48 -0
- package/dist/hydrogen.d.ts +48 -0
- package/dist/hydrogen.js +2 -0
- package/dist/hydrogen.js.map +1 -0
- package/dist/index.cjs +40 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1433 -33
- package/dist/index.d.ts +1433 -33
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/dist/next.cjs +42 -0
- package/dist/next.cjs.map +1 -0
- package/dist/next.d.cts +734 -0
- package/dist/next.d.ts +734 -0
- package/dist/next.js +26 -0
- package/dist/next.js.map +1 -0
- package/package.json +31 -4
package/dist/index.js
CHANGED
|
@@ -1,2 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
import{a as ne,b as M,c as m,d,e as ke,f as be,g as $,h as q,i as _e,j as W,k as j,l as Ce,m as J,n as Ge}from"./chunk-XXNIBCJ6.js";import{A as ee,B as Oe,C as Fe,D as Ne,E as ze,c as H,d as x,e as P,f as I,g as Te,h as B,i as Q,j as F,k as xe,l as D,m as Ae,n as Y,o as Se,p as K,q as Ee,r as Ue,s as Ie,t as Re,u as Le,v as X,w as Ve,x as Be,y as De,z as Z}from"./chunk-VUGOZ5MR.js";function ie(e){let t=I("ABAU")||{};t[e]||(t[e]=!0,x("ABAU",JSON.stringify(t)))}function ae(e){let t=F("ABAV")||{};t[e]||(t[e]=!0,B("ABAV",t))}function te(e){ie(e),ae(e)}function Me(e){return!!(F("ABAV")||{})[e]}function $e(e){return!!(I("ABAU")||{})[e]}function qe(){if(typeof navigator>"u")return"desktop";let e=navigator.userAgent||navigator.vendor||window.opera||"",t=e.toLowerCase();return/windows nt.*tablet pc|pixelbook/i.test(e)||/(?:macintosh|windows nt|win(?:95|98)|linux x86_64)/i.test(e)&&!/android|mobile|tablet|ipad|iphone|ipod/i.test(t)?"desktop":/ipad|playbook|tablet|kindle|nexus (7|10)|xoom|sm-t\d+|galaxy tab|tb-\d+|tb\d+[a-z]+|lenovo.*tb|dtab|ideatab|mediapad|matepad|honor.*pad|pad\s+\d+|mi\s+pad|redmi.*pad|xiaomi.*pad|oppo.*pad|oneplus.*pad|opd\d+|tcl.*tab|9\d{3}[a-z]|kobo|archos.*5(?!\d)|ereader|droipad/i.test(e)||/android(?!.*mobile)/i.test(t)&&!/dalvik.*miui|pocophone|mi\s+mix|edge\s+\d+|sm-g9\d+|pixel\s+\d|pixel\s+fold|advan\s+\d{4}/i.test(e)?"tablet":/android.+mobile|iphone|ipod|windows phone|blackberry|mobile|phone|kaios/i.test(t)||/^mobile;/i.test(e)||/dalvik.*miui|pocophone|mi\s+mix|pixel\s+\d|pixel\s+fold/i.test(e)?"mobile":"desktop"}function se(){if(typeof navigator>"u")return!1;let e=navigator.userAgent||navigator.vendor||window.opera;return/((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i.test(e)}function ce(){if(typeof navigator>"u")return!1;let e=navigator.userAgent||navigator.vendor||window.opera;return/(instagram)[\/ ]([-\w\.]+)/i.test(e)}function ue(){if(typeof navigator>"u")return!1;let e=navigator.userAgent||navigator.vendor||window.opera;return/musical_ly/i.test(e)}function de(){if(typeof navigator>"u")return!1;let e=navigator.userAgent||navigator.vendor||window.opera;return/(pinterest)[\/ ]([-\w\.]+)/i.test(e)}function We(){if(typeof window>"u")return"direct";let e=(document.referrer||"").toLowerCase(),t=e?new URL(e).hostname.replace("www.",""):"",r=window.location.hostname,o=se(),n=ce(),a=ue(),i=de();return o||["facebook.com","fb.com","fb.me","m.facebook.com","l.facebook.com","lm.facebook.com"].includes(t)?"facebook":n||t.includes("instagram")?"instagram":a||["tiktok.com","pangleglobal.com","ads.tiktok.com"].includes(t)?"tiktok":i||t.includes("pinterest")||t==="pin.it"?"pinterest":t.includes("google")?"google":!e||r===t?"direct":"other"}function je(e){let t={},r={};if(!e)return{assignments:t,views:r};let o=e.split("~");for(let n of o){let a=n.split("_");if(a.length>=2){let i=a[0],c=a[1],s=a[2]==="1";t[i]=c,r[i]=s}}return{assignments:t,views:r}}function N(){if(typeof window>"u")return{isPreview:!1,previewTestId:null,forcedAssignments:{},previewedViews:{}};let e=new URLSearchParams(window.location.search),r=(e.get("eabUserPreview")||P("eabUserPreview"))==="true",o=e.get("abtid");o||(o=Q("eabPreviewTestId"));let n=e.get("eab_tests")||"",{assignments:a,views:i}=je(n);return e.has("eabUserPreview")&&x("eabUserPreview","true"),e.has("abtid")&&o&&B("eabPreviewTestId",o),{isPreview:r,previewTestId:o,forcedAssignments:a,previewedViews:i}}function Je(e,t){if(!t)return!1;if(e===t)return!0;let r=e.slice(-5);return!!(r===t||t.endsWith(r)||e.endsWith(t))}function He(e,t){if(!t.isPreview)return null;if(t.forcedAssignments[e])return t.forcedAssignments[e];let r=e.slice(-5);return t.forcedAssignments[r]?t.forcedAssignments[r]:null}function le(e,t){return Object.entries(e).map(([r,o])=>{let n=r.slice(-5),a=t[r]?"1":"0";return`${n}_${o}_${a}`}).join("~")}function Qe(e,t,r){if(typeof window>"u")return;let o=new URL(window.location.href),n=le(e,t);n&&o.searchParams.set("eab_tests",n),r&&o.searchParams.set("eabUserId",r),window.history.replaceState({},"",o.toString())}function Ye(){if(!(typeof document>"u")&&(document.cookie="eabUserPreview=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;",typeof sessionStorage<"u"&&sessionStorage.removeItem("eabPreviewTestId"),typeof window<"u")){let e=new URL(window.location.href);e.searchParams.delete("eabUserPreview"),e.searchParams.delete("abtid"),e.searchParams.delete("eab_tests"),window.history.replaceState({},"",e.toString())}}function Ke(){return N().isPreview}var A={SHOPIFY_LOCALIZATION:"localization",EAB_COUNTRY:"eabCountryCode",EAB_GEO:"eabGeoLocation"};function R(){if(typeof window>"u")return null;let t=new URLSearchParams(window.location.search).get("country");if(t)return x(A.EAB_COUNTRY,t.toUpperCase()),t.toUpperCase();let r=P(A.SHOPIFY_LOCALIZATION);if(r)return r.toUpperCase();let o=P(A.EAB_COUNTRY);if(o)return o.toUpperCase();if(typeof localStorage<"u"){let n=localStorage.getItem(A.EAB_COUNTRY);if(n)return n.toUpperCase()}return null}function Xe(){let e=R(),t=P(A.EAB_GEO);if(t)try{let r=JSON.parse(t);return{country:r.country||e,region:r.region,city:r.city}}catch{}return{country:e}}function fe(e){let t=e.toUpperCase();x(A.EAB_COUNTRY,t),typeof localStorage<"u"&&localStorage.setItem(A.EAB_COUNTRY,t)}function Ze(e){e.country&&fe(e.country),x(A.EAB_GEO,JSON.stringify(e))}function pe(e,t){let r=t??R();return r?e.map(n=>n.toUpperCase()).includes(r.toUpperCase()):!1}function me(e,t){let r=t??R();return r?e.map(n=>n.toUpperCase()).includes(r.toUpperCase()):!1}function et(e){let t=R();return!e.includeCountries?.length&&!e.excludeCountries?.length?!0:!t||e.excludeCountries?.length&&me(e.excludeCountries,t)?!1:e.includeCountries?.length?pe(e.includeCountries,t):!0}var tt={US:"US",CA:"CA",GB:"GB",AU:"AU",DE:"DE",FR:"FR",JP:"JP",MX:"MX",BR:"BR",IN:"IN"},rt={NORTH_AMERICA:["US","CA","MX"],EUROPE:["GB","DE","FR","IT","ES","NL","BE","AT","CH","PL","SE","NO","DK","FI","IE","PT"],APAC:["AU","NZ","JP","KR","SG","HK","TW","TH","MY","PH","ID","VN","IN"],LATAM:["MX","BR","AR","CL","CO","PE"]};var T="eab-prevent-flicker",z="eab-flicker-styles";function ge(e=3e3){if(typeof document>"u"||document.getElementById(z))return;let t=document.createElement("style");t.id=z,t.textContent=`
|
|
2
|
+
/* Elevate AB - Flicker Prevention */
|
|
3
|
+
.${T} {
|
|
4
|
+
opacity: 0 !important;
|
|
5
|
+
pointer-events: none !important;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* Failsafe: ensure content shows after timeout via animation */
|
|
9
|
+
@keyframes eab-reveal {
|
|
10
|
+
to { opacity: 1; pointer-events: auto; }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.${T} {
|
|
14
|
+
animation: eab-reveal 0s ${e}ms forwards;
|
|
15
|
+
}
|
|
16
|
+
`;let r=document.head||document.getElementsByTagName("head")[0];r.insertBefore(t,r.firstChild)}function ve(e="body"){if(typeof document>"u")return;let t=document.querySelector(e);t&&t.classList.add(T)}function re(e="body"){if(typeof document>"u")return;let t=document.querySelector(e);t&&t.classList.remove(T)}function oe(e="body",t=3e3){if(typeof document>"u")return()=>{};ge(t),ve(e);let r=!1,o=setTimeout(()=>{r||(console.warn(`[ElevateAB] Flicker prevention timeout (${t}ms) reached. Revealing content. Check if test assignment is completing.`),re(e),r=!0)},t);return()=>{r||(clearTimeout(o),re(e),r=!0)}}function ot(){if(typeof document>"u")return;let e=document.getElementById(z);e&&e.remove(),document.querySelectorAll(`.${T}`).forEach(r=>r.classList.remove(T))}function nt(){return typeof document>"u"?!1:document.querySelector(`.${T}`)!==null}function it(e=3e3){return`
|
|
17
|
+
(function() {
|
|
18
|
+
var style = document.createElement('style');
|
|
19
|
+
style.id = '${z}';
|
|
20
|
+
style.textContent = '.${T}{opacity:0!important;pointer-events:none!important}@keyframes eab-reveal{to{opacity:1;pointer-events:auto}}.${T}{animation:eab-reveal 0s ${e}ms forwards}';
|
|
21
|
+
document.head.insertBefore(style, document.head.firstChild);
|
|
22
|
+
document.body && document.body.classList.add('${T}');
|
|
23
|
+
})();
|
|
24
|
+
`.trim()}function y(e){return e?e.includes("gid://")&&e.split("/").pop()||e:""}function at(e){return!e||!e.includes("gid://")?null:e.split("/")[3]||null}function st(e){return!!e&&e.startsWith("gid://shopify/")}function ct(){if(typeof window>"u")return;let e=window.Shopify;if(e?.currency?.active)return e.currency.active}import{useEffect as we,useRef as kt,useState as bt}from"react";var ut="https://bitter-river-9c62.support-67d.workers.dev",dt="https://d339co84ntxcme.cloudfront.net/Prod/orders",g=null;function G(e){g=e}function S(e){let t=e?.storeId||g?.storeId;return t||(console.warn("[ElevateAB] No storeId provided. Call initAnalytics() first or pass storeId to tracking function."),"")}function lt(e){return Object.entries(e).filter(([,t])=>typeof t=="string").map(([t,r])=>({test_id:t,variant_id:r}))}function ft(e,t){return Object.entries(e).filter(([r])=>typeof t[r]=="string").map(([r])=>({test_id:r,variant_id:t[r]}))}function pt(){return typeof window>"u"?!1:P("eabUserPreview")==="true"||new URLSearchParams(window.location.search).get("eabUserPreview")==="true"}function E(e,t,r){if(typeof window>"u"||pt())return null;let o=navigator.userAgent,n=window.location.pathname,a=j(n,r),{referrer:i,entryPage:c}=K(),s=W({referrer:i,entryPage:c,userAgent:o}),u=I("ABTL")||{},f=I("ABAU")||{},v=lt(u),p=ft(f,u),h=$(localStorage.getItem("shopifyCartId")),C=new Date().toISOString(),w=sessionStorage.getItem("eabIsFirstVisit")==="true",l=P("localization")||"";return{pixel_event_id:`sh-${H()}`,shop_name:e,timestamp:C,event_type:t,client_id:P("_shopify_y")||void 0,visitor_id:D(),session_id:Y(),cart_token:q(h||P("cart")),page_url:window.location.href,page_pathname:n,page_search:window.location.search,referrer_url:i,referrer_source:s?.referrer_source,previous_page:document.referrer,page_entry:c,page_entry_path:s?.page_entry_path,page_type:a,utm_medium:s?.utm_medium,utm_source:s?.utm_source,utm_campaign:s?.utm_campaign,utm_content:s?.utm_content,utm_term:s?.utm_term,gclid:s?.gclid,fbclid:s?.fbclid,pins_campaign_id:s?.pins_campaign_id,epik:s?.epik,browser_info:s?.browser_info,os_info:s?.os_info,device_type:s?.device_type,language:navigator.language,root_route:localStorage.getItem("eabRootRoute")||"",user_agent:o,user_agent_no_browser:J(o),is_first_visit:w,shopify_country:l,ab_test_assignments:v,ab_test_views:p,is_first_order:null}}async function U(e,t=ut){try{let r=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),keepalive:!0});if(!r.ok)throw new Error(`Worker error: ${r.status}`)}catch(r){console.error("[ElevateAB] Error sending analytics:",r)}}async function ye(e={}){let t=S(e);if(!t)return;let r=e.hasLocalizedPaths??g?.hasLocalizedPaths,o=e.workerUrl??g?.workerUrl,n=E(t,"page_viewed",r);if(!n)return;let a={...n,cart_currency:e.currency};await U(a,o)}async function mt(e){let t=S(e);if(!t)return;let{productId:r,productVendor:o,productPrice:n,productSku:a,currency:i}=e,c=e.hasLocalizedPaths??g?.hasLocalizedPaths,s=e.workerUrl??g?.workerUrl,u=E(t,"product_viewed",c);if(!u)return;let f={...u,cart_currency:i,product_id:y(r),product_vendor:m(o),product_price:d(n),product_sku:m(a)};await U(f,s)}async function gt(e){let t=S(e);if(!t)return;let{productId:r,variantId:o,productVendor:n,productPrice:a,productQuantity:i,productSku:c,currency:s,cartId:u}=e,f=e.hasLocalizedPaths??g?.hasLocalizedPaths,v=e.workerUrl??g?.workerUrl,p=e.storefrontAccessToken??g?.storefrontAccessToken,h=E(t,"product_added_to_cart",f);if(!h)return;let C={...h,cart_currency:s,product_id:y(r),variant_id:y(o),product_vendor:m(n),product_price:d(a),product_quantity:i,product_sku:m(c)};if(await U(C,v),u&&p)try{let{updateCartAttributes:w}=await import("./cartAttributes-4XA3JSEP.js");await w(u,{storefrontAccessToken:p})}catch(w){console.error("[ElevateAB] Failed to update cart attributes:",w)}}async function vt(e){let t=S(e);if(!t)return;let{productId:r,variantId:o,productVendor:n,productPrice:a,productQuantity:i,productSku:c,currency:s}=e,u=e.hasLocalizedPaths??g?.hasLocalizedPaths,f=e.workerUrl??g?.workerUrl,v=E(t,"product_removed_from_cart",u);if(!v)return;let p={...v,cart_currency:s,product_id:y(r),variant_id:y(o),product_vendor:m(n),product_price:d(a),product_quantity:i,product_sku:m(c)};await U(p,f)}async function wt(e){let t=S(e);if(!t)return;let{cartTotalPrice:r,cartTotalQuantity:o,cartItems:n,currency:a}=e,i=e.hasLocalizedPaths??g?.hasLocalizedPaths,c=e.workerUrl??g?.workerUrl,s=E(t,"cart_viewed",i);if(!s)return;let u={...s,cart_currency:a,cart_total_price:d(r),cart_total_quantity:o,cart_items:n?.map(f=>({product_id:y(f.productId),variant_id:y(f.variantId),product_vendor:m(f.productVendor)||"",product_price:d(f.productPrice),product_quantity:f.productQuantity??null,product_sku:m(f.productSku)||""}))};await U(u,c)}async function yt(e){let t=S(e);if(!t)return;let{searchQuery:r,currency:o}=e,n=e.hasLocalizedPaths??g?.hasLocalizedPaths,a=e.workerUrl??g?.workerUrl,i=E(t,"search_submitted",n);if(!i)return;let c={...i,cart_currency:o,search_query:m(r)};await U(c,a)}async function Pt(e){let t=S(e);if(!t)return;let{cartTotalPrice:r,cartSubtotalPrice:o,cartShippingPrice:n,cartTaxAmount:a,cartDiscountAmount:i,customerId:c,cartItems:s,currency:u}=e,f=e.hasLocalizedPaths??g?.hasLocalizedPaths,v=e.workerUrl??g?.workerUrl,p=E(t,"checkout_started",f);if(!p)return;let h=0,C=s?.map(l=>{let k=l.productQuantity??0;return h+=k,{product_id:y(l.productId),variant_id:y(l.variantId),product_vendor:m(l.productVendor)||"",vendor:m(l.productVendor)||"",product_price:d(l.productPrice),total_price:d(l.productPrice),product_quantity:k,quantity:k,product_sku:m(l.productSku)||"",sku:m(l.productSku)||"",total_discount:d(l.totalDiscount)}})||[],w={...p,cart_currency:u,cart_total_price:d(r),cart_subtotal_price:d(o),cart_total_quantity:h,cart_shipping_price:d(n),cart_tax_amount:d(a),cart_discount_amount:d(i),cart_items:C,customer_id:c};await U(w,v)}async function ht(e){let t=S(e);if(!t)return;let{orderId:r,cartTotalPrice:o,cartSubtotalPrice:n,cartShippingPrice:a,cartTaxAmount:i,cartDiscountAmount:c,customerId:s,isFirstOrder:u,noteAttributes:f,cartItems:v,currency:p}=e,h=e.hasLocalizedPaths??g?.hasLocalizedPaths,C=e.ordersWorkerUrl??g?.ordersWorkerUrl??dt,w=E(t,"checkout_completed",h);if(!w)return;let l=0,k=v?.map(b=>{let V=b.productQuantity??0;return l+=V,{product_id:y(b.productId),variant_id:y(b.variantId),product_vendor:m(b.productVendor)||"",vendor:m(b.productVendor)||"",product_price:d(b.productPrice),total_price:d(b.productPrice),product_quantity:V,quantity:V,product_sku:m(b.productSku)||"",sku:m(b.productSku)||"",total_discount:d(b.totalDiscount)}})||[],L={...w,cart_currency:p,cart_total_price:d(o),cart_subtotal_price:d(n),cart_total_quantity:l,cart_shipping_price:d(a),cart_tax_amount:d(i),cart_discount_amount:d(c),cart_items:k,order_id:r,customer_id:s,is_first_order:u??null,note_attributes:f};await U(L,C)}function _t(e){let{storeId:t,hasLocalizedPaths:r,currency:o,workerUrl:n,enabled:a=!0,pathname:i}=e,c=kt(null),[s,u]=bt(()=>i||(typeof window<"u"?window.location.pathname:""));we(()=>{i&&u(i)},[i]),we(()=>{typeof window>"u"||!a||c.current!==s&&(c.current=s,ye({storeId:t,hasLocalizedPaths:r,currency:o,workerUrl:n}))},[s,t,r,o,n,a])}import O from"react";function Ct(e){let{config:t}=M(),[r,o]=O.useState(null),[n,a]=O.useState(!0),i=O.useMemo(()=>t&&t.tests.find(s=>s.testId===e)||null,[t,e]),c=O.useRef(null);return O.useEffect(()=>{if(t===null)return;if(!i){c.current!==e&&(c.current=e,console.warn(`[ElevateAB] Test not found: ${e}`)),a(!1);return}if(!i.enabled){c.current!==`${e}-disabled`&&(c.current=`${e}-disabled`,console.warn(`[ElevateAB] Test disabled: ${e}`)),a(!1);return}if(!ee(i)){a(!1);return}let s=D(),u=Z(e,i,s);u&&(o(u),te(e)),a(!1)},[t,i,e]),{variant:r,isLoading:n,isControl:r?.isControl??!1,isA:r?.isA??!1,isB:r?.isB??!1,isC:r?.isC??!1,isD:r?.isD??!1}}import _,{useRef as Pe,useCallback as Tt}from"react";var xt=!1,At={allTests:{"price-test-001":{8606:{variationName:"Control",trafficPercentage:50,isDone:!1,isControl:!0},8607:{variationName:"Sale Price",trafficPercentage:50,isDone:!1,prices:{"41883969519701":{main:"USD",price:{USD:"599.95"},compare:{USD:"699.95"}}}},data:{name:"Snowboard Price Test",isLive:!0,settings:{afterDiscounts:!0},type:"PRICE_PLUS",filters:[],isPersonalization:!1,currencies:["USD"],handles:["the-complete-snowboard"],productIds:["7240161067093"]}},"content-test-001":{"ctrl-001":{variationName:"Control",trafficPercentage:34,isDone:!1,isControl:!0,content:{headline:"Welcome to our store",subheadline:"Shop the best products"}},"var-a-001":{variationName:"Urgency Copy",trafficPercentage:33,isDone:!1,content:{headline:"Limited Time Offer!",subheadline:"Don't miss out - sale ends soon"}},"var-b-001":{variationName:"Value Copy",trafficPercentage:33,isDone:!1,content:{headline:"Premium Quality, Great Value",subheadline:"Free shipping on orders over $50"}},data:{name:"Homepage Headline Test",isLive:!0,settings:{afterDiscounts:!0},type:"CONTENT",filters:[],isPersonalization:!1,pathnames:["/"]}},"custom-code-test-001":{10150:{variationName:"Control",trafficPercentage:50,isDone:!1,customCode:{id:"c11a582c-6b27-4263-941c-8ed123437c6b",js:"console.log('[Elevate] Control variant active');",css:"",pathnames:["*"],excludePathnames:[]},isControl:!0},10151:{variationName:"Enhanced UI",trafficPercentage:50,isDone:!1,customCode:{id:"df71546a-0a5f-4ad0-8d0f-a1bdeab05e84",js:"console.log('[Elevate] Enhanced UI variant'); document.body.style.borderTop = '3px solid #10b981';",css:".hero-section { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }",pathnames:["*"],excludePathnames:[]}},data:{name:"Custom Code Enhancement",isLive:!0,settings:{afterDiscounts:!0},type:"CUSTOM_CODE",filters:[],isPersonalization:!1,pathnames:["*"],excludePathnames:[]}},"split-url-test-001":{"split-ctrl":{variationName:"Control",trafficPercentage:50,isDone:!1,isControl:!0,splitUrlTestLinks:{default:"/collections/all"}},"split-var-a":{variationName:"New Landing Page",trafficPercentage:50,isDone:!1,splitUrlTestLinks:{default:"/collections/featured"}},data:{name:"Landing Page Split Test",isLive:!0,settings:{afterDiscounts:!0},type:"SPLIT_URL",filters:[],isPersonalization:!1,pathnames:["/promo"]}}},selectors:{selectorsV2:[]}};function St({storeId:e,storefrontAccessToken:t,preventFlickering:r=!1,flickerTimeout:o=3e3,children:n}){let[a,i]=_.useState(null),[c,s]=_.useState(null),[u,f]=_.useState(null),v=Pe(null);_.useEffect(()=>(r&&typeof window<"u"&&(v.current=oe("body",o)),()=>{v.current&&v.current()}),[r,o]),_.useEffect(()=>{typeof window>"u"||G({storeId:e,storefrontAccessToken:t})},[e,t]),_.useEffect(()=>{if(typeof window>"u")return;let w=N();s(w);let l=R();f(l)},[]);let p=Tt(()=>{v.current&&(v.current(),v.current=null)},[]);_.useEffect(()=>{async function w(){try{if(!xt){let he=X(At);i(he),p();return}let l=`https://configs.elevateab.com/config/${e}.json`,k=await fetch(l);if(k.status===404){i({tests:[],selectors:void 0}),p();return}if(!k.ok)throw new Error(`Failed to fetch config: ${k.status} ${k.statusText}`);let L=await k.json();if(L.subscriptionPaused){console.error(`[ElevateAB] Subscription is paused or stopped for store: ${e}. `+(L.subscriptionMessage||"A/B tests will not run. Please reactivate your subscription.")),i({tests:[],selectors:void 0}),p();return}if(!(Object.keys(L.allTests||{}).length>0)){i({tests:[],selectors:void 0}),p();return}let V=X(L);i(V),p()}catch(l){console.error("[ElevateAB] Failed to load config:",l),i({tests:[],selectors:void 0}),p()}}w()},[e,p]);let h=_.useMemo(()=>({config:a,storeId:e,storefrontAccessToken:t,isPreviewMode:c?.isPreview??!1,previewTestId:c?.previewTestId??null,countryCode:u}),[a,e,t,c,u]);_.useEffect(()=>{G({storeId:e,storefrontAccessToken:t})},[e,t]);let C=Pe(!1);return _.useEffect(()=>{!t&&!C.current&&(C.current=!0,console.warn("[ElevateAB] No storefrontAccessToken provided. A/B tests will work, but orders won't be attributed to test variants. Add storefrontAccessToken prop to enable order tracking."))},[t]),_.createElement(ne.Provider,{value:h},n)}var or="1.1.2",nr={enabled:!0,trackingEndpoint:"https://analytics.elevateab.com/track",cacheDuration:3600};export{Oe as CART_ATTRIBUTES_UPDATE_MUTATION,tt as COUNTRIES,nr as DEFAULT_CONFIG,Ge as ElevateAnalytics,St as ElevateProvider,rt as REGIONS,or as VERSION,Z as assignAndPersistVariant,Ee as assignVariant,le as buildEabTestsParam,Le as calculateRevenueLift,se as checkFacebookBrowser,_e as checkFacebookInstagramBrowser,ce as checkInstagramBrowser,de as checkPinterestBrowser,ue as checkTikTokBrowser,Ce as checkVisitorIdParams,q as cleanCartToken,ze as cleanupCartAttributes,ot as cleanupFlickerPrevention,Ye as clearPreviewMode,Te as deleteCookie,ct as detectShopifyCurrency,$ as extractCartToken,ke as extractProductId,be as extractProductVariantId,y as extractShopifyId,at as extractShopifyType,Re as generateExperimentId,De as getAssignedVariant,Fe as getCartAttributesPayload,P as getCookie,R as getCountryCode,qe as getDeviceType,it as getFlickerPreventionScript,Xe as getGeoLocation,I as getJsonCookie,F as getJsonSessionItem,j as getPageTypeFromPathname,N as getPreviewState,He as getPreviewVariation,K as getReferrerData,Y as getSessionId,Q as getSessionItem,Ve as getTestList,We as getTrafficSource,J as getUserAgentNoBrowser,D as getVisitorId,Me as hasSessionView,$e as hasUniqueView,Ue as hashString,ve as hideForFlicker,G as initAnalytics,Ae as initializeSessionId,xe as initializeVisitorId,ge as injectFlickerStyles,me as isCountryExcluded,pe as isCountryIncluded,nt as isFlickerPreventionActive,Ke as isInPreviewMode,Je as isPreviewTest,st as isShopifyGid,et as matchesGeoTargeting,W as parseAddViewData,re as revealAfterFlicker,d as roundToTwo,m as sanitizeString,Be as saveTestList,x as setCookie,fe as setCountryCode,Ze as setGeoLocation,Se as setReferrerData,B as setSessionItem,oe as setupFlickerPrevention,ee as shouldShowTest,gt as trackAddToCart,wt as trackCartView,ht as trackCheckoutCompleted,Pt as trackCheckoutStarted,ye as trackPageView,mt as trackProductView,vt as trackRemoveFromCart,yt as trackSearchSubmitted,ae as trackSessionView,ie as trackUniqueView,te as trackViews,Ne as updateCartAttributes,Qe as updateUrlWithTestParams,M as useElevateConfig,Ct as useExperiment,_t as usePageViewTracking,H as uuidv4,Ie as validateConfig};
|
|
2
25
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts","../src/components/Experiment.tsx","../src/contexts/ElevateContext.tsx","../src/components/ElevateProvider.tsx","../src/index.ts"],"sourcesContent":["import type { Variation, Test, BackendConfig, ElevateConfig } from \"./types\";\n\n/**\n * Assigns a variant based on weighted distribution\n */\nexport function assignVariant(\n variations: Variation[],\n userId: string\n): Variation {\n const totalWeight = variations.reduce((sum, v) => sum + v.weight, 0);\n const hash = hashString(userId);\n const normalized = hash % totalWeight;\n\n let cumulative = 0;\n for (const variation of variations) {\n cumulative += variation.weight;\n if (normalized < cumulative) {\n return variation;\n }\n }\n\n return variations[0];\n}\n\nexport function hashString(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n return Math.abs(hash);\n}\n\nexport function validateConfig(config: Test): boolean {\n if (!config.testId || !config.name) return false;\n if (!config.variations || config.variations.length === 0) return false;\n\n const totalWeight = config.variations.reduce((sum, v) => sum + v.weight, 0);\n return totalWeight === 100;\n}\n\nexport function generateExperimentId(name: string): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 9);\n const safeName = name.toLowerCase().replace(/[^a-z0-9]/g, \"-\");\n return `exp-${safeName}-${timestamp}-${random}`;\n}\n\nexport function calculateRevenueLift(\n controlRevenue: number,\n variantRevenue: number,\n controlSampleSize: number,\n variantSampleSize: number\n): { lift: number; confidence: number } {\n const controlMean = controlRevenue / controlSampleSize;\n const variantMean = variantRevenue / variantSampleSize;\n\n const lift = ((variantMean - controlMean) / controlMean) * 100;\n\n const pooledStdDev = Math.sqrt(\n (controlRevenue + variantRevenue) / (controlSampleSize + variantSampleSize)\n );\n const standardError =\n pooledStdDev * Math.sqrt(1 / controlSampleSize + 1 / variantSampleSize);\n const zScore = Math.abs(variantMean - controlMean) / standardError;\n const confidence = Math.min(99.9, zScore * 34);\n\n return { lift, confidence };\n}\n\n/**\n * Parse backend config format to SDK normalized format\n */\nexport function parseBackendConfig(backendData: BackendConfig): ElevateConfig {\n const tests: Test[] = [];\n\n for (const [testId, testData] of Object.entries(backendData.allTests)) {\n // Skip if not live\n if (!testData.data.isLive) continue;\n\n // Extract variations (all keys except 'data')\n const variations: Variation[] = [];\n for (const [key, value] of Object.entries(testData)) {\n if (key === \"data\") continue;\n\n const variation = value as BackendConfig[\"allTests\"][string][string];\n if (\n typeof variation === \"object\" &&\n variation !== null &&\n \"variationName\" in variation\n ) {\n variations.push({\n id: key,\n name: variation.variationName,\n weight: variation.trafficPercentage,\n isControl: variation.isControl,\n productId: variation.id,\n handle: variation.handle,\n price: variation.price,\n });\n }\n }\n\n // Only include tests with variations\n if (variations.length > 0) {\n tests.push({\n testId,\n name: testData.data.name,\n enabled: testData.data.isLive,\n type: testData.data.type,\n variations,\n });\n }\n }\n\n return {\n tests,\n selectors: backendData.selectors,\n };\n}\n","import React from \"react\";\nimport type { Variation, ExperimentContextValue } from \"../types\";\nimport { assignVariant } from \"../utils\";\nimport { useElevateConfig } from \"../contexts/ElevateContext\";\n\n// Internal context to pass assigned variant to VariantDisplay components\nconst ExperimentContext = React.createContext<ExperimentContextValue>({\n assignedVariantId: null,\n});\n\ninterface ExperimentProps {\n testId: string;\n userId: string;\n onVariantAssigned?: (variant: Variation) => void;\n children?: React.ReactNode;\n}\n\n/**\n * React component for A/B test experiments\n * Fetches config from ElevateProvider context based on testId\n */\nexport function Experiment({\n testId,\n userId,\n onVariantAssigned,\n children,\n}: ExperimentProps) {\n const { config } = useElevateConfig();\n const [assignedVariant, setAssignedVariant] =\n React.useState<Variation | null>(null);\n\n const testConfig = React.useMemo(() => {\n if (!config) return null;\n return config.tests.find((test) => test.testId === testId) || null;\n }, [config, testId]);\n\n React.useEffect(() => {\n if (testConfig && testConfig.enabled && testConfig.variations.length > 0) {\n const variant = assignVariant(testConfig.variations, userId);\n setAssignedVariant(variant);\n onVariantAssigned?.(variant);\n }\n }, [testConfig, userId, onVariantAssigned]);\n\n if (!testConfig || !testConfig.enabled || !assignedVariant) {\n return null;\n }\n\n return (\n <ExperimentContext.Provider value={{ assignedVariantId: assignedVariant.id }}>\n <div\n data-experiment-id={testConfig.testId}\n data-variant-id={assignedVariant.id}\n >\n {children}\n </div>\n </ExperimentContext.Provider>\n );\n}\n\ninterface VariantDisplayProps {\n variantId: string;\n children: React.ReactNode;\n}\n\nexport function VariantDisplay({ variantId, children }: VariantDisplayProps) {\n const { assignedVariantId } = React.useContext(ExperimentContext);\n\n if (!assignedVariantId) {\n return <>{children}</>;\n }\n\n if (assignedVariantId !== variantId) {\n return null;\n }\n\n return <>{children}</>;\n}\n\nexport function useExperiment(testId: string, userId: string) {\n const { config } = useElevateConfig();\n const [variant, setVariant] = React.useState<Variation | null>(null);\n const [isLoading, setIsLoading] = React.useState(true);\n\n const testConfig = React.useMemo(() => {\n if (!config) return null;\n return config.tests.find((test) => test.testId === testId) || null;\n }, [config, testId]);\n\n React.useEffect(() => {\n if (!testConfig) {\n console.error(`[ElevateAB] Test not found: ${testId}`);\n setIsLoading(false);\n return;\n }\n\n if (!testConfig.enabled) {\n console.error(`[ElevateAB] Test disabled: ${testId}`);\n setIsLoading(false);\n return;\n }\n\n const assigned = assignVariant(testConfig.variations, userId);\n setVariant(assigned);\n setIsLoading(false);\n }, [testConfig, userId, testId]);\n\n return { variant, isLoading };\n}\n","import React from \"react\";\nimport type { ElevateContextValue } from \"../types\";\n\nexport const ElevateContext = React.createContext<ElevateContextValue | null>(\n null\n);\n\n/**\n * Hook to access Elevate config from context\n */\nexport function useElevateConfig(): ElevateContextValue {\n const context = React.useContext(ElevateContext);\n\n if (context === null) {\n throw new Error(\"useElevateConfig must be used within ElevateProvider\");\n }\n\n return context;\n}\n","import React from \"react\";\nimport type {\n ElevateConfig,\n ElevateProviderProps,\n BackendConfig,\n} from \"../types\";\nimport { ElevateContext } from \"../contexts/ElevateContext\";\nimport { parseBackendConfig } from \"../utils\";\n\n// Hard-coded fallback config for development/testing\nconst FALLBACK_CONFIG: BackendConfig = {\n allTests: {\n \"test-product-title-1\": {\n data: {\n name: \"Product Title Test\",\n isLive: true,\n type: \"product-title\",\n testTrafficPercentage: 100,\n },\n \"variation-control\": {\n variationName: \"Control\",\n trafficPercentage: 50,\n isControl: true,\n },\n \"variation-test\": {\n variationName: \"Test Variation\",\n trafficPercentage: 50,\n },\n },\n \"test-price-display-1\": {\n data: {\n name: \"Price Display Test\",\n isLive: true,\n type: \"price-display\",\n testTrafficPercentage: 100,\n },\n \"variation-a\": {\n variationName: \"Standard Price\",\n trafficPercentage: 50,\n isControl: true,\n },\n \"variation-b\": {\n variationName: \"Savings Highlight\",\n trafficPercentage: 50,\n },\n },\n },\n selectors: {\n selectorsV2: [],\n },\n};\n\nconst isProduction = true;\n\nexport function ElevateProvider({ storeId, children }: ElevateProviderProps) {\n const [config, setConfig] = React.useState<ElevateConfig | null>(null);\n\n React.useEffect(() => {\n async function fetchConfig() {\n try {\n const url = `https://configs.elevateab.com/config/${storeId}.json`;\n const response = await fetch(url);\n\n if (response.status === 404) {\n if (isProduction) {\n // In production, no fallback - just empty config\n setConfig({ tests: [], selectors: undefined });\n } else {\n // In development, use fallback config\n console.warn(\n \"[ElevateAB] CDN config not found. Using fallback config for development.\"\n );\n const parsedConfig = parseBackendConfig(FALLBACK_CONFIG);\n setConfig(parsedConfig);\n }\n return;\n }\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch config: ${response.status} ${response.statusText}`\n );\n }\n\n const backendData: BackendConfig = await response.json();\n const parsedConfig = parseBackendConfig(backendData);\n setConfig(parsedConfig);\n } catch (err) {\n console.error(\"[ElevateAB] Failed to load config:\", err);\n\n if (isProduction) {\n // In production, no fallback - just empty config\n setConfig({ tests: [], selectors: undefined });\n } else {\n // In development, use fallback config\n console.warn(\n \"[ElevateAB] Using fallback config for development due to CDN error.\"\n );\n const parsedConfig = parseBackendConfig(FALLBACK_CONFIG);\n setConfig(parsedConfig);\n }\n }\n }\n\n fetchConfig();\n }, [storeId]);\n\n const value = React.useMemo(() => ({ config }), [config]);\n\n return (\n <ElevateContext.Provider value={value}>{children}</ElevateContext.Provider>\n );\n}\n","// Main entry point for the Elevate AB Testing NPM package\nexport type {\n Test,\n Variation,\n TrackingEvent,\n ExperimentStatus,\n ElevateConfig,\n ElevateProviderProps,\n ElevateContextValue,\n BackendConfig,\n} from \"./types\";\n\nexport {\n assignVariant,\n hashString,\n validateConfig,\n generateExperimentId,\n calculateRevenueLift,\n} from \"./utils\";\n\nexport {\n Experiment,\n VariantDisplay,\n useExperiment,\n} from \"./components/Experiment\";\n\nexport { ElevateProvider } from \"./components/ElevateProvider\";\nexport { useElevateConfig } from \"./contexts/ElevateContext\";\n\n// Package version\nexport const VERSION = \"1.1.0\";\n\n// Default configuration\nexport const DEFAULT_CONFIG = {\n enabled: true,\n trackingEndpoint: \"https://analytics.elevateab.com/track\",\n cacheDuration: 3600,\n};\n"],"mappings":"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","names":["assignVariant","variations","userId","totalWeight","sum","v","normalized","hashString","cumulative","variation","str","hash","i","char","validateConfig","config","generateExperimentId","name","timestamp","random","calculateRevenueLift","controlRevenue","variantRevenue","controlSampleSize","variantSampleSize","controlMean","variantMean","lift","standardError","zScore","confidence","parseBackendConfig","backendData","tests","testId","testData","key","value","React","React","ElevateContext","useElevateConfig","context","ExperimentContext","React","Experiment","testId","userId","onVariantAssigned","children","config","useElevateConfig","assignedVariant","setAssignedVariant","testConfig","test","variant","assignVariant","VariantDisplay","variantId","assignedVariantId","useExperiment","setVariant","isLoading","setIsLoading","assigned","React","FALLBACK_CONFIG","isProduction","ElevateProvider","storeId","children","config","setConfig","React","fetchConfig","url","response","parsedConfig","parseBackendConfig","backendData","err","value","ElevateContext","VERSION","DEFAULT_CONFIG"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/tracking.ts","../src/utils/conditions.ts","../src/utils/preview.ts","../src/utils/geo.ts","../src/utils/antiFlicker.ts","../src/utils/shopify.ts","../src/utils/manualTracking.ts","../src/components/Experiment.tsx","../src/components/ElevateProvider.tsx","../src/index.ts"],"sourcesContent":["/**\n * Tracking utilities for views and participation\n */\n\nimport {\n setCookie,\n setSessionItem,\n getJsonCookie,\n getJsonSessionItem,\n} from \"./storage\";\n\n/**\n * Track unique view for a test (ABAU cookie)\n */\nexport function trackUniqueView(testId: string): void {\n const addedUniqueViews = getJsonCookie<Record<string, boolean>>(\"ABAU\") || {};\n\n if (!addedUniqueViews[testId]) {\n addedUniqueViews[testId] = true;\n setCookie(\"ABAU\", JSON.stringify(addedUniqueViews));\n }\n}\n\n/**\n * Track session view for a test (ABAV session storage)\n */\nexport function trackSessionView(testId: string): void {\n const addedViews = getJsonSessionItem<Record<string, boolean>>(\"ABAV\") || {};\n\n if (!addedViews[testId]) {\n addedViews[testId] = true;\n setSessionItem(\"ABAV\", addedViews);\n }\n}\n\n/**\n * Track both unique and session views\n */\nexport function trackViews(testId: string): void {\n trackUniqueView(testId);\n trackSessionView(testId);\n}\n\n/**\n * Check if test has been viewed in this session\n */\nexport function hasSessionView(testId: string): boolean {\n const addedViews = getJsonSessionItem<Record<string, boolean>>(\"ABAV\") || {};\n return !!addedViews[testId];\n}\n\n/**\n * Check if test has a unique view\n */\nexport function hasUniqueView(testId: string): boolean {\n const addedUniqueViews = getJsonCookie<Record<string, boolean>>(\"ABAU\") || {};\n return !!addedUniqueViews[testId];\n}\n","/**\n * Condition checking utilities for targeting and filtering\n */\n\n/**\n * Detect device type\n */\nexport function getDeviceType(): \"desktop\" | \"tablet\" | \"mobile\" {\n if (typeof navigator === \"undefined\") return \"desktop\";\n\n const ua =\n navigator.userAgent || navigator.vendor || (window as any).opera || \"\";\n const lower = ua.toLowerCase();\n\n if (\n /windows nt.*tablet pc|pixelbook/i.test(ua) ||\n (/(?:macintosh|windows nt|win(?:95|98)|linux x86_64)/i.test(ua) &&\n !/android|mobile|tablet|ipad|iphone|ipod/i.test(lower))\n )\n return \"desktop\";\n\n const isTablet =\n /ipad|playbook|tablet|kindle|nexus (7|10)|xoom|sm-t\\d+|galaxy tab|tb-\\d+|tb\\d+[a-z]+|lenovo.*tb|dtab|ideatab|mediapad|matepad|honor.*pad|pad\\s+\\d+|mi\\s+pad|redmi.*pad|xiaomi.*pad|oppo.*pad|oneplus.*pad|opd\\d+|tcl.*tab|9\\d{3}[a-z]|kobo|archos.*5(?!\\d)|ereader|droipad/i.test(\n ua\n ) ||\n (/android(?!.*mobile)/i.test(lower) &&\n !/dalvik.*miui|pocophone|mi\\s+mix|edge\\s+\\d+|sm-g9\\d+|pixel\\s+\\d|pixel\\s+fold|advan\\s+\\d{4}/i.test(\n ua\n ));\n\n if (isTablet) return \"tablet\";\n\n const isMobile =\n /android.+mobile|iphone|ipod|windows phone|blackberry|mobile|phone|kaios/i.test(\n lower\n ) ||\n /^mobile;/i.test(ua) ||\n /dalvik.*miui|pocophone|mi\\s+mix|pixel\\s+\\d|pixel\\s+fold/i.test(ua);\n\n if (isMobile) return \"mobile\";\n\n return \"desktop\";\n}\n\n/**\n * Check if Facebook in-app browser\n */\nexport function checkFacebookBrowser(): boolean {\n if (typeof navigator === \"undefined\") return false;\n\n const userAgent =\n navigator.userAgent || navigator.vendor || (window as any).opera;\n const facebookBrowserRegex =\n /((?:fban\\/fbios|fb_iab\\/fb4a)(?!.+fbav)|;fbav\\/([\\w\\.]+);)/i;\n return facebookBrowserRegex.test(userAgent);\n}\n\n/**\n * Check if Instagram in-app browser\n */\nexport function checkInstagramBrowser(): boolean {\n if (typeof navigator === \"undefined\") return false;\n\n const userAgent =\n navigator.userAgent || navigator.vendor || (window as any).opera;\n const instagramBrowserRegex = /(instagram)[\\/ ]([-\\w\\.]+)/i;\n return instagramBrowserRegex.test(userAgent);\n}\n\n/**\n * Check if TikTok in-app browser\n */\nexport function checkTikTokBrowser(): boolean {\n if (typeof navigator === \"undefined\") return false;\n\n const userAgent =\n navigator.userAgent || navigator.vendor || (window as any).opera;\n const tikTokBrowserRegex = /musical_ly/i;\n return tikTokBrowserRegex.test(userAgent);\n}\n\n/**\n * Check if Pinterest in-app browser\n */\nexport function checkPinterestBrowser(): boolean {\n if (typeof navigator === \"undefined\") return false;\n\n const userAgent =\n navigator.userAgent || navigator.vendor || (window as any).opera;\n const pinterestBrowserRegex = /(pinterest)[\\/ ]([-\\w\\.]+)/i;\n return pinterestBrowserRegex.test(userAgent);\n}\n\n/**\n * Get traffic source\n */\nexport function getTrafficSource(): string {\n if (typeof window === \"undefined\") return \"direct\";\n\n const referrer = (document.referrer || \"\").toLowerCase();\n const referrerDomain = referrer\n ? new URL(referrer).hostname.replace(\"www.\", \"\")\n : \"\";\n const hostname = window.location.hostname;\n\n const isFacebookBrowser = checkFacebookBrowser();\n const isInstagramBrowser = checkInstagramBrowser();\n const isTikTokBrowser = checkTikTokBrowser();\n const isPinterestBrowser = checkPinterestBrowser();\n\n if (\n isFacebookBrowser ||\n [\n \"facebook.com\",\n \"fb.com\",\n \"fb.me\",\n \"m.facebook.com\",\n \"l.facebook.com\",\n \"lm.facebook.com\",\n ].includes(referrerDomain)\n ) {\n return \"facebook\";\n } else if (isInstagramBrowser || referrerDomain.includes(\"instagram\")) {\n return \"instagram\";\n } else if (\n isTikTokBrowser ||\n [\"tiktok.com\", \"pangleglobal.com\", \"ads.tiktok.com\"].includes(\n referrerDomain\n )\n ) {\n return \"tiktok\";\n } else if (\n isPinterestBrowser ||\n referrerDomain.includes(\"pinterest\") ||\n referrerDomain === \"pin.it\"\n ) {\n return \"pinterest\";\n } else if (referrerDomain.includes(\"google\")) {\n return \"google\";\n } else if (!referrer || hostname === referrerDomain) {\n return \"direct\";\n } else {\n return \"other\";\n }\n}\n","/**\n * Preview Mode Utilities\n *\n * Enables QA/preview functionality for A/B tests via URL parameters.\n *\n * URL Format:\n * ?eabUserPreview=true&abtid=<test_id>&eab_tests=<shortid>_<variation>_<seen>\n *\n * Example:\n * https://store.com/?eabUserPreview=true&abtid=b6e2ecb8-e35a-450e-ae49-bdc560cf0fd7&eab_tests=f0fd7_29913_1\n */\n\nimport {\n getCookie,\n setCookie,\n getSessionItem,\n setSessionItem,\n} from \"./storage\";\n\n/**\n * Preview mode state\n */\nexport interface PreviewState {\n /** Whether preview mode is active */\n isPreview: boolean;\n /** The test ID being previewed (full UUID or short ID) */\n previewTestId: string | null;\n /** Forced test assignments from URL params */\n forcedAssignments: Record<string, string>;\n /** Tests that have been marked as \"seen\" in preview */\n previewedViews: Record<string, boolean>;\n}\n\n/**\n * Parse eab_tests parameter format: shortid_variation_seen~shortid2_variation2_seen2\n * Example: \"f0fd7_29913_1\" or \"f0fd7_29913_1~a1b2c_12345_0\"\n */\nfunction parseEabTestsParam(param: string): {\n assignments: Record<string, string>;\n views: Record<string, boolean>;\n} {\n const assignments: Record<string, string> = {};\n const views: Record<string, boolean> = {};\n\n if (!param) return { assignments, views };\n\n const tests = param.split(\"~\");\n for (const test of tests) {\n const parts = test.split(\"_\");\n if (parts.length >= 2) {\n const shortTestId = parts[0];\n const variationId = parts[1];\n const hasSeen = parts[2] === \"1\";\n\n assignments[shortTestId] = variationId;\n views[shortTestId] = hasSeen;\n }\n }\n\n return { assignments, views };\n}\n\n/**\n * Get preview state from URL parameters and cookies\n */\nexport function getPreviewState(): PreviewState {\n if (typeof window === \"undefined\") {\n return {\n isPreview: false,\n previewTestId: null,\n forcedAssignments: {},\n previewedViews: {},\n };\n }\n\n const urlParams = new URLSearchParams(window.location.search);\n\n // Check URL param first, then cookie\n const eabUserPreview =\n urlParams.get(\"eabUserPreview\") || getCookie(\"eabUserPreview\");\n const isPreview = eabUserPreview === \"true\";\n\n // Get test ID from URL param or sessionStorage\n let previewTestId = urlParams.get(\"abtid\");\n if (!previewTestId) {\n previewTestId = getSessionItem(\"eabPreviewTestId\");\n }\n\n // Parse forced assignments from eab_tests param\n const eabTestsParam = urlParams.get(\"eab_tests\") || \"\";\n const { assignments, views } = parseEabTestsParam(eabTestsParam);\n\n // If URL has preview params, persist to storage\n if (urlParams.has(\"eabUserPreview\")) {\n setCookie(\"eabUserPreview\", \"true\");\n }\n if (urlParams.has(\"abtid\") && previewTestId) {\n setSessionItem(\"eabPreviewTestId\", previewTestId);\n }\n\n return {\n isPreview,\n previewTestId,\n forcedAssignments: assignments,\n previewedViews: views,\n };\n}\n\n/**\n * Check if a test matches the preview test ID\n * Supports both full UUID and short ID (last 5 chars) matching\n */\nexport function isPreviewTest(\n testId: string,\n previewTestId: string | null,\n): boolean {\n if (!previewTestId) return false;\n\n // Exact match\n if (testId === previewTestId) return true;\n\n // Short ID match (last 5 characters)\n const shortTestId = testId.slice(-5);\n if (shortTestId === previewTestId || previewTestId.endsWith(shortTestId)) {\n return true;\n }\n\n // Preview ID might be short, check if test ends with it\n if (testId.endsWith(previewTestId)) return true;\n\n return false;\n}\n\n/**\n * Get forced variation for a test in preview mode\n * Returns null if no forced assignment exists\n */\nexport function getPreviewVariation(\n testId: string,\n previewState: PreviewState,\n): string | null {\n if (!previewState.isPreview) return null;\n\n // Check by full test ID\n if (previewState.forcedAssignments[testId]) {\n return previewState.forcedAssignments[testId];\n }\n\n // Check by short test ID\n const shortTestId = testId.slice(-5);\n if (previewState.forcedAssignments[shortTestId]) {\n return previewState.forcedAssignments[shortTestId];\n }\n\n return null;\n}\n\n/**\n * Build eab_tests URL parameter string from test assignments\n * Used for sharing preview URLs with Facebook/Instagram traffic\n */\nexport function buildEabTestsParam(\n testAssignments: Record<string, string>,\n viewedTests: Record<string, boolean>,\n): string {\n return Object.entries(testAssignments)\n .map(([testId, variationId]) => {\n const shortTestId = testId.slice(-5);\n const hasSeen = viewedTests[testId] ? \"1\" : \"0\";\n return `${shortTestId}_${variationId}_${hasSeen}`;\n })\n .join(\"~\");\n}\n\n/**\n * Update URL with test parameters for social media browsers (FB/IG/TikTok)\n * These browsers often lose cookies, so we persist test assignments in URL\n */\nexport function updateUrlWithTestParams(\n testAssignments: Record<string, string>,\n viewedTests: Record<string, boolean>,\n visitorId?: string,\n): void {\n if (typeof window === \"undefined\") return;\n\n const url = new URL(window.location.href);\n const eabTestsValue = buildEabTestsParam(testAssignments, viewedTests);\n\n if (eabTestsValue) {\n url.searchParams.set(\"eab_tests\", eabTestsValue);\n }\n\n if (visitorId) {\n url.searchParams.set(\"eabUserId\", visitorId);\n }\n\n // Update URL without reload\n window.history.replaceState({}, \"\", url.toString());\n}\n\n/**\n * Clear preview mode\n */\nexport function clearPreviewMode(): void {\n if (typeof document === \"undefined\") return;\n\n // Clear cookie\n document.cookie =\n \"eabUserPreview=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;\";\n\n // Clear session storage\n if (typeof sessionStorage !== \"undefined\") {\n sessionStorage.removeItem(\"eabPreviewTestId\");\n }\n\n // Remove preview params from URL\n if (typeof window !== \"undefined\") {\n const url = new URL(window.location.href);\n url.searchParams.delete(\"eabUserPreview\");\n url.searchParams.delete(\"abtid\");\n url.searchParams.delete(\"eab_tests\");\n window.history.replaceState({}, \"\", url.toString());\n }\n}\n\n/**\n * Check if current session is in preview mode\n */\nexport function isInPreviewMode(): boolean {\n return getPreviewState().isPreview;\n}\n","/**\n * Geo-targeting Utilities\n *\n * Provides country detection and geo-based targeting for A/B tests.\n */\n\nimport { getCookie, setCookie } from \"./storage\";\n\n/**\n * Geo-location data\n */\nexport interface GeoLocation {\n /** ISO 3166-1 alpha-2 country code (e.g., \"US\", \"GB\", \"CA\") */\n country: string | null;\n /** Region/state code (if available) */\n region?: string | null;\n /** City name (if available) */\n city?: string | null;\n}\n\n/**\n * Cookie names for geo data\n */\nconst GEO_COOKIE_NAMES = {\n /** Shopify's localization cookie */\n SHOPIFY_LOCALIZATION: \"localization\",\n /** Our cached country code */\n EAB_COUNTRY: \"eabCountryCode\",\n /** Full geo data (JSON) */\n EAB_GEO: \"eabGeoLocation\",\n} as const;\n\n/**\n * Get the user's country code from various sources\n * Priority: URL param > Shopify localization > our cookie > localStorage\n */\nexport function getCountryCode(): string | null {\n if (typeof window === \"undefined\") return null;\n\n // 1. Check URL param (for explicit override)\n const urlParams = new URLSearchParams(window.location.search);\n const urlCountry = urlParams.get(\"country\");\n if (urlCountry) {\n // Cache it\n setCookie(GEO_COOKIE_NAMES.EAB_COUNTRY, urlCountry.toUpperCase());\n return urlCountry.toUpperCase();\n }\n\n // 2. Check Shopify's localization cookie (most common for Shopify stores)\n const shopifyCountry = getCookie(GEO_COOKIE_NAMES.SHOPIFY_LOCALIZATION);\n if (shopifyCountry) {\n return shopifyCountry.toUpperCase();\n }\n\n // 3. Check our cached cookie\n const cachedCountry = getCookie(GEO_COOKIE_NAMES.EAB_COUNTRY);\n if (cachedCountry) {\n return cachedCountry.toUpperCase();\n }\n\n // 4. Check localStorage (fallback)\n if (typeof localStorage !== \"undefined\") {\n const storedCountry = localStorage.getItem(GEO_COOKIE_NAMES.EAB_COUNTRY);\n if (storedCountry) {\n return storedCountry.toUpperCase();\n }\n }\n\n return null;\n}\n\n/**\n * Get full geo-location data\n */\nexport function getGeoLocation(): GeoLocation {\n const country = getCountryCode();\n\n // Try to get extended geo data from cookie\n const geoData = getCookie(GEO_COOKIE_NAMES.EAB_GEO);\n if (geoData) {\n try {\n const parsed = JSON.parse(geoData) as GeoLocation;\n return {\n country: parsed.country || country,\n region: parsed.region,\n city: parsed.city,\n };\n } catch {\n // Invalid JSON, fall through\n }\n }\n\n return { country };\n}\n\n/**\n * Set the user's country code (for manual override or after geo detection)\n */\nexport function setCountryCode(countryCode: string): void {\n const normalized = countryCode.toUpperCase();\n setCookie(GEO_COOKIE_NAMES.EAB_COUNTRY, normalized);\n\n // Also store in localStorage for extra persistence\n if (typeof localStorage !== \"undefined\") {\n localStorage.setItem(GEO_COOKIE_NAMES.EAB_COUNTRY, normalized);\n }\n}\n\n/**\n * Set full geo-location data\n */\nexport function setGeoLocation(geo: GeoLocation): void {\n if (geo.country) {\n setCountryCode(geo.country);\n }\n\n // Store full geo data\n setCookie(GEO_COOKIE_NAMES.EAB_GEO, JSON.stringify(geo));\n}\n\n/**\n * Check if user's country matches a list of allowed countries\n */\nexport function isCountryIncluded(\n allowedCountries: string[],\n userCountry?: string | null,\n): boolean {\n const country = userCountry ?? getCountryCode();\n if (!country) return false;\n\n const normalizedAllowed = allowedCountries.map((c) => c.toUpperCase());\n return normalizedAllowed.includes(country.toUpperCase());\n}\n\n/**\n * Check if user's country is in an excluded list\n */\nexport function isCountryExcluded(\n excludedCountries: string[],\n userCountry?: string | null,\n): boolean {\n const country = userCountry ?? getCountryCode();\n if (!country) return false;\n\n const normalizedExcluded = excludedCountries.map((c) => c.toUpperCase());\n return normalizedExcluded.includes(country.toUpperCase());\n}\n\n/**\n * Check if user matches geo-targeting rules\n * Returns true if user should be included in the test\n */\nexport function matchesGeoTargeting(rules: {\n includeCountries?: string[];\n excludeCountries?: string[];\n}): boolean {\n const country = getCountryCode();\n\n // If no rules, include everyone\n if (!rules.includeCountries?.length && !rules.excludeCountries?.length) {\n return true;\n }\n\n // If no country detected and rules exist, exclude (can't target unknown)\n if (!country) {\n return false;\n }\n\n // Check exclusions first (takes precedence)\n if (rules.excludeCountries?.length) {\n if (isCountryExcluded(rules.excludeCountries, country)) {\n return false;\n }\n }\n\n // If include list exists, user must be in it\n if (rules.includeCountries?.length) {\n return isCountryIncluded(rules.includeCountries, country);\n }\n\n // No include list, and not excluded = included\n return true;\n}\n\n/**\n * Common country code constants for convenience\n */\nexport const COUNTRIES = {\n US: \"US\",\n CA: \"CA\",\n GB: \"GB\",\n AU: \"AU\",\n DE: \"DE\",\n FR: \"FR\",\n JP: \"JP\",\n MX: \"MX\",\n BR: \"BR\",\n IN: \"IN\",\n // Add more as needed\n} as const;\n\n/**\n * Region groupings for common use cases\n */\nexport const REGIONS = {\n NORTH_AMERICA: [\"US\", \"CA\", \"MX\"],\n EUROPE: [\n \"GB\",\n \"DE\",\n \"FR\",\n \"IT\",\n \"ES\",\n \"NL\",\n \"BE\",\n \"AT\",\n \"CH\",\n \"PL\",\n \"SE\",\n \"NO\",\n \"DK\",\n \"FI\",\n \"IE\",\n \"PT\",\n ],\n APAC: [\n \"AU\",\n \"NZ\",\n \"JP\",\n \"KR\",\n \"SG\",\n \"HK\",\n \"TW\",\n \"TH\",\n \"MY\",\n \"PH\",\n \"ID\",\n \"VN\",\n \"IN\",\n ],\n LATAM: [\"MX\", \"BR\", \"AR\", \"CL\", \"CO\", \"PE\"],\n} as const;\n","/**\n * Anti-Flicker Utilities\n *\n * Prevents visual flickering during A/B test assignment by hiding content\n * until the variant is determined. Uses a CSS-based approach for performance.\n *\n * Note: Called \"preventFlickering\" in our API to differentiate from competitors.\n */\n\n/**\n * CSS class used to hide content during flicker prevention\n */\nconst FLICKER_CLASS = \"eab-prevent-flicker\";\n\n/**\n * Inline style ID for flicker prevention\n */\nconst STYLE_ID = \"eab-flicker-styles\";\n\n/**\n * Default timeout (ms) before showing content anyway (failsafe)\n */\nconst DEFAULT_TIMEOUT = 3000;\n\n/**\n * Inject the flicker prevention CSS styles\n * This should be called as early as possible (ideally in <head>)\n */\nexport function injectFlickerStyles(timeout = DEFAULT_TIMEOUT): void {\n if (typeof document === \"undefined\") return;\n\n // Don't inject twice\n if (document.getElementById(STYLE_ID)) return;\n\n const style = document.createElement(\"style\");\n style.id = STYLE_ID;\n style.textContent = `\n /* Elevate AB - Flicker Prevention */\n .${FLICKER_CLASS} {\n opacity: 0 !important;\n pointer-events: none !important;\n }\n \n /* Failsafe: ensure content shows after timeout via animation */\n @keyframes eab-reveal {\n to { opacity: 1; pointer-events: auto; }\n }\n \n .${FLICKER_CLASS} {\n animation: eab-reveal 0s ${timeout}ms forwards;\n }\n `;\n\n // Insert at the beginning of <head> for highest priority\n const head = document.head || document.getElementsByTagName(\"head\")[0];\n head.insertBefore(style, head.firstChild);\n}\n\n/**\n * Hide the page/element to prevent flicker\n * Call this before test assignment begins\n */\nexport function hideForFlicker(selector: string = \"body\"): void {\n if (typeof document === \"undefined\") return;\n\n const element = document.querySelector(selector);\n if (element) {\n element.classList.add(FLICKER_CLASS);\n }\n}\n\n/**\n * Show the page/element after test assignment is complete\n * Call this after variant is determined\n */\nexport function revealAfterFlicker(selector: string = \"body\"): void {\n if (typeof document === \"undefined\") return;\n\n const element = document.querySelector(selector);\n if (element) {\n element.classList.remove(FLICKER_CLASS);\n }\n}\n\n/**\n * Setup flicker prevention with automatic reveal\n * Returns a function to call when assignment is complete\n *\n * @param selector - CSS selector for element to hide (default: \"body\")\n * @param timeout - Maximum time to wait before revealing (default: 3000ms)\n * @returns Function to call when test assignment is complete\n *\n * @example\n * ```tsx\n * // In your app initialization\n * const reveal = setupFlickerPrevention();\n *\n * // After test assignment\n * reveal();\n * ```\n */\nexport function setupFlickerPrevention(\n selector: string = \"body\",\n timeout: number = DEFAULT_TIMEOUT,\n): () => void {\n if (typeof document === \"undefined\") {\n return () => {}; // No-op for SSR\n }\n\n // Inject styles\n injectFlickerStyles(timeout);\n\n // Hide content\n hideForFlicker(selector);\n\n // Setup timeout failsafe\n let hasRevealed = false;\n const timeoutId = setTimeout(() => {\n if (!hasRevealed) {\n console.warn(\n `[ElevateAB] Flicker prevention timeout (${timeout}ms) reached. ` +\n \"Revealing content. Check if test assignment is completing.\",\n );\n revealAfterFlicker(selector);\n hasRevealed = true;\n }\n }, timeout);\n\n // Return reveal function\n return () => {\n if (!hasRevealed) {\n clearTimeout(timeoutId);\n revealAfterFlicker(selector);\n hasRevealed = true;\n }\n };\n}\n\n/**\n * Remove all flicker prevention styles and classes\n * Useful for cleanup or when disabling the feature\n */\nexport function cleanupFlickerPrevention(): void {\n if (typeof document === \"undefined\") return;\n\n // Remove style tag\n const style = document.getElementById(STYLE_ID);\n if (style) {\n style.remove();\n }\n\n // Remove class from all elements\n const elements = document.querySelectorAll(`.${FLICKER_CLASS}`);\n elements.forEach((el) => el.classList.remove(FLICKER_CLASS));\n}\n\n/**\n * Check if flicker prevention is currently active\n */\nexport function isFlickerPreventionActive(): boolean {\n if (typeof document === \"undefined\") return false;\n\n return document.querySelector(`.${FLICKER_CLASS}`) !== null;\n}\n\n/**\n * Script snippet for inline injection in <head>\n * Use this when you need synchronous flicker prevention before React hydrates\n *\n * @example\n * ```tsx\n * // In your _document.tsx or layout.tsx\n * <script dangerouslySetInnerHTML={{ __html: getFlickerPreventionScript() }} />\n * ```\n */\nexport function getFlickerPreventionScript(timeout = DEFAULT_TIMEOUT): string {\n return `\n(function() {\n var style = document.createElement('style');\n style.id = '${STYLE_ID}';\n style.textContent = '.${FLICKER_CLASS}{opacity:0!important;pointer-events:none!important}@keyframes eab-reveal{to{opacity:1;pointer-events:auto}}.${FLICKER_CLASS}{animation:eab-reveal 0s ${timeout}ms forwards}';\n document.head.insertBefore(style, document.head.firstChild);\n document.body && document.body.classList.add('${FLICKER_CLASS}');\n})();\n`.trim();\n}\n","/**\n * Shopify-specific utilities\n */\n\n/**\n * Extract numeric ID from a Shopify Global ID (GID).\n *\n * Shopify uses GIDs like \"gid://shopify/Product/123456789\" or \"gid://shopify/ProductVariant/987654321\".\n * This utility extracts the numeric ID portion.\n *\n * @param gid - Shopify Global ID or numeric ID string\n * @returns The numeric ID portion (e.g., \"123456789\")\n *\n * @example\n * ```ts\n * extractShopifyId(\"gid://shopify/Product/123456789\"); // \"123456789\"\n * extractShopifyId(\"gid://shopify/ProductVariant/987654321\"); // \"987654321\"\n * extractShopifyId(\"gid://shopify/Cart/abc123\"); // \"abc123\"\n * extractShopifyId(\"123456789\"); // \"123456789\" (already numeric)\n * ```\n */\nexport function extractShopifyId(gid: string | null | undefined): string {\n if (!gid) return \"\";\n\n // If it's a GID, extract the last segment\n if (gid.includes(\"gid://\")) {\n return gid.split(\"/\").pop() || gid;\n }\n\n // Already a plain ID\n return gid;\n}\n\n/**\n * Extract the resource type from a Shopify Global ID.\n *\n * @param gid - Shopify Global ID\n * @returns The resource type (e.g., \"Product\", \"ProductVariant\", \"Cart\")\n *\n * @example\n * ```ts\n * extractShopifyType(\"gid://shopify/Product/123\"); // \"Product\"\n * extractShopifyType(\"gid://shopify/ProductVariant/456\"); // \"ProductVariant\"\n * extractShopifyType(\"123456789\"); // null (not a GID)\n * ```\n */\nexport function extractShopifyType(\n gid: string | null | undefined,\n): string | null {\n if (!gid || !gid.includes(\"gid://\")) return null;\n\n const parts = gid.split(\"/\");\n // gid://shopify/Product/123 -> parts = [\"gid:\", \"\", \"shopify\", \"Product\", \"123\"]\n return parts[3] || null;\n}\n\n/**\n * Check if a string is a Shopify Global ID.\n *\n * @param value - String to check\n * @returns True if it's a GID\n *\n * @example\n * ```ts\n * isShopifyGid(\"gid://shopify/Product/123\"); // true\n * isShopifyGid(\"123456789\"); // false\n * ```\n */\nexport function isShopifyGid(value: string | null | undefined): boolean {\n return !!value && value.startsWith(\"gid://shopify/\");\n}\n\n/**\n * Try to detect the shop currency from Shopify's global object.\n * Only works on Shopify theme stores, not headless.\n *\n * @returns Currency code (e.g., \"USD\") or undefined\n */\nexport function detectShopifyCurrency(): string | undefined {\n if (typeof window === \"undefined\") return undefined;\n\n // Try Shopify's global currency object (theme stores only)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const shopify = (window as any).Shopify;\n if (shopify?.currency?.active) {\n return shopify.currency.active;\n }\n\n return undefined;\n}\n","/**\n * Manual tracking functions for non-Hydrogen frameworks (Next.js, etc.)\n *\n * Initialize once with initAnalytics(), then call tracking functions without params:\n *\n * @example\n * ```tsx\n * // In your layout/provider (once)\n * initAnalytics({\n * storeId: 'your-store.myshopify.com',\n * storefrontAccessToken: 'your-token',\n * });\n *\n * // Then anywhere in your app (no params needed)\n * trackPageView();\n * trackAddToCart({ cartId, productId, ... });\n * ```\n */\n\nimport type {\n EventPayload,\n TestAssignment,\n TrackPageViewParams,\n TrackProductViewParams,\n TrackAddToCartParams,\n TrackRemoveFromCartParams,\n TrackCartViewParams,\n TrackSearchSubmittedParams,\n TrackCheckoutStartedParams,\n TrackCheckoutCompletedParams,\n} from \"../types\";\n\nimport { extractShopifyId } from \"./shopify\";\n\n// Re-import types for cleaner syntax below\nimport type { UsePageViewTrackingParams } from \"../types\";\nimport {\n parseAddViewData,\n extractCartToken,\n cleanCartToken,\n getPageTypeFromPathname,\n sanitizeString,\n roundToTwo,\n getUserAgentNoBrowser,\n} from \"./analytics\";\nimport {\n getVisitorId,\n getSessionId,\n getCookie,\n getJsonCookie,\n getReferrerData,\n uuidv4,\n} from \"./storage\";\n\nconst DEFAULT_WORKER_URL = \"https://bitter-river-9c62.support-67d.workers.dev\";\nconst DEFAULT_ORDERS_WORKER_URL =\n \"https://d339co84ntxcme.cloudfront.net/Prod/orders\";\n\n// ============================================================================\n// GLOBAL ANALYTICS CONFIG (initialized once, used by all tracking functions)\n// ============================================================================\n\ninterface AnalyticsConfig {\n storeId: string;\n storefrontAccessToken?: string;\n hasLocalizedPaths?: boolean;\n workerUrl?: string;\n ordersWorkerUrl?: string;\n}\n\nlet globalConfig: AnalyticsConfig | null = null;\n\n/**\n * Initialize analytics config once. Call this in your app's entry point or layout.\n * After init, tracking functions don't need storeId/token params.\n *\n * @example\n * ```tsx\n * // In _app.tsx or layout.tsx\n * initAnalytics({\n * storeId: 'your-store.myshopify.com',\n * storefrontAccessToken: process.env.NEXT_PUBLIC_STOREFRONT_TOKEN,\n * });\n * ```\n */\nexport function initAnalytics(config: AnalyticsConfig): void {\n globalConfig = config;\n}\n\n/**\n * Get the current analytics config (for internal use)\n */\nexport function getAnalyticsConfig(): AnalyticsConfig | null {\n return globalConfig;\n}\n\n/**\n * Check if analytics is initialized\n */\nexport function isAnalyticsInitialized(): boolean {\n return globalConfig !== null;\n}\n\n// Helper to get storeId from params or global config\nfunction getStoreId(params?: { storeId?: string }): string {\n const storeId = params?.storeId || globalConfig?.storeId;\n if (!storeId) {\n console.warn(\n \"[ElevateAB] No storeId provided. Call initAnalytics() first or pass storeId to tracking function.\",\n );\n return \"\";\n }\n return storeId;\n}\n\n// Transform test list format to event format\nfunction transformTestFormat(\n testObject: Record<string, string>,\n): TestAssignment[] {\n return Object.entries(testObject)\n .filter(([, variationId]) => typeof variationId === \"string\")\n .map(([testId, variationId]) => ({\n test_id: testId,\n variant_id: variationId,\n }));\n}\n\n// Transform viewed tests format\nfunction transformViewedTests(\n viewedObject: Record<string, boolean>,\n assignmentObject: Record<string, string>,\n): TestAssignment[] {\n return Object.entries(viewedObject)\n .filter(([testId]) => typeof assignmentObject[testId] === \"string\")\n .map(([testId]) => ({\n test_id: testId,\n variant_id: assignmentObject[testId],\n }));\n}\n\n// Check if we're in preview mode (should skip analytics)\nfunction isInPreviewMode(): boolean {\n if (typeof window === \"undefined\") return false;\n\n // Check cookie\n if (getCookie(\"eabUserPreview\") === \"true\") return true;\n\n // Check URL param\n const urlParams = new URLSearchParams(window.location.search);\n if (urlParams.get(\"eabUserPreview\") === \"true\") return true;\n\n return false;\n}\n\n// Create base event data (returns null if in preview mode)\nfunction createBaseEventData(\n storeId: string,\n eventType: string,\n hasLocalizedPaths?: boolean,\n): Partial<EventPayload> | null {\n if (typeof window === \"undefined\") return null;\n\n // Skip tracking in preview mode to avoid polluting analytics\n if (isInPreviewMode()) {\n return null;\n }\n\n const userAgent = navigator.userAgent;\n const pathname = window.location.pathname;\n const pageType = getPageTypeFromPathname(pathname, hasLocalizedPaths);\n\n const { referrer, entryPage } = getReferrerData();\n\n const parsedData = parseAddViewData({\n referrer,\n entryPage,\n userAgent,\n });\n\n const abtlObject = getJsonCookie<Record<string, string>>(\"ABTL\") || {};\n const abauObject = getJsonCookie<Record<string, boolean>>(\"ABAU\") || {};\n\n const testAssignments = transformTestFormat(abtlObject);\n const viewedTests = transformViewedTests(abauObject, abtlObject);\n\n const cartToken = extractCartToken(localStorage.getItem(\"shopifyCartId\"));\n const currentTimestamp = new Date().toISOString();\n\n // Get additional state\n const isFirstVisit = sessionStorage.getItem(\"eabIsFirstVisit\") === \"true\";\n const shopifyCountry = getCookie(\"localization\") || \"\";\n\n return {\n pixel_event_id: `sh-${uuidv4()}`,\n shop_name: storeId,\n timestamp: currentTimestamp,\n event_type: eventType,\n client_id: getCookie(\"_shopify_y\") || undefined,\n visitor_id: getVisitorId(),\n session_id: getSessionId(),\n cart_token: cleanCartToken(cartToken || getCookie(\"cart\")),\n\n page_url: window.location.href,\n page_pathname: pathname,\n page_search: window.location.search,\n referrer_url: referrer,\n referrer_source: parsedData?.referrer_source,\n previous_page: document.referrer,\n page_entry: entryPage,\n page_entry_path: parsedData?.page_entry_path,\n page_type: pageType,\n\n utm_medium: parsedData?.utm_medium,\n utm_source: parsedData?.utm_source,\n utm_campaign: parsedData?.utm_campaign,\n utm_content: parsedData?.utm_content,\n utm_term: parsedData?.utm_term,\n\n gclid: parsedData?.gclid,\n fbclid: parsedData?.fbclid,\n pins_campaign_id: parsedData?.pins_campaign_id,\n epik: parsedData?.epik,\n\n browser_info: parsedData?.browser_info,\n os_info: parsedData?.os_info,\n device_type: parsedData?.device_type,\n language: navigator.language,\n root_route: localStorage.getItem(\"eabRootRoute\") || \"\",\n user_agent: userAgent,\n user_agent_no_browser: getUserAgentNoBrowser(userAgent),\n\n is_first_visit: isFirstVisit,\n shopify_country: shopifyCountry,\n\n ab_test_assignments: testAssignments,\n ab_test_views: viewedTests,\n is_first_order: null,\n };\n}\n\n// Send event to CloudFlare Worker\nasync function sendEvent(\n data: Partial<EventPayload>,\n workerUrl: string = DEFAULT_WORKER_URL,\n): Promise<void> {\n try {\n const response = await fetch(workerUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(data),\n keepalive: true,\n });\n\n if (!response.ok) {\n throw new Error(`Worker error: ${response.status}`);\n }\n } catch (error) {\n console.error(\"[ElevateAB] Error sending analytics:\", error);\n }\n}\n\n/**\n * Track page view event\n * Call this on route changes or in useEffect\n *\n * @example After initAnalytics()\n * ```ts\n * await trackPageView(); // No params needed!\n * ```\n *\n * @example Without init (pass params)\n * ```ts\n * await trackPageView({ storeId: \"mystore.myshopify.com\" });\n * ```\n */\nexport async function trackPageView(\n params: Partial<TrackPageViewParams> = {},\n): Promise<void> {\n const storeId = getStoreId(params);\n if (!storeId) return;\n\n const hasLocalizedPaths =\n params.hasLocalizedPaths ?? globalConfig?.hasLocalizedPaths;\n const workerUrl = params.workerUrl ?? globalConfig?.workerUrl;\n\n const baseData = createBaseEventData(\n storeId,\n \"page_viewed\",\n hasLocalizedPaths,\n );\n if (!baseData) return; // Skip in preview mode\n\n const eventData: Partial<EventPayload> = {\n ...baseData,\n cart_currency: params.currency,\n };\n\n await sendEvent(eventData, workerUrl);\n}\n\n/**\n * Track product view event\n * Call this on product pages\n *\n * @example After initAnalytics()\n * ```ts\n * await trackProductView({ productId: \"123\", productPrice: 99.99 });\n * ```\n */\nexport async function trackProductView(\n params: Omit<TrackProductViewParams, \"storeId\"> & { storeId?: string },\n): Promise<void> {\n const storeId = getStoreId(params);\n if (!storeId) return;\n\n const { productId, productVendor, productPrice, productSku, currency } =\n params;\n const hasLocalizedPaths =\n params.hasLocalizedPaths ?? globalConfig?.hasLocalizedPaths;\n const workerUrl = params.workerUrl ?? globalConfig?.workerUrl;\n\n const baseData = createBaseEventData(\n storeId,\n \"product_viewed\",\n hasLocalizedPaths,\n );\n if (!baseData) return; // Skip in preview mode\n\n const eventData: Partial<EventPayload> = {\n ...baseData,\n cart_currency: currency,\n product_id: extractShopifyId(productId),\n product_vendor: sanitizeString(productVendor),\n product_price: roundToTwo(productPrice),\n product_sku: sanitizeString(productSku),\n };\n\n await sendEvent(eventData, workerUrl);\n}\n\n/**\n * Track add to cart event\n * Call this when user clicks \"Add to Cart\"\n *\n * Cart attributes are automatically updated for order attribution if\n * storefrontAccessToken was provided to initAnalytics() or passed here.\n *\n * @example After initAnalytics()\n * ```ts\n * await trackAddToCart({\n * cartId: \"gid://shopify/Cart/abc123\",\n * productId: \"123456789\",\n * variantId: \"987654321\",\n * productPrice: 99.99,\n * productQuantity: 1,\n * });\n * ```\n */\nexport async function trackAddToCart(\n params: Omit<TrackAddToCartParams, \"storeId\" | \"storefrontAccessToken\"> & {\n storeId?: string;\n storefrontAccessToken?: string;\n },\n): Promise<void> {\n const storeId = getStoreId(params);\n if (!storeId) return;\n\n const {\n productId,\n variantId,\n productVendor,\n productPrice,\n productQuantity,\n productSku,\n currency,\n cartId,\n } = params;\n\n const hasLocalizedPaths =\n params.hasLocalizedPaths ?? globalConfig?.hasLocalizedPaths;\n const workerUrl = params.workerUrl ?? globalConfig?.workerUrl;\n const storefrontAccessToken =\n params.storefrontAccessToken ?? globalConfig?.storefrontAccessToken;\n\n const baseData = createBaseEventData(\n storeId,\n \"product_added_to_cart\",\n hasLocalizedPaths,\n );\n if (!baseData) return; // Skip in preview mode\n\n const eventData: Partial<EventPayload> = {\n ...baseData,\n cart_currency: currency,\n product_id: extractShopifyId(productId),\n variant_id: extractShopifyId(variantId),\n product_vendor: sanitizeString(productVendor),\n product_price: roundToTwo(productPrice),\n product_quantity: productQuantity,\n product_sku: sanitizeString(productSku),\n };\n\n await sendEvent(eventData, workerUrl);\n\n // Auto-update cart attributes if cartId and token are available\n if (cartId && storefrontAccessToken) {\n try {\n const { updateCartAttributes } = await import(\"./cartAttributes\");\n await updateCartAttributes(cartId, { storefrontAccessToken });\n } catch (err) {\n console.error(\"[ElevateAB] Failed to update cart attributes:\", err);\n }\n }\n}\n\n/**\n * Track remove from cart event\n * Call this when user removes item from cart\n */\nexport async function trackRemoveFromCart(\n params: Omit<TrackRemoveFromCartParams, \"storeId\"> & { storeId?: string },\n): Promise<void> {\n const storeId = getStoreId(params);\n if (!storeId) return;\n\n const {\n productId,\n variantId,\n productVendor,\n productPrice,\n productQuantity,\n productSku,\n currency,\n } = params;\n\n const hasLocalizedPaths =\n params.hasLocalizedPaths ?? globalConfig?.hasLocalizedPaths;\n const workerUrl = params.workerUrl ?? globalConfig?.workerUrl;\n\n const baseData = createBaseEventData(\n storeId,\n \"product_removed_from_cart\",\n hasLocalizedPaths,\n );\n if (!baseData) return; // Skip in preview mode\n\n const eventData: Partial<EventPayload> = {\n ...baseData,\n cart_currency: currency,\n product_id: extractShopifyId(productId),\n variant_id: extractShopifyId(variantId),\n product_vendor: sanitizeString(productVendor),\n product_price: roundToTwo(productPrice),\n product_quantity: productQuantity,\n product_sku: sanitizeString(productSku),\n };\n\n await sendEvent(eventData, workerUrl);\n}\n\n/**\n * Track cart view event\n * Call this when user views cart page\n */\nexport async function trackCartView(\n params: Omit<TrackCartViewParams, \"storeId\"> & { storeId?: string },\n): Promise<void> {\n const storeId = getStoreId(params);\n if (!storeId) return;\n\n const { cartTotalPrice, cartTotalQuantity, cartItems, currency } = params;\n const hasLocalizedPaths =\n params.hasLocalizedPaths ?? globalConfig?.hasLocalizedPaths;\n const workerUrl = params.workerUrl ?? globalConfig?.workerUrl;\n\n const baseData = createBaseEventData(\n storeId,\n \"cart_viewed\",\n hasLocalizedPaths,\n );\n if (!baseData) return; // Skip in preview mode\n\n const eventData: Partial<EventPayload> = {\n ...baseData,\n cart_currency: currency,\n cart_total_price: roundToTwo(cartTotalPrice),\n cart_total_quantity: cartTotalQuantity,\n cart_items: cartItems?.map((item) => ({\n product_id: extractShopifyId(item.productId),\n variant_id: extractShopifyId(item.variantId),\n product_vendor: sanitizeString(item.productVendor) || \"\",\n product_price: roundToTwo(item.productPrice),\n product_quantity: item.productQuantity ?? null,\n product_sku: sanitizeString(item.productSku) || \"\",\n })),\n };\n\n await sendEvent(eventData, workerUrl);\n}\n\n/**\n * Track search submitted event\n * Call this when user submits a search\n *\n * @example After initAnalytics()\n * ```ts\n * await trackSearchSubmitted({ searchQuery: \"running shoes\" });\n * ```\n *\n * @example Without init (pass params)\n * ```ts\n * await trackSearchSubmitted({\n * storeId: \"mystore.myshopify.com\",\n * searchQuery: \"running shoes\",\n * currency: \"USD\"\n * });\n * ```\n */\nexport async function trackSearchSubmitted(\n params: Omit<TrackSearchSubmittedParams, \"storeId\"> & { storeId?: string },\n): Promise<void> {\n const storeId = getStoreId(params);\n if (!storeId) return;\n\n const { searchQuery, currency } = params;\n const hasLocalizedPaths =\n params.hasLocalizedPaths ?? globalConfig?.hasLocalizedPaths;\n const workerUrl = params.workerUrl ?? globalConfig?.workerUrl;\n\n const baseData = createBaseEventData(\n storeId,\n \"search_submitted\",\n hasLocalizedPaths,\n );\n if (!baseData) return; // Skip in preview mode\n\n const eventData: Partial<EventPayload> = {\n ...baseData,\n cart_currency: currency,\n search_query: sanitizeString(searchQuery),\n };\n\n await sendEvent(eventData, workerUrl);\n}\n\n/**\n * Track checkout started event\n * Call this when user starts checkout\n *\n * @example After initAnalytics()\n * ```ts\n * await trackCheckoutStarted({\n * cartTotalPrice: 109.98,\n * cartItems: [...],\n * });\n * ```\n */\nexport async function trackCheckoutStarted(\n params: Omit<TrackCheckoutStartedParams, \"storeId\"> & { storeId?: string },\n): Promise<void> {\n const storeId = getStoreId(params);\n if (!storeId) return;\n\n const {\n cartTotalPrice,\n cartSubtotalPrice,\n cartShippingPrice,\n cartTaxAmount,\n cartDiscountAmount,\n customerId,\n cartItems,\n currency,\n } = params;\n\n const hasLocalizedPaths =\n params.hasLocalizedPaths ?? globalConfig?.hasLocalizedPaths;\n const workerUrl = params.workerUrl ?? globalConfig?.workerUrl;\n\n const baseData = createBaseEventData(\n storeId,\n \"checkout_started\",\n hasLocalizedPaths,\n );\n if (!baseData) return; // Skip in preview mode\n\n let totalQuantity = 0;\n const items =\n cartItems?.map((item) => {\n const quantity = item.productQuantity ?? 0;\n totalQuantity += quantity;\n return {\n product_id: extractShopifyId(item.productId),\n variant_id: extractShopifyId(item.variantId),\n product_vendor: sanitizeString(item.productVendor) || \"\",\n vendor: sanitizeString(item.productVendor) || \"\",\n product_price: roundToTwo(item.productPrice),\n total_price: roundToTwo(item.productPrice),\n product_quantity: quantity,\n quantity: quantity,\n product_sku: sanitizeString(item.productSku) || \"\",\n sku: sanitizeString(item.productSku) || \"\",\n total_discount: roundToTwo(item.totalDiscount),\n };\n }) || [];\n\n const eventData: Partial<EventPayload> = {\n ...baseData,\n cart_currency: currency,\n cart_total_price: roundToTwo(cartTotalPrice),\n cart_subtotal_price: roundToTwo(cartSubtotalPrice),\n cart_total_quantity: totalQuantity,\n cart_shipping_price: roundToTwo(cartShippingPrice),\n cart_tax_amount: roundToTwo(cartTaxAmount),\n cart_discount_amount: roundToTwo(cartDiscountAmount),\n cart_items: items,\n customer_id: customerId,\n };\n\n await sendEvent(eventData, workerUrl);\n}\n\n/**\n * Track checkout completed event (order placed)\n * Call this when order is placed\n *\n * NOTE: This sends to a different endpoint (orders worker)\n *\n * @example After initAnalytics()\n * ```ts\n * await trackCheckoutCompleted({\n * orderId: \"order_123456\",\n * cartTotalPrice: 109.98,\n * cartItems: [...],\n * });\n * ```\n */\nexport async function trackCheckoutCompleted(\n params: Omit<TrackCheckoutCompletedParams, \"storeId\"> & { storeId?: string },\n): Promise<void> {\n const storeId = getStoreId(params);\n if (!storeId) return;\n\n const {\n orderId,\n cartTotalPrice,\n cartSubtotalPrice,\n cartShippingPrice,\n cartTaxAmount,\n cartDiscountAmount,\n customerId,\n isFirstOrder,\n noteAttributes,\n cartItems,\n currency,\n } = params;\n\n const hasLocalizedPaths =\n params.hasLocalizedPaths ?? globalConfig?.hasLocalizedPaths;\n const ordersWorkerUrl =\n params.ordersWorkerUrl ??\n globalConfig?.ordersWorkerUrl ??\n DEFAULT_ORDERS_WORKER_URL;\n\n const baseData = createBaseEventData(\n storeId,\n \"checkout_completed\",\n hasLocalizedPaths,\n );\n if (!baseData) return; // Skip in preview mode\n\n let totalQuantity = 0;\n const items =\n cartItems?.map((item) => {\n const quantity = item.productQuantity ?? 0;\n totalQuantity += quantity;\n return {\n product_id: extractShopifyId(item.productId),\n variant_id: extractShopifyId(item.variantId),\n product_vendor: sanitizeString(item.productVendor) || \"\",\n vendor: sanitizeString(item.productVendor) || \"\",\n product_price: roundToTwo(item.productPrice),\n total_price: roundToTwo(item.productPrice),\n product_quantity: quantity,\n quantity: quantity,\n product_sku: sanitizeString(item.productSku) || \"\",\n sku: sanitizeString(item.productSku) || \"\",\n total_discount: roundToTwo(item.totalDiscount),\n };\n }) || [];\n\n const eventData: Partial<EventPayload> = {\n ...baseData,\n cart_currency: currency,\n cart_total_price: roundToTwo(cartTotalPrice),\n cart_subtotal_price: roundToTwo(cartSubtotalPrice),\n cart_total_quantity: totalQuantity,\n cart_shipping_price: roundToTwo(cartShippingPrice),\n cart_tax_amount: roundToTwo(cartTaxAmount),\n cart_discount_amount: roundToTwo(cartDiscountAmount),\n cart_items: items,\n order_id: orderId,\n customer_id: customerId,\n is_first_order: isFirstOrder ?? null,\n note_attributes: noteAttributes,\n };\n\n // Send to orders worker (different endpoint!)\n await sendEvent(eventData, ordersWorkerUrl);\n}\n\nimport { useEffect, useRef, useState } from \"react\";\n\n/**\n * Hook for automatic page view tracking on route changes\n * Use in Next.js app router or any React app\n *\n * NOTE: For Next.js App Router, consider using this with `usePathname()`:\n * ```tsx\n * const pathname = usePathname();\n * usePageViewTracking({ pathname, enabled: true });\n * ```\n *\n * @example Basic usage (tracks on mount only)\n * ```tsx\n * function Layout({ children }) {\n * usePageViewTracking({ enabled: true });\n * return <>{children}</>;\n * }\n * ```\n *\n * @example With Next.js usePathname (tracks on route changes)\n * ```tsx\n * import { usePathname } from 'next/navigation';\n *\n * function Layout({ children }) {\n * const pathname = usePathname();\n * usePageViewTracking({ pathname, enabled: true });\n * return <>{children}</>;\n * }\n * ```\n */\nexport function usePageViewTracking(\n params: UsePageViewTrackingParams & { pathname?: string },\n): void {\n const {\n storeId,\n hasLocalizedPaths,\n currency,\n workerUrl,\n enabled = true,\n pathname: externalPathname,\n } = params;\n\n // Track the last pathname we've sent an event for\n const lastTrackedPathRef = useRef<string | null>(null);\n\n // Use external pathname if provided (e.g., from Next.js usePathname),\n // otherwise try to get it from window (works on mount)\n const [currentPath, setCurrentPath] = useState<string>(() => {\n if (externalPathname) return externalPathname;\n if (typeof window !== \"undefined\") return window.location.pathname;\n return \"\";\n });\n\n // Update currentPath when externalPathname changes\n useEffect(() => {\n if (externalPathname) {\n setCurrentPath(externalPathname);\n }\n }, [externalPathname]);\n\n // Track page view when path changes\n useEffect(() => {\n if (typeof window === \"undefined\" || !enabled) return;\n\n // Don't track if we've already tracked this path\n if (lastTrackedPathRef.current === currentPath) return;\n\n // Track the page view\n lastTrackedPathRef.current = currentPath;\n trackPageView({ storeId, hasLocalizedPaths, currency, workerUrl });\n }, [currentPath, storeId, hasLocalizedPaths, currency, workerUrl, enabled]);\n}\n","import React from \"react\";\nimport type { Variation } from \"../types\";\nimport { useElevateConfig } from \"../contexts/ElevateContext\";\nimport { getVisitorId } from \"../utils/storage\";\nimport { assignAndPersistVariant, shouldShowTest } from \"../utils/assignment\";\nimport { trackViews } from \"../utils/tracking\";\n\nexport interface UseExperimentResult {\n /** The full variant object (null if not assigned) */\n variant: Variation | null;\n /** True while loading config */\n isLoading: boolean;\n /** True if assigned to control group */\n isControl: boolean;\n /** True if assigned to variation A (first non-control) */\n isA: boolean;\n /** True if assigned to variation B (second non-control) */\n isB: boolean;\n /** True if assigned to variation C (third non-control) */\n isC: boolean;\n /** True if assigned to variation D (fourth non-control) */\n isD: boolean;\n}\n\n/**\n * Hook to get assigned variant for a test\n * \n * @example\n * ```tsx\n * const { isControl, isA, isB } = useExperiment('my-test');\n * \n * if (isControl) return <Original />;\n * if (isA) return <VariantA />;\n * if (isB) return <VariantB />;\n * ```\n */\nexport function useExperiment(testId: string): UseExperimentResult {\n const { config } = useElevateConfig();\n const [variant, setVariant] = React.useState<Variation | null>(null);\n const [isLoading, setIsLoading] = React.useState(true);\n\n const testConfig = React.useMemo(() => {\n if (!config) return null;\n return config.tests.find((test) => test.testId === testId) || null;\n }, [config, testId]);\n\n // Track if we've already warned about this test (prevent duplicate warnings)\n const hasWarnedRef = React.useRef<string | null>(null);\n\n React.useEffect(() => {\n // Wait for config to load before doing anything\n if (config === null) {\n return; // Still loading config\n }\n\n // Config loaded but test not found\n if (!testConfig) {\n if (hasWarnedRef.current !== testId) {\n hasWarnedRef.current = testId;\n console.warn(`[ElevateAB] Test not found: ${testId}`);\n }\n setIsLoading(false);\n return;\n }\n\n // Test exists but is disabled\n if (!testConfig.enabled) {\n if (hasWarnedRef.current !== `${testId}-disabled`) {\n hasWarnedRef.current = `${testId}-disabled`;\n console.warn(`[ElevateAB] Test disabled: ${testId}`);\n }\n setIsLoading(false);\n return;\n }\n\n // Check traffic percentage\n if (!shouldShowTest(testConfig)) {\n setIsLoading(false);\n return;\n }\n\n // Get or create visitor ID\n const userId = getVisitorId();\n\n // Assign variant (sets isControl, isA, isB, isC, isD)\n const assigned = assignAndPersistVariant(testId, testConfig, userId);\n\n if (assigned) {\n setVariant(assigned);\n trackViews(testId);\n }\n\n setIsLoading(false);\n }, [config, testConfig, testId]);\n\n return { \n variant, \n isLoading, \n isControl: variant?.isControl ?? false,\n isA: variant?.isA ?? false,\n isB: variant?.isB ?? false,\n isC: variant?.isC ?? false,\n isD: variant?.isD ?? false,\n };\n}\n","import React, { useRef, useCallback } from \"react\";\nimport type { ElevateConfig, BackendConfig } from \"../types\";\nimport { ElevateContext } from \"../contexts/ElevateContext\";\nimport { parseBackendConfig } from \"../utils\";\nimport { initAnalytics } from \"../utils/manualTracking\";\nimport { getPreviewState, type PreviewState } from \"../utils/preview\";\nimport { getCountryCode } from \"../utils/geo\";\nimport { setupFlickerPrevention } from \"../utils/antiFlicker\";\n\n/**\n * Set to false during local development to use fallback config.\n * In production, this should always be true.\n */\nconst USE_CDN_CONFIG = false; // Set to false for demo/development\n\n/**\n * Fallback config for local development/testing when CDN is not available.\n * Only used when USE_CDN_CONFIG = false.\n *\n * Supported test types: SPLIT_URL, PRICE_PLUS, CONTENT, CUSTOM_CODE\n */\nconst DEV_FALLBACK_CONFIG: BackendConfig = {\n allTests: {\n // Price Plus Test - Testing different price points\n \"price-test-001\": {\n \"8606\": {\n variationName: \"Control\",\n trafficPercentage: 50,\n isDone: false,\n isControl: true,\n },\n \"8607\": {\n variationName: \"Sale Price\",\n trafficPercentage: 50,\n isDone: false,\n prices: {\n \"41883969519701\": {\n main: \"USD\",\n price: { USD: \"599.95\" },\n compare: { USD: \"699.95\" },\n },\n },\n },\n data: {\n name: \"Snowboard Price Test\",\n isLive: true,\n settings: { afterDiscounts: true },\n type: \"PRICE_PLUS\",\n filters: [],\n isPersonalization: false,\n currencies: [\"USD\"],\n handles: [\"the-complete-snowboard\"],\n productIds: [\"7240161067093\"],\n },\n },\n\n // Content Test - Simple A/B/C headline test\n \"content-test-001\": {\n \"ctrl-001\": {\n variationName: \"Control\",\n trafficPercentage: 34,\n isDone: false,\n isControl: true,\n content: {\n headline: \"Welcome to our store\",\n subheadline: \"Shop the best products\",\n },\n },\n \"var-a-001\": {\n variationName: \"Urgency Copy\",\n trafficPercentage: 33,\n isDone: false,\n content: {\n headline: \"Limited Time Offer!\",\n subheadline: \"Don't miss out - sale ends soon\",\n },\n },\n \"var-b-001\": {\n variationName: \"Value Copy\",\n trafficPercentage: 33,\n isDone: false,\n content: {\n headline: \"Premium Quality, Great Value\",\n subheadline: \"Free shipping on orders over $50\",\n },\n },\n data: {\n name: \"Homepage Headline Test\",\n isLive: true,\n settings: { afterDiscounts: true },\n type: \"CONTENT\",\n filters: [],\n isPersonalization: false,\n pathnames: [\"/\"],\n },\n },\n\n // Custom Code Test - Injecting custom JS/CSS\n \"custom-code-test-001\": {\n \"10150\": {\n variationName: \"Control\",\n trafficPercentage: 50,\n isDone: false,\n customCode: {\n id: \"c11a582c-6b27-4263-941c-8ed123437c6b\",\n js: \"console.log('[Elevate] Control variant active');\",\n css: \"\",\n pathnames: [\"*\"],\n excludePathnames: [],\n },\n isControl: true,\n },\n \"10151\": {\n variationName: \"Enhanced UI\",\n trafficPercentage: 50,\n isDone: false,\n customCode: {\n id: \"df71546a-0a5f-4ad0-8d0f-a1bdeab05e84\",\n js: \"console.log('[Elevate] Enhanced UI variant'); document.body.style.borderTop = '3px solid #10b981';\",\n css: \".hero-section { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }\",\n pathnames: [\"*\"],\n excludePathnames: [],\n },\n },\n data: {\n name: \"Custom Code Enhancement\",\n isLive: true,\n settings: { afterDiscounts: true },\n type: \"CUSTOM_CODE\",\n filters: [],\n isPersonalization: false,\n pathnames: [\"*\"],\n excludePathnames: [],\n },\n },\n\n // Split URL Test - Redirect to different landing pages\n \"split-url-test-001\": {\n \"split-ctrl\": {\n variationName: \"Control\",\n trafficPercentage: 50,\n isDone: false,\n isControl: true,\n splitUrlTestLinks: {\n default: \"/collections/all\",\n },\n },\n \"split-var-a\": {\n variationName: \"New Landing Page\",\n trafficPercentage: 50,\n isDone: false,\n splitUrlTestLinks: {\n default: \"/collections/featured\",\n },\n },\n data: {\n name: \"Landing Page Split Test\",\n isLive: true,\n settings: { afterDiscounts: true },\n type: \"SPLIT_URL\",\n filters: [],\n isPersonalization: false,\n pathnames: [\"/promo\"],\n },\n },\n },\n selectors: { selectorsV2: [] },\n};\n\ninterface ElevateProviderSimpleProps {\n /** Shopify store domain (e.g., \"your-store.myshopify.com\") */\n storeId: string;\n /**\n * Storefront Access Token - Required for cart attribute tracking (order attribution)\n *\n * This is SAFE to use client-side - it's a public token with limited permissions.\n * Get it from: Shopify Admin → Settings → Apps → Develop apps\n *\n * Without this token, A/B tests work but orders won't be attributed to variants.\n */\n storefrontAccessToken?: string;\n /**\n * Enable flicker prevention - hides content until test assignment is complete\n * Prevents users from seeing content flash/change when variants load\n * @default false\n */\n preventFlickering?: boolean;\n /**\n * Timeout in milliseconds for flicker prevention failsafe\n * Content will show after this time even if assignment isn't complete\n * @default 3000\n */\n flickerTimeout?: number;\n children: React.ReactNode;\n}\n\n/**\n * ElevateProvider - Provides A/B test configuration to child components\n *\n * @example Next.js / Remix\n * ```tsx\n * <ElevateProvider\n * storeId=\"your-store.myshopify.com\"\n * storefrontAccessToken=\"your-public-token\"\n * >\n * <App />\n * </ElevateProvider>\n * ```\n *\n * @example Hydrogen (with Analytics.Provider)\n * ```tsx\n * <Analytics.Provider cart={cart} shop={shop} consent={consent}>\n * <ElevateProvider storeId=\"your-store.myshopify.com\" storefrontAccessToken=\"token\">\n * <ElevateAnalytics />\n * <App />\n * </ElevateProvider>\n * </Analytics.Provider>\n * ```\n */\nexport function ElevateProvider({\n storeId,\n storefrontAccessToken,\n preventFlickering = false,\n flickerTimeout = 3000,\n children,\n}: ElevateProviderSimpleProps) {\n const [config, setConfig] = React.useState<ElevateConfig | null>(null);\n const [previewState, setPreviewState] = React.useState<PreviewState | null>(\n null,\n );\n const [countryCode, setCountryCode] = React.useState<string | null>(null);\n const revealRef = useRef<(() => void) | null>(null);\n\n // Setup flicker prevention on mount (before config loads)\n React.useEffect(() => {\n if (preventFlickering && typeof window !== \"undefined\") {\n revealRef.current = setupFlickerPrevention(\"body\", flickerTimeout);\n }\n\n return () => {\n // Cleanup: ensure content is revealed on unmount\n if (revealRef.current) {\n revealRef.current();\n }\n };\n }, [preventFlickering, flickerTimeout]);\n\n // Initialize analytics config so tracking functions don't need storeId\n React.useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n initAnalytics({\n storeId,\n storefrontAccessToken,\n });\n }, [storeId, storefrontAccessToken]);\n\n // Initialize preview state and geo on mount\n React.useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n // Get preview state from URL/cookies\n const preview = getPreviewState();\n setPreviewState(preview);\n\n // Get country code\n const country = getCountryCode();\n setCountryCode(country);\n }, []);\n\n // Reveal callback - called when config is loaded or on error\n const revealContent = useCallback(() => {\n if (revealRef.current) {\n revealRef.current();\n revealRef.current = null;\n }\n }, []);\n\n React.useEffect(() => {\n async function fetchConfig() {\n try {\n // In dev mode, skip CDN fetch and use fallback config directly\n if (!USE_CDN_CONFIG) {\n const parsedConfig = parseBackendConfig(DEV_FALLBACK_CONFIG);\n setConfig(parsedConfig);\n revealContent();\n return;\n }\n\n // Production mode: fetch from CDN\n const url = `https://configs.elevateab.com/config/${storeId}.json`;\n const response = await fetch(url);\n\n if (response.status === 404) {\n // 404 means no config - could be new store or paused subscription\n // Just render children without A/B tests, no error log for this case\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n return;\n }\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch config: ${response.status} ${response.statusText}`,\n );\n }\n\n const backendData: BackendConfig = await response.json();\n\n // Check if subscription is paused/stopped\n if (backendData.subscriptionPaused) {\n console.error(\n `[ElevateAB] Subscription is paused or stopped for store: ${storeId}. ` +\n (backendData.subscriptionMessage || \"A/B tests will not run. Please reactivate your subscription.\"),\n );\n // Graceful degradation - just render children, no A/B tests\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n return;\n }\n\n // Check if config is empty (all tests might have been paused)\n const hasActiveTests = Object.keys(backendData.allTests || {}).length > 0;\n if (!hasActiveTests) {\n // Empty config - could be paused subscription or no active tests\n // Don't log error, just render children normally\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n return;\n }\n\n const parsedConfig = parseBackendConfig(backendData);\n setConfig(parsedConfig);\n revealContent();\n } catch (err) {\n console.error(\"[ElevateAB] Failed to load config:\", err);\n // Graceful degradation - just render children, website doesn't break\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n }\n }\n\n fetchConfig();\n }, [storeId, revealContent]);\n\n const value = React.useMemo(\n () => ({\n config,\n storeId,\n storefrontAccessToken,\n isPreviewMode: previewState?.isPreview ?? false,\n previewTestId: previewState?.previewTestId ?? null,\n countryCode,\n }),\n [config, storeId, storefrontAccessToken, previewState, countryCode],\n );\n\n // Initialize analytics so tracking functions don't need storeId/token each time\n React.useEffect(() => {\n initAnalytics({ storeId, storefrontAccessToken });\n }, [storeId, storefrontAccessToken]);\n\n // Warn once if storefrontAccessToken is missing (order attribution won't work)\n const hasWarnedRef = useRef(false);\n React.useEffect(() => {\n if (!storefrontAccessToken && !hasWarnedRef.current) {\n hasWarnedRef.current = true;\n console.warn(\n \"[ElevateAB] No storefrontAccessToken provided. \" +\n \"A/B tests will work, but orders won't be attributed to test variants. \" +\n \"Add storefrontAccessToken prop to enable order tracking.\",\n );\n }\n }, [storefrontAccessToken]);\n\n return (\n <ElevateContext.Provider value={value}>{children}</ElevateContext.Provider>\n );\n}\n","// Main entry point for the Elevate AB Testing NPM package\n\n// ============================================================================\n// TYPE EXPORTS\n// ============================================================================\n\n// Core SDK types\nexport type {\n Test,\n Variation,\n ElevateConfig,\n ElevateProviderProps,\n ElevateContextValue,\n ElevateAnalyticsProps,\n ExperimentStatus,\n BackendConfig,\n BackendTest,\n BackendVariation,\n} from \"./types\";\n\n// Event tracking types (for manual tracking)\nexport type {\n // Base config\n BaseTrackingConfig,\n // Individual event params\n TrackPageViewParams,\n TrackProductViewParams,\n TrackAddToCartParams,\n TrackRemoveFromCartParams,\n TrackCartViewParams,\n TrackSearchSubmittedParams,\n TrackCheckoutStartedParams,\n TrackCheckoutCompletedParams,\n UsePageViewTrackingParams,\n // Shared types\n CartItemInput,\n NoteAttribute,\n TestAssignment,\n // Internal payload (for advanced users)\n EventPayload,\n CartItemPayload,\n} from \"./types\";\n\n// Cart attribute types\nexport type { CartAttributesOptions, CartAttributeInput } from \"./types\";\n\n// Legacy types (deprecated)\nexport type { TrackingEvent } from \"./types\";\n\nexport {\n assignVariant,\n hashString,\n validateConfig,\n generateExperimentId,\n calculateRevenueLift,\n} from \"./utils\";\n\n// Storage utilities\nexport {\n setCookie,\n getCookie,\n getJsonCookie,\n deleteCookie,\n setSessionItem,\n getSessionItem,\n getJsonSessionItem,\n getVisitorId,\n initializeVisitorId,\n getSessionId,\n initializeSessionId,\n setReferrerData,\n getReferrerData,\n uuidv4,\n} from \"./utils/storage\";\n\n// Assignment utilities\nexport {\n getTestList,\n saveTestList,\n getAssignedVariant,\n assignAndPersistVariant,\n shouldShowTest,\n} from \"./utils/assignment\";\n\n// Tracking utilities\nexport {\n trackViews,\n trackUniqueView,\n trackSessionView,\n hasSessionView,\n hasUniqueView,\n} from \"./utils/tracking\";\n\n// Condition utilities\nexport {\n getDeviceType,\n getTrafficSource,\n checkFacebookBrowser,\n checkInstagramBrowser,\n checkTikTokBrowser,\n checkPinterestBrowser,\n} from \"./utils/conditions\";\n\n// Preview mode utilities\nexport {\n getPreviewState,\n isPreviewTest,\n getPreviewVariation,\n buildEabTestsParam,\n updateUrlWithTestParams,\n clearPreviewMode,\n isInPreviewMode,\n} from \"./utils/preview\";\nexport type { PreviewState } from \"./utils/preview\";\n\n// Geo-targeting utilities\nexport {\n getCountryCode,\n getGeoLocation,\n setCountryCode,\n setGeoLocation,\n isCountryIncluded,\n isCountryExcluded,\n matchesGeoTargeting,\n COUNTRIES,\n REGIONS,\n} from \"./utils/geo\";\nexport type { GeoLocation } from \"./utils/geo\";\n\n// Anti-flicker utilities\nexport {\n setupFlickerPrevention,\n injectFlickerStyles,\n hideForFlicker,\n revealAfterFlicker,\n cleanupFlickerPrevention,\n isFlickerPreventionActive,\n getFlickerPreventionScript,\n} from \"./utils/antiFlicker\";\n\n// Analytics utilities\nexport {\n parseAddViewData,\n extractProductId,\n extractProductVariantId,\n extractCartToken,\n cleanCartToken,\n getPageTypeFromPathname,\n sanitizeString,\n roundToTwo,\n checkFacebookInstagramBrowser,\n checkVisitorIdParams,\n getUserAgentNoBrowser,\n} from \"./utils/analytics\";\n\nexport type { ParsedViewData } from \"./utils/analytics\";\n\n// Shopify utilities\nexport {\n extractShopifyId,\n extractShopifyType,\n isShopifyGid,\n detectShopifyCurrency,\n} from \"./utils/shopify\";\n\n// Cart attribute utilities\nexport {\n updateCartAttributes,\n cleanupCartAttributes,\n getCartAttributesPayload,\n} from \"./utils/cartAttributes\";\n\n// Cart mutations\nexport { CART_ATTRIBUTES_UPDATE_MUTATION } from \"./mutations/cartAttributes.mutation\";\n\n// Manual tracking utilities (for Next.js and other frameworks)\n// Note: ElevateProvider auto-calls initAnalytics, so you usually don't need to call it manually\nexport {\n initAnalytics,\n trackPageView,\n trackProductView,\n trackAddToCart,\n trackRemoveFromCart,\n trackCartView,\n trackSearchSubmitted,\n trackCheckoutStarted,\n trackCheckoutCompleted,\n usePageViewTracking,\n} from \"./utils/manualTracking\";\n\n// Components\nexport { useExperiment } from \"./components/Experiment\";\nexport type { UseExperimentResult } from \"./components/Experiment\";\nexport { ElevateProvider } from \"./components/ElevateProvider\";\n\n// Analytics components\n// For Hydrogen stores: import from '@elevateab/sdk/hydrogen' for ElevateHydrogenAnalytics\n// For Next.js/Remix: use ElevateAnalytics with manual hook injection\nexport { ElevateAnalytics } from \"./components/ElevateAnalytics\";\nexport type {\n UseAnalyticsHook,\n ElevateHydrogenAnalyticsProps,\n} from \"./components/ElevateAnalytics\";\n\n// Note: ElevateHydrogenAnalytics is exported from '@elevateab/sdk/hydrogen' sub-path\n// to avoid bundling @shopify/hydrogen in non-Hydrogen projects\n\n// Contexts\nexport { useElevateConfig } from \"./contexts/ElevateContext\";\n\n// Package version\nexport const VERSION = \"1.1.2\";\n\n// Default configuration\nexport const DEFAULT_CONFIG = {\n enabled: true,\n trackingEndpoint: \"https://analytics.elevateab.com/track\",\n cacheDuration: 3600,\n};\n"],"mappings":"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","names":["trackUniqueView","testId","addedUniqueViews","getJsonCookie","setCookie","trackSessionView","addedViews","getJsonSessionItem","setSessionItem","trackViews","hasSessionView","hasUniqueView","getDeviceType","ua","lower","checkFacebookBrowser","userAgent","checkInstagramBrowser","checkTikTokBrowser","checkPinterestBrowser","getTrafficSource","referrer","referrerDomain","hostname","isFacebookBrowser","isInstagramBrowser","isTikTokBrowser","isPinterestBrowser","parseEabTestsParam","param","assignments","views","tests","test","parts","shortTestId","variationId","hasSeen","getPreviewState","urlParams","isPreview","getCookie","previewTestId","getSessionItem","eabTestsParam","setCookie","setSessionItem","isPreviewTest","testId","getPreviewVariation","previewState","buildEabTestsParam","testAssignments","viewedTests","updateUrlWithTestParams","visitorId","url","eabTestsValue","clearPreviewMode","isInPreviewMode","GEO_COOKIE_NAMES","getCountryCode","urlCountry","setCookie","shopifyCountry","getCookie","cachedCountry","storedCountry","getGeoLocation","country","geoData","parsed","setCountryCode","countryCode","normalized","setGeoLocation","geo","isCountryIncluded","allowedCountries","userCountry","c","isCountryExcluded","excludedCountries","matchesGeoTargeting","rules","COUNTRIES","REGIONS","FLICKER_CLASS","STYLE_ID","injectFlickerStyles","timeout","STYLE_ID","style","FLICKER_CLASS","head","hideForFlicker","selector","element","revealAfterFlicker","setupFlickerPrevention","hasRevealed","timeoutId","cleanupFlickerPrevention","el","isFlickerPreventionActive","getFlickerPreventionScript","extractShopifyId","gid","extractShopifyType","isShopifyGid","value","detectShopifyCurrency","shopify","useEffect","useRef","useState","DEFAULT_WORKER_URL","DEFAULT_ORDERS_WORKER_URL","globalConfig","initAnalytics","config","getStoreId","params","storeId","globalConfig","transformTestFormat","testObject","variationId","testId","transformViewedTests","viewedObject","assignmentObject","isInPreviewMode","getCookie","createBaseEventData","eventType","hasLocalizedPaths","userAgent","pathname","pageType","getPageTypeFromPathname","referrer","entryPage","getReferrerData","parsedData","parseAddViewData","abtlObject","getJsonCookie","abauObject","testAssignments","viewedTests","cartToken","extractCartToken","currentTimestamp","isFirstVisit","shopifyCountry","uuidv4","getVisitorId","getSessionId","cleanCartToken","getUserAgentNoBrowser","sendEvent","data","workerUrl","DEFAULT_WORKER_URL","response","error","trackPageView","baseData","eventData","trackProductView","productId","productVendor","productPrice","productSku","currency","extractShopifyId","sanitizeString","roundToTwo","trackAddToCart","variantId","productQuantity","cartId","storefrontAccessToken","updateCartAttributes","err","trackRemoveFromCart","trackCartView","cartTotalPrice","cartTotalQuantity","cartItems","item","trackSearchSubmitted","searchQuery","trackCheckoutStarted","cartSubtotalPrice","cartShippingPrice","cartTaxAmount","cartDiscountAmount","customerId","totalQuantity","items","quantity","trackCheckoutCompleted","orderId","isFirstOrder","noteAttributes","ordersWorkerUrl","DEFAULT_ORDERS_WORKER_URL","usePageViewTracking","enabled","externalPathname","lastTrackedPathRef","useRef","currentPath","setCurrentPath","useState","useEffect","React","useExperiment","testId","config","useElevateConfig","variant","setVariant","React","isLoading","setIsLoading","testConfig","test","hasWarnedRef","shouldShowTest","userId","getVisitorId","assigned","assignAndPersistVariant","trackViews","React","useRef","useCallback","USE_CDN_CONFIG","DEV_FALLBACK_CONFIG","ElevateProvider","storeId","storefrontAccessToken","preventFlickering","flickerTimeout","children","config","setConfig","React","previewState","setPreviewState","countryCode","setCountryCode","revealRef","useRef","setupFlickerPrevention","initAnalytics","preview","getPreviewState","country","getCountryCode","revealContent","useCallback","fetchConfig","parsedConfig","parseBackendConfig","url","response","backendData","err","value","hasWarnedRef","ElevateContext","VERSION","DEFAULT_CONFIG"]}
|
package/dist/next.cjs
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";var dr=Object.create;var xe=Object.defineProperty;var lr=Object.getOwnPropertyDescriptor;var fr=Object.getOwnPropertyNames;var pr=Object.getPrototypeOf,mr=Object.prototype.hasOwnProperty;var ce=(e,t)=>()=>(e&&(t=e(e=0)),t);var gr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Ft=(e,t)=>{for(var o in t)xe(e,o,{get:t[o],enumerable:!0})},Mt=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of fr(t))!mr.call(e,a)&&a!==o&&xe(e,a,{get:()=>t[a],enumerable:!(s=lr(t,a))||s.enumerable});return e};var ue=(e,t,o)=>(o=e!=null?dr(pr(e)):{},Mt(t||!e||!e.__esModule?xe(o,"default",{value:e,enumerable:!0}):o,e)),br=e=>Mt(xe({},"__esModule",{value:!0}),e);function Ye(e){let t=0;for(let o=0;o<e.length;o++){let s=e.charCodeAt(o);t=(t<<5)-t+s,t=t&t}return Math.abs(t)}function Qe(e){let t=[];for(let[o,s]of Object.entries(e.allTests)){if(!s.data.isLive)continue;let a=[],f=0;for(let[d,p]of Object.entries(s)){if(d==="data")continue;let l=p;if(typeof l=="object"&&l!==null&&"variationName"in l){let w=!!l.isControl;a.push({id:d,name:l.variationName,weight:l.trafficPercentage,isControl:w,productId:l.id,handle:l.handle,price:l.price,isA:!w&&f===0,isB:!w&&f===1,isC:!w&&f===2,isD:!w&&f===3}),w||f++}}a.length>0&&t.push({testId:o,name:s.data.name,enabled:s.data.isLive,type:s.data.type,variations:a})}return{tests:t,selectors:e.selectors}}var Te=ce(()=>{"use strict"});var zt=gr((le,Ae)=>{"use strict";(function(e,t){"use strict";var o="1.0.41",s="",a="?",f="function",d="undefined",p="object",l="string",w="major",r="model",c="name",n="type",i="vendor",u="version",T="architecture",_="console",m="mobile",g="tablet",x="smarttv",E="wearable",G="embedded",Fe=500,ge="Amazon",J="Apple",Tt="ASUS",At="BlackBerry",be="Browser",we="Chrome",ir="Edge",he="Firefox",ye="Google",Ct="Honor",Et="Huawei",ar="Lenovo",ve="LG",Me="Microsoft",ze="Motorola",qe="Nvidia",St="OnePlus",re="Opera",je="OPPO",oe="Samsung",It="Sharp",ne="Sony",$e="Xiaomi",Ge="Zebra",Ut="Facebook",Rt="Chromium OS",Ot="Mac OS",Vt=" Browser",sr=function(y,v){var h={};for(var P in y)v[P]&&v[P].length%2===0?h[P]=v[P].concat(y[P]):h[P]=y[P];return h},ke=function(y){for(var v={},h=0;h<y.length;h++)v[y[h].toUpperCase()]=y[h];return v},Lt=function(y,v){return typeof y===l?ie(v).indexOf(ie(y))!==-1:!1},ie=function(y){return y.toLowerCase()},cr=function(y){return typeof y===l?y.replace(/[^\d\.]/g,s).split(".")[0]:t},We=function(y,v){if(typeof y===l)return y=y.replace(/^\s\s*/,s),typeof v===d?y:y.substring(0,Fe)},ae=function(y,v){for(var h=0,P,F,B,k,b,D;h<v.length&&!b;){var He=v[h],Nt=v[h+1];for(P=F=0;P<He.length&&!b&&He[P];)if(b=He[P++].exec(y),b)for(B=0;B<Nt.length;B++)D=b[++F],k=Nt[B],typeof k===p&&k.length>0?k.length===2?typeof k[1]==f?this[k[0]]=k[1].call(this,D):this[k[0]]=k[1]:k.length===3?typeof k[1]===f&&!(k[1].exec&&k[1].test)?this[k[0]]=D?k[1].call(this,D,k[2]):t:this[k[0]]=D?D.replace(k[1],k[2]):t:k.length===4&&(this[k[0]]=D?k[3].call(this,D.replace(k[1],k[2])):t):this[k]=D||t;h+=2}},se=function(y,v){for(var h in v)if(typeof v[h]===p&&v[h].length>0){for(var P=0;P<v[h].length;P++)if(Lt(v[h][P],y))return h===a?t:h}else if(Lt(v[h],y))return h===a?t:h;return v.hasOwnProperty("*")?v["*"]:y},ur={"1.0":"/8","1.2":"/1","1.3":"/3","2.0":"/412","2.0.2":"/416","2.0.3":"/417","2.0.4":"/419","?":"/"},Bt={ME:"4.90","NT 3.11":"NT3.51","NT 4.0":"NT4.0",2e3:"NT 5.0",XP:["NT 5.1","NT 5.2"],Vista:"NT 6.0",7:"NT 6.1",8:"NT 6.2","8.1":"NT 6.3",10:["NT 6.4","NT 10.0"],RT:"ARM"},Dt={browser:[[/\b(?:crmo|crios)\/([\w\.]+)/i],[u,[c,"Chrome"]],[/edg(?:e|ios|a)?\/([\w\.]+)/i],[u,[c,"Edge"]],[/(opera mini)\/([-\w\.]+)/i,/(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i,/(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i],[c,u],[/opios[\/ ]+([\w\.]+)/i],[u,[c,re+" Mini"]],[/\bop(?:rg)?x\/([\w\.]+)/i],[u,[c,re+" GX"]],[/\bopr\/([\w\.]+)/i],[u,[c,re]],[/\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i],[u,[c,"Baidu"]],[/\b(?:mxbrowser|mxios|myie2)\/?([-\w\.]*)\b/i],[u,[c,"Maxthon"]],[/(kindle)\/([\w\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i,/(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i,/(?:ms|\()(ie) ([\w\.]+)/i,/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon)\/([-\w\.]+)/i,/(heytap|ovi|115)browser\/([\d\.]+)/i,/(weibo)__([\d\.]+)/i],[c,u],[/quark(?:pc)?\/([-\w\.]+)/i],[u,[c,"Quark"]],[/\bddg\/([\w\.]+)/i],[u,[c,"DuckDuckGo"]],[/(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i],[u,[c,"UC"+be]],[/microm.+\bqbcore\/([\w\.]+)/i,/\bqbcore\/([\w\.]+).+microm/i,/micromessenger\/([\w\.]+)/i],[u,[c,"WeChat"]],[/konqueror\/([\w\.]+)/i],[u,[c,"Konqueror"]],[/trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i],[u,[c,"IE"]],[/ya(?:search)?browser\/([\w\.]+)/i],[u,[c,"Yandex"]],[/slbrowser\/([\w\.]+)/i],[u,[c,"Smart Lenovo "+be]],[/(avast|avg)\/([\w\.]+)/i],[[c,/(.+)/,"$1 Secure "+be],u],[/\bfocus\/([\w\.]+)/i],[u,[c,he+" Focus"]],[/\bopt\/([\w\.]+)/i],[u,[c,re+" Touch"]],[/coc_coc\w+\/([\w\.]+)/i],[u,[c,"Coc Coc"]],[/dolfin\/([\w\.]+)/i],[u,[c,"Dolphin"]],[/coast\/([\w\.]+)/i],[u,[c,re+" Coast"]],[/miuibrowser\/([\w\.]+)/i],[u,[c,"MIUI"+Vt]],[/fxios\/([\w\.-]+)/i],[u,[c,he]],[/\bqihoobrowser\/?([\w\.]*)/i],[u,[c,"360"]],[/\b(qq)\/([\w\.]+)/i],[[c,/(.+)/,"$1Browser"],u],[/(oculus|sailfish|huawei|vivo|pico)browser\/([\w\.]+)/i],[[c,/(.+)/,"$1"+Vt],u],[/samsungbrowser\/([\w\.]+)/i],[u,[c,oe+" Internet"]],[/metasr[\/ ]?([\d\.]+)/i],[u,[c,"Sogou Explorer"]],[/(sogou)mo\w+\/([\d\.]+)/i],[[c,"Sogou Mobile"],u],[/(electron)\/([\w\.]+) safari/i,/(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i,/m?(qqbrowser|2345(?=browser|chrome|explorer))\w*[\/ ]?v?([\w\.]+)/i],[c,u],[/(lbbrowser|rekonq)/i,/\[(linkedin)app\]/i],[c],[/ome\/([\w\.]+) \w* ?(iron) saf/i,/ome\/([\w\.]+).+qihu (360)[es]e/i],[u,c],[/((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i],[[c,Ut],u],[/(Klarna)\/([\w\.]+)/i,/(kakao(?:talk|story))[\/ ]([\w\.]+)/i,/(naver)\(.*?(\d+\.[\w\.]+).*\)/i,/(daum)apps[\/ ]([\w\.]+)/i,/safari (line)\/([\w\.]+)/i,/\b(line)\/([\w\.]+)\/iab/i,/(alipay)client\/([\w\.]+)/i,/(twitter)(?:and| f.+e\/([\w\.]+))/i,/(chromium|instagram|snapchat)[\/ ]([-\w\.]+)/i],[c,u],[/\bgsa\/([\w\.]+) .*safari\//i],[u,[c,"GSA"]],[/musical_ly(?:.+app_?version\/|_)([\w\.]+)/i],[u,[c,"TikTok"]],[/headlesschrome(?:\/([\w\.]+)| )/i],[u,[c,we+" Headless"]],[/ wv\).+(chrome)\/([\w\.]+)/i],[[c,we+" WebView"],u],[/droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i],[u,[c,"Android "+be]],[/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i],[c,u],[/version\/([\w\.\,]+) .*mobile\/\w+ (safari)/i],[u,[c,"Mobile Safari"]],[/version\/([\w(\.|\,)]+) .*(mobile ?safari|safari)/i],[u,c],[/webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i],[c,[u,se,ur]],[/(webkit|khtml)\/([\w\.]+)/i],[c,u],[/(navigator|netscape\d?)\/([-\w\.]+)/i],[[c,"Netscape"],u],[/(wolvic|librewolf)\/([\w\.]+)/i],[c,u],[/mobile vr; rv:([\w\.]+)\).+firefox/i],[u,[c,he+" Reality"]],[/ekiohf.+(flow)\/([\w\.]+)/i,/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,/(firefox)\/([\w\.]+)/i,/(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i,/(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,/\b(links) \(([\w\.]+)/i],[c,[u,/_/g,"."]],[/(cobalt)\/([\w\.]+)/i],[c,[u,/master.|lts./,""]]],cpu:[[/\b((amd|x|x86[-_]?|wow|win)64)\b/i],[[T,"amd64"]],[/(ia32(?=;))/i,/\b((i[346]|x)86)(pc)?\b/i],[[T,"ia32"]],[/\b(aarch64|arm(v?[89]e?l?|_?64))\b/i],[[T,"arm64"]],[/\b(arm(v[67])?ht?n?[fl]p?)\b/i],[[T,"armhf"]],[/( (ce|mobile); ppc;|\/[\w\.]+arm\b)/i],[[T,"arm"]],[/((ppc|powerpc)(64)?)( mac|;|\))/i],[[T,/ower/,s,ie]],[/ sun4\w[;\)]/i],[[T,"sparc"]],[/\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i],[[T,ie]]],device:[[/\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i],[r,[i,oe],[n,g]],[/\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,/samsung[- ]((?!sm-[lr])[-\w]+)/i,/sec-(sgh\w+)/i],[r,[i,oe],[n,m]],[/(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i],[r,[i,J],[n,m]],[/\((ipad);[-\w\),; ]+apple/i,/applecoremedia\/[\w\.]+ \((ipad)/i,/\b(ipad)\d\d?,\d\d?[;\]].+ios/i],[r,[i,J],[n,g]],[/(macintosh);/i],[r,[i,J]],[/\b(sh-?[altvz]?\d\d[a-ekm]?)/i],[r,[i,It],[n,m]],[/\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\)|;)/i],[r,[i,Ct],[n,g]],[/honor([-\w ]+)[;\)]/i],[r,[i,Ct],[n,m]],[/\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\w\. ]*(?= bui|\)))\b(?!.+d\/s)/i],[r,[i,Et],[n,g]],[/(?:huawei)([-\w ]+)[;\)]/i,/\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i],[r,[i,Et],[n,m]],[/oid[^\)]+; (2[\dbc]{4}(182|283|rp\w{2})[cgl]|m2105k81a?c)(?: bui|\))/i,/\b((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i],[[r,/_/g," "],[i,$e],[n,g]],[/\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i,/\b; (\w+) build\/hm\1/i,/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i,/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i,/oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i,/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite|pro)?)(?: bui|\))/i,/ ([\w ]+) miui\/v?\d/i],[[r,/_/g," "],[i,$e],[n,m]],[/; (\w+) bui.+ oppo/i,/\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i],[r,[i,je],[n,m]],[/\b(opd2(\d{3}a?))(?: bui|\))/i],[r,[i,se,{OnePlus:["304","403","203"],"*":je}],[n,g]],[/vivo (\w+)(?: bui|\))/i,/\b(v[12]\d{3}\w?[at])(?: bui|;)/i],[r,[i,"Vivo"],[n,m]],[/\b(rmx[1-3]\d{3})(?: bui|;|\))/i],[r,[i,"Realme"],[n,m]],[/\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,/\bmot(?:orola)?[- ](\w*)/i,/((?:moto(?! 360)[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i],[r,[i,ze],[n,m]],[/\b(mz60\d|xoom[2 ]{0,2}) build\//i],[r,[i,ze],[n,g]],[/((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i],[r,[i,ve],[n,g]],[/(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,/\blg[-e;\/ ]+((?!browser|netcast|android tv|watch)\w+)/i,/\blg-?([\d\w]+) bui/i],[r,[i,ve],[n,m]],[/(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i,/lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i],[r,[i,ar],[n,g]],[/(nokia) (t[12][01])/i],[i,r,[n,g]],[/(?:maemo|nokia).*(n900|lumia \d+|rm-\d+)/i,/nokia[-_ ]?(([-\w\. ]*))/i],[[r,/_/g," "],[n,m],[i,"Nokia"]],[/(pixel (c|tablet))\b/i],[r,[i,ye],[n,g]],[/droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i],[r,[i,ye],[n,m]],[/droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i],[r,[i,ne],[n,m]],[/sony tablet [ps]/i,/\b(?:sony)?sgp\w+(?: bui|\))/i],[[r,"Xperia Tablet"],[i,ne],[n,g]],[/ (kb2005|in20[12]5|be20[12][59])\b/i,/(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i],[r,[i,St],[n,m]],[/(alexa)webm/i,/(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i,/(kf[a-z]+)( bui|\)).+silk\//i],[r,[i,ge],[n,g]],[/((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i],[[r,/(.+)/g,"Fire Phone $1"],[i,ge],[n,m]],[/(playbook);[-\w\),; ]+(rim)/i],[r,i,[n,g]],[/\b((?:bb[a-f]|st[hv])100-\d)/i,/\(bb10; (\w+)/i],[r,[i,At],[n,m]],[/(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i],[r,[i,Tt],[n,g]],[/ (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i],[r,[i,Tt],[n,m]],[/(nexus 9)/i],[r,[i,"HTC"],[n,g]],[/(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i,/(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,/(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i],[i,[r,/_/g," "],[n,m]],[/droid [\w\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])\w*(\)| bui)/i],[r,[i,"TCL"],[n,g]],[/(itel) ((\w+))/i],[[i,ie],r,[n,se,{tablet:["p10001l","w7001"],"*":"mobile"}]],[/droid.+; ([ab][1-7]-?[0178a]\d\d?)/i],[r,[i,"Acer"],[n,g]],[/droid.+; (m[1-5] note) bui/i,/\bmz-([-\w]{2,})/i],[r,[i,"Meizu"],[n,m]],[/; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i],[r,[i,"Ulefone"],[n,m]],[/; (energy ?\w+)(?: bui|\))/i,/; energizer ([\w ]+)(?: bui|\))/i],[r,[i,"Energizer"],[n,m]],[/; cat (b35);/i,/; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\))/i],[r,[i,"Cat"],[n,m]],[/((?:new )?andromax[\w- ]+)(?: bui|\))/i],[r,[i,"Smartfren"],[n,m]],[/droid.+; (a(?:015|06[35]|142p?))/i],[r,[i,"Nothing"],[n,m]],[/; (x67 5g|tikeasy \w+|ac[1789]\d\w+)( b|\))/i,/archos ?(5|gamepad2?|([\w ]*[t1789]|hello) ?\d+[\w ]*)( b|\))/i],[r,[i,"Archos"],[n,g]],[/archos ([\w ]+)( b|\))/i,/; (ac[3-6]\d\w{2,8})( b|\))/i],[r,[i,"Archos"],[n,m]],[/(imo) (tab \w+)/i,/(infinix) (x1101b?)/i],[i,r,[n,g]],[/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\w]*)/i,/; (hmd|imo) ([\w ]+?)(?: bui|\))/i,/(hp) ([\w ]+\w)/i,/(microsoft); (lumia[\w ]+)/i,/(lenovo)[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i,/(oppo) ?([\w ]+) bui/i],[i,r,[n,m]],[/(kobo)\s(ereader|touch)/i,/(hp).+(touchpad(?!.+tablet)|tablet)/i,/(kindle)\/([\w\.]+)/i,/(nook)[\w ]+build\/(\w+)/i,/(dell) (strea[kpr\d ]*[\dko])/i,/(le[- ]+pan)[- ]+(\w{1,9}) bui/i,/(trinity)[- ]*(t\d{3}) bui/i,/(gigaset)[- ]+(q\w{1,9}) bui/i,/(vodafone) ([\w ]+)(?:\)| bui)/i],[i,r,[n,g]],[/(surface duo)/i],[r,[i,Me],[n,g]],[/droid [\d\.]+; (fp\du?)(?: b|\))/i],[r,[i,"Fairphone"],[n,m]],[/(u304aa)/i],[r,[i,"AT&T"],[n,m]],[/\bsie-(\w*)/i],[r,[i,"Siemens"],[n,m]],[/\b(rct\w+) b/i],[r,[i,"RCA"],[n,g]],[/\b(venue[\d ]{2,7}) b/i],[r,[i,"Dell"],[n,g]],[/\b(q(?:mv|ta)\w+) b/i],[r,[i,"Verizon"],[n,g]],[/\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i],[r,[i,"Barnes & Noble"],[n,g]],[/\b(tm\d{3}\w+) b/i],[r,[i,"NuVision"],[n,g]],[/\b(k88) b/i],[r,[i,"ZTE"],[n,g]],[/\b(nx\d{3}j) b/i],[r,[i,"ZTE"],[n,m]],[/\b(gen\d{3}) b.+49h/i],[r,[i,"Swiss"],[n,m]],[/\b(zur\d{3}) b/i],[r,[i,"Swiss"],[n,g]],[/\b((zeki)?tb.*\b) b/i],[r,[i,"Zeki"],[n,g]],[/\b([yr]\d{2}) b/i,/\b(dragon[- ]+touch |dt)(\w{5}) b/i],[[i,"Dragon Touch"],r,[n,g]],[/\b(ns-?\w{0,9}) b/i],[r,[i,"Insignia"],[n,g]],[/\b((nxa|next)-?\w{0,9}) b/i],[r,[i,"NextBook"],[n,g]],[/\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i],[[i,"Voice"],r,[n,m]],[/\b(lvtel\-)?(v1[12]) b/i],[[i,"LvTel"],r,[n,m]],[/\b(ph-1) /i],[r,[i,"Essential"],[n,m]],[/\b(v(100md|700na|7011|917g).*\b) b/i],[r,[i,"Envizen"],[n,g]],[/\b(trio[-\w\. ]+) b/i],[r,[i,"MachSpeed"],[n,g]],[/\btu_(1491) b/i],[r,[i,"Rotor"],[n,g]],[/((?:tegranote|shield t(?!.+d tv))[\w- ]*?)(?: b|\))/i],[r,[i,qe],[n,g]],[/(sprint) (\w+)/i],[i,r,[n,m]],[/(kin\.[onetw]{3})/i],[[r,/\./g," "],[i,Me],[n,m]],[/droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i],[r,[i,Ge],[n,g]],[/droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i],[r,[i,Ge],[n,m]],[/smart-tv.+(samsung)/i],[i,[n,x]],[/hbbtv.+maple;(\d+)/i],[[r,/^/,"SmartTV"],[i,oe],[n,x]],[/(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i],[[i,ve],[n,x]],[/(apple) ?tv/i],[i,[r,J+" TV"],[n,x]],[/crkey/i],[[r,we+"cast"],[i,ye],[n,x]],[/droid.+aft(\w+)( bui|\))/i],[r,[i,ge],[n,x]],[/(shield \w+ tv)/i],[r,[i,qe],[n,x]],[/\(dtv[\);].+(aquos)/i,/(aquos-tv[\w ]+)\)/i],[r,[i,It],[n,x]],[/(bravia[\w ]+)( bui|\))/i],[r,[i,ne],[n,x]],[/(mi(tv|box)-?\w+) bui/i],[r,[i,$e],[n,x]],[/Hbbtv.*(technisat) (.*);/i],[i,r,[n,x]],[/\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i,/hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i],[[i,We],[r,We],[n,x]],[/droid.+; ([\w- ]+) (?:android tv|smart[- ]?tv)/i],[r,[n,x]],[/\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i],[[n,x]],[/(ouya)/i,/(nintendo) ([wids3utch]+)/i],[i,r,[n,_]],[/droid.+; (shield)( bui|\))/i],[r,[i,qe],[n,_]],[/(playstation \w+)/i],[r,[i,ne],[n,_]],[/\b(xbox(?: one)?(?!; xbox))[\); ]/i],[r,[i,Me],[n,_]],[/\b(sm-[lr]\d\d[0156][fnuw]?s?|gear live)\b/i],[r,[i,oe],[n,E]],[/((pebble))app/i,/(asus|google|lg|oppo) ((pixel |zen)?watch[\w ]*)( bui|\))/i],[i,r,[n,E]],[/(ow(?:19|20)?we?[1-3]{1,3})/i],[r,[i,je],[n,E]],[/(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i],[r,[i,J],[n,E]],[/(opwwe\d{3})/i],[r,[i,St],[n,E]],[/(moto 360)/i],[r,[i,ze],[n,E]],[/(smartwatch 3)/i],[r,[i,ne],[n,E]],[/(g watch r)/i],[r,[i,ve],[n,E]],[/droid.+; (wt63?0{2,3})\)/i],[r,[i,Ge],[n,E]],[/droid.+; (glass) \d/i],[r,[i,ye],[n,E]],[/(pico) (4|neo3(?: link|pro)?)/i],[i,r,[n,E]],[/; (quest( \d| pro)?)/i],[r,[i,Ut],[n,E]],[/(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i],[i,[n,G]],[/(aeobc)\b/i],[r,[i,ge],[n,G]],[/(homepod).+mac os/i],[r,[i,J],[n,G]],[/windows iot/i],[[n,G]],[/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+? mobile safari/i],[r,[n,m]],[/droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i],[r,[n,g]],[/\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i],[[n,g]],[/(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i],[[n,m]],[/droid .+?; ([\w\. -]+)( bui|\))/i],[r,[i,"Generic"]]],engine:[[/windows.+ edge\/([\w\.]+)/i],[u,[c,ir+"HTML"]],[/(arkweb)\/([\w\.]+)/i],[c,u],[/webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i],[u,[c,"Blink"]],[/(presto)\/([\w\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i,/ekioh(flow)\/([\w\.]+)/i,/(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i,/(icab)[\/ ]([23]\.[\d\.]+)/i,/\b(libweb)/i],[c,u],[/ladybird\//i],[[c,"LibWeb"]],[/rv\:([\w\.]{1,9})\b.+(gecko)/i],[u,c]],os:[[/microsoft (windows) (vista|xp)/i],[c,u],[/(windows (?:phone(?: os)?|mobile|iot))[\/ ]?([\d\.\w ]*)/i],[c,[u,se,Bt]],[/windows nt 6\.2; (arm)/i,/windows[\/ ]([ntce\d\. ]+\w)(?!.+xbox)/i,/(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i],[[u,se,Bt],[c,"Windows"]],[/[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i,/(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,/cfnetwork\/.+darwin/i],[[u,/_/g,"."],[c,"iOS"]],[/(mac os x) ?([\w\. ]*)/i,/(macintosh|mac_powerpc\b)(?!.+haiku)/i],[[c,Ot],[u,/_/g,"."]],[/droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i],[u,c],[/(ubuntu) ([\w\.]+) like android/i],[[c,/(.+)/,"$1 Touch"],u],[/(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen|webos)\w*[-\/; ]?([\d\.]*)/i],[c,u],[/\(bb(10);/i],[u,[c,At]],[/(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\/ ]?([\w\.]*)/i],[u,[c,"Symbian"]],[/mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i],[u,[c,he+" OS"]],[/web0s;.+rt(tv)/i,/\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i],[u,[c,"webOS"]],[/watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i],[u,[c,"watchOS"]],[/crkey\/([\d\.]+)/i],[u,[c,we+"cast"]],[/(cros) [\w]+(?:\)| ([\w\.]+)\b)/i],[[c,Rt],u],[/panasonic;(viera)/i,/(netrange)mmh/i,/(nettv)\/(\d+\.[\w\.]+)/i,/(nintendo|playstation) ([wids345portablevuch]+)/i,/(xbox); +xbox ([^\);]+)/i,/\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i,/(mint)[\/\(\) ]?(\w*)/i,/(mageia|vectorlinux)[; ]/i,/([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i,/(hurd|linux)(?: arm\w*| x86\w*| ?)([\w\.]*)/i,/(gnu) ?([\w\.]*)/i,/\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i,/(haiku) (\w+)/i],[c,u],[/(sunos) ?([\w\.\d]*)/i],[[c,"Solaris"],u],[/((?:open)?solaris)[-\/ ]?([\w\.]*)/i,/(aix) ((\d)(?=\.|\)| )[\w\.])*/i,/\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i,/(unix) ?([\w\.]*)/i],[c,u]]},O=function(y,v){if(typeof y===p&&(v=y,y=t),!(this instanceof O))return new O(y,v).getResult();var h=typeof e!==d&&e.navigator?e.navigator:t,P=y||(h&&h.userAgent?h.userAgent:s),F=h&&h.userAgentData?h.userAgentData:t,B=v?sr(Dt,v):Dt,k=h&&h.userAgent==P;return this.getBrowser=function(){var b={};return b[c]=t,b[u]=t,ae.call(b,P,B.browser),b[w]=cr(b[u]),k&&h&&h.brave&&typeof h.brave.isBrave==f&&(b[c]="Brave"),b},this.getCPU=function(){var b={};return b[T]=t,ae.call(b,P,B.cpu),b},this.getDevice=function(){var b={};return b[i]=t,b[r]=t,b[n]=t,ae.call(b,P,B.device),k&&!b[n]&&F&&F.mobile&&(b[n]=m),k&&b[r]=="Macintosh"&&h&&typeof h.standalone!==d&&h.maxTouchPoints&&h.maxTouchPoints>2&&(b[r]="iPad",b[n]=g),b},this.getEngine=function(){var b={};return b[c]=t,b[u]=t,ae.call(b,P,B.engine),b},this.getOS=function(){var b={};return b[c]=t,b[u]=t,ae.call(b,P,B.os),k&&!b[c]&&F&&F.platform&&F.platform!="Unknown"&&(b[c]=F.platform.replace(/chrome os/i,Rt).replace(/macos/i,Ot)),b},this.getResult=function(){return{ua:this.getUA(),browser:this.getBrowser(),engine:this.getEngine(),os:this.getOS(),device:this.getDevice(),cpu:this.getCPU()}},this.getUA=function(){return P},this.setUA=function(b){return P=typeof b===l&&b.length>Fe?We(b,Fe):b,this},this.setUA(P),this};O.VERSION=o,O.BROWSER=ke([c,u,w]),O.CPU=ke([T]),O.DEVICE=ke([r,i,n,_,m,x,g,E,G]),O.ENGINE=O.OS=ke([c,u]),typeof le!==d?(typeof Ae!==d&&Ae.exports&&(le=Ae.exports=O),le.UAParser=O):typeof define===f&&define.amd?define(function(){return O}):typeof e!==d&&(e.UAParser=O);var Y=typeof e!==d&&(e.jQuery||e.Zepto);if(Y&&!Y.ua){var _e=new O;Y.ua=_e.getResult(),Y.ua.get=function(){return _e.getUA()},Y.ua.set=function(y){_e.setUA(y);var v=_e.getResult();for(var h in v)Y.ua[h]=v[h]}}})(typeof window=="object"?window:le)});function Q(){try{if(typeof window<"u"&&window.crypto&&window.crypto.getRandomValues){let e=new Uint8Array(16);window.crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=Array.from(e).map(o=>o.toString(16).padStart(2,"0"));return[t.slice(0,4).join(""),t.slice(4,6).join(""),t.slice(6,8).join(""),t.slice(8,10).join(""),t.slice(10,16).join("")].join("-")}}catch(e){console.warn("[ElevateAB] Crypto UUID generation failed, falling back to Math.random()",e)}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}function N(e,t){if(typeof document>"u")return;let o=new Date;o.setTime(o.getTime()+365*24*60*60*1e3);let s="; expires="+o.toUTCString();document.cookie=e+"="+(t||"")+s+"; path=/"}function I(e){if(typeof document>"u")return null;let t=e+"=",o=document.cookie.split(";");for(let s=0;s<o.length;s++){let a=o[s];for(;a.charAt(0)===" ";)a=a.substring(1,a.length);if(a.indexOf(t)===0)return a.substring(t.length,a.length)}return null}function V(e){let t=I(e);if(t)try{return JSON.parse(t)}catch(o){return console.error("[ElevateAB] Error parsing JSON from cookie",o),null}return null}function K(e,t){typeof sessionStorage>"u"||sessionStorage.setItem(e,JSON.stringify(t))}function W(e){return typeof sessionStorage>"u"?null:sessionStorage.getItem(e)}function et(e){let t=W(e);return t?JSON.parse(t):null}function jt(){let e=I("eabUserId");return e||(e=Q(),N("eabUserId",e)),e}function X(){return jt()}function $t(){let e=W("eabSessionId");return e||(e=Q(),K("eabSessionId",e)),e}function Re(){return $t()}function Oe(){return{referrer:W("eabReferrer")||"",entryPage:W("eabEntry")||""}}var L=ce(()=>{"use strict"});function fe(){return V("ABTL")||{}}function Gt(e){N("ABTL",JSON.stringify(e))}function tt(e){return fe()[e]||null}function Wt(e,t){if(e[t]?.isControl)return-1;let s=0;for(let a=0;a<t;a++)e[a]?.isControl||s++;return s}function _r(e,t){let o=e.every(r=>typeof r.weight=="number"),s=[],a=0;if(o)for(let r of e)a+=r.weight,s.push(a);else{let r=100/e.length;for(let c=0;c<e.length;c++)a+=r,s.push(a)}let d=Ye(t)%1e4/100,p=0;for(let r=0;r<s.length;r++)if(d<s[r]){p=r;break}let l=e[p]||e[0],w=Wt(e,p);return{...l,isA:w===0,isB:w===1,isC:w===2,isD:w===3}}function rt(e,t,o){let s=tt(e);if(s){let l=t.variations.findIndex(w=>w.id===s);if(l!==-1){let w=t.variations[l],r=Wt(t.variations,l);return{...w,isA:r===0,isB:r===1,isC:r===2,isD:r===3}}}let a=t.variations.filter(l=>!l.isDone);if(a.length===0)return null;let f=t.isPersonalization,d;f?d=a.find(w=>!w.isControl)||a[0]:d=_r(a,o);let p=fe();return p[e]=d.id,Gt(p),d}function ot(e){let t=e.testTrafficPercentage;return typeof t!="number"||tt(e.testId)?!0:Math.random()*100<t}var Ve=ce(()=>{"use strict";L();Te()});var Le,nt=ce(()=>{"use strict";Le=`#graphql
|
|
3
|
+
mutation cartAttributesUpdate($cartId: ID!, $attributes: [AttributeInput!]!) {
|
|
4
|
+
cartAttributesUpdate(cartId: $cartId, attributes: $attributes) {
|
|
5
|
+
cart {
|
|
6
|
+
id
|
|
7
|
+
attributes {
|
|
8
|
+
key
|
|
9
|
+
value
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
userErrors {
|
|
13
|
+
field
|
|
14
|
+
message
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
`});var Yt={};Ft(Yt,{cleanupCartAttributes:()=>Ht,getCartAttributesPayload:()=>it,updateCartAttributes:()=>at});function it(){let e=fe(),t=V("ABAU")||{},o=I("eabUserId"),s=I("eabUserPreview")==="true",a=I("abtid"),f={};for(let p in e)t[p]&&(f[p]=e[p]);let d=[{key:"_eabTestsList",value:JSON.stringify(f)},{key:"_eabUserId",value:o||""},{key:"_eabList",value:JSON.stringify(e)}];return s&&a&&d.push({key:"_eabPreviewTest",value:a}),d}async function at(e,t={}){if(typeof window>"u")return{success:!1,error:"Not in browser environment"};if(!t.storefrontAccessToken&&!t.storefrontApiUrl)return console.warn("[ElevateAB] Missing storefrontAccessToken. For Next.js/non-Hydrogen stores, you must provide a Storefront Access Token. This token is SAFE to use client-side - it's a public token with limited permissions. Get it from: Shopify Admin \u2192 Settings \u2192 Apps \u2192 Develop apps"),{success:!1,error:"Missing storefrontAccessToken. Required for direct Storefront API calls."};try{let o=it(),s=e.startsWith("gid://")?e:`gid://shopify/Cart/${e}`,a=t.storefrontApiUrl||`https://${Jt()}/api/2025-01/graphql.json`,f=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json","X-Shopify-Storefront-Access-Token":t.storefrontAccessToken},body:JSON.stringify({query:Le,variables:{cartId:s,attributes:o}})});if(!f.ok)throw new Error(`HTTP error! status: ${f.status}`);let d=await f.json();if(d.errors||d.data?.cartAttributesUpdate?.userErrors?.length>0){let p=d.errors?.[0]?.message||d.data?.cartAttributesUpdate?.userErrors?.[0]?.message||"Unknown error";return console.error("[ElevateAB] Cart attributes update failed:",p),{success:!1,error:p}}return{success:!0}}catch(o){return console.error("[ElevateAB] Error updating cart attributes:",o),{success:!1,error:o instanceof Error?o.message:"Unknown error"}}}async function Ht(e,t={}){if(typeof window>"u")return{success:!1,error:"Not in browser environment"};if(!t.storefrontAccessToken&&!t.storefrontApiUrl)return{success:!1,error:"Missing storefrontAccessToken. Required for direct Storefront API calls."};try{let o=e.startsWith("gid://")?e:`gid://shopify/Cart/${e}`,s=[{key:"_eabTestsList",value:""},{key:"_eabUserId",value:""},{key:"_eabList",value:""},{key:"_eabPreviewTest",value:""}],a=t.storefrontApiUrl||`https://${Jt()}/api/2025-01/graphql.json`,f=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json","X-Shopify-Storefront-Access-Token":t.storefrontAccessToken},body:JSON.stringify({query:Le,variables:{cartId:o,attributes:s}})});if(!f.ok)throw new Error(`HTTP error! status: ${f.status}`);let d=await f.json();if(d.errors||d.data?.cartAttributesUpdate?.userErrors?.length>0){let p=d.errors?.[0]?.message||d.data?.cartAttributesUpdate?.userErrors?.[0]?.message||"Unknown error";return console.error("[ElevateAB] Cart attributes cleanup failed:",p),{success:!1,error:p}}return{success:!0}}catch(o){return console.error("[ElevateAB] Error cleaning up cart attributes:",o),{success:!1,error:o instanceof Error?o.message:"Unknown error"}}}function Jt(){return typeof window>"u"?"":window.location.hostname}var Be=ce(()=>{"use strict";Ve();L();nt()});var Lr={};Ft(Lr,{ElevateNextProvider:()=>er,ProductViewTracker:()=>rr,clearPreviewMode:()=>mt,extractShopifyId:()=>R,extractShopifyType:()=>Ke,getCountryCode:()=>$,getFlickerPreventionScript:()=>vt,getPreviewState:()=>ee,isInPreviewMode:()=>gt,isShopifyGid:()=>Xe,matchesGeoTargeting:()=>bt,trackAddToCart:()=>st,trackCartView:()=>ut,trackCheckoutCompleted:()=>ft,trackCheckoutStarted:()=>lt,trackPageView:()=>pe,trackProductView:()=>me,trackRemoveFromCart:()=>ct,trackSearchSubmitted:()=>dt,useElevateConfig:()=>de,useExperiment:()=>xt});module.exports=br(Lr);var M=ue(require("react"),1);var U=ue(require("react"),1);var Je=ue(require("react"),1),Pe=Je.default.createContext(null);function de(){let e=Je.default.useContext(Pe);if(e===null)throw new Error("useElevateConfig must be used within ElevateProvider");return e}Te();function R(e){return e?e.includes("gid://")&&e.split("/").pop()||e:""}function Ke(e){return!e||!e.includes("gid://")?null:e.split("/")[3]||null}function Xe(e){return!!e&&e.startsWith("gid://shopify/")}var Ze=ue(zt(),1),qt={"facebook.com":"Facebook","fb.me":"Facebook","m.facebook.com":"Facebook","l.facebook.com":"Facebook","lm.facebook.com":"Facebook","instagram.com":"Instagram","l.instagram.com":"Instagram","youtube.com":"Youtube","youtu.be":"Youtube","m.youtube.com":"Youtube","bing.com":"Bing","www.bing.com":"Bing","msnbc.msn.com":"Bing","dizionario.it.msn.com":"Bing","cc.bingj.com":"Bing","m.bing.com":"Bing","twitter.com":"Twitter","t.co":"Twitter"};function C(e){return typeof e!="string"?String(e):e.replace(/[\\"'`\x00-\x1F\x7F]/g,"")}function A(e){if(e==null)return null;let t=typeof e=="string"?parseFloat(e):Number(e);return isNaN(t)?null:+(Math.round(+(t+"e2"))+"e-2")}function Ce(e){if(!e)return null;let t=/gid:\/\/shopify\/Cart\/([^?]+(\?.+)?)/,o=e.match(t);return o?o[1]:null}function Ee(e){try{return typeof e!="string"?null:decodeURIComponent(e).split("?")[0]}catch{return e||null}}function wr(e){if(!e)return"";switch(e){case"Mobile Safari":return"Safari";case"Chrome Mobile":case"Chrome Mobile iOS":return"Chrome";case"Firefox Mobile":case"Firefox Mobile iOS":return"Firefox";case"Opera Mobile":case"Opera Mini":case"Opera Mini iOS":return"Opera";case"Yandex Browser Lite":return"Yandex Browser";case"Chrome Webview":case"Mobile App":return"Mobile App";default:return e}}function hr(e){let t={};return e.searchParams.forEach((o,s)=>{t[s]||(t[s]=o)}),t}function yr(e){return!!e.host&&["http:","https:"].includes(e.protocol)}function vr(e){return e.replace(/^www\./,"")}function kr(e,t,o){if(t&&{Facebook:"Facebook",Instagram:"Instagram"}[t])return t;let a,f;try{if(e&&e.trim()!=="")a=new URL(e);else return"Direct";if(a?.hostname&&yr(a)){if(f=a.hostname,o&&o===f)return"Direct"}else return""}catch{}if(!f)return"";let d=vr(f);return d?qt[d]?qt[d]:d?.includes("google")?"Google":d:""}function Se(e){let{referrer:t,entryPage:o,userAgent:s}=e,a={referrer_source:"",browser_info:"",os_info:"",device_type:"",page_entry_path:"",utm_medium:"",utm_source:"",utm_campaign:"",utm_content:"",utm_term:"",referrer_url:t||"",gclid:"",fbclid:"",pins_campaign_id:"",epik:""};try{let f;if(o&&o.trim()!==""&&o.startsWith("http"))try{let d=new URL(o),p=d?.pathname;f=d?.hostname,p&&(a.page_entry_path=p??"");let l=hr(d);a.utm_medium=l.utm_medium??"",a.utm_source=l.utm_source??"",a.utm_campaign=l.utm_campaign??"",a.utm_content=l.utm_content??"",a.utm_term=l.utm_term??"",a.gclid=l.gclid??"",a.fbclid=l.fbclid??"",a.pins_campaign_id=l.pins_campaign_id??"",a.epik=l.epik??""}catch{}if(s){let d=(0,Ze.UAParser)(s),p=d?.browser?.name,l=wr(p);a.browser_info=l??"",a.os_info=d?.os?.name??"",s&&(a.device_type=(d?.device?.type||"desktop")?.toUpperCase()??"")}return a.referrer_source=kr(t,a?.browser_info,f)??"",a}catch{return a}}function Ie(e,t){let o=e==="/"||e==="",a=t&&/^\/[a-z]{2}(-[a-z]{2})?\/?$/i.test(e);return o||a?"index":/\/products\//.test(e)?"product":/\/collections\//.test(e)?"collection":/\/pages\//.test(e)?"page":/\/search/.test(e)?"search":/\/cart/.test(e)?"cart":/\/checkouts\//.test(e)?"checkout":"unknown"}function Ue(e){if(!e)return"";try{let t=(0,Ze.UAParser)(e),o=t?.os,s=t?.device,a="";return o?.name&&(a+=o.name,o.version&&(a+=` ${o.version}`)),s?.type&&(a+=a?` (${s.type})`:s.type),s?.vendor&&(a+=a?` ${s.vendor}`:s.vendor),s?.model&&(a+=a?` ${s.model}`:s.model),a||e}catch{return e}}L();var pt=require("react"),xr="https://bitter-river-9c62.support-67d.workers.dev",Pr="https://d339co84ntxcme.cloudfront.net/Prod/orders",S=null;function Z(e){S=e}function z(e){let t=e?.storeId||S?.storeId;return t||(console.warn("[ElevateAB] No storeId provided. Call initAnalytics() first or pass storeId to tracking function."),"")}function Tr(e){return Object.entries(e).filter(([,t])=>typeof t=="string").map(([t,o])=>({test_id:t,variant_id:o}))}function Ar(e,t){return Object.entries(e).filter(([o])=>typeof t[o]=="string").map(([o])=>({test_id:o,variant_id:t[o]}))}function Cr(){return typeof window>"u"?!1:I("eabUserPreview")==="true"||new URLSearchParams(window.location.search).get("eabUserPreview")==="true"}function q(e,t,o){if(typeof window>"u"||Cr())return null;let s=navigator.userAgent,a=window.location.pathname,f=Ie(a,o),{referrer:d,entryPage:p}=Oe(),l=Se({referrer:d,entryPage:p,userAgent:s}),w=V("ABTL")||{},r=V("ABAU")||{},c=Tr(w),n=Ar(r,w),i=Ce(localStorage.getItem("shopifyCartId")),u=new Date().toISOString(),T=sessionStorage.getItem("eabIsFirstVisit")==="true",_=I("localization")||"";return{pixel_event_id:`sh-${Q()}`,shop_name:e,timestamp:u,event_type:t,client_id:I("_shopify_y")||void 0,visitor_id:X(),session_id:Re(),cart_token:Ee(i||I("cart")),page_url:window.location.href,page_pathname:a,page_search:window.location.search,referrer_url:d,referrer_source:l?.referrer_source,previous_page:document.referrer,page_entry:p,page_entry_path:l?.page_entry_path,page_type:f,utm_medium:l?.utm_medium,utm_source:l?.utm_source,utm_campaign:l?.utm_campaign,utm_content:l?.utm_content,utm_term:l?.utm_term,gclid:l?.gclid,fbclid:l?.fbclid,pins_campaign_id:l?.pins_campaign_id,epik:l?.epik,browser_info:l?.browser_info,os_info:l?.os_info,device_type:l?.device_type,language:navigator.language,root_route:localStorage.getItem("eabRootRoute")||"",user_agent:s,user_agent_no_browser:Ue(s),is_first_visit:T,shopify_country:_,ab_test_assignments:c,ab_test_views:n,is_first_order:null}}async function j(e,t=xr){try{let o=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),keepalive:!0});if(!o.ok)throw new Error(`Worker error: ${o.status}`)}catch(o){console.error("[ElevateAB] Error sending analytics:",o)}}async function pe(e={}){let t=z(e);if(!t)return;let o=e.hasLocalizedPaths??S?.hasLocalizedPaths,s=e.workerUrl??S?.workerUrl,a=q(t,"page_viewed",o);if(!a)return;let f={...a,cart_currency:e.currency};await j(f,s)}async function me(e){let t=z(e);if(!t)return;let{productId:o,productVendor:s,productPrice:a,productSku:f,currency:d}=e,p=e.hasLocalizedPaths??S?.hasLocalizedPaths,l=e.workerUrl??S?.workerUrl,w=q(t,"product_viewed",p);if(!w)return;let r={...w,cart_currency:d,product_id:R(o),product_vendor:C(s),product_price:A(a),product_sku:C(f)};await j(r,l)}async function st(e){let t=z(e);if(!t)return;let{productId:o,variantId:s,productVendor:a,productPrice:f,productQuantity:d,productSku:p,currency:l,cartId:w}=e,r=e.hasLocalizedPaths??S?.hasLocalizedPaths,c=e.workerUrl??S?.workerUrl,n=e.storefrontAccessToken??S?.storefrontAccessToken,i=q(t,"product_added_to_cart",r);if(!i)return;let u={...i,cart_currency:l,product_id:R(o),variant_id:R(s),product_vendor:C(a),product_price:A(f),product_quantity:d,product_sku:C(p)};if(await j(u,c),w&&n)try{let{updateCartAttributes:T}=await Promise.resolve().then(()=>(Be(),Yt));await T(w,{storefrontAccessToken:n})}catch(T){console.error("[ElevateAB] Failed to update cart attributes:",T)}}async function ct(e){let t=z(e);if(!t)return;let{productId:o,variantId:s,productVendor:a,productPrice:f,productQuantity:d,productSku:p,currency:l}=e,w=e.hasLocalizedPaths??S?.hasLocalizedPaths,r=e.workerUrl??S?.workerUrl,c=q(t,"product_removed_from_cart",w);if(!c)return;let n={...c,cart_currency:l,product_id:R(o),variant_id:R(s),product_vendor:C(a),product_price:A(f),product_quantity:d,product_sku:C(p)};await j(n,r)}async function ut(e){let t=z(e);if(!t)return;let{cartTotalPrice:o,cartTotalQuantity:s,cartItems:a,currency:f}=e,d=e.hasLocalizedPaths??S?.hasLocalizedPaths,p=e.workerUrl??S?.workerUrl,l=q(t,"cart_viewed",d);if(!l)return;let w={...l,cart_currency:f,cart_total_price:A(o),cart_total_quantity:s,cart_items:a?.map(r=>({product_id:R(r.productId),variant_id:R(r.variantId),product_vendor:C(r.productVendor)||"",product_price:A(r.productPrice),product_quantity:r.productQuantity??null,product_sku:C(r.productSku)||""}))};await j(w,p)}async function dt(e){let t=z(e);if(!t)return;let{searchQuery:o,currency:s}=e,a=e.hasLocalizedPaths??S?.hasLocalizedPaths,f=e.workerUrl??S?.workerUrl,d=q(t,"search_submitted",a);if(!d)return;let p={...d,cart_currency:s,search_query:C(o)};await j(p,f)}async function lt(e){let t=z(e);if(!t)return;let{cartTotalPrice:o,cartSubtotalPrice:s,cartShippingPrice:a,cartTaxAmount:f,cartDiscountAmount:d,customerId:p,cartItems:l,currency:w}=e,r=e.hasLocalizedPaths??S?.hasLocalizedPaths,c=e.workerUrl??S?.workerUrl,n=q(t,"checkout_started",r);if(!n)return;let i=0,u=l?.map(_=>{let m=_.productQuantity??0;return i+=m,{product_id:R(_.productId),variant_id:R(_.variantId),product_vendor:C(_.productVendor)||"",vendor:C(_.productVendor)||"",product_price:A(_.productPrice),total_price:A(_.productPrice),product_quantity:m,quantity:m,product_sku:C(_.productSku)||"",sku:C(_.productSku)||"",total_discount:A(_.totalDiscount)}})||[],T={...n,cart_currency:w,cart_total_price:A(o),cart_subtotal_price:A(s),cart_total_quantity:i,cart_shipping_price:A(a),cart_tax_amount:A(f),cart_discount_amount:A(d),cart_items:u,customer_id:p};await j(T,c)}async function ft(e){let t=z(e);if(!t)return;let{orderId:o,cartTotalPrice:s,cartSubtotalPrice:a,cartShippingPrice:f,cartTaxAmount:d,cartDiscountAmount:p,customerId:l,isFirstOrder:w,noteAttributes:r,cartItems:c,currency:n}=e,i=e.hasLocalizedPaths??S?.hasLocalizedPaths,u=e.ordersWorkerUrl??S?.ordersWorkerUrl??Pr,T=q(t,"checkout_completed",i);if(!T)return;let _=0,m=c?.map(x=>{let E=x.productQuantity??0;return _+=E,{product_id:R(x.productId),variant_id:R(x.variantId),product_vendor:C(x.productVendor)||"",vendor:C(x.productVendor)||"",product_price:A(x.productPrice),total_price:A(x.productPrice),product_quantity:E,quantity:E,product_sku:C(x.productSku)||"",sku:C(x.productSku)||"",total_discount:A(x.totalDiscount)}})||[],g={...T,cart_currency:n,cart_total_price:A(s),cart_subtotal_price:A(a),cart_total_quantity:_,cart_shipping_price:A(f),cart_tax_amount:A(d),cart_discount_amount:A(p),cart_items:m,order_id:o,customer_id:l,is_first_order:w??null,note_attributes:r};await j(g,u)}L();function Er(e){let t={},o={};if(!e)return{assignments:t,views:o};let s=e.split("~");for(let a of s){let f=a.split("_");if(f.length>=2){let d=f[0],p=f[1],l=f[2]==="1";t[d]=p,o[d]=l}}return{assignments:t,views:o}}function ee(){if(typeof window>"u")return{isPreview:!1,previewTestId:null,forcedAssignments:{},previewedViews:{}};let e=new URLSearchParams(window.location.search),o=(e.get("eabUserPreview")||I("eabUserPreview"))==="true",s=e.get("abtid");s||(s=W("eabPreviewTestId"));let a=e.get("eab_tests")||"",{assignments:f,views:d}=Er(a);return e.has("eabUserPreview")&&N("eabUserPreview","true"),e.has("abtid")&&s&&K("eabPreviewTestId",s),{isPreview:o,previewTestId:s,forcedAssignments:f,previewedViews:d}}function mt(){if(!(typeof document>"u")&&(document.cookie="eabUserPreview=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;",typeof sessionStorage<"u"&&sessionStorage.removeItem("eabPreviewTestId"),typeof window<"u")){let e=new URL(window.location.href);e.searchParams.delete("eabUserPreview"),e.searchParams.delete("abtid"),e.searchParams.delete("eab_tests"),window.history.replaceState({},"",e.toString())}}function gt(){return ee().isPreview}L();var De={SHOPIFY_LOCALIZATION:"localization",EAB_COUNTRY:"eabCountryCode",EAB_GEO:"eabGeoLocation"};function $(){if(typeof window>"u")return null;let t=new URLSearchParams(window.location.search).get("country");if(t)return N(De.EAB_COUNTRY,t.toUpperCase()),t.toUpperCase();let o=I(De.SHOPIFY_LOCALIZATION);if(o)return o.toUpperCase();let s=I(De.EAB_COUNTRY);if(s)return s.toUpperCase();if(typeof localStorage<"u"){let a=localStorage.getItem(De.EAB_COUNTRY);if(a)return a.toUpperCase()}return null}function Qt(e,t){let o=t??$();return o?e.map(a=>a.toUpperCase()).includes(o.toUpperCase()):!1}function Kt(e,t){let o=t??$();return o?e.map(a=>a.toUpperCase()).includes(o.toUpperCase()):!1}function bt(e){let t=$();return!e.includeCountries?.length&&!e.excludeCountries?.length?!0:!t||e.excludeCountries?.length&&Kt(e.excludeCountries,t)?!1:e.includeCountries?.length?Qt(e.includeCountries,t):!0}var H="eab-prevent-flicker",wt="eab-flicker-styles";function Xt(e=3e3){if(typeof document>"u"||document.getElementById(wt))return;let t=document.createElement("style");t.id=wt,t.textContent=`
|
|
19
|
+
/* Elevate AB - Flicker Prevention */
|
|
20
|
+
.${H} {
|
|
21
|
+
opacity: 0 !important;
|
|
22
|
+
pointer-events: none !important;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Failsafe: ensure content shows after timeout via animation */
|
|
26
|
+
@keyframes eab-reveal {
|
|
27
|
+
to { opacity: 1; pointer-events: auto; }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.${H} {
|
|
31
|
+
animation: eab-reveal 0s ${e}ms forwards;
|
|
32
|
+
}
|
|
33
|
+
`;let o=document.head||document.getElementsByTagName("head")[0];o.insertBefore(t,o.firstChild)}function Zt(e="body"){if(typeof document>"u")return;let t=document.querySelector(e);t&&t.classList.add(H)}function ht(e="body"){if(typeof document>"u")return;let t=document.querySelector(e);t&&t.classList.remove(H)}function yt(e="body",t=3e3){if(typeof document>"u")return()=>{};Xt(t),Zt(e);let o=!1,s=setTimeout(()=>{o||(console.warn(`[ElevateAB] Flicker prevention timeout (${t}ms) reached. Revealing content. Check if test assignment is completing.`),ht(e),o=!0)},t);return()=>{o||(clearTimeout(s),ht(e),o=!0)}}function vt(e=3e3){return`
|
|
34
|
+
(function() {
|
|
35
|
+
var style = document.createElement('style');
|
|
36
|
+
style.id = '${wt}';
|
|
37
|
+
style.textContent = '.${H}{opacity:0!important;pointer-events:none!important}@keyframes eab-reveal{to{opacity:1;pointer-events:auto}}.${H}{animation:eab-reveal 0s ${e}ms forwards}';
|
|
38
|
+
document.head.insertBefore(style, document.head.firstChild);
|
|
39
|
+
document.body && document.body.classList.add('${H}');
|
|
40
|
+
})();
|
|
41
|
+
`.trim()}var Sr=!1,Ir={allTests:{"price-test-001":{8606:{variationName:"Control",trafficPercentage:50,isDone:!1,isControl:!0},8607:{variationName:"Sale Price",trafficPercentage:50,isDone:!1,prices:{"41883969519701":{main:"USD",price:{USD:"599.95"},compare:{USD:"699.95"}}}},data:{name:"Snowboard Price Test",isLive:!0,settings:{afterDiscounts:!0},type:"PRICE_PLUS",filters:[],isPersonalization:!1,currencies:["USD"],handles:["the-complete-snowboard"],productIds:["7240161067093"]}},"content-test-001":{"ctrl-001":{variationName:"Control",trafficPercentage:34,isDone:!1,isControl:!0,content:{headline:"Welcome to our store",subheadline:"Shop the best products"}},"var-a-001":{variationName:"Urgency Copy",trafficPercentage:33,isDone:!1,content:{headline:"Limited Time Offer!",subheadline:"Don't miss out - sale ends soon"}},"var-b-001":{variationName:"Value Copy",trafficPercentage:33,isDone:!1,content:{headline:"Premium Quality, Great Value",subheadline:"Free shipping on orders over $50"}},data:{name:"Homepage Headline Test",isLive:!0,settings:{afterDiscounts:!0},type:"CONTENT",filters:[],isPersonalization:!1,pathnames:["/"]}},"custom-code-test-001":{10150:{variationName:"Control",trafficPercentage:50,isDone:!1,customCode:{id:"c11a582c-6b27-4263-941c-8ed123437c6b",js:"console.log('[Elevate] Control variant active');",css:"",pathnames:["*"],excludePathnames:[]},isControl:!0},10151:{variationName:"Enhanced UI",trafficPercentage:50,isDone:!1,customCode:{id:"df71546a-0a5f-4ad0-8d0f-a1bdeab05e84",js:"console.log('[Elevate] Enhanced UI variant'); document.body.style.borderTop = '3px solid #10b981';",css:".hero-section { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }",pathnames:["*"],excludePathnames:[]}},data:{name:"Custom Code Enhancement",isLive:!0,settings:{afterDiscounts:!0},type:"CUSTOM_CODE",filters:[],isPersonalization:!1,pathnames:["*"],excludePathnames:[]}},"split-url-test-001":{"split-ctrl":{variationName:"Control",trafficPercentage:50,isDone:!1,isControl:!0,splitUrlTestLinks:{default:"/collections/all"}},"split-var-a":{variationName:"New Landing Page",trafficPercentage:50,isDone:!1,splitUrlTestLinks:{default:"/collections/featured"}},data:{name:"Landing Page Split Test",isLive:!0,settings:{afterDiscounts:!0},type:"SPLIT_URL",filters:[],isPersonalization:!1,pathnames:["/promo"]}}},selectors:{selectorsV2:[]}};function kt({storeId:e,storefrontAccessToken:t,preventFlickering:o=!1,flickerTimeout:s=3e3,children:a}){let[f,d]=U.default.useState(null),[p,l]=U.default.useState(null),[w,r]=U.default.useState(null),c=(0,U.useRef)(null);U.default.useEffect(()=>(o&&typeof window<"u"&&(c.current=yt("body",s)),()=>{c.current&&c.current()}),[o,s]),U.default.useEffect(()=>{typeof window>"u"||Z({storeId:e,storefrontAccessToken:t})},[e,t]),U.default.useEffect(()=>{if(typeof window>"u")return;let T=ee();l(T);let _=$();r(_)},[]);let n=(0,U.useCallback)(()=>{c.current&&(c.current(),c.current=null)},[]);U.default.useEffect(()=>{async function T(){try{if(!Sr){let G=Qe(Ir);d(G),n();return}let _=`https://configs.elevateab.com/config/${e}.json`,m=await fetch(_);if(m.status===404){d({tests:[],selectors:void 0}),n();return}if(!m.ok)throw new Error(`Failed to fetch config: ${m.status} ${m.statusText}`);let g=await m.json();if(g.subscriptionPaused){console.error(`[ElevateAB] Subscription is paused or stopped for store: ${e}. `+(g.subscriptionMessage||"A/B tests will not run. Please reactivate your subscription.")),d({tests:[],selectors:void 0}),n();return}if(!(Object.keys(g.allTests||{}).length>0)){d({tests:[],selectors:void 0}),n();return}let E=Qe(g);d(E),n()}catch(_){console.error("[ElevateAB] Failed to load config:",_),d({tests:[],selectors:void 0}),n()}}T()},[e,n]);let i=U.default.useMemo(()=>({config:f,storeId:e,storefrontAccessToken:t,isPreviewMode:p?.isPreview??!1,previewTestId:p?.previewTestId??null,countryCode:w}),[f,e,t,p,w]);U.default.useEffect(()=>{Z({storeId:e,storefrontAccessToken:t})},[e,t]);let u=(0,U.useRef)(!1);return U.default.useEffect(()=>{!t&&!u.current&&(u.current=!0,console.warn("[ElevateAB] No storefrontAccessToken provided. A/B tests will work, but orders won't be attributed to test variants. Add storefrontAccessToken prop to enable order tracking."))},[t]),U.default.createElement(Pe.Provider,{value:i},a)}var Ne=require("next/navigation");function Ur({currency:e}){let t=(0,Ne.usePathname)(),o=(0,Ne.useSearchParams)();return(0,M.useEffect)(()=>{o.get("eabUserPreview")!=="true"&&pe({currency:e})},[t,o,e]),null}function er({storeId:e,storefrontAccessToken:t,preventFlickering:o=!1,flickerTimeout:s=3e3,currency:a,children:f}){return(0,M.useEffect)(()=>{Z({storeId:e,storefrontAccessToken:t})},[e,t]),M.default.createElement(kt,{storeId:e,storefrontAccessToken:t,preventFlickering:o,flickerTimeout:s},M.default.createElement(M.Suspense,{fallback:null},M.default.createElement(Ur,{currency:a})),f)}var tr=require("react");function rr({productId:e,productVendor:t,productPrice:o,productSku:s,currency:a}){return(0,tr.useEffect)(()=>{e&&me({productId:e,productVendor:t,productPrice:o,productSku:s,currency:a})},[e,t,o,s,a]),null}Te();L();Ve();L();function or(e){let t=V("ABAU")||{};t[e]||(t[e]=!0,N("ABAU",JSON.stringify(t)))}function nr(e){let t=et("ABAV")||{};t[e]||(t[e]=!0,K("ABAV",t))}function _t(e){or(e),nr(e)}Be();nt();var te=ue(require("react"),1);L();Ve();function xt(e){let{config:t}=de(),[o,s]=te.default.useState(null),[a,f]=te.default.useState(!0),d=te.default.useMemo(()=>t&&t.tests.find(l=>l.testId===e)||null,[t,e]),p=te.default.useRef(null);return te.default.useEffect(()=>{if(t===null)return;if(!d){p.current!==e&&(p.current=e,console.warn(`[ElevateAB] Test not found: ${e}`)),f(!1);return}if(!d.enabled){p.current!==`${e}-disabled`&&(p.current=`${e}-disabled`,console.warn(`[ElevateAB] Test disabled: ${e}`)),f(!1);return}if(!ot(d)){f(!1);return}let l=X(),w=rt(e,d,l);w&&(s(w),_t(e)),f(!1)},[t,d,e]),{variant:o,isLoading:a,isControl:o?.isControl??!1,isA:o?.isA??!1,isB:o?.isB??!1,isC:o?.isC??!1,isD:o?.isD??!1}}var Pt=require("react");L();L();Be();0&&(module.exports={ElevateNextProvider,ProductViewTracker,clearPreviewMode,extractShopifyId,extractShopifyType,getCountryCode,getFlickerPreventionScript,getPreviewState,isInPreviewMode,isShopifyGid,matchesGeoTargeting,trackAddToCart,trackCartView,trackCheckoutCompleted,trackCheckoutStarted,trackPageView,trackProductView,trackRemoveFromCart,trackSearchSubmitted,useElevateConfig,useExperiment});
|
|
42
|
+
//# sourceMappingURL=next.cjs.map
|