@aranova/tracking-react 1.2.1 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.mjs CHANGED
@@ -1651,6 +1651,97 @@ function withConversionAutoFire(client, autoFire) {
1651
1651
  };
1652
1652
  }
1653
1653
 
1654
+ // ../tracking-core/src/events/semantics.ts
1655
+ var EVENT_SEMANTICS = {
1656
+ page_view: {
1657
+ label: "Page view",
1658
+ category: "page",
1659
+ outcomeRole: "navigation",
1660
+ clientVisibility: "simple"
1661
+ },
1662
+ time_on_site: {
1663
+ label: "Time on site",
1664
+ category: "engagement",
1665
+ outcomeRole: "engagement",
1666
+ clientVisibility: "detailed"
1667
+ },
1668
+ specific_page_visit: {
1669
+ label: "Key page visit",
1670
+ category: "engagement",
1671
+ outcomeRole: "engagement",
1672
+ clientVisibility: "detailed"
1673
+ },
1674
+ scroll_depth: {
1675
+ label: "Scroll depth",
1676
+ category: "engagement",
1677
+ outcomeRole: "engagement",
1678
+ clientVisibility: "detailed"
1679
+ },
1680
+ multi_page_session: {
1681
+ label: "Multi-page session",
1682
+ category: "engagement",
1683
+ outcomeRole: "engagement",
1684
+ clientVisibility: "detailed"
1685
+ },
1686
+ form_start: {
1687
+ label: "Form started",
1688
+ category: "engagement",
1689
+ outcomeRole: "engagement",
1690
+ clientVisibility: "simple"
1691
+ },
1692
+ sdk_heartbeat: {
1693
+ label: "SDK heartbeat",
1694
+ category: "system",
1695
+ outcomeRole: "diagnostic",
1696
+ clientVisibility: "hidden"
1697
+ },
1698
+ page_exit: {
1699
+ label: "Page exit",
1700
+ category: "engagement",
1701
+ outcomeRole: "diagnostic",
1702
+ clientVisibility: "detailed"
1703
+ },
1704
+ form_step: {
1705
+ label: "Form step",
1706
+ category: "engagement",
1707
+ outcomeRole: "engagement",
1708
+ clientVisibility: "detailed"
1709
+ },
1710
+ form_submit: {
1711
+ label: "Form submitted",
1712
+ category: "lead",
1713
+ outcomeRole: "lead",
1714
+ clientVisibility: "simple"
1715
+ },
1716
+ phone_click: {
1717
+ label: "Phone click",
1718
+ category: "lead",
1719
+ outcomeRole: "lead",
1720
+ clientVisibility: "simple"
1721
+ },
1722
+ cta_click: {
1723
+ label: "CTA click",
1724
+ category: "engagement",
1725
+ outcomeRole: "engagement",
1726
+ clientVisibility: "simple"
1727
+ },
1728
+ site_link_click: {
1729
+ label: "Left for sibling site",
1730
+ category: "page",
1731
+ outcomeRole: "navigation",
1732
+ clientVisibility: "detailed"
1733
+ },
1734
+ site_link_arrival: {
1735
+ label: "Arrived from sibling site",
1736
+ category: "page",
1737
+ outcomeRole: "navigation",
1738
+ clientVisibility: "simple"
1739
+ }
1740
+ };
1741
+ function getEventSemantics(eventName) {
1742
+ return eventName in EVENT_SEMANTICS ? EVENT_SEMANTICS[eventName] : null;
1743
+ }
1744
+
1654
1745
  // ../tracking-core/src/page-view.ts
1655
1746
  import { parse } from "zod/mini";
1656
1747
 
@@ -1697,6 +1788,13 @@ function writeSessionStorage(key, value) {
1697
1788
  } catch {
1698
1789
  }
1699
1790
  }
1791
+ function deleteSessionStorage(key) {
1792
+ try {
1793
+ if (typeof window === "undefined") return;
1794
+ window.sessionStorage.removeItem(key);
1795
+ } catch {
1796
+ }
1797
+ }
1700
1798
  function getLastFiredUrl() {
1701
1799
  if (!lastFiredUrlHydrated) {
1702
1800
  lastFiredUrlHydrated = true;
@@ -1710,6 +1808,31 @@ function setLastFiredUrl(url) {
1710
1808
  lastFiredUrlHydrated = true;
1711
1809
  writeSessionStorage(LAST_FIRED_URL_STORAGE_KEY, url);
1712
1810
  }
1811
+ function resetPageViewState() {
1812
+ lastFiredUrl = null;
1813
+ lastFiredUrlHydrated = false;
1814
+ deleteSessionStorage(LAST_FIRED_URL_STORAGE_KEY);
1815
+ autoPageViewSlot().key = null;
1816
+ }
1817
+ var AUTO_PAGE_VIEW_SLOT = /* @__PURE__ */ Symbol.for("aranova.tracking.autoPageView");
1818
+ function autoPageViewSlot() {
1819
+ const scope = globalThis;
1820
+ scope[AUTO_PAGE_VIEW_SLOT] ?? (scope[AUTO_PAGE_VIEW_SLOT] = { key: null });
1821
+ return scope[AUTO_PAGE_VIEW_SLOT];
1822
+ }
1823
+ function pageViewRouteKey(pathname, search) {
1824
+ const query = stripLinkParamFromSearch(search);
1825
+ return query.length > 1 ? `${pathname}${query}` : pathname;
1826
+ }
1827
+ function fireAutoPageView(client, options = {}) {
1828
+ if (typeof window === "undefined") return false;
1829
+ const key = pageViewRouteKey(window.location.pathname, window.location.search);
1830
+ const slot = autoPageViewSlot();
1831
+ if (!options.force && slot.key === key) return false;
1832
+ slot.key = key;
1833
+ fireManualPageView(client);
1834
+ return true;
1835
+ }
1713
1836
  function buildPageViewMetadata(referrerOverride) {
1714
1837
  if (typeof window === "undefined" || typeof document === "undefined") return null;
1715
1838
  return parse(pageViewMetadataSchema, {
@@ -1745,49 +1868,41 @@ function attachBfcacheRestore(client) {
1745
1868
  };
1746
1869
  function handlePageShow(event) {
1747
1870
  if (!event.persisted) return;
1748
- fireManualPageView(client);
1871
+ fireAutoPageView(client, { force: true });
1749
1872
  }
1750
1873
  window.addEventListener("pageshow", handlePageShow);
1751
1874
  return () => {
1752
1875
  window.removeEventListener("pageshow", handlePageShow);
1753
1876
  };
1754
1877
  }
1755
- function attachAutoPageView(client, options = {}) {
1878
+ function attachAutoPageView(client) {
1756
1879
  if (typeof window === "undefined" || typeof history === "undefined") {
1757
1880
  return () => {
1758
1881
  };
1759
1882
  }
1760
- let lastPath = window.location.pathname + window.location.search;
1761
- function maybeFire() {
1762
- const current = window.location.pathname + window.location.search;
1763
- if (current === lastPath) return;
1764
- lastPath = current;
1765
- fireManualPageView(client);
1883
+ function fireForCurrentRoute() {
1884
+ fireAutoPageView(client);
1766
1885
  }
1767
1886
  const originalPushState = history.pushState.bind(history);
1768
1887
  const originalReplaceState = history.replaceState.bind(history);
1769
1888
  function patchedPushState(...args) {
1770
1889
  originalPushState(...args);
1771
- setTimeout(maybeFire, 0);
1890
+ setTimeout(fireForCurrentRoute, 0);
1772
1891
  }
1773
1892
  function patchedReplaceState(...args) {
1774
1893
  originalReplaceState(...args);
1775
- setTimeout(maybeFire, 0);
1776
- }
1777
- function handlePageShow(event) {
1778
- if (!event.persisted) return;
1779
- fireManualPageView(client);
1894
+ setTimeout(fireForCurrentRoute, 0);
1780
1895
  }
1781
1896
  history.pushState = patchedPushState;
1782
1897
  history.replaceState = patchedReplaceState;
1783
- window.addEventListener("popstate", maybeFire);
1784
- window.addEventListener("pageshow", handlePageShow);
1785
- if (!options.skipInitial) fireManualPageView(client);
1898
+ window.addEventListener("popstate", fireForCurrentRoute);
1899
+ const detachBfcacheRestore = attachBfcacheRestore(client);
1900
+ fireForCurrentRoute();
1786
1901
  return () => {
1787
1902
  history.pushState = originalPushState;
1788
1903
  history.replaceState = originalReplaceState;
1789
- window.removeEventListener("popstate", maybeFire);
1790
- window.removeEventListener("pageshow", handlePageShow);
1904
+ window.removeEventListener("popstate", fireForCurrentRoute);
1905
+ detachBfcacheRestore();
1791
1906
  };
1792
1907
  }
1793
1908
 
@@ -1965,6 +2080,7 @@ function getOrCreateTrackingClient(config) {
1965
2080
  }
1966
2081
  if (globalClient !== null) {
1967
2082
  globalClient.destroy();
2083
+ resetPageViewState();
1968
2084
  }
1969
2085
  globalClient = createTrackingClient(config);
1970
2086
  globalClientKey = key;
@@ -2171,11 +2287,12 @@ function createTrackingClient(config) {
2171
2287
  identityHeaders,
2172
2288
  false
2173
2289
  );
2290
+ if (destroyed) return;
2174
2291
  if (outcome === "retry") {
2175
2292
  retryAttempt += 1;
2176
2293
  return;
2177
2294
  }
2178
- pending = pending.slice(1);
2295
+ pending = pending.filter((entry) => entry !== batch);
2179
2296
  writePendingBatches(bufferKey, pending);
2180
2297
  retryAttempt = 0;
2181
2298
  }
@@ -2206,13 +2323,14 @@ function createTrackingClient(config) {
2206
2323
  metadata: input.metadata ?? null,
2207
2324
  occurred_at: occurredAt
2208
2325
  });
2209
- if (queue.length >= maxQueueSize) {
2326
+ if (queue.length >= maxQueueSize || getEventSemantics(input.eventType)?.outcomeRole === "lead") {
2210
2327
  void flush();
2211
2328
  } else {
2212
2329
  scheduleFlush();
2213
2330
  }
2214
2331
  }
2215
2332
  function flushOnUnload() {
2333
+ if (destroyed) return;
2216
2334
  bufferQueued();
2217
2335
  clearScheduledFlush();
2218
2336
  if (pending.length === 0) return;
@@ -2222,11 +2340,12 @@ function createTrackingClient(config) {
2222
2340
  const body = { session: batch.session, events: batch.events };
2223
2341
  void postWithFetch(eventsUrl, JSON.stringify(body), config.apiKey, identityHeaders, true);
2224
2342
  }
2343
+ function onVisibilityChange() {
2344
+ if (document.visibilityState === "hidden") flushOnUnload();
2345
+ }
2225
2346
  if (typeof window !== "undefined") {
2226
2347
  window.addEventListener("pagehide", flushOnUnload);
2227
- window.addEventListener("visibilitychange", () => {
2228
- if (document.visibilityState === "hidden") flushOnUnload();
2229
- });
2348
+ window.addEventListener("visibilitychange", onVisibilityChange);
2230
2349
  }
2231
2350
  return {
2232
2351
  trackEvent,
@@ -2235,21 +2354,23 @@ function createTrackingClient(config) {
2235
2354
  getSessionId: () => sessionId,
2236
2355
  getVisitorId: () => visitorId,
2237
2356
  destroy: () => {
2238
- destroyed = true;
2357
+ if (destroyed) return;
2239
2358
  if (queue.length > 0) {
2240
2359
  flushOnUnload();
2241
2360
  }
2361
+ destroyed = true;
2242
2362
  clearScheduledFlush();
2243
2363
  queue = [];
2244
2364
  if (typeof window !== "undefined") {
2245
2365
  window.removeEventListener("pagehide", flushOnUnload);
2366
+ window.removeEventListener("visibilitychange", onVisibilityChange);
2246
2367
  }
2247
2368
  }
2248
2369
  };
2249
2370
  }
2250
2371
 
2251
2372
  // ../tracking-core/src/ingest-typed.ts
2252
- import { parse as parse2 } from "zod/mini";
2373
+ import { parse as parse2, safeParse } from "zod/mini";
2253
2374
 
2254
2375
  // ../tracking-core/src/events/cta-click.ts
2255
2376
  import * as z3 from "zod/mini";
@@ -2306,58 +2427,79 @@ var formStartConfigSchema = z5.strictObject({
2306
2427
  selector: z5.optional(z5.string())
2307
2428
  });
2308
2429
 
2309
- // ../tracking-core/src/events/form-submit.ts
2430
+ // ../tracking-core/src/events/form-step.ts
2310
2431
  import * as z6 from "zod/mini";
2311
- var jsonValueSchema = z6.lazy(
2312
- () => z6.union([
2313
- z6.string(),
2314
- z6.number(),
2315
- z6.boolean(),
2316
- z6.null(),
2317
- z6.array(jsonValueSchema),
2318
- z6.record(z6.string(), jsonValueSchema)
2319
- ])
2320
- ).register(z6.globalRegistry, { id: "JsonSerializableValue" });
2321
- var formSubmitMetadataSchema = z6.strictObject({
2432
+ var formStepMetadataSchema = z6.strictObject({
2322
2433
  form: z6.strictObject({
2323
2434
  id: z6.string(),
2324
- action: z6.nullable(z6.string()),
2325
- fields: z6.optional(
2326
- z6.array(
2327
- z6.strictObject({
2328
- name: z6.string(),
2329
- type: z6.string(),
2330
- label: z6.nullable(z6.string()),
2331
- value: jsonValueSchema
2332
- })
2333
- )
2334
- )
2435
+ action: z6.nullable(z6.string())
2335
2436
  }),
2437
+ step: z6.strictObject({
2438
+ id: z6.string().check(z6.minLength(1), z6.maxLength(64), z6.regex(/^[A-Za-z0-9_-]+$/)),
2439
+ // 1-based position in the flow the visitor is on right now.
2440
+ index: z6.int().check(z6.gte(1), z6.lte(50)),
2441
+ // Null when the number of steps depends on earlier answers.
2442
+ total: z6.nullable(z6.int().check(z6.gte(1), z6.lte(50)))
2443
+ }),
2444
+ direction: z6.enum(["forward", "back"]),
2336
2445
  page: z6.strictObject({
2337
2446
  path: z6.string()
2338
2447
  })
2339
2448
  });
2340
- var formSubmitConfigSchema = z6.strictObject({});
2449
+ var formStepConfigSchema = z6.strictObject({});
2341
2450
 
2342
- // ../tracking-core/src/events/multi-page-session.ts
2451
+ // ../tracking-core/src/events/form-submit.ts
2343
2452
  import * as z7 from "zod/mini";
2344
- var multiPageSessionMetadataSchema = z7.strictObject({
2345
- page_count: z7.int().check(z7.gte(2)),
2453
+ var jsonValueSchema = z7.lazy(
2454
+ () => z7.union([
2455
+ z7.string(),
2456
+ z7.number(),
2457
+ z7.boolean(),
2458
+ z7.null(),
2459
+ z7.array(jsonValueSchema),
2460
+ z7.record(z7.string(), jsonValueSchema)
2461
+ ])
2462
+ ).register(z7.globalRegistry, { id: "JsonSerializableValue" });
2463
+ var formSubmitMetadataSchema = z7.strictObject({
2464
+ form: z7.strictObject({
2465
+ id: z7.string(),
2466
+ action: z7.nullable(z7.string()),
2467
+ fields: z7.optional(
2468
+ z7.array(
2469
+ z7.strictObject({
2470
+ name: z7.string(),
2471
+ type: z7.string(),
2472
+ label: z7.nullable(z7.string()),
2473
+ value: jsonValueSchema
2474
+ })
2475
+ )
2476
+ )
2477
+ }),
2346
2478
  page: z7.strictObject({
2347
2479
  path: z7.string()
2348
2480
  })
2349
2481
  });
2350
- var multiPageSessionConfigSchema = z7.strictObject({
2351
- pageThreshold: z7.int().check(z7.gte(2))
2482
+ var formSubmitConfigSchema = z7.strictObject({});
2483
+
2484
+ // ../tracking-core/src/events/multi-page-session.ts
2485
+ import * as z8 from "zod/mini";
2486
+ var multiPageSessionMetadataSchema = z8.strictObject({
2487
+ page_count: z8.int().check(z8.gte(2)),
2488
+ page: z8.strictObject({
2489
+ path: z8.string()
2490
+ })
2491
+ });
2492
+ var multiPageSessionConfigSchema = z8.strictObject({
2493
+ pageThreshold: z8.int().check(z8.gte(2))
2352
2494
  });
2353
2495
 
2354
2496
  // ../tracking-core/src/events/page-exit.ts
2355
- import * as z8 from "zod/mini";
2356
- var pageExitMetadataSchema = z8.strictObject({
2357
- dwell_ms: z8.int().check(z8.gte(0)),
2497
+ import * as z9 from "zod/mini";
2498
+ var pageExitMetadataSchema = z9.strictObject({
2499
+ dwell_ms: z9.int().check(z9.gte(0)),
2358
2500
  // null = left without any scroll signal; floor is 0 so a valid 0% is never
2359
2501
  // rejected (a single bad field 422s the whole keepalive beacon batch).
2360
- max_scroll_percent: z8.nullable(z8.int().check(z8.gte(0), z8.lte(100))),
2502
+ max_scroll_percent: z9.nullable(z9.int().check(z9.gte(0), z9.lte(100))),
2361
2503
  // The gating baseline: the fraction of the page visible at load with
2362
2504
  // zero scrolling — or, for pages that grew after the post-paint snapshot
2363
2505
  // (skeleton/streaming renders), the first-scroll position that
@@ -2365,188 +2507,106 @@ var pageExitMetadataSchema = z8.strictObject({
2365
2507
  // ended before the snapshot. Optionality is load-bearing: SDK builds
2366
2508
  // predating this field keep POSTing page_exit without the key —
2367
2509
  // requiring it would 422 whole keepalive beacon batches.
2368
- scroll_baseline_percent: z8.optional(z8.nullable(z8.int().check(z8.gte(0), z8.lte(100)))),
2369
- page: z8.strictObject({
2370
- path: z8.string()
2510
+ scroll_baseline_percent: z9.optional(z9.nullable(z9.int().check(z9.gte(0), z9.lte(100)))),
2511
+ page: z9.strictObject({
2512
+ path: z9.string()
2371
2513
  })
2372
2514
  });
2373
- var pageExitConfigSchema = z8.strictObject({});
2515
+ var pageExitConfigSchema = z9.strictObject({});
2374
2516
 
2375
2517
  // ../tracking-core/src/events/phone-click.ts
2376
- import * as z9 from "zod/mini";
2377
- var phoneClickMetadataSchema = z9.strictObject({
2378
- phone_number: z9.string(),
2379
- page: z9.strictObject({
2380
- path: z9.string()
2518
+ import * as z10 from "zod/mini";
2519
+ var phoneClickMetadataSchema = z10.strictObject({
2520
+ phone_number: z10.string(),
2521
+ page: z10.strictObject({
2522
+ path: z10.string()
2381
2523
  }),
2382
- section: z9.optional(z9.nullable(z9.string()))
2524
+ section: z10.optional(z10.nullable(z10.string()))
2383
2525
  });
2384
- var phoneClickConfigSchema = z9.strictObject({
2385
- autoCapture: z9.optional(
2386
- z9.strictObject({
2387
- selector: z9.optional(z9.string())
2526
+ var phoneClickConfigSchema = z10.strictObject({
2527
+ autoCapture: z10.optional(
2528
+ z10.strictObject({
2529
+ selector: z10.optional(z10.string())
2388
2530
  })
2389
2531
  )
2390
2532
  });
2391
2533
 
2392
2534
  // ../tracking-core/src/events/scroll-depth.ts
2393
- import * as z10 from "zod/mini";
2394
- var scrollDepthMetadataSchema = z10.strictObject({
2395
- depth_percent: z10.int().check(z10.gte(1), z10.lte(100)),
2396
- page: z10.strictObject({
2397
- path: z10.string()
2535
+ import * as z11 from "zod/mini";
2536
+ var scrollDepthMetadataSchema = z11.strictObject({
2537
+ depth_percent: z11.int().check(z11.gte(1), z11.lte(100)),
2538
+ page: z11.strictObject({
2539
+ path: z11.string()
2398
2540
  })
2399
2541
  });
2400
- var scrollDepthConfigSchema = z10.strictObject({
2401
- thresholds: z10.array(z10.int().check(z10.gte(1), z10.lte(100))).check(z10.minLength(1))
2542
+ var scrollDepthConfigSchema = z11.strictObject({
2543
+ thresholds: z11.array(z11.int().check(z11.gte(1), z11.lte(100))).check(z11.minLength(1))
2402
2544
  });
2403
2545
 
2404
2546
  // ../tracking-core/src/events/specific-page-visit.ts
2405
- import * as z11 from "zod/mini";
2547
+ import * as z12 from "zod/mini";
2406
2548
  var PAGE_IDENTITY_MAX_LENGTH = 64;
2407
2549
  var PAGE_IDENTITY_PATTERN = /^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/;
2408
- var pageIdentitySchema = z11.string().check(
2409
- z11.maxLength(PAGE_IDENTITY_MAX_LENGTH),
2410
- z11.regex(PAGE_IDENTITY_PATTERN, {
2550
+ var pageIdentitySchema = z12.string().check(
2551
+ z12.maxLength(PAGE_IDENTITY_MAX_LENGTH),
2552
+ z12.regex(PAGE_IDENTITY_PATTERN, {
2411
2553
  message: "page identity must be lowercase snake_case, start with a letter, and contain at most 64 characters"
2412
2554
  })
2413
2555
  );
2414
2556
  var specificPageNameSchema = pageIdentitySchema;
2415
- var specificPageVisitMetadataSchema = z11.strictObject({
2557
+ var specificPageVisitMetadataSchema = z12.strictObject({
2416
2558
  page_name: specificPageNameSchema,
2417
- page: z11.strictObject({
2418
- path: z11.string()
2559
+ page: z12.strictObject({
2560
+ path: z12.string()
2419
2561
  })
2420
2562
  });
2421
- var specificPageVisitConfigSchema = z11.strictObject({
2422
- pages: z11.array(
2423
- z11.strictObject({
2563
+ var specificPageVisitConfigSchema = z12.strictObject({
2564
+ pages: z12.array(
2565
+ z12.strictObject({
2424
2566
  name: specificPageNameSchema,
2425
- pathPattern: z11.custom((value) => value instanceof RegExp, {
2567
+ pathPattern: z12.custom((value) => value instanceof RegExp, {
2426
2568
  message: "pathPattern must be a RegExp"
2427
2569
  })
2428
2570
  })
2429
- ).check(z11.minLength(1))
2571
+ ).check(z12.minLength(1))
2430
2572
  });
2431
2573
 
2432
2574
  // ../tracking-core/src/events/site-link.ts
2433
- import * as z12 from "zod/mini";
2434
- var siteLinkClickMetadataSchema = z12.strictObject({
2435
- destination_host: z12.string(),
2436
- destination_url: z12.string(),
2437
- page: z12.strictObject({
2438
- path: z12.string()
2575
+ import * as z13 from "zod/mini";
2576
+ var siteLinkClickMetadataSchema = z13.strictObject({
2577
+ destination_host: z13.string(),
2578
+ destination_url: z13.string(),
2579
+ page: z13.strictObject({
2580
+ path: z13.string()
2439
2581
  })
2440
2582
  });
2441
- var siteLinkClickConfigSchema = z12.strictObject({});
2442
- var siteLinkArrivalMetadataSchema = z12.strictObject({
2443
- outcome: z12.enum(["linked", "stale", "invalid"]),
2444
- origin_session_id: z12.optional(z12.nullable(z12.string())),
2445
- origin_visitor_id: z12.optional(z12.nullable(z12.string())),
2583
+ var siteLinkClickConfigSchema = z13.strictObject({});
2584
+ var siteLinkArrivalMetadataSchema = z13.strictObject({
2585
+ outcome: z13.enum(["linked", "stale", "invalid"]),
2586
+ origin_session_id: z13.optional(z13.nullable(z13.string())),
2587
+ origin_visitor_id: z13.optional(z13.nullable(z13.string())),
2446
2588
  // Milliseconds between the origin click and this page load.
2447
- transit_ms: z12.optional(z12.nullable(z12.number())),
2589
+ transit_ms: z13.optional(z13.nullable(z13.number())),
2448
2590
  // True when this browser had no visitor id and took the origin's.
2449
- adopted_visitor: z12.boolean(),
2450
- page: z12.strictObject({
2451
- path: z12.string()
2591
+ adopted_visitor: z13.boolean(),
2592
+ page: z13.strictObject({
2593
+ path: z13.string()
2452
2594
  })
2453
2595
  });
2454
- var siteLinkArrivalConfigSchema = z12.strictObject({});
2596
+ var siteLinkArrivalConfigSchema = z13.strictObject({});
2455
2597
 
2456
2598
  // ../tracking-core/src/events/time-on-site.ts
2457
- import * as z13 from "zod/mini";
2458
- var timeOnSiteMetadataSchema = z13.strictObject({
2459
- duration_ms: z13.int().check(z13.nonnegative()),
2460
- page: z13.strictObject({
2461
- path: z13.string()
2599
+ import * as z14 from "zod/mini";
2600
+ var timeOnSiteMetadataSchema = z14.strictObject({
2601
+ duration_ms: z14.int().check(z14.nonnegative()),
2602
+ page: z14.strictObject({
2603
+ path: z14.string()
2462
2604
  })
2463
2605
  });
2464
- var timeOnSiteConfigSchema = z13.strictObject({
2465
- thresholdSeconds: z13.int().check(z13.positive())
2606
+ var timeOnSiteConfigSchema = z14.strictObject({
2607
+ thresholdSeconds: z14.int().check(z14.positive())
2466
2608
  });
2467
2609
 
2468
- // ../tracking-core/src/events/semantics.ts
2469
- var EVENT_SEMANTICS = {
2470
- page_view: {
2471
- label: "Page view",
2472
- category: "page",
2473
- outcomeRole: "navigation",
2474
- clientVisibility: "simple"
2475
- },
2476
- time_on_site: {
2477
- label: "Time on site",
2478
- category: "engagement",
2479
- outcomeRole: "engagement",
2480
- clientVisibility: "detailed"
2481
- },
2482
- specific_page_visit: {
2483
- label: "Key page visit",
2484
- category: "engagement",
2485
- outcomeRole: "engagement",
2486
- clientVisibility: "detailed"
2487
- },
2488
- scroll_depth: {
2489
- label: "Scroll depth",
2490
- category: "engagement",
2491
- outcomeRole: "engagement",
2492
- clientVisibility: "detailed"
2493
- },
2494
- multi_page_session: {
2495
- label: "Multi-page session",
2496
- category: "engagement",
2497
- outcomeRole: "engagement",
2498
- clientVisibility: "detailed"
2499
- },
2500
- form_start: {
2501
- label: "Form started",
2502
- category: "engagement",
2503
- outcomeRole: "engagement",
2504
- clientVisibility: "simple"
2505
- },
2506
- sdk_heartbeat: {
2507
- label: "SDK heartbeat",
2508
- category: "system",
2509
- outcomeRole: "diagnostic",
2510
- clientVisibility: "hidden"
2511
- },
2512
- page_exit: {
2513
- label: "Page exit",
2514
- category: "engagement",
2515
- outcomeRole: "diagnostic",
2516
- clientVisibility: "detailed"
2517
- },
2518
- form_submit: {
2519
- label: "Form submitted",
2520
- category: "lead",
2521
- outcomeRole: "lead",
2522
- clientVisibility: "simple"
2523
- },
2524
- phone_click: {
2525
- label: "Phone click",
2526
- category: "lead",
2527
- outcomeRole: "lead",
2528
- clientVisibility: "simple"
2529
- },
2530
- cta_click: {
2531
- label: "CTA click",
2532
- category: "engagement",
2533
- outcomeRole: "engagement",
2534
- clientVisibility: "simple"
2535
- },
2536
- site_link_click: {
2537
- label: "Left for sibling site",
2538
- category: "page",
2539
- outcomeRole: "navigation",
2540
- clientVisibility: "detailed"
2541
- },
2542
- site_link_arrival: {
2543
- label: "Arrived from sibling site",
2544
- category: "page",
2545
- outcomeRole: "navigation",
2546
- clientVisibility: "simple"
2547
- }
2548
- };
2549
-
2550
2610
  // ../tracking-core/src/events/registry.ts
2551
2611
  var EVENT_REGISTRY = {
2552
2612
  // --- automatic triggers ---
@@ -2620,6 +2680,12 @@ var EVENT_REGISTRY = {
2620
2680
  metadataSchema: formSubmitMetadataSchema,
2621
2681
  configSchema: formSubmitConfigSchema
2622
2682
  },
2683
+ form_step: {
2684
+ kind: "manual",
2685
+ semantics: EVENT_SEMANTICS.form_step,
2686
+ metadataSchema: formStepMetadataSchema,
2687
+ configSchema: formStepConfigSchema
2688
+ },
2623
2689
  phone_click: {
2624
2690
  kind: "manual",
2625
2691
  semantics: EVENT_SEMANTICS.phone_click,
@@ -2646,9 +2712,14 @@ function createTypedClient(raw, registry, options = {}) {
2646
2712
  if (registry.manual?.form_submit) registerCapability("form_capture");
2647
2713
  return {
2648
2714
  trackEvent(eventType, metadata, opts) {
2715
+ const def = getEventDefinition(eventType);
2649
2716
  if (debug) {
2650
- const def = getEventDefinition(eventType);
2651
2717
  parse2(def.metadataSchema, metadata);
2718
+ } else if (!safeParse(def.metadataSchema, metadata).success) {
2719
+ console.warn(
2720
+ `[AranovaTracking] trackEvent: metadata for "${eventType}" failed schema validation; event dropped`
2721
+ );
2722
+ return;
2652
2723
  }
2653
2724
  raw.trackEvent({
2654
2725
  eventType,
@@ -3023,8 +3094,14 @@ function attachFormStart(client, config) {
3023
3094
  return `index:${forms.indexOf(form)}`;
3024
3095
  }
3025
3096
  function onFocusIn(event) {
3026
- const target = event.target;
3027
- if (!(target instanceof HTMLElement)) return;
3097
+ startFrom(event.target);
3098
+ }
3099
+ function onPointerDown(event) {
3100
+ if (event.button !== 0) return;
3101
+ startFrom(event.target);
3102
+ }
3103
+ function startFrom(target) {
3104
+ if (!(target instanceof Element)) return;
3028
3105
  const form = target.closest(selector);
3029
3106
  if (!form || form.tagName !== "FORM") return;
3030
3107
  const key = getFormKey(form);
@@ -3063,11 +3140,13 @@ function attachFormStart(client, config) {
3063
3140
  history.replaceState = patchedReplaceState;
3064
3141
  window.addEventListener("popstate", resetIfPathChanged);
3065
3142
  document.addEventListener("focusin", onFocusIn);
3143
+ document.addEventListener("pointerdown", onPointerDown, { capture: true, passive: true });
3066
3144
  return () => {
3067
3145
  history.pushState = originalPushState;
3068
3146
  history.replaceState = originalReplaceState;
3069
3147
  window.removeEventListener("popstate", resetIfPathChanged);
3070
3148
  document.removeEventListener("focusin", onFocusIn);
3149
+ document.removeEventListener("pointerdown", onPointerDown, { capture: true });
3071
3150
  };
3072
3151
  }
3073
3152
 
@@ -3654,7 +3733,7 @@ function GoogleAdsTracking(props) {
3654
3733
  import { createContext as createContext2, useContext as useContext2, useEffect as useEffect5, useMemo as useMemo4 } from "react";
3655
3734
 
3656
3735
  // package.json
3657
- var version = "1.2.1";
3736
+ var version = "1.2.3";
3658
3737
 
3659
3738
  // ../tracking-core/src/phone-react.tsx
3660
3739
  import {
@@ -3867,7 +3946,6 @@ function createTracking(options) {
3867
3946
  }
3868
3947
  } : detectorClient;
3869
3948
  detachers.push(attachAutoPageView(pageClient));
3870
- detachers.push(attachBfcacheRestore(pageClient));
3871
3949
  detachers.push(attachPageExit(detectorClient));
3872
3950
  const timeOnSite = triggers.automatic.time_on_site;
3873
3951
  if (timeOnSite) {