@aranova/tracking-react 0.13.0 → 0.14.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.
package/dist/index.mjs CHANGED
@@ -7,6 +7,13 @@ import { useCallback, useEffect, useState } from "react";
7
7
  // ../tracking-core/src/consent.ts
8
8
  var CONSENT_STATE_KEY = "consent_state";
9
9
  var CONSENT_TIMESTAMP_KEY = "consent_timestamp";
10
+ var grantedListeners = /* @__PURE__ */ new Set();
11
+ function onConsentGranted(listener) {
12
+ grantedListeners.add(listener);
13
+ return () => {
14
+ grantedListeners.delete(listener);
15
+ };
16
+ }
10
17
  function buildConsentPayload(state) {
11
18
  return {
12
19
  ad_storage: state,
@@ -35,6 +42,14 @@ function setConsentState(state) {
35
42
  window.gtag("consent", "update", buildConsentPayload(state));
36
43
  if (typeof window.fbq === "function")
37
44
  window.fbq("consent", state === "granted" ? "grant" : "revoke");
45
+ if (state === "granted") {
46
+ for (const listener of grantedListeners) {
47
+ try {
48
+ listener();
49
+ } catch {
50
+ }
51
+ }
52
+ }
38
53
  }
39
54
  function resetConsent() {
40
55
  if (typeof window === "undefined") return;
@@ -170,6 +185,24 @@ function ensureGtagFunction() {
170
185
  };
171
186
  return window.gtag;
172
187
  }
188
+ var SEND_TO_RE = /^AW-[A-Za-z0-9]+\/[A-Za-z0-9_-]+$/;
189
+ function isValidSendTo(sendTo) {
190
+ return SEND_TO_RE.test(sendTo);
191
+ }
192
+ function fireGtagConversion(input) {
193
+ if (typeof window === "undefined" || typeof window.gtag !== "function") return false;
194
+ if (!isValidSendTo(input.sendTo)) return false;
195
+ const params = { send_to: input.sendTo };
196
+ if (input.value != null) params.value = input.value;
197
+ if (input.currency) params.currency = input.currency;
198
+ if (input.transactionId) params.transaction_id = input.transactionId;
199
+ try {
200
+ window.gtag("event", "conversion", params);
201
+ return true;
202
+ } catch {
203
+ return false;
204
+ }
205
+ }
173
206
  function applyDefaultConsentState() {
174
207
  const gtag = ensureGtagFunction();
175
208
  gtag("consent", "default", {
@@ -376,6 +409,289 @@ function createTrackingEventCreatePayload(trackingParams, input, context) {
376
409
  };
377
410
  }
378
411
 
412
+ // ../tracking-core/src/resources/conversion-firing.ts
413
+ var DEDUP_PREFIX = "_aranova_conv_";
414
+ var MAX_PENDING = 100;
415
+ var pendingQueue = [];
416
+ function dedupKey(input) {
417
+ return `${DEDUP_PREFIX}${input.transactionId ?? ""}:${input.sendTo}`;
418
+ }
419
+ function alreadyFired(input) {
420
+ if (!input.transactionId || typeof window === "undefined") return false;
421
+ try {
422
+ return window.sessionStorage.getItem(dedupKey(input)) !== null;
423
+ } catch {
424
+ return false;
425
+ }
426
+ }
427
+ function markFired(input) {
428
+ if (!input.transactionId || typeof window === "undefined") return;
429
+ try {
430
+ window.sessionStorage.setItem(dedupKey(input), "1");
431
+ } catch {
432
+ }
433
+ }
434
+ function fireOnce(input) {
435
+ if (alreadyFired(input)) return;
436
+ if (fireGtagConversion(input)) markFired(input);
437
+ }
438
+ function fireConversionWithConsent(input) {
439
+ const state = getConsentState();
440
+ if (state === "denied") return;
441
+ if (state === "pending") {
442
+ if (pendingQueue.length >= MAX_PENDING) pendingQueue.shift();
443
+ pendingQueue.push(input);
444
+ return;
445
+ }
446
+ fireOnce(input);
447
+ }
448
+ function flushPendingConversions() {
449
+ if (getConsentState() !== "granted") return;
450
+ while (pendingQueue.length > 0) {
451
+ const input = pendingQueue.shift();
452
+ if (input) fireOnce(input);
453
+ }
454
+ }
455
+ if (typeof window !== "undefined") onConsentGranted(flushPendingConversions);
456
+
457
+ // ../tracking-core/src/resources/conversion-config.ts
458
+ function isStringMap(value) {
459
+ return typeof value === "object" && value !== null && Object.values(value).every((v) => typeof v === "string");
460
+ }
461
+ function parseFiring(value) {
462
+ if (!value || typeof value !== "object") return null;
463
+ const f = value;
464
+ if (typeof f.send_to !== "string") return null;
465
+ return {
466
+ send_to: f.send_to,
467
+ value_cents: typeof f.value_cents === "number" ? f.value_cents : null,
468
+ currency: typeof f.currency === "string" ? f.currency : null
469
+ };
470
+ }
471
+ function parseTrigger(value) {
472
+ if (!value || typeof value !== "object") return null;
473
+ const t = value;
474
+ if (typeof t.event_type !== "string") return null;
475
+ const spec = { event_type: t.event_type };
476
+ if (typeof t.threshold_percent === "number") spec.threshold_percent = t.threshold_percent;
477
+ if (typeof t.threshold_seconds === "number") spec.threshold_seconds = t.threshold_seconds;
478
+ if (typeof t.page_threshold === "number") spec.page_threshold = t.page_threshold;
479
+ if (typeof t.page_name === "string") spec.page_name = t.page_name;
480
+ return spec;
481
+ }
482
+ function parseConversionConfig(raw) {
483
+ if (!raw || typeof raw !== "object") return null;
484
+ const obj = raw;
485
+ const servicesRaw = Array.isArray(obj.services) ? obj.services : [];
486
+ const services = servicesRaw.flatMap((entry) => {
487
+ if (!entry || typeof entry !== "object") return [];
488
+ const s = entry;
489
+ if (typeof s.key !== "string") return [];
490
+ return [
491
+ {
492
+ key: s.key,
493
+ label: typeof s.label === "string" ? s.label : void 0,
494
+ firing: parseFiring(s.firing)
495
+ }
496
+ ];
497
+ });
498
+ const goalsRaw = Array.isArray(obj.goals) ? obj.goals : null;
499
+ const goals = goalsRaw ? goalsRaw.flatMap((entry) => {
500
+ if (!entry || typeof entry !== "object") return [];
501
+ const g = entry;
502
+ if (typeof g.key !== "string") return [];
503
+ return [
504
+ {
505
+ key: g.key,
506
+ label: typeof g.label === "string" ? g.label : void 0,
507
+ kind: g.kind === "event" ? "event" : "sale",
508
+ trigger: parseTrigger(g.trigger),
509
+ firing: parseFiring(g.firing)
510
+ }
511
+ ];
512
+ }) : services.map((s) => ({
513
+ key: s.key,
514
+ label: s.label,
515
+ kind: "sale",
516
+ trigger: null,
517
+ firing: s.firing
518
+ }));
519
+ return {
520
+ schema_version: typeof obj.schema_version === "number" ? obj.schema_version : 1,
521
+ config_version: typeof obj.config_version === "number" ? obj.config_version : 0,
522
+ business_id: typeof obj.business_id === "string" ? obj.business_id : void 0,
523
+ customer_id: typeof obj.customer_id === "string" ? obj.customer_id : null,
524
+ environment: typeof obj.environment === "string" ? obj.environment : void 0,
525
+ gtag_ids: isStringMap(obj.gtag_ids) ? obj.gtag_ids : {},
526
+ meta_pixel_ids: isStringMap(obj.meta_pixel_ids) ? obj.meta_pixel_ids : {},
527
+ services,
528
+ goals
529
+ };
530
+ }
531
+ var CACHE_PREFIX = "_aranova_cfg_";
532
+ function cacheKey(url) {
533
+ return `${CACHE_PREFIX}${url}`;
534
+ }
535
+ function readCache(url) {
536
+ if (typeof window === "undefined") return null;
537
+ try {
538
+ const raw = window.sessionStorage.getItem(cacheKey(url));
539
+ if (!raw) return null;
540
+ const parsed = JSON.parse(raw);
541
+ const config = parseConversionConfig(parsed.config);
542
+ if (!config) return null;
543
+ return {
544
+ etag: typeof parsed.etag === "string" ? parsed.etag : null,
545
+ config
546
+ };
547
+ } catch {
548
+ return null;
549
+ }
550
+ }
551
+ function writeCache(url, entry) {
552
+ if (typeof window === "undefined") return;
553
+ try {
554
+ window.sessionStorage.setItem(cacheKey(url), JSON.stringify(entry));
555
+ } catch {
556
+ }
557
+ }
558
+ function resolveConversionConfig(options) {
559
+ const cached = readCache(options.cdnUrl);
560
+ let current = cached?.config ?? options.baked ?? null;
561
+ let etag = cached?.etag ?? null;
562
+ const goalsByKey = /* @__PURE__ */ new Map();
563
+ function rebuildIndex() {
564
+ goalsByKey.clear();
565
+ for (const goal of current?.goals ?? []) {
566
+ goalsByKey.set(goal.key, goal);
567
+ }
568
+ }
569
+ function adopt(next, nextEtag) {
570
+ if (!next) return;
571
+ if (current && next.config_version <= current.config_version) return;
572
+ current = next;
573
+ etag = nextEtag;
574
+ rebuildIndex();
575
+ writeCache(options.cdnUrl, { etag, config: next });
576
+ }
577
+ async function revalidate() {
578
+ if (typeof window === "undefined") return;
579
+ try {
580
+ const doFetch = options.fetchImpl ?? globalThis.fetch;
581
+ if (!doFetch) return;
582
+ const headers = {};
583
+ if (etag) headers["If-None-Match"] = etag;
584
+ const response = await doFetch(options.cdnUrl, {
585
+ method: "GET",
586
+ headers
587
+ });
588
+ if (response.status === 304 || !response.ok) return;
589
+ adopt(parseConversionConfig(await response.json()), response.headers.get("ETag"));
590
+ } catch {
591
+ }
592
+ }
593
+ rebuildIndex();
594
+ void revalidate();
595
+ return {
596
+ getFiring: (key) => goalsByKey.get(key)?.firing ?? null,
597
+ getGoal: (key) => goalsByKey.get(key) ?? null,
598
+ listGoals: () => [...goalsByKey.values()],
599
+ current: () => current,
600
+ revalidate
601
+ };
602
+ }
603
+
604
+ // ../tracking-core/src/resources/sales/money.ts
605
+ var MINOR_UNIT_EXPONENT = {
606
+ USD: 2,
607
+ CAD: 2
608
+ };
609
+ function exponentFor(currency) {
610
+ return MINOR_UNIT_EXPONENT[currency] ?? 2;
611
+ }
612
+ function toMinor(amount, currency) {
613
+ return Math.round(amount * 10 ** exponentFor(currency));
614
+ }
615
+ function fromMinor(cents, currency) {
616
+ return cents / 10 ** exponentFor(currency);
617
+ }
618
+ function formatMoney(cents, currency, locale) {
619
+ return new Intl.NumberFormat(locale, { style: "currency", currency }).format(
620
+ fromMinor(cents, currency)
621
+ );
622
+ }
623
+ function formatDateInTz(iso, timeZone, opts, locale) {
624
+ const date = new Date(iso);
625
+ if (Number.isNaN(date.getTime())) return iso;
626
+ return new Intl.DateTimeFormat(locale, {
627
+ year: "numeric",
628
+ month: "short",
629
+ day: "2-digit",
630
+ hour: "2-digit",
631
+ minute: "2-digit",
632
+ ...opts,
633
+ timeZone
634
+ }).format(date);
635
+ }
636
+
637
+ // ../tracking-core/src/resources/conversion-autofire.ts
638
+ function thresholdMet(goal, eventType, metadata) {
639
+ const t = goal.trigger;
640
+ if (!t || t.event_type !== eventType) return false;
641
+ switch (eventType) {
642
+ case "scroll_depth":
643
+ return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
644
+ case "time_on_site":
645
+ return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
646
+ case "multi_page_session":
647
+ return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
648
+ case "specific_page_visit":
649
+ return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
650
+ case "page_view":
651
+ case "form_start":
652
+ return true;
653
+ // no threshold — fire whenever the detector emits
654
+ default:
655
+ return false;
656
+ }
657
+ }
658
+ function currentPath() {
659
+ return typeof window === "undefined" ? "" : window.location.pathname;
660
+ }
661
+ function createConversionAutoFire(store) {
662
+ return {
663
+ onAutomaticEvent(eventType, metadata) {
664
+ for (const goal of store.listGoals()) {
665
+ if (goal.kind !== "event" || !goal.firing) continue;
666
+ if (!thresholdMet(goal, eventType, metadata)) continue;
667
+ const firing = goal.firing;
668
+ const cents = firing.value_cents ?? null;
669
+ const currency = firing.currency ?? null;
670
+ fireConversionWithConsent({
671
+ sendTo: firing.send_to,
672
+ value: cents != null && currency ? fromMinor(cents, currency) : null,
673
+ currency,
674
+ // Page-scoped txn id → fire once per (goal, path) per session; engagement conversions
675
+ // shouldn't re-fire as the visitor scrolls back and forth or re-enters a page.
676
+ transactionId: `auto:${goal.key}:${currentPath()}`
677
+ });
678
+ }
679
+ }
680
+ };
681
+ }
682
+ function withConversionAutoFire(client, autoFire) {
683
+ return {
684
+ ...client,
685
+ trackEvent: (input) => {
686
+ client.trackEvent(input);
687
+ try {
688
+ autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {});
689
+ } catch {
690
+ }
691
+ }
692
+ };
693
+ }
694
+
379
695
  // ../tracking-core/src/session.ts
380
696
  var VISITOR_STORAGE_KEY = "aranova_tracking_visitor";
381
697
  var SESSION_STORAGE_KEY = "aranova_tracking_session";
@@ -1195,7 +1511,7 @@ function attachScrollDepth(client, config) {
1195
1511
  }
1196
1512
  const thresholds = new Set(config.thresholds);
1197
1513
  let firedForPath = /* @__PURE__ */ new Set();
1198
- let currentPath = window.location.pathname;
1514
+ let currentPath2 = window.location.pathname;
1199
1515
  let rafId = null;
1200
1516
  function getScrollPercent() {
1201
1517
  const doc = document.documentElement;
@@ -1214,7 +1530,7 @@ function attachScrollDepth(client, config) {
1214
1530
  eventType: "scroll_depth",
1215
1531
  metadata: {
1216
1532
  depth_percent: threshold,
1217
- page: { path: currentPath }
1533
+ page: { path: currentPath2 }
1218
1534
  },
1219
1535
  pageUrl: window.location.href,
1220
1536
  occurredAt: null
@@ -1231,8 +1547,8 @@ function attachScrollDepth(client, config) {
1231
1547
  }
1232
1548
  function resetIfPathChanged() {
1233
1549
  const newPath = window.location.pathname;
1234
- if (newPath === currentPath) return;
1235
- currentPath = newPath;
1550
+ if (newPath === currentPath2) return;
1551
+ currentPath2 = newPath;
1236
1552
  firedForPath = /* @__PURE__ */ new Set();
1237
1553
  setTimeout(checkThresholds, 0);
1238
1554
  }
@@ -1308,13 +1624,13 @@ function attachMultiPageSession(client, config) {
1308
1624
  return storage.getItem(FIRED_KEY) === "1";
1309
1625
  }
1310
1626
  function check() {
1311
- const currentPath = window.location.pathname;
1312
- if (currentPath === lastCheckedPath) return;
1313
- lastCheckedPath = currentPath;
1627
+ const currentPath2 = window.location.pathname;
1628
+ if (currentPath2 === lastCheckedPath) return;
1629
+ lastCheckedPath = currentPath2;
1314
1630
  resetIfSessionChanged();
1315
1631
  if (hasFired()) return;
1316
1632
  const paths = getDistinctPaths();
1317
- paths.add(currentPath);
1633
+ paths.add(currentPath2);
1318
1634
  saveDistinctPaths(paths);
1319
1635
  if (paths.size >= pageThreshold) {
1320
1636
  storage.setItem(FIRED_KEY, "1");
@@ -1358,7 +1674,7 @@ function attachFormStart(client, config) {
1358
1674
  }
1359
1675
  const selector = config.selector ?? "form";
1360
1676
  let firedForms = /* @__PURE__ */ new Set();
1361
- let currentPath = window.location.pathname;
1677
+ let currentPath2 = window.location.pathname;
1362
1678
  function getFormKey(form) {
1363
1679
  if (form.id) return `id:${form.id}`;
1364
1680
  const explicitAction = form.getAttribute("action");
@@ -1389,8 +1705,8 @@ function attachFormStart(client, config) {
1389
1705
  }
1390
1706
  function resetIfPathChanged() {
1391
1707
  const newPath = window.location.pathname;
1392
- if (newPath === currentPath) return;
1393
- currentPath = newPath;
1708
+ if (newPath === currentPath2) return;
1709
+ currentPath2 = newPath;
1394
1710
  firedForms = /* @__PURE__ */ new Set();
1395
1711
  }
1396
1712
  const originalPushState = history.pushState.bind(history);
@@ -1469,21 +1785,64 @@ async function salesRequest(config, method, path, body) {
1469
1785
  }
1470
1786
 
1471
1787
  // ../tracking-core/src/resources/sales/client.ts
1788
+ function fireRecordedConversions(firing, input, recorded, sale, currency) {
1789
+ if (!firing) return;
1790
+ const txnBase = input.external_id ?? sale.id;
1791
+ for (const item of recorded) {
1792
+ if (!item.service) continue;
1793
+ const config = firing.getFiring(item.service);
1794
+ if (!config) continue;
1795
+ const cents = item.amount_cents ?? config.value_cents ?? null;
1796
+ fireConversionWithConsent({
1797
+ sendTo: config.send_to,
1798
+ value: cents != null ? fromMinor(cents, currency) : null,
1799
+ currency: config.currency ?? currency,
1800
+ transactionId: `${txnBase}:${item.service}`
1801
+ });
1802
+ }
1803
+ }
1472
1804
  function createSalesClient(config) {
1473
- return {
1474
- async record(input) {
1475
- const currency = input.currency ?? config.defaultCurrency;
1476
- if (!currency) {
1477
- throw new Error(
1478
- "record: `currency` is required (pass it on the sale or set config.defaultCurrency)"
1479
- );
1805
+ async function record(input) {
1806
+ const currency = input.currency ?? config.defaultCurrency;
1807
+ if (!currency) {
1808
+ throw new Error(
1809
+ "record: `currency` is required (pass it on the sale or set config.defaultCurrency)"
1810
+ );
1811
+ }
1812
+ const body = {
1813
+ ...input,
1814
+ currency,
1815
+ occurred_at: input.occurred_at ?? (/* @__PURE__ */ new Date()).toISOString()
1816
+ };
1817
+ const sale = await salesRequest(config, "POST", "/sales", body);
1818
+ const recorded = input.services?.length ? input.services.map((s) => ({
1819
+ service: s.service,
1820
+ amount_cents: s.amount_cents
1821
+ })) : [
1822
+ {
1823
+ service: input.service,
1824
+ amount_cents: input.amount_total_cents ?? null
1480
1825
  }
1481
- const body = {
1482
- ...input,
1826
+ ];
1827
+ fireRecordedConversions(config.firing, input, recorded, sale, currency);
1828
+ return sale;
1829
+ }
1830
+ return {
1831
+ record,
1832
+ // recordSale is the intent-revealing alias — same behavior, clearer call site.
1833
+ recordSale: record,
1834
+ trackConversion(key, options) {
1835
+ const firing = config.firing?.getFiring(key);
1836
+ if (!firing) return;
1837
+ const currency = firing.currency ?? options?.currency ?? config.defaultCurrency ?? null;
1838
+ const cents = firing.value_cents ?? null;
1839
+ const value = options?.value ?? (cents != null && currency ? fromMinor(cents, currency) : null);
1840
+ fireConversionWithConsent({
1841
+ sendTo: firing.send_to,
1842
+ value,
1483
1843
  currency,
1484
- occurred_at: input.occurred_at ?? (/* @__PURE__ */ new Date()).toISOString()
1485
- };
1486
- return salesRequest(config, "POST", "/sales", body);
1844
+ transactionId: options?.transactionId ?? null
1845
+ });
1487
1846
  },
1488
1847
  async list(query) {
1489
1848
  const { cursor, limit, sort, order, want_total, ...filters } = query ?? {};
@@ -1577,39 +1936,6 @@ function createSalesClient(config) {
1577
1936
  };
1578
1937
  }
1579
1938
 
1580
- // ../tracking-core/src/resources/sales/money.ts
1581
- var MINOR_UNIT_EXPONENT = {
1582
- USD: 2,
1583
- CAD: 2
1584
- };
1585
- function exponentFor(currency) {
1586
- return MINOR_UNIT_EXPONENT[currency] ?? 2;
1587
- }
1588
- function toMinor(amount, currency) {
1589
- return Math.round(amount * 10 ** exponentFor(currency));
1590
- }
1591
- function fromMinor(cents, currency) {
1592
- return cents / 10 ** exponentFor(currency);
1593
- }
1594
- function formatMoney(cents, currency, locale) {
1595
- return new Intl.NumberFormat(locale, { style: "currency", currency }).format(
1596
- fromMinor(cents, currency)
1597
- );
1598
- }
1599
- function formatDateInTz(iso, timeZone, opts, locale) {
1600
- const date = new Date(iso);
1601
- if (Number.isNaN(date.getTime())) return iso;
1602
- return new Intl.DateTimeFormat(locale, {
1603
- year: "numeric",
1604
- month: "short",
1605
- day: "2-digit",
1606
- hour: "2-digit",
1607
- minute: "2-digit",
1608
- ...opts,
1609
- timeZone
1610
- }).format(date);
1611
- }
1612
-
1613
1939
  // ../tracking-core/src/resources/sales/schema.ts
1614
1940
  import { z as z11 } from "zod";
1615
1941
  var SUPPORTED_CURRENCIES = ["USD", "CAD"];
@@ -2057,7 +2383,7 @@ function GoogleAdsTracking(props) {
2057
2383
  import { createContext as createContext2, useContext as useContext2, useEffect as useEffect5, useMemo as useMemo4 } from "react";
2058
2384
 
2059
2385
  // package.json
2060
- var version = "0.13.0";
2386
+ var version = "0.14.0";
2061
2387
 
2062
2388
  // ../tracking-core/src/phone-react.tsx
2063
2389
  import {
@@ -2163,7 +2489,7 @@ var NOOP_CLIENT = {
2163
2489
  getVisitorId: () => ""
2164
2490
  };
2165
2491
  function createTracking(options) {
2166
- const { apiKey, endpoint, triggers, environment, debug, phone } = options;
2492
+ const { apiKey, endpoint, triggers, environment, debug, phone, conversionConfig } = options;
2167
2493
  if (!apiKey || !endpoint) {
2168
2494
  if (apiKey || endpoint) {
2169
2495
  console.warn(
@@ -2238,27 +2564,32 @@ function createTracking(options) {
2238
2564
  activeGtagIds: resolvedGtagIds,
2239
2565
  debug
2240
2566
  });
2241
- detachers.push(attachAutoPageView(rawClient));
2242
- detachers.push(attachBfcacheRestore(rawClient));
2567
+ const conversionStore = conversionConfig ? resolveConversionConfig({
2568
+ cdnUrl: conversionConfig.cdnUrl,
2569
+ baked: conversionConfig.baked
2570
+ }) : null;
2571
+ const detectorClient = conversionStore ? withConversionAutoFire(rawClient, createConversionAutoFire(conversionStore)) : rawClient;
2572
+ detachers.push(attachAutoPageView(detectorClient));
2573
+ detachers.push(attachBfcacheRestore(detectorClient));
2243
2574
  const timeOnSite = triggers.automatic.time_on_site;
2244
2575
  if (timeOnSite) {
2245
- detachers.push(attachTimeOnSite(rawClient, timeOnSite));
2576
+ detachers.push(attachTimeOnSite(detectorClient, timeOnSite));
2246
2577
  }
2247
2578
  const specificPageVisit = triggers.automatic.specific_page_visit;
2248
2579
  if (specificPageVisit) {
2249
- detachers.push(attachSpecificPageVisit(rawClient, specificPageVisit));
2580
+ detachers.push(attachSpecificPageVisit(detectorClient, specificPageVisit));
2250
2581
  }
2251
2582
  const scrollDepth = triggers.automatic.scroll_depth;
2252
2583
  if (scrollDepth) {
2253
- detachers.push(attachScrollDepth(rawClient, scrollDepth));
2584
+ detachers.push(attachScrollDepth(detectorClient, scrollDepth));
2254
2585
  }
2255
2586
  const multiPageSession = triggers.automatic.multi_page_session;
2256
2587
  if (multiPageSession) {
2257
- detachers.push(attachMultiPageSession(rawClient, multiPageSession));
2588
+ detachers.push(attachMultiPageSession(detectorClient, multiPageSession));
2258
2589
  }
2259
2590
  const formStart = triggers.automatic.form_start;
2260
2591
  if (formStart) {
2261
- detachers.push(attachFormStart(rawClient, formStart));
2592
+ detachers.push(attachFormStart(detectorClient, formStart));
2262
2593
  }
2263
2594
  return () => {
2264
2595
  for (let i = detachers.length - 1; i >= 0; i--) {
@@ -2306,6 +2637,7 @@ export {
2306
2637
  parsePhone,
2307
2638
  phoneField,
2308
2639
  resetConsent,
2640
+ resolveConversionConfig,
2309
2641
  saleCreateSchema,
2310
2642
  saleItemSchema,
2311
2643
  saleServiceSchema,