@drip-apex/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -0
  3. package/dist/_headers +3 -0
  4. package/dist/bundle-report.json +564 -0
  5. package/dist/drip.debug.js +2 -0
  6. package/dist/drip.debug.js.map +1 -0
  7. package/dist/drip.heatmap.js +2 -0
  8. package/dist/drip.heatmap.js.map +1 -0
  9. package/dist/drip.js +2 -0
  10. package/dist/drip.js.map +1 -0
  11. package/dist/drip.live.js +2 -0
  12. package/dist/drip.live.js.map +1 -0
  13. package/dist/editor.js +480 -0
  14. package/dist/editor.js.map +7 -0
  15. package/dist/index.mjs +645 -0
  16. package/dist/index.mjs.map +7 -0
  17. package/dist/metafiles/drip.debug.meta.json +973 -0
  18. package/dist/metafiles/drip.heatmap.meta.json +918 -0
  19. package/dist/metafiles/drip.live.meta.json +918 -0
  20. package/dist/metafiles/drip.meta.json +973 -0
  21. package/dist/metafiles/editor.meta.json +321 -0
  22. package/dist/metafiles/index.meta.json +1039 -0
  23. package/dist/metafiles/index.mjs.meta.json +78 -0
  24. package/dist/react/index.js +16973 -0
  25. package/dist/react/index.js.map +7 -0
  26. package/dist/sri.json +27 -0
  27. package/dist/types/analytics.d.ts +15 -0
  28. package/dist/types/antiflicker.d.ts +14 -0
  29. package/dist/types/assignment-store.d.ts +30 -0
  30. package/dist/types/audit.d.ts +9 -0
  31. package/dist/types/bucket.d.ts +2 -0
  32. package/dist/types/bucketing-cleanup.d.ts +5 -0
  33. package/dist/types/commerce-gift.d.ts +41 -0
  34. package/dist/types/commerce-price.d.ts +22 -0
  35. package/dist/types/commerce-shipping.d.ts +28 -0
  36. package/dist/types/css.d.ts +5 -0
  37. package/dist/types/cwv.d.ts +10 -0
  38. package/dist/types/data-layer-normalize.d.ts +1 -0
  39. package/dist/types/debug.d.ts +23 -0
  40. package/dist/types/define.d.ts +87 -0
  41. package/dist/types/devtools.d.ts +32 -0
  42. package/dist/types/dom-trigger.d.ts +3 -0
  43. package/dist/types/editor/api.d.ts +37 -0
  44. package/dist/types/editor/artifacts.d.ts +15 -0
  45. package/dist/types/editor/command-runtime.d.ts +48 -0
  46. package/dist/types/editor/controller.d.ts +97 -0
  47. package/dist/types/editor/device-preview.d.ts +23 -0
  48. package/dist/types/editor/index.d.ts +9 -0
  49. package/dist/types/editor/operator.d.ts +39 -0
  50. package/dist/types/editor/picker.d.ts +23 -0
  51. package/dist/types/editor/selector.d.ts +2 -0
  52. package/dist/types/editor/types.d.ts +55 -0
  53. package/dist/types/editor/view-kit.d.ts +33 -0
  54. package/dist/types/editor/view.d.ts +5 -0
  55. package/dist/types/editor-bootstrap.d.ts +37 -0
  56. package/dist/types/exclusion-groups.d.ts +59 -0
  57. package/dist/types/exposure-signals.d.ts +7 -0
  58. package/dist/types/flags.d.ts +65 -0
  59. package/dist/types/goals.d.ts +16 -0
  60. package/dist/types/guards.d.ts +39 -0
  61. package/dist/types/handover.d.ts +10 -0
  62. package/dist/types/hash.d.ts +19 -0
  63. package/dist/types/heatmap.d.ts +8 -0
  64. package/dist/types/hideflicker.d.ts +15 -0
  65. package/dist/types/hydration.d.ts +11 -0
  66. package/dist/types/index.d.ts +144 -0
  67. package/dist/types/js.d.ts +6 -0
  68. package/dist/types/module.d.ts +4 -0
  69. package/dist/types/money.d.ts +14 -0
  70. package/dist/types/mutate.d.ts +34 -0
  71. package/dist/types/observer-mute.d.ts +3 -0
  72. package/dist/types/pii-keys.d.ts +1 -0
  73. package/dist/types/prerequisites.d.ts +12 -0
  74. package/dist/types/qa-assistant-state.d.ts +68 -0
  75. package/dist/types/qa-assistant-view.d.ts +6 -0
  76. package/dist/types/qa-assistant.d.ts +9 -0
  77. package/dist/types/qa-toolbar.d.ts +19 -0
  78. package/dist/types/react/index.d.ts +84 -0
  79. package/dist/types/reassert-sentinel.d.ts +6 -0
  80. package/dist/types/router.d.ts +9 -0
  81. package/dist/types/runtime-tools.d.ts +50 -0
  82. package/dist/types/runtime.d.ts +22 -0
  83. package/dist/types/safe-regex.d.ts +6 -0
  84. package/dist/types/sanitize.d.ts +5 -0
  85. package/dist/types/semantic.d.ts +7 -0
  86. package/dist/types/shopify-cart-events.d.ts +7 -0
  87. package/dist/types/shopify-cart.d.ts +62 -0
  88. package/dist/types/signals.d.ts +31 -0
  89. package/dist/types/surface-signals.d.ts +6 -0
  90. package/dist/types/targeting-diagnostics.d.ts +5 -0
  91. package/dist/types/targeting.d.ts +50 -0
  92. package/dist/types/test-fixtures/commerce.d.ts +12 -0
  93. package/dist/types/track.d.ts +79 -0
  94. package/dist/types/types.d.ts +859 -0
  95. package/dist/types/wait.d.ts +7 -0
  96. package/package.json +74 -0
  97. package/src/analytics.ts +146 -0
  98. package/src/antiflicker.test.ts +127 -0
  99. package/src/antiflicker.ts +147 -0
  100. package/src/assignment-store.test.ts +171 -0
  101. package/src/assignment-store.ts +208 -0
  102. package/src/audit.test.ts +17 -0
  103. package/src/audit.ts +362 -0
  104. package/src/bucket.test.ts +65 -0
  105. package/src/bucket.ts +18 -0
  106. package/src/bucketing-cleanup.test.ts +30 -0
  107. package/src/bucketing-cleanup.ts +72 -0
  108. package/src/bucketing-parity.test.ts +41 -0
  109. package/src/commerce-analytics-lifecycle.test.ts +1416 -0
  110. package/src/commerce-config-lifecycle.test.ts +274 -0
  111. package/src/commerce-epoch-lifecycle.test.ts +62 -0
  112. package/src/commerce-gift.test.ts +1293 -0
  113. package/src/commerce-gift.ts +979 -0
  114. package/src/commerce-offers-display.test.ts +154 -0
  115. package/src/commerce-price.test.ts +1145 -0
  116. package/src/commerce-price.ts +941 -0
  117. package/src/commerce-revocation-lifecycle.test.ts +78 -0
  118. package/src/commerce-shipping.test.ts +630 -0
  119. package/src/commerce-shipping.ts +447 -0
  120. package/src/config-fetch.test.ts +325 -0
  121. package/src/css.ts +54 -0
  122. package/src/cwv.test.ts +95 -0
  123. package/src/cwv.ts +129 -0
  124. package/src/data-layer-normalize.ts +21 -0
  125. package/src/debug.test.ts +83 -0
  126. package/src/debug.ts +138 -0
  127. package/src/define.test.ts +327 -0
  128. package/src/define.ts +208 -0
  129. package/src/devtools.ts +582 -0
  130. package/src/dom-trigger.test.ts +70 -0
  131. package/src/dom-trigger.ts +55 -0
  132. package/src/editor/api.test.ts +154 -0
  133. package/src/editor/api.ts +185 -0
  134. package/src/editor/artifacts.test.ts +57 -0
  135. package/src/editor/artifacts.ts +115 -0
  136. package/src/editor/command-runtime.test.ts +225 -0
  137. package/src/editor/command-runtime.ts +572 -0
  138. package/src/editor/controller.test.ts +371 -0
  139. package/src/editor/controller.ts +596 -0
  140. package/src/editor/device-preview.test.ts +60 -0
  141. package/src/editor/device-preview.ts +120 -0
  142. package/src/editor/index.test.ts +161 -0
  143. package/src/editor/index.ts +169 -0
  144. package/src/editor/operator.test.ts +148 -0
  145. package/src/editor/operator.ts +256 -0
  146. package/src/editor/picker.test.ts +58 -0
  147. package/src/editor/picker.ts +152 -0
  148. package/src/editor/selector.test.ts +44 -0
  149. package/src/editor/selector.ts +110 -0
  150. package/src/editor/types.ts +92 -0
  151. package/src/editor/view-kit.ts +162 -0
  152. package/src/editor/view.test.ts +535 -0
  153. package/src/editor/view.ts +1395 -0
  154. package/src/editor-bootstrap.test.ts +116 -0
  155. package/src/editor-bootstrap.ts +213 -0
  156. package/src/event-schema-contract.test.ts +35 -0
  157. package/src/exclusion-groups.test.ts +383 -0
  158. package/src/exclusion-groups.ts +270 -0
  159. package/src/exposure-signals.test.ts +182 -0
  160. package/src/exposure-signals.ts +110 -0
  161. package/src/flags.test.ts +322 -0
  162. package/src/flags.ts +201 -0
  163. package/src/goals.test.ts +42 -0
  164. package/src/goals.ts +200 -0
  165. package/src/guards.test.ts +249 -0
  166. package/src/guards.ts +250 -0
  167. package/src/handover-cache-order.test.ts +32 -0
  168. package/src/handover.test.ts +349 -0
  169. package/src/handover.ts +309 -0
  170. package/src/hash.ts +214 -0
  171. package/src/heatmap.test.ts +305 -0
  172. package/src/heatmap.ts +373 -0
  173. package/src/hideflicker.ts +21 -0
  174. package/src/hydration.test.ts +252 -0
  175. package/src/hydration.ts +203 -0
  176. package/src/index.ts +7513 -0
  177. package/src/init-empty.test.ts +5572 -0
  178. package/src/js.test.ts +26 -0
  179. package/src/js.ts +61 -0
  180. package/src/module.ts +50 -0
  181. package/src/money.test.ts +35 -0
  182. package/src/money.ts +53 -0
  183. package/src/mutate.test.ts +304 -0
  184. package/src/mutate.ts +469 -0
  185. package/src/observer-mute.test.ts +88 -0
  186. package/src/observer-mute.ts +45 -0
  187. package/src/page-trigger.test.ts +84 -0
  188. package/src/personalization.test.ts +68 -0
  189. package/src/pii-keys.ts +17 -0
  190. package/src/prerequisites.test.ts +39 -0
  191. package/src/prerequisites.ts +94 -0
  192. package/src/qa-assistant-state.test.ts +471 -0
  193. package/src/qa-assistant-state.ts +505 -0
  194. package/src/qa-assistant-view.test.ts +185 -0
  195. package/src/qa-assistant-view.ts +768 -0
  196. package/src/qa-assistant.ts +40 -0
  197. package/src/qa-toolbar.ts +444 -0
  198. package/src/react/index.test.tsx +177 -0
  199. package/src/react/index.tsx +252 -0
  200. package/src/reassert-sentinel.test.ts +314 -0
  201. package/src/reassert-sentinel.ts +191 -0
  202. package/src/router.test.ts +78 -0
  203. package/src/router.ts +92 -0
  204. package/src/runtime-tools.test.ts +112 -0
  205. package/src/runtime-tools.ts +403 -0
  206. package/src/runtime.test.ts +217 -0
  207. package/src/runtime.ts +268 -0
  208. package/src/safe-regex.ts +35 -0
  209. package/src/sanitize.ts +34 -0
  210. package/src/semantic.ts +245 -0
  211. package/src/shopify-cart-events.test.ts +76 -0
  212. package/src/shopify-cart-events.ts +115 -0
  213. package/src/shopify-cart.test.ts +2823 -0
  214. package/src/shopify-cart.ts +1256 -0
  215. package/src/signals.ts +226 -0
  216. package/src/surface-signals.test.ts +83 -0
  217. package/src/surface-signals.ts +165 -0
  218. package/src/targeting-diagnostics.ts +560 -0
  219. package/src/targeting.detailed.test.ts +443 -0
  220. package/src/targeting.test.ts +1054 -0
  221. package/src/targeting.ts +1024 -0
  222. package/src/test-fixtures/commerce.ts +65 -0
  223. package/src/track.test.ts +817 -0
  224. package/src/track.ts +519 -0
  225. package/src/types.ts +991 -0
  226. package/src/wait.test.ts +96 -0
  227. package/src/wait.ts +238 -0
@@ -0,0 +1,34 @@
1
+ import { Mutation, MutationAction } from "./types";
2
+ export type ApplyOptions = {
3
+ root?: Document | HTMLElement;
4
+ onApplied?: (mutation: Mutation, element: Element, index: number) => void;
5
+ onMiss?: (mutation: Mutation, index: number) => void;
6
+ };
7
+ export declare function isSafeMutationAttribute(name: string, value: string | null): boolean;
8
+ export declare function normalizeCssPropertyName(name: string): string;
9
+ export declare function getMutationKey(mutation: Mutation, index: number): string;
10
+ export declare function isInsertAction(action: MutationAction): boolean;
11
+ export declare function applyToElement(mutation: Mutation, element: Element): void;
12
+ export declare function isInsertDuplicate(element: Element, key: string): boolean;
13
+ export declare function markInserted(el: Element, key: string): void;
14
+ export declare function applyTrackedMutation(mutation: Mutation, element: Element, key?: string): Element | null;
15
+ export declare function matchesOriginalInnerHtmlSnapshot(element: Element, current: string): boolean;
16
+ export declare function applyMutations(mutations: Mutation[], options?: ApplyOptions): void;
17
+ export declare function reassertNonStructuralMutations(mutations: Mutation[], options?: ApplyOptions): void;
18
+ export declare function resetAppliedMutations(): void;
19
+ export type MutationApplicationContext = {
20
+ apply: (mutations: Mutation[], options?: ApplyOptions) => void;
21
+ rollback: () => void;
22
+ readonly snapshotCount: number;
23
+ };
24
+ /**
25
+ * Owns only the DOM snapshots created through this context. Rolling it back
26
+ * restores the state that existed immediately before its mutations, without
27
+ * touching shopper assignment mutations tracked by the main SDK runtime.
28
+ */
29
+ export declare function createMutationApplicationContext(): MutationApplicationContext;
30
+ /** @internal — exposed for unit testing only. Tree-shaken from production build. */
31
+ export declare const __test: {
32
+ normalizeCssPropertyName: typeof normalizeCssPropertyName;
33
+ };
34
+ export declare function observeSpaNavigation(onChange: () => void): () => void;
@@ -0,0 +1,3 @@
1
+ export declare function registerMutedObserver(observer: MutationObserver, callback?: MutationCallback): void;
2
+ export declare function unregisterMutedObserver(observer: MutationObserver): void;
3
+ export declare function runMuted<T>(fn: () => T): T;
@@ -0,0 +1 @@
1
+ export declare function containsPiiToken(key: string): boolean;
@@ -0,0 +1,12 @@
1
+ import type { InitConfig } from "./types";
2
+ type PrerequisiteContext = {
3
+ type: "show_variations" | "start_tracking";
4
+ url: string;
5
+ attributes: Record<string, unknown>;
6
+ userId: string | null;
7
+ consentRequired: boolean;
8
+ consentGranted: boolean;
9
+ };
10
+ export declare function evaluateProjectPrerequisite(rule: string | undefined, context: PrerequisiteContext, fallback: boolean): boolean;
11
+ export declare function buildPrerequisiteContext(config: InitConfig, userId: string | null, consentRequired: boolean, consentGranted: boolean, type: PrerequisiteContext["type"]): PrerequisiteContext;
12
+ export {};
@@ -0,0 +1,68 @@
1
+ export type QaExperimentModel = {
2
+ id: string;
3
+ name: string;
4
+ variationId: string | null;
5
+ variationName: string | null;
6
+ applied: boolean;
7
+ forced: boolean;
8
+ subline: string;
9
+ triggerPill: "accepted" | "rejected" | "not evaluated" | "all pages";
10
+ segmentPill: "accepted" | "rejected" | "not evaluated" | "all visitors";
11
+ displayFrequencyPill: "accepted" | "outside traffic %" | "personalization stop" | "excluded by overlap" | "not running" | "not evaluated" | "forced";
12
+ conditions: Array<{
13
+ id: string;
14
+ group: "pages" | "audience";
15
+ state: "pass" | "fail" | "skip" | "error";
16
+ text: string;
17
+ detail: string | null;
18
+ rawCode: string | null;
19
+ }>;
20
+ variations: Array<{
21
+ id: string;
22
+ name: string;
23
+ isControl: boolean;
24
+ isCurrent: boolean;
25
+ isReal: boolean;
26
+ }>;
27
+ };
28
+ export type QaEventModel = {
29
+ at: number;
30
+ type: "exposure" | "goal" | "revenue" | "pageview";
31
+ label: string;
32
+ value: string | null;
33
+ duplicateOf?: number;
34
+ };
35
+ export type QaTransactionsModel = {
36
+ kind: "unsupported";
37
+ } | {
38
+ kind: "shopify";
39
+ cartStamped: boolean;
40
+ variationName: string | null;
41
+ stampedAt: number | null;
42
+ attribution: Array<{
43
+ experimentName: string;
44
+ variationName: string | null;
45
+ }>;
46
+ } | {
47
+ kind: "order";
48
+ orderNumber: string | null;
49
+ attribution: Array<{
50
+ experimentName: string;
51
+ variationName: string | null;
52
+ }>;
53
+ serverReceipt: "pending" | "confirmed" | "unknown";
54
+ };
55
+ export type QaAssistantState = {
56
+ experiments: QaExperimentModel[];
57
+ events: QaEventModel[];
58
+ transactions: QaTransactionsModel;
59
+ forcedSummary: string | null;
60
+ };
61
+ export type QaAssistantStore = {
62
+ getState(): QaAssistantState;
63
+ subscribe(listener: (s: QaAssistantState) => void): () => void;
64
+ forceVariation(experimentId: string, variationId: string): void;
65
+ resetForce(experimentId?: string): void;
66
+ exitQa(): void;
67
+ };
68
+ export declare function createQaAssistantStore(): QaAssistantStore;
@@ -0,0 +1,6 @@
1
+ import type { QaAssistantStore } from "./qa-assistant-state";
2
+ export declare const QA_ASSISTANT_HOST_ID = "drip-qa-assistant-host";
3
+ export type QaAssistantView = {
4
+ destroy(): void;
5
+ };
6
+ export declare function mountQaAssistantView(store: QaAssistantStore): QaAssistantView;
@@ -0,0 +1,9 @@
1
+ import { type QaAssistantStore } from "./qa-assistant-state";
2
+ import { type QaAssistantView } from "./qa-assistant-view";
3
+ /**
4
+ * Mounts the QA Assistant panel (store + shadow-DOM view). QA-only module:
5
+ * live/heatmap builds stub this file out entirely (see build.mjs), and the
6
+ * caller in index.ts additionally gates on QA mode.
7
+ */
8
+ export declare function mountQaAssistant(): QaAssistantView | null;
9
+ export declare function getQaAssistantStore(): QaAssistantStore;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * QA Toolbar — floating in-page toolbar for QA preview sessions.
3
+ *
4
+ * Renders inside a Shadow DOM to avoid style interference with the host page.
5
+ * Shows active experiments, variation switcher, and exit QA button.
6
+ */
7
+ import { Assignment, Experiment } from "./types";
8
+ export interface QaToolbarOptions {
9
+ experiments: Experiment[];
10
+ assignments: Assignment[];
11
+ forceMap: Record<string, string> | null;
12
+ qaSessionId?: string;
13
+ onSwitchVariation: (experimentId: string, variationId: string) => void;
14
+ onExitQa: () => void;
15
+ onReloadLatest?: () => void;
16
+ onExitHarness?: () => void;
17
+ }
18
+ export declare function mountQaToolbar(options: QaToolbarOptions): void;
19
+ export declare function unmountQaToolbar(): void;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * React bindings for Drip SDK.
3
+ *
4
+ * Usage:
5
+ * import { DripProvider, useExperiment, useVariation, useFeatureFlag, useFeatureFlagValue, useTrackGoal } from "@drip-apex/sdk/react";
6
+ *
7
+ * function App() {
8
+ * return (
9
+ * <DripProvider shopId="shop_xxx" endpoint="https://events.drip-apex.com">
10
+ * <HeroSection />
11
+ * </DripProvider>
12
+ * );
13
+ * }
14
+ *
15
+ * function HeroSection() {
16
+ * const assignment = useExperiment("hero-test");
17
+ * const variation = useVariation("hero-test");
18
+ * const isDarkMode = useFeatureFlag("dark-mode-rollout");
19
+ * const offerCopy = useFeatureFlagValue("offer-copy", "Default offer");
20
+ * const trackGoal = useTrackGoal();
21
+ *
22
+ * return (
23
+ * <div>
24
+ * <h1>{variation?.id === "variant-a" ? "New headline" : "Default headline"}</h1>
25
+ * <button onClick={() => trackGoal("cta-click")}>CTA</button>
26
+ * </div>
27
+ * );
28
+ * }
29
+ */
30
+ import { type ReactNode } from "react";
31
+ import type { Assignment, InitConfig, Variation } from "../types";
32
+ export interface DripProviderProps extends Omit<InitConfig, "onExperimentViewed"> {
33
+ children: ReactNode;
34
+ /** Callback when an experiment is viewed (assignment applied). */
35
+ onExperimentViewed?: (assignment: Assignment) => void;
36
+ }
37
+ /**
38
+ * Drip SDK provider for React applications.
39
+ *
40
+ * Initializes the SDK, fetches experiment config (if shopId provided),
41
+ * and provides assignment context to child components.
42
+ */
43
+ export declare function DripProvider({ children, onExperimentViewed, ...config }: DripProviderProps): import("react/jsx-runtime").JSX.Element;
44
+ /**
45
+ * Get the assignment for a specific experiment by ID or slug.
46
+ * Returns `null` if the user is not assigned to this experiment.
47
+ */
48
+ export declare function useExperiment(experimentId: string): Assignment | null;
49
+ /**
50
+ * Get the assigned variation for a specific experiment.
51
+ * Returns `null` if the user is not assigned.
52
+ */
53
+ export declare function useVariation(experimentId: string): Pick<Variation, "id" | "isControl"> | null;
54
+ /**
55
+ * Evaluate a feature flag (experiment-backed).
56
+ * Returns `true` if the user is bucketed into a non-control variation.
57
+ */
58
+ export declare function useFeatureFlag(flagId: string): boolean;
59
+ /**
60
+ * Read the typed value assigned by a feature flag.
61
+ * Returns the fallback when the visitor is not assigned or the flag is missing.
62
+ */
63
+ export declare function useFeatureFlagValue<T = unknown>(flagId: string, fallback: T): T | unknown;
64
+ /**
65
+ * Returns a function to track goals.
66
+ */
67
+ export declare function useTrackGoal(): (goalId: string, data?: Record<string, unknown>) => void;
68
+ /**
69
+ * Returns a function to track custom events.
70
+ */
71
+ export declare function useTrack(): (type: string, data?: Record<string, unknown>) => void;
72
+ /**
73
+ * Returns a function to track revenue.
74
+ */
75
+ export declare function useTrackRevenue(): (revenue: number, data?: Record<string, unknown>) => void;
76
+ /**
77
+ * Get all current assignments.
78
+ */
79
+ export declare function useAssignments(): Assignment[];
80
+ /**
81
+ * Whether the SDK is still loading experiment config.
82
+ */
83
+ export declare function useLoading(): boolean;
84
+ export type { Assignment, Experiment, Variation, InitConfig } from "../types";
@@ -0,0 +1,6 @@
1
+ import type { Mutation } from "./types";
2
+ export declare function trackAppliedMutation(element: Element, mutation: Mutation, context: {
3
+ experimentId?: string;
4
+ variationId?: string;
5
+ }, apply: (element: Element, mutation: Mutation) => void): void;
6
+ export declare function resetReassertSentinel(): void;
@@ -0,0 +1,9 @@
1
+ import { RouterMode } from "./types";
2
+ export type RouteChangeEvent = {
3
+ previousUrl: string;
4
+ nextUrl: string;
5
+ reason: "pushState" | "replaceState" | "popstate" | "hashchange" | "navigation";
6
+ };
7
+ type RouteObserver = (event: RouteChangeEvent) => void;
8
+ export declare function observeRouteChanges(mode: RouterMode, observer: RouteObserver): () => void;
9
+ export {};
@@ -0,0 +1,50 @@
1
+ type Cleanup = () => void;
2
+ type DataLayerEntry = Record<string, unknown>;
3
+ type DataLayerMatcher = Record<string, unknown> | Array<[string, unknown]>;
4
+ type RuntimeToolsEnvironment = {
5
+ document?: Document;
6
+ window?: Window & typeof globalThis;
7
+ location?: Location;
8
+ track?: (type: string, data?: Record<string, unknown>) => void;
9
+ trackGoal?: (goalId: string, data?: Record<string, unknown>) => void;
10
+ signal?: (key: string, value: unknown, ttlDays?: number) => void;
11
+ reInit?: (forceReapply?: boolean) => unknown;
12
+ get?: (key: string) => unknown;
13
+ };
14
+ export type WaitForElementOptions = {
15
+ root?: ParentNode;
16
+ once?: boolean;
17
+ timeoutMs?: number;
18
+ };
19
+ export type DomChangedOptions = {
20
+ root?: Node;
21
+ subtree?: boolean;
22
+ debounceMs?: number;
23
+ };
24
+ export type ElementInViewOptions = {
25
+ root?: Element | Document | null;
26
+ rootMargin?: string;
27
+ threshold?: number;
28
+ once?: boolean;
29
+ timeoutMs?: number;
30
+ };
31
+ export type DataLayerOptions = {
32
+ layerName?: string;
33
+ once?: boolean;
34
+ timeoutMs?: number;
35
+ };
36
+ export type ApexRuntimeTools = {
37
+ waitForElement: (selector: string, callback: (element: Element) => void, options?: WaitForElementOptions) => Cleanup;
38
+ elementIsInView: (selector: string, callback: (element: Element) => void, options?: ElementInViewOptions | boolean) => Cleanup;
39
+ domChanged: (callback: (mutations: MutationRecord[]) => void, options?: DomChangedOptions) => Cleanup;
40
+ domLoaded: (callback: () => void) => Cleanup;
41
+ waitForDataLayer: (matcher: DataLayerMatcher, callback: (entry: DataLayerEntry) => void, options?: DataLayerOptions) => Cleanup;
42
+ track: (type: string, data?: Record<string, unknown>) => void;
43
+ trackGoal: (goalId: string, data?: Record<string, unknown>) => void;
44
+ signal: (key: string, value: unknown, ttlDays?: number) => void;
45
+ redirect: (target: string) => void;
46
+ reInit: (forceReapply?: boolean) => unknown;
47
+ get: (key: string) => unknown;
48
+ };
49
+ export declare function createApexRuntimeTools(env?: RuntimeToolsEnvironment): ApexRuntimeTools;
50
+ export {};
@@ -0,0 +1,22 @@
1
+ import type { ActivationMode, Assignment, Experiment, InitConfig, PerfFeatureFlag, PlatformHint, RouterMode } from "./types";
2
+ type UrlDiffNeeds = {
3
+ path: boolean;
4
+ search: boolean;
5
+ hash: boolean;
6
+ };
7
+ export type PerfFlagState = Record<PerfFeatureFlag, boolean>;
8
+ /**
9
+ * Browser-side validation for a server-compiled empty-project profile. The
10
+ * browser may reject the profile, but never upgrades a full profile itself.
11
+ */
12
+ export declare function canUseEmptyProjectProfile(config: InitConfig, experiments: Experiment[], platform?: PlatformHint): boolean;
13
+ export declare function detectRuntimePlatform(): PlatformHint;
14
+ export declare function resolvePlatform(config: InitConfig): PlatformHint;
15
+ export declare function resolveRouterMode(config: InitConfig, platform: PlatformHint): RouterMode;
16
+ export declare function resolveActivationMode(config: InitConfig): ActivationMode;
17
+ export declare function readPerfFlags(config: InitConfig): PerfFlagState;
18
+ export declare function computeUrlDiffNeeds(experiments: Experiment[], signals?: InitConfig["signals"]): UrlDiffNeeds;
19
+ export declare function shouldReevaluateForUrlChange(previousUrl: string, nextUrl: string, deps: UrlDiffNeeds): boolean;
20
+ export declare function assignmentSignature(assignments: Assignment[]): string;
21
+ export declare function getBlankScreenMs(): number;
22
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Safe wrapper around RegExp construction and testing.
3
+ * Prevents crashes from invalid patterns and guards against
4
+ * extremely long patterns that could cause ReDoS.
5
+ */
6
+ export declare function safeRegexTest(pattern: string, input: string): boolean;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Lightweight HTML sanitizer using the browser's DOMParser.
3
+ * Strips <script> tags, on* event handlers, and javascript: URLs.
4
+ */
5
+ export declare function sanitizeHtml(html: string): string;
@@ -0,0 +1,7 @@
1
+ import type { SemanticTrackingSettings } from "./types";
2
+ type TrackFn = (type: string, data?: Record<string, unknown>) => void;
3
+ type Controller = {
4
+ stop: () => void;
5
+ };
6
+ export declare function startSemanticCapture(settings: SemanticTrackingSettings | undefined, track: TrackFn): Controller | null;
7
+ export {};
@@ -0,0 +1,7 @@
1
+ export type ShopifyCartMutationHandler = () => void;
2
+ export declare function onShopifyCartMutation(handler: ShopifyCartMutationHandler): () => void;
3
+ /**
4
+ * Use for Apex's own cart-attribute write so it does not recursively look like
5
+ * a shopper/theme mutation to subscribers of the shared fetch wrapper.
6
+ */
7
+ export declare function fetchWithoutShopifyCartMutationNotification(...args: Parameters<typeof fetch>): ReturnType<typeof fetch>;
@@ -0,0 +1,62 @@
1
+ export type CartAssignment = {
2
+ experimentId: string;
3
+ variationId: string;
4
+ assignmentEpoch?: number;
5
+ commercePriceOnly?: boolean;
6
+ };
7
+ export type CartAttributeSyncInput = {
8
+ assignments: CartAssignment[];
9
+ requiredAssignments?: CartAssignment[];
10
+ visitorId: string;
11
+ sessionId: string;
12
+ shopId?: string;
13
+ endpoint?: string;
14
+ ingestSignature?: string;
15
+ url?: string;
16
+ environment?: string;
17
+ cartToken?: string;
18
+ offersAuthorizationRevision?: number;
19
+ offersExperimentIds?: string[];
20
+ shippingAuthorizationRevision?: number;
21
+ shippingExperimentIds?: string[];
22
+ priceAuthorizationRevision?: number;
23
+ priceExperimentIds?: string[];
24
+ adoptOffersAssignments?: (assignments: CartAssignment[]) => boolean;
25
+ /** Pre-write feasibility check; must not apply anything. */
26
+ canAdoptOffersAssignments?: (assignments: CartAssignment[]) => boolean;
27
+ /** Headless capture hook: stage a validated offers adoption for {@link confirmCartAttributesWritten}. */
28
+ stageOffersAdoptionAssignments?: (assignments: CartAssignment[]) => void;
29
+ adoptPriceAssignments?: (assignments: CartAssignment[]) => boolean;
30
+ authorizePriceDisplayAssignments?: (assignments: CartAssignment[]) => void;
31
+ authorizeShippingDisplayAssignments?: (assignments: CartAssignment[]) => void;
32
+ authorizeOffersDisplayAssignments?: (assignments: CartAssignment[]) => void;
33
+ /** Receives the parsed /cart/update.js response body after a successful stamp write. */
34
+ onCartSnapshot?: (cart: unknown) => void;
35
+ exclusionGroupSelections?: Array<{
36
+ groupId: string;
37
+ experimentId: string;
38
+ epoch: number;
39
+ }>;
40
+ };
41
+ export type CartAttributeEntry = {
42
+ key: string;
43
+ value: string;
44
+ };
45
+ export type CartAttributeSyncResult = {
46
+ status: "sent" | "skipped" | "failed";
47
+ reason?: string;
48
+ };
49
+ export type CartAttributeSyncOptions = {
50
+ /** Re-write after a real cart mutation even if this assignment was stamped earlier. */
51
+ force?: boolean;
52
+ };
53
+ /** Prevent an obsolete authorization response from reaching the cart write. */
54
+ export declare function invalidateShopifyCartAttributeSync(): void;
55
+ export declare function cannotRequestRequiredCommerceAuthorization(input: CartAttributeSyncInput): boolean;
56
+ export declare function isShopifyStorefront(): boolean;
57
+ /** Validated locale-aware storefront root ("/fr/" on localized markets, "/" otherwise). */
58
+ export declare function shopifyRoutesRoot(): string;
59
+ export declare function shopifyCartPath(): string;
60
+ export declare function syncShopifyCartAttributes(input: CartAttributeSyncInput, options?: CartAttributeSyncOptions): Promise<CartAttributeSyncResult>;
61
+ export declare function buildSignedCartAttributeEntries(input: CartAttributeSyncInput): Promise<CartAttributeEntry[]>;
62
+ export declare function buildCartAttributeEntries(input: CartAttributeSyncInput, commerceAuthorization?: string | null): CartAttributeEntry[];
@@ -0,0 +1,31 @@
1
+ type SignalValue = string | number | boolean | string[] | Record<string, unknown> | null;
2
+ export type ProductSignalInput = {
3
+ id?: string | number | null;
4
+ handle?: string | null;
5
+ title?: string | null;
6
+ type?: string | null;
7
+ vendor?: string | null;
8
+ tags?: string[] | null;
9
+ price?: number | string | null;
10
+ };
11
+ export declare function configureSignalPersistenceAllowed(predicate?: () => boolean): void;
12
+ export declare function setSignal(key: string, value: unknown, ttlDays?: number, source?: string): void;
13
+ export declare function getSignals(options?: {
14
+ markVisitorSeen?: boolean;
15
+ }): Record<string, SignalValue>;
16
+ export declare function clearStoredSignals(): void;
17
+ export declare function setRuntimeSignal(key: string, value: unknown, source?: string): void;
18
+ export declare function clearRuntimeSignal(key: string): void;
19
+ export declare function getSignalDiagnostics(options?: {
20
+ markVisitorSeen?: boolean;
21
+ }): {
22
+ values: Record<string, SignalValue>;
23
+ sources: Record<string, string>;
24
+ };
25
+ export declare function rememberProduct(product: ProductSignalInput, ttlDays?: number): void;
26
+ export declare function setCartSignals(args: {
27
+ itemCount?: number;
28
+ productIds?: string[];
29
+ }, ttlDays?: number): void;
30
+ export declare function setSearchSignal(query: string, ttlDays?: number): void;
31
+ export {};
@@ -0,0 +1,6 @@
1
+ export declare const CART_DRAWER_OPEN_SIGNAL = "surface.cart_drawer.open";
2
+ export declare const CART_DRAWER_SELECTORS: string[];
3
+ export declare function findCartDrawerContainer(root?: ParentNode): Element | null;
4
+ export declare function detectCartDrawerOpen(root?: ParentNode): boolean;
5
+ export declare function installCartDrawerOpenListener(onChange: (open: boolean) => void): () => void;
6
+ export declare function installSurfaceSignals(onChange: () => void): () => void;
@@ -0,0 +1,5 @@
1
+ import type { Targeting, TargetingDiagnostics } from "./types";
2
+ export declare function evaluateTargetingGatesWithConditionDiagnostics(targeting: Targeting | undefined, ctx: {
3
+ url: string;
4
+ attributes: Record<string, unknown>;
5
+ }): TargetingDiagnostics;
@@ -0,0 +1,50 @@
1
+ import { AttributeRule, ActivationGateDiagnostic, Experiment, PageTargetingRule, SegmentCondition, Targeting, TargetingDiagnostics, UrlRule } from "./types";
2
+ export declare function evalUrlRule(url: string, rule: UrlRule): boolean;
3
+ export declare function normalizeRuntimeUrlRules(targeting: Targeting | undefined): UrlRule[];
4
+ export declare function matchUrlRules(url: string, rules: UrlRule[]): boolean;
5
+ type BooleanDiagnosticResult = {
6
+ matched: boolean;
7
+ reason?: string;
8
+ error?: unknown;
9
+ };
10
+ export declare function evaluatePageAdvancedConditionResult(rule: PageTargetingRule, ctx: {
11
+ url: string;
12
+ attributes: Record<string, unknown>;
13
+ }): BooleanDiagnosticResult;
14
+ export declare function pageManualTriggerMatches(rule: PageTargetingRule, ctx: {
15
+ attributes: Record<string, unknown>;
16
+ }): boolean;
17
+ export declare function matchAttributeRule(attrs: Record<string, unknown>, rule: AttributeRule): boolean;
18
+ export declare function buildTargetingAttributes(baseAttributes?: Record<string, unknown>, currentUrl?: string, options?: {
19
+ persistSignals?: boolean;
20
+ }): Record<string, unknown>;
21
+ export declare function resolveNamedConditionActual(condition: SegmentCondition, ctx: {
22
+ url: string;
23
+ attributes: Record<string, unknown>;
24
+ }): unknown;
25
+ export declare function resolveNamedConditionExpected(condition: SegmentCondition): SegmentCondition["value"];
26
+ export declare function evaluateJsTriggerResult(condition: SegmentCondition, ctx: {
27
+ url: string;
28
+ attributes: Record<string, unknown>;
29
+ }): {
30
+ actual: unknown;
31
+ reason?: string;
32
+ };
33
+ export declare function matchSegmentConditionValues(condition: SegmentCondition, actual: unknown, expected: SegmentCondition["value"]): boolean;
34
+ export declare function matchesTargeting(targeting: Targeting | undefined, ctx: {
35
+ url: string;
36
+ attributes: Record<string, unknown>;
37
+ }): boolean;
38
+ export declare function targetingHasJsTriggers(experiments: Experiment[]): boolean;
39
+ export declare function evaluateTargetingGatesDetailed(targeting: Targeting | undefined, ctx: {
40
+ url: string;
41
+ attributes: Record<string, unknown>;
42
+ }): TargetingDiagnostics;
43
+ export declare function evaluateTargetingGates(targeting: Targeting | undefined, ctx: {
44
+ url: string;
45
+ attributes: Record<string, unknown>;
46
+ }): {
47
+ matched: boolean;
48
+ gates: ActivationGateDiagnostic[];
49
+ };
50
+ export {};
@@ -0,0 +1,12 @@
1
+ import type { Experiment, InitConfig } from "../types";
2
+ export declare const commercePriceFixture: NonNullable<InitConfig["commerce"]>;
3
+ export declare const priceExperimentsFixture: Experiment[];
4
+ export declare const commerceAssignmentResponseFixture: {
5
+ assignments: {
6
+ experiment_id: string;
7
+ variation_id: string;
8
+ assignment_epoch: number;
9
+ }[];
10
+ commerce_authorization: string;
11
+ };
12
+ export declare function installCommerceProductPage(): void;
@@ -0,0 +1,79 @@
1
+ import { TrackEvent } from "./types";
2
+ type TrackerOptions = {
3
+ endpoint: string;
4
+ shopId?: string;
5
+ ingestShopId?: string;
6
+ ingestSignature?: string;
7
+ visitorId?: string;
8
+ flushIntervalMs?: number;
9
+ maxBatchSize?: number;
10
+ /** Returns the active experiment/variation at unload time for page_exit attribution. */
11
+ getActiveAssignment?: () => {
12
+ experimentId: string;
13
+ variationId: string;
14
+ } | null;
15
+ /** Builds global and experiment-scoped page-exit events without flushing during unload. */
16
+ buildPageExitEvents?: (type: string, data?: Record<string, unknown>) => TrackEvent[];
17
+ /** When true, all events are tagged as QA traffic. */
18
+ qaMode?: boolean;
19
+ /** Unique QA session identifier for grouping QA events. */
20
+ qaSessionId?: string;
21
+ /** Active Apex environment stamped onto every outgoing event. */
22
+ environment?: string;
23
+ };
24
+ export declare class Tracker {
25
+ private endpoint;
26
+ private shopId;
27
+ private ingestShopId;
28
+ private ingestSignature;
29
+ private visitorId;
30
+ private sessionId;
31
+ private visitorSessions;
32
+ private flushIntervalMs;
33
+ private maxBatchSize;
34
+ private queue;
35
+ private activeBatch;
36
+ private timer;
37
+ private flushInFlight;
38
+ private flushPromise;
39
+ private nextFlushAt;
40
+ private backoffMs;
41
+ private readonly maxQueueSize;
42
+ private getActiveAssignment;
43
+ private buildPageExitEvents;
44
+ private qaMode;
45
+ private qaSessionId;
46
+ private environment;
47
+ private pagehideHandler;
48
+ private beforeUnloadHandler;
49
+ private pageshowHandler;
50
+ private beforeUnloadResetTimer;
51
+ private visibilityHandler;
52
+ private pageLifecycleFlushed;
53
+ private pageTeardownStarted;
54
+ constructor(options: TrackerOptions);
55
+ private getOrCreateSessionId;
56
+ /** Public accessor for the session ID (used by the Shopify pixel bridge). */
57
+ getSessionId(): string;
58
+ start(): void;
59
+ stop(): void;
60
+ track(event: TrackEvent): void;
61
+ private enrichEvent;
62
+ private scheduleBackoff;
63
+ private resetBackoff;
64
+ private parseRetryAfterSeconds;
65
+ flush(): Promise<void>;
66
+ private drainQueue;
67
+ private buildPayload;
68
+ private buildHeaders;
69
+ private recoveryEventKey;
70
+ private readRecovery;
71
+ private saveRecovery;
72
+ private removeRecovery;
73
+ private queuePageExitEvents;
74
+ private flushForPageLifecycle;
75
+ private recoverEvents;
76
+ private resetPageLifecycle;
77
+ private listenUnload;
78
+ }
79
+ export {};