@elevateab/sdk 1.4.7 → 1.4.9
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 +8 -3
- 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
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts","../src/utils/storage.ts","../src/utils/preview.ts","../src/utils/tracking.ts","../src/utils/assignment.ts","../node_modules/ua-parser-js/src/ua-parser.js","../src/mutations/cartAttributes.mutation.ts","../src/utils/cartAttributes.ts","../src/index.ts","../src/utils/conditions.ts","../src/utils/geo.ts","../src/handlers/splitUrl.ts","../src/utils/navigation.ts","../src/utils/analytics.ts","../src/utils/shopify.ts","../src/utils/content.ts","../src/utils/manualTracking.ts","../src/components/Experiment.tsx","../src/contexts/ElevateContext.tsx","../src/handlers/registry.ts","../src/handlers/pricePlus.ts","../src/handlers/content.ts","../src/handlers/customCode.ts","../src/handlers/index.ts","../src/components/ElevateProvider.tsx","../src/utils/customCode.ts","../src/components/ElevateAnalytics.tsx"],"sourcesContent":["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","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","/**\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 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]) continue;\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/* UAParser.js v1.0.41\n Copyright © 2012-2025 Faisal Salman <f@faisalman.com>\n MIT License *//*\n Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.\n Supports browser & node.js environment. \n Demo : https://faisalman.github.io/ua-parser-js\n Source : https://github.com/faisalman/ua-parser-js */\n/////////////////////////////////////////////////////////////////////////////////\n\n(function (window, undefined) {\n\n 'use strict';\n\n //////////////\n // Constants\n /////////////\n\n\n var LIBVERSION = '1.0.41',\n EMPTY = '',\n UNKNOWN = '?',\n FUNC_TYPE = 'function',\n UNDEF_TYPE = 'undefined',\n OBJ_TYPE = 'object',\n STR_TYPE = 'string',\n MAJOR = 'major',\n MODEL = 'model',\n NAME = 'name',\n TYPE = 'type',\n VENDOR = 'vendor',\n VERSION = 'version',\n ARCHITECTURE= 'architecture',\n CONSOLE = 'console',\n MOBILE = 'mobile',\n TABLET = 'tablet',\n SMARTTV = 'smarttv',\n WEARABLE = 'wearable',\n EMBEDDED = 'embedded',\n UA_MAX_LENGTH = 500;\n\n var AMAZON = 'Amazon',\n APPLE = 'Apple',\n ASUS = 'ASUS',\n BLACKBERRY = 'BlackBerry',\n BROWSER = 'Browser',\n CHROME = 'Chrome',\n EDGE = 'Edge',\n FIREFOX = 'Firefox',\n GOOGLE = 'Google',\n HONOR = 'Honor',\n HUAWEI = 'Huawei',\n LENOVO = 'Lenovo',\n LG = 'LG',\n MICROSOFT = 'Microsoft',\n MOTOROLA = 'Motorola',\n NVIDIA = 'Nvidia',\n ONEPLUS = 'OnePlus',\n OPERA = 'Opera',\n OPPO = 'OPPO',\n SAMSUNG = 'Samsung',\n SHARP = 'Sharp',\n SONY = 'Sony',\n XIAOMI = 'Xiaomi',\n ZEBRA = 'Zebra',\n FACEBOOK = 'Facebook',\n CHROMIUM_OS = 'Chromium OS',\n MAC_OS = 'Mac OS',\n SUFFIX_BROWSER = ' Browser';\n\n ///////////\n // Helper\n //////////\n\n var extend = function (regexes, extensions) {\n var mergedRegexes = {};\n for (var i in regexes) {\n if (extensions[i] && extensions[i].length % 2 === 0) {\n mergedRegexes[i] = extensions[i].concat(regexes[i]);\n } else {\n mergedRegexes[i] = regexes[i];\n }\n }\n return mergedRegexes;\n },\n enumerize = function (arr) {\n var enums = {};\n for (var i=0; i<arr.length; i++) {\n enums[arr[i].toUpperCase()] = arr[i];\n }\n return enums;\n },\n has = function (str1, str2) {\n return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;\n },\n lowerize = function (str) {\n return str.toLowerCase();\n },\n majorize = function (version) {\n return typeof(version) === STR_TYPE ? version.replace(/[^\\d\\.]/g, EMPTY).split('.')[0] : undefined;\n },\n trim = function (str, len) {\n if (typeof(str) === STR_TYPE) {\n str = str.replace(/^\\s\\s*/, EMPTY);\n return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);\n }\n };\n\n ///////////////\n // Map helper\n //////////////\n\n var rgxMapper = function (ua, arrays) {\n\n var i = 0, j, k, p, q, matches, match;\n\n // loop through all regexes maps\n while (i < arrays.length && !matches) {\n\n var regex = arrays[i], // even sequence (0,2,4,..)\n props = arrays[i + 1]; // odd sequence (1,3,5,..)\n j = k = 0;\n\n // try matching uastring with regexes\n while (j < regex.length && !matches) {\n\n if (!regex[j]) { break; }\n matches = regex[j++].exec(ua);\n\n if (!!matches) {\n for (p = 0; p < props.length; p++) {\n match = matches[++k];\n q = props[p];\n // check if given property is actually array\n if (typeof q === OBJ_TYPE && q.length > 0) {\n if (q.length === 2) {\n if (typeof q[1] == FUNC_TYPE) {\n // assign modified match\n this[q[0]] = q[1].call(this, match);\n } else {\n // assign given value, ignore regex match\n this[q[0]] = q[1];\n }\n } else if (q.length === 3) {\n // check whether function or regex\n if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {\n // call function (usually string mapper)\n this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;\n } else {\n // sanitize match using given regex\n this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;\n }\n } else if (q.length === 4) {\n this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;\n }\n } else {\n this[q] = match ? match : undefined;\n }\n }\n }\n }\n i += 2;\n }\n },\n\n strMapper = function (str, map) {\n\n for (var i in map) {\n // check if current value is array\n if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {\n for (var j = 0; j < map[i].length; j++) {\n if (has(map[i][j], str)) {\n return (i === UNKNOWN) ? undefined : i;\n }\n }\n } else if (has(map[i], str)) {\n return (i === UNKNOWN) ? undefined : i;\n }\n }\n return map.hasOwnProperty('*') ? map['*'] : str;\n };\n\n ///////////////\n // String map\n //////////////\n\n // Safari < 3.0\n var oldSafariMap = {\n '1.0' : '/8',\n '1.2' : '/1',\n '1.3' : '/3',\n '2.0' : '/412',\n '2.0.2' : '/416',\n '2.0.3' : '/417',\n '2.0.4' : '/419',\n '?' : '/'\n },\n windowsVersionMap = {\n 'ME' : '4.90',\n 'NT 3.11' : 'NT3.51',\n 'NT 4.0' : 'NT4.0',\n '2000' : 'NT 5.0',\n 'XP' : ['NT 5.1', 'NT 5.2'],\n 'Vista' : 'NT 6.0',\n '7' : 'NT 6.1',\n '8' : 'NT 6.2',\n '8.1' : 'NT 6.3',\n '10' : ['NT 6.4', 'NT 10.0'],\n 'RT' : 'ARM'\n };\n\n //////////////\n // Regex map\n /////////////\n\n var regexes = {\n\n browser : [[\n\n /\\b(?:crmo|crios)\\/([\\w\\.]+)/i // Chrome for Android/iOS\n ], [VERSION, [NAME, 'Chrome']], [\n /edg(?:e|ios|a)?\\/([\\w\\.]+)/i // Microsoft Edge\n ], [VERSION, [NAME, 'Edge']], [\n\n // Presto based\n /(opera mini)\\/([-\\w\\.]+)/i, // Opera Mini\n /(opera [mobiletab]{3,6})\\b.+version\\/([-\\w\\.]+)/i, // Opera Mobi/Tablet\n /(opera)(?:.+version\\/|[\\/ ]+)([\\w\\.]+)/i // Opera\n ], [NAME, VERSION], [\n /opios[\\/ ]+([\\w\\.]+)/i // Opera mini on iphone >= 8.0\n ], [VERSION, [NAME, OPERA+' Mini']], [\n /\\bop(?:rg)?x\\/([\\w\\.]+)/i // Opera GX\n ], [VERSION, [NAME, OPERA+' GX']], [\n /\\bopr\\/([\\w\\.]+)/i // Opera Webkit\n ], [VERSION, [NAME, OPERA]], [\n\n // Mixed\n /\\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\\/ ]?([\\w\\.]+)/i // Baidu\n ], [VERSION, [NAME, 'Baidu']], [\n /\\b(?:mxbrowser|mxios|myie2)\\/?([-\\w\\.]*)\\b/i // Maxthon\n ], [VERSION, [NAME, 'Maxthon']], [\n /(kindle)\\/([\\w\\.]+)/i, // Kindle\n /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\\/ ]?([\\w\\.]*)/i, \n // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir\n // Trident based\n /(avant|iemobile|slim(?:browser|boat|jet))[\\/ ]?([\\d\\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet\n /(?:ms|\\()(ie) ([\\w\\.]+)/i, // Internet Explorer\n\n // Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon\n /(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,\n // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon\n /(heytap|ovi|115)browser\\/([\\d\\.]+)/i, // HeyTap/Ovi/115\n /(weibo)__([\\d\\.]+)/i // Weibo\n ], [NAME, VERSION], [\n /quark(?:pc)?\\/([-\\w\\.]+)/i // Quark\n ], [VERSION, [NAME, 'Quark']], [\n /\\bddg\\/([\\w\\.]+)/i // DuckDuckGo\n ], [VERSION, [NAME, 'DuckDuckGo']], [\n /(?:\\buc? ?browser|(?:juc.+)ucweb)[\\/ ]?([\\w\\.]+)/i // UCBrowser\n ], [VERSION, [NAME, 'UC'+BROWSER]], [\n /microm.+\\bqbcore\\/([\\w\\.]+)/i, // WeChat Desktop for Windows Built-in Browser\n /\\bqbcore\\/([\\w\\.]+).+microm/i,\n /micromessenger\\/([\\w\\.]+)/i // WeChat\n ], [VERSION, [NAME, 'WeChat']], [\n /konqueror\\/([\\w\\.]+)/i // Konqueror\n ], [VERSION, [NAME, 'Konqueror']], [\n /trident.+rv[: ]([\\w\\.]{1,9})\\b.+like gecko/i // IE11\n ], [VERSION, [NAME, 'IE']], [\n /ya(?:search)?browser\\/([\\w\\.]+)/i // Yandex\n ], [VERSION, [NAME, 'Yandex']], [\n /slbrowser\\/([\\w\\.]+)/i // Smart Lenovo Browser\n ], [VERSION, [NAME, 'Smart Lenovo '+BROWSER]], [\n /(avast|avg)\\/([\\w\\.]+)/i // Avast/AVG Secure Browser\n ], [[NAME, /(.+)/, '$1 Secure '+BROWSER], VERSION], [\n /\\bfocus\\/([\\w\\.]+)/i // Firefox Focus\n ], [VERSION, [NAME, FIREFOX+' Focus']], [\n /\\bopt\\/([\\w\\.]+)/i // Opera Touch\n ], [VERSION, [NAME, OPERA+' Touch']], [\n /coc_coc\\w+\\/([\\w\\.]+)/i // Coc Coc Browser\n ], [VERSION, [NAME, 'Coc Coc']], [\n /dolfin\\/([\\w\\.]+)/i // Dolphin\n ], [VERSION, [NAME, 'Dolphin']], [\n /coast\\/([\\w\\.]+)/i // Opera Coast\n ], [VERSION, [NAME, OPERA+' Coast']], [\n /miuibrowser\\/([\\w\\.]+)/i // MIUI Browser\n ], [VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]], [\n /fxios\\/([\\w\\.-]+)/i // Firefox for iOS\n ], [VERSION, [NAME, FIREFOX]], [\n /\\bqihoobrowser\\/?([\\w\\.]*)/i // 360\n ], [VERSION, [NAME, '360']], [\n /\\b(qq)\\/([\\w\\.]+)/i // QQ\n ], [[NAME, /(.+)/, '$1Browser'], VERSION], [\n /(oculus|sailfish|huawei|vivo|pico)browser\\/([\\w\\.]+)/i\n ], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [ // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser\n /samsungbrowser\\/([\\w\\.]+)/i // Samsung Internet\n ], [VERSION, [NAME, SAMSUNG + ' Internet']], [\n /metasr[\\/ ]?([\\d\\.]+)/i // Sogou Explorer\n ], [VERSION, [NAME, 'Sogou Explorer']], [\n /(sogou)mo\\w+\\/([\\d\\.]+)/i // Sogou Mobile\n ], [[NAME, 'Sogou Mobile'], VERSION], [\n /(electron)\\/([\\w\\.]+) safari/i, // Electron-based App\n /(tesla)(?: qtcarbrowser|\\/(20\\d\\d\\.[-\\w\\.]+))/i, // Tesla\n /m?(qqbrowser|2345(?=browser|chrome|explorer))\\w*[\\/ ]?v?([\\w\\.]+)/i // QQ/2345\n ], [NAME, VERSION], [\n /(lbbrowser|rekonq)/i, // LieBao Browser/Rekonq\n /\\[(linkedin)app\\]/i // LinkedIn App for iOS & Android\n ], [NAME], [\n /ome\\/([\\w\\.]+) \\w* ?(iron) saf/i, // Iron\n /ome\\/([\\w\\.]+).+qihu (360)[es]e/i // 360\n ], [VERSION, NAME], [\n\n // WebView\n /((?:fban\\/fbios|fb_iab\\/fb4a)(?!.+fbav)|;fbav\\/([\\w\\.]+);)/i // Facebook App for iOS & Android\n ], [[NAME, FACEBOOK], VERSION], [\n /(Klarna)\\/([\\w\\.]+)/i, // Klarna Shopping Browser for iOS & Android\n /(kakao(?:talk|story))[\\/ ]([\\w\\.]+)/i, // Kakao App\n /(naver)\\(.*?(\\d+\\.[\\w\\.]+).*\\)/i, // Naver InApp\n /(daum)apps[\\/ ]([\\w\\.]+)/i, // Daum App\n /safari (line)\\/([\\w\\.]+)/i, // Line App for iOS\n /\\b(line)\\/([\\w\\.]+)\\/iab/i, // Line App for Android\n /(alipay)client\\/([\\w\\.]+)/i, // Alipay\n /(twitter)(?:and| f.+e\\/([\\w\\.]+))/i, // Twitter\n /(chromium|instagram|snapchat)[\\/ ]([-\\w\\.]+)/i // Chromium/Instagram/Snapchat\n ], [NAME, VERSION], [\n /\\bgsa\\/([\\w\\.]+) .*safari\\//i // Google Search Appliance on iOS\n ], [VERSION, [NAME, 'GSA']], [\n /musical_ly(?:.+app_?version\\/|_)([\\w\\.]+)/i // TikTok\n ], [VERSION, [NAME, 'TikTok']], [\n\n /headlesschrome(?:\\/([\\w\\.]+)| )/i // Chrome Headless\n ], [VERSION, [NAME, CHROME+' Headless']], [\n\n / wv\\).+(chrome)\\/([\\w\\.]+)/i // Chrome WebView\n ], [[NAME, CHROME+' WebView'], VERSION], [\n\n /droid.+ version\\/([\\w\\.]+)\\b.+(?:mobile safari|safari)/i // Android Browser\n ], [VERSION, [NAME, 'Android '+BROWSER]], [\n\n /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\\/v?([\\w\\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia\n ], [NAME, VERSION], [\n\n /version\\/([\\w\\.\\,]+) .*mobile\\/\\w+ (safari)/i // Mobile Safari\n ], [VERSION, [NAME, 'Mobile Safari']], [\n /version\\/([\\w(\\.|\\,)]+) .*(mobile ?safari|safari)/i // Safari & Safari Mobile\n ], [VERSION, NAME], [\n /webkit.+?(mobile ?safari|safari)(\\/[\\w\\.]+)/i // Safari < 3.0\n ], [NAME, [VERSION, strMapper, oldSafariMap]], [\n\n /(webkit|khtml)\\/([\\w\\.]+)/i\n ], [NAME, VERSION], [\n\n // Gecko based\n /(navigator|netscape\\d?)\\/([-\\w\\.]+)/i // Netscape\n ], [[NAME, 'Netscape'], VERSION], [\n /(wolvic|librewolf)\\/([\\w\\.]+)/i // Wolvic/LibreWolf\n ], [NAME, VERSION], [\n /mobile vr; rv:([\\w\\.]+)\\).+firefox/i // Firefox Reality\n ], [VERSION, [NAME, FIREFOX+' Reality']], [\n /ekiohf.+(flow)\\/([\\w\\.]+)/i, // Flow\n /(swiftfox)/i, // Swiftfox\n /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\\/ ]?([\\w\\.\\+]+)/i,\n // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror\n /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\\/([-\\w\\.]+)$/i,\n // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix\n /(firefox)\\/([\\w\\.]+)/i, // Other Firefox-based\n /(mozilla)\\/([\\w\\.]+) .+rv\\:.+gecko\\/\\d+/i, // Mozilla\n\n // Other\n /(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\\. ]?browser)[-\\/ ]?v?([\\w\\.]+)/i,\n // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser/Ladybird\n /\\b(links) \\(([\\w\\.]+)/i // Links\n ], [NAME, [VERSION, /_/g, '.']], [\n \n /(cobalt)\\/([\\w\\.]+)/i // Cobalt\n ], [NAME, [VERSION, /master.|lts./, \"\"]]\n ],\n\n cpu : [[\n\n /\\b((amd|x|x86[-_]?|wow|win)64)\\b/i // AMD64 (x64)\n ], [[ARCHITECTURE, 'amd64']], [\n\n /(ia32(?=;))/i, // IA32 (quicktime)\n /\\b((i[346]|x)86)(pc)?\\b/i // IA32 (x86)\n ], [[ARCHITECTURE, 'ia32']], [\n\n /\\b(aarch64|arm(v?[89]e?l?|_?64))\\b/i // ARM64\n ], [[ARCHITECTURE, 'arm64']], [\n\n /\\b(arm(v[67])?ht?n?[fl]p?)\\b/i // ARMHF\n ], [[ARCHITECTURE, 'armhf']], [\n\n // PocketPC mistakenly identified as PowerPC\n /( (ce|mobile); ppc;|\\/[\\w\\.]+arm\\b)/i\n ], [[ARCHITECTURE, 'arm']], [\n\n /((ppc|powerpc)(64)?)( mac|;|\\))/i // PowerPC\n ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [\n\n / sun4\\w[;\\)]/i // SPARC\n ], [[ARCHITECTURE, 'sparc']], [\n\n /\\b(avr32|ia64(?=;)|68k(?=\\))|\\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\\b|pa-risc)/i\n // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC\n ], [[ARCHITECTURE, lowerize]]\n ],\n\n device : [[\n\n //////////////////////////\n // MOBILES & TABLETS\n /////////////////////////\n\n // Samsung\n /\\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\n ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [\n /\\b((?:s[cgp]h|gt|sm)-(?![lr])\\w+|sc[g-]?[\\d]+a?|galaxy nexus)/i,\n /samsung[- ]((?!sm-[lr])[-\\w]+)/i,\n /sec-(sgh\\w+)/i\n ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [\n\n // Apple\n /(?:\\/|\\()(ip(?:hone|od)[\\w, ]*)(?:\\/|;)/i // iPod/iPhone\n ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [\n /\\((ipad);[-\\w\\),; ]+apple/i, // iPad\n /applecoremedia\\/[\\w\\.]+ \\((ipad)/i,\n /\\b(ipad)\\d\\d?,\\d\\d?[;\\]].+ios/i\n ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [\n /(macintosh);/i\n ], [MODEL, [VENDOR, APPLE]], [\n\n // Sharp\n /\\b(sh-?[altvz]?\\d\\d[a-ekm]?)/i\n ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [\n\n // Honor\n /\\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\\)|;)/i\n ], [MODEL, [VENDOR, HONOR], [TYPE, TABLET]], [\n /honor([-\\w ]+)[;\\)]/i\n ], [MODEL, [VENDOR, HONOR], [TYPE, MOBILE]], [\n\n // Huawei\n /\\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\n ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [\n /(?:huawei)([-\\w ]+)[;\\)]/i,\n /\\b(nexus 6p|\\w{2,4}e?-[atu]?[ln][\\dx][012359c][adn]?)\\b(?!.+d\\/s)/i\n ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [\n\n // Xiaomi\n /oid[^\\)]+; (2[\\dbc]{4}(182|283|rp\\w{2})[cgl]|m2105k81a?c)(?: bui|\\))/i,\n /\\b((?:red)?mi[-_ ]?pad[\\w- ]*)(?: bui|\\))/i // Mi Pad tablets\n ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [\n\n /\\b(poco[\\w ]+|m2\\d{3}j\\d\\d[a-z]{2})(?: bui|\\))/i, // Xiaomi POCO\n /\\b; (\\w+) build\\/hm\\1/i, // Xiaomi Hongmi 'numeric' models\n /\\b(hm[-_ ]?note?[_ ]?(?:\\d\\w)?) bui/i, // Xiaomi Hongmi\n /\\b(redmi[\\-_ ]?(?:note|k)?[\\w_ ]+)(?: bui|\\))/i, // Xiaomi Redmi\n /oid[^\\)]+; (m?[12][0-389][01]\\w{3,6}[c-y])( bui|; wv|\\))/i, // Xiaomi Redmi 'numeric' models\n /\\b(mi[-_ ]?(?:a\\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\\d?\\w?)[_ ]?(?:plus|se|lite|pro)?)(?: bui|\\))/i, // Xiaomi Mi\n / ([\\w ]+) miui\\/v?\\d/i\n ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [\n\n // OPPO\n /; (\\w+) bui.+ oppo/i,\n /\\b(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007|a101op)\\b/i\n ], [MODEL, [VENDOR, OPPO], [TYPE, MOBILE]], [\n /\\b(opd2(\\d{3}a?))(?: bui|\\))/i\n ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['304', '403', '203'], '*' : OPPO }], [TYPE, TABLET]], [\n\n // Vivo\n /vivo (\\w+)(?: bui|\\))/i,\n /\\b(v[12]\\d{3}\\w?[at])(?: bui|;)/i\n ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [\n\n // Realme\n /\\b(rmx[1-3]\\d{3})(?: bui|;|\\))/i\n ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [\n\n // Motorola\n /\\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\\b[\\w ]+build\\//i,\n /\\bmot(?:orola)?[- ](\\w*)/i,\n /((?:moto(?! 360)[\\w\\(\\) ]+|xt\\d{3,4}|nexus 6)(?= bui|\\)))/i\n ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [\n /\\b(mz60\\d|xoom[2 ]{0,2}) build\\//i\n ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [\n\n // LG\n /((?=lg)?[vl]k\\-?\\d{3}) bui| 3\\.[-\\w; ]{10}lg?-([06cv9]{3,4})/i\n ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [\n /(lm(?:-?f100[nv]?|-[\\w\\.]+)(?= bui|\\))|nexus [45])/i,\n /\\blg[-e;\\/ ]+((?!browser|netcast|android tv|watch)\\w+)/i,\n /\\blg-?([\\d\\w]+) bui/i\n ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [\n\n // Lenovo\n /(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,\n /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\\w- ]+?)|tb[\\w-]{6,7})( bui|;|\\)|\\/)/i\n ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [\n\n // Nokia\n /(nokia) (t[12][01])/i\n ], [VENDOR, MODEL, [TYPE, TABLET]], [\n /(?:maemo|nokia).*(n900|lumia \\d+|rm-\\d+)/i,\n /nokia[-_ ]?(([-\\w\\. ]*))/i\n ], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [\n\n // Google\n /(pixel (c|tablet))\\b/i // Google Pixel C/Tablet\n ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [\n /droid.+; (pixel[\\daxl ]{0,6})(?: bui|\\))/i // Google Pixel\n ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [\n\n // Sony\n /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\n ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [\n /sony tablet [ps]/i,\n /\\b(?:sony)?sgp\\w+(?: bui|\\))/i\n ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [\n\n // OnePlus\n / (kb2005|in20[12]5|be20[12][59])\\b/i,\n /(?:one)?(?:plus)? (a\\d0\\d\\d)(?: b|\\))/i\n ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [\n\n // Amazon\n /(alexa)webm/i,\n /(kf[a-z]{2}wi|aeo(?!bc)\\w\\w)( bui|\\))/i, // Kindle Fire without Silk / Echo Show\n /(kf[a-z]+)( bui|\\)).+silk\\//i // Kindle Fire HD\n ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [\n /((?:sd|kf)[0349hijorstuw]+)( bui|\\)).+silk\\//i // Fire Phone\n ], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [\n\n // BlackBerry\n /(playbook);[-\\w\\),; ]+(rim)/i // BlackBerry PlayBook\n ], [MODEL, VENDOR, [TYPE, TABLET]], [\n /\\b((?:bb[a-f]|st[hv])100-\\d)/i,\n /\\(bb10; (\\w+)/i // BlackBerry 10\n ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [\n\n // Asus\n /(?:\\b|asus_)(transfo[prime ]{4,10} \\w+|eeepc|slider \\w+|nexus 7|padfone|p00[cj])/i\n ], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [\n / (z[bes]6[027][012][km][ls]|zenfone \\d\\w?)\\b/i\n ], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [\n\n // HTC\n /(nexus 9)/i // HTC Nexus 9\n ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [\n /(htc)[-;_ ]{1,2}([\\w ]+(?=\\)| bui)|\\w+)/i, // HTC\n\n // ZTE\n /(zte)[- ]([\\w ]+?)(?: bui|\\/|\\))/i,\n /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\\.))|sony(?!-bra))[-_ ]?([-\\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony\n ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [\n\n // TCL\n /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\n ], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [\n\n // itel\n /(itel) ((\\w+))/i\n ], [[VENDOR, lowerize], MODEL, [TYPE, strMapper, { 'tablet' : ['p10001l', 'w7001'], '*' : 'mobile' }]], [\n\n // Acer\n /droid.+; ([ab][1-7]-?[0178a]\\d\\d?)/i\n ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [\n\n // Meizu\n /droid.+; (m[1-5] note) bui/i,\n /\\bmz-([-\\w]{2,})/i\n ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [\n \n // Ulefone\n /; ((?:power )?armor(?:[\\w ]{0,8}))(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [\n\n // Energizer\n /; (energy ?\\w+)(?: bui|\\))/i,\n /; energizer ([\\w ]+)(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]], [\n\n // Cat\n /; cat (b35);/i,\n /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]], [\n\n // Smartfren\n /((?:new )?andromax[\\w- ]+)(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [\n\n // Nothing\n /droid.+; (a(?:015|06[35]|142p?))/i\n ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [\n\n // Archos\n /; (x67 5g|tikeasy \\w+|ac[1789]\\d\\w+)( b|\\))/i,\n /archos ?(5|gamepad2?|([\\w ]*[t1789]|hello) ?\\d+[\\w ]*)( b|\\))/i\n ], [MODEL, [VENDOR, 'Archos'], [TYPE, TABLET]], [\n /archos ([\\w ]+)( b|\\))/i,\n /; (ac[3-6]\\d\\w{2,8})( b|\\))/i \n ], [MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]], [\n\n // MIXED\n /(imo) (tab \\w+)/i, // IMO\n /(infinix) (x1101b?)/i // Infinix XPad\n ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n /(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\\w]*)/i,\n // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan\n /; (hmd|imo) ([\\w ]+?)(?: bui|\\))/i, // HMD/IMO\n /(hp) ([\\w ]+\\w)/i, // HP iPAQ\n /(microsoft); (lumia[\\w ]+)/i, // Microsoft Lumia\n /(lenovo)[-_ ]?([-\\w ]+?)(?: bui|\\)|\\/)/i, // Lenovo\n /(oppo) ?([\\w ]+) bui/i // OPPO\n ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n\n /(kobo)\\s(ereader|touch)/i, // Kobo\n /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad\n /(kindle)\\/([\\w\\.]+)/i, // Kindle\n /(nook)[\\w ]+build\\/(\\w+)/i, // Nook\n /(dell) (strea[kpr\\d ]*[\\dko])/i, // Dell Streak\n /(le[- ]+pan)[- ]+(\\w{1,9}) bui/i, // Le Pan Tablets\n /(trinity)[- ]*(t\\d{3}) bui/i, // Trinity Tablets\n /(gigaset)[- ]+(q\\w{1,9}) bui/i, // Gigaset Tablets\n /(vodafone) ([\\w ]+)(?:\\)| bui)/i // Vodafone\n ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n /(surface duo)/i // Surface Duo\n ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [\n /droid [\\d\\.]+; (fp\\du?)(?: b|\\))/i // Fairphone\n ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [\n /(u304aa)/i // AT&T\n ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [\n /\\bsie-(\\w*)/i // Siemens\n ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [\n /\\b(rct\\w+) b/i // RCA Tablets\n ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [\n /\\b(venue[\\d ]{2,7}) b/i // Dell Venue Tablets\n ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [\n /\\b(q(?:mv|ta)\\w+) b/i // Verizon Tablet\n ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [\n /\\b(?:barnes[& ]+noble |bn[rt])([\\w\\+ ]*) b/i // Barnes & Noble Tablet\n ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [\n /\\b(tm\\d{3}\\w+) b/i\n ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [\n /\\b(k88) b/i // ZTE K Series Tablet\n ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [\n /\\b(nx\\d{3}j) b/i // ZTE Nubia\n ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [\n /\\b(gen\\d{3}) b.+49h/i // Swiss GEN Mobile\n ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [\n /\\b(zur\\d{3}) b/i // Swiss ZUR Tablet\n ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [\n /\\b((zeki)?tb.*\\b) b/i // Zeki Tablets\n ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [\n /\\b([yr]\\d{2}) b/i,\n /\\b(dragon[- ]+touch |dt)(\\w{5}) b/i // Dragon Touch Tablet\n ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [\n /\\b(ns-?\\w{0,9}) b/i // Insignia Tablets\n ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [\n /\\b((nxa|next)-?\\w{0,9}) b/i // NextBook Tablets\n ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [\n /\\b(xtreme\\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones\n ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [\n /\\b(lvtel\\-)?(v1[12]) b/i // LvTel Phones\n ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [\n /\\b(ph-1) /i // Essential PH-1\n ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [\n /\\b(v(100md|700na|7011|917g).*\\b) b/i // Envizen Tablets\n ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [\n /\\b(trio[-\\w\\. ]+) b/i // MachSpeed Tablets\n ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [\n /\\btu_(1491) b/i // Rotor Tablets\n ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [\n /((?:tegranote|shield t(?!.+d tv))[\\w- ]*?)(?: b|\\))/i // Nvidia Tablets\n ], [MODEL, [VENDOR, NVIDIA], [TYPE, TABLET]], [\n /(sprint) (\\w+)/i // Sprint Phones\n ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n /(kin\\.[onetw]{3})/i // Microsoft Kin\n ], [[MODEL, /\\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [\n /droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i // Zebra\n ], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [\n /droid.+; (ec30|ps20|tc[2-8]\\d[kx])\\)/i\n ], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [\n\n ///////////////////\n // SMARTTVS\n ///////////////////\n\n /smart-tv.+(samsung)/i // Samsung\n ], [VENDOR, [TYPE, SMARTTV]], [\n /hbbtv.+maple;(\\d+)/i\n ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [\n /(nux; netcast.+smarttv|lg (netcast\\.tv-201\\d|android tv))/i // LG SmartTV\n ], [[VENDOR, LG], [TYPE, SMARTTV]], [\n /(apple) ?tv/i // Apple TV\n ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [\n /crkey/i // Google Chromecast\n ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n /droid.+aft(\\w+)( bui|\\))/i // Fire TV\n ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [\n /(shield \\w+ tv)/i // Nvidia Shield TV\n ], [MODEL, [VENDOR, NVIDIA], [TYPE, SMARTTV]], [\n /\\(dtv[\\);].+(aquos)/i,\n /(aquos-tv[\\w ]+)\\)/i // Sharp\n ], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[\n /(bravia[\\w ]+)( bui|\\))/i // Sony\n ], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [\n /(mi(tv|box)-?\\w+) bui/i // Xiaomi\n ], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [\n /Hbbtv.*(technisat) (.*);/i // TechniSAT\n ], [VENDOR, MODEL, [TYPE, SMARTTV]], [\n /\\b(roku)[\\dx]*[\\)\\/]((?:dvp-)?[\\d\\.]*)/i, // Roku\n /hbbtv\\/\\d+\\.\\d+\\.\\d+ +\\([\\w\\+ ]*; *([\\w\\d][^;]*);([^;]*)/i // HbbTV devices\n ], [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]], [\n // SmartTV from Unidentified Vendors\n /droid.+; ([\\w- ]+) (?:android tv|smart[- ]?tv)/i\n ], [MODEL, [TYPE, SMARTTV]], [\n /\\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\\b/i\n ], [[TYPE, SMARTTV]], [\n\n ///////////////////\n // CONSOLES\n ///////////////////\n\n /(ouya)/i, // Ouya\n /(nintendo) ([wids3utch]+)/i // Nintendo\n ], [VENDOR, MODEL, [TYPE, CONSOLE]], [\n /droid.+; (shield)( bui|\\))/i // Nvidia Portable\n ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [\n /(playstation \\w+)/i // Playstation\n ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [\n /\\b(xbox(?: one)?(?!; xbox))[\\); ]/i // Microsoft Xbox\n ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [\n\n ///////////////////\n // WEARABLES\n ///////////////////\n\n /\\b(sm-[lr]\\d\\d[0156][fnuw]?s?|gear live)\\b/i // Samsung Galaxy Watch\n ], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [\n /((pebble))app/i, // Pebble\n /(asus|google|lg|oppo) ((pixel |zen)?watch[\\w ]*)( bui|\\))/i // Asus ZenWatch / LG Watch / Pixel Watch\n ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n /(ow(?:19|20)?we?[1-3]{1,3})/i // Oppo Watch\n ], [MODEL, [VENDOR, OPPO], [TYPE, WEARABLE]], [\n /(watch)(?: ?os[,\\/]|\\d,\\d\\/)[\\d\\.]+/i // Apple Watch\n ], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [\n /(opwwe\\d{3})/i // OnePlus Watch\n ], [MODEL, [VENDOR, ONEPLUS], [TYPE, WEARABLE]], [\n /(moto 360)/i // Motorola 360\n ], [MODEL, [VENDOR, MOTOROLA], [TYPE, WEARABLE]], [\n /(smartwatch 3)/i // Sony SmartWatch\n ], [MODEL, [VENDOR, SONY], [TYPE, WEARABLE]], [\n /(g watch r)/i // LG G Watch R\n ], [MODEL, [VENDOR, LG], [TYPE, WEARABLE]], [\n /droid.+; (wt63?0{2,3})\\)/i\n ], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [\n\n ///////////////////\n // XR\n ///////////////////\n\n /droid.+; (glass) \\d/i // Google Glass\n ], [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]], [\n /(pico) (4|neo3(?: link|pro)?)/i // Pico\n ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n /; (quest( \\d| pro)?)/i // Oculus Quest\n ], [MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]], [\n\n ///////////////////\n // EMBEDDED\n ///////////////////\n\n /(tesla)(?: qtcarbrowser|\\/[-\\w\\.]+)/i // Tesla\n ], [VENDOR, [TYPE, EMBEDDED]], [\n /(aeobc)\\b/i // Echo Dot\n ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [\n /(homepod).+mac os/i // Apple HomePod\n ], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [\n /windows iot/i\n ], [[TYPE, EMBEDDED]], [\n\n ////////////////////\n // MIXED (GENERIC)\n ///////////////////\n\n /droid .+?; ([^;]+?)(?: bui|; wv\\)|\\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors\n ], [MODEL, [TYPE, MOBILE]], [\n /droid .+?; ([^;]+?)(?: bui|\\) applew).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors\n ], [MODEL, [TYPE, TABLET]], [\n /\\b((tablet|tab)[;\\/]|focus\\/\\d(?!.+mobile))/i // Unidentifiable Tablet\n ], [[TYPE, TABLET]], [\n /(phone|mobile(?:[;\\/]| [ \\w\\/\\.]*safari)|pda(?=.+windows ce))/i // Unidentifiable Mobile\n ], [[TYPE, MOBILE]], [\n /droid .+?; ([\\w\\. -]+)( bui|\\))/i // Generic Android Device\n ], [MODEL, [VENDOR, 'Generic']]\n ],\n\n engine : [[\n\n /windows.+ edge\\/([\\w\\.]+)/i // EdgeHTML\n ], [VERSION, [NAME, EDGE+'HTML']], [\n\n /(arkweb)\\/([\\w\\.]+)/i // ArkWeb\n ], [NAME, VERSION], [\n\n /webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i // Blink\n ], [VERSION, [NAME, 'Blink']], [\n\n /(presto)\\/([\\w\\.]+)/i, // Presto\n /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\\/([\\w\\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo\n /ekioh(flow)\\/([\\w\\.]+)/i, // Flow\n /(khtml|tasman|links)[\\/ ]\\(?([\\w\\.]+)/i, // KHTML/Tasman/Links\n /(icab)[\\/ ]([23]\\.[\\d\\.]+)/i, // iCab\n\n /\\b(libweb)/i // LibWeb\n ], [NAME, VERSION], [\n /ladybird\\//i\n ], [[NAME, 'LibWeb']], [\n\n /rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i // Gecko\n ], [VERSION, NAME]\n ],\n\n os : [[\n\n // Windows\n /microsoft (windows) (vista|xp)/i // Windows (iTunes)\n ], [NAME, VERSION], [\n /(windows (?:phone(?: os)?|mobile|iot))[\\/ ]?([\\d\\.\\w ]*)/i // Windows Phone\n ], [NAME, [VERSION, strMapper, windowsVersionMap]], [\n /windows nt 6\\.2; (arm)/i, // Windows RT\n /windows[\\/ ]([ntce\\d\\. ]+\\w)(?!.+xbox)/i,\n /(?:win(?=3|9|n)|win 9x )([nt\\d\\.]+)/i\n ], [[VERSION, strMapper, windowsVersionMap], [NAME, 'Windows']], [\n\n // iOS/macOS\n /[adehimnop]{4,7}\\b(?:.*os ([\\w]+) like mac|; opera)/i, // iOS\n /(?:ios;fbsv\\/|iphone.+ios[\\/ ])([\\d\\.]+)/i,\n /cfnetwork\\/.+darwin/i\n ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [\n /(mac os x) ?([\\w\\. ]*)/i,\n /(macintosh|mac_powerpc\\b)(?!.+haiku)/i // Mac OS\n ], [[NAME, MAC_OS], [VERSION, /_/g, '.']], [\n\n // Mobile OSes\n /droid ([\\w\\.]+)\\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS\n ], [VERSION, NAME], [ \n /(ubuntu) ([\\w\\.]+) like android/i // Ubuntu Touch\n ], [[NAME, /(.+)/, '$1 Touch'], VERSION], [\n // Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen\n /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen|webos)\\w*[-\\/; ]?([\\d\\.]*)/i\n ], [NAME, VERSION], [\n /\\(bb(10);/i // BlackBerry 10\n ], [VERSION, [NAME, BLACKBERRY]], [\n /(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\\/ ]?([\\w\\.]*)/i // Symbian\n ], [VERSION, [NAME, 'Symbian']], [\n /mozilla\\/[\\d\\.]+ \\((?:mobile|tablet|tv|mobile; [\\w ]+); rv:.+ gecko\\/([\\w\\.]+)/i // Firefox OS\n ], [VERSION, [NAME, FIREFOX+' OS']], [\n /web0s;.+rt(tv)/i,\n /\\b(?:hp)?wos(?:browser)?\\/([\\w\\.]+)/i // WebOS\n ], [VERSION, [NAME, 'webOS']], [\n /watch(?: ?os[,\\/]|\\d,\\d\\/)([\\d\\.]+)/i // watchOS\n ], [VERSION, [NAME, 'watchOS']], [\n\n // Google Chromecast\n /crkey\\/([\\d\\.]+)/i // Google Chromecast\n ], [VERSION, [NAME, CHROME+'cast']], [\n /(cros) [\\w]+(?:\\)| ([\\w\\.]+)\\b)/i // Chromium OS\n ], [[NAME, CHROMIUM_OS], VERSION],[\n\n // Smart TVs\n /panasonic;(viera)/i, // Panasonic Viera\n /(netrange)mmh/i, // Netrange\n /(nettv)\\/(\\d+\\.[\\w\\.]+)/i, // NetTV\n\n // Console\n /(nintendo|playstation) ([wids345portablevuch]+)/i, // Nintendo/Playstation\n /(xbox); +xbox ([^\\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)\n\n // Other\n /\\b(joli|palm)\\b ?(?:os)?\\/?([\\w\\.]*)/i, // Joli/Palm\n /(mint)[\\/\\(\\) ]?(\\w*)/i, // Mint\n /(mageia|vectorlinux)[; ]/i, // Mageia/VectorLinux\n /([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,\n // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire\n /(hurd|linux)(?: arm\\w*| x86\\w*| ?)([\\w\\.]*)/i, // Hurd/Linux\n /(gnu) ?([\\w\\.]*)/i, // GNU\n /\\b([-frentopcghs]{0,5}bsd|dragonfly)[\\/ ]?(?!amd|[ix346]{1,2}86)([\\w\\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly\n /(haiku) (\\w+)/i // Haiku\n ], [NAME, VERSION], [\n /(sunos) ?([\\w\\.\\d]*)/i // Solaris\n ], [[NAME, 'Solaris'], VERSION], [\n /((?:open)?solaris)[-\\/ ]?([\\w\\.]*)/i, // Solaris\n /(aix) ((\\d)(?=\\.|\\)| )[\\w\\.])*/i, // AIX\n /\\b(beos|os\\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS\n /(unix) ?([\\w\\.]*)/i // UNIX\n ], [NAME, VERSION]\n ]\n };\n\n /////////////////\n // Constructor\n ////////////////\n\n var UAParser = function (ua, extensions) {\n\n if (typeof ua === OBJ_TYPE) {\n extensions = ua;\n ua = undefined;\n }\n\n if (!(this instanceof UAParser)) {\n return new UAParser(ua, extensions).getResult();\n }\n\n var _navigator = (typeof window !== UNDEF_TYPE && window.navigator) ? window.navigator : undefined;\n var _ua = ua || ((_navigator && _navigator.userAgent) ? _navigator.userAgent : EMPTY);\n var _uach = (_navigator && _navigator.userAgentData) ? _navigator.userAgentData : undefined;\n var _rgxmap = extensions ? extend(regexes, extensions) : regexes;\n var _isSelfNav = _navigator && _navigator.userAgent == _ua;\n\n this.getBrowser = function () {\n var _browser = {};\n _browser[NAME] = undefined;\n _browser[VERSION] = undefined;\n rgxMapper.call(_browser, _ua, _rgxmap.browser);\n _browser[MAJOR] = majorize(_browser[VERSION]);\n // Brave-specific detection\n if (_isSelfNav && _navigator && _navigator.brave && typeof _navigator.brave.isBrave == FUNC_TYPE) {\n _browser[NAME] = 'Brave';\n }\n return _browser;\n };\n this.getCPU = function () {\n var _cpu = {};\n _cpu[ARCHITECTURE] = undefined;\n rgxMapper.call(_cpu, _ua, _rgxmap.cpu);\n return _cpu;\n };\n this.getDevice = function () {\n var _device = {};\n _device[VENDOR] = undefined;\n _device[MODEL] = undefined;\n _device[TYPE] = undefined;\n rgxMapper.call(_device, _ua, _rgxmap.device);\n if (_isSelfNav && !_device[TYPE] && _uach && _uach.mobile) {\n _device[TYPE] = MOBILE;\n }\n // iPadOS-specific detection: identified as Mac, but has some iOS-only properties\n if (_isSelfNav && _device[MODEL] == 'Macintosh' && _navigator && typeof _navigator.standalone !== UNDEF_TYPE && _navigator.maxTouchPoints && _navigator.maxTouchPoints > 2) {\n _device[MODEL] = 'iPad';\n _device[TYPE] = TABLET;\n }\n return _device;\n };\n this.getEngine = function () {\n var _engine = {};\n _engine[NAME] = undefined;\n _engine[VERSION] = undefined;\n rgxMapper.call(_engine, _ua, _rgxmap.engine);\n return _engine;\n };\n this.getOS = function () {\n var _os = {};\n _os[NAME] = undefined;\n _os[VERSION] = undefined;\n rgxMapper.call(_os, _ua, _rgxmap.os);\n if (_isSelfNav && !_os[NAME] && _uach && _uach.platform && _uach.platform != 'Unknown') {\n _os[NAME] = _uach.platform \n .replace(/chrome os/i, CHROMIUM_OS)\n .replace(/macos/i, MAC_OS); // backward compatibility\n }\n return _os;\n };\n this.getResult = function () {\n return {\n ua : this.getUA(),\n browser : this.getBrowser(),\n engine : this.getEngine(),\n os : this.getOS(),\n device : this.getDevice(),\n cpu : this.getCPU()\n };\n };\n this.getUA = function () {\n return _ua;\n };\n this.setUA = function (ua) {\n _ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? trim(ua, UA_MAX_LENGTH) : ua;\n return this;\n };\n this.setUA(_ua);\n return this;\n };\n\n UAParser.VERSION = LIBVERSION;\n UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]);\n UAParser.CPU = enumerize([ARCHITECTURE]);\n UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);\n UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);\n\n ///////////\n // Export\n //////////\n\n // check js environment\n if (typeof(exports) !== UNDEF_TYPE) {\n // nodejs env\n if (typeof module !== UNDEF_TYPE && module.exports) {\n exports = module.exports = UAParser;\n }\n exports.UAParser = UAParser;\n } else {\n // requirejs env (optional)\n if (typeof(define) === FUNC_TYPE && define.amd) {\n define(function () {\n return UAParser;\n });\n } else if (typeof window !== UNDEF_TYPE) {\n // browser env\n window.UAParser = UAParser;\n }\n }\n\n // jQuery/Zepto specific (optional)\n // Note:\n // In AMD env the global scope should be kept clean, but jQuery is an exception.\n // jQuery always exports to global scope, unless jQuery.noConflict(true) is used,\n // and we should catch that.\n var $ = typeof window !== UNDEF_TYPE && (window.jQuery || window.Zepto);\n if ($ && !$.ua) {\n var parser = new UAParser();\n $.ua = parser.getResult();\n $.ua.get = function () {\n return parser.getUA();\n };\n $.ua.set = function (ua) {\n parser.setUA(ua);\n var result = parser.getResult();\n for (var prop in result) {\n $.ua[prop] = result[prop];\n }\n };\n }\n\n})(typeof window === 'object' ? window : this);\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","// 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 // Content test types\n ContentChange,\n ContentElement,\n ContentBlock,\n ContentCustomCode,\n ContentTestData,\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// Internal utilities (exported for advanced use cases)\nexport { hashString } 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 canAssignToTest,\n assignAllTests,\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// Split URL utilities\nexport {\n getSplitUrlBlockingScript,\n processSplitUrlTests,\n} from \"./handlers/splitUrl\";\nexport type { SplitUrlScriptOptions } from \"./handlers/splitUrl\";\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// Content test utilities\nexport {\n matchesWildcardPattern,\n applyContentChanges,\n applyContentElements,\n applyCustomCode,\n processContentTests,\n reprocessContentTests,\n setupContentTestListeners,\n hasContentTests,\n restoreOriginalElements,\n cleanupContentTests,\n} from \"./utils/content\";\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\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\";\nexport { ElevateAnalytics } from \"./components/ElevateAnalytics\";\nexport type {\n UseAnalyticsHook,\n ElevateHydrogenAnalyticsProps,\n} from \"./components/ElevateAnalytics\";\n\nexport { useElevateConfig } from \"./contexts/ElevateContext\";\n\nexport type {\n TestTypeHandler,\n HandlerContext,\n HandlerVariantData,\n} from \"./handlers/types\";\nexport {\n registerHandler,\n getHandler,\n getAllHandlers,\n hasHandler,\n} from \"./handlers/registry\";\n\n// Handlers\nexport { contentHandler } from \"./handlers/content\";\n\nexport const VERSION = \"1.1.2\";\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 * 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","import type { Test, Variation, ElevateConfig } from \"../types\";\nimport type { PreviewState } from \"../utils/preview\";\nimport { getAssignedVariant } from \"../utils/assignment\";\nimport { getCookie, setCookie, getJsonCookie } from \"../utils/storage\";\nimport { onNavigate } from \"../utils/navigation\";\n\nexport interface SplitUrlScriptOptions {\n configUrl: string;\n timeout?: number;\n}\n\nexport function getSplitUrlBlockingScript(\n options: SplitUrlScriptOptions\n): string {\n const { configUrl, timeout = 2000 } = options;\n\n return `(function(){\n if(new URLSearchParams(location.search).get('abtr')==='true')return;\n \n var style=document.createElement('style');\n style.id='eab-split-hide';\n style.textContent='body{opacity:0!important;visibility:hidden!important}';\n document.head.appendChild(style);\n \n window.__eab_reveal=function(){\n var s=document.getElementById('eab-split-hide');\n if(s)s.remove();\n window.__eab_reveal=null;\n };\n \n setTimeout(function(){\n if(window.__eab_reveal)window.__eab_reveal();\n },${timeout});\n \n if(window.eab_data){\n return;\n }\n \n var script=document.createElement('script');\n script.src='${configUrl}';\n script.onerror=function(){\n if(window.__eab_reveal)window.__eab_reveal();\n };\n document.head.appendChild(script);\n})();`;\n}\n\nfunction normalizeUrl(url: string): string {\n if (!url?.trim()) return \"\";\n\n try {\n const withoutProtocol = url.trim().replace(/^https?:\\/\\//, \"\");\n const withProtocol = `https://${withoutProtocol}`;\n const urlObj = new URL(withProtocol.replace(/\\/+$/, \"\"));\n\n if (urlObj.hostname.startsWith(\"www.\")) {\n urlObj.hostname = urlObj.hostname.substring(4);\n }\n\n return urlObj.toString().replace(/\\/+$/, \"\");\n } catch {\n return url.trim().replace(/\\/+$/, \"\");\n }\n}\n\nfunction urlMatches(currentUrl: string, urlList: string[]): boolean {\n const normalizedCurrent = normalizeUrl(currentUrl.split(\"?\")[0]);\n\n for (const url of urlList) {\n const normalizedTarget = normalizeUrl(url.split(\"?\")[0]);\n if (normalizedCurrent === normalizedTarget) {\n return true;\n }\n // Also check pathname match for same-origin URLs\n try {\n const currentPath = new URL(currentUrl).pathname;\n const targetPath = new URL(url, currentUrl).pathname;\n if (currentPath === targetPath) {\n return true;\n }\n } catch {\n // Ignore URL parse errors\n }\n }\n return false;\n}\n\ntype RedirectBehavior =\n | \"redirectAll\"\n | \"redirectOnlyControlUrl\"\n | \"redirectOnce\"\n | \"redirectOnceControlUrlOnly\";\n\nfunction getRedirectBehavior(test: Test): RedirectBehavior {\n return (\n ((test as any).data?.redirectBehavior as RedirectBehavior) || \"redirectAll\"\n );\n}\n\nfunction hasBeenRedirected(testId: string): boolean {\n const redirectedTests =\n getJsonCookie<Record<string, boolean>>(\"eabRedirectedTests\") || {};\n return !!redirectedTests[testId];\n}\n\nfunction markAsRedirected(testId: string): void {\n const redirectedTests =\n getJsonCookie<Record<string, boolean>>(\"eabRedirectedTests\") || {};\n redirectedTests[testId] = true;\n setCookie(\"eabRedirectedTests\", JSON.stringify(redirectedTests));\n}\n\n/**\n * Find SPLIT_URL test that matches current URL\n */\nfunction findMatchingSplitUrlTest(\n config: ElevateConfig,\n currentUrl: string\n): { test: Test; matchedVariation: Variation; isControlUrl: boolean } | null {\n for (const test of config.tests) {\n if (test.type !== \"SPLIT_URL\" || !test.enabled) continue;\n\n for (const variation of test.variations) {\n const urls = (variation as any).splitUrlTestLinks || [];\n if (urls.length === 0) continue;\n\n if (urlMatches(currentUrl, urls)) {\n return {\n test,\n matchedVariation: variation,\n isControlUrl: !!variation.isControl,\n };\n }\n }\n }\n return null;\n}\n\n/**\n * Perform redirect using appropriate method for SPA frameworks\n */\nfunction performRedirect(targetUrl: string): void {\n if (typeof window === \"undefined\") return;\n\n // Add abtr=true param to prevent redirect loops\n const url = new URL(targetUrl, window.location.origin);\n url.searchParams.set(\"abtr\", \"true\");\n const finalUrl = url.toString();\n\n // Try SPA navigation first (Remix, Next.js, Nuxt)\n const navigate =\n (window as any).__remixRouter?.navigate ??\n (window as any).next?.router?.push ??\n (window as any).$nuxt?.$router?.push ??\n (window as any).__navigate;\n\n if (navigate && typeof navigate === \"function\") {\n try {\n const pathname = url.pathname + url.search;\n navigate(pathname);\n return;\n } catch {\n // Fall through to hard redirect\n }\n }\n\n // Hard redirect as fallback\n window.location.href = finalUrl;\n}\n\n/**\n * Process Split URL tests and redirect if needed\n * This is called automatically from ElevateProvider on mount.\n *\n * @returns true if a redirect was triggered, false otherwise\n */\nexport function processSplitUrlTests(\n config: ElevateConfig,\n previewState?: PreviewState | null | undefined\n): boolean {\n if (typeof window === \"undefined\") return false;\n\n const currentUrl = window.location.href;\n\n // Check if already redirected (abtr param present)\n const urlParams = new URLSearchParams(window.location.search);\n if (urlParams.get(\"abtr\") === \"true\") {\n return false;\n }\n\n // Find matching Split URL test\n const match = findMatchingSplitUrlTest(config, currentUrl);\n if (!match) return false;\n\n const { test, matchedVariation, isControlUrl } = match;\n const testId = test.testId;\n const redirectBehavior = getRedirectBehavior(test);\n\n const assignedVariationId = getAssignedVariant(testId);\n if (!assignedVariationId) return false;\n\n const assignedVariation = test.variations.find(\n (v) => v.id === assignedVariationId\n );\n if (!assignedVariation) return false;\n\n // Get target URLs for assigned variation\n const targetUrls = (assignedVariation as any).splitUrlTestLinks || [];\n if (targetUrls.length === 0) return false;\n\n // Check if already on assigned variation's URL\n if (urlMatches(currentUrl, targetUrls)) {\n return false; // Already on correct URL\n }\n\n // Apply redirect behavior rules\n switch (redirectBehavior) {\n case \"redirectOnlyControlUrl\":\n // Only redirect when on control URL\n if (!isControlUrl) return false;\n if (assignedVariation.isControl) return false; // Assigned to control, no redirect needed\n break;\n\n case \"redirectOnce\":\n // Redirect once from any URL\n if (hasBeenRedirected(testId)) return false;\n markAsRedirected(testId);\n break;\n\n case \"redirectOnceControlUrlOnly\":\n // Redirect once, but only from control URL\n if (!isControlUrl) return false;\n if (hasBeenRedirected(testId)) return false;\n if (assignedVariation.isControl) return false;\n markAsRedirected(testId);\n break;\n\n case \"redirectAll\":\n default:\n // Always redirect to assigned variation URL\n break;\n }\n\n // Perform the redirect\n const targetUrl = targetUrls[0];\n performRedirect(targetUrl);\n return true;\n}\n\n/**\n * Check if there are any active split URL tests\n */\nexport function hasSplitUrlTests(config: ElevateConfig): boolean {\n return config.tests.some((t) => t.type === \"SPLIT_URL\" && t.enabled);\n}\n\n/**\n * Setup event listeners for split URL test re-processing.\n *\n * Listens for ALL SPA navigation (pushState, replaceState, popstate)\n * and re-checks whether a redirect is needed on the new URL.\n */\nexport function setupSplitUrlTestListeners(\n config: ElevateConfig,\n previewState?: PreviewState | null\n): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n // Handle ALL SPA navigation (pushState, replaceState, popstate)\n const cleanupNavigation = onNavigate(() => {\n processSplitUrlTests(config, previewState);\n });\n\n return () => {\n cleanupNavigation();\n };\n}\n\nexport const splitUrlHandler = {\n type: \"SPLIT_URL\",\n\n shouldActivate(test: Test, context: { currentUrl: string }): boolean {\n for (const variation of test.variations) {\n const urls = (variation as any).splitUrlTestLinks || [];\n if (urlMatches(context.currentUrl, urls)) {\n return true;\n }\n }\n return false;\n },\n\n getVariantData() {\n return { handlerActivated: true };\n },\n};\n","/**\n * SPA Navigation Listener Utility\n *\n * Detects ALL client-side navigation in SPAs including:\n * - history.pushState() — link clicks handled by SPA routers\n * - history.replaceState() — in-place URL changes\n * - popstate — browser back/forward buttons\n *\n * The native `popstate` event only fires on back/forward navigation.\n * SPA routers (React Router, Remix, Next.js, etc.) navigate via\n * history.pushState(), which does NOT fire `popstate`.\n *\n * This utility monkey-patches pushState/replaceState to dispatch\n * a custom `eab:navigate` event, giving us a single event to\n * listen for ALL navigation types.\n */\n\nconst NAVIGATE_EVENT = \"eab:navigate\";\n\nlet patched = false;\nlet patchRefCount = 0;\nlet originalPushState: typeof history.pushState | null = null;\nlet originalReplaceState: typeof history.replaceState | null = null;\n\n/**\n * Patch history.pushState and history.replaceState to dispatch\n * a custom navigation event. Uses reference counting so multiple\n * callers can install/uninstall independently.\n */\nfunction patchHistory(): void {\n if (typeof window === \"undefined\") return;\n\n patchRefCount++;\n if (patched) return;\n patched = true;\n\n originalPushState = history.pushState.bind(history);\n originalReplaceState = history.replaceState.bind(history);\n\n history.pushState = function (...args: Parameters<typeof history.pushState>) {\n originalPushState!(...args);\n window.dispatchEvent(new Event(NAVIGATE_EVENT));\n };\n\n history.replaceState = function (\n ...args: Parameters<typeof history.replaceState>\n ) {\n originalReplaceState!(...args);\n window.dispatchEvent(new Event(NAVIGATE_EVENT));\n };\n}\n\n/**\n * Restore original history methods when no more listeners need them.\n */\nfunction unpatchHistory(): void {\n if (typeof window === \"undefined\") return;\n\n patchRefCount--;\n if (patchRefCount > 0 || !patched) return;\n\n if (originalPushState) {\n history.pushState = originalPushState;\n originalPushState = null;\n }\n if (originalReplaceState) {\n history.replaceState = originalReplaceState;\n originalReplaceState = null;\n }\n patched = false;\n}\n\n/**\n * Subscribe to ALL SPA navigation events (pushState, replaceState, popstate).\n *\n * The callback receives no arguments — the caller should read\n * `window.location` to determine the new URL.\n *\n * Returns a cleanup function that removes all listeners.\n *\n * @example\n * ```ts\n * const cleanup = onNavigate(() => {\n * // handle route change\n * });\n * // Later:\n * cleanup();\n * ```\n */\nexport function onNavigate(callback: () => void): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n // Keep track of the last URL to avoid duplicate calls\n // (e.g. replaceState to the same URL)\n let lastUrl = window.location.href;\n\n const handler = () => {\n const currentUrl = window.location.href;\n if (currentUrl === lastUrl) return;\n lastUrl = currentUrl;\n callback();\n };\n\n patchHistory();\n\n window.addEventListener(NAVIGATE_EVENT, handler);\n window.addEventListener(\"popstate\", handler);\n\n return () => {\n window.removeEventListener(NAVIGATE_EVENT, handler);\n window.removeEventListener(\"popstate\", handler);\n unpatchHistory();\n };\n}\n","/**\n * Analytics utilities for parsing and extracting data from events\n */\n\nimport { UAParser } from \"ua-parser-js\";\n\n// URL source mappings\nconst urlSources: Record<string, string> = {\n \"facebook.com\": \"Facebook\",\n \"fb.me\": \"Facebook\",\n \"m.facebook.com\": \"Facebook\",\n \"l.facebook.com\": \"Facebook\",\n \"lm.facebook.com\": \"Facebook\",\n \"instagram.com\": \"Instagram\",\n \"l.instagram.com\": \"Instagram\",\n \"youtube.com\": \"Youtube\",\n \"youtu.be\": \"Youtube\",\n \"m.youtube.com\": \"Youtube\",\n \"bing.com\": \"Bing\",\n \"www.bing.com\": \"Bing\",\n \"msnbc.msn.com\": \"Bing\",\n \"dizionario.it.msn.com\": \"Bing\",\n \"cc.bingj.com\": \"Bing\",\n \"m.bing.com\": \"Bing\",\n \"twitter.com\": \"Twitter\",\n \"t.co\": \"Twitter\",\n};\n\n/**\n * Sanitize string values to prevent XSS\n */\nexport function sanitizeString(value: unknown): string {\n if (typeof value !== \"string\") return String(value);\n return value.replace(/[\\\\\"'`\\x00-\\x1F\\x7F]/g, \"\");\n}\n\n/**\n * Round number to 2 decimal places\n */\nexport function roundToTwo(value: unknown): number | null {\n if (value === null || value === undefined) {\n return null;\n }\n const num = typeof value === \"string\" ? parseFloat(value) : Number(value);\n\n if (isNaN(num)) {\n return null;\n }\n return Number(Math.round(Number(num + \"e2\")) + \"e-2\");\n}\n\n/**\n * Extract product ID from Shopify GID\n */\nexport function extractProductId(gid: string | undefined): string | null {\n if (!gid) return null;\n const regex = /gid:\\/\\/shopify\\/Product\\/(\\d+)/;\n const match = gid.match(regex);\n return match ? match[1] : null;\n}\n\n/**\n * Extract product variant ID from Shopify GID\n */\nexport function extractProductVariantId(\n gid: string | undefined\n): string | null {\n if (!gid) return null;\n const regex = /gid:\\/\\/shopify\\/ProductVariant\\/(\\d+)/;\n const match = gid.match(regex);\n return match ? match[1] : null;\n}\n\n/**\n * Extract cart token from Shopify GID\n */\nexport function extractCartToken(\n gid: string | undefined | null\n): string | null {\n if (!gid) return null;\n const regex = /gid:\\/\\/shopify\\/Cart\\/([^?]+(\\?.+)?)/;\n const match = gid.match(regex);\n return match ? match[1] : null;\n}\n\n/**\n * Clean cart token by removing query parameters\n */\nexport function cleanCartToken(\n cartToken: string | null | undefined\n): string | null {\n try {\n if (typeof cartToken !== \"string\") {\n return null;\n }\n const decodedToken = decodeURIComponent(cartToken);\n const tokenPart = decodedToken.split(\"?\")[0];\n return tokenPart;\n } catch {\n // Silently fail - cart token extraction is not critical\n return cartToken || null;\n }\n}\n\n/**\n * Check if Facebook in-app browser\n */\nexport function checkFacebookBrowser(userAgent: string): boolean {\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(userAgent: string): boolean {\n const instagramBrowserRegex = /(instagram)[\\/ ]([-\\w\\.]+)/i;\n return instagramBrowserRegex.test(userAgent);\n}\n\n/**\n * Check if Facebook or Instagram browser\n */\nexport function checkFacebookInstagramBrowser(userAgent: string): boolean {\n return checkFacebookBrowser(userAgent) || checkInstagramBrowser(userAgent);\n}\n\n/**\n * Get browser name from UA parser result\n */\nfunction getBrowserName(browser: string | undefined): string {\n if (!browser) {\n return \"\";\n }\n switch (browser) {\n case \"Mobile Safari\":\n return \"Safari\";\n case \"Chrome Mobile\":\n case \"Chrome Mobile iOS\":\n return \"Chrome\";\n case \"Firefox Mobile\":\n case \"Firefox Mobile iOS\":\n return \"Firefox\";\n case \"Opera Mobile\":\n case \"Opera Mini\":\n case \"Opera Mini iOS\":\n return \"Opera\";\n case \"Yandex Browser Lite\":\n return \"Yandex Browser\";\n case \"Chrome Webview\":\n case \"Mobile App\":\n return \"Mobile App\";\n default:\n return browser;\n }\n}\n\n/**\n * Extract query parameters from URL\n */\nfunction getQueryParams(parsedUrl: URL): Record<string, string> {\n const queryParams: Record<string, string> = {};\n\n parsedUrl.searchParams.forEach((value, key) => {\n if (!queryParams[key]) {\n queryParams[key] = value;\n }\n });\n\n return queryParams;\n}\n\n/**\n * Check if referrer URI is valid\n */\nfunction isValidReferrerURI(uri: URL): boolean {\n return !!uri.host && [\"http:\", \"https:\"].includes(uri.protocol);\n}\n\n/**\n * Extract referrer source from hostname\n */\nfunction extractReferrerSource(host: string): string {\n return host.replace(/^www\\./, \"\");\n}\n\n/**\n * Parse referrer to determine traffic source\n */\nfunction parseReferrer(\n referrer: string | undefined,\n browser: string,\n siteHostname: string | undefined\n): string {\n const browserObj: Record<string, string> = {\n Facebook: \"Facebook\",\n Instagram: \"Instagram\",\n };\n if (browser && browserObj[browser]) {\n return browser;\n }\n\n let referrerObj: URL | undefined;\n let host: string | undefined;\n try {\n if (referrer && referrer.trim() !== '') {\n referrerObj = new URL(referrer);\n } else {\n return \"Direct\";\n }\n if (referrerObj?.hostname && isValidReferrerURI(referrerObj)) {\n host = referrerObj.hostname;\n if (siteHostname && siteHostname === host) {\n return \"Direct\";\n }\n } else {\n return \"\";\n }\n } catch {\n // Silently handle invalid referrer URLs\n }\n if (!host) {\n return \"\";\n }\n const source = extractReferrerSource(host);\n if (!source) {\n return \"\";\n }\n if (urlSources[source]) {\n return urlSources[source];\n }\n if (source?.includes(\"google\")) {\n return \"Google\";\n }\n return source;\n}\n\n/**\n * Parse and extract analytics view data from referrer, entry page, and user agent\n */\nexport interface ParsedViewData {\n referrer_source: string;\n browser_info: string;\n os_info: string;\n device_type: string;\n page_entry_path: string;\n utm_medium: string;\n utm_source: string;\n utm_campaign: string;\n utm_content: string;\n utm_term: string;\n referrer_url: string;\n gclid: string;\n fbclid: string;\n pins_campaign_id: string;\n epik: string;\n}\n\nexport function parseAddViewData(params: {\n referrer?: string;\n entryPage?: string;\n userAgent?: string;\n}): ParsedViewData {\n const { referrer, entryPage, userAgent } = params;\n\n const data: ParsedViewData = {\n referrer_source: \"\",\n browser_info: \"\",\n os_info: \"\",\n device_type: \"\",\n page_entry_path: \"\",\n utm_medium: \"\",\n utm_source: \"\",\n utm_campaign: \"\",\n utm_content: \"\",\n utm_term: \"\",\n referrer_url: referrer || \"\",\n gclid: \"\",\n fbclid: \"\",\n pins_campaign_id: \"\",\n epik: \"\",\n };\n\n try {\n let siteHostname: string | undefined;\n if (entryPage && entryPage.trim() !== '' && entryPage.startsWith('http')) {\n try {\n const entryObj = new URL(entryPage);\n const entryPath = entryObj?.pathname;\n siteHostname = entryObj?.hostname;\n if (entryPath) {\n data.page_entry_path = entryPath ?? \"\";\n }\n const entryQueryParams = getQueryParams(entryObj);\n data.utm_medium = entryQueryParams[\"utm_medium\"] ?? \"\";\n data.utm_source = entryQueryParams[\"utm_source\"] ?? \"\";\n data.utm_campaign = entryQueryParams[\"utm_campaign\"] ?? \"\";\n data.utm_content = entryQueryParams[\"utm_content\"] ?? \"\";\n data.utm_term = entryQueryParams[\"utm_term\"] ?? \"\";\n data.gclid = entryQueryParams[\"gclid\"] ?? \"\";\n data.fbclid = entryQueryParams[\"fbclid\"] ?? \"\";\n data.pins_campaign_id = entryQueryParams[\"pins_campaign_id\"] ?? \"\";\n data.epik = entryQueryParams[\"epik\"] ?? \"\";\n } catch {\n // Silently handle invalid URLs - entry page might be invalid in some contexts\n }\n }\n\n if (userAgent) {\n const userAgentObj = UAParser(userAgent);\n const browser = userAgentObj?.browser?.name;\n const browserName = getBrowserName(browser);\n data.browser_info = browserName ?? \"\";\n data.os_info = userAgentObj?.os?.name ?? \"\";\n if (userAgent) {\n data.device_type =\n (userAgentObj?.device?.type || \"desktop\")?.toUpperCase() ?? \"\";\n }\n }\n\n data.referrer_source =\n parseReferrer(referrer, data?.browser_info, siteHostname) ?? \"\";\n return data;\n } catch {\n // Return partial data on parse error\n return data;\n }\n}\n\n/**\n * Get page type from pathname\n */\nexport function getPageTypeFromPathname(\n path: string,\n hasLocalizedPaths?: boolean\n): string {\n const hasNormalPath = path === \"/\" || path === \"\";\n\n // Check if this is a localized homepage (e.g., /en-us/, /fr-ca/)\n const localizedHomepagePattern = /^\\/[a-z]{2}(-[a-z]{2})?\\/?$/i;\n const isLocalizedHomepage =\n hasLocalizedPaths && localizedHomepagePattern.test(path);\n\n if (hasNormalPath || isLocalizedHomepage) {\n return \"index\";\n }\n\n if (/\\/products\\//.test(path)) {\n return \"product\";\n }\n\n if (/\\/collections\\//.test(path)) {\n return \"collection\";\n }\n\n if (/\\/pages\\//.test(path)) {\n return \"page\";\n }\n if (/\\/search/.test(path)) {\n return \"search\";\n }\n\n if (/\\/cart/.test(path)) {\n return \"cart\";\n }\n\n if (/\\/checkouts\\//.test(path)) {\n return \"checkout\";\n }\n\n return \"unknown\";\n}\n\n/**\n * Check if visitor ID is in URL params\n */\nexport function checkVisitorIdParams(searchParams: string): string | false {\n try {\n if (!searchParams) return false;\n const params = new URLSearchParams(searchParams);\n return params.get(\"eabUserId\") || false;\n } catch {\n // URL parsing failed, return false\n return false;\n }\n}\n\n/**\n * Get user agent string without browser info\n * Used for more consistent user fingerprinting\n */\nexport function getUserAgentNoBrowser(userAgent: string): string {\n if (!userAgent) return \"\";\n\n try {\n const userAgentObj = UAParser(userAgent);\n const os = userAgentObj?.os;\n const device = userAgentObj?.device;\n\n let result = \"\";\n if (os?.name) {\n result += os.name;\n if (os.version) result += ` ${os.version}`;\n }\n if (device?.type) {\n result += result ? ` (${device.type})` : device.type;\n }\n if (device?.vendor) {\n result += result ? ` ${device.vendor}` : device.vendor;\n }\n if (device?.model) {\n result += result ? ` ${device.model}` : device.model;\n }\n\n return result || userAgent;\n } catch {\n return userAgent;\n }\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 * Content Test Utilities\n *\n * Handles DOM manipulation for Content Tests (Visual Editor Experiments).\n * Automatically applies changes, injects elements, and runs custom code\n * based on the assigned variant's content configuration.\n */\n\nimport type {\n ContentChange,\n ContentElement,\n ContentCustomCode,\n ContentTestData,\n ElevateConfig,\n Test,\n Variation,\n} from \"../types\";\nimport type { PreviewState } from \"./preview\";\nimport { getAssignedVariant } from \"./assignment\";\nimport { onNavigate } from \"./navigation\";\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst ELEMENT_ID_PREFIX = \"elv-el-\";\nconst NODE_TYPES = {\n ELEMENT_NODE: 1,\n TEXT_NODE: 3,\n};\n\n// ============================================================================\n// STATE MANAGEMENT\n// ============================================================================\n\n/** Tracks original elements for restoration on responsive changes */\nconst originalElements: Map<string, HTMLElement> = new Map();\n\n/** Tracks injected style elements for cleanup */\nconst injectedStyles: Map<string, HTMLStyleElement> = new Map();\n\n/** Tracks injected script elements for cleanup */\nconst injectedScripts: Map<string, HTMLScriptElement> = new Map();\n\n/** Tracks injected content elements for cleanup */\nconst injectedElements: Map<string, HTMLElement> = new Map();\n\n/** Current device type (for responsive changes) */\nlet isMobile = false;\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Check if a pathname matches a wildcard pattern\n * Supports: \"*\" (all), \"*\\/products\\/*\" (contains), \"*.json\" (ends with)\n */\nexport function matchesWildcardPattern(\n pathname: string,\n pattern: string\n): boolean {\n // Match all\n if (pattern === \"*\") return true;\n\n // Contains pattern: *something*\n if (pattern.startsWith(\"*\") && pattern.endsWith(\"*\")) {\n const trimmedPattern = pattern.slice(1, -1);\n return pathname.includes(trimmedPattern);\n }\n\n // Ends with pattern: *something\n if (pattern.startsWith(\"*\")) {\n const suffix = pattern.slice(1);\n return pathname.endsWith(suffix);\n }\n\n // Exact match\n return pattern === pathname;\n}\n\n/**\n * Check if current device is mobile (viewport width < 768px)\n */\nfunction checkIsMobile(): boolean {\n if (typeof window === \"undefined\") return false;\n return window.innerWidth < 768;\n}\n\n/**\n * Convert camelCase to kebab-case for CSS properties\n */\nfunction convertToKebabCase(text: string): string {\n let result = \"\";\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n if (char >= \"A\" && char <= \"Z\") {\n if (i !== 0) result += \"-\";\n result += char.toLowerCase();\n } else {\n result += char;\n }\n }\n return result;\n}\n\n/**\n * Check if a node is a text node\n */\nfunction isTextNode(node: Node): boolean {\n return node.nodeType === NODE_TYPES.TEXT_NODE;\n}\n\n/**\n * Check if a node is an element node\n */\nfunction isElementNode(node: Node): node is HTMLElement {\n return node.nodeType === NODE_TYPES.ELEMENT_NODE;\n}\n\n/**\n * Store original element for later restoration\n */\nfunction storeOriginalElement(selector: string, element: HTMLElement): void {\n if (!originalElements.has(selector)) {\n originalElements.set(selector, element.cloneNode(true) as HTMLElement);\n }\n}\n\n/**\n * Decode escaped characters in code strings\n */\nfunction decodeCodeString(code: string): string {\n let decoded = code;\n\n // Replace HTML entities (using replace with regex for ES2020 compatibility)\n decoded = decoded.replace(/`/g, \"`\").replace(/$/g, \"$\");\n\n // Try JSON decode for escaped characters\n try {\n decoded = JSON.parse('\"' + decoded + '\"');\n } catch {\n // If JSON.parse fails, use the partially decoded version\n }\n\n return decoded;\n}\n\n// ============================================================================\n// CONTENT CHANGES (Text, Styles, Attributes)\n// ============================================================================\n\n/**\n * Apply content changes to existing elements\n */\nexport function applyContentChanges(changes: ContentChange[]): void {\n if (typeof window === \"undefined\" || changes.length === 0) return;\n\n const currentPathname = window.location.pathname;\n\n // Filter changes that match current pathname\n const matchingChanges = changes.filter((change) => {\n if (!change.pathnames?.length) return true;\n return change.pathnames.some((pathname) =>\n matchesWildcardPattern(currentPathname, pathname)\n );\n });\n\n // Detect mobile/desktop\n isMobile = checkIsMobile();\n\n // Process each change with responsive support\n const processedChanges = matchingChanges.map((change) => ({\n ...change,\n // Merge responsive styles (lg + sm if mobile)\n style: change.style\n ? { ...change.style.lg, ...(isMobile && change.style.sm) }\n : undefined,\n // Select responsive content\n content:\n change.content && isMobile && change.content.sm\n ? change.content.sm\n : change.content?.lg,\n }));\n\n // Apply text content changes\n processedChanges\n .filter((change) => change.content !== undefined)\n .forEach((change) => {\n const elements = change.applyAll\n ? Array.from(document.querySelectorAll(change.selector))\n : [document.querySelector(change.selector)].filter(Boolean);\n\n elements.forEach((element, index) => {\n if (!element) return;\n\n const uniqueSelector = change.applyAll\n ? `${change.selector}-${index}-${\n element.id || Math.random().toString(36).substr(2, 9)\n }`\n : change.selector;\n\n storeOriginalElement(uniqueSelector, element as HTMLElement);\n\n // Apply content\n if (isTextNode(element)) {\n (element as unknown as Text).nodeValue = change.content!;\n } else if (isElementNode(element)) {\n element.innerHTML = change.content!;\n }\n });\n });\n\n // Apply style changes\n processedChanges\n .filter((change) => change.style !== undefined)\n .forEach((change) => {\n const element = document.querySelector(change.selector) as HTMLElement;\n if (!element || !isElementNode(element)) return;\n\n storeOriginalElement(change.selector, element);\n\n Object.entries(change.style!).forEach(([prop, value]) => {\n const kebabProp = convertToKebabCase(prop);\n const hasImportant = value.toString().includes(\"!important\");\n const cleanValue = value.toString().replace(/\\s*!important\\s*$/, \"\");\n\n element.style.setProperty(\n kebabProp,\n cleanValue,\n hasImportant ? \"important\" : undefined\n );\n });\n });\n\n // Apply attribute changes\n processedChanges\n .filter((change) => change.attributes !== undefined)\n .forEach((change) => {\n const element = document.querySelector(change.selector) as HTMLElement;\n if (!element || !isElementNode(element)) return;\n\n storeOriginalElement(change.selector, element);\n\n Object.entries(change.attributes!).forEach(([key, value]) => {\n element.setAttribute(key, value);\n });\n });\n}\n\n// ============================================================================\n// CONTENT ELEMENTS (HTML Injection)\n// ============================================================================\n\n/**\n * Apply content elements (inject new HTML elements)\n */\nexport function applyContentElements(elements: ContentElement[]): void {\n if (typeof window === \"undefined\" || elements.length === 0) return;\n\n const currentPathname = window.location.pathname;\n\n // Filter elements that match current pathname\n const matchingElements = elements.filter((element) => {\n if (!element.selector?.pathnames?.length) return true;\n return element.selector.pathnames.some((pathname) =>\n matchesWildcardPattern(currentPathname, pathname)\n );\n });\n\n matchingElements.forEach((element) => {\n const elementId = `${ELEMENT_ID_PREFIX}${element.id}`;\n\n const trackedElement = injectedElements.get(elementId);\n if (trackedElement && !document.contains(trackedElement)) {\n injectedElements.delete(elementId);\n }\n\n // Skip if already injected\n if (injectedElements.has(elementId)) return;\n\n const target = document.querySelector(element.selector.target);\n if (!target) return;\n\n // Check if element already exists in DOM\n if (target.parentElement?.querySelector(`#${elementId}`)) return;\n\n // Create the DOM element\n const domElement = createDOMElement(element);\n\n // Insert based on placement\n if (element.selector.placement === \"after\") {\n target.after(domElement);\n } else if (element.selector.placement === \"before\") {\n target.before(domElement);\n }\n\n // Track for cleanup\n injectedElements.set(elementId, domElement);\n });\n}\n\n/**\n * Create a DOM element from ContentElement definition\n */\nfunction createDOMElement(element: ContentElement): HTMLElement {\n const domElement = document.createElement(element.tagName);\n\n domElement.id = `${ELEMENT_ID_PREFIX}${element.id}`;\n\n // Apply styles\n if (element.style) {\n Object.assign(domElement.style, element.style);\n }\n\n // Apply attributes\n if (element.attributes) {\n Object.entries(element.attributes).forEach(([key, value]) => {\n domElement.setAttribute(key, value);\n });\n }\n\n // Set content for text elements\n if (element.kind === \"text\" && element.content) {\n domElement.innerText = element.content;\n }\n\n // Recursively render children for containers\n if (element.kind === \"container\" && element.childrens) {\n element.childrens.forEach((child) => {\n const childElement = createDOMElement(child);\n domElement.appendChild(childElement);\n });\n }\n\n return domElement;\n}\n\n// ============================================================================\n// CUSTOM CODE (CSS/JS Injection)\n// ============================================================================\n\n/**\n * Apply custom code (CSS and JS injection)\n */\nexport function applyCustomCode(\n customCodes: ContentCustomCode[],\n nonce?: string\n): void {\n if (typeof window === \"undefined\" || customCodes.length === 0) return;\n\n const currentPathname = window.location.pathname;\n\n // Filter codes that match current pathname\n const matchingCodes = customCodes.filter((code) => {\n // If no pathnames specified, run on all pages\n if (!code.pathnames?.length) return true;\n\n // Check excludes first\n if (code.excludePathnames?.length) {\n const isExcluded = code.excludePathnames.some((pathname) =>\n matchesWildcardPattern(currentPathname, pathname)\n );\n if (isExcluded) return false;\n }\n\n // Check includes\n return code.pathnames.some((pathname) =>\n matchesWildcardPattern(currentPathname, pathname)\n );\n });\n\n matchingCodes.forEach((code) => {\n if (!code.id) return;\n\n // Inject CSS\n if (code.css) {\n injectCSS(code.id, code.css);\n }\n\n // Inject JS\n if (code.js) {\n injectJS(code.id, code.js, nonce);\n }\n });\n}\n\n/**\n * Inject CSS into the page\n */\nfunction injectCSS(id: string, css: string): void {\n const styleId = `css-${id}`;\n\n const trackedStyle = injectedStyles.get(styleId);\n if (trackedStyle && !document.contains(trackedStyle)) {\n injectedStyles.delete(styleId);\n }\n\n if (injectedStyles.has(styleId) || document.getElementById(styleId)) return;\n\n const styleElement = document.createElement(\"style\");\n styleElement.id = styleId;\n styleElement.textContent = decodeCodeString(css);\n\n document.head.appendChild(styleElement);\n injectedStyles.set(styleId, styleElement);\n}\n\n/**\n * Inject JavaScript into the page\n */\nfunction injectJS(id: string, js: string, nonce?: string): void {\n const scriptId = `js-${id}`;\n\n const trackedScript = injectedScripts.get(scriptId);\n if (trackedScript && !document.contains(trackedScript)) {\n injectedScripts.delete(scriptId);\n }\n\n if (injectedScripts.has(scriptId) || document.getElementById(scriptId)) return;\n\n const scriptElement = document.createElement(\"script\");\n scriptElement.id = scriptId;\n\n // Add nonce for CSP compliance\n if (nonce) {\n scriptElement.setAttribute(\"nonce\", nonce);\n }\n\n // Wrap in try-catch for safety\n const decodedJs = decodeCodeString(js);\n scriptElement.textContent =\n \"(function(){try{\" +\n decodedJs +\n \"}catch(e){console.error('[ElevateAB] Custom script error:', e)}})();\";\n\n document.head.appendChild(scriptElement);\n injectedScripts.set(scriptId, scriptElement);\n}\n\n// ============================================================================\n// CLEANUP FUNCTIONS\n// ============================================================================\n\n/**\n * Restore original elements (for responsive changes or cleanup)\n */\nexport function restoreOriginalElements(): void {\n originalElements.forEach((originalElement, selector) => {\n // Try to find the element by selector\n const target = document.querySelector(selector);\n if (target) {\n target.replaceWith(originalElement.cloneNode(true));\n }\n });\n}\n\n/**\n * Clean up all injected content\n */\nexport function cleanupContentTests(): void {\n // Remove injected styles\n injectedStyles.forEach((style) => style.remove());\n injectedStyles.clear();\n\n // Remove injected scripts\n injectedScripts.forEach((script) => script.remove());\n injectedScripts.clear();\n\n // Remove injected elements\n injectedElements.forEach((element) => element.remove());\n injectedElements.clear();\n\n // Clear original elements cache\n originalElements.clear();\n}\n\n// ============================================================================\n// MAIN PROCESSOR\n// ============================================================================\n\n/**\n * Collect all content test data from assigned variants\n */\nfunction collectContentTestData(\n config: ElevateConfig,\n previewState?: PreviewState | null\n): ContentTestData {\n const allChanges: ContentChange[] = [];\n const allElements: ContentElement[] = [];\n const allCustomCodes: ContentCustomCode[] = [];\n\n // Find all CONTENT type tests\n const contentTests = config.tests.filter(\n (test) => test.type === \"CONTENT\" && test.enabled\n );\n\n contentTests.forEach((test) => {\n const assignedVariantId = getAssignedVariant(test.testId);\n if (!assignedVariantId) return;\n\n const variation = test.variations.find((v) => v.id === assignedVariantId);\n if (!variation?.content) return;\n\n // Collect content data\n if (variation.content.changes?.length) {\n allChanges.push(...variation.content.changes);\n }\n if (variation.content.elements?.length) {\n allElements.push(...variation.content.elements);\n }\n if (variation.content.customCodes?.length) {\n allCustomCodes.push(...variation.content.customCodes);\n }\n });\n\n return {\n changes: allChanges,\n elements: allElements,\n blocks: [], // Blocks deferred to v2\n customCodes: allCustomCodes,\n };\n}\n\n/**\n * Check if there are any active content tests\n */\nexport function hasContentTests(config: ElevateConfig): boolean {\n return config.tests.some((test) => test.type === \"CONTENT\" && test.enabled);\n}\n\n/**\n * Process and apply all content tests\n * This is the main entry point called by ElevateProvider\n */\nexport function processContentTests(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string\n): void {\n if (typeof window === \"undefined\") return;\n\n // Check if there are any content tests\n if (!hasContentTests(config)) return;\n\n // Collect all content data from assigned variants\n const contentData = collectContentTestData(config, previewState);\n\n // Check if there's anything to apply\n const hasContent =\n contentData.changes.length > 0 ||\n contentData.elements.length > 0 ||\n contentData.customCodes.length > 0;\n\n if (!hasContent) return;\n\n // Apply content changes\n applyContentChanges(contentData.changes);\n applyContentElements(contentData.elements);\n applyCustomCode(contentData.customCodes, nonce);\n}\n\n/**\n * Re-process content tests (called on pathname change or resize)\n */\nexport function reprocessContentTests(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string\n): void {\n if (typeof window === \"undefined\") return;\n\n // Check for responsive change\n const currentIsMobile = checkIsMobile();\n if (currentIsMobile !== isMobile) {\n // Responsive change - restore and reapply\n restoreOriginalElements();\n isMobile = currentIsMobile;\n }\n\n // Re-process content tests\n processContentTests(config, previewState, nonce);\n}\n\n/**\n * Setup event listeners for content test re-processing.\n *\n * Listens for ALL SPA navigation (pushState, replaceState, popstate)\n * via the shared navigation utility, plus resize for responsive changes.\n */\nexport function setupContentTestListeners(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string,\n listenToNavigation = true\n): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n // Handle resize for responsive changes\n const handleResize = () => {\n const currentIsMobile = checkIsMobile();\n if (currentIsMobile !== isMobile) {\n reprocessContentTests(config, previewState, nonce);\n }\n };\n\n window.addEventListener(\"resize\", handleResize);\n\n let cleanupNavigation = () => {};\n if (listenToNavigation) {\n // Handle ALL SPA navigation (pushState, replaceState, popstate)\n cleanupNavigation = onNavigate(() => {\n reprocessContentTests(config, previewState, nonce);\n });\n }\n\n // Return cleanup function\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n cleanupNavigation();\n cleanupContentTests();\n };\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 { getAssignedVariant } from \"../utils/assignment\";\nimport { trackViews } from \"../utils/tracking\";\nimport { getPreviewState } from \"../utils/preview\";\nimport { getHandler } from \"../handlers/registry\";\nimport type { HandlerContext } from \"../handlers/types\";\n\n// Import handlers to trigger auto-registration\nimport \"../handlers\";\n\nexport interface UseExperimentResult {\n /** The full variant object with handler data (null if not assigned) */\n variant: (Variation & Record<string, unknown>) | 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 * Build handler context from current environment\n */\nfunction buildHandlerContext(selectors?: unknown): HandlerContext {\n if (typeof window === \"undefined\") {\n return { currentUrl: \"\", selectors };\n }\n\n const url = window.location.href;\n const pathname = window.location.pathname;\n\n // Extract product info from URL\n let productHandle: string | undefined;\n const productMatch = pathname.match(/\\/products\\/([^\\/\\?]+)/);\n if (productMatch) {\n productHandle = productMatch[1];\n }\n\n // Try to detect variant ID from URL params\n let variantId: string | undefined;\n const urlParams = new URLSearchParams(window.location.search);\n const variantParam = urlParams.get(\"variant\");\n if (variantParam) {\n variantId = variantParam;\n }\n\n return {\n currentUrl: url,\n productHandle,\n variantId,\n selectors,\n currencyCode: \"USD\", // Default, could be detected from page\n };\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 {\n config,\n previewState: contextPreviewState,\n selectors,\n } = useElevateConfig();\n const [variant, setVariant] = React.useState<\n (Variation & Record<string, unknown>) | null\n >(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 // Get preview state - use context or get fresh\n const previewState = React.useMemo(() => {\n return contextPreviewState || getPreviewState();\n }, [contextPreviewState]);\n\n // Track if we've already warned about this test (prevent duplicate warnings)\n const hasWarnedRef = React.useRef<string | null>(null);\n // Track if effect has been applied (prevent duplicate DOM updates)\n const effectAppliedRef = React.useRef<string | null>(null);\n\n React.useEffect(() => {\n let isMounted = true;\n\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 if (isMounted) setIsLoading(false);\n return;\n }\n\n // Test exists but is disabled (but allow preview mode to override)\n if (!testConfig.enabled && !previewState?.isPreview) {\n if (hasWarnedRef.current !== `${testId}-disabled`) {\n hasWarnedRef.current = `${testId}-disabled`;\n console.warn(`[ElevateAB] Test disabled: ${testId}`);\n }\n if (isMounted) setIsLoading(false);\n return;\n }\n\n const assignedVariantId = getAssignedVariant(testId);\n if (!assignedVariantId) {\n if (isMounted) setIsLoading(false);\n return;\n }\n\n const assigned = testConfig.variations.find(\n (v) => v.id === assignedVariantId\n );\n if (!assigned) {\n if (isMounted) setIsLoading(false);\n return;\n }\n\n const handler = getHandler(testConfig.type);\n const context = buildHandlerContext(selectors);\n\n let enrichedVariant: Variation & Record<string, unknown> = {\n ...assigned,\n };\n\n if (handler?.shouldActivate(testConfig, context)) {\n const effectKey = `${testId}-${assigned.id}`;\n if (handler.applyEffect && effectAppliedRef.current !== effectKey) {\n effectAppliedRef.current = effectKey;\n handler.applyEffect(testConfig, assigned, context);\n }\n\n const handlerData = handler.getVariantData(testConfig, assigned, context);\n enrichedVariant = { ...enrichedVariant, ...handlerData };\n }\n\n if (isMounted) setVariant(enrichedVariant);\n\n if (!previewState?.isPreview) {\n trackViews(testId);\n }\n\n if (isMounted) setIsLoading(false);\n\n return () => {\n isMounted = false;\n };\n }, [config, testConfig, testId, previewState, selectors]);\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 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 type { TestTypeHandler } from \"./types\";\n\nconst handlers: Map<string, TestTypeHandler> = new Map();\n\nexport function registerHandler(handler: TestTypeHandler): void {\n handlers.set(handler.type, handler);\n}\n\nexport function getHandler(type: string): TestTypeHandler | undefined {\n return handlers.get(type);\n}\n\nexport function getAllHandlers(): TestTypeHandler[] {\n return Array.from(handlers.values());\n}\n\nexport function hasHandler(type: string): boolean {\n return handlers.has(type);\n}\n","\nimport type { Test, Variation } from \"../types\";\nimport type {\n TestTypeHandler,\n HandlerContext,\n HandlerVariantData,\n} from \"./types\";\n\nfunction extractProductHandleFromUrl(url: string): string | null {\n try {\n const urlObj = new URL(url, \"https://example.com\");\n const pathname = urlObj.pathname;\n\n // Match /products/{handle}\n const match = pathname.match(/\\/products\\/([^\\/\\?]+)/);\n return match ? match[1] : null;\n } catch {\n return null;\n }\n}\n\nfunction updatePriceElements(\n variation: Variation,\n variantId: string | undefined,\n currencyCode: string,\n selectors: unknown,\n): void {\n if (typeof window === \"undefined\") return;\n if (!variation.prices || !variantId) return;\n\n const variantPrices = variation.prices[variantId];\n if (!variantPrices) return;\n\n const priceAmount = variantPrices.price?.[currencyCode];\n const compareAmount = variantPrices.compare?.[currencyCode];\n\n // Get selectors configuration\n const selectorsConfig = selectors as {\n selectorsV2?: Array<{\n price?: string;\n compareAt?: string;\n saving?: Array<{ selector: string; isPercentage?: boolean }>;\n }>;\n };\n\n if (!selectorsConfig?.selectorsV2?.length) return;\n\n // Update each selector set\n for (const selectorSet of selectorsConfig.selectorsV2) {\n // Update price elements\n if (selectorSet.price && priceAmount) {\n const priceSelector = selectorSet.price.replace(\n \"{{variant}}\",\n variantId,\n );\n const priceElements = document.querySelectorAll(priceSelector);\n priceElements.forEach((el) => {\n // Format price with currency\n const formattedPrice = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: currencyCode,\n }).format(parseFloat(priceAmount));\n el.textContent = formattedPrice;\n });\n }\n\n // Update compare-at price elements\n if (selectorSet.compareAt && compareAmount) {\n const compareSelector = selectorSet.compareAt.replace(\n \"{{variant}}\",\n variantId,\n );\n const compareElements = document.querySelectorAll(compareSelector);\n compareElements.forEach((el) => {\n const formattedPrice = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: currencyCode,\n }).format(parseFloat(compareAmount));\n el.textContent = formattedPrice;\n });\n }\n\n // Update saving elements\n if (selectorSet.saving && priceAmount && compareAmount) {\n for (const savingConfig of selectorSet.saving) {\n const savingSelector = savingConfig.selector.replace(\n \"{{variant}}\",\n variantId,\n );\n const savingElements = document.querySelectorAll(savingSelector);\n savingElements.forEach((el) => {\n const price = parseFloat(priceAmount);\n const compare = parseFloat(compareAmount);\n const saving = compare - price;\n\n if (savingConfig.isPercentage) {\n const percentage = Math.round((saving / compare) * 100);\n el.textContent = `${percentage}%`;\n } else {\n const formattedSaving = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: currencyCode,\n }).format(saving);\n el.textContent = formattedSaving;\n }\n });\n }\n }\n }\n}\n\nexport const pricePlusHandler: TestTypeHandler = {\n type: \"PRICE_PLUS\",\n\n shouldActivate(test: Test, context: HandlerContext): boolean {\n const testData = (test as any).data;\n if (!testData) return false;\n\n // Get product identifiers from context\n const { productId, productHandle } = context;\n\n // Auto-detect from URL if not provided\n const urlHandle =\n productHandle || extractProductHandleFromUrl(context.currentUrl);\n\n // Check if this product matches the test\n const matchesProductId =\n productId && testData.productIds?.includes(productId);\n const matchesHandle = urlHandle && testData.handles?.includes(urlHandle);\n\n return matchesProductId || matchesHandle;\n },\n\n applyEffect(\n test: Test,\n variation: Variation,\n context: HandlerContext,\n ): void {\n // Update DOM elements using selectors\n updatePriceElements(\n variation,\n context.variantId,\n context.currencyCode || \"USD\",\n context.selectors,\n );\n },\n\n getVariantData(\n test: Test,\n variation: Variation,\n context: HandlerContext,\n ): HandlerVariantData {\n const testData = (test as any).data;\n\n // Return prices for manual rendering\n return {\n prices: variation.prices,\n matchedProductId: context.productId,\n productIds: testData?.productIds,\n handles: testData?.handles,\n handlerActivated: true,\n };\n },\n};\n","/**\n * Content Test Handler\n *\n * Handles CONTENT type tests (Visual Editor Experiments).\n * These tests modify page content without redirects - they can:\n * - Remove/hide elements\n * - Modify text/headings/descriptions\n * - Change CSS styles (colors, fonts, sizes)\n * - Add new HTML elements\n * - Modify attributes (href, src, etc.)\n * - Inject custom CSS/JS\n */\n\nimport type { Test, Variation } from \"../types\";\nimport type {\n TestTypeHandler,\n HandlerContext,\n HandlerVariantData,\n} from \"./types\";\nimport { matchesWildcardPattern } from \"../utils/content\";\n\n/**\n * Check if current URL matches any of the test's pathnames\n */\nfunction matchesTestPathnames(test: Test, currentUrl: string): boolean {\n const testData = (test as any).data;\n const pathnames: string[] = testData?.pathnames || [];\n\n // If no pathnames specified, match all pages\n if (!pathnames.length) return true;\n\n try {\n const url = new URL(currentUrl, \"https://example.com\");\n const pathname = url.pathname;\n\n // Check if any pathname pattern matches\n return pathnames.some((pattern) =>\n matchesWildcardPattern(pathname, pattern)\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Content test handler\n *\n * Note: Content test effects are applied by processContentTests in ElevateProvider,\n * not through the handler's applyEffect. This ensures all content tests are\n * processed together after variant assignment for better coordination.\n */\nexport const contentHandler: TestTypeHandler = {\n type: \"CONTENT\",\n\n shouldActivate(test: Test, context: HandlerContext): boolean {\n return matchesTestPathnames(test, context.currentUrl);\n },\n\n getVariantData(\n test: Test,\n variation: Variation,\n _context: HandlerContext\n ): HandlerVariantData {\n const testData = (test as any).data;\n\n return {\n content: variation.content,\n pathnames: testData?.pathnames,\n handlerActivated: true,\n };\n },\n};\n","/**\n * Custom Code Test Handler\n *\n * Handles CUSTOM_CODE type tests.\n * These tests inject custom CSS/JS into the page based on pathname matching.\n * Both control and non-control variations can have custom code.\n */\n\nimport type { Test, Variation } from \"../types\";\nimport type {\n TestTypeHandler,\n HandlerContext,\n HandlerVariantData,\n} from \"./types\";\nimport { matchesWildcardPattern } from \"../utils/content\";\n\n/**\n * Check if current URL matches any of the test's pathnames\n */\nfunction matchesTestPathnames(test: Test, currentUrl: string): boolean {\n const testData = (test as any).data;\n const pathnames: string[] = testData?.pathnames || [];\n\n // If no pathnames specified, match all pages\n if (!pathnames.length) return true;\n\n try {\n const url = new URL(currentUrl, \"https://example.com\");\n const pathname = url.pathname;\n\n // Check if any pathname pattern matches\n return pathnames.some((pattern) =>\n matchesWildcardPattern(pathname, pattern)\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Custom code test handler\n *\n * Note: Custom code effects are applied by processCustomCodeTests in ElevateProvider,\n * not through the handler's applyEffect. This ensures all custom code tests are\n * processed together after variant assignment for better coordination.\n */\nexport const customCodeHandler: TestTypeHandler = {\n type: \"CUSTOM_CODE\",\n\n shouldActivate(test: Test, context: HandlerContext): boolean {\n return matchesTestPathnames(test, context.currentUrl);\n },\n\n getVariantData(\n test: Test,\n variation: Variation,\n _context: HandlerContext\n ): HandlerVariantData {\n const testData = (test as any).data;\n\n return {\n customCode: variation.customCode,\n pathnames: testData?.pathnames,\n excludePathnames: testData?.excludePathnames,\n handlerActivated: true,\n };\n },\n};\n","export type {\n TestTypeHandler,\n HandlerContext,\n HandlerVariantData,\n} from \"./types\";\n\nexport {\n registerHandler,\n getHandler,\n getAllHandlers,\n hasHandler,\n} from \"./registry\";\n\nexport { pricePlusHandler } from \"./pricePlus\";\nexport { splitUrlHandler, processSplitUrlTests } from \"./splitUrl\";\nexport { contentHandler } from \"./content\";\nexport { customCodeHandler } from \"./customCode\";\n\nimport { registerHandler } from \"./registry\";\nimport { pricePlusHandler } from \"./pricePlus\";\nimport { splitUrlHandler } from \"./splitUrl\";\nimport { contentHandler } from \"./content\";\nimport { customCodeHandler } from \"./customCode\";\n\nregisterHandler(pricePlusHandler);\nregisterHandler(splitUrlHandler);\nregisterHandler(contentHandler);\nregisterHandler(customCodeHandler);","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 {\n processSplitUrlTests,\n getSplitUrlBlockingScript,\n hasSplitUrlTests,\n} from \"../handlers/splitUrl\";\nimport {\n processContentTests,\n setupContentTestListeners,\n hasContentTests,\n} from \"../utils/content\";\nimport {\n processCustomCodeTests,\n hasCustomCodeTests,\n} from \"../utils/customCode\";\nimport { assignAllTests } from \"../utils/assignment\";\nimport { onNavigate } from \"../utils/navigation\";\n\nconst CDN_BASE_URL = \"https://ds0wlyksfn0sb.cloudfront.net/headless\";\n\nfunction getStoreName(storeId: string): string {\n return storeId.replace(/^https?:\\/\\//, \"\").replace(\".myshopify.com\", \"\");\n}\n\nfunction getConfigUrl(storeId: string): string {\n return `${CDN_BASE_URL}/${getStoreName(storeId)}.js`;\n}\n\ninterface ElevateProviderSimpleProps {\n storeId: string;\n storefrontAccessToken?: string;\n preventFlickering?: boolean;\n flickerTimeout?: number;\n nonce?: string;\n children: React.ReactNode;\n}\n\nconst useIsomorphicLayoutEffect =\n typeof window !== \"undefined\" ? React.useLayoutEffect : React.useEffect;\n\nexport function ElevateProvider({\n storeId,\n storefrontAccessToken,\n preventFlickering = false,\n flickerTimeout = 3000,\n nonce,\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\n React.useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n initAnalytics({\n storeId,\n storefrontAccessToken,\n });\n\n const preview = getPreviewState();\n setPreviewState(preview);\n\n const country = getCountryCode();\n setCountryCode(country);\n }, [storeId, storefrontAccessToken]);\n\n const revealContent = useCallback(() => {\n if (typeof window !== \"undefined\" && (window as any).__eab_reveal) {\n (window as any).__eab_reveal();\n }\n }, []);\n\n React.useEffect(() => {\n async function fetchConfig() {\n try {\n const currentPreviewState =\n typeof window !== \"undefined\" ? getPreviewState() : null;\n\n let backendData: BackendConfig | null = null;\n\n if (typeof window !== \"undefined\" && (window as any).eab_data) {\n backendData = (window as any).eab_data;\n } else {\n const url = getConfigUrl(storeId);\n\n backendData = await new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = url;\n script.async = true;\n\n script.onload = () => {\n const data = (window as any).eab_data;\n script.remove();\n\n if (!data) {\n reject(\n new Error(\n \"Failed to load config: window.eab_data is undefined\",\n ),\n );\n } else {\n resolve(data);\n }\n };\n\n script.onerror = () => {\n script.remove();\n resolve({\n allTests: {},\n selectors: { selectorsV2: [] },\n } as BackendConfig);\n };\n\n document.head.appendChild(script);\n });\n }\n\n if (\n !backendData ||\n !backendData.allTests ||\n Object.keys(backendData.allTests).length === 0\n ) {\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n return;\n }\n\n if (backendData.subscriptionPaused) {\n console.error(\n `[ElevateAB] Subscription is paused or stopped for store: ${storeId}. ` +\n (backendData.subscriptionMessage ||\n \"A/B tests will not run. Please reactivate your subscription.\"),\n );\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n return;\n }\n\n const hasActiveTests =\n Object.keys(backendData.allTests || {}).length > 0;\n if (!hasActiveTests) {\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n return;\n }\n\n const parsedConfig = parseBackendConfig(backendData);\n\n assignAllTests(parsedConfig, currentPreviewState);\n\n if (parsedConfig.tests.some((t) => t.type === \"SPLIT_URL\")) {\n const redirected = processSplitUrlTests(\n parsedConfig,\n currentPreviewState,\n );\n if (redirected) return;\n }\n\n setConfig(parsedConfig);\n revealContent();\n } catch (err) {\n console.error(\"[ElevateAB] Failed to load config:\", err);\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n }\n }\n\n fetchConfig();\n }, [storeId, revealContent]);\n\n useIsomorphicLayoutEffect(() => {\n if (!config || typeof window === \"undefined\") return;\n\n const applySplitUrlTests = (): boolean => {\n if (!hasSplitUrlTests(config)) return false;\n return processSplitUrlTests(config, previewState);\n };\n\n const applyNonRedirectTests = () => {\n if (hasContentTests(config)) {\n try {\n processContentTests(config, previewState, nonce);\n } catch (err) {\n console.error(\"[ElevateAB] Failed to apply CONTENT tests:\", err);\n }\n }\n\n if (hasCustomCodeTests(config)) {\n try {\n processCustomCodeTests(config, previewState, nonce);\n } catch (err) {\n console.error(\"[ElevateAB] Failed to apply CUSTOM_CODE tests:\", err);\n }\n }\n };\n\n // Apply on initial load with parsed config.\n if (!applySplitUrlTests()) {\n applyNonRedirectTests();\n }\n\n let navigationRafId: number | null = null;\n let navigationTimeoutId: number | null = null;\n\n // Re-apply all tests on SPA navigation.\n const cleanupNavigation = onNavigate(() => {\n // Run split URL checks immediately on navigation.\n if (applySplitUrlTests()) return;\n\n // Try immediately, then retry after the next paint frame so\n // content tests can target elements rendered by the new route.\n applyNonRedirectTests();\n if (navigationRafId !== null) {\n window.cancelAnimationFrame(navigationRafId);\n }\n if (navigationTimeoutId !== null) {\n window.clearTimeout(navigationTimeoutId);\n }\n navigationRafId = window.requestAnimationFrame(() => {\n applyNonRedirectTests();\n navigationTimeoutId = window.setTimeout(() => {\n applyNonRedirectTests();\n navigationTimeoutId = null;\n }, 80);\n navigationRafId = null;\n });\n });\n\n // Keep content resize handling, but avoid duplicate navigation listeners.\n const cleanupContent = hasContentTests(config)\n ? setupContentTestListeners(config, previewState, nonce, false)\n : () => {};\n\n return () => {\n if (navigationRafId !== null) {\n window.cancelAnimationFrame(navigationRafId);\n }\n if (navigationTimeoutId !== null) {\n window.clearTimeout(navigationTimeoutId);\n }\n cleanupNavigation();\n cleanupContent();\n };\n }, [config, previewState, nonce]);\n\n const value = React.useMemo(\n () => ({\n config,\n storeId,\n storefrontAccessToken,\n isPreviewMode: previewState?.isPreview ?? false,\n previewTestId: previewState?.previewTestId ?? null,\n previewState,\n selectors: config?.selectors,\n countryCode,\n }),\n [config, storeId, storefrontAccessToken, previewState, countryCode],\n );\n\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. Orders won't be attributed to test variants.\",\n );\n }\n }, [storefrontAccessToken]);\n\n const configUrl = React.useMemo(() => getConfigUrl(storeId), [storeId]);\n\n const blockingScript = React.useMemo(() => {\n const timeout = preventFlickering ? flickerTimeout : 2000;\n return getSplitUrlBlockingScript({ configUrl, timeout });\n }, [configUrl, preventFlickering, flickerTimeout]);\n\n return (\n <ElevateContext.Provider value={value}>\n <script\n nonce={nonce}\n dangerouslySetInnerHTML={{ __html: blockingScript }}\n />\n {children}\n </ElevateContext.Provider>\n );\n}\n","/**\n * Custom Code Test Utilities\n *\n * Handles processing and execution of CUSTOM_CODE type tests.\n * Custom code tests inject CSS/JS into the page based on pathname matching.\n * Both control and non-control variations can have custom code.\n */\n\nimport type { ContentCustomCode, ElevateConfig } from \"../types\";\nimport type { PreviewState } from \"./preview\";\nimport { getAssignedVariant } from \"./assignment\";\nimport { applyCustomCode } from \"./content\";\nimport { onNavigate } from \"./navigation\";\n\n/**\n * Check if there are any active custom code tests\n */\nexport function hasCustomCodeTests(config: ElevateConfig): boolean {\n return config.tests.some(\n (test) => test.type === \"CUSTOM_CODE\" && test.enabled\n );\n}\n\n/**\n * Process and apply all custom code tests\n * This is the main entry point called by ElevateProvider\n */\nexport function processCustomCodeTests(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string\n): void {\n if (typeof window === \"undefined\") return;\n\n // Check if there are any custom code tests\n if (!hasCustomCodeTests(config)) return;\n\n // Find all CUSTOM_CODE type tests\n const customCodeTests = config.tests.filter(\n (test) => test.type === \"CUSTOM_CODE\" && test.enabled\n );\n\n // Collect custom code from assigned variants\n const customCodes: ContentCustomCode[] = [];\n\n customCodeTests.forEach((test) => {\n const assignedVariantId = getAssignedVariant(test.testId);\n if (!assignedVariantId) return;\n\n const variation = test.variations.find((v) => v.id === assignedVariantId);\n if (!variation?.customCode) return;\n\n // Check if there's any code to inject\n if (variation.customCode.js || variation.customCode.css) {\n customCodes.push(variation.customCode);\n }\n });\n\n // Apply custom code if we have any\n if (customCodes.length > 0) {\n applyCustomCode(customCodes, nonce);\n }\n}\n\n/**\n * Re-process custom code tests (called on pathname change)\n */\nexport function reprocessCustomCodeTests(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string\n): void {\n if (typeof window === \"undefined\") return;\n\n // Re-process custom code tests\n processCustomCodeTests(config, previewState, nonce);\n}\n\n/**\n * Setup event listeners for custom code test re-processing.\n *\n * Listens for ALL SPA navigation (pushState, replaceState, popstate)\n * via the shared navigation utility.\n */\nexport function setupCustomCodeTestListeners(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string\n): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n // Handle ALL SPA navigation (pushState, replaceState, popstate)\n const cleanupNavigation = onNavigate(() => {\n reprocessCustomCodeTests(config, previewState, nonce);\n });\n\n // Return cleanup function\n return () => {\n cleanupNavigation();\n };\n}\n","/**\n * ElevateAnalytics Component\n *\n * Internal component used by ElevateHydrogenAnalytics.\n * Subscribes to Hydrogen analytics events and sends them to Elevate.\n *\n * For Hydrogen stores, use ElevateHydrogenAnalytics instead - it's zero-config!\n * For Next.js/Remix, use manual tracking functions (trackPageView, trackAddToCart, etc.)\n */\n\nimport React, { useEffect, useContext, useRef } from \"react\";\nimport type { EventPayload, TestAssignment } from \"../types\";\nimport { ElevateContext } from \"../contexts/ElevateContext\";\n\n/**\n * Type for useAnalytics hook signature (matches @shopify/hydrogen)\n */\nexport type UseAnalyticsHook = () => {\n subscribe: (event: string, callback: (data: unknown) => void) => void;\n register: (name: string) => { ready: () => void };\n};\n\n/**\n * Props for ElevateHydrogenAnalytics (public API)\n */\nexport interface ElevateHydrogenAnalyticsProps {\n /** Override storeId from context (optional) */\n storeId?: string;\n /** Override storefrontAccessToken from context (optional) */\n storefrontAccessToken?: string;\n /** Enable localized path detection (e.g., /en-us/, /fr-ca/) */\n hasLocalizedPaths?: boolean;\n /** Custom CloudFlare Worker URL */\n workerUrl?: string;\n /** Custom orders worker URL */\n ordersWorkerUrl?: string;\n}\n\n/**\n * Internal props for ElevateAnalytics (requires useAnalytics hook)\n */\ninterface ElevateAnalyticsProps extends ElevateHydrogenAnalyticsProps {\n /** The useAnalytics hook from @shopify/hydrogen (required) */\n useAnalytics: UseAnalyticsHook;\n}\nimport {\n parseAddViewData,\n extractProductId,\n extractProductVariantId,\n extractCartToken,\n cleanCartToken,\n getPageTypeFromPathname,\n sanitizeString,\n roundToTwo,\n getUserAgentNoBrowser,\n} from \"../utils/analytics\";\nimport {\n getVisitorId,\n getSessionId,\n getCookie,\n getJsonCookie,\n setReferrerData,\n getReferrerData,\n} from \"../utils/storage\";\nimport { uuidv4 } from \"../utils/storage\";\nimport { updateCartAttributes } from \"../utils/cartAttributes\";\n\n// Default CloudFlare Worker endpoints\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// Generate pixel event ID\nfunction generatePixelEventId(): string {\n return `sh-${uuidv4()}`;\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/**\n * ElevateAnalytics - Subscribes to Hydrogen analytics events\n *\n * @internal Used by ElevateHydrogenAnalytics. For Hydrogen stores, use ElevateHydrogenAnalytics instead!\n */\nexport function ElevateAnalytics({\n storeId: storeIdProp,\n storefrontAccessToken: tokenProp,\n hasLocalizedPaths,\n workerUrl = DEFAULT_WORKER_URL,\n ordersWorkerUrl = DEFAULT_ORDERS_WORKER_URL,\n useAnalytics,\n}: ElevateAnalyticsProps) {\n // Get values from context, allow props to override\n const context = useContext(ElevateContext);\n const storeId = storeIdProp || context?.storeId || \"\";\n const storefrontAccessToken = tokenProp || context?.storefrontAccessToken;\n\n // Track if we've warned about missing context (warn only once)\n const hasWarnedContextRef = useRef(false);\n\n // Warn once if not inside ElevateProvider\n useEffect(() => {\n if (!context && !storeIdProp && !hasWarnedContextRef.current) {\n hasWarnedContextRef.current = true;\n console.error(\n \"[ElevateAB] ElevateAnalytics must be used inside ElevateProvider, \" +\n \"or you must pass storeId as a prop.\",\n );\n }\n }, [context, storeIdProp]);\n const { subscribe, register } = useAnalytics();\n const { ready } = register(\"Elevate Analytics\");\n\n useEffect(() => {\n // Skip in non-browser environments\n if (typeof window === \"undefined\") return;\n\n // Initialize visitor ID and session ID\n getVisitorId();\n getSessionId();\n\n // Initialize referrer data if not already set\n if (typeof document !== \"undefined\") {\n const currentReferrer = document.referrer || \"\";\n const currentUrl = window.location.href;\n setReferrerData(currentReferrer, currentUrl);\n }\n\n const setupAnalytics = () => {\n // Initialize state\n const initializeState = (event: any) => {\n const productPageId = extractProductId(event.products?.[0]?.id);\n if (productPageId && typeof localStorage !== \"undefined\") {\n localStorage.setItem(\"eabProductPageId\", productPageId);\n } else if (\n typeof window !== \"undefined\" &&\n !window.location.pathname.includes(\"/products/\")\n ) {\n localStorage?.removeItem(\"eabProductPageId\");\n }\n\n const cartToken = extractCartToken(\n typeof localStorage !== \"undefined\"\n ? localStorage.getItem(\"shopifyCartId\")\n : null,\n );\n\n const { referrer, entryPage } = getReferrerData();\n\n return {\n visitorId: getVisitorId(),\n sessionId: getSessionId(),\n cartToken: cartToken || getCookie(\"cart\") || \"\",\n referrer,\n entryPage,\n clientId: getCookie(\"_shopify_y\"),\n rootRoute:\n typeof localStorage !== \"undefined\"\n ? localStorage.getItem(\"eabRootRoute\") || \"\"\n : \"\",\n productPageId:\n typeof localStorage !== \"undefined\"\n ? localStorage.getItem(\"eabProductPageId\") || \"\"\n : \"\",\n };\n };\n\n // Create base event data\n const createBaseEventData = (\n eventName: string,\n pixelEventId: string,\n event: any,\n state: any,\n ): EventPayload => {\n const userAgent =\n typeof navigator !== \"undefined\" ? navigator.userAgent : \"\";\n const pathname = event?.url\n ? new URL(event.url).pathname\n : typeof window !== \"undefined\"\n ? window.location.pathname\n : \"\";\n const pageType = getPageTypeFromPathname(pathname, hasLocalizedPaths);\n\n const parsedData = parseAddViewData({\n referrer: state.referrer,\n entryPage: state.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 currentTimestamp = new Date().toISOString();\n\n // Get additional state from cookies/storage\n const isFirstVisit =\n typeof sessionStorage !== \"undefined\"\n ? sessionStorage.getItem(\"eabIsFirstVisit\") === \"true\"\n : false;\n const shopifyCountry = getCookie(\"localization\") || \"\";\n\n return {\n pixel_event_id: pixelEventId,\n shop_name: storeId,\n timestamp: currentTimestamp,\n event_type: eventName,\n client_id: state.clientId,\n visitor_id: state.visitorId,\n session_id: state.sessionId,\n cart_token: cleanCartToken(state.cartToken),\n\n page_url:\n event.context?.document?.location?.href ||\n (typeof window !== \"undefined\" ? window.location.href : \"\"),\n page_pathname: pathname,\n page_search:\n event.context?.document?.location?.search ||\n (typeof window !== \"undefined\" ? window.location.search : \"\"),\n referrer_url: state.referrer,\n referrer_source: parsedData?.referrer_source,\n previous_page:\n typeof document !== \"undefined\" ? document.referrer : \"\",\n page_entry: state.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:\n event.context?.navigator?.language ||\n (typeof navigator !== \"undefined\" ? navigator.language : \"\"),\n root_route: state.rootRoute,\n user_agent: userAgent,\n user_agent_no_browser: getUserAgentNoBrowser(userAgent),\n\n is_first_visit: isFirstVisit,\n shopify_country: shopifyCountry,\n\n cart_currency: event.shop?.currency,\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\n const sendEvent = async (data: EventPayload) => {\n if (data.exclude) return;\n\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\n return response;\n } catch (error) {\n console.error(\"[ElevateAB] Error sending analytics:\", error);\n }\n };\n\n // Event handlers\n const handlePageViewed = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const eventData = createBaseEventData(\n \"page_viewed\",\n pixelEventId,\n event,\n state,\n );\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\"[ElevateAB] Error handling page_viewed:\", error);\n }\n };\n\n const handleProductViewed = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"product_viewed\",\n pixelEventId,\n event,\n state,\n );\n\n const eventData: EventPayload = {\n ...baseData,\n product_id: extractProductId(event?.products?.[0]?.id) || \"\",\n product_vendor: sanitizeString(event?.products?.[0]?.vendor) ?? \"\",\n product_price: roundToTwo(event?.products?.[0]?.price) ?? null,\n product_sku: sanitizeString(event?.products?.[0]?.sku) ?? \"\",\n };\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\"[ElevateAB] Error handling product_viewed:\", error);\n }\n };\n\n const handleProductAddedToCart = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"product_added_to_cart\",\n pixelEventId,\n event,\n state,\n );\n\n const eventData: EventPayload = {\n ...baseData,\n product_id:\n extractProductId(event?.currentLine?.merchandise?.product?.id) ??\n \"\",\n variant_id:\n extractProductVariantId(event?.currentLine?.merchandise?.id) ??\n \"\",\n product_vendor:\n sanitizeString(\n event?.currentLine?.merchandise?.product?.vendor,\n ) ?? \"\",\n product_price:\n roundToTwo(event?.currentLine?.cost?.totalAmount?.amount) ?? null,\n product_quantity: event?.currentLine?.quantity ?? null,\n product_sku:\n sanitizeString(event?.currentLine?.merchandise?.sku) ?? \"\",\n };\n\n await sendEvent(eventData);\n\n // Update cart attributes with A/B test data (for order attribution)\n const cartId = event?.cart?.id;\n if (cartId && storefrontAccessToken && storeId) {\n updateCartAttributes(cartId, {\n storefrontAccessToken,\n storefrontApiUrl: `https://${storeId}/api/2025-01/graphql.json`,\n }).catch((err) => {\n console.error(\n \"[ElevateAB] Failed to update cart attributes:\",\n err,\n );\n });\n }\n } catch (error) {\n console.error(\n \"[ElevateAB] Error handling product_added_to_cart:\",\n error,\n );\n }\n };\n\n const handleProductRemovedFromCart = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"product_removed_from_cart\",\n pixelEventId,\n event,\n state,\n );\n\n const eventData: EventPayload = {\n ...baseData,\n product_id:\n extractProductId(event?.prevLine?.merchandise?.product?.id) ?? \"\",\n variant_id:\n extractProductVariantId(event?.prevLine?.merchandise?.id) ?? \"\",\n product_vendor:\n sanitizeString(event?.prevLine?.merchandise?.product?.vendor) ??\n \"\",\n product_price:\n roundToTwo(event?.prevLine?.cost?.totalAmount?.amount) ?? null,\n product_quantity: event?.prevLine?.quantity ?? null,\n product_sku:\n sanitizeString(event?.prevLine?.merchandise?.sku) ?? \"\",\n };\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\n \"[ElevateAB] Error handling product_removed_from_cart:\",\n error,\n );\n }\n };\n\n const handleCartViewed = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"cart_viewed\",\n pixelEventId,\n event,\n state,\n );\n\n const lines =\n event?.data?.cart?.lines?.nodes || event?.data?.cart?.lines || [];\n const cartProducts = lines.map((item: any) => ({\n product_id: extractProductId(item?.merchandise?.product?.id) ?? \"\",\n variant_id: extractProductVariantId(item?.merchandise?.id) ?? \"\",\n vendor: sanitizeString(item?.merchandise?.product?.vendor) ?? \"\",\n total_price: roundToTwo(item?.cost?.totalAmount?.amount) ?? null,\n quantity: item?.quantity ?? null,\n sku: sanitizeString(item?.merchandise?.sku) ?? \"\",\n }));\n\n const eventData: EventPayload = {\n ...baseData,\n cart_total_price:\n roundToTwo(event?.cart?.cost?.totalAmount?.amount) ?? null,\n cart_total_quantity: event?.cart?.totalQuantity ?? null,\n cart_items: cartProducts,\n };\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\"[ElevateAB] Error handling cart_viewed:\", error);\n }\n };\n\n const handleSearchSubmitted = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"search_submitted\",\n pixelEventId,\n event,\n state,\n );\n\n const eventData: EventPayload = {\n ...baseData,\n search_query:\n sanitizeString(event?.data?.searchResult?.query) ?? \"\",\n };\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\"[ElevateAB] Error handling search_submitted:\", error);\n }\n };\n\n const handleCheckoutStarted = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"checkout_started\",\n pixelEventId,\n event,\n state,\n );\n\n let totalQuantity = 0;\n const lineItems = event?.data?.checkout?.lineItems ?? [];\n const checkoutProducts = lineItems.map((item: any) => {\n const quantity = item?.quantity ?? 0;\n totalQuantity += quantity;\n\n const discountAllocations = item?.discountAllocations ?? [];\n const total_discount = discountAllocations?.reduce(\n (acc: number, discount: any) =>\n acc + (discount?.amount?.amount || 0),\n 0,\n );\n\n return {\n product_id: extractProductId(item?.variant?.product?.id) ?? \"\",\n variant_id: extractProductVariantId(item?.variant?.id) ?? \"\",\n vendor: sanitizeString(item?.variant?.product?.vendor) ?? \"\",\n total_price: roundToTwo(item?.finalLinePrice?.amount) ?? null,\n quantity: quantity,\n sku: sanitizeString(item?.variant?.sku) ?? \"\",\n total_discount: roundToTwo(total_discount) ?? null,\n };\n });\n\n const eventData: EventPayload = {\n ...baseData,\n cart_total_price:\n roundToTwo(event?.data?.checkout?.totalPrice?.amount) ?? null,\n cart_subtotal_price:\n roundToTwo(event?.data?.checkout?.subtotalPrice?.amount) ?? null,\n cart_total_quantity: totalQuantity,\n cart_shipping_price:\n roundToTwo(event?.data?.checkout?.shippingLine?.price?.amount) ??\n null,\n cart_tax_amount:\n roundToTwo(event?.data?.checkout?.totalTax?.amount) ?? null,\n cart_discount_amount:\n roundToTwo(event?.data?.checkout?.discountsAmount?.amount) ??\n null,\n cart_items: checkoutProducts,\n customer_id: event?.data?.checkout?.order?.customer?.id ?? \"\",\n };\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\"[ElevateAB] Error handling checkout_started:\", error);\n }\n };\n\n const handleCheckoutCompleted = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"checkout_completed\",\n pixelEventId,\n event,\n state,\n );\n\n let totalQuantity = 0;\n const lineItems = event?.data?.checkout?.lineItems ?? [];\n const checkoutProducts = lineItems.map((item: any) => {\n const quantity = item?.quantity ?? 0;\n totalQuantity += quantity;\n\n const discountAllocations = item?.discountAllocations ?? [];\n const total_discount = discountAllocations?.reduce(\n (acc: number, discount: any) =>\n acc + (discount?.amount?.amount || 0),\n 0,\n );\n\n return {\n product_id: extractProductId(item?.variant?.product?.id) ?? \"\",\n variant_id: extractProductVariantId(item?.variant?.id) ?? \"\",\n vendor: sanitizeString(item?.variant?.product?.vendor) ?? \"\",\n total_price: roundToTwo(item?.finalLinePrice?.amount) ?? null,\n quantity: quantity,\n sku: sanitizeString(item?.variant?.sku) ?? \"\",\n total_discount: roundToTwo(total_discount) ?? null,\n };\n });\n\n const eventData: EventPayload = {\n ...baseData,\n cart_total_price:\n roundToTwo(event?.data?.checkout?.totalPrice?.amount) ?? null,\n cart_subtotal_price:\n roundToTwo(event?.data?.checkout?.subtotalPrice?.amount) ?? null,\n cart_total_quantity: totalQuantity,\n cart_shipping_price:\n roundToTwo(event?.data?.checkout?.shippingLine?.price?.amount) ??\n null,\n cart_tax_amount:\n roundToTwo(event?.data?.checkout?.totalTax?.amount) ?? null,\n cart_discount_amount:\n roundToTwo(event?.data?.checkout?.discountsAmount?.amount) ??\n null,\n cart_items: checkoutProducts,\n order_id: event?.data?.checkout?.order?.id ?? \"\",\n customer_id: event?.data?.checkout?.order?.customer?.id ?? \"\",\n is_first_order:\n event?.data?.checkout?.order?.customer?.isFirstOrder ?? null,\n note_attributes: event?.data?.checkout?.attributes ?? [],\n };\n\n // Send to orders worker (different endpoint)\n await sendOrderEvent(eventData);\n } catch (error) {\n console.error(\n \"[ElevateAB] Error handling checkout_completed:\",\n error,\n );\n }\n };\n\n // Send event to orders CloudFlare Worker (for checkout_completed)\n const sendOrderEvent = async (data: EventPayload) => {\n if (data.exclude) return;\n\n try {\n const response = await fetch(ordersWorkerUrl, {\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(`Orders worker error: ${response.status}`);\n }\n\n return response;\n } catch (error) {\n console.error(\"[ElevateAB] Error sending order analytics:\", error);\n }\n };\n\n // Subscribe to events\n subscribe(\"page_viewed\", handlePageViewed);\n subscribe(\"product_viewed\", handleProductViewed);\n subscribe(\"product_added_to_cart\", handleProductAddedToCart);\n subscribe(\"product_removed_from_cart\", handleProductRemovedFromCart);\n subscribe(\"cart_viewed\", handleCartViewed);\n subscribe(\"search_submitted\", handleSearchSubmitted);\n subscribe(\"checkout_started\", handleCheckoutStarted);\n subscribe(\"checkout_completed\", handleCheckoutCompleted);\n };\n\n setupAnalytics();\n ready();\n }, [\n subscribe,\n ready,\n storeId,\n hasLocalizedPaths,\n storefrontAccessToken,\n workerUrl,\n ordersWorkerUrl,\n ]);\n\n return null;\n}\n"],"mappings":"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","names":["hashString","str","hash","i","char","parseBackendConfig","backendData","tests","testId","testData","variations","nonControlIndex","key","value","variation","isControl","rawContent","content","rawCustomCode","customCode","init_utils","__esmMin","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","init_storage","__esmMin","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","init_preview","__esmMin","init_storage","trackUniqueView","testId","addedUniqueViews","getJsonCookie","setCookie","trackSessionView","addedViews","getJsonSessionItem","setSessionItem","trackViews","hasSessionView","hasUniqueView","init_tracking","__esmMin","init_storage","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","canAssignToTestWithCache","init_assignment","__esmMin","init_storage","init_utils","init_preview","init_tracking","require_ua_parser","__commonJSMin","exports","module","window","undefined","LIBVERSION","EMPTY","UNKNOWN","FUNC_TYPE","UNDEF_TYPE","OBJ_TYPE","STR_TYPE","MAJOR","MODEL","NAME","TYPE","VENDOR","VERSION","ARCHITECTURE","CONSOLE","MOBILE","TABLET","SMARTTV","WEARABLE","EMBEDDED","UA_MAX_LENGTH","AMAZON","APPLE","ASUS","BLACKBERRY","BROWSER","CHROME","EDGE","FIREFOX","GOOGLE","HONOR","HUAWEI","LENOVO","LG","MICROSOFT","MOTOROLA","NVIDIA","ONEPLUS","OPERA","OPPO","SAMSUNG","SHARP","SONY","XIAOMI","ZEBRA","FACEBOOK","CHROMIUM_OS","MAC_OS","SUFFIX_BROWSER","extend","regexes","extensions","mergedRegexes","i","enumerize","arr","enums","has","str1","str2","lowerize","str","majorize","version","trim","len","rgxMapper","ua","arrays","j","k","p","q","matches","match","regex","props","strMapper","map","oldSafariMap","windowsVersionMap","UAParser","_navigator","_ua","_uach","_rgxmap","_isSelfNav","_browser","_cpu","_device","_engine","_os","$","parser","result","prop","CART_ATTRIBUTES_UPDATE_MUTATION","init_cartAttributes_mutation","__esmMin","cartAttributes_exports","__export","cleanupCartAttributes","getCartAttributesPayload","updateCartAttributes","testList","getTestList","addedUniqueViews","getJsonCookie","eabUserId","getCookie","isPreviewMode","abtidValue","viewedTests","testId","attributes","cartId","options","cartGid","storefrontUrl","getStoreDomain","response","CART_ATTRIBUTES_UPDATE_MUTATION","result","errorMsg","error","init_cartAttributes","__esmMin","init_assignment","init_storage","init_cartAttributes_mutation","index_exports","__export","CART_ATTRIBUTES_UPDATE_MUTATION","COUNTRIES","ElevateAnalytics","ElevateProvider","REGIONS","VERSION","applyContentChanges","applyContentElements","applyCustomCode","assignAllTests","assignAndPersistVariant","buildEabTestsParam","canAssignToTest","checkFacebookBrowser","checkFacebookInstagramBrowser","checkInstagramBrowser","checkPinterestBrowser","checkTikTokBrowser","checkVisitorIdParams","cleanCartToken","cleanupCartAttributes","cleanupContentTests","clearPreviewMode","contentHandler","deleteCookie","detectShopifyCurrency","extractCartToken","extractProductId","extractProductVariantId","extractShopifyId","extractShopifyType","getAllHandlers","getAssignedVariant","getCartAttributesPayload","getCookie","getCountryCode","getDeviceType","getGeoLocation","getHandler","getJsonCookie","getJsonSessionItem","getPageTypeFromPathname","getPreviewState","getPreviewVariation","getReferrerData","getSessionId","getSessionItem","getSplitUrlBlockingScript","getTestList","getTrafficSource","getUserAgentNoBrowser","getVisitorId","hasContentTests","hasHandler","hasSessionView","hasUniqueView","hashString","initAnalytics","initializeSessionId","initializeVisitorId","isCountryExcluded","isCountryIncluded","isInPreviewMode","isPreviewTest","isShopifyGid","matchesGeoTargeting","matchesWildcardPattern","parseAddViewData","processContentTests","processSplitUrlTests","registerHandler","reprocessContentTests","restoreOriginalElements","roundToTwo","sanitizeString","saveTestList","setCookie","setCountryCode","setGeoLocation","setReferrerData","setSessionItem","setupContentTestListeners","shouldShowTest","trackAddToCart","trackCartView","trackCheckoutCompleted","trackCheckoutStarted","trackPageView","trackProductView","trackRemoveFromCart","trackSearchSubmitted","trackSessionView","trackUniqueView","trackViews","updateCartAttributes","updateUrlWithTestParams","useElevateConfig","useExperiment","usePageViewTracking","uuidv4","__toCommonJS","init_utils","init_storage","init_assignment","init_tracking","getDeviceType","ua","lower","checkFacebookBrowser","userAgent","checkInstagramBrowser","checkTikTokBrowser","checkPinterestBrowser","getTrafficSource","referrer","referrerDomain","hostname","isFacebookBrowser","isInstagramBrowser","isTikTokBrowser","isPinterestBrowser","init_preview","init_storage","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","init_assignment","init_storage","NAVIGATE_EVENT","patched","patchRefCount","originalPushState","originalReplaceState","patchHistory","args","unpatchHistory","onNavigate","callback","lastUrl","handler","currentUrl","getSplitUrlBlockingScript","options","configUrl","timeout","normalizeUrl","url","withProtocol","urlObj","urlMatches","currentUrl","urlList","normalizedCurrent","normalizedTarget","currentPath","targetPath","getRedirectBehavior","test","hasBeenRedirected","testId","getJsonCookie","markAsRedirected","redirectedTests","setCookie","findMatchingSplitUrlTest","config","variation","urls","performRedirect","targetUrl","finalUrl","navigate","pathname","processSplitUrlTests","previewState","match","matchedVariation","isControlUrl","redirectBehavior","assignedVariationId","getAssignedVariant","assignedVariation","v","targetUrls","hasSplitUrlTests","splitUrlHandler","test","context","variation","urls","urlMatches","import_ua_parser_js","urlSources","sanitizeString","value","roundToTwo","num","extractProductId","gid","regex","match","extractProductVariantId","extractCartToken","cleanCartToken","cartToken","checkFacebookBrowser","userAgent","checkInstagramBrowser","checkFacebookInstagramBrowser","getBrowserName","browser","getQueryParams","parsedUrl","queryParams","key","isValidReferrerURI","uri","extractReferrerSource","host","parseReferrer","referrer","siteHostname","referrerObj","source","parseAddViewData","params","entryPage","data","entryObj","entryPath","entryQueryParams","userAgentObj","browserName","getPageTypeFromPathname","path","hasLocalizedPaths","hasNormalPath","isLocalizedHomepage","checkVisitorIdParams","searchParams","getUserAgentNoBrowser","os","device","result","extractShopifyId","gid","extractShopifyType","isShopifyGid","value","detectShopifyCurrency","shopify","init_assignment","ELEMENT_ID_PREFIX","NODE_TYPES","originalElements","injectedStyles","injectedScripts","injectedElements","isMobile","matchesWildcardPattern","pathname","pattern","trimmedPattern","suffix","checkIsMobile","convertToKebabCase","text","result","i","char","isTextNode","node","isElementNode","storeOriginalElement","selector","element","decodeCodeString","code","decoded","applyContentChanges","changes","currentPathname","matchingChanges","change","processedChanges","index","uniqueSelector","prop","value","kebabProp","hasImportant","cleanValue","key","applyContentElements","elements","elementId","trackedElement","target","domElement","createDOMElement","child","childElement","applyCustomCode","customCodes","nonce","injectCSS","injectJS","id","css","styleId","trackedStyle","styleElement","js","scriptId","trackedScript","scriptElement","decodedJs","restoreOriginalElements","originalElement","cleanupContentTests","style","script","collectContentTestData","config","previewState","allChanges","allElements","allCustomCodes","test","assignedVariantId","getAssignedVariant","variation","v","hasContentTests","processContentTests","contentData","reprocessContentTests","currentIsMobile","setupContentTestListeners","listenToNavigation","handleResize","cleanupNavigation","onNavigate","init_cartAttributes","init_cartAttributes_mutation","init_storage","import_react","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","currentPath","setCurrentPath","import_react","import_react","ElevateContext","React","useElevateConfig","context","init_assignment","init_tracking","init_preview","handlers","registerHandler","handler","getHandler","type","getAllHandlers","hasHandler","extractProductHandleFromUrl","url","match","updatePriceElements","variation","variantId","currencyCode","selectors","variantPrices","priceAmount","compareAmount","selectorsConfig","selectorSet","priceSelector","el","formattedPrice","compareSelector","savingConfig","savingSelector","price","compare","saving","percentage","formattedSaving","pricePlusHandler","test","context","testData","productId","productHandle","urlHandle","matchesProductId","matchesHandle","matchesTestPathnames","test","currentUrl","pathnames","pathname","pattern","matchesWildcardPattern","contentHandler","context","variation","_context","testData","matchesTestPathnames","test","currentUrl","pathnames","pathname","pattern","matchesWildcardPattern","customCodeHandler","context","variation","_context","testData","registerHandler","pricePlusHandler","splitUrlHandler","contentHandler","customCodeHandler","buildHandlerContext","selectors","url","pathname","productHandle","productMatch","variantId","variantParam","useExperiment","testId","config","contextPreviewState","useElevateConfig","variant","setVariant","React","isLoading","setIsLoading","testConfig","test","previewState","getPreviewState","hasWarnedRef","effectAppliedRef","isMounted","assignedVariantId","getAssignedVariant","assigned","v","handler","getHandler","context","enrichedVariant","effectKey","handlerData","trackViews","import_react","init_utils","init_preview","init_assignment","hasCustomCodeTests","config","test","processCustomCodeTests","previewState","nonce","customCodeTests","customCodes","assignedVariantId","getAssignedVariant","variation","v","applyCustomCode","init_assignment","import_jsx_runtime","CDN_BASE_URL","getStoreName","storeId","getConfigUrl","useIsomorphicLayoutEffect","React","ElevateProvider","storefrontAccessToken","preventFlickering","flickerTimeout","nonce","children","config","setConfig","previewState","setPreviewState","countryCode","setCountryCode","initAnalytics","preview","getPreviewState","country","getCountryCode","revealContent","fetchConfig","currentPreviewState","backendData","url","resolve","reject","script","data","parsedConfig","parseBackendConfig","assignAllTests","t","processSplitUrlTests","err","applySplitUrlTests","hasSplitUrlTests","applyNonRedirectTests","hasContentTests","processContentTests","hasCustomCodeTests","processCustomCodeTests","navigationRafId","navigationTimeoutId","cleanupNavigation","onNavigate","cleanupContent","setupContentTestListeners","value","hasWarnedRef","configUrl","blockingScript","getSplitUrlBlockingScript","ElevateContext","import_react","init_storage","init_cartAttributes","DEFAULT_WORKER_URL","DEFAULT_ORDERS_WORKER_URL","generatePixelEventId","uuidv4","transformTestFormat","testObject","variationId","testId","transformViewedTests","viewedObject","assignmentObject","ElevateAnalytics","storeIdProp","tokenProp","hasLocalizedPaths","workerUrl","ordersWorkerUrl","useAnalytics","context","ElevateContext","storeId","storefrontAccessToken","hasWarnedContextRef","subscribe","register","ready","getVisitorId","getSessionId","currentReferrer","currentUrl","setReferrerData","initializeState","event","productPageId","extractProductId","cartToken","extractCartToken","referrer","entryPage","getReferrerData","getCookie","createBaseEventData","eventName","pixelEventId","state","userAgent","pathname","pageType","getPageTypeFromPathname","parsedData","parseAddViewData","abtlObject","getJsonCookie","abauObject","testAssignments","viewedTests","currentTimestamp","isFirstVisit","shopifyCountry","cleanCartToken","getUserAgentNoBrowser","sendEvent","data","response","error","handlePageViewed","eventData","handleProductViewed","sanitizeString","roundToTwo","handleProductAddedToCart","extractProductVariantId","cartId","updateCartAttributes","err","handleProductRemovedFromCart","handleCartViewed","baseData","cartProducts","item","handleSearchSubmitted","handleCheckoutStarted","totalQuantity","checkoutProducts","quantity","total_discount","acc","discount","handleCheckoutCompleted","sendOrderEvent","VERSION"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/utils/storage.ts","../src/utils/preview.ts","../src/utils/tracking.ts","../src/utils/assignment.ts","../node_modules/ua-parser-js/src/ua-parser.js","../src/mutations/cartAttributes.mutation.ts","../src/utils/cartAttributes.ts","../src/index.ts","../src/utils/conditions.ts","../src/utils/geo.ts","../src/handlers/splitUrl.ts","../src/utils/navigation.ts","../src/utils/analytics.ts","../src/utils/shopify.ts","../src/utils/content.ts","../src/utils/manualTracking.ts","../src/components/Experiment.tsx","../src/contexts/ElevateContext.tsx","../src/handlers/registry.ts","../src/handlers/pricePlus.ts","../src/handlers/content.ts","../src/handlers/customCode.ts","../src/handlers/index.ts","../src/components/ElevateProvider.tsx","../src/utils/customCode.ts","../src/components/ElevateAnalytics.tsx"],"sourcesContent":["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","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","/**\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/* UAParser.js v1.0.41\n Copyright © 2012-2025 Faisal Salman <f@faisalman.com>\n MIT License *//*\n Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.\n Supports browser & node.js environment. \n Demo : https://faisalman.github.io/ua-parser-js\n Source : https://github.com/faisalman/ua-parser-js */\n/////////////////////////////////////////////////////////////////////////////////\n\n(function (window, undefined) {\n\n 'use strict';\n\n //////////////\n // Constants\n /////////////\n\n\n var LIBVERSION = '1.0.41',\n EMPTY = '',\n UNKNOWN = '?',\n FUNC_TYPE = 'function',\n UNDEF_TYPE = 'undefined',\n OBJ_TYPE = 'object',\n STR_TYPE = 'string',\n MAJOR = 'major',\n MODEL = 'model',\n NAME = 'name',\n TYPE = 'type',\n VENDOR = 'vendor',\n VERSION = 'version',\n ARCHITECTURE= 'architecture',\n CONSOLE = 'console',\n MOBILE = 'mobile',\n TABLET = 'tablet',\n SMARTTV = 'smarttv',\n WEARABLE = 'wearable',\n EMBEDDED = 'embedded',\n UA_MAX_LENGTH = 500;\n\n var AMAZON = 'Amazon',\n APPLE = 'Apple',\n ASUS = 'ASUS',\n BLACKBERRY = 'BlackBerry',\n BROWSER = 'Browser',\n CHROME = 'Chrome',\n EDGE = 'Edge',\n FIREFOX = 'Firefox',\n GOOGLE = 'Google',\n HONOR = 'Honor',\n HUAWEI = 'Huawei',\n LENOVO = 'Lenovo',\n LG = 'LG',\n MICROSOFT = 'Microsoft',\n MOTOROLA = 'Motorola',\n NVIDIA = 'Nvidia',\n ONEPLUS = 'OnePlus',\n OPERA = 'Opera',\n OPPO = 'OPPO',\n SAMSUNG = 'Samsung',\n SHARP = 'Sharp',\n SONY = 'Sony',\n XIAOMI = 'Xiaomi',\n ZEBRA = 'Zebra',\n FACEBOOK = 'Facebook',\n CHROMIUM_OS = 'Chromium OS',\n MAC_OS = 'Mac OS',\n SUFFIX_BROWSER = ' Browser';\n\n ///////////\n // Helper\n //////////\n\n var extend = function (regexes, extensions) {\n var mergedRegexes = {};\n for (var i in regexes) {\n if (extensions[i] && extensions[i].length % 2 === 0) {\n mergedRegexes[i] = extensions[i].concat(regexes[i]);\n } else {\n mergedRegexes[i] = regexes[i];\n }\n }\n return mergedRegexes;\n },\n enumerize = function (arr) {\n var enums = {};\n for (var i=0; i<arr.length; i++) {\n enums[arr[i].toUpperCase()] = arr[i];\n }\n return enums;\n },\n has = function (str1, str2) {\n return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;\n },\n lowerize = function (str) {\n return str.toLowerCase();\n },\n majorize = function (version) {\n return typeof(version) === STR_TYPE ? version.replace(/[^\\d\\.]/g, EMPTY).split('.')[0] : undefined;\n },\n trim = function (str, len) {\n if (typeof(str) === STR_TYPE) {\n str = str.replace(/^\\s\\s*/, EMPTY);\n return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);\n }\n };\n\n ///////////////\n // Map helper\n //////////////\n\n var rgxMapper = function (ua, arrays) {\n\n var i = 0, j, k, p, q, matches, match;\n\n // loop through all regexes maps\n while (i < arrays.length && !matches) {\n\n var regex = arrays[i], // even sequence (0,2,4,..)\n props = arrays[i + 1]; // odd sequence (1,3,5,..)\n j = k = 0;\n\n // try matching uastring with regexes\n while (j < regex.length && !matches) {\n\n if (!regex[j]) { break; }\n matches = regex[j++].exec(ua);\n\n if (!!matches) {\n for (p = 0; p < props.length; p++) {\n match = matches[++k];\n q = props[p];\n // check if given property is actually array\n if (typeof q === OBJ_TYPE && q.length > 0) {\n if (q.length === 2) {\n if (typeof q[1] == FUNC_TYPE) {\n // assign modified match\n this[q[0]] = q[1].call(this, match);\n } else {\n // assign given value, ignore regex match\n this[q[0]] = q[1];\n }\n } else if (q.length === 3) {\n // check whether function or regex\n if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {\n // call function (usually string mapper)\n this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;\n } else {\n // sanitize match using given regex\n this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;\n }\n } else if (q.length === 4) {\n this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;\n }\n } else {\n this[q] = match ? match : undefined;\n }\n }\n }\n }\n i += 2;\n }\n },\n\n strMapper = function (str, map) {\n\n for (var i in map) {\n // check if current value is array\n if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {\n for (var j = 0; j < map[i].length; j++) {\n if (has(map[i][j], str)) {\n return (i === UNKNOWN) ? undefined : i;\n }\n }\n } else if (has(map[i], str)) {\n return (i === UNKNOWN) ? undefined : i;\n }\n }\n return map.hasOwnProperty('*') ? map['*'] : str;\n };\n\n ///////////////\n // String map\n //////////////\n\n // Safari < 3.0\n var oldSafariMap = {\n '1.0' : '/8',\n '1.2' : '/1',\n '1.3' : '/3',\n '2.0' : '/412',\n '2.0.2' : '/416',\n '2.0.3' : '/417',\n '2.0.4' : '/419',\n '?' : '/'\n },\n windowsVersionMap = {\n 'ME' : '4.90',\n 'NT 3.11' : 'NT3.51',\n 'NT 4.0' : 'NT4.0',\n '2000' : 'NT 5.0',\n 'XP' : ['NT 5.1', 'NT 5.2'],\n 'Vista' : 'NT 6.0',\n '7' : 'NT 6.1',\n '8' : 'NT 6.2',\n '8.1' : 'NT 6.3',\n '10' : ['NT 6.4', 'NT 10.0'],\n 'RT' : 'ARM'\n };\n\n //////////////\n // Regex map\n /////////////\n\n var regexes = {\n\n browser : [[\n\n /\\b(?:crmo|crios)\\/([\\w\\.]+)/i // Chrome for Android/iOS\n ], [VERSION, [NAME, 'Chrome']], [\n /edg(?:e|ios|a)?\\/([\\w\\.]+)/i // Microsoft Edge\n ], [VERSION, [NAME, 'Edge']], [\n\n // Presto based\n /(opera mini)\\/([-\\w\\.]+)/i, // Opera Mini\n /(opera [mobiletab]{3,6})\\b.+version\\/([-\\w\\.]+)/i, // Opera Mobi/Tablet\n /(opera)(?:.+version\\/|[\\/ ]+)([\\w\\.]+)/i // Opera\n ], [NAME, VERSION], [\n /opios[\\/ ]+([\\w\\.]+)/i // Opera mini on iphone >= 8.0\n ], [VERSION, [NAME, OPERA+' Mini']], [\n /\\bop(?:rg)?x\\/([\\w\\.]+)/i // Opera GX\n ], [VERSION, [NAME, OPERA+' GX']], [\n /\\bopr\\/([\\w\\.]+)/i // Opera Webkit\n ], [VERSION, [NAME, OPERA]], [\n\n // Mixed\n /\\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\\/ ]?([\\w\\.]+)/i // Baidu\n ], [VERSION, [NAME, 'Baidu']], [\n /\\b(?:mxbrowser|mxios|myie2)\\/?([-\\w\\.]*)\\b/i // Maxthon\n ], [VERSION, [NAME, 'Maxthon']], [\n /(kindle)\\/([\\w\\.]+)/i, // Kindle\n /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\\/ ]?([\\w\\.]*)/i, \n // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir\n // Trident based\n /(avant|iemobile|slim(?:browser|boat|jet))[\\/ ]?([\\d\\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet\n /(?:ms|\\()(ie) ([\\w\\.]+)/i, // Internet Explorer\n\n // Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon\n /(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,\n // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon\n /(heytap|ovi|115)browser\\/([\\d\\.]+)/i, // HeyTap/Ovi/115\n /(weibo)__([\\d\\.]+)/i // Weibo\n ], [NAME, VERSION], [\n /quark(?:pc)?\\/([-\\w\\.]+)/i // Quark\n ], [VERSION, [NAME, 'Quark']], [\n /\\bddg\\/([\\w\\.]+)/i // DuckDuckGo\n ], [VERSION, [NAME, 'DuckDuckGo']], [\n /(?:\\buc? ?browser|(?:juc.+)ucweb)[\\/ ]?([\\w\\.]+)/i // UCBrowser\n ], [VERSION, [NAME, 'UC'+BROWSER]], [\n /microm.+\\bqbcore\\/([\\w\\.]+)/i, // WeChat Desktop for Windows Built-in Browser\n /\\bqbcore\\/([\\w\\.]+).+microm/i,\n /micromessenger\\/([\\w\\.]+)/i // WeChat\n ], [VERSION, [NAME, 'WeChat']], [\n /konqueror\\/([\\w\\.]+)/i // Konqueror\n ], [VERSION, [NAME, 'Konqueror']], [\n /trident.+rv[: ]([\\w\\.]{1,9})\\b.+like gecko/i // IE11\n ], [VERSION, [NAME, 'IE']], [\n /ya(?:search)?browser\\/([\\w\\.]+)/i // Yandex\n ], [VERSION, [NAME, 'Yandex']], [\n /slbrowser\\/([\\w\\.]+)/i // Smart Lenovo Browser\n ], [VERSION, [NAME, 'Smart Lenovo '+BROWSER]], [\n /(avast|avg)\\/([\\w\\.]+)/i // Avast/AVG Secure Browser\n ], [[NAME, /(.+)/, '$1 Secure '+BROWSER], VERSION], [\n /\\bfocus\\/([\\w\\.]+)/i // Firefox Focus\n ], [VERSION, [NAME, FIREFOX+' Focus']], [\n /\\bopt\\/([\\w\\.]+)/i // Opera Touch\n ], [VERSION, [NAME, OPERA+' Touch']], [\n /coc_coc\\w+\\/([\\w\\.]+)/i // Coc Coc Browser\n ], [VERSION, [NAME, 'Coc Coc']], [\n /dolfin\\/([\\w\\.]+)/i // Dolphin\n ], [VERSION, [NAME, 'Dolphin']], [\n /coast\\/([\\w\\.]+)/i // Opera Coast\n ], [VERSION, [NAME, OPERA+' Coast']], [\n /miuibrowser\\/([\\w\\.]+)/i // MIUI Browser\n ], [VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]], [\n /fxios\\/([\\w\\.-]+)/i // Firefox for iOS\n ], [VERSION, [NAME, FIREFOX]], [\n /\\bqihoobrowser\\/?([\\w\\.]*)/i // 360\n ], [VERSION, [NAME, '360']], [\n /\\b(qq)\\/([\\w\\.]+)/i // QQ\n ], [[NAME, /(.+)/, '$1Browser'], VERSION], [\n /(oculus|sailfish|huawei|vivo|pico)browser\\/([\\w\\.]+)/i\n ], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [ // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser\n /samsungbrowser\\/([\\w\\.]+)/i // Samsung Internet\n ], [VERSION, [NAME, SAMSUNG + ' Internet']], [\n /metasr[\\/ ]?([\\d\\.]+)/i // Sogou Explorer\n ], [VERSION, [NAME, 'Sogou Explorer']], [\n /(sogou)mo\\w+\\/([\\d\\.]+)/i // Sogou Mobile\n ], [[NAME, 'Sogou Mobile'], VERSION], [\n /(electron)\\/([\\w\\.]+) safari/i, // Electron-based App\n /(tesla)(?: qtcarbrowser|\\/(20\\d\\d\\.[-\\w\\.]+))/i, // Tesla\n /m?(qqbrowser|2345(?=browser|chrome|explorer))\\w*[\\/ ]?v?([\\w\\.]+)/i // QQ/2345\n ], [NAME, VERSION], [\n /(lbbrowser|rekonq)/i, // LieBao Browser/Rekonq\n /\\[(linkedin)app\\]/i // LinkedIn App for iOS & Android\n ], [NAME], [\n /ome\\/([\\w\\.]+) \\w* ?(iron) saf/i, // Iron\n /ome\\/([\\w\\.]+).+qihu (360)[es]e/i // 360\n ], [VERSION, NAME], [\n\n // WebView\n /((?:fban\\/fbios|fb_iab\\/fb4a)(?!.+fbav)|;fbav\\/([\\w\\.]+);)/i // Facebook App for iOS & Android\n ], [[NAME, FACEBOOK], VERSION], [\n /(Klarna)\\/([\\w\\.]+)/i, // Klarna Shopping Browser for iOS & Android\n /(kakao(?:talk|story))[\\/ ]([\\w\\.]+)/i, // Kakao App\n /(naver)\\(.*?(\\d+\\.[\\w\\.]+).*\\)/i, // Naver InApp\n /(daum)apps[\\/ ]([\\w\\.]+)/i, // Daum App\n /safari (line)\\/([\\w\\.]+)/i, // Line App for iOS\n /\\b(line)\\/([\\w\\.]+)\\/iab/i, // Line App for Android\n /(alipay)client\\/([\\w\\.]+)/i, // Alipay\n /(twitter)(?:and| f.+e\\/([\\w\\.]+))/i, // Twitter\n /(chromium|instagram|snapchat)[\\/ ]([-\\w\\.]+)/i // Chromium/Instagram/Snapchat\n ], [NAME, VERSION], [\n /\\bgsa\\/([\\w\\.]+) .*safari\\//i // Google Search Appliance on iOS\n ], [VERSION, [NAME, 'GSA']], [\n /musical_ly(?:.+app_?version\\/|_)([\\w\\.]+)/i // TikTok\n ], [VERSION, [NAME, 'TikTok']], [\n\n /headlesschrome(?:\\/([\\w\\.]+)| )/i // Chrome Headless\n ], [VERSION, [NAME, CHROME+' Headless']], [\n\n / wv\\).+(chrome)\\/([\\w\\.]+)/i // Chrome WebView\n ], [[NAME, CHROME+' WebView'], VERSION], [\n\n /droid.+ version\\/([\\w\\.]+)\\b.+(?:mobile safari|safari)/i // Android Browser\n ], [VERSION, [NAME, 'Android '+BROWSER]], [\n\n /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\\/v?([\\w\\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia\n ], [NAME, VERSION], [\n\n /version\\/([\\w\\.\\,]+) .*mobile\\/\\w+ (safari)/i // Mobile Safari\n ], [VERSION, [NAME, 'Mobile Safari']], [\n /version\\/([\\w(\\.|\\,)]+) .*(mobile ?safari|safari)/i // Safari & Safari Mobile\n ], [VERSION, NAME], [\n /webkit.+?(mobile ?safari|safari)(\\/[\\w\\.]+)/i // Safari < 3.0\n ], [NAME, [VERSION, strMapper, oldSafariMap]], [\n\n /(webkit|khtml)\\/([\\w\\.]+)/i\n ], [NAME, VERSION], [\n\n // Gecko based\n /(navigator|netscape\\d?)\\/([-\\w\\.]+)/i // Netscape\n ], [[NAME, 'Netscape'], VERSION], [\n /(wolvic|librewolf)\\/([\\w\\.]+)/i // Wolvic/LibreWolf\n ], [NAME, VERSION], [\n /mobile vr; rv:([\\w\\.]+)\\).+firefox/i // Firefox Reality\n ], [VERSION, [NAME, FIREFOX+' Reality']], [\n /ekiohf.+(flow)\\/([\\w\\.]+)/i, // Flow\n /(swiftfox)/i, // Swiftfox\n /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\\/ ]?([\\w\\.\\+]+)/i,\n // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror\n /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\\/([-\\w\\.]+)$/i,\n // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix\n /(firefox)\\/([\\w\\.]+)/i, // Other Firefox-based\n /(mozilla)\\/([\\w\\.]+) .+rv\\:.+gecko\\/\\d+/i, // Mozilla\n\n // Other\n /(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\\. ]?browser)[-\\/ ]?v?([\\w\\.]+)/i,\n // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser/Ladybird\n /\\b(links) \\(([\\w\\.]+)/i // Links\n ], [NAME, [VERSION, /_/g, '.']], [\n \n /(cobalt)\\/([\\w\\.]+)/i // Cobalt\n ], [NAME, [VERSION, /master.|lts./, \"\"]]\n ],\n\n cpu : [[\n\n /\\b((amd|x|x86[-_]?|wow|win)64)\\b/i // AMD64 (x64)\n ], [[ARCHITECTURE, 'amd64']], [\n\n /(ia32(?=;))/i, // IA32 (quicktime)\n /\\b((i[346]|x)86)(pc)?\\b/i // IA32 (x86)\n ], [[ARCHITECTURE, 'ia32']], [\n\n /\\b(aarch64|arm(v?[89]e?l?|_?64))\\b/i // ARM64\n ], [[ARCHITECTURE, 'arm64']], [\n\n /\\b(arm(v[67])?ht?n?[fl]p?)\\b/i // ARMHF\n ], [[ARCHITECTURE, 'armhf']], [\n\n // PocketPC mistakenly identified as PowerPC\n /( (ce|mobile); ppc;|\\/[\\w\\.]+arm\\b)/i\n ], [[ARCHITECTURE, 'arm']], [\n\n /((ppc|powerpc)(64)?)( mac|;|\\))/i // PowerPC\n ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [\n\n / sun4\\w[;\\)]/i // SPARC\n ], [[ARCHITECTURE, 'sparc']], [\n\n /\\b(avr32|ia64(?=;)|68k(?=\\))|\\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\\b|pa-risc)/i\n // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC\n ], [[ARCHITECTURE, lowerize]]\n ],\n\n device : [[\n\n //////////////////////////\n // MOBILES & TABLETS\n /////////////////////////\n\n // Samsung\n /\\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\n ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [\n /\\b((?:s[cgp]h|gt|sm)-(?![lr])\\w+|sc[g-]?[\\d]+a?|galaxy nexus)/i,\n /samsung[- ]((?!sm-[lr])[-\\w]+)/i,\n /sec-(sgh\\w+)/i\n ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [\n\n // Apple\n /(?:\\/|\\()(ip(?:hone|od)[\\w, ]*)(?:\\/|;)/i // iPod/iPhone\n ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [\n /\\((ipad);[-\\w\\),; ]+apple/i, // iPad\n /applecoremedia\\/[\\w\\.]+ \\((ipad)/i,\n /\\b(ipad)\\d\\d?,\\d\\d?[;\\]].+ios/i\n ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [\n /(macintosh);/i\n ], [MODEL, [VENDOR, APPLE]], [\n\n // Sharp\n /\\b(sh-?[altvz]?\\d\\d[a-ekm]?)/i\n ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [\n\n // Honor\n /\\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\\)|;)/i\n ], [MODEL, [VENDOR, HONOR], [TYPE, TABLET]], [\n /honor([-\\w ]+)[;\\)]/i\n ], [MODEL, [VENDOR, HONOR], [TYPE, MOBILE]], [\n\n // Huawei\n /\\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\n ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [\n /(?:huawei)([-\\w ]+)[;\\)]/i,\n /\\b(nexus 6p|\\w{2,4}e?-[atu]?[ln][\\dx][012359c][adn]?)\\b(?!.+d\\/s)/i\n ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [\n\n // Xiaomi\n /oid[^\\)]+; (2[\\dbc]{4}(182|283|rp\\w{2})[cgl]|m2105k81a?c)(?: bui|\\))/i,\n /\\b((?:red)?mi[-_ ]?pad[\\w- ]*)(?: bui|\\))/i // Mi Pad tablets\n ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [\n\n /\\b(poco[\\w ]+|m2\\d{3}j\\d\\d[a-z]{2})(?: bui|\\))/i, // Xiaomi POCO\n /\\b; (\\w+) build\\/hm\\1/i, // Xiaomi Hongmi 'numeric' models\n /\\b(hm[-_ ]?note?[_ ]?(?:\\d\\w)?) bui/i, // Xiaomi Hongmi\n /\\b(redmi[\\-_ ]?(?:note|k)?[\\w_ ]+)(?: bui|\\))/i, // Xiaomi Redmi\n /oid[^\\)]+; (m?[12][0-389][01]\\w{3,6}[c-y])( bui|; wv|\\))/i, // Xiaomi Redmi 'numeric' models\n /\\b(mi[-_ ]?(?:a\\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\\d?\\w?)[_ ]?(?:plus|se|lite|pro)?)(?: bui|\\))/i, // Xiaomi Mi\n / ([\\w ]+) miui\\/v?\\d/i\n ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [\n\n // OPPO\n /; (\\w+) bui.+ oppo/i,\n /\\b(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007|a101op)\\b/i\n ], [MODEL, [VENDOR, OPPO], [TYPE, MOBILE]], [\n /\\b(opd2(\\d{3}a?))(?: bui|\\))/i\n ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['304', '403', '203'], '*' : OPPO }], [TYPE, TABLET]], [\n\n // Vivo\n /vivo (\\w+)(?: bui|\\))/i,\n /\\b(v[12]\\d{3}\\w?[at])(?: bui|;)/i\n ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [\n\n // Realme\n /\\b(rmx[1-3]\\d{3})(?: bui|;|\\))/i\n ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [\n\n // Motorola\n /\\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\\b[\\w ]+build\\//i,\n /\\bmot(?:orola)?[- ](\\w*)/i,\n /((?:moto(?! 360)[\\w\\(\\) ]+|xt\\d{3,4}|nexus 6)(?= bui|\\)))/i\n ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [\n /\\b(mz60\\d|xoom[2 ]{0,2}) build\\//i\n ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [\n\n // LG\n /((?=lg)?[vl]k\\-?\\d{3}) bui| 3\\.[-\\w; ]{10}lg?-([06cv9]{3,4})/i\n ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [\n /(lm(?:-?f100[nv]?|-[\\w\\.]+)(?= bui|\\))|nexus [45])/i,\n /\\blg[-e;\\/ ]+((?!browser|netcast|android tv|watch)\\w+)/i,\n /\\blg-?([\\d\\w]+) bui/i\n ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [\n\n // Lenovo\n /(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,\n /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\\w- ]+?)|tb[\\w-]{6,7})( bui|;|\\)|\\/)/i\n ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [\n\n // Nokia\n /(nokia) (t[12][01])/i\n ], [VENDOR, MODEL, [TYPE, TABLET]], [\n /(?:maemo|nokia).*(n900|lumia \\d+|rm-\\d+)/i,\n /nokia[-_ ]?(([-\\w\\. ]*))/i\n ], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [\n\n // Google\n /(pixel (c|tablet))\\b/i // Google Pixel C/Tablet\n ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [\n /droid.+; (pixel[\\daxl ]{0,6})(?: bui|\\))/i // Google Pixel\n ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [\n\n // Sony\n /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\n ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [\n /sony tablet [ps]/i,\n /\\b(?:sony)?sgp\\w+(?: bui|\\))/i\n ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [\n\n // OnePlus\n / (kb2005|in20[12]5|be20[12][59])\\b/i,\n /(?:one)?(?:plus)? (a\\d0\\d\\d)(?: b|\\))/i\n ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [\n\n // Amazon\n /(alexa)webm/i,\n /(kf[a-z]{2}wi|aeo(?!bc)\\w\\w)( bui|\\))/i, // Kindle Fire without Silk / Echo Show\n /(kf[a-z]+)( bui|\\)).+silk\\//i // Kindle Fire HD\n ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [\n /((?:sd|kf)[0349hijorstuw]+)( bui|\\)).+silk\\//i // Fire Phone\n ], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [\n\n // BlackBerry\n /(playbook);[-\\w\\),; ]+(rim)/i // BlackBerry PlayBook\n ], [MODEL, VENDOR, [TYPE, TABLET]], [\n /\\b((?:bb[a-f]|st[hv])100-\\d)/i,\n /\\(bb10; (\\w+)/i // BlackBerry 10\n ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [\n\n // Asus\n /(?:\\b|asus_)(transfo[prime ]{4,10} \\w+|eeepc|slider \\w+|nexus 7|padfone|p00[cj])/i\n ], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [\n / (z[bes]6[027][012][km][ls]|zenfone \\d\\w?)\\b/i\n ], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [\n\n // HTC\n /(nexus 9)/i // HTC Nexus 9\n ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [\n /(htc)[-;_ ]{1,2}([\\w ]+(?=\\)| bui)|\\w+)/i, // HTC\n\n // ZTE\n /(zte)[- ]([\\w ]+?)(?: bui|\\/|\\))/i,\n /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\\.))|sony(?!-bra))[-_ ]?([-\\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony\n ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [\n\n // TCL\n /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\n ], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [\n\n // itel\n /(itel) ((\\w+))/i\n ], [[VENDOR, lowerize], MODEL, [TYPE, strMapper, { 'tablet' : ['p10001l', 'w7001'], '*' : 'mobile' }]], [\n\n // Acer\n /droid.+; ([ab][1-7]-?[0178a]\\d\\d?)/i\n ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [\n\n // Meizu\n /droid.+; (m[1-5] note) bui/i,\n /\\bmz-([-\\w]{2,})/i\n ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [\n \n // Ulefone\n /; ((?:power )?armor(?:[\\w ]{0,8}))(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [\n\n // Energizer\n /; (energy ?\\w+)(?: bui|\\))/i,\n /; energizer ([\\w ]+)(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]], [\n\n // Cat\n /; cat (b35);/i,\n /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]], [\n\n // Smartfren\n /((?:new )?andromax[\\w- ]+)(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [\n\n // Nothing\n /droid.+; (a(?:015|06[35]|142p?))/i\n ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [\n\n // Archos\n /; (x67 5g|tikeasy \\w+|ac[1789]\\d\\w+)( b|\\))/i,\n /archos ?(5|gamepad2?|([\\w ]*[t1789]|hello) ?\\d+[\\w ]*)( b|\\))/i\n ], [MODEL, [VENDOR, 'Archos'], [TYPE, TABLET]], [\n /archos ([\\w ]+)( b|\\))/i,\n /; (ac[3-6]\\d\\w{2,8})( b|\\))/i \n ], [MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]], [\n\n // MIXED\n /(imo) (tab \\w+)/i, // IMO\n /(infinix) (x1101b?)/i // Infinix XPad\n ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n /(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\\w]*)/i,\n // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan\n /; (hmd|imo) ([\\w ]+?)(?: bui|\\))/i, // HMD/IMO\n /(hp) ([\\w ]+\\w)/i, // HP iPAQ\n /(microsoft); (lumia[\\w ]+)/i, // Microsoft Lumia\n /(lenovo)[-_ ]?([-\\w ]+?)(?: bui|\\)|\\/)/i, // Lenovo\n /(oppo) ?([\\w ]+) bui/i // OPPO\n ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n\n /(kobo)\\s(ereader|touch)/i, // Kobo\n /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad\n /(kindle)\\/([\\w\\.]+)/i, // Kindle\n /(nook)[\\w ]+build\\/(\\w+)/i, // Nook\n /(dell) (strea[kpr\\d ]*[\\dko])/i, // Dell Streak\n /(le[- ]+pan)[- ]+(\\w{1,9}) bui/i, // Le Pan Tablets\n /(trinity)[- ]*(t\\d{3}) bui/i, // Trinity Tablets\n /(gigaset)[- ]+(q\\w{1,9}) bui/i, // Gigaset Tablets\n /(vodafone) ([\\w ]+)(?:\\)| bui)/i // Vodafone\n ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n /(surface duo)/i // Surface Duo\n ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [\n /droid [\\d\\.]+; (fp\\du?)(?: b|\\))/i // Fairphone\n ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [\n /(u304aa)/i // AT&T\n ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [\n /\\bsie-(\\w*)/i // Siemens\n ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [\n /\\b(rct\\w+) b/i // RCA Tablets\n ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [\n /\\b(venue[\\d ]{2,7}) b/i // Dell Venue Tablets\n ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [\n /\\b(q(?:mv|ta)\\w+) b/i // Verizon Tablet\n ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [\n /\\b(?:barnes[& ]+noble |bn[rt])([\\w\\+ ]*) b/i // Barnes & Noble Tablet\n ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [\n /\\b(tm\\d{3}\\w+) b/i\n ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [\n /\\b(k88) b/i // ZTE K Series Tablet\n ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [\n /\\b(nx\\d{3}j) b/i // ZTE Nubia\n ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [\n /\\b(gen\\d{3}) b.+49h/i // Swiss GEN Mobile\n ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [\n /\\b(zur\\d{3}) b/i // Swiss ZUR Tablet\n ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [\n /\\b((zeki)?tb.*\\b) b/i // Zeki Tablets\n ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [\n /\\b([yr]\\d{2}) b/i,\n /\\b(dragon[- ]+touch |dt)(\\w{5}) b/i // Dragon Touch Tablet\n ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [\n /\\b(ns-?\\w{0,9}) b/i // Insignia Tablets\n ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [\n /\\b((nxa|next)-?\\w{0,9}) b/i // NextBook Tablets\n ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [\n /\\b(xtreme\\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones\n ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [\n /\\b(lvtel\\-)?(v1[12]) b/i // LvTel Phones\n ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [\n /\\b(ph-1) /i // Essential PH-1\n ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [\n /\\b(v(100md|700na|7011|917g).*\\b) b/i // Envizen Tablets\n ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [\n /\\b(trio[-\\w\\. ]+) b/i // MachSpeed Tablets\n ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [\n /\\btu_(1491) b/i // Rotor Tablets\n ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [\n /((?:tegranote|shield t(?!.+d tv))[\\w- ]*?)(?: b|\\))/i // Nvidia Tablets\n ], [MODEL, [VENDOR, NVIDIA], [TYPE, TABLET]], [\n /(sprint) (\\w+)/i // Sprint Phones\n ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n /(kin\\.[onetw]{3})/i // Microsoft Kin\n ], [[MODEL, /\\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [\n /droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i // Zebra\n ], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [\n /droid.+; (ec30|ps20|tc[2-8]\\d[kx])\\)/i\n ], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [\n\n ///////////////////\n // SMARTTVS\n ///////////////////\n\n /smart-tv.+(samsung)/i // Samsung\n ], [VENDOR, [TYPE, SMARTTV]], [\n /hbbtv.+maple;(\\d+)/i\n ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [\n /(nux; netcast.+smarttv|lg (netcast\\.tv-201\\d|android tv))/i // LG SmartTV\n ], [[VENDOR, LG], [TYPE, SMARTTV]], [\n /(apple) ?tv/i // Apple TV\n ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [\n /crkey/i // Google Chromecast\n ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n /droid.+aft(\\w+)( bui|\\))/i // Fire TV\n ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [\n /(shield \\w+ tv)/i // Nvidia Shield TV\n ], [MODEL, [VENDOR, NVIDIA], [TYPE, SMARTTV]], [\n /\\(dtv[\\);].+(aquos)/i,\n /(aquos-tv[\\w ]+)\\)/i // Sharp\n ], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[\n /(bravia[\\w ]+)( bui|\\))/i // Sony\n ], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [\n /(mi(tv|box)-?\\w+) bui/i // Xiaomi\n ], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [\n /Hbbtv.*(technisat) (.*);/i // TechniSAT\n ], [VENDOR, MODEL, [TYPE, SMARTTV]], [\n /\\b(roku)[\\dx]*[\\)\\/]((?:dvp-)?[\\d\\.]*)/i, // Roku\n /hbbtv\\/\\d+\\.\\d+\\.\\d+ +\\([\\w\\+ ]*; *([\\w\\d][^;]*);([^;]*)/i // HbbTV devices\n ], [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]], [\n // SmartTV from Unidentified Vendors\n /droid.+; ([\\w- ]+) (?:android tv|smart[- ]?tv)/i\n ], [MODEL, [TYPE, SMARTTV]], [\n /\\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\\b/i\n ], [[TYPE, SMARTTV]], [\n\n ///////////////////\n // CONSOLES\n ///////////////////\n\n /(ouya)/i, // Ouya\n /(nintendo) ([wids3utch]+)/i // Nintendo\n ], [VENDOR, MODEL, [TYPE, CONSOLE]], [\n /droid.+; (shield)( bui|\\))/i // Nvidia Portable\n ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [\n /(playstation \\w+)/i // Playstation\n ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [\n /\\b(xbox(?: one)?(?!; xbox))[\\); ]/i // Microsoft Xbox\n ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [\n\n ///////////////////\n // WEARABLES\n ///////////////////\n\n /\\b(sm-[lr]\\d\\d[0156][fnuw]?s?|gear live)\\b/i // Samsung Galaxy Watch\n ], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [\n /((pebble))app/i, // Pebble\n /(asus|google|lg|oppo) ((pixel |zen)?watch[\\w ]*)( bui|\\))/i // Asus ZenWatch / LG Watch / Pixel Watch\n ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n /(ow(?:19|20)?we?[1-3]{1,3})/i // Oppo Watch\n ], [MODEL, [VENDOR, OPPO], [TYPE, WEARABLE]], [\n /(watch)(?: ?os[,\\/]|\\d,\\d\\/)[\\d\\.]+/i // Apple Watch\n ], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [\n /(opwwe\\d{3})/i // OnePlus Watch\n ], [MODEL, [VENDOR, ONEPLUS], [TYPE, WEARABLE]], [\n /(moto 360)/i // Motorola 360\n ], [MODEL, [VENDOR, MOTOROLA], [TYPE, WEARABLE]], [\n /(smartwatch 3)/i // Sony SmartWatch\n ], [MODEL, [VENDOR, SONY], [TYPE, WEARABLE]], [\n /(g watch r)/i // LG G Watch R\n ], [MODEL, [VENDOR, LG], [TYPE, WEARABLE]], [\n /droid.+; (wt63?0{2,3})\\)/i\n ], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [\n\n ///////////////////\n // XR\n ///////////////////\n\n /droid.+; (glass) \\d/i // Google Glass\n ], [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]], [\n /(pico) (4|neo3(?: link|pro)?)/i // Pico\n ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n /; (quest( \\d| pro)?)/i // Oculus Quest\n ], [MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]], [\n\n ///////////////////\n // EMBEDDED\n ///////////////////\n\n /(tesla)(?: qtcarbrowser|\\/[-\\w\\.]+)/i // Tesla\n ], [VENDOR, [TYPE, EMBEDDED]], [\n /(aeobc)\\b/i // Echo Dot\n ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [\n /(homepod).+mac os/i // Apple HomePod\n ], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [\n /windows iot/i\n ], [[TYPE, EMBEDDED]], [\n\n ////////////////////\n // MIXED (GENERIC)\n ///////////////////\n\n /droid .+?; ([^;]+?)(?: bui|; wv\\)|\\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors\n ], [MODEL, [TYPE, MOBILE]], [\n /droid .+?; ([^;]+?)(?: bui|\\) applew).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors\n ], [MODEL, [TYPE, TABLET]], [\n /\\b((tablet|tab)[;\\/]|focus\\/\\d(?!.+mobile))/i // Unidentifiable Tablet\n ], [[TYPE, TABLET]], [\n /(phone|mobile(?:[;\\/]| [ \\w\\/\\.]*safari)|pda(?=.+windows ce))/i // Unidentifiable Mobile\n ], [[TYPE, MOBILE]], [\n /droid .+?; ([\\w\\. -]+)( bui|\\))/i // Generic Android Device\n ], [MODEL, [VENDOR, 'Generic']]\n ],\n\n engine : [[\n\n /windows.+ edge\\/([\\w\\.]+)/i // EdgeHTML\n ], [VERSION, [NAME, EDGE+'HTML']], [\n\n /(arkweb)\\/([\\w\\.]+)/i // ArkWeb\n ], [NAME, VERSION], [\n\n /webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i // Blink\n ], [VERSION, [NAME, 'Blink']], [\n\n /(presto)\\/([\\w\\.]+)/i, // Presto\n /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\\/([\\w\\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo\n /ekioh(flow)\\/([\\w\\.]+)/i, // Flow\n /(khtml|tasman|links)[\\/ ]\\(?([\\w\\.]+)/i, // KHTML/Tasman/Links\n /(icab)[\\/ ]([23]\\.[\\d\\.]+)/i, // iCab\n\n /\\b(libweb)/i // LibWeb\n ], [NAME, VERSION], [\n /ladybird\\//i\n ], [[NAME, 'LibWeb']], [\n\n /rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i // Gecko\n ], [VERSION, NAME]\n ],\n\n os : [[\n\n // Windows\n /microsoft (windows) (vista|xp)/i // Windows (iTunes)\n ], [NAME, VERSION], [\n /(windows (?:phone(?: os)?|mobile|iot))[\\/ ]?([\\d\\.\\w ]*)/i // Windows Phone\n ], [NAME, [VERSION, strMapper, windowsVersionMap]], [\n /windows nt 6\\.2; (arm)/i, // Windows RT\n /windows[\\/ ]([ntce\\d\\. ]+\\w)(?!.+xbox)/i,\n /(?:win(?=3|9|n)|win 9x )([nt\\d\\.]+)/i\n ], [[VERSION, strMapper, windowsVersionMap], [NAME, 'Windows']], [\n\n // iOS/macOS\n /[adehimnop]{4,7}\\b(?:.*os ([\\w]+) like mac|; opera)/i, // iOS\n /(?:ios;fbsv\\/|iphone.+ios[\\/ ])([\\d\\.]+)/i,\n /cfnetwork\\/.+darwin/i\n ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [\n /(mac os x) ?([\\w\\. ]*)/i,\n /(macintosh|mac_powerpc\\b)(?!.+haiku)/i // Mac OS\n ], [[NAME, MAC_OS], [VERSION, /_/g, '.']], [\n\n // Mobile OSes\n /droid ([\\w\\.]+)\\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS\n ], [VERSION, NAME], [ \n /(ubuntu) ([\\w\\.]+) like android/i // Ubuntu Touch\n ], [[NAME, /(.+)/, '$1 Touch'], VERSION], [\n // Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen\n /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen|webos)\\w*[-\\/; ]?([\\d\\.]*)/i\n ], [NAME, VERSION], [\n /\\(bb(10);/i // BlackBerry 10\n ], [VERSION, [NAME, BLACKBERRY]], [\n /(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\\/ ]?([\\w\\.]*)/i // Symbian\n ], [VERSION, [NAME, 'Symbian']], [\n /mozilla\\/[\\d\\.]+ \\((?:mobile|tablet|tv|mobile; [\\w ]+); rv:.+ gecko\\/([\\w\\.]+)/i // Firefox OS\n ], [VERSION, [NAME, FIREFOX+' OS']], [\n /web0s;.+rt(tv)/i,\n /\\b(?:hp)?wos(?:browser)?\\/([\\w\\.]+)/i // WebOS\n ], [VERSION, [NAME, 'webOS']], [\n /watch(?: ?os[,\\/]|\\d,\\d\\/)([\\d\\.]+)/i // watchOS\n ], [VERSION, [NAME, 'watchOS']], [\n\n // Google Chromecast\n /crkey\\/([\\d\\.]+)/i // Google Chromecast\n ], [VERSION, [NAME, CHROME+'cast']], [\n /(cros) [\\w]+(?:\\)| ([\\w\\.]+)\\b)/i // Chromium OS\n ], [[NAME, CHROMIUM_OS], VERSION],[\n\n // Smart TVs\n /panasonic;(viera)/i, // Panasonic Viera\n /(netrange)mmh/i, // Netrange\n /(nettv)\\/(\\d+\\.[\\w\\.]+)/i, // NetTV\n\n // Console\n /(nintendo|playstation) ([wids345portablevuch]+)/i, // Nintendo/Playstation\n /(xbox); +xbox ([^\\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)\n\n // Other\n /\\b(joli|palm)\\b ?(?:os)?\\/?([\\w\\.]*)/i, // Joli/Palm\n /(mint)[\\/\\(\\) ]?(\\w*)/i, // Mint\n /(mageia|vectorlinux)[; ]/i, // Mageia/VectorLinux\n /([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,\n // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire\n /(hurd|linux)(?: arm\\w*| x86\\w*| ?)([\\w\\.]*)/i, // Hurd/Linux\n /(gnu) ?([\\w\\.]*)/i, // GNU\n /\\b([-frentopcghs]{0,5}bsd|dragonfly)[\\/ ]?(?!amd|[ix346]{1,2}86)([\\w\\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly\n /(haiku) (\\w+)/i // Haiku\n ], [NAME, VERSION], [\n /(sunos) ?([\\w\\.\\d]*)/i // Solaris\n ], [[NAME, 'Solaris'], VERSION], [\n /((?:open)?solaris)[-\\/ ]?([\\w\\.]*)/i, // Solaris\n /(aix) ((\\d)(?=\\.|\\)| )[\\w\\.])*/i, // AIX\n /\\b(beos|os\\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS\n /(unix) ?([\\w\\.]*)/i // UNIX\n ], [NAME, VERSION]\n ]\n };\n\n /////////////////\n // Constructor\n ////////////////\n\n var UAParser = function (ua, extensions) {\n\n if (typeof ua === OBJ_TYPE) {\n extensions = ua;\n ua = undefined;\n }\n\n if (!(this instanceof UAParser)) {\n return new UAParser(ua, extensions).getResult();\n }\n\n var _navigator = (typeof window !== UNDEF_TYPE && window.navigator) ? window.navigator : undefined;\n var _ua = ua || ((_navigator && _navigator.userAgent) ? _navigator.userAgent : EMPTY);\n var _uach = (_navigator && _navigator.userAgentData) ? _navigator.userAgentData : undefined;\n var _rgxmap = extensions ? extend(regexes, extensions) : regexes;\n var _isSelfNav = _navigator && _navigator.userAgent == _ua;\n\n this.getBrowser = function () {\n var _browser = {};\n _browser[NAME] = undefined;\n _browser[VERSION] = undefined;\n rgxMapper.call(_browser, _ua, _rgxmap.browser);\n _browser[MAJOR] = majorize(_browser[VERSION]);\n // Brave-specific detection\n if (_isSelfNav && _navigator && _navigator.brave && typeof _navigator.brave.isBrave == FUNC_TYPE) {\n _browser[NAME] = 'Brave';\n }\n return _browser;\n };\n this.getCPU = function () {\n var _cpu = {};\n _cpu[ARCHITECTURE] = undefined;\n rgxMapper.call(_cpu, _ua, _rgxmap.cpu);\n return _cpu;\n };\n this.getDevice = function () {\n var _device = {};\n _device[VENDOR] = undefined;\n _device[MODEL] = undefined;\n _device[TYPE] = undefined;\n rgxMapper.call(_device, _ua, _rgxmap.device);\n if (_isSelfNav && !_device[TYPE] && _uach && _uach.mobile) {\n _device[TYPE] = MOBILE;\n }\n // iPadOS-specific detection: identified as Mac, but has some iOS-only properties\n if (_isSelfNav && _device[MODEL] == 'Macintosh' && _navigator && typeof _navigator.standalone !== UNDEF_TYPE && _navigator.maxTouchPoints && _navigator.maxTouchPoints > 2) {\n _device[MODEL] = 'iPad';\n _device[TYPE] = TABLET;\n }\n return _device;\n };\n this.getEngine = function () {\n var _engine = {};\n _engine[NAME] = undefined;\n _engine[VERSION] = undefined;\n rgxMapper.call(_engine, _ua, _rgxmap.engine);\n return _engine;\n };\n this.getOS = function () {\n var _os = {};\n _os[NAME] = undefined;\n _os[VERSION] = undefined;\n rgxMapper.call(_os, _ua, _rgxmap.os);\n if (_isSelfNav && !_os[NAME] && _uach && _uach.platform && _uach.platform != 'Unknown') {\n _os[NAME] = _uach.platform \n .replace(/chrome os/i, CHROMIUM_OS)\n .replace(/macos/i, MAC_OS); // backward compatibility\n }\n return _os;\n };\n this.getResult = function () {\n return {\n ua : this.getUA(),\n browser : this.getBrowser(),\n engine : this.getEngine(),\n os : this.getOS(),\n device : this.getDevice(),\n cpu : this.getCPU()\n };\n };\n this.getUA = function () {\n return _ua;\n };\n this.setUA = function (ua) {\n _ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? trim(ua, UA_MAX_LENGTH) : ua;\n return this;\n };\n this.setUA(_ua);\n return this;\n };\n\n UAParser.VERSION = LIBVERSION;\n UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]);\n UAParser.CPU = enumerize([ARCHITECTURE]);\n UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);\n UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);\n\n ///////////\n // Export\n //////////\n\n // check js environment\n if (typeof(exports) !== UNDEF_TYPE) {\n // nodejs env\n if (typeof module !== UNDEF_TYPE && module.exports) {\n exports = module.exports = UAParser;\n }\n exports.UAParser = UAParser;\n } else {\n // requirejs env (optional)\n if (typeof(define) === FUNC_TYPE && define.amd) {\n define(function () {\n return UAParser;\n });\n } else if (typeof window !== UNDEF_TYPE) {\n // browser env\n window.UAParser = UAParser;\n }\n }\n\n // jQuery/Zepto specific (optional)\n // Note:\n // In AMD env the global scope should be kept clean, but jQuery is an exception.\n // jQuery always exports to global scope, unless jQuery.noConflict(true) is used,\n // and we should catch that.\n var $ = typeof window !== UNDEF_TYPE && (window.jQuery || window.Zepto);\n if ($ && !$.ua) {\n var parser = new UAParser();\n $.ua = parser.getResult();\n $.ua.get = function () {\n return parser.getUA();\n };\n $.ua.set = function (ua) {\n parser.setUA(ua);\n var result = parser.getResult();\n for (var prop in result) {\n $.ua[prop] = result[prop];\n }\n };\n }\n\n})(typeof window === 'object' ? window : this);\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","// 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 // Content test types\n ContentChange,\n ContentElement,\n ContentBlock,\n ContentCustomCode,\n ContentTestData,\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// Internal utilities (exported for advanced use cases)\nexport { hashString } 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 canAssignToTest,\n assignAllTests,\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// Split URL utilities\nexport {\n getSplitUrlBlockingScript,\n processSplitUrlTests,\n} from \"./handlers/splitUrl\";\nexport type { SplitUrlScriptOptions } from \"./handlers/splitUrl\";\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// Content test utilities\nexport {\n matchesWildcardPattern,\n applyContentChanges,\n applyContentElements,\n applyCustomCode,\n processContentTests,\n reprocessContentTests,\n setupContentTestListeners,\n hasContentTests,\n restoreOriginalElements,\n cleanupContentTests,\n} from \"./utils/content\";\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\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\";\nexport { ElevateAnalytics } from \"./components/ElevateAnalytics\";\nexport type {\n UseAnalyticsHook,\n ElevateHydrogenAnalyticsProps,\n} from \"./components/ElevateAnalytics\";\n\nexport { useElevateConfig } from \"./contexts/ElevateContext\";\n\nexport type {\n TestTypeHandler,\n HandlerContext,\n HandlerVariantData,\n} from \"./handlers/types\";\nexport {\n registerHandler,\n getHandler,\n getAllHandlers,\n hasHandler,\n} from \"./handlers/registry\";\n\n// Handlers\nexport { contentHandler } from \"./handlers/content\";\n\nexport const VERSION = \"1.1.2\";\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 * 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","import type { Test, Variation, ElevateConfig } from \"../types\";\nimport type { PreviewState } from \"../utils/preview\";\nimport { getAssignedVariant } from \"../utils/assignment\";\nimport { getCookie, setCookie, getJsonCookie } from \"../utils/storage\";\nimport { onNavigate } from \"../utils/navigation\";\n\nexport interface SplitUrlScriptOptions {\n configUrl: string;\n timeout?: number;\n}\n\nexport function getSplitUrlBlockingScript(\n options: SplitUrlScriptOptions\n): string {\n const { configUrl, timeout = 2000 } = options;\n\n return `(function(){\n if(new URLSearchParams(location.search).get('abtr')==='true')return;\n \n var style=document.createElement('style');\n style.id='eab-split-hide';\n style.textContent='body{opacity:0!important;visibility:hidden!important}';\n document.head.appendChild(style);\n \n window.__eab_reveal=function(){\n var s=document.getElementById('eab-split-hide');\n if(s)s.remove();\n window.__eab_reveal=null;\n };\n \n setTimeout(function(){\n if(window.__eab_reveal)window.__eab_reveal();\n },${timeout});\n \n if(window.eab_data){\n return;\n }\n \n var script=document.createElement('script');\n script.src='${configUrl}';\n script.onerror=function(){\n if(window.__eab_reveal)window.__eab_reveal();\n };\n document.head.appendChild(script);\n})();`;\n}\n\nfunction normalizeUrl(url: string): string {\n if (!url?.trim()) return \"\";\n\n try {\n const withoutProtocol = url.trim().replace(/^https?:\\/\\//, \"\");\n const withProtocol = `https://${withoutProtocol}`;\n const urlObj = new URL(withProtocol.replace(/\\/+$/, \"\"));\n\n if (urlObj.hostname.startsWith(\"www.\")) {\n urlObj.hostname = urlObj.hostname.substring(4);\n }\n\n return urlObj.toString().replace(/\\/+$/, \"\");\n } catch {\n return url.trim().replace(/\\/+$/, \"\");\n }\n}\n\nfunction urlMatches(currentUrl: string, urlList: string[]): boolean {\n const normalizedCurrent = normalizeUrl(currentUrl.split(\"?\")[0]);\n\n for (const url of urlList) {\n const normalizedTarget = normalizeUrl(url.split(\"?\")[0]);\n if (normalizedCurrent === normalizedTarget) {\n return true;\n }\n // Also check pathname match for same-origin URLs\n try {\n const currentPath = new URL(currentUrl).pathname;\n const targetPath = new URL(url, currentUrl).pathname;\n if (currentPath === targetPath) {\n return true;\n }\n } catch {\n // Ignore URL parse errors\n }\n }\n return false;\n}\n\ntype RedirectBehavior =\n | \"redirectAll\"\n | \"redirectOnlyControlUrl\"\n | \"redirectOnce\"\n | \"redirectOnceControlUrlOnly\";\n\nfunction getRedirectBehavior(test: Test): RedirectBehavior {\n return (\n ((test as any).data?.redirectBehavior as RedirectBehavior) || \"redirectAll\"\n );\n}\n\nfunction hasBeenRedirected(testId: string): boolean {\n const redirectedTests =\n getJsonCookie<Record<string, boolean>>(\"eabRedirectedTests\") || {};\n return !!redirectedTests[testId];\n}\n\nfunction markAsRedirected(testId: string): void {\n const redirectedTests =\n getJsonCookie<Record<string, boolean>>(\"eabRedirectedTests\") || {};\n redirectedTests[testId] = true;\n setCookie(\"eabRedirectedTests\", JSON.stringify(redirectedTests));\n}\n\n/**\n * Find SPLIT_URL test that matches current URL\n */\nfunction findMatchingSplitUrlTest(\n config: ElevateConfig,\n currentUrl: string\n): { test: Test; matchedVariation: Variation; isControlUrl: boolean } | null {\n for (const test of config.tests) {\n if (test.type !== \"SPLIT_URL\" || !test.enabled) continue;\n\n for (const variation of test.variations) {\n const urls = (variation as any).splitUrlTestLinks || [];\n if (urls.length === 0) continue;\n\n if (urlMatches(currentUrl, urls)) {\n return {\n test,\n matchedVariation: variation,\n isControlUrl: !!variation.isControl,\n };\n }\n }\n }\n return null;\n}\n\n/**\n * Perform redirect using appropriate method for SPA frameworks\n */\nfunction performRedirect(targetUrl: string): void {\n if (typeof window === \"undefined\") return;\n\n // Add abtr=true param to prevent redirect loops\n const url = new URL(targetUrl, window.location.origin);\n url.searchParams.set(\"abtr\", \"true\");\n const finalUrl = url.toString();\n\n // Try SPA navigation first (Remix, Next.js, Nuxt)\n const navigate =\n (window as any).__remixRouter?.navigate ??\n (window as any).next?.router?.push ??\n (window as any).$nuxt?.$router?.push ??\n (window as any).__navigate;\n\n if (navigate && typeof navigate === \"function\") {\n try {\n const pathname = url.pathname + url.search;\n navigate(pathname);\n return;\n } catch {\n // Fall through to hard redirect\n }\n }\n\n // Hard redirect as fallback\n window.location.href = finalUrl;\n}\n\n/**\n * Process Split URL tests and redirect if needed\n * This is called automatically from ElevateProvider on mount.\n *\n * @returns true if a redirect was triggered, false otherwise\n */\nexport function processSplitUrlTests(\n config: ElevateConfig,\n previewState?: PreviewState | null | undefined\n): boolean {\n if (typeof window === \"undefined\") return false;\n\n const currentUrl = window.location.href;\n\n // Check if already redirected (abtr param present)\n const urlParams = new URLSearchParams(window.location.search);\n if (urlParams.get(\"abtr\") === \"true\") {\n return false;\n }\n\n // Find matching Split URL test\n const match = findMatchingSplitUrlTest(config, currentUrl);\n if (!match) return false;\n\n const { test, matchedVariation, isControlUrl } = match;\n const testId = test.testId;\n const redirectBehavior = getRedirectBehavior(test);\n\n const assignedVariationId = getAssignedVariant(testId);\n if (!assignedVariationId) return false;\n\n const assignedVariation = test.variations.find(\n (v) => v.id === assignedVariationId\n );\n if (!assignedVariation) return false;\n\n // Get target URLs for assigned variation\n const targetUrls = (assignedVariation as any).splitUrlTestLinks || [];\n if (targetUrls.length === 0) return false;\n\n // Check if already on assigned variation's URL\n if (urlMatches(currentUrl, targetUrls)) {\n return false; // Already on correct URL\n }\n\n // Apply redirect behavior rules\n switch (redirectBehavior) {\n case \"redirectOnlyControlUrl\":\n // Only redirect when on control URL\n if (!isControlUrl) return false;\n if (assignedVariation.isControl) return false; // Assigned to control, no redirect needed\n break;\n\n case \"redirectOnce\":\n // Redirect once from any URL\n if (hasBeenRedirected(testId)) return false;\n markAsRedirected(testId);\n break;\n\n case \"redirectOnceControlUrlOnly\":\n // Redirect once, but only from control URL\n if (!isControlUrl) return false;\n if (hasBeenRedirected(testId)) return false;\n if (assignedVariation.isControl) return false;\n markAsRedirected(testId);\n break;\n\n case \"redirectAll\":\n default:\n // Always redirect to assigned variation URL\n break;\n }\n\n // Perform the redirect\n const targetUrl = targetUrls[0];\n performRedirect(targetUrl);\n return true;\n}\n\n/**\n * Check if there are any active split URL tests\n */\nexport function hasSplitUrlTests(config: ElevateConfig): boolean {\n return config.tests.some((t) => t.type === \"SPLIT_URL\" && t.enabled);\n}\n\n/**\n * Setup event listeners for split URL test re-processing.\n *\n * Listens for ALL SPA navigation (pushState, replaceState, popstate)\n * and re-checks whether a redirect is needed on the new URL.\n */\nexport function setupSplitUrlTestListeners(\n config: ElevateConfig,\n previewState?: PreviewState | null\n): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n // Handle ALL SPA navigation (pushState, replaceState, popstate)\n const cleanupNavigation = onNavigate(() => {\n processSplitUrlTests(config, previewState);\n });\n\n return () => {\n cleanupNavigation();\n };\n}\n\nexport const splitUrlHandler = {\n type: \"SPLIT_URL\",\n\n shouldActivate(test: Test, context: { currentUrl: string }): boolean {\n for (const variation of test.variations) {\n const urls = (variation as any).splitUrlTestLinks || [];\n if (urlMatches(context.currentUrl, urls)) {\n return true;\n }\n }\n return false;\n },\n\n getVariantData() {\n return { handlerActivated: true };\n },\n};\n","/**\n * SPA Navigation Listener Utility\n *\n * Detects ALL client-side navigation in SPAs including:\n * - history.pushState() — link clicks handled by SPA routers\n * - history.replaceState() — in-place URL changes\n * - popstate — browser back/forward buttons\n *\n * The native `popstate` event only fires on back/forward navigation.\n * SPA routers (React Router, Remix, Next.js, etc.) navigate via\n * history.pushState(), which does NOT fire `popstate`.\n *\n * This utility monkey-patches pushState/replaceState to dispatch\n * a custom `eab:navigate` event, giving us a single event to\n * listen for ALL navigation types.\n */\n\nconst NAVIGATE_EVENT = \"eab:navigate\";\n\nlet patched = false;\nlet patchRefCount = 0;\nlet originalPushState: typeof history.pushState | null = null;\nlet originalReplaceState: typeof history.replaceState | null = null;\n\n/**\n * Patch history.pushState and history.replaceState to dispatch\n * a custom navigation event. Uses reference counting so multiple\n * callers can install/uninstall independently.\n */\nfunction patchHistory(): void {\n if (typeof window === \"undefined\") return;\n\n patchRefCount++;\n if (patched) return;\n patched = true;\n\n originalPushState = history.pushState.bind(history);\n originalReplaceState = history.replaceState.bind(history);\n\n history.pushState = function (...args: Parameters<typeof history.pushState>) {\n originalPushState!(...args);\n window.dispatchEvent(new Event(NAVIGATE_EVENT));\n };\n\n history.replaceState = function (\n ...args: Parameters<typeof history.replaceState>\n ) {\n originalReplaceState!(...args);\n window.dispatchEvent(new Event(NAVIGATE_EVENT));\n };\n}\n\n/**\n * Restore original history methods when no more listeners need them.\n */\nfunction unpatchHistory(): void {\n if (typeof window === \"undefined\") return;\n\n patchRefCount--;\n if (patchRefCount > 0 || !patched) return;\n\n if (originalPushState) {\n history.pushState = originalPushState;\n originalPushState = null;\n }\n if (originalReplaceState) {\n history.replaceState = originalReplaceState;\n originalReplaceState = null;\n }\n patched = false;\n}\n\n/**\n * Subscribe to ALL SPA navigation events (pushState, replaceState, popstate).\n *\n * The callback receives no arguments — the caller should read\n * `window.location` to determine the new URL.\n *\n * Returns a cleanup function that removes all listeners.\n *\n * @example\n * ```ts\n * const cleanup = onNavigate(() => {\n * // handle route change\n * });\n * // Later:\n * cleanup();\n * ```\n */\nexport function onNavigate(callback: () => void): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n // Keep track of the last URL to avoid duplicate calls\n // (e.g. replaceState to the same URL)\n let lastUrl = window.location.href;\n\n const handler = () => {\n const currentUrl = window.location.href;\n if (currentUrl === lastUrl) return;\n lastUrl = currentUrl;\n callback();\n };\n\n patchHistory();\n\n window.addEventListener(NAVIGATE_EVENT, handler);\n window.addEventListener(\"popstate\", handler);\n\n return () => {\n window.removeEventListener(NAVIGATE_EVENT, handler);\n window.removeEventListener(\"popstate\", handler);\n unpatchHistory();\n };\n}\n","/**\n * Analytics utilities for parsing and extracting data from events\n */\n\nimport { UAParser } from \"ua-parser-js\";\n\n// URL source mappings\nconst urlSources: Record<string, string> = {\n \"facebook.com\": \"Facebook\",\n \"fb.me\": \"Facebook\",\n \"m.facebook.com\": \"Facebook\",\n \"l.facebook.com\": \"Facebook\",\n \"lm.facebook.com\": \"Facebook\",\n \"instagram.com\": \"Instagram\",\n \"l.instagram.com\": \"Instagram\",\n \"youtube.com\": \"Youtube\",\n \"youtu.be\": \"Youtube\",\n \"m.youtube.com\": \"Youtube\",\n \"bing.com\": \"Bing\",\n \"www.bing.com\": \"Bing\",\n \"msnbc.msn.com\": \"Bing\",\n \"dizionario.it.msn.com\": \"Bing\",\n \"cc.bingj.com\": \"Bing\",\n \"m.bing.com\": \"Bing\",\n \"twitter.com\": \"Twitter\",\n \"t.co\": \"Twitter\",\n};\n\n/**\n * Sanitize string values to prevent XSS\n */\nexport function sanitizeString(value: unknown): string {\n if (typeof value !== \"string\") return String(value);\n return value.replace(/[\\\\\"'`\\x00-\\x1F\\x7F]/g, \"\");\n}\n\n/**\n * Round number to 2 decimal places\n */\nexport function roundToTwo(value: unknown): number | null {\n if (value === null || value === undefined) {\n return null;\n }\n const num = typeof value === \"string\" ? parseFloat(value) : Number(value);\n\n if (isNaN(num)) {\n return null;\n }\n return Number(Math.round(Number(num + \"e2\")) + \"e-2\");\n}\n\n/**\n * Extract product ID from Shopify GID\n */\nexport function extractProductId(gid: string | undefined): string | null {\n if (!gid) return null;\n const regex = /gid:\\/\\/shopify\\/Product\\/(\\d+)/;\n const match = gid.match(regex);\n return match ? match[1] : null;\n}\n\n/**\n * Extract product variant ID from Shopify GID\n */\nexport function extractProductVariantId(\n gid: string | undefined\n): string | null {\n if (!gid) return null;\n const regex = /gid:\\/\\/shopify\\/ProductVariant\\/(\\d+)/;\n const match = gid.match(regex);\n return match ? match[1] : null;\n}\n\n/**\n * Extract cart token from Shopify GID\n */\nexport function extractCartToken(\n gid: string | undefined | null\n): string | null {\n if (!gid) return null;\n const regex = /gid:\\/\\/shopify\\/Cart\\/([^?]+(\\?.+)?)/;\n const match = gid.match(regex);\n return match ? match[1] : null;\n}\n\n/**\n * Clean cart token by removing query parameters\n */\nexport function cleanCartToken(\n cartToken: string | null | undefined\n): string | null {\n try {\n if (typeof cartToken !== \"string\") {\n return null;\n }\n const decodedToken = decodeURIComponent(cartToken);\n const tokenPart = decodedToken.split(\"?\")[0];\n return tokenPart;\n } catch {\n // Silently fail - cart token extraction is not critical\n return cartToken || null;\n }\n}\n\n/**\n * Check if Facebook in-app browser\n */\nexport function checkFacebookBrowser(userAgent: string): boolean {\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(userAgent: string): boolean {\n const instagramBrowserRegex = /(instagram)[\\/ ]([-\\w\\.]+)/i;\n return instagramBrowserRegex.test(userAgent);\n}\n\n/**\n * Check if Facebook or Instagram browser\n */\nexport function checkFacebookInstagramBrowser(userAgent: string): boolean {\n return checkFacebookBrowser(userAgent) || checkInstagramBrowser(userAgent);\n}\n\n/**\n * Get browser name from UA parser result\n */\nfunction getBrowserName(browser: string | undefined): string {\n if (!browser) {\n return \"\";\n }\n switch (browser) {\n case \"Mobile Safari\":\n return \"Safari\";\n case \"Chrome Mobile\":\n case \"Chrome Mobile iOS\":\n return \"Chrome\";\n case \"Firefox Mobile\":\n case \"Firefox Mobile iOS\":\n return \"Firefox\";\n case \"Opera Mobile\":\n case \"Opera Mini\":\n case \"Opera Mini iOS\":\n return \"Opera\";\n case \"Yandex Browser Lite\":\n return \"Yandex Browser\";\n case \"Chrome Webview\":\n case \"Mobile App\":\n return \"Mobile App\";\n default:\n return browser;\n }\n}\n\n/**\n * Extract query parameters from URL\n */\nfunction getQueryParams(parsedUrl: URL): Record<string, string> {\n const queryParams: Record<string, string> = {};\n\n parsedUrl.searchParams.forEach((value, key) => {\n if (!queryParams[key]) {\n queryParams[key] = value;\n }\n });\n\n return queryParams;\n}\n\n/**\n * Check if referrer URI is valid\n */\nfunction isValidReferrerURI(uri: URL): boolean {\n return !!uri.host && [\"http:\", \"https:\"].includes(uri.protocol);\n}\n\n/**\n * Extract referrer source from hostname\n */\nfunction extractReferrerSource(host: string): string {\n return host.replace(/^www\\./, \"\");\n}\n\n/**\n * Parse referrer to determine traffic source\n */\nfunction parseReferrer(\n referrer: string | undefined,\n browser: string,\n siteHostname: string | undefined\n): string {\n const browserObj: Record<string, string> = {\n Facebook: \"Facebook\",\n Instagram: \"Instagram\",\n };\n if (browser && browserObj[browser]) {\n return browser;\n }\n\n let referrerObj: URL | undefined;\n let host: string | undefined;\n try {\n if (referrer && referrer.trim() !== '') {\n referrerObj = new URL(referrer);\n } else {\n return \"Direct\";\n }\n if (referrerObj?.hostname && isValidReferrerURI(referrerObj)) {\n host = referrerObj.hostname;\n if (siteHostname && siteHostname === host) {\n return \"Direct\";\n }\n } else {\n return \"\";\n }\n } catch {\n // Silently handle invalid referrer URLs\n }\n if (!host) {\n return \"\";\n }\n const source = extractReferrerSource(host);\n if (!source) {\n return \"\";\n }\n if (urlSources[source]) {\n return urlSources[source];\n }\n if (source?.includes(\"google\")) {\n return \"Google\";\n }\n return source;\n}\n\n/**\n * Parse and extract analytics view data from referrer, entry page, and user agent\n */\nexport interface ParsedViewData {\n referrer_source: string;\n browser_info: string;\n os_info: string;\n device_type: string;\n page_entry_path: string;\n utm_medium: string;\n utm_source: string;\n utm_campaign: string;\n utm_content: string;\n utm_term: string;\n referrer_url: string;\n gclid: string;\n fbclid: string;\n pins_campaign_id: string;\n epik: string;\n}\n\nexport function parseAddViewData(params: {\n referrer?: string;\n entryPage?: string;\n userAgent?: string;\n}): ParsedViewData {\n const { referrer, entryPage, userAgent } = params;\n\n const data: ParsedViewData = {\n referrer_source: \"\",\n browser_info: \"\",\n os_info: \"\",\n device_type: \"\",\n page_entry_path: \"\",\n utm_medium: \"\",\n utm_source: \"\",\n utm_campaign: \"\",\n utm_content: \"\",\n utm_term: \"\",\n referrer_url: referrer || \"\",\n gclid: \"\",\n fbclid: \"\",\n pins_campaign_id: \"\",\n epik: \"\",\n };\n\n try {\n let siteHostname: string | undefined;\n if (entryPage && entryPage.trim() !== '' && entryPage.startsWith('http')) {\n try {\n const entryObj = new URL(entryPage);\n const entryPath = entryObj?.pathname;\n siteHostname = entryObj?.hostname;\n if (entryPath) {\n data.page_entry_path = entryPath ?? \"\";\n }\n const entryQueryParams = getQueryParams(entryObj);\n data.utm_medium = entryQueryParams[\"utm_medium\"] ?? \"\";\n data.utm_source = entryQueryParams[\"utm_source\"] ?? \"\";\n data.utm_campaign = entryQueryParams[\"utm_campaign\"] ?? \"\";\n data.utm_content = entryQueryParams[\"utm_content\"] ?? \"\";\n data.utm_term = entryQueryParams[\"utm_term\"] ?? \"\";\n data.gclid = entryQueryParams[\"gclid\"] ?? \"\";\n data.fbclid = entryQueryParams[\"fbclid\"] ?? \"\";\n data.pins_campaign_id = entryQueryParams[\"pins_campaign_id\"] ?? \"\";\n data.epik = entryQueryParams[\"epik\"] ?? \"\";\n } catch {\n // Silently handle invalid URLs - entry page might be invalid in some contexts\n }\n }\n\n if (userAgent) {\n const userAgentObj = UAParser(userAgent);\n const browser = userAgentObj?.browser?.name;\n const browserName = getBrowserName(browser);\n data.browser_info = browserName ?? \"\";\n data.os_info = userAgentObj?.os?.name ?? \"\";\n if (userAgent) {\n data.device_type =\n (userAgentObj?.device?.type || \"desktop\")?.toUpperCase() ?? \"\";\n }\n }\n\n data.referrer_source =\n parseReferrer(referrer, data?.browser_info, siteHostname) ?? \"\";\n return data;\n } catch {\n // Return partial data on parse error\n return data;\n }\n}\n\n/**\n * Get page type from pathname\n */\nexport function getPageTypeFromPathname(\n path: string,\n hasLocalizedPaths?: boolean\n): string {\n const hasNormalPath = path === \"/\" || path === \"\";\n\n // Check if this is a localized homepage (e.g., /en-us/, /fr-ca/)\n const localizedHomepagePattern = /^\\/[a-z]{2}(-[a-z]{2})?\\/?$/i;\n const isLocalizedHomepage =\n hasLocalizedPaths && localizedHomepagePattern.test(path);\n\n if (hasNormalPath || isLocalizedHomepage) {\n return \"index\";\n }\n\n if (/\\/products\\//.test(path)) {\n return \"product\";\n }\n\n if (/\\/collections\\//.test(path)) {\n return \"collection\";\n }\n\n if (/\\/pages\\//.test(path)) {\n return \"page\";\n }\n if (/\\/search/.test(path)) {\n return \"search\";\n }\n\n if (/\\/cart/.test(path)) {\n return \"cart\";\n }\n\n if (/\\/checkouts\\//.test(path)) {\n return \"checkout\";\n }\n\n return \"unknown\";\n}\n\n/**\n * Check if visitor ID is in URL params\n */\nexport function checkVisitorIdParams(searchParams: string): string | false {\n try {\n if (!searchParams) return false;\n const params = new URLSearchParams(searchParams);\n return params.get(\"eabUserId\") || false;\n } catch {\n // URL parsing failed, return false\n return false;\n }\n}\n\n/**\n * Get user agent string without browser info\n * Used for more consistent user fingerprinting\n */\nexport function getUserAgentNoBrowser(userAgent: string): string {\n if (!userAgent) return \"\";\n\n try {\n const userAgentObj = UAParser(userAgent);\n const os = userAgentObj?.os;\n const device = userAgentObj?.device;\n\n let result = \"\";\n if (os?.name) {\n result += os.name;\n if (os.version) result += ` ${os.version}`;\n }\n if (device?.type) {\n result += result ? ` (${device.type})` : device.type;\n }\n if (device?.vendor) {\n result += result ? ` ${device.vendor}` : device.vendor;\n }\n if (device?.model) {\n result += result ? ` ${device.model}` : device.model;\n }\n\n return result || userAgent;\n } catch {\n return userAgent;\n }\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 * Content Test Utilities\n *\n * Handles DOM manipulation for Content Tests (Visual Editor Experiments).\n * Automatically applies changes, injects elements, and runs custom code\n * based on the assigned variant's content configuration.\n */\n\nimport type {\n ContentChange,\n ContentElement,\n ContentCustomCode,\n ContentTestData,\n ElevateConfig,\n Test,\n Variation,\n} from \"../types\";\nimport type { PreviewState } from \"./preview\";\nimport { getAssignedVariant } from \"./assignment\";\nimport { onNavigate } from \"./navigation\";\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst ELEMENT_ID_PREFIX = \"elv-el-\";\nconst NODE_TYPES = {\n ELEMENT_NODE: 1,\n TEXT_NODE: 3,\n};\n\n// ============================================================================\n// STATE MANAGEMENT\n// ============================================================================\n\n/** Tracks original elements for restoration on responsive changes */\nconst originalElements: Map<string, HTMLElement> = new Map();\n\n/** Tracks injected style elements for cleanup */\nconst injectedStyles: Map<string, HTMLStyleElement> = new Map();\n\n/** Tracks injected script elements for cleanup */\nconst injectedScripts: Map<string, HTMLScriptElement> = new Map();\n\n/** Tracks injected content elements for cleanup */\nconst injectedElements: Map<string, HTMLElement> = new Map();\n\n/** Current device type (for responsive changes) */\nlet isMobile = false;\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Check if a pathname matches a wildcard pattern\n * Supports: \"*\" (all), \"*\\/products\\/*\" (contains), \"*.json\" (ends with)\n */\nexport function matchesWildcardPattern(\n pathname: string,\n pattern: string\n): boolean {\n // Match all\n if (pattern === \"*\") return true;\n\n // Contains pattern: *something*\n if (pattern.startsWith(\"*\") && pattern.endsWith(\"*\")) {\n const trimmedPattern = pattern.slice(1, -1);\n return pathname.includes(trimmedPattern);\n }\n\n // Ends with pattern: *something\n if (pattern.startsWith(\"*\")) {\n const suffix = pattern.slice(1);\n return pathname.endsWith(suffix);\n }\n\n // Exact match\n return pattern === pathname;\n}\n\n/**\n * Check if current device is mobile (viewport width < 768px)\n */\nfunction checkIsMobile(): boolean {\n if (typeof window === \"undefined\") return false;\n return window.innerWidth < 768;\n}\n\n/**\n * Convert camelCase to kebab-case for CSS properties\n */\nfunction convertToKebabCase(text: string): string {\n let result = \"\";\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n if (char >= \"A\" && char <= \"Z\") {\n if (i !== 0) result += \"-\";\n result += char.toLowerCase();\n } else {\n result += char;\n }\n }\n return result;\n}\n\n/**\n * Check if a node is a text node\n */\nfunction isTextNode(node: Node): boolean {\n return node.nodeType === NODE_TYPES.TEXT_NODE;\n}\n\n/**\n * Check if a node is an element node\n */\nfunction isElementNode(node: Node): node is HTMLElement {\n return node.nodeType === NODE_TYPES.ELEMENT_NODE;\n}\n\n/**\n * Store original element for later restoration\n */\nfunction storeOriginalElement(selector: string, element: HTMLElement): void {\n if (!originalElements.has(selector)) {\n originalElements.set(selector, element.cloneNode(true) as HTMLElement);\n }\n}\n\n/**\n * Decode escaped characters in code strings\n */\nfunction decodeCodeString(code: string): string {\n let decoded = code;\n\n // Replace HTML entities (using replace with regex for ES2020 compatibility)\n decoded = decoded.replace(/`/g, \"`\").replace(/$/g, \"$\");\n\n // Try JSON decode for escaped characters\n try {\n decoded = JSON.parse('\"' + decoded + '\"');\n } catch {\n // If JSON.parse fails, use the partially decoded version\n }\n\n return decoded;\n}\n\n// ============================================================================\n// CONTENT CHANGES (Text, Styles, Attributes)\n// ============================================================================\n\n/**\n * Apply content changes to existing elements\n */\nexport function applyContentChanges(changes: ContentChange[]): void {\n if (typeof window === \"undefined\" || changes.length === 0) return;\n\n const currentPathname = window.location.pathname;\n\n // Filter changes that match current pathname\n const matchingChanges = changes.filter((change) => {\n if (!change.pathnames?.length) return true;\n return change.pathnames.some((pathname) =>\n matchesWildcardPattern(currentPathname, pathname)\n );\n });\n\n // Detect mobile/desktop\n isMobile = checkIsMobile();\n\n // Process each change with responsive support\n const processedChanges = matchingChanges.map((change) => ({\n ...change,\n // Merge responsive styles (lg + sm if mobile)\n style: change.style\n ? { ...change.style.lg, ...(isMobile && change.style.sm) }\n : undefined,\n // Select responsive content\n content:\n change.content && isMobile && change.content.sm\n ? change.content.sm\n : change.content?.lg,\n }));\n\n // Apply text content changes\n processedChanges\n .filter((change) => change.content !== undefined)\n .forEach((change) => {\n const elements = change.applyAll\n ? Array.from(document.querySelectorAll(change.selector))\n : [document.querySelector(change.selector)].filter(Boolean);\n\n elements.forEach((element, index) => {\n if (!element) return;\n\n const uniqueSelector = change.applyAll\n ? `${change.selector}-${index}-${\n element.id || Math.random().toString(36).substr(2, 9)\n }`\n : change.selector;\n\n storeOriginalElement(uniqueSelector, element as HTMLElement);\n\n // Apply content\n if (isTextNode(element)) {\n (element as unknown as Text).nodeValue = change.content!;\n } else if (isElementNode(element)) {\n element.innerHTML = change.content!;\n }\n });\n });\n\n // Apply style changes\n processedChanges\n .filter((change) => change.style !== undefined)\n .forEach((change) => {\n const element = document.querySelector(change.selector) as HTMLElement;\n if (!element || !isElementNode(element)) return;\n\n storeOriginalElement(change.selector, element);\n\n Object.entries(change.style!).forEach(([prop, value]) => {\n const kebabProp = convertToKebabCase(prop);\n const hasImportant = value.toString().includes(\"!important\");\n const cleanValue = value.toString().replace(/\\s*!important\\s*$/, \"\");\n\n element.style.setProperty(\n kebabProp,\n cleanValue,\n hasImportant ? \"important\" : undefined\n );\n });\n });\n\n // Apply attribute changes\n processedChanges\n .filter((change) => change.attributes !== undefined)\n .forEach((change) => {\n const element = document.querySelector(change.selector) as HTMLElement;\n if (!element || !isElementNode(element)) return;\n\n storeOriginalElement(change.selector, element);\n\n Object.entries(change.attributes!).forEach(([key, value]) => {\n element.setAttribute(key, value);\n });\n });\n}\n\n// ============================================================================\n// CONTENT ELEMENTS (HTML Injection)\n// ============================================================================\n\n/**\n * Apply content elements (inject new HTML elements)\n */\nexport function applyContentElements(elements: ContentElement[]): void {\n if (typeof window === \"undefined\" || elements.length === 0) return;\n\n const currentPathname = window.location.pathname;\n\n // Filter elements that match current pathname\n const matchingElements = elements.filter((element) => {\n if (!element.selector?.pathnames?.length) return true;\n return element.selector.pathnames.some((pathname) =>\n matchesWildcardPattern(currentPathname, pathname)\n );\n });\n\n matchingElements.forEach((element) => {\n const elementId = `${ELEMENT_ID_PREFIX}${element.id}`;\n\n const trackedElement = injectedElements.get(elementId);\n if (trackedElement && !document.contains(trackedElement)) {\n injectedElements.delete(elementId);\n }\n\n // Skip if already injected\n if (injectedElements.has(elementId)) return;\n\n const target = document.querySelector(element.selector.target);\n if (!target) return;\n\n // Check if element already exists in DOM\n if (target.parentElement?.querySelector(`#${elementId}`)) return;\n\n // Create the DOM element\n const domElement = createDOMElement(element);\n\n // Insert based on placement\n if (element.selector.placement === \"after\") {\n target.after(domElement);\n } else if (element.selector.placement === \"before\") {\n target.before(domElement);\n }\n\n // Track for cleanup\n injectedElements.set(elementId, domElement);\n });\n}\n\n/**\n * Create a DOM element from ContentElement definition\n */\nfunction createDOMElement(element: ContentElement): HTMLElement {\n const domElement = document.createElement(element.tagName);\n\n domElement.id = `${ELEMENT_ID_PREFIX}${element.id}`;\n\n // Apply styles\n if (element.style) {\n Object.assign(domElement.style, element.style);\n }\n\n // Apply attributes\n if (element.attributes) {\n Object.entries(element.attributes).forEach(([key, value]) => {\n domElement.setAttribute(key, value);\n });\n }\n\n // Set content for text elements\n if (element.kind === \"text\" && element.content) {\n domElement.innerText = element.content;\n }\n\n // Recursively render children for containers\n if (element.kind === \"container\" && element.childrens) {\n element.childrens.forEach((child) => {\n const childElement = createDOMElement(child);\n domElement.appendChild(childElement);\n });\n }\n\n return domElement;\n}\n\n// ============================================================================\n// CUSTOM CODE (CSS/JS Injection)\n// ============================================================================\n\n/**\n * Apply custom code (CSS and JS injection)\n */\nexport function applyCustomCode(\n customCodes: ContentCustomCode[],\n nonce?: string\n): void {\n if (typeof window === \"undefined\" || customCodes.length === 0) return;\n\n const currentPathname = window.location.pathname;\n\n // Filter codes that match current pathname\n const matchingCodes = customCodes.filter((code) => {\n // If no pathnames specified, run on all pages\n if (!code.pathnames?.length) return true;\n\n // Check excludes first\n if (code.excludePathnames?.length) {\n const isExcluded = code.excludePathnames.some((pathname) =>\n matchesWildcardPattern(currentPathname, pathname)\n );\n if (isExcluded) return false;\n }\n\n // Check includes\n return code.pathnames.some((pathname) =>\n matchesWildcardPattern(currentPathname, pathname)\n );\n });\n\n matchingCodes.forEach((code) => {\n if (!code.id) return;\n\n // Inject CSS\n if (code.css) {\n injectCSS(code.id, code.css);\n }\n\n // Inject JS\n if (code.js) {\n injectJS(code.id, code.js, nonce);\n }\n });\n}\n\n/**\n * Inject CSS into the page\n */\nfunction injectCSS(id: string, css: string): void {\n const styleId = `css-${id}`;\n\n const trackedStyle = injectedStyles.get(styleId);\n if (trackedStyle && !document.contains(trackedStyle)) {\n injectedStyles.delete(styleId);\n }\n\n if (injectedStyles.has(styleId) || document.getElementById(styleId)) return;\n\n const styleElement = document.createElement(\"style\");\n styleElement.id = styleId;\n styleElement.textContent = decodeCodeString(css);\n\n document.head.appendChild(styleElement);\n injectedStyles.set(styleId, styleElement);\n}\n\n/**\n * Inject JavaScript into the page\n */\nfunction injectJS(id: string, js: string, nonce?: string): void {\n const scriptId = `js-${id}`;\n\n const trackedScript = injectedScripts.get(scriptId);\n if (trackedScript && !document.contains(trackedScript)) {\n injectedScripts.delete(scriptId);\n }\n\n if (injectedScripts.has(scriptId) || document.getElementById(scriptId)) return;\n\n const scriptElement = document.createElement(\"script\");\n scriptElement.id = scriptId;\n\n // Add nonce for CSP compliance\n if (nonce) {\n scriptElement.setAttribute(\"nonce\", nonce);\n }\n\n // Wrap in try-catch for safety\n const decodedJs = decodeCodeString(js);\n scriptElement.textContent =\n \"(function(){try{\" +\n decodedJs +\n \"}catch(e){console.error('[ElevateAB] Custom script error:', e)}})();\";\n\n document.head.appendChild(scriptElement);\n injectedScripts.set(scriptId, scriptElement);\n}\n\n// ============================================================================\n// CLEANUP FUNCTIONS\n// ============================================================================\n\n/**\n * Restore original elements (for responsive changes or cleanup)\n */\nexport function restoreOriginalElements(): void {\n originalElements.forEach((originalElement, selector) => {\n // Try to find the element by selector\n const target = document.querySelector(selector);\n if (target) {\n target.replaceWith(originalElement.cloneNode(true));\n }\n });\n}\n\n/**\n * Clean up all injected content\n */\nexport function cleanupContentTests(): void {\n // Remove injected styles\n injectedStyles.forEach((style) => style.remove());\n injectedStyles.clear();\n\n // Remove injected scripts\n injectedScripts.forEach((script) => script.remove());\n injectedScripts.clear();\n\n // Remove injected elements\n injectedElements.forEach((element) => element.remove());\n injectedElements.clear();\n\n // Clear original elements cache\n originalElements.clear();\n}\n\n// ============================================================================\n// MAIN PROCESSOR\n// ============================================================================\n\n/**\n * Collect all content test data from assigned variants\n */\nfunction collectContentTestData(\n config: ElevateConfig,\n previewState?: PreviewState | null\n): ContentTestData {\n const allChanges: ContentChange[] = [];\n const allElements: ContentElement[] = [];\n const allCustomCodes: ContentCustomCode[] = [];\n\n // Find all CONTENT type tests\n const contentTests = config.tests.filter(\n (test) => test.type === \"CONTENT\" && test.enabled\n );\n\n contentTests.forEach((test) => {\n const assignedVariantId = getAssignedVariant(test.testId);\n if (!assignedVariantId) return;\n\n const variation = test.variations.find((v) => v.id === assignedVariantId);\n if (!variation?.content) return;\n\n // Collect content data\n if (variation.content.changes?.length) {\n allChanges.push(...variation.content.changes);\n }\n if (variation.content.elements?.length) {\n allElements.push(...variation.content.elements);\n }\n if (variation.content.customCodes?.length) {\n allCustomCodes.push(...variation.content.customCodes);\n }\n });\n\n return {\n changes: allChanges,\n elements: allElements,\n blocks: [], // Blocks deferred to v2\n customCodes: allCustomCodes,\n };\n}\n\n/**\n * Check if there are any active content tests\n */\nexport function hasContentTests(config: ElevateConfig): boolean {\n return config.tests.some((test) => test.type === \"CONTENT\" && test.enabled);\n}\n\n/**\n * Process and apply all content tests\n * This is the main entry point called by ElevateProvider\n */\nexport function processContentTests(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string\n): void {\n if (typeof window === \"undefined\") return;\n\n // Check if there are any content tests\n if (!hasContentTests(config)) return;\n\n // Collect all content data from assigned variants\n const contentData = collectContentTestData(config, previewState);\n\n // Check if there's anything to apply\n const hasContent =\n contentData.changes.length > 0 ||\n contentData.elements.length > 0 ||\n contentData.customCodes.length > 0;\n\n if (!hasContent) return;\n\n // Apply content changes\n applyContentChanges(contentData.changes);\n applyContentElements(contentData.elements);\n applyCustomCode(contentData.customCodes, nonce);\n}\n\n/**\n * Re-process content tests (called on pathname change or resize)\n */\nexport function reprocessContentTests(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string\n): void {\n if (typeof window === \"undefined\") return;\n\n // Check for responsive change\n const currentIsMobile = checkIsMobile();\n if (currentIsMobile !== isMobile) {\n // Responsive change - restore and reapply\n restoreOriginalElements();\n isMobile = currentIsMobile;\n }\n\n // Re-process content tests\n processContentTests(config, previewState, nonce);\n}\n\n/**\n * Setup event listeners for content test re-processing.\n *\n * Listens for ALL SPA navigation (pushState, replaceState, popstate)\n * via the shared navigation utility, plus resize for responsive changes.\n */\nexport function setupContentTestListeners(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string,\n listenToNavigation = true\n): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n // Handle resize for responsive changes\n const handleResize = () => {\n const currentIsMobile = checkIsMobile();\n if (currentIsMobile !== isMobile) {\n reprocessContentTests(config, previewState, nonce);\n }\n };\n\n window.addEventListener(\"resize\", handleResize);\n\n let cleanupNavigation = () => {};\n if (listenToNavigation) {\n // Handle ALL SPA navigation (pushState, replaceState, popstate)\n cleanupNavigation = onNavigate(() => {\n reprocessContentTests(config, previewState, nonce);\n });\n }\n\n // Return cleanup function\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n cleanupNavigation();\n cleanupContentTests();\n };\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 { getAssignedVariant } from \"../utils/assignment\";\nimport { trackViews } from \"../utils/tracking\";\nimport { getPreviewState } from \"../utils/preview\";\nimport { getHandler } from \"../handlers/registry\";\nimport type { HandlerContext } from \"../handlers/types\";\n\n// Import handlers to trigger auto-registration\nimport \"../handlers\";\n\nexport interface UseExperimentResult {\n /** The full variant object with handler data (null if not assigned) */\n variant: (Variation & Record<string, unknown>) | 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 * Build handler context from current environment\n */\nfunction buildHandlerContext(selectors?: unknown): HandlerContext {\n if (typeof window === \"undefined\") {\n return { currentUrl: \"\", selectors };\n }\n\n const url = window.location.href;\n const pathname = window.location.pathname;\n\n // Extract product info from URL\n let productHandle: string | undefined;\n const productMatch = pathname.match(/\\/products\\/([^\\/\\?]+)/);\n if (productMatch) {\n productHandle = productMatch[1];\n }\n\n // Try to detect variant ID from URL params\n let variantId: string | undefined;\n const urlParams = new URLSearchParams(window.location.search);\n const variantParam = urlParams.get(\"variant\");\n if (variantParam) {\n variantId = variantParam;\n }\n\n return {\n currentUrl: url,\n productHandle,\n variantId,\n selectors,\n currencyCode: \"USD\", // Default, could be detected from page\n };\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 {\n config,\n previewState: contextPreviewState,\n selectors,\n } = useElevateConfig();\n const [variant, setVariant] = React.useState<\n (Variation & Record<string, unknown>) | null\n >(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 // Get preview state - use context or get fresh\n const previewState = React.useMemo(() => {\n return contextPreviewState || getPreviewState();\n }, [contextPreviewState]);\n\n // Track if we've already warned about this test (prevent duplicate warnings)\n const hasWarnedRef = React.useRef<string | null>(null);\n // Track if effect has been applied (prevent duplicate DOM updates)\n const effectAppliedRef = React.useRef<string | null>(null);\n\n React.useEffect(() => {\n let isMounted = true;\n\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 if (isMounted) setIsLoading(false);\n return;\n }\n\n // Test exists but is disabled (but allow preview mode to override)\n if (!testConfig.enabled && !previewState?.isPreview) {\n if (hasWarnedRef.current !== `${testId}-disabled`) {\n hasWarnedRef.current = `${testId}-disabled`;\n console.warn(`[ElevateAB] Test disabled: ${testId}`);\n }\n if (isMounted) setIsLoading(false);\n return;\n }\n\n const assignedVariantId = getAssignedVariant(testId);\n if (!assignedVariantId) {\n if (isMounted) setIsLoading(false);\n return;\n }\n\n const assigned = testConfig.variations.find(\n (v) => v.id === assignedVariantId\n );\n if (!assigned) {\n if (isMounted) setIsLoading(false);\n return;\n }\n\n const handler = getHandler(testConfig.type);\n const context = buildHandlerContext(selectors);\n\n let enrichedVariant: Variation & Record<string, unknown> = {\n ...assigned,\n };\n\n if (handler?.shouldActivate(testConfig, context)) {\n const effectKey = `${testId}-${assigned.id}`;\n if (handler.applyEffect && effectAppliedRef.current !== effectKey) {\n effectAppliedRef.current = effectKey;\n handler.applyEffect(testConfig, assigned, context);\n }\n\n const handlerData = handler.getVariantData(testConfig, assigned, context);\n enrichedVariant = { ...enrichedVariant, ...handlerData };\n }\n\n if (isMounted) setVariant(enrichedVariant);\n\n if (!previewState?.isPreview) {\n trackViews(testId);\n }\n\n if (isMounted) setIsLoading(false);\n\n return () => {\n isMounted = false;\n };\n }, [config, testConfig, testId, previewState, selectors]);\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 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 type { TestTypeHandler } from \"./types\";\n\nconst handlers: Map<string, TestTypeHandler> = new Map();\n\nexport function registerHandler(handler: TestTypeHandler): void {\n handlers.set(handler.type, handler);\n}\n\nexport function getHandler(type: string): TestTypeHandler | undefined {\n return handlers.get(type);\n}\n\nexport function getAllHandlers(): TestTypeHandler[] {\n return Array.from(handlers.values());\n}\n\nexport function hasHandler(type: string): boolean {\n return handlers.has(type);\n}\n","\nimport type { Test, Variation } from \"../types\";\nimport type {\n TestTypeHandler,\n HandlerContext,\n HandlerVariantData,\n} from \"./types\";\n\nfunction extractProductHandleFromUrl(url: string): string | null {\n try {\n const urlObj = new URL(url, \"https://example.com\");\n const pathname = urlObj.pathname;\n\n // Match /products/{handle}\n const match = pathname.match(/\\/products\\/([^\\/\\?]+)/);\n return match ? match[1] : null;\n } catch {\n return null;\n }\n}\n\nfunction updatePriceElements(\n variation: Variation,\n variantId: string | undefined,\n currencyCode: string,\n selectors: unknown,\n): void {\n if (typeof window === \"undefined\") return;\n if (!variation.prices || !variantId) return;\n\n const variantPrices = variation.prices[variantId];\n if (!variantPrices) return;\n\n const priceAmount = variantPrices.price?.[currencyCode];\n const compareAmount = variantPrices.compare?.[currencyCode];\n\n // Get selectors configuration\n const selectorsConfig = selectors as {\n selectorsV2?: Array<{\n price?: string;\n compareAt?: string;\n saving?: Array<{ selector: string; isPercentage?: boolean }>;\n }>;\n };\n\n if (!selectorsConfig?.selectorsV2?.length) return;\n\n // Update each selector set\n for (const selectorSet of selectorsConfig.selectorsV2) {\n // Update price elements\n if (selectorSet.price && priceAmount) {\n const priceSelector = selectorSet.price.replace(\n \"{{variant}}\",\n variantId,\n );\n const priceElements = document.querySelectorAll(priceSelector);\n priceElements.forEach((el) => {\n // Format price with currency\n const formattedPrice = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: currencyCode,\n }).format(parseFloat(priceAmount));\n el.textContent = formattedPrice;\n });\n }\n\n // Update compare-at price elements\n if (selectorSet.compareAt && compareAmount) {\n const compareSelector = selectorSet.compareAt.replace(\n \"{{variant}}\",\n variantId,\n );\n const compareElements = document.querySelectorAll(compareSelector);\n compareElements.forEach((el) => {\n const formattedPrice = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: currencyCode,\n }).format(parseFloat(compareAmount));\n el.textContent = formattedPrice;\n });\n }\n\n // Update saving elements\n if (selectorSet.saving && priceAmount && compareAmount) {\n for (const savingConfig of selectorSet.saving) {\n const savingSelector = savingConfig.selector.replace(\n \"{{variant}}\",\n variantId,\n );\n const savingElements = document.querySelectorAll(savingSelector);\n savingElements.forEach((el) => {\n const price = parseFloat(priceAmount);\n const compare = parseFloat(compareAmount);\n const saving = compare - price;\n\n if (savingConfig.isPercentage) {\n const percentage = Math.round((saving / compare) * 100);\n el.textContent = `${percentage}%`;\n } else {\n const formattedSaving = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: currencyCode,\n }).format(saving);\n el.textContent = formattedSaving;\n }\n });\n }\n }\n }\n}\n\nexport const pricePlusHandler: TestTypeHandler = {\n type: \"PRICE_PLUS\",\n\n shouldActivate(test: Test, context: HandlerContext): boolean {\n const testData = (test as any).data;\n if (!testData) return false;\n\n // Get product identifiers from context\n const { productId, productHandle } = context;\n\n // Auto-detect from URL if not provided\n const urlHandle =\n productHandle || extractProductHandleFromUrl(context.currentUrl);\n\n // Check if this product matches the test\n const matchesProductId =\n productId && testData.productIds?.includes(productId);\n const matchesHandle = urlHandle && testData.handles?.includes(urlHandle);\n\n return matchesProductId || matchesHandle;\n },\n\n applyEffect(\n test: Test,\n variation: Variation,\n context: HandlerContext,\n ): void {\n // Update DOM elements using selectors\n updatePriceElements(\n variation,\n context.variantId,\n context.currencyCode || \"USD\",\n context.selectors,\n );\n },\n\n getVariantData(\n test: Test,\n variation: Variation,\n context: HandlerContext,\n ): HandlerVariantData {\n const testData = (test as any).data;\n\n // Return prices for manual rendering\n return {\n prices: variation.prices,\n matchedProductId: context.productId,\n productIds: testData?.productIds,\n handles: testData?.handles,\n handlerActivated: true,\n };\n },\n};\n","/**\n * Content Test Handler\n *\n * Handles CONTENT type tests (Visual Editor Experiments).\n * These tests modify page content without redirects - they can:\n * - Remove/hide elements\n * - Modify text/headings/descriptions\n * - Change CSS styles (colors, fonts, sizes)\n * - Add new HTML elements\n * - Modify attributes (href, src, etc.)\n * - Inject custom CSS/JS\n */\n\nimport type { Test, Variation } from \"../types\";\nimport type {\n TestTypeHandler,\n HandlerContext,\n HandlerVariantData,\n} from \"./types\";\nimport { matchesWildcardPattern } from \"../utils/content\";\n\n/**\n * Check if current URL matches any of the test's pathnames\n */\nfunction matchesTestPathnames(test: Test, currentUrl: string): boolean {\n const testData = (test as any).data;\n const pathnames: string[] = testData?.pathnames || [];\n\n // If no pathnames specified, match all pages\n if (!pathnames.length) return true;\n\n try {\n const url = new URL(currentUrl, \"https://example.com\");\n const pathname = url.pathname;\n\n // Check if any pathname pattern matches\n return pathnames.some((pattern) =>\n matchesWildcardPattern(pathname, pattern)\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Content test handler\n *\n * Note: Content test effects are applied by processContentTests in ElevateProvider,\n * not through the handler's applyEffect. This ensures all content tests are\n * processed together after variant assignment for better coordination.\n */\nexport const contentHandler: TestTypeHandler = {\n type: \"CONTENT\",\n\n shouldActivate(test: Test, context: HandlerContext): boolean {\n return matchesTestPathnames(test, context.currentUrl);\n },\n\n getVariantData(\n test: Test,\n variation: Variation,\n _context: HandlerContext\n ): HandlerVariantData {\n const testData = (test as any).data;\n\n return {\n content: variation.content,\n pathnames: testData?.pathnames,\n handlerActivated: true,\n };\n },\n};\n","/**\n * Custom Code Test Handler\n *\n * Handles CUSTOM_CODE type tests.\n * These tests inject custom CSS/JS into the page based on pathname matching.\n * Both control and non-control variations can have custom code.\n */\n\nimport type { Test, Variation } from \"../types\";\nimport type {\n TestTypeHandler,\n HandlerContext,\n HandlerVariantData,\n} from \"./types\";\nimport { matchesWildcardPattern } from \"../utils/content\";\n\n/**\n * Check if current URL matches any of the test's pathnames\n */\nfunction matchesTestPathnames(test: Test, currentUrl: string): boolean {\n const testData = (test as any).data;\n const pathnames: string[] = testData?.pathnames || [];\n\n // If no pathnames specified, match all pages\n if (!pathnames.length) return true;\n\n try {\n const url = new URL(currentUrl, \"https://example.com\");\n const pathname = url.pathname;\n\n // Check if any pathname pattern matches\n return pathnames.some((pattern) =>\n matchesWildcardPattern(pathname, pattern)\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Custom code test handler\n *\n * Note: Custom code effects are applied by processCustomCodeTests in ElevateProvider,\n * not through the handler's applyEffect. This ensures all custom code tests are\n * processed together after variant assignment for better coordination.\n */\nexport const customCodeHandler: TestTypeHandler = {\n type: \"CUSTOM_CODE\",\n\n shouldActivate(test: Test, context: HandlerContext): boolean {\n return matchesTestPathnames(test, context.currentUrl);\n },\n\n getVariantData(\n test: Test,\n variation: Variation,\n _context: HandlerContext\n ): HandlerVariantData {\n const testData = (test as any).data;\n\n return {\n customCode: variation.customCode,\n pathnames: testData?.pathnames,\n excludePathnames: testData?.excludePathnames,\n handlerActivated: true,\n };\n },\n};\n","export type {\n TestTypeHandler,\n HandlerContext,\n HandlerVariantData,\n} from \"./types\";\n\nexport {\n registerHandler,\n getHandler,\n getAllHandlers,\n hasHandler,\n} from \"./registry\";\n\nexport { pricePlusHandler } from \"./pricePlus\";\nexport { splitUrlHandler, processSplitUrlTests } from \"./splitUrl\";\nexport { contentHandler } from \"./content\";\nexport { customCodeHandler } from \"./customCode\";\n\nimport { registerHandler } from \"./registry\";\nimport { pricePlusHandler } from \"./pricePlus\";\nimport { splitUrlHandler } from \"./splitUrl\";\nimport { contentHandler } from \"./content\";\nimport { customCodeHandler } from \"./customCode\";\n\nregisterHandler(pricePlusHandler);\nregisterHandler(splitUrlHandler);\nregisterHandler(contentHandler);\nregisterHandler(customCodeHandler);","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 {\n processSplitUrlTests,\n getSplitUrlBlockingScript,\n hasSplitUrlTests,\n} from \"../handlers/splitUrl\";\nimport {\n processContentTests,\n setupContentTestListeners,\n hasContentTests,\n} from \"../utils/content\";\nimport {\n processCustomCodeTests,\n hasCustomCodeTests,\n} from \"../utils/customCode\";\nimport { assignAllTests } from \"../utils/assignment\";\nimport { onNavigate } from \"../utils/navigation\";\n\nconst CDN_BASE_URL = \"https://ds0wlyksfn0sb.cloudfront.net/headless\";\n\nfunction getStoreName(storeId: string): string {\n return storeId.replace(/^https?:\\/\\//, \"\").replace(\".myshopify.com\", \"\");\n}\n\nfunction getConfigUrl(storeId: string): string {\n return `${CDN_BASE_URL}/${getStoreName(storeId)}.js`;\n}\n\ninterface ElevateProviderSimpleProps {\n storeId: string;\n storefrontAccessToken?: string;\n preventFlickering?: boolean;\n flickerTimeout?: number;\n nonce?: string;\n children: React.ReactNode;\n}\n\nconst useIsomorphicLayoutEffect =\n typeof window !== \"undefined\" ? React.useLayoutEffect : React.useEffect;\n\nexport function ElevateProvider({\n storeId,\n storefrontAccessToken,\n preventFlickering = false,\n flickerTimeout = 3000,\n nonce,\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\n React.useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n initAnalytics({\n storeId,\n storefrontAccessToken,\n });\n\n const preview = getPreviewState();\n setPreviewState(preview);\n\n const country = getCountryCode();\n setCountryCode(country);\n }, [storeId, storefrontAccessToken]);\n\n const revealContent = useCallback(() => {\n if (typeof window !== \"undefined\" && (window as any).__eab_reveal) {\n (window as any).__eab_reveal();\n }\n }, []);\n\n React.useEffect(() => {\n async function fetchConfig() {\n try {\n const currentPreviewState =\n typeof window !== \"undefined\" ? getPreviewState() : null;\n\n let backendData: BackendConfig | null = null;\n\n if (typeof window !== \"undefined\" && (window as any).eab_data) {\n backendData = (window as any).eab_data;\n } else {\n const url = getConfigUrl(storeId);\n\n backendData = await new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = url;\n script.async = true;\n\n script.onload = () => {\n const data = (window as any).eab_data;\n script.remove();\n\n if (!data) {\n reject(\n new Error(\n \"Failed to load config: window.eab_data is undefined\",\n ),\n );\n } else {\n resolve(data);\n }\n };\n\n script.onerror = () => {\n script.remove();\n resolve({\n allTests: {},\n selectors: { selectorsV2: [] },\n } as BackendConfig);\n };\n\n document.head.appendChild(script);\n });\n }\n\n if (\n !backendData ||\n !backendData.allTests ||\n Object.keys(backendData.allTests).length === 0\n ) {\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n return;\n }\n\n if (backendData.subscriptionPaused) {\n console.error(\n `[ElevateAB] Subscription is paused or stopped for store: ${storeId}. ` +\n (backendData.subscriptionMessage ||\n \"A/B tests will not run. Please reactivate your subscription.\"),\n );\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n return;\n }\n\n const hasActiveTests =\n Object.keys(backendData.allTests || {}).length > 0;\n if (!hasActiveTests) {\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n return;\n }\n\n const parsedConfig = parseBackendConfig(backendData);\n\n assignAllTests(parsedConfig, currentPreviewState);\n\n if (parsedConfig.tests.some((t) => t.type === \"SPLIT_URL\")) {\n const redirected = processSplitUrlTests(\n parsedConfig,\n currentPreviewState,\n );\n if (redirected) return;\n }\n\n setConfig(parsedConfig);\n revealContent();\n } catch (err) {\n console.error(\"[ElevateAB] Failed to load config:\", err);\n setConfig({ tests: [], selectors: undefined });\n revealContent();\n }\n }\n\n fetchConfig();\n }, [storeId, revealContent]);\n\n useIsomorphicLayoutEffect(() => {\n if (!config || typeof window === \"undefined\") return;\n\n const applySplitUrlTests = (): boolean => {\n if (!hasSplitUrlTests(config)) return false;\n return processSplitUrlTests(config, previewState);\n };\n\n const applyNonRedirectTests = () => {\n if (hasContentTests(config)) {\n try {\n processContentTests(config, previewState, nonce);\n } catch (err) {\n console.error(\"[ElevateAB] Failed to apply CONTENT tests:\", err);\n }\n }\n\n if (hasCustomCodeTests(config)) {\n try {\n processCustomCodeTests(config, previewState, nonce);\n } catch (err) {\n console.error(\"[ElevateAB] Failed to apply CUSTOM_CODE tests:\", err);\n }\n }\n };\n\n // Apply on initial load with parsed config.\n if (!applySplitUrlTests()) {\n applyNonRedirectTests();\n }\n\n let navigationRafId: number | null = null;\n let navigationTimeoutId: number | null = null;\n\n // Re-apply all tests on SPA navigation.\n const cleanupNavigation = onNavigate(() => {\n // Run split URL checks immediately on navigation.\n if (applySplitUrlTests()) return;\n\n // Try immediately, then retry after the next paint frame so\n // content tests can target elements rendered by the new route.\n applyNonRedirectTests();\n if (navigationRafId !== null) {\n window.cancelAnimationFrame(navigationRafId);\n }\n if (navigationTimeoutId !== null) {\n window.clearTimeout(navigationTimeoutId);\n }\n navigationRafId = window.requestAnimationFrame(() => {\n applyNonRedirectTests();\n navigationTimeoutId = window.setTimeout(() => {\n applyNonRedirectTests();\n navigationTimeoutId = null;\n }, 80);\n navigationRafId = null;\n });\n });\n\n // Keep content resize handling, but avoid duplicate navigation listeners.\n const cleanupContent = hasContentTests(config)\n ? setupContentTestListeners(config, previewState, nonce, false)\n : () => {};\n\n return () => {\n if (navigationRafId !== null) {\n window.cancelAnimationFrame(navigationRafId);\n }\n if (navigationTimeoutId !== null) {\n window.clearTimeout(navigationTimeoutId);\n }\n cleanupNavigation();\n cleanupContent();\n };\n }, [config, previewState, nonce]);\n\n const value = React.useMemo(\n () => ({\n config,\n storeId,\n storefrontAccessToken,\n isPreviewMode: previewState?.isPreview ?? false,\n previewTestId: previewState?.previewTestId ?? null,\n previewState,\n selectors: config?.selectors,\n countryCode,\n }),\n [config, storeId, storefrontAccessToken, previewState, countryCode],\n );\n\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. Orders won't be attributed to test variants.\",\n );\n }\n }, [storefrontAccessToken]);\n\n const configUrl = React.useMemo(() => getConfigUrl(storeId), [storeId]);\n\n const blockingScript = React.useMemo(() => {\n const timeout = preventFlickering ? flickerTimeout : 2000;\n return getSplitUrlBlockingScript({ configUrl, timeout });\n }, [configUrl, preventFlickering, flickerTimeout]);\n\n return (\n <ElevateContext.Provider value={value}>\n <script\n nonce={nonce}\n dangerouslySetInnerHTML={{ __html: blockingScript }}\n />\n {children}\n </ElevateContext.Provider>\n );\n}\n","/**\n * Custom Code Test Utilities\n *\n * Handles processing and execution of CUSTOM_CODE type tests.\n * Custom code tests inject CSS/JS into the page based on pathname matching.\n * Both control and non-control variations can have custom code.\n */\n\nimport type { ContentCustomCode, ElevateConfig } from \"../types\";\nimport type { PreviewState } from \"./preview\";\nimport { getAssignedVariant } from \"./assignment\";\nimport { applyCustomCode } from \"./content\";\nimport { onNavigate } from \"./navigation\";\n\n/**\n * Check if there are any active custom code tests\n */\nexport function hasCustomCodeTests(config: ElevateConfig): boolean {\n return config.tests.some(\n (test) => test.type === \"CUSTOM_CODE\" && test.enabled\n );\n}\n\n/**\n * Process and apply all custom code tests\n * This is the main entry point called by ElevateProvider\n */\nexport function processCustomCodeTests(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string\n): void {\n if (typeof window === \"undefined\") return;\n\n // Check if there are any custom code tests\n if (!hasCustomCodeTests(config)) return;\n\n // Find all CUSTOM_CODE type tests\n const customCodeTests = config.tests.filter(\n (test) => test.type === \"CUSTOM_CODE\" && test.enabled\n );\n\n // Collect custom code from assigned variants\n const customCodes: ContentCustomCode[] = [];\n\n customCodeTests.forEach((test) => {\n const assignedVariantId = getAssignedVariant(test.testId);\n if (!assignedVariantId) return;\n\n const variation = test.variations.find((v) => v.id === assignedVariantId);\n if (!variation?.customCode) return;\n\n // Check if there's any code to inject\n if (variation.customCode.js || variation.customCode.css) {\n customCodes.push(variation.customCode);\n }\n });\n\n // Apply custom code if we have any\n if (customCodes.length > 0) {\n applyCustomCode(customCodes, nonce);\n }\n}\n\n/**\n * Re-process custom code tests (called on pathname change)\n */\nexport function reprocessCustomCodeTests(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string\n): void {\n if (typeof window === \"undefined\") return;\n\n // Re-process custom code tests\n processCustomCodeTests(config, previewState, nonce);\n}\n\n/**\n * Setup event listeners for custom code test re-processing.\n *\n * Listens for ALL SPA navigation (pushState, replaceState, popstate)\n * via the shared navigation utility.\n */\nexport function setupCustomCodeTestListeners(\n config: ElevateConfig,\n previewState?: PreviewState | null,\n nonce?: string\n): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n // Handle ALL SPA navigation (pushState, replaceState, popstate)\n const cleanupNavigation = onNavigate(() => {\n reprocessCustomCodeTests(config, previewState, nonce);\n });\n\n // Return cleanup function\n return () => {\n cleanupNavigation();\n };\n}\n","/**\n * ElevateAnalytics Component\n *\n * Internal component used by ElevateHydrogenAnalytics.\n * Subscribes to Hydrogen analytics events and sends them to Elevate.\n *\n * For Hydrogen stores, use ElevateHydrogenAnalytics instead - it's zero-config!\n * For Next.js/Remix, use manual tracking functions (trackPageView, trackAddToCart, etc.)\n */\n\nimport React, { useEffect, useContext, useRef } from \"react\";\nimport type { EventPayload, TestAssignment } from \"../types\";\nimport { ElevateContext } from \"../contexts/ElevateContext\";\n\n/**\n * Type for useAnalytics hook signature (matches @shopify/hydrogen)\n */\nexport type UseAnalyticsHook = () => {\n subscribe: (event: string, callback: (data: unknown) => void) => void;\n register: (name: string) => { ready: () => void };\n};\n\n/**\n * Props for ElevateHydrogenAnalytics (public API)\n */\nexport interface ElevateHydrogenAnalyticsProps {\n /** Override storeId from context (optional) */\n storeId?: string;\n /** Override storefrontAccessToken from context (optional) */\n storefrontAccessToken?: string;\n /** Enable localized path detection (e.g., /en-us/, /fr-ca/) */\n hasLocalizedPaths?: boolean;\n /** Custom CloudFlare Worker URL */\n workerUrl?: string;\n /** Custom orders worker URL */\n ordersWorkerUrl?: string;\n}\n\n/**\n * Internal props for ElevateAnalytics (requires useAnalytics hook)\n */\ninterface ElevateAnalyticsProps extends ElevateHydrogenAnalyticsProps {\n /** The useAnalytics hook from @shopify/hydrogen (required) */\n useAnalytics: UseAnalyticsHook;\n}\nimport {\n parseAddViewData,\n extractProductId,\n extractProductVariantId,\n extractCartToken,\n cleanCartToken,\n getPageTypeFromPathname,\n sanitizeString,\n roundToTwo,\n getUserAgentNoBrowser,\n} from \"../utils/analytics\";\nimport {\n getVisitorId,\n getSessionId,\n getCookie,\n getJsonCookie,\n setReferrerData,\n getReferrerData,\n} from \"../utils/storage\";\nimport { uuidv4 } from \"../utils/storage\";\nimport { updateCartAttributes } from \"../utils/cartAttributes\";\n\n// Default CloudFlare Worker endpoints\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// Generate pixel event ID\nfunction generatePixelEventId(): string {\n return `sh-${uuidv4()}`;\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/**\n * ElevateAnalytics - Subscribes to Hydrogen analytics events\n *\n * @internal Used by ElevateHydrogenAnalytics. For Hydrogen stores, use ElevateHydrogenAnalytics instead!\n */\nexport function ElevateAnalytics({\n storeId: storeIdProp,\n storefrontAccessToken: tokenProp,\n hasLocalizedPaths,\n workerUrl = DEFAULT_WORKER_URL,\n ordersWorkerUrl = DEFAULT_ORDERS_WORKER_URL,\n useAnalytics,\n}: ElevateAnalyticsProps) {\n // Get values from context, allow props to override\n const context = useContext(ElevateContext);\n const storeId = storeIdProp || context?.storeId || \"\";\n const storefrontAccessToken = tokenProp || context?.storefrontAccessToken;\n\n // Track if we've warned about missing context (warn only once)\n const hasWarnedContextRef = useRef(false);\n\n // Warn once if not inside ElevateProvider\n useEffect(() => {\n if (!context && !storeIdProp && !hasWarnedContextRef.current) {\n hasWarnedContextRef.current = true;\n console.error(\n \"[ElevateAB] ElevateAnalytics must be used inside ElevateProvider, \" +\n \"or you must pass storeId as a prop.\",\n );\n }\n }, [context, storeIdProp]);\n const { subscribe, register } = useAnalytics();\n const { ready } = register(\"Elevate Analytics\");\n\n useEffect(() => {\n // Skip in non-browser environments\n if (typeof window === \"undefined\") return;\n\n // Initialize visitor ID and session ID\n getVisitorId();\n getSessionId();\n\n // Initialize referrer data if not already set\n if (typeof document !== \"undefined\") {\n const currentReferrer = document.referrer || \"\";\n const currentUrl = window.location.href;\n setReferrerData(currentReferrer, currentUrl);\n }\n\n const setupAnalytics = () => {\n // Initialize state\n const initializeState = (event: any) => {\n const productPageId = extractProductId(event.products?.[0]?.id);\n if (productPageId && typeof localStorage !== \"undefined\") {\n localStorage.setItem(\"eabProductPageId\", productPageId);\n } else if (\n typeof window !== \"undefined\" &&\n !window.location.pathname.includes(\"/products/\")\n ) {\n localStorage?.removeItem(\"eabProductPageId\");\n }\n\n const cartToken = extractCartToken(\n typeof localStorage !== \"undefined\"\n ? localStorage.getItem(\"shopifyCartId\")\n : null,\n );\n\n const { referrer, entryPage } = getReferrerData();\n\n return {\n visitorId: getVisitorId(),\n sessionId: getSessionId(),\n cartToken: cartToken || getCookie(\"cart\") || \"\",\n referrer,\n entryPage,\n clientId: getCookie(\"_shopify_y\"),\n rootRoute:\n typeof localStorage !== \"undefined\"\n ? localStorage.getItem(\"eabRootRoute\") || \"\"\n : \"\",\n productPageId:\n typeof localStorage !== \"undefined\"\n ? localStorage.getItem(\"eabProductPageId\") || \"\"\n : \"\",\n };\n };\n\n // Create base event data\n const createBaseEventData = (\n eventName: string,\n pixelEventId: string,\n event: any,\n state: any,\n ): EventPayload => {\n const userAgent =\n typeof navigator !== \"undefined\" ? navigator.userAgent : \"\";\n const pathname = event?.url\n ? new URL(event.url).pathname\n : typeof window !== \"undefined\"\n ? window.location.pathname\n : \"\";\n const pageType = getPageTypeFromPathname(pathname, hasLocalizedPaths);\n\n const parsedData = parseAddViewData({\n referrer: state.referrer,\n entryPage: state.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 currentTimestamp = new Date().toISOString();\n\n // Get additional state from cookies/storage\n const isFirstVisit =\n typeof sessionStorage !== \"undefined\"\n ? sessionStorage.getItem(\"eabIsFirstVisit\") === \"true\"\n : false;\n const shopifyCountry = getCookie(\"localization\") || \"\";\n\n return {\n pixel_event_id: pixelEventId,\n shop_name: storeId,\n timestamp: currentTimestamp,\n event_type: eventName,\n client_id: state.clientId,\n visitor_id: state.visitorId,\n session_id: state.sessionId,\n cart_token: cleanCartToken(state.cartToken),\n\n page_url:\n event.context?.document?.location?.href ||\n (typeof window !== \"undefined\" ? window.location.href : \"\"),\n page_pathname: pathname,\n page_search:\n event.context?.document?.location?.search ||\n (typeof window !== \"undefined\" ? window.location.search : \"\"),\n referrer_url: state.referrer,\n referrer_source: parsedData?.referrer_source,\n previous_page:\n typeof document !== \"undefined\" ? document.referrer : \"\",\n page_entry: state.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:\n event.context?.navigator?.language ||\n (typeof navigator !== \"undefined\" ? navigator.language : \"\"),\n root_route: state.rootRoute,\n user_agent: userAgent,\n user_agent_no_browser: getUserAgentNoBrowser(userAgent),\n\n is_first_visit: isFirstVisit,\n shopify_country: shopifyCountry,\n\n cart_currency: event.shop?.currency,\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\n const sendEvent = async (data: EventPayload) => {\n if (data.exclude) return;\n\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\n return response;\n } catch (error) {\n console.error(\"[ElevateAB] Error sending analytics:\", error);\n }\n };\n\n // Event handlers\n const handlePageViewed = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const eventData = createBaseEventData(\n \"page_viewed\",\n pixelEventId,\n event,\n state,\n );\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\"[ElevateAB] Error handling page_viewed:\", error);\n }\n };\n\n const handleProductViewed = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"product_viewed\",\n pixelEventId,\n event,\n state,\n );\n\n const eventData: EventPayload = {\n ...baseData,\n product_id: extractProductId(event?.products?.[0]?.id) || \"\",\n product_vendor: sanitizeString(event?.products?.[0]?.vendor) ?? \"\",\n product_price: roundToTwo(event?.products?.[0]?.price) ?? null,\n product_sku: sanitizeString(event?.products?.[0]?.sku) ?? \"\",\n };\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\"[ElevateAB] Error handling product_viewed:\", error);\n }\n };\n\n const handleProductAddedToCart = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"product_added_to_cart\",\n pixelEventId,\n event,\n state,\n );\n\n const eventData: EventPayload = {\n ...baseData,\n product_id:\n extractProductId(event?.currentLine?.merchandise?.product?.id) ??\n \"\",\n variant_id:\n extractProductVariantId(event?.currentLine?.merchandise?.id) ??\n \"\",\n product_vendor:\n sanitizeString(\n event?.currentLine?.merchandise?.product?.vendor,\n ) ?? \"\",\n product_price:\n roundToTwo(event?.currentLine?.cost?.totalAmount?.amount) ?? null,\n product_quantity: event?.currentLine?.quantity ?? null,\n product_sku:\n sanitizeString(event?.currentLine?.merchandise?.sku) ?? \"\",\n };\n\n await sendEvent(eventData);\n\n // Update cart attributes with A/B test data (for order attribution)\n const cartId = event?.cart?.id;\n if (cartId && storefrontAccessToken && storeId) {\n updateCartAttributes(cartId, {\n storefrontAccessToken,\n storefrontApiUrl: `https://${storeId}/api/2025-01/graphql.json`,\n }).catch((err) => {\n console.error(\n \"[ElevateAB] Failed to update cart attributes:\",\n err,\n );\n });\n }\n } catch (error) {\n console.error(\n \"[ElevateAB] Error handling product_added_to_cart:\",\n error,\n );\n }\n };\n\n const handleProductRemovedFromCart = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"product_removed_from_cart\",\n pixelEventId,\n event,\n state,\n );\n\n const eventData: EventPayload = {\n ...baseData,\n product_id:\n extractProductId(event?.prevLine?.merchandise?.product?.id) ?? \"\",\n variant_id:\n extractProductVariantId(event?.prevLine?.merchandise?.id) ?? \"\",\n product_vendor:\n sanitizeString(event?.prevLine?.merchandise?.product?.vendor) ??\n \"\",\n product_price:\n roundToTwo(event?.prevLine?.cost?.totalAmount?.amount) ?? null,\n product_quantity: event?.prevLine?.quantity ?? null,\n product_sku:\n sanitizeString(event?.prevLine?.merchandise?.sku) ?? \"\",\n };\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\n \"[ElevateAB] Error handling product_removed_from_cart:\",\n error,\n );\n }\n };\n\n const handleCartViewed = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"cart_viewed\",\n pixelEventId,\n event,\n state,\n );\n\n const lines =\n event?.data?.cart?.lines?.nodes || event?.data?.cart?.lines || [];\n const cartProducts = lines.map((item: any) => ({\n product_id: extractProductId(item?.merchandise?.product?.id) ?? \"\",\n variant_id: extractProductVariantId(item?.merchandise?.id) ?? \"\",\n vendor: sanitizeString(item?.merchandise?.product?.vendor) ?? \"\",\n total_price: roundToTwo(item?.cost?.totalAmount?.amount) ?? null,\n quantity: item?.quantity ?? null,\n sku: sanitizeString(item?.merchandise?.sku) ?? \"\",\n }));\n\n const eventData: EventPayload = {\n ...baseData,\n cart_total_price:\n roundToTwo(event?.cart?.cost?.totalAmount?.amount) ?? null,\n cart_total_quantity: event?.cart?.totalQuantity ?? null,\n cart_items: cartProducts,\n };\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\"[ElevateAB] Error handling cart_viewed:\", error);\n }\n };\n\n const handleSearchSubmitted = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"search_submitted\",\n pixelEventId,\n event,\n state,\n );\n\n const eventData: EventPayload = {\n ...baseData,\n search_query:\n sanitizeString(event?.data?.searchResult?.query) ?? \"\",\n };\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\"[ElevateAB] Error handling search_submitted:\", error);\n }\n };\n\n const handleCheckoutStarted = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"checkout_started\",\n pixelEventId,\n event,\n state,\n );\n\n let totalQuantity = 0;\n const lineItems = event?.data?.checkout?.lineItems ?? [];\n const checkoutProducts = lineItems.map((item: any) => {\n const quantity = item?.quantity ?? 0;\n totalQuantity += quantity;\n\n const discountAllocations = item?.discountAllocations ?? [];\n const total_discount = discountAllocations?.reduce(\n (acc: number, discount: any) =>\n acc + (discount?.amount?.amount || 0),\n 0,\n );\n\n return {\n product_id: extractProductId(item?.variant?.product?.id) ?? \"\",\n variant_id: extractProductVariantId(item?.variant?.id) ?? \"\",\n vendor: sanitizeString(item?.variant?.product?.vendor) ?? \"\",\n total_price: roundToTwo(item?.finalLinePrice?.amount) ?? null,\n quantity: quantity,\n sku: sanitizeString(item?.variant?.sku) ?? \"\",\n total_discount: roundToTwo(total_discount) ?? null,\n };\n });\n\n const eventData: EventPayload = {\n ...baseData,\n cart_total_price:\n roundToTwo(event?.data?.checkout?.totalPrice?.amount) ?? null,\n cart_subtotal_price:\n roundToTwo(event?.data?.checkout?.subtotalPrice?.amount) ?? null,\n cart_total_quantity: totalQuantity,\n cart_shipping_price:\n roundToTwo(event?.data?.checkout?.shippingLine?.price?.amount) ??\n null,\n cart_tax_amount:\n roundToTwo(event?.data?.checkout?.totalTax?.amount) ?? null,\n cart_discount_amount:\n roundToTwo(event?.data?.checkout?.discountsAmount?.amount) ??\n null,\n cart_items: checkoutProducts,\n customer_id: event?.data?.checkout?.order?.customer?.id ?? \"\",\n };\n\n await sendEvent(eventData);\n } catch (error) {\n console.error(\"[ElevateAB] Error handling checkout_started:\", error);\n }\n };\n\n const handleCheckoutCompleted = async (event: any) => {\n try {\n const state = initializeState(event);\n const pixelEventId = generatePixelEventId();\n const baseData = createBaseEventData(\n \"checkout_completed\",\n pixelEventId,\n event,\n state,\n );\n\n let totalQuantity = 0;\n const lineItems = event?.data?.checkout?.lineItems ?? [];\n const checkoutProducts = lineItems.map((item: any) => {\n const quantity = item?.quantity ?? 0;\n totalQuantity += quantity;\n\n const discountAllocations = item?.discountAllocations ?? [];\n const total_discount = discountAllocations?.reduce(\n (acc: number, discount: any) =>\n acc + (discount?.amount?.amount || 0),\n 0,\n );\n\n return {\n product_id: extractProductId(item?.variant?.product?.id) ?? \"\",\n variant_id: extractProductVariantId(item?.variant?.id) ?? \"\",\n vendor: sanitizeString(item?.variant?.product?.vendor) ?? \"\",\n total_price: roundToTwo(item?.finalLinePrice?.amount) ?? null,\n quantity: quantity,\n sku: sanitizeString(item?.variant?.sku) ?? \"\",\n total_discount: roundToTwo(total_discount) ?? null,\n };\n });\n\n const eventData: EventPayload = {\n ...baseData,\n cart_total_price:\n roundToTwo(event?.data?.checkout?.totalPrice?.amount) ?? null,\n cart_subtotal_price:\n roundToTwo(event?.data?.checkout?.subtotalPrice?.amount) ?? null,\n cart_total_quantity: totalQuantity,\n cart_shipping_price:\n roundToTwo(event?.data?.checkout?.shippingLine?.price?.amount) ??\n null,\n cart_tax_amount:\n roundToTwo(event?.data?.checkout?.totalTax?.amount) ?? null,\n cart_discount_amount:\n roundToTwo(event?.data?.checkout?.discountsAmount?.amount) ??\n null,\n cart_items: checkoutProducts,\n order_id: event?.data?.checkout?.order?.id ?? \"\",\n customer_id: event?.data?.checkout?.order?.customer?.id ?? \"\",\n is_first_order:\n event?.data?.checkout?.order?.customer?.isFirstOrder ?? null,\n note_attributes: event?.data?.checkout?.attributes ?? [],\n };\n\n // Send to orders worker (different endpoint)\n await sendOrderEvent(eventData);\n } catch (error) {\n console.error(\n \"[ElevateAB] Error handling checkout_completed:\",\n error,\n );\n }\n };\n\n // Send event to orders CloudFlare Worker (for checkout_completed)\n const sendOrderEvent = async (data: EventPayload) => {\n if (data.exclude) return;\n\n try {\n const response = await fetch(ordersWorkerUrl, {\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(`Orders worker error: ${response.status}`);\n }\n\n return response;\n } catch (error) {\n console.error(\"[ElevateAB] Error sending order analytics:\", error);\n }\n };\n\n // Subscribe to events\n subscribe(\"page_viewed\", handlePageViewed);\n subscribe(\"product_viewed\", handleProductViewed);\n subscribe(\"product_added_to_cart\", handleProductAddedToCart);\n subscribe(\"product_removed_from_cart\", handleProductRemovedFromCart);\n subscribe(\"cart_viewed\", handleCartViewed);\n subscribe(\"search_submitted\", handleSearchSubmitted);\n subscribe(\"checkout_started\", handleCheckoutStarted);\n subscribe(\"checkout_completed\", handleCheckoutCompleted);\n };\n\n setupAnalytics();\n ready();\n }, [\n subscribe,\n ready,\n storeId,\n hasLocalizedPaths,\n storefrontAccessToken,\n workerUrl,\n ordersWorkerUrl,\n ]);\n\n return null;\n}\n"],"mappings":"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","names":["hashString","str","hash","i","char","parseBackendConfig","backendData","tests","testId","testData","variations","nonControlIndex","key","value","variation","isControl","rawContent","content","rawCustomCode","customCode","init_utils","__esmMin","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","init_storage","__esmMin","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","init_preview","__esmMin","init_storage","trackUniqueView","testId","addedUniqueViews","getJsonCookie","setCookie","trackSessionView","addedViews","getJsonSessionItem","setSessionItem","trackViews","hasSessionView","hasUniqueView","init_tracking","__esmMin","init_storage","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","init_assignment","__esmMin","init_storage","init_utils","init_preview","init_tracking","require_ua_parser","__commonJSMin","exports","module","window","undefined","LIBVERSION","EMPTY","UNKNOWN","FUNC_TYPE","UNDEF_TYPE","OBJ_TYPE","STR_TYPE","MAJOR","MODEL","NAME","TYPE","VENDOR","VERSION","ARCHITECTURE","CONSOLE","MOBILE","TABLET","SMARTTV","WEARABLE","EMBEDDED","UA_MAX_LENGTH","AMAZON","APPLE","ASUS","BLACKBERRY","BROWSER","CHROME","EDGE","FIREFOX","GOOGLE","HONOR","HUAWEI","LENOVO","LG","MICROSOFT","MOTOROLA","NVIDIA","ONEPLUS","OPERA","OPPO","SAMSUNG","SHARP","SONY","XIAOMI","ZEBRA","FACEBOOK","CHROMIUM_OS","MAC_OS","SUFFIX_BROWSER","extend","regexes","extensions","mergedRegexes","i","enumerize","arr","enums","has","str1","str2","lowerize","str","majorize","version","trim","len","rgxMapper","ua","arrays","j","k","p","q","matches","match","regex","props","strMapper","map","oldSafariMap","windowsVersionMap","UAParser","_navigator","_ua","_uach","_rgxmap","_isSelfNav","_browser","_cpu","_device","_engine","_os","$","parser","result","prop","CART_ATTRIBUTES_UPDATE_MUTATION","init_cartAttributes_mutation","__esmMin","cartAttributes_exports","__export","cleanupCartAttributes","getCartAttributesPayload","updateCartAttributes","testList","getTestList","addedUniqueViews","getJsonCookie","eabUserId","getCookie","isPreviewMode","abtidValue","viewedTests","testId","attributes","cartId","options","cartGid","storefrontUrl","getStoreDomain","response","CART_ATTRIBUTES_UPDATE_MUTATION","result","errorMsg","error","init_cartAttributes","__esmMin","init_assignment","init_storage","init_cartAttributes_mutation","index_exports","__export","CART_ATTRIBUTES_UPDATE_MUTATION","COUNTRIES","ElevateAnalytics","ElevateProvider","REGIONS","VERSION","applyContentChanges","applyContentElements","applyCustomCode","assignAllTests","assignAndPersistVariant","buildEabTestsParam","canAssignToTest","checkFacebookBrowser","checkFacebookInstagramBrowser","checkInstagramBrowser","checkPinterestBrowser","checkTikTokBrowser","checkVisitorIdParams","cleanCartToken","cleanupCartAttributes","cleanupContentTests","clearPreviewMode","contentHandler","deleteCookie","detectShopifyCurrency","extractCartToken","extractProductId","extractProductVariantId","extractShopifyId","extractShopifyType","getAllHandlers","getAssignedVariant","getCartAttributesPayload","getCookie","getCountryCode","getDeviceType","getGeoLocation","getHandler","getJsonCookie","getJsonSessionItem","getPageTypeFromPathname","getPreviewState","getPreviewVariation","getReferrerData","getSessionId","getSessionItem","getSplitUrlBlockingScript","getTestList","getTrafficSource","getUserAgentNoBrowser","getVisitorId","hasContentTests","hasHandler","hasSessionView","hasUniqueView","hashString","initAnalytics","initializeSessionId","initializeVisitorId","isCountryExcluded","isCountryIncluded","isInPreviewMode","isPreviewTest","isShopifyGid","matchesGeoTargeting","matchesWildcardPattern","parseAddViewData","processContentTests","processSplitUrlTests","registerHandler","reprocessContentTests","restoreOriginalElements","roundToTwo","sanitizeString","saveTestList","setCookie","setCountryCode","setGeoLocation","setReferrerData","setSessionItem","setupContentTestListeners","shouldShowTest","trackAddToCart","trackCartView","trackCheckoutCompleted","trackCheckoutStarted","trackPageView","trackProductView","trackRemoveFromCart","trackSearchSubmitted","trackSessionView","trackUniqueView","trackViews","updateCartAttributes","updateUrlWithTestParams","useElevateConfig","useExperiment","usePageViewTracking","uuidv4","__toCommonJS","init_utils","init_storage","init_assignment","init_tracking","getDeviceType","ua","lower","checkFacebookBrowser","userAgent","checkInstagramBrowser","checkTikTokBrowser","checkPinterestBrowser","getTrafficSource","referrer","referrerDomain","hostname","isFacebookBrowser","isInstagramBrowser","isTikTokBrowser","isPinterestBrowser","init_preview","init_storage","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","init_assignment","init_storage","NAVIGATE_EVENT","patched","patchRefCount","originalPushState","originalReplaceState","patchHistory","args","unpatchHistory","onNavigate","callback","lastUrl","handler","currentUrl","getSplitUrlBlockingScript","options","configUrl","timeout","normalizeUrl","url","withProtocol","urlObj","urlMatches","currentUrl","urlList","normalizedCurrent","normalizedTarget","currentPath","targetPath","getRedirectBehavior","test","hasBeenRedirected","testId","getJsonCookie","markAsRedirected","redirectedTests","setCookie","findMatchingSplitUrlTest","config","variation","urls","performRedirect","targetUrl","finalUrl","navigate","pathname","processSplitUrlTests","previewState","match","matchedVariation","isControlUrl","redirectBehavior","assignedVariationId","getAssignedVariant","assignedVariation","v","targetUrls","hasSplitUrlTests","splitUrlHandler","test","context","variation","urls","urlMatches","import_ua_parser_js","urlSources","sanitizeString","value","roundToTwo","num","extractProductId","gid","regex","match","extractProductVariantId","extractCartToken","cleanCartToken","cartToken","checkFacebookBrowser","userAgent","checkInstagramBrowser","checkFacebookInstagramBrowser","getBrowserName","browser","getQueryParams","parsedUrl","queryParams","key","isValidReferrerURI","uri","extractReferrerSource","host","parseReferrer","referrer","siteHostname","referrerObj","source","parseAddViewData","params","entryPage","data","entryObj","entryPath","entryQueryParams","userAgentObj","browserName","getPageTypeFromPathname","path","hasLocalizedPaths","hasNormalPath","isLocalizedHomepage","checkVisitorIdParams","searchParams","getUserAgentNoBrowser","os","device","result","extractShopifyId","gid","extractShopifyType","isShopifyGid","value","detectShopifyCurrency","shopify","init_assignment","ELEMENT_ID_PREFIX","NODE_TYPES","originalElements","injectedStyles","injectedScripts","injectedElements","isMobile","matchesWildcardPattern","pathname","pattern","trimmedPattern","suffix","checkIsMobile","convertToKebabCase","text","result","i","char","isTextNode","node","isElementNode","storeOriginalElement","selector","element","decodeCodeString","code","decoded","applyContentChanges","changes","currentPathname","matchingChanges","change","processedChanges","index","uniqueSelector","prop","value","kebabProp","hasImportant","cleanValue","key","applyContentElements","elements","elementId","trackedElement","target","domElement","createDOMElement","child","childElement","applyCustomCode","customCodes","nonce","injectCSS","injectJS","id","css","styleId","trackedStyle","styleElement","js","scriptId","trackedScript","scriptElement","decodedJs","restoreOriginalElements","originalElement","cleanupContentTests","style","script","collectContentTestData","config","previewState","allChanges","allElements","allCustomCodes","test","assignedVariantId","getAssignedVariant","variation","v","hasContentTests","processContentTests","contentData","reprocessContentTests","currentIsMobile","setupContentTestListeners","listenToNavigation","handleResize","cleanupNavigation","onNavigate","init_cartAttributes","init_cartAttributes_mutation","init_storage","import_react","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","currentPath","setCurrentPath","import_react","import_react","ElevateContext","React","useElevateConfig","context","init_assignment","init_tracking","init_preview","handlers","registerHandler","handler","getHandler","type","getAllHandlers","hasHandler","extractProductHandleFromUrl","url","match","updatePriceElements","variation","variantId","currencyCode","selectors","variantPrices","priceAmount","compareAmount","selectorsConfig","selectorSet","priceSelector","el","formattedPrice","compareSelector","savingConfig","savingSelector","price","compare","saving","percentage","formattedSaving","pricePlusHandler","test","context","testData","productId","productHandle","urlHandle","matchesProductId","matchesHandle","matchesTestPathnames","test","currentUrl","pathnames","pathname","pattern","matchesWildcardPattern","contentHandler","context","variation","_context","testData","matchesTestPathnames","test","currentUrl","pathnames","pathname","pattern","matchesWildcardPattern","customCodeHandler","context","variation","_context","testData","registerHandler","pricePlusHandler","splitUrlHandler","contentHandler","customCodeHandler","buildHandlerContext","selectors","url","pathname","productHandle","productMatch","variantId","variantParam","useExperiment","testId","config","contextPreviewState","useElevateConfig","variant","setVariant","React","isLoading","setIsLoading","testConfig","test","previewState","getPreviewState","hasWarnedRef","effectAppliedRef","isMounted","assignedVariantId","getAssignedVariant","assigned","v","handler","getHandler","context","enrichedVariant","effectKey","handlerData","trackViews","import_react","init_utils","init_preview","init_assignment","hasCustomCodeTests","config","test","processCustomCodeTests","previewState","nonce","customCodeTests","customCodes","assignedVariantId","getAssignedVariant","variation","v","applyCustomCode","init_assignment","import_jsx_runtime","CDN_BASE_URL","getStoreName","storeId","getConfigUrl","useIsomorphicLayoutEffect","React","ElevateProvider","storefrontAccessToken","preventFlickering","flickerTimeout","nonce","children","config","setConfig","previewState","setPreviewState","countryCode","setCountryCode","initAnalytics","preview","getPreviewState","country","getCountryCode","revealContent","fetchConfig","currentPreviewState","backendData","url","resolve","reject","script","data","parsedConfig","parseBackendConfig","assignAllTests","t","processSplitUrlTests","err","applySplitUrlTests","hasSplitUrlTests","applyNonRedirectTests","hasContentTests","processContentTests","hasCustomCodeTests","processCustomCodeTests","navigationRafId","navigationTimeoutId","cleanupNavigation","onNavigate","cleanupContent","setupContentTestListeners","value","hasWarnedRef","configUrl","blockingScript","getSplitUrlBlockingScript","ElevateContext","import_react","init_storage","init_cartAttributes","DEFAULT_WORKER_URL","DEFAULT_ORDERS_WORKER_URL","generatePixelEventId","uuidv4","transformTestFormat","testObject","variationId","testId","transformViewedTests","viewedObject","assignmentObject","ElevateAnalytics","storeIdProp","tokenProp","hasLocalizedPaths","workerUrl","ordersWorkerUrl","useAnalytics","context","ElevateContext","storeId","storefrontAccessToken","hasWarnedContextRef","subscribe","register","ready","getVisitorId","getSessionId","currentReferrer","currentUrl","setReferrerData","initializeState","event","productPageId","extractProductId","cartToken","extractCartToken","referrer","entryPage","getReferrerData","getCookie","createBaseEventData","eventName","pixelEventId","state","userAgent","pathname","pageType","getPageTypeFromPathname","parsedData","parseAddViewData","abtlObject","getJsonCookie","abauObject","testAssignments","viewedTests","currentTimestamp","isFirstVisit","shopifyCountry","cleanCartToken","getUserAgentNoBrowser","sendEvent","data","response","error","handlePageViewed","eventData","handleProductViewed","sanitizeString","roundToTwo","handleProductAddedToCart","extractProductVariantId","cartId","updateCartAttributes","err","handleProductRemovedFromCart","handleCartViewed","baseData","cartProducts","item","handleSearchSubmitted","handleCheckoutStarted","totalQuantity","checkoutProducts","quantity","total_discount","acc","discount","handleCheckoutCompleted","sendOrderEvent","VERSION"]}
|