@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.js CHANGED
@@ -1697,6 +1697,97 @@ function withConversionAutoFire(client, autoFire) {
1697
1697
  };
1698
1698
  }
1699
1699
 
1700
+ // ../tracking-core/src/events/semantics.ts
1701
+ var EVENT_SEMANTICS = {
1702
+ page_view: {
1703
+ label: "Page view",
1704
+ category: "page",
1705
+ outcomeRole: "navigation",
1706
+ clientVisibility: "simple"
1707
+ },
1708
+ time_on_site: {
1709
+ label: "Time on site",
1710
+ category: "engagement",
1711
+ outcomeRole: "engagement",
1712
+ clientVisibility: "detailed"
1713
+ },
1714
+ specific_page_visit: {
1715
+ label: "Key page visit",
1716
+ category: "engagement",
1717
+ outcomeRole: "engagement",
1718
+ clientVisibility: "detailed"
1719
+ },
1720
+ scroll_depth: {
1721
+ label: "Scroll depth",
1722
+ category: "engagement",
1723
+ outcomeRole: "engagement",
1724
+ clientVisibility: "detailed"
1725
+ },
1726
+ multi_page_session: {
1727
+ label: "Multi-page session",
1728
+ category: "engagement",
1729
+ outcomeRole: "engagement",
1730
+ clientVisibility: "detailed"
1731
+ },
1732
+ form_start: {
1733
+ label: "Form started",
1734
+ category: "engagement",
1735
+ outcomeRole: "engagement",
1736
+ clientVisibility: "simple"
1737
+ },
1738
+ sdk_heartbeat: {
1739
+ label: "SDK heartbeat",
1740
+ category: "system",
1741
+ outcomeRole: "diagnostic",
1742
+ clientVisibility: "hidden"
1743
+ },
1744
+ page_exit: {
1745
+ label: "Page exit",
1746
+ category: "engagement",
1747
+ outcomeRole: "diagnostic",
1748
+ clientVisibility: "detailed"
1749
+ },
1750
+ form_step: {
1751
+ label: "Form step",
1752
+ category: "engagement",
1753
+ outcomeRole: "engagement",
1754
+ clientVisibility: "detailed"
1755
+ },
1756
+ form_submit: {
1757
+ label: "Form submitted",
1758
+ category: "lead",
1759
+ outcomeRole: "lead",
1760
+ clientVisibility: "simple"
1761
+ },
1762
+ phone_click: {
1763
+ label: "Phone click",
1764
+ category: "lead",
1765
+ outcomeRole: "lead",
1766
+ clientVisibility: "simple"
1767
+ },
1768
+ cta_click: {
1769
+ label: "CTA click",
1770
+ category: "engagement",
1771
+ outcomeRole: "engagement",
1772
+ clientVisibility: "simple"
1773
+ },
1774
+ site_link_click: {
1775
+ label: "Left for sibling site",
1776
+ category: "page",
1777
+ outcomeRole: "navigation",
1778
+ clientVisibility: "detailed"
1779
+ },
1780
+ site_link_arrival: {
1781
+ label: "Arrived from sibling site",
1782
+ category: "page",
1783
+ outcomeRole: "navigation",
1784
+ clientVisibility: "simple"
1785
+ }
1786
+ };
1787
+ function getEventSemantics(eventName) {
1788
+ return eventName in EVENT_SEMANTICS ? EVENT_SEMANTICS[eventName] : null;
1789
+ }
1790
+
1700
1791
  // ../tracking-core/src/page-view.ts
1701
1792
  var import_mini = require("zod/mini");
1702
1793
 
@@ -1743,6 +1834,13 @@ function writeSessionStorage(key, value) {
1743
1834
  } catch {
1744
1835
  }
1745
1836
  }
1837
+ function deleteSessionStorage(key) {
1838
+ try {
1839
+ if (typeof window === "undefined") return;
1840
+ window.sessionStorage.removeItem(key);
1841
+ } catch {
1842
+ }
1843
+ }
1746
1844
  function getLastFiredUrl() {
1747
1845
  if (!lastFiredUrlHydrated) {
1748
1846
  lastFiredUrlHydrated = true;
@@ -1756,6 +1854,31 @@ function setLastFiredUrl(url) {
1756
1854
  lastFiredUrlHydrated = true;
1757
1855
  writeSessionStorage(LAST_FIRED_URL_STORAGE_KEY, url);
1758
1856
  }
1857
+ function resetPageViewState() {
1858
+ lastFiredUrl = null;
1859
+ lastFiredUrlHydrated = false;
1860
+ deleteSessionStorage(LAST_FIRED_URL_STORAGE_KEY);
1861
+ autoPageViewSlot().key = null;
1862
+ }
1863
+ var AUTO_PAGE_VIEW_SLOT = /* @__PURE__ */ Symbol.for("aranova.tracking.autoPageView");
1864
+ function autoPageViewSlot() {
1865
+ const scope = globalThis;
1866
+ scope[AUTO_PAGE_VIEW_SLOT] ?? (scope[AUTO_PAGE_VIEW_SLOT] = { key: null });
1867
+ return scope[AUTO_PAGE_VIEW_SLOT];
1868
+ }
1869
+ function pageViewRouteKey(pathname, search) {
1870
+ const query = stripLinkParamFromSearch(search);
1871
+ return query.length > 1 ? `${pathname}${query}` : pathname;
1872
+ }
1873
+ function fireAutoPageView(client, options = {}) {
1874
+ if (typeof window === "undefined") return false;
1875
+ const key = pageViewRouteKey(window.location.pathname, window.location.search);
1876
+ const slot = autoPageViewSlot();
1877
+ if (!options.force && slot.key === key) return false;
1878
+ slot.key = key;
1879
+ fireManualPageView(client);
1880
+ return true;
1881
+ }
1759
1882
  function buildPageViewMetadata(referrerOverride) {
1760
1883
  if (typeof window === "undefined" || typeof document === "undefined") return null;
1761
1884
  return (0, import_mini.parse)(pageViewMetadataSchema, {
@@ -1791,49 +1914,41 @@ function attachBfcacheRestore(client) {
1791
1914
  };
1792
1915
  function handlePageShow(event) {
1793
1916
  if (!event.persisted) return;
1794
- fireManualPageView(client);
1917
+ fireAutoPageView(client, { force: true });
1795
1918
  }
1796
1919
  window.addEventListener("pageshow", handlePageShow);
1797
1920
  return () => {
1798
1921
  window.removeEventListener("pageshow", handlePageShow);
1799
1922
  };
1800
1923
  }
1801
- function attachAutoPageView(client, options = {}) {
1924
+ function attachAutoPageView(client) {
1802
1925
  if (typeof window === "undefined" || typeof history === "undefined") {
1803
1926
  return () => {
1804
1927
  };
1805
1928
  }
1806
- let lastPath = window.location.pathname + window.location.search;
1807
- function maybeFire() {
1808
- const current = window.location.pathname + window.location.search;
1809
- if (current === lastPath) return;
1810
- lastPath = current;
1811
- fireManualPageView(client);
1929
+ function fireForCurrentRoute() {
1930
+ fireAutoPageView(client);
1812
1931
  }
1813
1932
  const originalPushState = history.pushState.bind(history);
1814
1933
  const originalReplaceState = history.replaceState.bind(history);
1815
1934
  function patchedPushState(...args) {
1816
1935
  originalPushState(...args);
1817
- setTimeout(maybeFire, 0);
1936
+ setTimeout(fireForCurrentRoute, 0);
1818
1937
  }
1819
1938
  function patchedReplaceState(...args) {
1820
1939
  originalReplaceState(...args);
1821
- setTimeout(maybeFire, 0);
1822
- }
1823
- function handlePageShow(event) {
1824
- if (!event.persisted) return;
1825
- fireManualPageView(client);
1940
+ setTimeout(fireForCurrentRoute, 0);
1826
1941
  }
1827
1942
  history.pushState = patchedPushState;
1828
1943
  history.replaceState = patchedReplaceState;
1829
- window.addEventListener("popstate", maybeFire);
1830
- window.addEventListener("pageshow", handlePageShow);
1831
- if (!options.skipInitial) fireManualPageView(client);
1944
+ window.addEventListener("popstate", fireForCurrentRoute);
1945
+ const detachBfcacheRestore = attachBfcacheRestore(client);
1946
+ fireForCurrentRoute();
1832
1947
  return () => {
1833
1948
  history.pushState = originalPushState;
1834
1949
  history.replaceState = originalReplaceState;
1835
- window.removeEventListener("popstate", maybeFire);
1836
- window.removeEventListener("pageshow", handlePageShow);
1950
+ window.removeEventListener("popstate", fireForCurrentRoute);
1951
+ detachBfcacheRestore();
1837
1952
  };
1838
1953
  }
1839
1954
 
@@ -2011,6 +2126,7 @@ function getOrCreateTrackingClient(config) {
2011
2126
  }
2012
2127
  if (globalClient !== null) {
2013
2128
  globalClient.destroy();
2129
+ resetPageViewState();
2014
2130
  }
2015
2131
  globalClient = createTrackingClient(config);
2016
2132
  globalClientKey = key;
@@ -2217,11 +2333,12 @@ function createTrackingClient(config) {
2217
2333
  identityHeaders,
2218
2334
  false
2219
2335
  );
2336
+ if (destroyed) return;
2220
2337
  if (outcome === "retry") {
2221
2338
  retryAttempt += 1;
2222
2339
  return;
2223
2340
  }
2224
- pending = pending.slice(1);
2341
+ pending = pending.filter((entry) => entry !== batch);
2225
2342
  writePendingBatches(bufferKey, pending);
2226
2343
  retryAttempt = 0;
2227
2344
  }
@@ -2252,13 +2369,14 @@ function createTrackingClient(config) {
2252
2369
  metadata: input.metadata ?? null,
2253
2370
  occurred_at: occurredAt
2254
2371
  });
2255
- if (queue.length >= maxQueueSize) {
2372
+ if (queue.length >= maxQueueSize || getEventSemantics(input.eventType)?.outcomeRole === "lead") {
2256
2373
  void flush();
2257
2374
  } else {
2258
2375
  scheduleFlush();
2259
2376
  }
2260
2377
  }
2261
2378
  function flushOnUnload() {
2379
+ if (destroyed) return;
2262
2380
  bufferQueued();
2263
2381
  clearScheduledFlush();
2264
2382
  if (pending.length === 0) return;
@@ -2268,11 +2386,12 @@ function createTrackingClient(config) {
2268
2386
  const body = { session: batch.session, events: batch.events };
2269
2387
  void postWithFetch(eventsUrl, JSON.stringify(body), config.apiKey, identityHeaders, true);
2270
2388
  }
2389
+ function onVisibilityChange() {
2390
+ if (document.visibilityState === "hidden") flushOnUnload();
2391
+ }
2271
2392
  if (typeof window !== "undefined") {
2272
2393
  window.addEventListener("pagehide", flushOnUnload);
2273
- window.addEventListener("visibilitychange", () => {
2274
- if (document.visibilityState === "hidden") flushOnUnload();
2275
- });
2394
+ window.addEventListener("visibilitychange", onVisibilityChange);
2276
2395
  }
2277
2396
  return {
2278
2397
  trackEvent,
@@ -2281,14 +2400,16 @@ function createTrackingClient(config) {
2281
2400
  getSessionId: () => sessionId,
2282
2401
  getVisitorId: () => visitorId,
2283
2402
  destroy: () => {
2284
- destroyed = true;
2403
+ if (destroyed) return;
2285
2404
  if (queue.length > 0) {
2286
2405
  flushOnUnload();
2287
2406
  }
2407
+ destroyed = true;
2288
2408
  clearScheduledFlush();
2289
2409
  queue = [];
2290
2410
  if (typeof window !== "undefined") {
2291
2411
  window.removeEventListener("pagehide", flushOnUnload);
2412
+ window.removeEventListener("visibilitychange", onVisibilityChange);
2292
2413
  }
2293
2414
  }
2294
2415
  };
@@ -2352,58 +2473,79 @@ var formStartConfigSchema = z5.strictObject({
2352
2473
  selector: z5.optional(z5.string())
2353
2474
  });
2354
2475
 
2355
- // ../tracking-core/src/events/form-submit.ts
2476
+ // ../tracking-core/src/events/form-step.ts
2356
2477
  var z6 = __toESM(require("zod/mini"));
2357
- var jsonValueSchema = z6.lazy(
2358
- () => z6.union([
2359
- z6.string(),
2360
- z6.number(),
2361
- z6.boolean(),
2362
- z6.null(),
2363
- z6.array(jsonValueSchema),
2364
- z6.record(z6.string(), jsonValueSchema)
2365
- ])
2366
- ).register(z6.globalRegistry, { id: "JsonSerializableValue" });
2367
- var formSubmitMetadataSchema = z6.strictObject({
2478
+ var formStepMetadataSchema = z6.strictObject({
2368
2479
  form: z6.strictObject({
2369
2480
  id: z6.string(),
2370
- action: z6.nullable(z6.string()),
2371
- fields: z6.optional(
2372
- z6.array(
2373
- z6.strictObject({
2374
- name: z6.string(),
2375
- type: z6.string(),
2376
- label: z6.nullable(z6.string()),
2377
- value: jsonValueSchema
2378
- })
2379
- )
2380
- )
2481
+ action: z6.nullable(z6.string())
2381
2482
  }),
2483
+ step: z6.strictObject({
2484
+ id: z6.string().check(z6.minLength(1), z6.maxLength(64), z6.regex(/^[A-Za-z0-9_-]+$/)),
2485
+ // 1-based position in the flow the visitor is on right now.
2486
+ index: z6.int().check(z6.gte(1), z6.lte(50)),
2487
+ // Null when the number of steps depends on earlier answers.
2488
+ total: z6.nullable(z6.int().check(z6.gte(1), z6.lte(50)))
2489
+ }),
2490
+ direction: z6.enum(["forward", "back"]),
2382
2491
  page: z6.strictObject({
2383
2492
  path: z6.string()
2384
2493
  })
2385
2494
  });
2386
- var formSubmitConfigSchema = z6.strictObject({});
2495
+ var formStepConfigSchema = z6.strictObject({});
2387
2496
 
2388
- // ../tracking-core/src/events/multi-page-session.ts
2497
+ // ../tracking-core/src/events/form-submit.ts
2389
2498
  var z7 = __toESM(require("zod/mini"));
2390
- var multiPageSessionMetadataSchema = z7.strictObject({
2391
- page_count: z7.int().check(z7.gte(2)),
2499
+ var jsonValueSchema = z7.lazy(
2500
+ () => z7.union([
2501
+ z7.string(),
2502
+ z7.number(),
2503
+ z7.boolean(),
2504
+ z7.null(),
2505
+ z7.array(jsonValueSchema),
2506
+ z7.record(z7.string(), jsonValueSchema)
2507
+ ])
2508
+ ).register(z7.globalRegistry, { id: "JsonSerializableValue" });
2509
+ var formSubmitMetadataSchema = z7.strictObject({
2510
+ form: z7.strictObject({
2511
+ id: z7.string(),
2512
+ action: z7.nullable(z7.string()),
2513
+ fields: z7.optional(
2514
+ z7.array(
2515
+ z7.strictObject({
2516
+ name: z7.string(),
2517
+ type: z7.string(),
2518
+ label: z7.nullable(z7.string()),
2519
+ value: jsonValueSchema
2520
+ })
2521
+ )
2522
+ )
2523
+ }),
2392
2524
  page: z7.strictObject({
2393
2525
  path: z7.string()
2394
2526
  })
2395
2527
  });
2396
- var multiPageSessionConfigSchema = z7.strictObject({
2397
- pageThreshold: z7.int().check(z7.gte(2))
2528
+ var formSubmitConfigSchema = z7.strictObject({});
2529
+
2530
+ // ../tracking-core/src/events/multi-page-session.ts
2531
+ var z8 = __toESM(require("zod/mini"));
2532
+ var multiPageSessionMetadataSchema = z8.strictObject({
2533
+ page_count: z8.int().check(z8.gte(2)),
2534
+ page: z8.strictObject({
2535
+ path: z8.string()
2536
+ })
2537
+ });
2538
+ var multiPageSessionConfigSchema = z8.strictObject({
2539
+ pageThreshold: z8.int().check(z8.gte(2))
2398
2540
  });
2399
2541
 
2400
2542
  // ../tracking-core/src/events/page-exit.ts
2401
- var z8 = __toESM(require("zod/mini"));
2402
- var pageExitMetadataSchema = z8.strictObject({
2403
- dwell_ms: z8.int().check(z8.gte(0)),
2543
+ var z9 = __toESM(require("zod/mini"));
2544
+ var pageExitMetadataSchema = z9.strictObject({
2545
+ dwell_ms: z9.int().check(z9.gte(0)),
2404
2546
  // null = left without any scroll signal; floor is 0 so a valid 0% is never
2405
2547
  // rejected (a single bad field 422s the whole keepalive beacon batch).
2406
- max_scroll_percent: z8.nullable(z8.int().check(z8.gte(0), z8.lte(100))),
2548
+ max_scroll_percent: z9.nullable(z9.int().check(z9.gte(0), z9.lte(100))),
2407
2549
  // The gating baseline: the fraction of the page visible at load with
2408
2550
  // zero scrolling — or, for pages that grew after the post-paint snapshot
2409
2551
  // (skeleton/streaming renders), the first-scroll position that
@@ -2411,188 +2553,106 @@ var pageExitMetadataSchema = z8.strictObject({
2411
2553
  // ended before the snapshot. Optionality is load-bearing: SDK builds
2412
2554
  // predating this field keep POSTing page_exit without the key —
2413
2555
  // requiring it would 422 whole keepalive beacon batches.
2414
- scroll_baseline_percent: z8.optional(z8.nullable(z8.int().check(z8.gte(0), z8.lte(100)))),
2415
- page: z8.strictObject({
2416
- path: z8.string()
2556
+ scroll_baseline_percent: z9.optional(z9.nullable(z9.int().check(z9.gte(0), z9.lte(100)))),
2557
+ page: z9.strictObject({
2558
+ path: z9.string()
2417
2559
  })
2418
2560
  });
2419
- var pageExitConfigSchema = z8.strictObject({});
2561
+ var pageExitConfigSchema = z9.strictObject({});
2420
2562
 
2421
2563
  // ../tracking-core/src/events/phone-click.ts
2422
- var z9 = __toESM(require("zod/mini"));
2423
- var phoneClickMetadataSchema = z9.strictObject({
2424
- phone_number: z9.string(),
2425
- page: z9.strictObject({
2426
- path: z9.string()
2564
+ var z10 = __toESM(require("zod/mini"));
2565
+ var phoneClickMetadataSchema = z10.strictObject({
2566
+ phone_number: z10.string(),
2567
+ page: z10.strictObject({
2568
+ path: z10.string()
2427
2569
  }),
2428
- section: z9.optional(z9.nullable(z9.string()))
2570
+ section: z10.optional(z10.nullable(z10.string()))
2429
2571
  });
2430
- var phoneClickConfigSchema = z9.strictObject({
2431
- autoCapture: z9.optional(
2432
- z9.strictObject({
2433
- selector: z9.optional(z9.string())
2572
+ var phoneClickConfigSchema = z10.strictObject({
2573
+ autoCapture: z10.optional(
2574
+ z10.strictObject({
2575
+ selector: z10.optional(z10.string())
2434
2576
  })
2435
2577
  )
2436
2578
  });
2437
2579
 
2438
2580
  // ../tracking-core/src/events/scroll-depth.ts
2439
- var z10 = __toESM(require("zod/mini"));
2440
- var scrollDepthMetadataSchema = z10.strictObject({
2441
- depth_percent: z10.int().check(z10.gte(1), z10.lte(100)),
2442
- page: z10.strictObject({
2443
- path: z10.string()
2581
+ var z11 = __toESM(require("zod/mini"));
2582
+ var scrollDepthMetadataSchema = z11.strictObject({
2583
+ depth_percent: z11.int().check(z11.gte(1), z11.lte(100)),
2584
+ page: z11.strictObject({
2585
+ path: z11.string()
2444
2586
  })
2445
2587
  });
2446
- var scrollDepthConfigSchema = z10.strictObject({
2447
- thresholds: z10.array(z10.int().check(z10.gte(1), z10.lte(100))).check(z10.minLength(1))
2588
+ var scrollDepthConfigSchema = z11.strictObject({
2589
+ thresholds: z11.array(z11.int().check(z11.gte(1), z11.lte(100))).check(z11.minLength(1))
2448
2590
  });
2449
2591
 
2450
2592
  // ../tracking-core/src/events/specific-page-visit.ts
2451
- var z11 = __toESM(require("zod/mini"));
2593
+ var z12 = __toESM(require("zod/mini"));
2452
2594
  var PAGE_IDENTITY_MAX_LENGTH = 64;
2453
2595
  var PAGE_IDENTITY_PATTERN = /^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/;
2454
- var pageIdentitySchema = z11.string().check(
2455
- z11.maxLength(PAGE_IDENTITY_MAX_LENGTH),
2456
- z11.regex(PAGE_IDENTITY_PATTERN, {
2596
+ var pageIdentitySchema = z12.string().check(
2597
+ z12.maxLength(PAGE_IDENTITY_MAX_LENGTH),
2598
+ z12.regex(PAGE_IDENTITY_PATTERN, {
2457
2599
  message: "page identity must be lowercase snake_case, start with a letter, and contain at most 64 characters"
2458
2600
  })
2459
2601
  );
2460
2602
  var specificPageNameSchema = pageIdentitySchema;
2461
- var specificPageVisitMetadataSchema = z11.strictObject({
2603
+ var specificPageVisitMetadataSchema = z12.strictObject({
2462
2604
  page_name: specificPageNameSchema,
2463
- page: z11.strictObject({
2464
- path: z11.string()
2605
+ page: z12.strictObject({
2606
+ path: z12.string()
2465
2607
  })
2466
2608
  });
2467
- var specificPageVisitConfigSchema = z11.strictObject({
2468
- pages: z11.array(
2469
- z11.strictObject({
2609
+ var specificPageVisitConfigSchema = z12.strictObject({
2610
+ pages: z12.array(
2611
+ z12.strictObject({
2470
2612
  name: specificPageNameSchema,
2471
- pathPattern: z11.custom((value) => value instanceof RegExp, {
2613
+ pathPattern: z12.custom((value) => value instanceof RegExp, {
2472
2614
  message: "pathPattern must be a RegExp"
2473
2615
  })
2474
2616
  })
2475
- ).check(z11.minLength(1))
2617
+ ).check(z12.minLength(1))
2476
2618
  });
2477
2619
 
2478
2620
  // ../tracking-core/src/events/site-link.ts
2479
- var z12 = __toESM(require("zod/mini"));
2480
- var siteLinkClickMetadataSchema = z12.strictObject({
2481
- destination_host: z12.string(),
2482
- destination_url: z12.string(),
2483
- page: z12.strictObject({
2484
- path: z12.string()
2621
+ var z13 = __toESM(require("zod/mini"));
2622
+ var siteLinkClickMetadataSchema = z13.strictObject({
2623
+ destination_host: z13.string(),
2624
+ destination_url: z13.string(),
2625
+ page: z13.strictObject({
2626
+ path: z13.string()
2485
2627
  })
2486
2628
  });
2487
- var siteLinkClickConfigSchema = z12.strictObject({});
2488
- var siteLinkArrivalMetadataSchema = z12.strictObject({
2489
- outcome: z12.enum(["linked", "stale", "invalid"]),
2490
- origin_session_id: z12.optional(z12.nullable(z12.string())),
2491
- origin_visitor_id: z12.optional(z12.nullable(z12.string())),
2629
+ var siteLinkClickConfigSchema = z13.strictObject({});
2630
+ var siteLinkArrivalMetadataSchema = z13.strictObject({
2631
+ outcome: z13.enum(["linked", "stale", "invalid"]),
2632
+ origin_session_id: z13.optional(z13.nullable(z13.string())),
2633
+ origin_visitor_id: z13.optional(z13.nullable(z13.string())),
2492
2634
  // Milliseconds between the origin click and this page load.
2493
- transit_ms: z12.optional(z12.nullable(z12.number())),
2635
+ transit_ms: z13.optional(z13.nullable(z13.number())),
2494
2636
  // True when this browser had no visitor id and took the origin's.
2495
- adopted_visitor: z12.boolean(),
2496
- page: z12.strictObject({
2497
- path: z12.string()
2637
+ adopted_visitor: z13.boolean(),
2638
+ page: z13.strictObject({
2639
+ path: z13.string()
2498
2640
  })
2499
2641
  });
2500
- var siteLinkArrivalConfigSchema = z12.strictObject({});
2642
+ var siteLinkArrivalConfigSchema = z13.strictObject({});
2501
2643
 
2502
2644
  // ../tracking-core/src/events/time-on-site.ts
2503
- var z13 = __toESM(require("zod/mini"));
2504
- var timeOnSiteMetadataSchema = z13.strictObject({
2505
- duration_ms: z13.int().check(z13.nonnegative()),
2506
- page: z13.strictObject({
2507
- path: z13.string()
2645
+ var z14 = __toESM(require("zod/mini"));
2646
+ var timeOnSiteMetadataSchema = z14.strictObject({
2647
+ duration_ms: z14.int().check(z14.nonnegative()),
2648
+ page: z14.strictObject({
2649
+ path: z14.string()
2508
2650
  })
2509
2651
  });
2510
- var timeOnSiteConfigSchema = z13.strictObject({
2511
- thresholdSeconds: z13.int().check(z13.positive())
2652
+ var timeOnSiteConfigSchema = z14.strictObject({
2653
+ thresholdSeconds: z14.int().check(z14.positive())
2512
2654
  });
2513
2655
 
2514
- // ../tracking-core/src/events/semantics.ts
2515
- var EVENT_SEMANTICS = {
2516
- page_view: {
2517
- label: "Page view",
2518
- category: "page",
2519
- outcomeRole: "navigation",
2520
- clientVisibility: "simple"
2521
- },
2522
- time_on_site: {
2523
- label: "Time on site",
2524
- category: "engagement",
2525
- outcomeRole: "engagement",
2526
- clientVisibility: "detailed"
2527
- },
2528
- specific_page_visit: {
2529
- label: "Key page visit",
2530
- category: "engagement",
2531
- outcomeRole: "engagement",
2532
- clientVisibility: "detailed"
2533
- },
2534
- scroll_depth: {
2535
- label: "Scroll depth",
2536
- category: "engagement",
2537
- outcomeRole: "engagement",
2538
- clientVisibility: "detailed"
2539
- },
2540
- multi_page_session: {
2541
- label: "Multi-page session",
2542
- category: "engagement",
2543
- outcomeRole: "engagement",
2544
- clientVisibility: "detailed"
2545
- },
2546
- form_start: {
2547
- label: "Form started",
2548
- category: "engagement",
2549
- outcomeRole: "engagement",
2550
- clientVisibility: "simple"
2551
- },
2552
- sdk_heartbeat: {
2553
- label: "SDK heartbeat",
2554
- category: "system",
2555
- outcomeRole: "diagnostic",
2556
- clientVisibility: "hidden"
2557
- },
2558
- page_exit: {
2559
- label: "Page exit",
2560
- category: "engagement",
2561
- outcomeRole: "diagnostic",
2562
- clientVisibility: "detailed"
2563
- },
2564
- form_submit: {
2565
- label: "Form submitted",
2566
- category: "lead",
2567
- outcomeRole: "lead",
2568
- clientVisibility: "simple"
2569
- },
2570
- phone_click: {
2571
- label: "Phone click",
2572
- category: "lead",
2573
- outcomeRole: "lead",
2574
- clientVisibility: "simple"
2575
- },
2576
- cta_click: {
2577
- label: "CTA click",
2578
- category: "engagement",
2579
- outcomeRole: "engagement",
2580
- clientVisibility: "simple"
2581
- },
2582
- site_link_click: {
2583
- label: "Left for sibling site",
2584
- category: "page",
2585
- outcomeRole: "navigation",
2586
- clientVisibility: "detailed"
2587
- },
2588
- site_link_arrival: {
2589
- label: "Arrived from sibling site",
2590
- category: "page",
2591
- outcomeRole: "navigation",
2592
- clientVisibility: "simple"
2593
- }
2594
- };
2595
-
2596
2656
  // ../tracking-core/src/events/registry.ts
2597
2657
  var EVENT_REGISTRY = {
2598
2658
  // --- automatic triggers ---
@@ -2666,6 +2726,12 @@ var EVENT_REGISTRY = {
2666
2726
  metadataSchema: formSubmitMetadataSchema,
2667
2727
  configSchema: formSubmitConfigSchema
2668
2728
  },
2729
+ form_step: {
2730
+ kind: "manual",
2731
+ semantics: EVENT_SEMANTICS.form_step,
2732
+ metadataSchema: formStepMetadataSchema,
2733
+ configSchema: formStepConfigSchema
2734
+ },
2669
2735
  phone_click: {
2670
2736
  kind: "manual",
2671
2737
  semantics: EVENT_SEMANTICS.phone_click,
@@ -2692,9 +2758,14 @@ function createTypedClient(raw, registry, options = {}) {
2692
2758
  if (registry.manual?.form_submit) registerCapability("form_capture");
2693
2759
  return {
2694
2760
  trackEvent(eventType, metadata, opts) {
2761
+ const def = getEventDefinition(eventType);
2695
2762
  if (debug) {
2696
- const def = getEventDefinition(eventType);
2697
2763
  (0, import_mini2.parse)(def.metadataSchema, metadata);
2764
+ } else if (!(0, import_mini2.safeParse)(def.metadataSchema, metadata).success) {
2765
+ console.warn(
2766
+ `[AranovaTracking] trackEvent: metadata for "${eventType}" failed schema validation; event dropped`
2767
+ );
2768
+ return;
2698
2769
  }
2699
2770
  raw.trackEvent({
2700
2771
  eventType,
@@ -3069,8 +3140,14 @@ function attachFormStart(client, config) {
3069
3140
  return `index:${forms.indexOf(form)}`;
3070
3141
  }
3071
3142
  function onFocusIn(event) {
3072
- const target = event.target;
3073
- if (!(target instanceof HTMLElement)) return;
3143
+ startFrom(event.target);
3144
+ }
3145
+ function onPointerDown(event) {
3146
+ if (event.button !== 0) return;
3147
+ startFrom(event.target);
3148
+ }
3149
+ function startFrom(target) {
3150
+ if (!(target instanceof Element)) return;
3074
3151
  const form = target.closest(selector);
3075
3152
  if (!form || form.tagName !== "FORM") return;
3076
3153
  const key = getFormKey(form);
@@ -3109,11 +3186,13 @@ function attachFormStart(client, config) {
3109
3186
  history.replaceState = patchedReplaceState;
3110
3187
  window.addEventListener("popstate", resetIfPathChanged);
3111
3188
  document.addEventListener("focusin", onFocusIn);
3189
+ document.addEventListener("pointerdown", onPointerDown, { capture: true, passive: true });
3112
3190
  return () => {
3113
3191
  history.pushState = originalPushState;
3114
3192
  history.replaceState = originalReplaceState;
3115
3193
  window.removeEventListener("popstate", resetIfPathChanged);
3116
3194
  document.removeEventListener("focusin", onFocusIn);
3195
+ document.removeEventListener("pointerdown", onPointerDown, { capture: true });
3117
3196
  };
3118
3197
  }
3119
3198
 
@@ -3700,7 +3779,7 @@ function GoogleAdsTracking(props) {
3700
3779
  var import_react6 = require("react");
3701
3780
 
3702
3781
  // package.json
3703
- var version = "1.2.1";
3782
+ var version = "1.2.3";
3704
3783
 
3705
3784
  // ../tracking-core/src/phone-react.tsx
3706
3785
  var import_react5 = require("react");
@@ -3906,7 +3985,6 @@ function createTracking(options) {
3906
3985
  }
3907
3986
  } : detectorClient;
3908
3987
  detachers.push(attachAutoPageView(pageClient));
3909
- detachers.push(attachBfcacheRestore(pageClient));
3910
3988
  detachers.push(attachPageExit(detectorClient));
3911
3989
  const timeOnSite = triggers.automatic.time_on_site;
3912
3990
  if (timeOnSite) {