@elevateab/sdk 1.4.7 → 1.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cartAttributes-MBKMHUMX.js +2 -0
- package/dist/cartAttributes-OBFX2SHM.js +3 -0
- package/dist/{chunk-5TU25234.js → chunk-EDXSTPN4.js} +3 -3
- package/dist/chunk-EDXSTPN4.js.map +1 -0
- package/dist/{chunk-GGAESORE.js → chunk-SCLOA5QZ.js} +3 -3
- package/dist/chunk-SCLOA5QZ.js.map +1 -0
- package/dist/{chunk-7OUZ2CQ5.js → chunk-Z4N3VDSA.js} +2 -2
- package/dist/hydrogen.cjs.map +1 -1
- package/dist/hydrogen.js +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/next.cjs +3 -3
- package/dist/next.cjs.map +1 -1
- package/dist/next.js +1 -1
- package/package.json +1 -1
- package/dist/cartAttributes-DBBVZUFZ.js +0 -2
- package/dist/cartAttributes-V5XBJEGE.js +0 -3
- package/dist/chunk-5TU25234.js.map +0 -1
- package/dist/chunk-GGAESORE.js.map +0 -1
- /package/dist/{cartAttributes-DBBVZUFZ.js.map → cartAttributes-MBKMHUMX.js.map} +0 -0
- /package/dist/{cartAttributes-V5XBJEGE.js.map → cartAttributes-OBFX2SHM.js.map} +0 -0
- /package/dist/{chunk-7OUZ2CQ5.js.map → chunk-Z4N3VDSA.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var B=Object.create;var
|
|
1
|
+
var B=Object.create;var I=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var _=Object.getPrototypeOf,J=Object.prototype.hasOwnProperty;var Y=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var N=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of j(t))!J.call(e,s)&&s!==r&&I(e,s,{get:()=>t[s],enumerable:!(n=O(t,s))||n.enumerable});return e};var Z=(e,t,r)=>(r=e!=null?B(_(e)):{},N(t||!e||!e.__esModule?I(r,"default",{value:e,enumerable:!0}):r,e));function C(){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(r=>r.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 h(e,t){if(typeof document>"u")return;let r=new Date;r.setTime(r.getTime()+365*24*60*60*1e3);let n="; expires="+r.toUTCString();document.cookie=e+"="+(t||"")+n+"; path=/"}function p(e){if(typeof document>"u")return null;let t=e+"=",r=document.cookie.split(";");for(let n=0;n<r.length;n++){let s=r[n];for(;s.charAt(0)===" ";)s=s.substring(1,s.length);if(s.indexOf(t)===0)return s.substring(t.length,s.length)}return null}function w(e){let t=p(e);if(t)try{return JSON.parse(t)}catch(r){return console.error("[ElevateAB] Error parsing JSON from cookie",r),null}return null}function te(e){typeof document>"u"||(document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;")}function b(e,t){typeof sessionStorage>"u"||(typeof t=="string"?sessionStorage.setItem(e,t):sessionStorage.setItem(e,JSON.stringify(t)))}function g(e){if(typeof sessionStorage>"u")return null;let t=sessionStorage.getItem(e);if(t&&t.length>=2&&t.startsWith('"')&&t.endsWith('"'))try{let r=JSON.parse(t);if(typeof r=="string")return sessionStorage.setItem(e,r),r}catch{}return t}function x(e){let t=g(e);return t?JSON.parse(t):null}function D(){let e=p("eabUserId");return e||(e=C(),h("eabUserId",e)),e}function P(){return D()}function M(){let e=g("eabSessionId");return e||(e=C(),b("eabSessionId",e)),e}function re(){return M()}function ne(e,t){if(typeof sessionStorage>"u")return;let r=g("eabReferrer"),n=g("eabEntry");r||b("eabReferrer",e),n||b("eabEntry",t)}function se(){return{referrer:g("eabReferrer")||"",entryPage:g("eabEntry")||""}}function k(e){let t=0;for(let r=0;r<e.length;r++){let n=e.charCodeAt(r);t=(t<<5)-t+n,t=t&t}return Math.abs(t)}function oe(e){let t=[];for(let[r,n]of Object.entries(e.allTests)){if(!n.data.isLive)continue;let s=[],i=0;for(let[o,a]of Object.entries(n)){if(o==="data")continue;let u=a;if(typeof u=="object"&&u!==null&&"variationName"in u){let f=!!u.isControl,c=u.content,d;c&&typeof c=="object"&&(d={changes:c.changes||[],elements:c.elements||[],blocks:c.blocks||[],customCodes:c.customCodes||[]});let l=u.customCode,v;l&&typeof l=="object"&&l.id&&(v={id:l.id,js:l.js,css:l.css,pathnames:l.pathnames||[],excludePathnames:l.excludePathnames}),s.push({id:o,name:u.variationName,weight:u.trafficPercentage,isControl:f,productId:u.id,handle:u.handle,price:u.price,prices:u.prices,splitUrlTestLinks:u.splitUrlTestLinks,content:d,customCode:v,isA:!f&&i===0,isB:!f&&i===1,isC:!f&&i===2,isD:!f&&i===3}),f||i++}}s.length>0&&t.push({testId:r,name:n.data.name,enabled:n.data.isLive,type:n.data.type,variations:s,data:n.data})}return{tests:t,selectors:e.selectors}}function q(e){let t={},r={};if(!e)return{assignments:t,views:r};let n=e.split("~");for(let s of n){let i=s.split("_");if(i.length>=2){let o=i[0],a=i[1],u=i[2]==="1";t[o]=a,r[o]=u}}return{assignments:t,views:r}}function $(){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",n=e.get("abtid");n||(n=g("eabPreviewTestId"));let s=e.get("eab_tests")||"",{assignments:i,views:o}=q(s);return e.has("eabUserPreview")&&h("eabUserPreview","true"),e.has("abtid")&&n&&b("eabPreviewTestId",n),{isPreview:r,previewTestId:n,forcedAssignments:i,previewedViews:o}}function ue(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 y(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 W(e,t){return Object.entries(e).map(([r,n])=>{let s=r.slice(-5),i=t[r]?"1":"0";return`${s}_${n}_${i}`}).join("~")}function fe(e,t,r){if(typeof window>"u")return;let n=new URL(window.location.href),s=W(e,t);s&&n.searchParams.set("eab_tests",s),r&&n.searchParams.set("eabUserId",r),window.history.replaceState({},"",n.toString())}function de(){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 le(){return $().isPreview}function z(e){let t=w("ABAU")||{};t[e]||(t[e]=!0,h("ABAU",JSON.stringify(t)))}function H(e){let t=x("ABAV")||{};t[e]||(t[e]=!0,b("ABAV",t))}function S(e){z(e),H(e)}function me(e){return!!(x("ABAV")||{})[e]}function be(e){return!!(w("ABAU")||{})[e]}function m(){return w("ABTL")||{}}function U(e){h("ABTL",JSON.stringify(e))}function E(e){return m()[e]||null}function R(e,t){if(e[t]?.isControl)return-1;let n=0;for(let s=0;s<t;s++)e[s]?.isControl||n++;return n}function F(e,t){let r=e.every(c=>typeof c.weight=="number"),n=[],s=0;if(r)for(let c of e)s+=c.weight,n.push(s);else{let c=100/e.length;for(let d=0;d<e.length;d++)s+=c,n.push(s)}let o=k(t)%1e4/100,a=0;for(let c=0;c<n.length;c++)if(o<n[c]){a=c;break}let u=e[a]||e[0],f=R(e,a);return{...u,isA:f===0,isB:f===1,isC:f===2,isD:f===3}}function V(e,t){let r=t.findIndex(s=>s.id===e.id),n=R(t,r);return{...e,isA:n===0,isB:n===1,isC:n===2,isD:n===3}}function G(e,t,r,n){if(n?.isPreview){let f=y(e,n);if(f){let c=t.variations.find(d=>d.id===f);if(c){let d=m();return d[e]=c.id,U(d),V(c,t.variations)}}}let s=E(e);if(s){let f=t.variations.find(c=>c.id===s);if(f)return V(f,t.variations)}let i=t.variations.filter(f=>!f.isDone);if(i.length===0)return null;let o=t.isPersonalization,a;o?a=i.find(c=>!c.isControl)||i[0]:a=F(i,r);let u=m();return u[e]=a.id,U(u),S(e),a}function T(e){return typeof e.testTrafficPercentage=="number"}function X(e,t){try{let r=m(),n=Object.keys(r);if(r[e]||n.length===0)return!0;if(n.some(o=>{let a=t.find(u=>u.testId===o);return a&&T(a)}))return!1;let i=t.find(o=>o.testId===e);return i?!T(i):!0}catch(r){return console.error("[ElevateAB] Error in canAssignToTest:",r),!0}}function ve(e,t){let r=e.testTrafficPercentage;return typeof r!="number"||E(e.testId)?!0:t&&!X(e.testId,t)?!1:Math.random()*100<r}function Ie(e,t){let r=P(),n=e.tests,s=m();for(let i of n){if(!i.enabled)continue;if(s[i.testId])if(t?.isPreview){let a=y(i.testId,t);if(!a||a===s[i.testId])continue}else continue;if(!Q(i.testId,n,s))continue;let o=i.testTrafficPercentage;!t?.isPreview&&typeof o=="number"&&Math.random()*100>=o||(G(i.testId,i,r,t??void 0),s=m())}}function Q(e,t,r){let n=Object.keys(r);if(n.length===0)return!0;if(n.some(o=>{let a=t.find(u=>u.testId===o);return a&&T(a)}))return!1;let i=t.find(o=>o.testId===e);return i?!T(i):!0}var A=`#graphql
|
|
2
2
|
mutation cartAttributesUpdate($cartId: ID!, $attributes: [AttributeInput!]!) {
|
|
3
3
|
cartAttributesUpdate(cartId: $cartId, attributes: $attributes) {
|
|
4
4
|
cart {
|
|
@@ -14,5 +14,5 @@ var B=Object.create;var v=Object.defineProperty;var L=Object.getOwnPropertyDescr
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
`;function K(){let e=
|
|
18
|
-
//# sourceMappingURL=chunk-
|
|
17
|
+
`;function K(){let e=m(),t=w("ABAU")||{},r=p("eabUserId"),n=p("eabUserPreview")==="true",s=p("abtid"),i={};for(let a in e)t[a]&&(i[a]=e[a]);let o=[{key:"_eabTestsList",value:JSON.stringify(i)},{key:"_eabUserId",value:r||""},{key:"_eabList",value:JSON.stringify(e)}];return n&&s&&o.push({key:"_eabPreviewTest",value:s}),o}async function Ve(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 r=K(),n=e.startsWith("gid://")?e:`gid://shopify/Cart/${e}`,s=t.storefrontApiUrl||`https://${L()}/api/2025-01/graphql.json`,i=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json","X-Shopify-Storefront-Access-Token":t.storefrontAccessToken},body:JSON.stringify({query:A,variables:{cartId:n,attributes:r}})});if(!i.ok)throw new Error(`HTTP error! status: ${i.status}`);let o=await i.json();if(o.errors||o.data?.cartAttributesUpdate?.userErrors?.length>0){let a=o.errors?.[0]?.message||o.data?.cartAttributesUpdate?.userErrors?.[0]?.message||"Unknown error";return console.error("[ElevateAB] Cart attributes update failed:",a),{success:!1,error:a}}return{success:!0}}catch(r){return console.error("[ElevateAB] Error updating cart attributes:",r),{success:!1,error:r instanceof Error?r.message:"Unknown error"}}}async function Ee(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 r=e.startsWith("gid://")?e:`gid://shopify/Cart/${e}`,n=[{key:"_eabTestsList",value:""},{key:"_eabUserId",value:""},{key:"_eabList",value:""},{key:"_eabPreviewTest",value:""}],s=t.storefrontApiUrl||`https://${L()}/api/2025-01/graphql.json`,i=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json","X-Shopify-Storefront-Access-Token":t.storefrontAccessToken},body:JSON.stringify({query:A,variables:{cartId:r,attributes:n}})});if(!i.ok)throw new Error(`HTTP error! status: ${i.status}`);let o=await i.json();if(o.errors||o.data?.cartAttributesUpdate?.userErrors?.length>0){let a=o.errors?.[0]?.message||o.data?.cartAttributesUpdate?.userErrors?.[0]?.message||"Unknown error";return console.error("[ElevateAB] Cart attributes cleanup failed:",a),{success:!1,error:a}}return{success:!0}}catch(r){return console.error("[ElevateAB] Error cleaning up cart attributes:",r),{success:!1,error:r instanceof Error?r.message:"Unknown error"}}}function L(){return typeof window>"u"?"":window.location.hostname}export{Y as a,Z as b,C as c,h as d,p as e,w as f,te as g,b as h,g as i,x as j,D as k,P as l,M as m,re as n,ne as o,se as p,k as q,oe as r,$ as s,ue as t,y as u,W as v,fe as w,de as x,le as y,z,H as A,S as B,me as C,be as D,m as E,U as F,E as G,G as H,X as I,ve as J,Ie as K,A as L,K as M,Ve as N,Ee as O};
|
|
18
|
+
//# sourceMappingURL=chunk-EDXSTPN4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/storage.ts","../src/utils.ts","../src/utils/preview.ts","../src/utils/tracking.ts","../src/utils/assignment.ts","../src/mutations/cartAttributes.mutation.ts","../src/utils/cartAttributes.ts"],"sourcesContent":["export function uuidv4(): string {\n try {\n if (\n typeof window !== \"undefined\" &&\n window.crypto &&\n window.crypto.getRandomValues\n ) {\n const rnds = new Uint8Array(16);\n window.crypto.getRandomValues(rnds);\n rnds[6] = (rnds[6] & 0x0f) | 0x40; // Version 4\n rnds[8] = (rnds[8] & 0x3f) | 0x80; // Variant 1\n\n const hexValues = Array.from(rnds).map((b) =>\n b.toString(16).padStart(2, \"0\")\n );\n\n return [\n hexValues.slice(0, 4).join(\"\"),\n hexValues.slice(4, 6).join(\"\"),\n hexValues.slice(6, 8).join(\"\"),\n hexValues.slice(8, 10).join(\"\"),\n hexValues.slice(10, 16).join(\"\"),\n ].join(\"-\");\n }\n } catch (e) {\n console.warn(\n \"[ElevateAB] Crypto UUID generation failed, falling back to Math.random()\",\n e\n );\n }\n\n // Fallback to Math.random\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function setCookie(name: string, value: string): void {\n if (typeof document === \"undefined\") return;\n\n const date = new Date();\n date.setTime(date.getTime() + 365 * 24 * 60 * 60 * 1000);\n const expires = \"; expires=\" + date.toUTCString();\n document.cookie = name + \"=\" + (value || \"\") + expires + \"; path=/\";\n}\n\nexport function getCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n\n const nameEQ = name + \"=\";\n const ca = document.cookie.split(\";\");\n for (let i = 0; i < ca.length; i++) {\n let c = ca[i];\n while (c.charAt(0) === \" \") c = c.substring(1, c.length);\n if (c.indexOf(nameEQ) === 0) {\n return c.substring(nameEQ.length, c.length);\n }\n }\n return null;\n}\n\nexport function getJsonCookie<T = Record<string, unknown>>(\n name: string\n): T | null {\n const cookieValue = getCookie(name);\n if (cookieValue) {\n try {\n return JSON.parse(cookieValue) as T;\n } catch (error) {\n console.error(\"[ElevateAB] Error parsing JSON from cookie\", error);\n return null;\n }\n }\n return null;\n}\n\nexport function deleteCookie(cookieName: string): void {\n if (typeof document === \"undefined\") return;\n\n document.cookie =\n cookieName + \"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;\";\n}\n\nexport function setSessionItem(name: string, value: unknown): void {\n if (typeof sessionStorage === \"undefined\") return;\n\n // Store strings directly to avoid wrapping quotes in sessionStorage.\n if (typeof value === \"string\") {\n sessionStorage.setItem(name, value);\n } else {\n sessionStorage.setItem(name, JSON.stringify(value));\n }\n}\n\nexport function getSessionItem(name: string): string | null {\n if (typeof sessionStorage === \"undefined\") return null;\n\n const value = sessionStorage.getItem(name);\n\n // Backward compatibility: old values may be double-serialized strings.\n if (value && value.length >= 2 && value.startsWith('\"') && value.endsWith('\"')) {\n try {\n const parsed = JSON.parse(value);\n if (typeof parsed === \"string\") {\n sessionStorage.setItem(name, parsed);\n return parsed;\n }\n } catch {\n // Not JSON-wrapped; return original value below.\n }\n }\n\n return value;\n}\n\nexport function getJsonSessionItem<T = unknown>(name: string): T | null {\n const item = getSessionItem(name);\n return item ? (JSON.parse(item) as T) : null;\n}\n\nexport function initializeVisitorId(): string {\n let visitorId = getCookie(\"eabUserId\");\n\n if (!visitorId) {\n visitorId = uuidv4();\n setCookie(\"eabUserId\", visitorId);\n }\n\n return visitorId;\n}\n\nexport function getVisitorId(): string {\n return initializeVisitorId();\n}\n\nexport function initializeSessionId(): string {\n let sessionId = getSessionItem(\"eabSessionId\");\n\n if (!sessionId) {\n sessionId = uuidv4();\n setSessionItem(\"eabSessionId\", sessionId);\n }\n\n return sessionId;\n}\n\nexport function getSessionId(): string {\n return initializeSessionId();\n}\n\nexport function setReferrerData(referrer: string, entryPage: string): void {\n if (typeof sessionStorage === \"undefined\") return;\n\n // Only set if not already set (preserve first referrer/entry)\n const existingReferrer = getSessionItem(\"eabReferrer\");\n const existingEntry = getSessionItem(\"eabEntry\");\n\n if (!existingReferrer) {\n setSessionItem(\"eabReferrer\", referrer);\n }\n if (!existingEntry) {\n setSessionItem(\"eabEntry\", entryPage);\n }\n}\n\nexport function getReferrerData(): { referrer: string; entryPage: string } {\n return {\n referrer: getSessionItem(\"eabReferrer\") || \"\",\n entryPage: getSessionItem(\"eabEntry\") || \"\",\n };\n}\n","import type {\n Variation,\n Test,\n BackendConfig,\n ElevateConfig,\n ContentTestData,\n ContentCustomCode,\n} from \"./types\";\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 parseBackendConfig(backendData: BackendConfig): ElevateConfig {\n const tests: Test[] = [];\n\n for (const [testId, testData] of Object.entries(backendData.allTests)) {\n if (!testData.data.isLive) continue;\n\n const variations: Variation[] = [];\n let nonControlIndex = 0;\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 const isControl = !!variation.isControl;\n\n const rawContent = (variation as any).content;\n let content: ContentTestData | undefined;\n if (rawContent && typeof rawContent === \"object\") {\n content = {\n changes: rawContent.changes || [],\n elements: rawContent.elements || [],\n blocks: rawContent.blocks || [],\n customCodes: rawContent.customCodes || [],\n };\n }\n\n const rawCustomCode = (variation as any).customCode;\n let customCode: ContentCustomCode | undefined;\n if (rawCustomCode && typeof rawCustomCode === \"object\" && rawCustomCode.id) {\n customCode = {\n id: rawCustomCode.id,\n js: rawCustomCode.js,\n css: rawCustomCode.css,\n pathnames: rawCustomCode.pathnames || [],\n excludePathnames: rawCustomCode.excludePathnames,\n };\n }\n\n variations.push({\n id: key,\n name: variation.variationName,\n weight: variation.trafficPercentage,\n isControl,\n productId: variation.id,\n handle: variation.handle,\n price: variation.price,\n prices: (variation as any).prices,\n splitUrlTestLinks: (variation as any).splitUrlTestLinks,\n content,\n customCode,\n isA: !isControl && nonControlIndex === 0,\n isB: !isControl && nonControlIndex === 1,\n isC: !isControl && nonControlIndex === 2,\n isD: !isControl && nonControlIndex === 3,\n });\n if (!isControl) nonControlIndex++;\n }\n }\n\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 data: testData.data,\n });\n }\n }\n\n return {\n tests,\n selectors: backendData.selectors,\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","import {\n setCookie,\n setSessionItem,\n getJsonCookie,\n getJsonSessionItem,\n} from \"./storage\";\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\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\nexport function trackViews(testId: string): void {\n trackUniqueView(testId);\n trackSessionView(testId);\n}\n\nexport function hasSessionView(testId: string): boolean {\n const addedViews = getJsonSessionItem<Record<string, boolean>>(\"ABAV\") || {};\n return !!addedViews[testId];\n}\n\nexport function hasUniqueView(testId: string): boolean {\n const addedUniqueViews = getJsonCookie<Record<string, boolean>>(\"ABAU\") || {};\n return !!addedUniqueViews[testId];\n}\n","import type { Test, Variation, ElevateConfig } from \"../types\";\nimport type { PreviewState } from \"./preview\";\nimport { getCookie, setCookie, getJsonCookie, getVisitorId } from \"./storage\";\nimport { hashString } from \"../utils\";\nimport { getPreviewVariation } from \"./preview\";\nimport { trackViews } from \"./tracking\";\n\nexport interface TestList {\n [testId: string]: string; // testId -> variantId\n}\n\nexport function getTestList(): TestList {\n return getJsonCookie<TestList>(\"ABTL\") || {};\n}\n\nexport function saveTestList(testList: TestList): void {\n setCookie(\"ABTL\", JSON.stringify(testList));\n}\n\nexport function getAssignedVariant(testId: string): string | null {\n const testList = getTestList();\n return testList[testId] || null;\n}\n\nfunction getNonControlIndex(\n variations: Variation[],\n targetIndex: number\n): number {\n const variation = variations[targetIndex];\n if (variation?.isControl) return -1;\n\n let nonControlIndex = 0;\n for (let i = 0; i < targetIndex; i++) {\n if (!variations[i]?.isControl) {\n nonControlIndex++;\n }\n }\n return nonControlIndex;\n}\n\nexport function assignVariantForUser(\n variations: Variation[],\n userId: string\n): Variation {\n const allHaveTrafficPercentage = variations.every(\n (v) => typeof v.weight === \"number\"\n );\n\n let cumulativeWeights: number[] = [];\n let totalWeight = 0;\n\n if (allHaveTrafficPercentage) {\n for (const variation of variations) {\n totalWeight += variation.weight;\n cumulativeWeights.push(totalWeight);\n }\n } else {\n const defaultWeight = 100 / variations.length;\n for (let i = 0; i < variations.length; i++) {\n totalWeight += defaultWeight;\n cumulativeWeights.push(totalWeight);\n }\n }\n\n const hash = hashString(userId);\n const randomWeight = (hash % 10000) / 100;\n\n let assignedIndex = 0;\n for (let i = 0; i < cumulativeWeights.length; i++) {\n if (randomWeight < cumulativeWeights[i]) {\n assignedIndex = i;\n break;\n }\n }\n\n const assignedVariation = variations[assignedIndex] || variations[0];\n const nonControlIndex = getNonControlIndex(variations, assignedIndex);\n\n return {\n ...assignedVariation,\n isA: nonControlIndex === 0,\n isB: nonControlIndex === 1,\n isC: nonControlIndex === 2,\n isD: nonControlIndex === 3,\n };\n}\n\nfunction enrichVariant(variant: Variation, variations: Variation[]): Variation {\n const variantIndex = variations.findIndex((v) => v.id === variant.id);\n const nonControlIndex = getNonControlIndex(variations, variantIndex);\n return {\n ...variant,\n isA: nonControlIndex === 0,\n isB: nonControlIndex === 1,\n isC: nonControlIndex === 2,\n isD: nonControlIndex === 3,\n };\n}\n\nexport function assignAndPersistVariant(\n testId: string,\n test: Test,\n userId: string,\n previewState?: PreviewState\n): Variation | null {\n if (previewState?.isPreview) {\n const forcedVariationId = getPreviewVariation(testId, previewState);\n if (forcedVariationId) {\n const forcedVariant = test.variations.find(\n (v) => v.id === forcedVariationId\n );\n if (forcedVariant) {\n const testList = getTestList();\n testList[testId] = forcedVariant.id;\n saveTestList(testList);\n return enrichVariant(forcedVariant, test.variations);\n }\n }\n }\n\n const existingVariantId = getAssignedVariant(testId);\n if (existingVariantId) {\n const existingVariant = test.variations.find(\n (v) => v.id === existingVariantId\n );\n if (existingVariant) {\n return enrichVariant(existingVariant, test.variations);\n }\n }\n\n const activeVariations = test.variations.filter((v) => {\n const isDone = (v as any).isDone;\n return !isDone;\n });\n\n if (activeVariations.length === 0) {\n return null;\n }\n\n const isPersonalization = (test as any).isPersonalization;\n let assignedVariant: Variation;\n\n if (isPersonalization) {\n const personalizedVariation = activeVariations.find((v) => !v.isControl);\n assignedVariant = personalizedVariation || activeVariations[0];\n } else {\n assignedVariant = assignVariantForUser(activeVariations, userId);\n }\n\n const testList = getTestList();\n testList[testId] = assignedVariant.id;\n saveTestList(testList);\n trackViews(testId);\n\n return assignedVariant;\n}\n\nfunction isIsolatedTest(test: Test): boolean {\n const trafficPercentage = (test as any).testTrafficPercentage;\n return typeof trafficPercentage === \"number\";\n}\n\nexport function canAssignToTest(testId: string, allTests: Test[]): boolean {\n try {\n const currentAssignments = getTestList();\n const currentTestIds = Object.keys(currentAssignments);\n\n if (currentAssignments[testId]) {\n return true;\n }\n\n if (currentTestIds.length === 0) {\n return true;\n }\n\n const isInIsolatedTest = currentTestIds.some((id) => {\n const test = allTests.find((t) => t.testId === id);\n return test && isIsolatedTest(test);\n });\n\n if (isInIsolatedTest) {\n return false;\n }\n\n const targetTest = allTests.find((t) => t.testId === testId);\n if (!targetTest) {\n return true;\n }\n\n if (isIsolatedTest(targetTest)) {\n return false;\n }\n\n return true;\n } catch (error) {\n console.error(\"[ElevateAB] Error in canAssignToTest:\", error);\n return true;\n }\n}\n\nexport function shouldShowTest(test: Test, allTests?: Test[]): boolean {\n const testTrafficPercentage = (test as any).testTrafficPercentage;\n\n if (typeof testTrafficPercentage !== \"number\") {\n return true;\n }\n\n const existingVariantId = getAssignedVariant(test.testId);\n if (existingVariantId) {\n return true;\n }\n\n if (allTests && !canAssignToTest(test.testId, allTests)) {\n return false;\n }\n\n const random = Math.random() * 100;\n return random < testTrafficPercentage;\n}\n\nexport function assignAllTests(\n config: ElevateConfig,\n previewState?: PreviewState | null\n): void {\n const userId = getVisitorId();\n const allTests = config.tests;\n let cachedTestList = getTestList();\n\n for (const test of allTests) {\n if (!test.enabled) continue;\n\n if (cachedTestList[test.testId]) {\n if (previewState?.isPreview) {\n const forcedId = getPreviewVariation(test.testId, previewState);\n if (!forcedId || forcedId === cachedTestList[test.testId]) {\n continue;\n }\n } else {\n continue;\n }\n }\n\n if (!canAssignToTestWithCache(test.testId, allTests, cachedTestList)) {\n continue;\n }\n\n const testTrafficPercentage = (test as any).testTrafficPercentage;\n if (!previewState?.isPreview && typeof testTrafficPercentage === \"number\") {\n const random = Math.random() * 100;\n if (random >= testTrafficPercentage) continue;\n }\n\n assignAndPersistVariant(\n test.testId,\n test,\n userId,\n previewState ?? undefined\n );\n\n cachedTestList = getTestList();\n }\n}\n\nfunction canAssignToTestWithCache(\n testId: string,\n allTests: Test[],\n cachedTestList: TestList\n): boolean {\n const currentTestIds = Object.keys(cachedTestList);\n\n // No current assignments - can join any test\n if (currentTestIds.length === 0) {\n return true;\n }\n\n // Check if user is in any isolated test\n const isInIsolatedTest = currentTestIds.some((id) => {\n const test = allTests.find((t) => t.testId === id);\n return test && isIsolatedTest(test);\n });\n\n if (isInIsolatedTest) {\n return false;\n }\n\n // Check if target test is isolated\n const targetTest = allTests.find((t) => t.testId === testId);\n if (!targetTest) {\n return true;\n }\n\n if (isIsolatedTest(targetTest)) {\n return false;\n }\n\n return true;\n}\n","/**\n * GraphQL mutations for cart attributes\n */\n\n/**\n * GraphQL mutation for updating cart attributes\n * Use this in your Storefront API calls\n */\nexport const CART_ATTRIBUTES_UPDATE_MUTATION = `#graphql\n mutation cartAttributesUpdate($cartId: ID!, $attributes: [AttributeInput!]!) {\n cartAttributesUpdate(cartId: $cartId, attributes: $attributes) {\n cart {\n id\n attributes {\n key\n value\n }\n }\n userErrors {\n field\n message\n }\n }\n }\n`;\n","/**\n * Cart attribute utilities for tagging carts with A/B test data\n *\n * These functions update Shopify cart attributes with test assignment data,\n * enabling order attribution for A/B test analysis.\n */\n\nimport { getTestList } from \"./assignment\";\nimport { getCookie, getJsonCookie } from \"./storage\";\nimport { CART_ATTRIBUTES_UPDATE_MUTATION } from \"../mutations/cartAttributes.mutation\";\nimport type { CartAttributesOptions, CartAttributeInput } from \"../types\";\n\n// Re-export types for backwards compatibility\nexport type { CartAttributesOptions, CartAttributeInput } from \"../types\";\n\n/**\n * Get cart attributes payload from current test assignments\n * Returns an array of key-value pairs ready to be sent to Shopify\n *\n * @example\n * ```ts\n * const attributes = getCartAttributesPayload();\n * // Use with your own Storefront client\n * await storefront.mutate(CART_ATTRIBUTES_UPDATE_MUTATION, {\n * variables: { cartId, attributes }\n * });\n * ```\n */\nexport function getCartAttributesPayload(): CartAttributeInput[] {\n const testList = getTestList(); // ABTL - all assignments\n const addedUniqueViews = getJsonCookie<Record<string, boolean>>(\"ABAU\") || {};\n const eabUserId = getCookie(\"eabUserId\");\n const isPreviewMode = getCookie(\"eabUserPreview\") === \"true\";\n const abtidValue = getCookie(\"abtid\");\n\n // Filter viewed tests - only include tests that have been viewed\n const viewedTests: Record<string, string> = {};\n for (const testId in testList) {\n if (addedUniqueViews[testId]) {\n viewedTests[testId] = testList[testId];\n }\n }\n\n const attributes: CartAttributeInput[] = [\n {\n key: \"_eabTestsList\",\n value: JSON.stringify(viewedTests),\n },\n {\n key: \"_eabUserId\",\n value: eabUserId || \"\",\n },\n {\n key: \"_eabList\",\n value: JSON.stringify(testList),\n },\n ];\n\n // Add preview test if in preview mode\n if (isPreviewMode && abtidValue) {\n attributes.push({\n key: \"_eabPreviewTest\",\n value: abtidValue,\n });\n }\n\n return attributes;\n}\n\n/**\n * Update cart attributes with test assignment data\n *\n * This function calls the Shopify Storefront API to update cart attributes.\n *\n * ## Authentication\n *\n * **For Hydrogen stores:** Use your storefront client directly with `getCartAttributesPayload()`\n *\n * **For Next.js/Other stores:** Pass the `storefrontAccessToken` option.\n *\n * ✅ The Storefront Access Token is **safe to use client-side**.\n * It's a public token designed by Shopify for browser use.\n * It can only read products and manage carts - it CANNOT delete products,\n * access admin functions, or do anything destructive.\n *\n * Get your token from: Shopify Admin → Settings → Apps → Develop apps\n *\n * @param cartId - The cart ID (GID or token, e.g., \"gid://shopify/Cart/abc123\" or just \"abc123\")\n * @param options - Configuration options including storefrontAccessToken\n * @returns Promise with success status and optional error message\n *\n * @example\n * ```ts\n * // Next.js usage - token is safe to use client-side!\n * const result = await updateCartAttributes(cartId, {\n * storefrontAccessToken: process.env.NEXT_PUBLIC_STOREFRONT_TOKEN\n * });\n *\n * if (!result.success) {\n * console.error('Failed to update cart attributes:', result.error);\n * }\n * ```\n */\nexport async function updateCartAttributes(\n cartId: string,\n options: CartAttributesOptions = {}\n): Promise<{ success: boolean; error?: string }> {\n if (typeof window === \"undefined\") {\n return { success: false, error: \"Not in browser environment\" };\n }\n\n // Validate token is provided for direct API calls\n if (!options.storefrontAccessToken && !options.storefrontApiUrl) {\n console.warn(\n \"[ElevateAB] Missing storefrontAccessToken. \" +\n \"For Next.js/non-Hydrogen stores, you must provide a Storefront Access Token. \" +\n \"This token 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 return {\n success: false,\n error:\n \"Missing storefrontAccessToken. Required for direct Storefront API calls.\",\n };\n }\n\n try {\n const attributes = getCartAttributesPayload();\n\n // Format cartId as GID if it's not already\n const cartGid = cartId.startsWith(\"gid://\")\n ? cartId\n : `gid://shopify/Cart/${cartId}`;\n\n const storefrontUrl =\n options.storefrontApiUrl ||\n `https://${getStoreDomain()}/api/2025-01/graphql.json`;\n\n const response = await fetch(storefrontUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Shopify-Storefront-Access-Token\": options.storefrontAccessToken!,\n },\n body: JSON.stringify({\n query: CART_ATTRIBUTES_UPDATE_MUTATION,\n variables: {\n cartId: cartGid,\n attributes,\n },\n }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const result = await response.json();\n\n if (\n result.errors ||\n result.data?.cartAttributesUpdate?.userErrors?.length > 0\n ) {\n const errorMsg =\n result.errors?.[0]?.message ||\n result.data?.cartAttributesUpdate?.userErrors?.[0]?.message ||\n \"Unknown error\";\n console.error(\"[ElevateAB] Cart attributes update failed:\", errorMsg);\n return { success: false, error: errorMsg };\n }\n\n return { success: true };\n } catch (error) {\n console.error(\"[ElevateAB] Error updating cart attributes:\", error);\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n}\n\n/**\n * Cleanup/remove cart attributes\n * Sets all Elevate attributes to empty strings\n *\n * @param cartId - The cart ID (GID or token)\n * @param options - Configuration options including storefrontAccessToken\n */\nexport async function cleanupCartAttributes(\n cartId: string,\n options: CartAttributesOptions = {}\n): Promise<{ success: boolean; error?: string }> {\n if (typeof window === \"undefined\") {\n return { success: false, error: \"Not in browser environment\" };\n }\n\n // Validate token is provided\n if (!options.storefrontAccessToken && !options.storefrontApiUrl) {\n return {\n success: false,\n error:\n \"Missing storefrontAccessToken. Required for direct Storefront API calls.\",\n };\n }\n\n try {\n const cartGid = cartId.startsWith(\"gid://\")\n ? cartId\n : `gid://shopify/Cart/${cartId}`;\n\n const attributes: CartAttributeInput[] = [\n { key: \"_eabTestsList\", value: \"\" },\n { key: \"_eabUserId\", value: \"\" },\n { key: \"_eabList\", value: \"\" },\n { key: \"_eabPreviewTest\", value: \"\" },\n ];\n\n const storefrontUrl =\n options.storefrontApiUrl ||\n `https://${getStoreDomain()}/api/2025-01/graphql.json`;\n\n const response = await fetch(storefrontUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Shopify-Storefront-Access-Token\": options.storefrontAccessToken!,\n },\n body: JSON.stringify({\n query: CART_ATTRIBUTES_UPDATE_MUTATION,\n variables: {\n cartId: cartGid,\n attributes,\n },\n }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const result = await response.json();\n\n if (\n result.errors ||\n result.data?.cartAttributesUpdate?.userErrors?.length > 0\n ) {\n const errorMsg =\n result.errors?.[0]?.message ||\n result.data?.cartAttributesUpdate?.userErrors?.[0]?.message ||\n \"Unknown error\";\n console.error(\"[ElevateAB] Cart attributes cleanup failed:\", errorMsg);\n return { success: false, error: errorMsg };\n }\n\n return { success: true };\n } catch (error) {\n console.error(\"[ElevateAB] Error cleaning up cart attributes:\", error);\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n}\n\n/**\n * Helper to get store domain from current URL\n * Assumes format: mystore.myshopify.com or custom domain\n */\nfunction getStoreDomain(): string {\n if (typeof window === \"undefined\") return \"\";\n return window.location.hostname;\n}\n"],"mappings":"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","names":["uuidv4","rnds","hexValues","b","c","r","setCookie","name","value","date","expires","getCookie","nameEQ","ca","i","getJsonCookie","cookieValue","error","deleteCookie","cookieName","setSessionItem","getSessionItem","parsed","getJsonSessionItem","item","initializeVisitorId","visitorId","getVisitorId","initializeSessionId","sessionId","getSessionId","setReferrerData","referrer","entryPage","existingReferrer","existingEntry","getReferrerData","hashString","str","hash","i","char","parseBackendConfig","backendData","tests","testId","testData","variations","nonControlIndex","key","value","variation","isControl","rawContent","content","rawCustomCode","customCode","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","trackUniqueView","testId","addedUniqueViews","getJsonCookie","setCookie","trackSessionView","addedViews","getJsonSessionItem","setSessionItem","trackViews","hasSessionView","hasUniqueView","getTestList","getJsonCookie","saveTestList","testList","setCookie","getAssignedVariant","testId","getNonControlIndex","variations","targetIndex","nonControlIndex","i","assignVariantForUser","userId","allHaveTrafficPercentage","v","cumulativeWeights","totalWeight","variation","defaultWeight","randomWeight","hashString","assignedIndex","assignedVariation","enrichVariant","variant","variantIndex","assignAndPersistVariant","test","previewState","forcedVariationId","getPreviewVariation","forcedVariant","existingVariantId","existingVariant","activeVariations","isPersonalization","assignedVariant","trackViews","isIsolatedTest","canAssignToTest","allTests","currentAssignments","currentTestIds","id","t","targetTest","error","shouldShowTest","testTrafficPercentage","assignAllTests","config","getVisitorId","cachedTestList","forcedId","canAssignToTestWithCache","CART_ATTRIBUTES_UPDATE_MUTATION","getCartAttributesPayload","testList","getTestList","addedUniqueViews","getJsonCookie","eabUserId","getCookie","isPreviewMode","abtidValue","viewedTests","testId","attributes","updateCartAttributes","cartId","options","cartGid","storefrontUrl","getStoreDomain","response","CART_ATTRIBUTES_UPDATE_MUTATION","result","errorMsg","error","cleanupCartAttributes"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
var
|
|
2
|
+
var L=Object.create;var A=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,_=Object.prototype.hasOwnProperty;var Q=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var J=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of O(t))!_.call(e,s)&&s!==r&&A(e,s,{get:()=>t[s],enumerable:!(n=B(t,s))||n.enumerable});return e};var K=(e,t,r)=>(r=e!=null?L(j(e)):{},J(t||!e||!e.__esModule?A(r,"default",{value:e,enumerable:!0}):r,e));function v(){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(r=>r.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 p(e,t){if(typeof document>"u")return;let r=new Date;r.setTime(r.getTime()+365*24*60*60*1e3);let n="; expires="+r.toUTCString();document.cookie=e+"="+(t||"")+n+"; path=/"}function g(e){if(typeof document>"u")return null;let t=e+"=",r=document.cookie.split(";");for(let n=0;n<r.length;n++){let s=r[n];for(;s.charAt(0)===" ";)s=s.substring(1,s.length);if(s.indexOf(t)===0)return s.substring(t.length,s.length)}return null}function h(e){let t=g(e);if(t)try{return JSON.parse(t)}catch(r){return console.error("[ElevateAB] Error parsing JSON from cookie",r),null}return null}function w(e,t){typeof sessionStorage>"u"||(typeof t=="string"?sessionStorage.setItem(e,t):sessionStorage.setItem(e,JSON.stringify(t)))}function b(e){if(typeof sessionStorage>"u")return null;let t=sessionStorage.getItem(e);if(t&&t.length>=2&&t.startsWith('"')&&t.endsWith('"'))try{let r=JSON.parse(t);if(typeof r=="string")return sessionStorage.setItem(e,r),r}catch{}return t}function I(e){let t=b(e);return t?JSON.parse(t):null}function N(){let e=g("eabUserId");return e||(e=v(),p("eabUserId",e)),e}function C(){return N()}function D(){let e=b("eabSessionId");return e||(e=v(),w("eabSessionId",e)),e}function Z(){return D()}function ee(){return{referrer:b("eabReferrer")||"",entryPage:b("eabEntry")||""}}function P(e){let t=0;for(let r=0;r<e.length;r++){let n=e.charCodeAt(r);t=(t<<5)-t+n,t=t&t}return Math.abs(t)}function re(e){let t=[];for(let[r,n]of Object.entries(e.allTests)){if(!n.data.isLive)continue;let s=[],i=0;for(let[o,a]of Object.entries(n)){if(o==="data")continue;let u=a;if(typeof u=="object"&&u!==null&&"variationName"in u){let f=!!u.isControl,c=u.content,d;c&&typeof c=="object"&&(d={changes:c.changes||[],elements:c.elements||[],blocks:c.blocks||[],customCodes:c.customCodes||[]});let l=u.customCode,y;l&&typeof l=="object"&&l.id&&(y={id:l.id,js:l.js,css:l.css,pathnames:l.pathnames||[],excludePathnames:l.excludePathnames}),s.push({id:o,name:u.variationName,weight:u.trafficPercentage,isControl:f,productId:u.id,handle:u.handle,price:u.price,prices:u.prices,splitUrlTestLinks:u.splitUrlTestLinks,content:d,customCode:y,isA:!f&&i===0,isB:!f&&i===1,isC:!f&&i===2,isD:!f&&i===3}),f||i++}}s.length>0&&t.push({testId:r,name:n.data.name,enabled:n.data.isLive,type:n.data.type,variations:s,data:n.data})}return{tests:t,selectors:e.selectors}}function M(e){let t={},r={};if(!e)return{assignments:t,views:r};let n=e.split("~");for(let s of n){let i=s.split("_");if(i.length>=2){let o=i[0],a=i[1],u=i[2]==="1";t[o]=a,r[o]=u}}return{assignments:t,views:r}}function q(){if(typeof window>"u")return{isPreview:!1,previewTestId:null,forcedAssignments:{},previewedViews:{}};let e=new URLSearchParams(window.location.search),r=(e.get("eabUserPreview")||g("eabUserPreview"))==="true",n=e.get("abtid");n||(n=b("eabPreviewTestId"));let s=e.get("eab_tests")||"",{assignments:i,views:o}=M(s);return e.has("eabUserPreview")&&p("eabUserPreview","true"),e.has("abtid")&&n&&w("eabPreviewTestId",n),{isPreview:r,previewTestId:n,forcedAssignments:i,previewedViews:o}}function T(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 ie(){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 oe(){return q().isPreview}function $(e){let t=h("ABAU")||{};t[e]||(t[e]=!0,p("ABAU",JSON.stringify(t)))}function W(e){let t=I("ABAV")||{};t[e]||(t[e]=!0,w("ABAV",t))}function k(e){$(e),W(e)}function m(){return h("ABTL")||{}}function S(e){p("ABTL",JSON.stringify(e))}function z(e){return m()[e]||null}function E(e,t){if(e[t]?.isControl)return-1;let n=0;for(let s=0;s<t;s++)e[s]?.isControl||n++;return n}function H(e,t){let r=e.every(c=>typeof c.weight=="number"),n=[],s=0;if(r)for(let c of e)s+=c.weight,n.push(s);else{let c=100/e.length;for(let d=0;d<e.length;d++)s+=c,n.push(s)}let o=P(t)%1e4/100,a=0;for(let c=0;c<n.length;c++)if(o<n[c]){a=c;break}let u=e[a]||e[0],f=E(e,a);return{...u,isA:f===0,isB:f===1,isC:f===2,isD:f===3}}function U(e,t){let r=t.findIndex(s=>s.id===e.id),n=E(t,r);return{...e,isA:n===0,isB:n===1,isC:n===2,isD:n===3}}function F(e,t,r,n){if(n?.isPreview){let f=T(e,n);if(f){let c=t.variations.find(d=>d.id===f);if(c){let d=m();return d[e]=c.id,S(d),U(c,t.variations)}}}let s=z(e);if(s){let f=t.variations.find(c=>c.id===s);if(f)return U(f,t.variations)}let i=t.variations.filter(f=>!f.isDone);if(i.length===0)return null;let o=t.isPersonalization,a;o?a=i.find(c=>!c.isControl)||i[0]:a=H(i,r);let u=m();return u[e]=a.id,S(u),k(e),a}function V(e){return typeof e.testTrafficPercentage=="number"}function me(e,t){let r=C(),n=e.tests,s=m();for(let i of n){if(!i.enabled)continue;if(s[i.testId])if(t?.isPreview){let a=T(i.testId,t);if(!a||a===s[i.testId])continue}else continue;if(!G(i.testId,n,s))continue;let o=i.testTrafficPercentage;!t?.isPreview&&typeof o=="number"&&Math.random()*100>=o||(F(i.testId,i,r,t??void 0),s=m())}}function G(e,t,r){let n=Object.keys(r);if(n.length===0)return!0;if(n.some(o=>{let a=t.find(u=>u.testId===o);return a&&V(a)}))return!1;let i=t.find(o=>o.testId===e);return i?!V(i):!0}var x=`#graphql
|
|
3
3
|
mutation cartAttributesUpdate($cartId: ID!, $attributes: [AttributeInput!]!) {
|
|
4
4
|
cartAttributesUpdate(cartId: $cartId, attributes: $attributes) {
|
|
5
5
|
cart {
|
|
@@ -15,5 +15,5 @@ var R=Object.create;var y=Object.defineProperty;var B=Object.getOwnPropertyDescr
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
`;function X(){let e=
|
|
19
|
-
//# sourceMappingURL=chunk-
|
|
18
|
+
`;function X(){let e=m(),t=h("ABAU")||{},r=g("eabUserId"),n=g("eabUserPreview")==="true",s=g("abtid"),i={};for(let a in e)t[a]&&(i[a]=e[a]);let o=[{key:"_eabTestsList",value:JSON.stringify(i)},{key:"_eabUserId",value:r||""},{key:"_eabList",value:JSON.stringify(e)}];return n&&s&&o.push({key:"_eabPreviewTest",value:s}),o}async function ye(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 r=X(),n=e.startsWith("gid://")?e:`gid://shopify/Cart/${e}`,s=t.storefrontApiUrl||`https://${R()}/api/2025-01/graphql.json`,i=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json","X-Shopify-Storefront-Access-Token":t.storefrontAccessToken},body:JSON.stringify({query:x,variables:{cartId:n,attributes:r}})});if(!i.ok)throw new Error(`HTTP error! status: ${i.status}`);let o=await i.json();if(o.errors||o.data?.cartAttributesUpdate?.userErrors?.length>0){let a=o.errors?.[0]?.message||o.data?.cartAttributesUpdate?.userErrors?.[0]?.message||"Unknown error";return console.error("[ElevateAB] Cart attributes update failed:",a),{success:!1,error:a}}return{success:!0}}catch(r){return console.error("[ElevateAB] Error updating cart attributes:",r),{success:!1,error:r instanceof Error?r.message:"Unknown error"}}}async function Ae(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 r=e.startsWith("gid://")?e:`gid://shopify/Cart/${e}`,n=[{key:"_eabTestsList",value:""},{key:"_eabUserId",value:""},{key:"_eabList",value:""},{key:"_eabPreviewTest",value:""}],s=t.storefrontApiUrl||`https://${R()}/api/2025-01/graphql.json`,i=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json","X-Shopify-Storefront-Access-Token":t.storefrontAccessToken},body:JSON.stringify({query:x,variables:{cartId:r,attributes:n}})});if(!i.ok)throw new Error(`HTTP error! status: ${i.status}`);let o=await i.json();if(o.errors||o.data?.cartAttributesUpdate?.userErrors?.length>0){let a=o.errors?.[0]?.message||o.data?.cartAttributesUpdate?.userErrors?.[0]?.message||"Unknown error";return console.error("[ElevateAB] Cart attributes cleanup failed:",a),{success:!1,error:a}}return{success:!0}}catch(r){return console.error("[ElevateAB] Error cleaning up cart attributes:",r),{success:!1,error:r instanceof Error?r.message:"Unknown error"}}}function R(){return typeof window>"u"?"":window.location.hostname}export{Q as a,K as b,re as c,v as d,p as e,g as f,h as g,C as h,Z as i,ee as j,q as k,ie as l,oe as m,k as n,z as o,me as p,X as q,ye as r,Ae as s};
|
|
19
|
+
//# sourceMappingURL=chunk-SCLOA5QZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/storage.ts","../src/utils.ts","../src/utils/preview.ts","../src/utils/tracking.ts","../src/utils/assignment.ts","../src/mutations/cartAttributes.mutation.ts","../src/utils/cartAttributes.ts"],"sourcesContent":["export function uuidv4(): string {\n try {\n if (\n typeof window !== \"undefined\" &&\n window.crypto &&\n window.crypto.getRandomValues\n ) {\n const rnds = new Uint8Array(16);\n window.crypto.getRandomValues(rnds);\n rnds[6] = (rnds[6] & 0x0f) | 0x40; // Version 4\n rnds[8] = (rnds[8] & 0x3f) | 0x80; // Variant 1\n\n const hexValues = Array.from(rnds).map((b) =>\n b.toString(16).padStart(2, \"0\")\n );\n\n return [\n hexValues.slice(0, 4).join(\"\"),\n hexValues.slice(4, 6).join(\"\"),\n hexValues.slice(6, 8).join(\"\"),\n hexValues.slice(8, 10).join(\"\"),\n hexValues.slice(10, 16).join(\"\"),\n ].join(\"-\");\n }\n } catch (e) {\n console.warn(\n \"[ElevateAB] Crypto UUID generation failed, falling back to Math.random()\",\n e\n );\n }\n\n // Fallback to Math.random\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function setCookie(name: string, value: string): void {\n if (typeof document === \"undefined\") return;\n\n const date = new Date();\n date.setTime(date.getTime() + 365 * 24 * 60 * 60 * 1000);\n const expires = \"; expires=\" + date.toUTCString();\n document.cookie = name + \"=\" + (value || \"\") + expires + \"; path=/\";\n}\n\nexport function getCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n\n const nameEQ = name + \"=\";\n const ca = document.cookie.split(\";\");\n for (let i = 0; i < ca.length; i++) {\n let c = ca[i];\n while (c.charAt(0) === \" \") c = c.substring(1, c.length);\n if (c.indexOf(nameEQ) === 0) {\n return c.substring(nameEQ.length, c.length);\n }\n }\n return null;\n}\n\nexport function getJsonCookie<T = Record<string, unknown>>(\n name: string\n): T | null {\n const cookieValue = getCookie(name);\n if (cookieValue) {\n try {\n return JSON.parse(cookieValue) as T;\n } catch (error) {\n console.error(\"[ElevateAB] Error parsing JSON from cookie\", error);\n return null;\n }\n }\n return null;\n}\n\nexport function deleteCookie(cookieName: string): void {\n if (typeof document === \"undefined\") return;\n\n document.cookie =\n cookieName + \"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;\";\n}\n\nexport function setSessionItem(name: string, value: unknown): void {\n if (typeof sessionStorage === \"undefined\") return;\n\n // Store strings directly to avoid wrapping quotes in sessionStorage.\n if (typeof value === \"string\") {\n sessionStorage.setItem(name, value);\n } else {\n sessionStorage.setItem(name, JSON.stringify(value));\n }\n}\n\nexport function getSessionItem(name: string): string | null {\n if (typeof sessionStorage === \"undefined\") return null;\n\n const value = sessionStorage.getItem(name);\n\n // Backward compatibility: old values may be double-serialized strings.\n if (value && value.length >= 2 && value.startsWith('\"') && value.endsWith('\"')) {\n try {\n const parsed = JSON.parse(value);\n if (typeof parsed === \"string\") {\n sessionStorage.setItem(name, parsed);\n return parsed;\n }\n } catch {\n // Not JSON-wrapped; return original value below.\n }\n }\n\n return value;\n}\n\nexport function getJsonSessionItem<T = unknown>(name: string): T | null {\n const item = getSessionItem(name);\n return item ? (JSON.parse(item) as T) : null;\n}\n\nexport function initializeVisitorId(): string {\n let visitorId = getCookie(\"eabUserId\");\n\n if (!visitorId) {\n visitorId = uuidv4();\n setCookie(\"eabUserId\", visitorId);\n }\n\n return visitorId;\n}\n\nexport function getVisitorId(): string {\n return initializeVisitorId();\n}\n\nexport function initializeSessionId(): string {\n let sessionId = getSessionItem(\"eabSessionId\");\n\n if (!sessionId) {\n sessionId = uuidv4();\n setSessionItem(\"eabSessionId\", sessionId);\n }\n\n return sessionId;\n}\n\nexport function getSessionId(): string {\n return initializeSessionId();\n}\n\nexport function setReferrerData(referrer: string, entryPage: string): void {\n if (typeof sessionStorage === \"undefined\") return;\n\n // Only set if not already set (preserve first referrer/entry)\n const existingReferrer = getSessionItem(\"eabReferrer\");\n const existingEntry = getSessionItem(\"eabEntry\");\n\n if (!existingReferrer) {\n setSessionItem(\"eabReferrer\", referrer);\n }\n if (!existingEntry) {\n setSessionItem(\"eabEntry\", entryPage);\n }\n}\n\nexport function getReferrerData(): { referrer: string; entryPage: string } {\n return {\n referrer: getSessionItem(\"eabReferrer\") || \"\",\n entryPage: getSessionItem(\"eabEntry\") || \"\",\n };\n}\n","import type {\n Variation,\n Test,\n BackendConfig,\n ElevateConfig,\n ContentTestData,\n ContentCustomCode,\n} from \"./types\";\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 parseBackendConfig(backendData: BackendConfig): ElevateConfig {\n const tests: Test[] = [];\n\n for (const [testId, testData] of Object.entries(backendData.allTests)) {\n if (!testData.data.isLive) continue;\n\n const variations: Variation[] = [];\n let nonControlIndex = 0;\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 const isControl = !!variation.isControl;\n\n const rawContent = (variation as any).content;\n let content: ContentTestData | undefined;\n if (rawContent && typeof rawContent === \"object\") {\n content = {\n changes: rawContent.changes || [],\n elements: rawContent.elements || [],\n blocks: rawContent.blocks || [],\n customCodes: rawContent.customCodes || [],\n };\n }\n\n const rawCustomCode = (variation as any).customCode;\n let customCode: ContentCustomCode | undefined;\n if (rawCustomCode && typeof rawCustomCode === \"object\" && rawCustomCode.id) {\n customCode = {\n id: rawCustomCode.id,\n js: rawCustomCode.js,\n css: rawCustomCode.css,\n pathnames: rawCustomCode.pathnames || [],\n excludePathnames: rawCustomCode.excludePathnames,\n };\n }\n\n variations.push({\n id: key,\n name: variation.variationName,\n weight: variation.trafficPercentage,\n isControl,\n productId: variation.id,\n handle: variation.handle,\n price: variation.price,\n prices: (variation as any).prices,\n splitUrlTestLinks: (variation as any).splitUrlTestLinks,\n content,\n customCode,\n isA: !isControl && nonControlIndex === 0,\n isB: !isControl && nonControlIndex === 1,\n isC: !isControl && nonControlIndex === 2,\n isD: !isControl && nonControlIndex === 3,\n });\n if (!isControl) nonControlIndex++;\n }\n }\n\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 data: testData.data,\n });\n }\n }\n\n return {\n tests,\n selectors: backendData.selectors,\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","import {\n setCookie,\n setSessionItem,\n getJsonCookie,\n getJsonSessionItem,\n} from \"./storage\";\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\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\nexport function trackViews(testId: string): void {\n trackUniqueView(testId);\n trackSessionView(testId);\n}\n\nexport function hasSessionView(testId: string): boolean {\n const addedViews = getJsonSessionItem<Record<string, boolean>>(\"ABAV\") || {};\n return !!addedViews[testId];\n}\n\nexport function hasUniqueView(testId: string): boolean {\n const addedUniqueViews = getJsonCookie<Record<string, boolean>>(\"ABAU\") || {};\n return !!addedUniqueViews[testId];\n}\n","import type { Test, Variation, ElevateConfig } from \"../types\";\nimport type { PreviewState } from \"./preview\";\nimport { getCookie, setCookie, getJsonCookie, getVisitorId } from \"./storage\";\nimport { hashString } from \"../utils\";\nimport { getPreviewVariation } from \"./preview\";\nimport { trackViews } from \"./tracking\";\n\nexport interface TestList {\n [testId: string]: string; // testId -> variantId\n}\n\nexport function getTestList(): TestList {\n return getJsonCookie<TestList>(\"ABTL\") || {};\n}\n\nexport function saveTestList(testList: TestList): void {\n setCookie(\"ABTL\", JSON.stringify(testList));\n}\n\nexport function getAssignedVariant(testId: string): string | null {\n const testList = getTestList();\n return testList[testId] || null;\n}\n\nfunction getNonControlIndex(\n variations: Variation[],\n targetIndex: number\n): number {\n const variation = variations[targetIndex];\n if (variation?.isControl) return -1;\n\n let nonControlIndex = 0;\n for (let i = 0; i < targetIndex; i++) {\n if (!variations[i]?.isControl) {\n nonControlIndex++;\n }\n }\n return nonControlIndex;\n}\n\nexport function assignVariantForUser(\n variations: Variation[],\n userId: string\n): Variation {\n const allHaveTrafficPercentage = variations.every(\n (v) => typeof v.weight === \"number\"\n );\n\n let cumulativeWeights: number[] = [];\n let totalWeight = 0;\n\n if (allHaveTrafficPercentage) {\n for (const variation of variations) {\n totalWeight += variation.weight;\n cumulativeWeights.push(totalWeight);\n }\n } else {\n const defaultWeight = 100 / variations.length;\n for (let i = 0; i < variations.length; i++) {\n totalWeight += defaultWeight;\n cumulativeWeights.push(totalWeight);\n }\n }\n\n const hash = hashString(userId);\n const randomWeight = (hash % 10000) / 100;\n\n let assignedIndex = 0;\n for (let i = 0; i < cumulativeWeights.length; i++) {\n if (randomWeight < cumulativeWeights[i]) {\n assignedIndex = i;\n break;\n }\n }\n\n const assignedVariation = variations[assignedIndex] || variations[0];\n const nonControlIndex = getNonControlIndex(variations, assignedIndex);\n\n return {\n ...assignedVariation,\n isA: nonControlIndex === 0,\n isB: nonControlIndex === 1,\n isC: nonControlIndex === 2,\n isD: nonControlIndex === 3,\n };\n}\n\nfunction enrichVariant(variant: Variation, variations: Variation[]): Variation {\n const variantIndex = variations.findIndex((v) => v.id === variant.id);\n const nonControlIndex = getNonControlIndex(variations, variantIndex);\n return {\n ...variant,\n isA: nonControlIndex === 0,\n isB: nonControlIndex === 1,\n isC: nonControlIndex === 2,\n isD: nonControlIndex === 3,\n };\n}\n\nexport function assignAndPersistVariant(\n testId: string,\n test: Test,\n userId: string,\n previewState?: PreviewState\n): Variation | null {\n if (previewState?.isPreview) {\n const forcedVariationId = getPreviewVariation(testId, previewState);\n if (forcedVariationId) {\n const forcedVariant = test.variations.find(\n (v) => v.id === forcedVariationId\n );\n if (forcedVariant) {\n const testList = getTestList();\n testList[testId] = forcedVariant.id;\n saveTestList(testList);\n return enrichVariant(forcedVariant, test.variations);\n }\n }\n }\n\n const existingVariantId = getAssignedVariant(testId);\n if (existingVariantId) {\n const existingVariant = test.variations.find(\n (v) => v.id === existingVariantId\n );\n if (existingVariant) {\n return enrichVariant(existingVariant, test.variations);\n }\n }\n\n const activeVariations = test.variations.filter((v) => {\n const isDone = (v as any).isDone;\n return !isDone;\n });\n\n if (activeVariations.length === 0) {\n return null;\n }\n\n const isPersonalization = (test as any).isPersonalization;\n let assignedVariant: Variation;\n\n if (isPersonalization) {\n const personalizedVariation = activeVariations.find((v) => !v.isControl);\n assignedVariant = personalizedVariation || activeVariations[0];\n } else {\n assignedVariant = assignVariantForUser(activeVariations, userId);\n }\n\n const testList = getTestList();\n testList[testId] = assignedVariant.id;\n saveTestList(testList);\n trackViews(testId);\n\n return assignedVariant;\n}\n\nfunction isIsolatedTest(test: Test): boolean {\n const trafficPercentage = (test as any).testTrafficPercentage;\n return typeof trafficPercentage === \"number\";\n}\n\nexport function canAssignToTest(testId: string, allTests: Test[]): boolean {\n try {\n const currentAssignments = getTestList();\n const currentTestIds = Object.keys(currentAssignments);\n\n if (currentAssignments[testId]) {\n return true;\n }\n\n if (currentTestIds.length === 0) {\n return true;\n }\n\n const isInIsolatedTest = currentTestIds.some((id) => {\n const test = allTests.find((t) => t.testId === id);\n return test && isIsolatedTest(test);\n });\n\n if (isInIsolatedTest) {\n return false;\n }\n\n const targetTest = allTests.find((t) => t.testId === testId);\n if (!targetTest) {\n return true;\n }\n\n if (isIsolatedTest(targetTest)) {\n return false;\n }\n\n return true;\n } catch (error) {\n console.error(\"[ElevateAB] Error in canAssignToTest:\", error);\n return true;\n }\n}\n\nexport function shouldShowTest(test: Test, allTests?: Test[]): boolean {\n const testTrafficPercentage = (test as any).testTrafficPercentage;\n\n if (typeof testTrafficPercentage !== \"number\") {\n return true;\n }\n\n const existingVariantId = getAssignedVariant(test.testId);\n if (existingVariantId) {\n return true;\n }\n\n if (allTests && !canAssignToTest(test.testId, allTests)) {\n return false;\n }\n\n const random = Math.random() * 100;\n return random < testTrafficPercentage;\n}\n\nexport function assignAllTests(\n config: ElevateConfig,\n previewState?: PreviewState | null\n): void {\n const userId = getVisitorId();\n const allTests = config.tests;\n let cachedTestList = getTestList();\n\n for (const test of allTests) {\n if (!test.enabled) continue;\n\n if (cachedTestList[test.testId]) {\n if (previewState?.isPreview) {\n const forcedId = getPreviewVariation(test.testId, previewState);\n if (!forcedId || forcedId === cachedTestList[test.testId]) {\n continue;\n }\n } else {\n continue;\n }\n }\n\n if (!canAssignToTestWithCache(test.testId, allTests, cachedTestList)) {\n continue;\n }\n\n const testTrafficPercentage = (test as any).testTrafficPercentage;\n if (!previewState?.isPreview && typeof testTrafficPercentage === \"number\") {\n const random = Math.random() * 100;\n if (random >= testTrafficPercentage) continue;\n }\n\n assignAndPersistVariant(\n test.testId,\n test,\n userId,\n previewState ?? undefined\n );\n\n cachedTestList = getTestList();\n }\n}\n\nfunction canAssignToTestWithCache(\n testId: string,\n allTests: Test[],\n cachedTestList: TestList\n): boolean {\n const currentTestIds = Object.keys(cachedTestList);\n\n // No current assignments - can join any test\n if (currentTestIds.length === 0) {\n return true;\n }\n\n // Check if user is in any isolated test\n const isInIsolatedTest = currentTestIds.some((id) => {\n const test = allTests.find((t) => t.testId === id);\n return test && isIsolatedTest(test);\n });\n\n if (isInIsolatedTest) {\n return false;\n }\n\n // Check if target test is isolated\n const targetTest = allTests.find((t) => t.testId === testId);\n if (!targetTest) {\n return true;\n }\n\n if (isIsolatedTest(targetTest)) {\n return false;\n }\n\n return true;\n}\n","/**\n * GraphQL mutations for cart attributes\n */\n\n/**\n * GraphQL mutation for updating cart attributes\n * Use this in your Storefront API calls\n */\nexport const CART_ATTRIBUTES_UPDATE_MUTATION = `#graphql\n mutation cartAttributesUpdate($cartId: ID!, $attributes: [AttributeInput!]!) {\n cartAttributesUpdate(cartId: $cartId, attributes: $attributes) {\n cart {\n id\n attributes {\n key\n value\n }\n }\n userErrors {\n field\n message\n }\n }\n }\n`;\n","/**\n * Cart attribute utilities for tagging carts with A/B test data\n *\n * These functions update Shopify cart attributes with test assignment data,\n * enabling order attribution for A/B test analysis.\n */\n\nimport { getTestList } from \"./assignment\";\nimport { getCookie, getJsonCookie } from \"./storage\";\nimport { CART_ATTRIBUTES_UPDATE_MUTATION } from \"../mutations/cartAttributes.mutation\";\nimport type { CartAttributesOptions, CartAttributeInput } from \"../types\";\n\n// Re-export types for backwards compatibility\nexport type { CartAttributesOptions, CartAttributeInput } from \"../types\";\n\n/**\n * Get cart attributes payload from current test assignments\n * Returns an array of key-value pairs ready to be sent to Shopify\n *\n * @example\n * ```ts\n * const attributes = getCartAttributesPayload();\n * // Use with your own Storefront client\n * await storefront.mutate(CART_ATTRIBUTES_UPDATE_MUTATION, {\n * variables: { cartId, attributes }\n * });\n * ```\n */\nexport function getCartAttributesPayload(): CartAttributeInput[] {\n const testList = getTestList(); // ABTL - all assignments\n const addedUniqueViews = getJsonCookie<Record<string, boolean>>(\"ABAU\") || {};\n const eabUserId = getCookie(\"eabUserId\");\n const isPreviewMode = getCookie(\"eabUserPreview\") === \"true\";\n const abtidValue = getCookie(\"abtid\");\n\n // Filter viewed tests - only include tests that have been viewed\n const viewedTests: Record<string, string> = {};\n for (const testId in testList) {\n if (addedUniqueViews[testId]) {\n viewedTests[testId] = testList[testId];\n }\n }\n\n const attributes: CartAttributeInput[] = [\n {\n key: \"_eabTestsList\",\n value: JSON.stringify(viewedTests),\n },\n {\n key: \"_eabUserId\",\n value: eabUserId || \"\",\n },\n {\n key: \"_eabList\",\n value: JSON.stringify(testList),\n },\n ];\n\n // Add preview test if in preview mode\n if (isPreviewMode && abtidValue) {\n attributes.push({\n key: \"_eabPreviewTest\",\n value: abtidValue,\n });\n }\n\n return attributes;\n}\n\n/**\n * Update cart attributes with test assignment data\n *\n * This function calls the Shopify Storefront API to update cart attributes.\n *\n * ## Authentication\n *\n * **For Hydrogen stores:** Use your storefront client directly with `getCartAttributesPayload()`\n *\n * **For Next.js/Other stores:** Pass the `storefrontAccessToken` option.\n *\n * ✅ The Storefront Access Token is **safe to use client-side**.\n * It's a public token designed by Shopify for browser use.\n * It can only read products and manage carts - it CANNOT delete products,\n * access admin functions, or do anything destructive.\n *\n * Get your token from: Shopify Admin → Settings → Apps → Develop apps\n *\n * @param cartId - The cart ID (GID or token, e.g., \"gid://shopify/Cart/abc123\" or just \"abc123\")\n * @param options - Configuration options including storefrontAccessToken\n * @returns Promise with success status and optional error message\n *\n * @example\n * ```ts\n * // Next.js usage - token is safe to use client-side!\n * const result = await updateCartAttributes(cartId, {\n * storefrontAccessToken: process.env.NEXT_PUBLIC_STOREFRONT_TOKEN\n * });\n *\n * if (!result.success) {\n * console.error('Failed to update cart attributes:', result.error);\n * }\n * ```\n */\nexport async function updateCartAttributes(\n cartId: string,\n options: CartAttributesOptions = {}\n): Promise<{ success: boolean; error?: string }> {\n if (typeof window === \"undefined\") {\n return { success: false, error: \"Not in browser environment\" };\n }\n\n // Validate token is provided for direct API calls\n if (!options.storefrontAccessToken && !options.storefrontApiUrl) {\n console.warn(\n \"[ElevateAB] Missing storefrontAccessToken. \" +\n \"For Next.js/non-Hydrogen stores, you must provide a Storefront Access Token. \" +\n \"This token 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 return {\n success: false,\n error:\n \"Missing storefrontAccessToken. Required for direct Storefront API calls.\",\n };\n }\n\n try {\n const attributes = getCartAttributesPayload();\n\n // Format cartId as GID if it's not already\n const cartGid = cartId.startsWith(\"gid://\")\n ? cartId\n : `gid://shopify/Cart/${cartId}`;\n\n const storefrontUrl =\n options.storefrontApiUrl ||\n `https://${getStoreDomain()}/api/2025-01/graphql.json`;\n\n const response = await fetch(storefrontUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Shopify-Storefront-Access-Token\": options.storefrontAccessToken!,\n },\n body: JSON.stringify({\n query: CART_ATTRIBUTES_UPDATE_MUTATION,\n variables: {\n cartId: cartGid,\n attributes,\n },\n }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const result = await response.json();\n\n if (\n result.errors ||\n result.data?.cartAttributesUpdate?.userErrors?.length > 0\n ) {\n const errorMsg =\n result.errors?.[0]?.message ||\n result.data?.cartAttributesUpdate?.userErrors?.[0]?.message ||\n \"Unknown error\";\n console.error(\"[ElevateAB] Cart attributes update failed:\", errorMsg);\n return { success: false, error: errorMsg };\n }\n\n return { success: true };\n } catch (error) {\n console.error(\"[ElevateAB] Error updating cart attributes:\", error);\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n}\n\n/**\n * Cleanup/remove cart attributes\n * Sets all Elevate attributes to empty strings\n *\n * @param cartId - The cart ID (GID or token)\n * @param options - Configuration options including storefrontAccessToken\n */\nexport async function cleanupCartAttributes(\n cartId: string,\n options: CartAttributesOptions = {}\n): Promise<{ success: boolean; error?: string }> {\n if (typeof window === \"undefined\") {\n return { success: false, error: \"Not in browser environment\" };\n }\n\n // Validate token is provided\n if (!options.storefrontAccessToken && !options.storefrontApiUrl) {\n return {\n success: false,\n error:\n \"Missing storefrontAccessToken. Required for direct Storefront API calls.\",\n };\n }\n\n try {\n const cartGid = cartId.startsWith(\"gid://\")\n ? cartId\n : `gid://shopify/Cart/${cartId}`;\n\n const attributes: CartAttributeInput[] = [\n { key: \"_eabTestsList\", value: \"\" },\n { key: \"_eabUserId\", value: \"\" },\n { key: \"_eabList\", value: \"\" },\n { key: \"_eabPreviewTest\", value: \"\" },\n ];\n\n const storefrontUrl =\n options.storefrontApiUrl ||\n `https://${getStoreDomain()}/api/2025-01/graphql.json`;\n\n const response = await fetch(storefrontUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Shopify-Storefront-Access-Token\": options.storefrontAccessToken!,\n },\n body: JSON.stringify({\n query: CART_ATTRIBUTES_UPDATE_MUTATION,\n variables: {\n cartId: cartGid,\n attributes,\n },\n }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const result = await response.json();\n\n if (\n result.errors ||\n result.data?.cartAttributesUpdate?.userErrors?.length > 0\n ) {\n const errorMsg =\n result.errors?.[0]?.message ||\n result.data?.cartAttributesUpdate?.userErrors?.[0]?.message ||\n \"Unknown error\";\n console.error(\"[ElevateAB] Cart attributes cleanup failed:\", errorMsg);\n return { success: false, error: errorMsg };\n }\n\n return { success: true };\n } catch (error) {\n console.error(\"[ElevateAB] Error cleaning up cart attributes:\", error);\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n}\n\n/**\n * Helper to get store domain from current URL\n * Assumes format: mystore.myshopify.com or custom domain\n */\nfunction getStoreDomain(): string {\n if (typeof window === \"undefined\") return \"\";\n return window.location.hostname;\n}\n"],"mappings":"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","names":["uuidv4","rnds","hexValues","b","c","r","setCookie","name","value","date","expires","getCookie","nameEQ","ca","i","getJsonCookie","cookieValue","error","setSessionItem","name","value","getSessionItem","parsed","getJsonSessionItem","item","initializeVisitorId","visitorId","getCookie","uuidv4","setCookie","getVisitorId","initializeSessionId","sessionId","getSessionId","getReferrerData","getSessionItem","hashString","str","hash","i","char","parseBackendConfig","backendData","tests","testId","testData","variations","nonControlIndex","key","value","variation","isControl","rawContent","content","rawCustomCode","customCode","parseEabTestsParam","param","assignments","views","tests","test","parts","shortTestId","variationId","hasSeen","getPreviewState","urlParams","isPreview","getCookie","previewTestId","getSessionItem","eabTestsParam","setCookie","setSessionItem","getPreviewVariation","testId","previewState","shortTestId","clearPreviewMode","url","isInPreviewMode","getPreviewState","trackUniqueView","testId","addedUniqueViews","getJsonCookie","setCookie","trackSessionView","addedViews","getJsonSessionItem","setSessionItem","trackViews","getTestList","getJsonCookie","saveTestList","testList","setCookie","getAssignedVariant","testId","getNonControlIndex","variations","targetIndex","nonControlIndex","i","assignVariantForUser","userId","allHaveTrafficPercentage","v","cumulativeWeights","totalWeight","variation","defaultWeight","randomWeight","hashString","assignedIndex","assignedVariation","enrichVariant","variant","variantIndex","assignAndPersistVariant","test","previewState","forcedVariationId","getPreviewVariation","forcedVariant","existingVariantId","existingVariant","activeVariations","isPersonalization","assignedVariant","trackViews","isIsolatedTest","assignAllTests","config","previewState","userId","getVisitorId","allTests","cachedTestList","getTestList","test","forcedId","getPreviewVariation","canAssignToTestWithCache","testTrafficPercentage","assignAndPersistVariant","testId","currentTestIds","id","t","isIsolatedTest","targetTest","CART_ATTRIBUTES_UPDATE_MUTATION","getCartAttributesPayload","testList","getTestList","addedUniqueViews","getJsonCookie","eabUserId","getCookie","isPreviewMode","abtidValue","viewedTests","testId","attributes","updateCartAttributes","cartId","options","cartGid","storefrontUrl","getStoreDomain","response","CART_ATTRIBUTES_UPDATE_MUTATION","result","errorMsg","error","cleanupCartAttributes"]}
|