@aranova/tracking-react 0.27.0 → 1.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 (35) hide show
  1. package/dist/client.d.mts +11 -4
  2. package/dist/client.d.ts +11 -4
  3. package/dist/client.js +620 -350
  4. package/dist/client.js.map +1 -1
  5. package/dist/client.mjs +610 -350
  6. package/dist/client.mjs.map +1 -1
  7. package/dist/index.d.mts +7 -6
  8. package/dist/index.d.ts +7 -6
  9. package/dist/index.js +339 -393
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs +328 -393
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/ingest-typed-MBuMe9Pn.d.ts +883 -0
  14. package/dist/ingest-typed-UA13xTfI.d.mts +883 -0
  15. package/dist/{phone-utils-BVzSNBf1.d.mts → phone-utils-C0ds6cqZ.d.mts} +24 -78
  16. package/dist/{phone-utils-BVzSNBf1.d.ts → phone-utils-C0ds6cqZ.d.ts} +24 -78
  17. package/dist/phone.d.mts +2 -2
  18. package/dist/phone.d.ts +2 -2
  19. package/dist/phone.js +0 -464
  20. package/dist/phone.js.map +1 -1
  21. package/dist/phone.mjs +0 -464
  22. package/dist/phone.mjs.map +1 -1
  23. package/dist/{sales-D4TB9gRS.d.ts → sales-BuKD_bdo.d.mts} +90 -329
  24. package/dist/{sales-cYjB07y8.d.mts → sales-C3O_xxZ_.d.ts} +90 -329
  25. package/dist/sales.d.mts +3 -3
  26. package/dist/sales.d.ts +3 -3
  27. package/dist/sales.js +270 -127
  28. package/dist/sales.js.map +1 -1
  29. package/dist/sales.mjs +259 -127
  30. package/dist/sales.mjs.map +1 -1
  31. package/dist/{tracking-config-runtime-D7prdTE1.d.mts → tracking-config-runtime-C6H7ofmo.d.mts} +6 -0
  32. package/dist/{tracking-config-runtime-D7prdTE1.d.ts → tracking-config-runtime-C6H7ofmo.d.ts} +6 -0
  33. package/package.json +2 -2
  34. package/dist/ingest-typed-BxLFlZ7N.d.mts +0 -1371
  35. package/dist/ingest-typed-ByQVRMvP.d.ts +0 -1371
package/dist/index.mjs CHANGED
@@ -60,7 +60,7 @@ function normalizeEmail(raw) {
60
60
  return EMAIL_SHAPE.test(cleaned) ? cleaned : null;
61
61
  }
62
62
  function stashUserData(data, country) {
63
- const email = normalizeEmail(data.email);
63
+ const email3 = normalizeEmail(data.email);
64
64
  let phoneNumber = null;
65
65
  if (typeof data.phone === "string" && data.phone.length > 0) {
66
66
  try {
@@ -70,7 +70,7 @@ function stashUserData(data, country) {
70
70
  }
71
71
  }
72
72
  stash = {
73
- email: email ?? stash.email,
73
+ email: email3 ?? stash.email,
74
74
  phoneNumber: phoneNumber ?? stash.phoneNumber
75
75
  };
76
76
  }
@@ -79,11 +79,11 @@ function clearStashedUserData() {
79
79
  }
80
80
  function applyUserDataForConversion(explicit, country) {
81
81
  if (typeof window === "undefined" || typeof window.gtag !== "function") return false;
82
- let email = stash.email;
82
+ let email3 = stash.email;
83
83
  let phoneNumber = stash.phoneNumber;
84
84
  if (explicit) {
85
85
  const normalizedEmail = normalizeEmail(explicit.email);
86
- if (normalizedEmail) email = normalizedEmail;
86
+ if (normalizedEmail) email3 = normalizedEmail;
87
87
  if (typeof explicit.phone === "string" && explicit.phone.length > 0) {
88
88
  try {
89
89
  phoneNumber = toE164(explicit.phone, country) ?? phoneNumber;
@@ -91,10 +91,10 @@ function applyUserDataForConversion(explicit, country) {
91
91
  }
92
92
  }
93
93
  }
94
- if (email === null && phoneNumber === null) return false;
94
+ if (email3 === null && phoneNumber === null) return false;
95
95
  try {
96
96
  window.gtag("set", "user_data", {
97
- ...email !== null ? { email } : {},
97
+ ...email3 !== null ? { email: email3 } : {},
98
98
  ...phoneNumber !== null ? { phone_number: phoneNumber } : {}
99
99
  });
100
100
  return true;
@@ -226,6 +226,7 @@ var TRACKING_CAPABILITIES = [
226
226
  "consent_controls",
227
227
  "conversion_goals_auto",
228
228
  "conversion_goals_manual",
229
+ "cross_site_linker",
229
230
  "cta_click_capture",
230
231
  "form_capture",
231
232
  "phone_click_capture",
@@ -252,6 +253,9 @@ function readDomMarkers() {
252
253
  return found;
253
254
  }
254
255
 
256
+ // ../tracking-core/src/cross-site-link.ts
257
+ import * as z from "zod/mini";
258
+
255
259
  // ../tracking-core/src/tracking.ts
256
260
  var TRACKING_COOKIE_MAX_AGE_SECONDS = 7776e3;
257
261
  var TRACKING_PARAM_KEYS = [
@@ -450,10 +454,10 @@ function readStoredRecord() {
450
454
  return null;
451
455
  }
452
456
  }
453
- function writeRecord(record) {
454
- memoryRecord = record;
457
+ function writeRecord(record3) {
458
+ memoryRecord = record3;
455
459
  try {
456
- window.localStorage.setItem(LANDING_STORAGE_KEY, JSON.stringify(record));
460
+ window.localStorage.setItem(LANDING_STORAGE_KEY, JSON.stringify(record3));
457
461
  } catch {
458
462
  }
459
463
  }
@@ -475,9 +479,9 @@ function getOrCaptureLandingParams(sessionId, url) {
475
479
  if (memoryRecord && memoryRecord.session_id === sessionId) {
476
480
  return memoryRecord.params;
477
481
  }
478
- const record = { session_id: sessionId, params: captureFromUrl(url) };
479
- writeRecord(record);
480
- return record.params;
482
+ const record3 = { session_id: sessionId, params: captureFromUrl(url) };
483
+ writeRecord(record3);
484
+ return record3.params;
481
485
  }
482
486
  function buildLandingPayloadFields(sessionId, override) {
483
487
  const params = override ?? (typeof window === "undefined" ? null : getOrCaptureLandingParams(sessionId));
@@ -496,6 +500,43 @@ function buildLandingPayloadFields(sessionId, override) {
496
500
  };
497
501
  }
498
502
 
503
+ // ../tracking-core/src/cross-site-link.ts
504
+ var LINK_PARAM = "_arv";
505
+ var LINK_TOKEN_TTL_MS = 5 * 60 * 1e3;
506
+ var FUTURE_SKEW_MS = 60 * 1e3;
507
+ var CARRIED_KEYS = {
508
+ g: "gclid",
509
+ w: "wbraid",
510
+ gb: "gbraid",
511
+ f: "fbclid",
512
+ y: "ylpcid"
513
+ };
514
+ var CARRIED_ENTRIES = Object.entries(CARRIED_KEYS);
515
+ var identifier = z.string().check(z.minLength(1), z.maxLength(128));
516
+ var optionalIdentifier = z.optional(identifier);
517
+ var linkTokenSchema = z.object({
518
+ v: identifier,
519
+ s: identifier,
520
+ // Epoch ms in base36.
521
+ t: z.string().check(z.regex(/^[0-9a-z]{1,12}$/)),
522
+ g: optionalIdentifier,
523
+ w: optionalIdentifier,
524
+ gb: optionalIdentifier,
525
+ f: optionalIdentifier,
526
+ fc: optionalIdentifier,
527
+ y: optionalIdentifier
528
+ });
529
+ function stripLinkParam(url) {
530
+ try {
531
+ const parsed = new URL(url, typeof window === "undefined" ? void 0 : window.location.href);
532
+ if (!parsed.searchParams.has(LINK_PARAM)) return url;
533
+ parsed.searchParams.delete(LINK_PARAM);
534
+ return parsed.href;
535
+ } catch {
536
+ return url;
537
+ }
538
+ }
539
+
499
540
  // ../tracking-core/src/payloads.ts
500
541
  function createTrackingClientContext(surface, input = {}) {
501
542
  return {
@@ -535,6 +576,7 @@ function createTrackingSessionUpsertPayload(trackingParams, input, context) {
535
576
  };
536
577
  }
537
578
  function createTrackingEventCreatePayload(trackingParams, input, context) {
579
+ const pageUrl = input.pageUrl ?? (typeof window === "undefined" ? null : window.location.href);
538
580
  return {
539
581
  session_id: input.sessionId,
540
582
  event_type: input.eventType,
@@ -545,7 +587,7 @@ function createTrackingEventCreatePayload(trackingParams, input, context) {
545
587
  fbclid: trackingParams.fbclid,
546
588
  fbc: getFbcCookie(),
547
589
  fbp: getFbpCookie(),
548
- page_url: input.pageUrl ?? (typeof window === "undefined" ? null : window.location.href),
590
+ page_url: pageUrl === null ? null : stripLinkParam(pageUrl),
549
591
  metadata: input.metadata ?? null,
550
592
  context
551
593
  };
@@ -657,7 +699,8 @@ function parseConversionConfig(raw) {
657
699
  gtag_ids: isStringMap(obj.gtag_ids) ? obj.gtag_ids : {},
658
700
  meta_pixel_ids: isStringMap(obj.meta_pixel_ids) ? obj.meta_pixel_ids : {},
659
701
  services,
660
- goals
702
+ goals,
703
+ linked_hostnames: Array.isArray(obj.linked_hostnames) ? obj.linked_hostnames.filter((h) => typeof h === "string" && h.length > 0) : []
661
704
  };
662
705
  }
663
706
  var CACHE_PREFIX = "_aranova_cfg_";
@@ -741,6 +784,7 @@ function resolveConversionConfig(options) {
741
784
  getFiring: (key) => goalsByKey.get(key)?.firing ?? null,
742
785
  getGoal: (key) => goalsByKey.get(key) ?? null,
743
786
  listGoals: () => [...goalsByKey.values()],
787
+ linkedHostnames: () => current?.linked_hostnames ?? [],
744
788
  current: () => current,
745
789
  isReady: () => current !== null,
746
790
  onResolve: (listener) => {
@@ -854,9 +898,9 @@ function automaticThresholdMet(goal, eventType, metadata) {
854
898
  }
855
899
 
856
900
  // ../tracking-core/src/resources/intl/date.ts
857
- function formatDateInTz(iso, timeZone, opts, locale) {
858
- const date = new Date(iso);
859
- if (Number.isNaN(date.getTime())) return iso;
901
+ function formatDateInTz(iso3, timeZone, opts, locale) {
902
+ const date = new Date(iso3);
903
+ if (Number.isNaN(date.getTime())) return iso3;
860
904
  return new Intl.DateTimeFormat(locale, {
861
905
  year: "numeric",
862
906
  month: "short",
@@ -948,7 +992,7 @@ function validateConfig(config, ref) {
948
992
  function pageViewSnapshot() {
949
993
  if (typeof window === "undefined" || typeof document === "undefined") return null;
950
994
  return {
951
- href: window.location.href,
995
+ href: stripLinkParam(window.location.href),
952
996
  title: document.title || null,
953
997
  referrer: document.referrer || null
954
998
  };
@@ -1099,6 +1143,10 @@ var TrackingConfigRuntime = class {
1099
1143
  listGoals() {
1100
1144
  return this.current?.goals ?? [];
1101
1145
  }
1146
+ /** Sibling hostnames for the linker — read from the cached object even while unconfirmed. */
1147
+ linkedHostnames() {
1148
+ return this.current?.linked_hostnames ?? [];
1149
+ }
1102
1150
  async revalidateNow() {
1103
1151
  try {
1104
1152
  const headers = {};
@@ -1268,29 +1316,6 @@ function getTrackingConfigRuntime(ref, fetchImpl) {
1268
1316
  return runtime;
1269
1317
  }
1270
1318
 
1271
- // ../tracking-core/src/session.ts
1272
- var SESSION_IDLE_MS = 30 * 60 * 1e3;
1273
-
1274
- // ../tracking-core/src/events/page-view.ts
1275
- import { z } from "zod";
1276
- var pageViewMetadataSchema = z.object({
1277
- page: z.object({
1278
- title: z.string().nullable(),
1279
- path: z.string(),
1280
- search: z.string(),
1281
- hash: z.string()
1282
- }).strict(),
1283
- referrer: z.string().nullable(),
1284
- // `.nullable().optional()` — absent (undefined) OR explicit null OR a
1285
- // real viewport object. Mirrors Pydantic's `_Viewport | None = None`
1286
- // on the backend side so the drift test stays clean.
1287
- viewport: z.object({
1288
- w: z.number(),
1289
- h: z.number()
1290
- }).strict().nullable().optional()
1291
- }).strict();
1292
- var pageViewConfigSchema = z.object({}).strict();
1293
-
1294
1319
  // ../tracking-core/src/ingest.ts
1295
1320
  var API_KEY_HEADER = "X-Aranova-Api-Key";
1296
1321
  var SDK_VERSION_HEADER = "X-Aranova-Sdk-Version";
@@ -1298,187 +1323,6 @@ var SDK_PACKAGE_HEADER = "X-Aranova-Sdk-Package";
1298
1323
  var SDK_SURFACE_HEADER = "X-Aranova-Sdk-Surface";
1299
1324
  var SDK_ENVIRONMENT_HEADER = "X-Aranova-Sdk-Environment";
1300
1325
 
1301
- // ../tracking-core/src/events/cta-click.ts
1302
- import { z as z2 } from "zod";
1303
- var ctaClickMetadataSchema = z2.object({
1304
- cta_name: z2.string(),
1305
- page: z2.object({
1306
- path: z2.string()
1307
- }).strict(),
1308
- section: z2.string().nullable().optional(),
1309
- destination_url: z2.string().nullable().optional(),
1310
- // Set by auto-capture (and available to manual callers): the link target
1311
- // and a short element descriptor (tag#id) for tying clicks to specific UI.
1312
- href: z2.string().nullable().optional(),
1313
- element: z2.string().nullable().optional()
1314
- }).strict();
1315
- var ctaClickConfigSchema = z2.object({
1316
- autoCapture: z2.object({
1317
- selector: z2.string().optional()
1318
- }).strict().optional()
1319
- }).strict();
1320
-
1321
- // ../tracking-core/src/events/sdk-heartbeat.ts
1322
- import { z as z3 } from "zod";
1323
- var sdkHeartbeatTriggersSchema = z3.object({
1324
- automatic: z3.array(z3.string()),
1325
- manual: z3.array(z3.string())
1326
- }).strict();
1327
- var sdkHeartbeatMetadataSchema = z3.object({
1328
- sdk_version: z3.string(),
1329
- package_name: z3.string().nullable(),
1330
- surface: z3.enum(["next", "react", "script"]),
1331
- triggers: sdkHeartbeatTriggersSchema,
1332
- trigger_config: z3.record(z3.string(), z3.record(z3.string(), z3.unknown())).nullable().optional(),
1333
- configured_gtag_ids: z3.record(z3.string(), z3.string()).nullable().optional(),
1334
- // Site whose config object the SDK resolves; null on a legacy business ref.
1335
- config_site_id: z3.string().uuid().nullable().optional()
1336
- }).strict();
1337
- var sdkHeartbeatConfigSchema = z3.object({}).strict();
1338
-
1339
- // ../tracking-core/src/events/form-start.ts
1340
- import { z as z4 } from "zod";
1341
- var formStartMetadataSchema = z4.object({
1342
- form: z4.object({
1343
- id: z4.string(),
1344
- action: z4.string().nullable()
1345
- }).strict(),
1346
- page: z4.object({
1347
- path: z4.string()
1348
- }).strict()
1349
- }).strict();
1350
- var formStartConfigSchema = z4.object({
1351
- selector: z4.string().optional()
1352
- }).strict();
1353
-
1354
- // ../tracking-core/src/events/form-submit.ts
1355
- import { z as z5 } from "zod";
1356
- var jsonValueSchema = z5.lazy(
1357
- () => z5.union([
1358
- z5.string(),
1359
- z5.number().finite(),
1360
- z5.boolean(),
1361
- z5.null(),
1362
- z5.array(jsonValueSchema),
1363
- z5.record(jsonValueSchema)
1364
- ])
1365
- );
1366
- var formSubmitMetadataSchema = z5.object({
1367
- form: z5.object({
1368
- id: z5.string(),
1369
- action: z5.string().nullable(),
1370
- fields: z5.array(
1371
- z5.object({
1372
- name: z5.string(),
1373
- type: z5.string(),
1374
- label: z5.string().nullable(),
1375
- value: jsonValueSchema
1376
- }).strict()
1377
- ).optional()
1378
- }).strict(),
1379
- page: z5.object({
1380
- path: z5.string()
1381
- }).strict()
1382
- }).strict();
1383
- var formSubmitConfigSchema = z5.object({}).strict();
1384
-
1385
- // ../tracking-core/src/events/multi-page-session.ts
1386
- import { z as z6 } from "zod";
1387
- var multiPageSessionMetadataSchema = z6.object({
1388
- page_count: z6.number().int().min(2),
1389
- page: z6.object({
1390
- path: z6.string()
1391
- }).strict()
1392
- }).strict();
1393
- var multiPageSessionConfigSchema = z6.object({
1394
- pageThreshold: z6.number().int().min(2)
1395
- }).strict();
1396
-
1397
- // ../tracking-core/src/events/page-exit.ts
1398
- import { z as z7 } from "zod";
1399
- var pageExitMetadataSchema = z7.object({
1400
- dwell_ms: z7.number().int().min(0),
1401
- // null = left without any scroll signal; floor is 0 so a valid 0% is never
1402
- // rejected (a single bad field 422s the whole keepalive beacon batch).
1403
- max_scroll_percent: z7.number().int().min(0).max(100).nullable(),
1404
- // The gating baseline: the fraction of the page visible at load with
1405
- // zero scrolling — or, for pages that grew after the post-paint snapshot
1406
- // (skeleton/streaming renders), the first-scroll position that
1407
- // established it. null = page had no scrollable range, or the segment
1408
- // ended before the snapshot. `.optional()` is load-bearing: SDK builds
1409
- // predating this field keep POSTing page_exit without the key —
1410
- // requiring it would 422 whole keepalive beacon batches.
1411
- scroll_baseline_percent: z7.number().int().min(0).max(100).nullable().optional(),
1412
- page: z7.object({
1413
- path: z7.string()
1414
- }).strict()
1415
- }).strict();
1416
- var pageExitConfigSchema = z7.object({}).strict();
1417
-
1418
- // ../tracking-core/src/events/phone-click.ts
1419
- import { z as z8 } from "zod";
1420
- var phoneClickMetadataSchema = z8.object({
1421
- phone_number: z8.string(),
1422
- page: z8.object({
1423
- path: z8.string()
1424
- }).strict(),
1425
- section: z8.string().nullable().optional()
1426
- }).strict();
1427
- var phoneClickConfigSchema = z8.object({
1428
- autoCapture: z8.object({
1429
- selector: z8.string().optional()
1430
- }).strict().optional()
1431
- }).strict();
1432
-
1433
- // ../tracking-core/src/events/scroll-depth.ts
1434
- import { z as z9 } from "zod";
1435
- var scrollDepthMetadataSchema = z9.object({
1436
- depth_percent: z9.number().int().min(1).max(100),
1437
- page: z9.object({
1438
- path: z9.string()
1439
- }).strict()
1440
- }).strict();
1441
- var scrollDepthConfigSchema = z9.object({
1442
- thresholds: z9.array(z9.number().int().min(1).max(100)).min(1)
1443
- }).strict();
1444
-
1445
- // ../tracking-core/src/events/specific-page-visit.ts
1446
- import { z as z10 } from "zod";
1447
- var PAGE_IDENTITY_MAX_LENGTH = 64;
1448
- var PAGE_IDENTITY_PATTERN = /^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/;
1449
- var pageIdentitySchema = z10.string().max(PAGE_IDENTITY_MAX_LENGTH).regex(PAGE_IDENTITY_PATTERN, {
1450
- message: "page identity must be lowercase snake_case, start with a letter, and contain at most 64 characters"
1451
- });
1452
- var specificPageNameSchema = pageIdentitySchema;
1453
- var specificPageVisitMetadataSchema = z10.object({
1454
- page_name: specificPageNameSchema,
1455
- page: z10.object({
1456
- path: z10.string()
1457
- }).strict()
1458
- }).strict();
1459
- var specificPageVisitConfigSchema = z10.object({
1460
- pages: z10.array(
1461
- z10.object({
1462
- name: specificPageNameSchema,
1463
- pathPattern: z10.custom((value) => value instanceof RegExp, {
1464
- message: "pathPattern must be a RegExp"
1465
- })
1466
- }).strict()
1467
- ).min(1)
1468
- }).strict();
1469
-
1470
- // ../tracking-core/src/events/time-on-site.ts
1471
- import { z as z11 } from "zod";
1472
- var timeOnSiteMetadataSchema = z11.object({
1473
- duration_ms: z11.number().int().nonnegative(),
1474
- page: z11.object({
1475
- path: z11.string()
1476
- }).strict()
1477
- }).strict();
1478
- var timeOnSiteConfigSchema = z11.object({
1479
- thresholdSeconds: z11.number().int().positive()
1480
- }).strict();
1481
-
1482
1326
  // ../tracking-core/src/events/semantics.ts
1483
1327
  var EVENT_SEMANTICS = {
1484
1328
  page_view: {
@@ -1546,88 +1390,24 @@ var EVENT_SEMANTICS = {
1546
1390
  category: "engagement",
1547
1391
  outcomeRole: "engagement",
1548
1392
  clientVisibility: "simple"
1393
+ },
1394
+ site_link_click: {
1395
+ label: "Left for sibling site",
1396
+ category: "page",
1397
+ outcomeRole: "navigation",
1398
+ clientVisibility: "detailed"
1399
+ },
1400
+ site_link_arrival: {
1401
+ label: "Arrived from sibling site",
1402
+ category: "page",
1403
+ outcomeRole: "navigation",
1404
+ clientVisibility: "simple"
1549
1405
  }
1550
1406
  };
1551
1407
  function getEventSemantics(eventName) {
1552
1408
  return eventName in EVENT_SEMANTICS ? EVENT_SEMANTICS[eventName] : null;
1553
1409
  }
1554
1410
 
1555
- // ../tracking-core/src/events/registry.ts
1556
- var EVENT_REGISTRY = {
1557
- // --- automatic triggers ---
1558
- page_view: {
1559
- kind: "automatic",
1560
- semantics: EVENT_SEMANTICS.page_view,
1561
- metadataSchema: pageViewMetadataSchema,
1562
- configSchema: pageViewConfigSchema
1563
- },
1564
- time_on_site: {
1565
- kind: "automatic",
1566
- semantics: EVENT_SEMANTICS.time_on_site,
1567
- metadataSchema: timeOnSiteMetadataSchema,
1568
- configSchema: timeOnSiteConfigSchema
1569
- },
1570
- specific_page_visit: {
1571
- kind: "automatic",
1572
- semantics: EVENT_SEMANTICS.specific_page_visit,
1573
- metadataSchema: specificPageVisitMetadataSchema,
1574
- configSchema: specificPageVisitConfigSchema
1575
- },
1576
- scroll_depth: {
1577
- kind: "automatic",
1578
- semantics: EVENT_SEMANTICS.scroll_depth,
1579
- metadataSchema: scrollDepthMetadataSchema,
1580
- configSchema: scrollDepthConfigSchema
1581
- },
1582
- multi_page_session: {
1583
- kind: "automatic",
1584
- semantics: EVENT_SEMANTICS.multi_page_session,
1585
- metadataSchema: multiPageSessionMetadataSchema,
1586
- configSchema: multiPageSessionConfigSchema
1587
- },
1588
- form_start: {
1589
- kind: "automatic",
1590
- semantics: EVENT_SEMANTICS.form_start,
1591
- metadataSchema: formStartMetadataSchema,
1592
- configSchema: formStartConfigSchema
1593
- },
1594
- // --- SDK-internal automatic (not consumer-configurable) ---
1595
- sdk_heartbeat: {
1596
- kind: "automatic",
1597
- semantics: EVENT_SEMANTICS.sdk_heartbeat,
1598
- metadataSchema: sdkHeartbeatMetadataSchema,
1599
- configSchema: sdkHeartbeatConfigSchema
1600
- },
1601
- page_exit: {
1602
- kind: "automatic",
1603
- semantics: EVENT_SEMANTICS.page_exit,
1604
- metadataSchema: pageExitMetadataSchema,
1605
- configSchema: pageExitConfigSchema
1606
- },
1607
- // --- manual triggers ---
1608
- form_submit: {
1609
- kind: "manual",
1610
- semantics: EVENT_SEMANTICS.form_submit,
1611
- metadataSchema: formSubmitMetadataSchema,
1612
- configSchema: formSubmitConfigSchema
1613
- },
1614
- phone_click: {
1615
- kind: "manual",
1616
- semantics: EVENT_SEMANTICS.phone_click,
1617
- metadataSchema: phoneClickMetadataSchema,
1618
- configSchema: phoneClickConfigSchema
1619
- },
1620
- cta_click: {
1621
- kind: "manual",
1622
- semantics: EVENT_SEMANTICS.cta_click,
1623
- metadataSchema: ctaClickMetadataSchema,
1624
- configSchema: ctaClickConfigSchema
1625
- }
1626
- };
1627
- var ALL_AUTOMATIC_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.kind === "automatic").map(([name]) => name);
1628
- var ALL_MANUAL_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.kind === "manual").map(([name]) => name);
1629
- var ALL_LEAD_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.semantics.outcomeRole === "lead").map(([name]) => name);
1630
-
1631
1411
  // ../tracking-core/src/resources/http/errors.ts
1632
1412
  var AranovaApiError = class extends Error {
1633
1413
  constructor(message, options) {
@@ -1665,9 +1445,9 @@ async function apiRequest(config, method, path, body, extraHeaders) {
1665
1445
  try {
1666
1446
  const parsed = await response.json();
1667
1447
  if (parsed && typeof parsed === "object") {
1668
- const record = parsed;
1669
- if (typeof record.detail === "string") detail = record.detail;
1670
- if (typeof record.code === "string") code = record.code;
1448
+ const record3 = parsed;
1449
+ if (typeof record3.detail === "string") detail = record3.detail;
1450
+ if (typeof record3.code === "string") code = record3.code;
1671
1451
  }
1672
1452
  } catch {
1673
1453
  }
@@ -1716,7 +1496,7 @@ function fireRecordedConversions(firing, input, recorded, sale, currency) {
1716
1496
  }
1717
1497
  function createSalesClient(config) {
1718
1498
  if (config.firing) registerCapability("conversion_goals_manual");
1719
- async function record(input) {
1499
+ async function record3(input) {
1720
1500
  const currency = input.currency ?? config.defaultCurrency;
1721
1501
  if (!currency) {
1722
1502
  throw new Error(
@@ -1742,9 +1522,9 @@ function createSalesClient(config) {
1742
1522
  return sale;
1743
1523
  }
1744
1524
  return {
1745
- record,
1525
+ record: record3,
1746
1526
  // recordSale is the intent-revealing alias — same behavior, clearer call site.
1747
- recordSale: record,
1527
+ recordSale: record3,
1748
1528
  trackConversion(key, options) {
1749
1529
  if (config.firing && "fireConversion" in config.firing) {
1750
1530
  if (options?.userData && getConsentState() !== "denied") stashUserData(options.userData);
@@ -1863,115 +1643,269 @@ function createSalesClient(config) {
1863
1643
  }
1864
1644
 
1865
1645
  // ../tracking-core/src/resources/sales/schema.ts
1866
- import { z as z12 } from "zod";
1867
- var SUPPORTED_CURRENCIES = ["USD", "CAD"];
1868
- var TRACKING_ENVIRONMENTS = ["production", "development"];
1869
- var currencySchema = z12.enum(SUPPORTED_CURRENCIES);
1870
- var centsSchema = z12.number().int().nonnegative();
1871
- var quantitySchema = z12.string().regex(/^\d+(\.\d{1,3})?$/);
1872
- var metadataSchema = z12.record(z12.unknown());
1873
- var saleItemSchema = z12.object({
1874
- external_item_id: z12.string().nullable().optional(),
1875
- name: z12.string().nullable().optional(),
1876
- category: z12.string().nullable().optional(),
1877
- quantity: quantitySchema,
1878
- unit_price_cents: centsSchema,
1879
- // Non-negativity validated on the wire — same contract as the other cents
1880
- // fields — and backstopped by the DB CHECK.
1881
- unit_cost_cents: centsSchema.nullable().optional()
1882
- }).strict();
1883
- var saleServiceSchema = z12.object({
1884
- service: z12.string(),
1885
- amount_cents: centsSchema
1886
- }).strict();
1887
- var customerNameSchema = z12.string().max(200);
1888
- var customerPhoneSchema = z12.string().max(64);
1889
- var customerEmailSchema = z12.string().max(320).email();
1646
+ import * as z3 from "zod/mini";
1647
+
1648
+ // ../tracking-core/src/resources/sales/generated/zod.gen.ts
1649
+ import * as z2 from "zod/mini";
1650
+ var zErrorCode = z2.enum([
1651
+ "missing_credentials",
1652
+ "invalid_api_key",
1653
+ "not_authenticated",
1654
+ "wrong_key_type",
1655
+ "origin_missing",
1656
+ "origin_not_allowed",
1657
+ "capability_denied",
1658
+ "session_required",
1659
+ "operator_only",
1660
+ "cross_tenant",
1661
+ "business_id_required",
1662
+ "bad_request",
1663
+ "not_found",
1664
+ "conflict",
1665
+ "incompatible_payload",
1666
+ "repeat_confirmation_required",
1667
+ "idempotency_conflict",
1668
+ "validation_error",
1669
+ "unknown_service",
1670
+ "invalid_sale_properties",
1671
+ "invalid_cursor",
1672
+ "rate_limited",
1673
+ "internal_error"
1674
+ ]);
1675
+ var zSaleItemEntitySchema = z2.object({
1676
+ category: z2.nullable(z2.string()),
1677
+ external_item_id: z2.nullable(z2.string()),
1678
+ id: z2.uuid(),
1679
+ name: z2.nullable(z2.string()),
1680
+ quantity: z2.string().check(z2.regex(/^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$/)),
1681
+ unit_cost_cents: z2.nullable(z2.int()),
1682
+ unit_price_cents: z2.int()
1683
+ });
1684
+ var zSaleItemInputSchema = z2.strictObject({
1685
+ category: z2.nullish(z2.string()),
1686
+ external_item_id: z2.nullish(z2.string()),
1687
+ name: z2.nullish(z2.string()),
1688
+ quantity: z2.string().check(z2.regex(/^\d+(\.\d{1,3})?$/)),
1689
+ unit_cost_cents: z2.nullish(z2.int().check(z2.gte(0))),
1690
+ unit_price_cents: z2.int().check(z2.gte(0))
1691
+ });
1692
+ var zSaleServiceEntitySchema = z2.object({
1693
+ amount_cents: z2.int(),
1694
+ id: z2.uuid(),
1695
+ mapped: z2.nullable(z2.boolean()),
1696
+ service_id: z2.uuid(),
1697
+ service_key: z2.string(),
1698
+ service_label: z2.string()
1699
+ });
1700
+ var zSaleServiceInputSchema = z2.strictObject({
1701
+ amount_cents: z2.int().check(z2.gte(0)),
1702
+ service: z2.string()
1703
+ });
1704
+ var zSmsAutomationState = z2.enum([
1705
+ "needs_check",
1706
+ "failed",
1707
+ "undelivered",
1708
+ "blocked_opted_out",
1709
+ "withheld",
1710
+ "queued",
1711
+ "sent",
1712
+ "delivered",
1713
+ "eligible",
1714
+ "not_applicable"
1715
+ ]);
1716
+ var zSmsWithheldReason = z2.enum([
1717
+ "automation_disabled",
1718
+ "sms_disabled",
1719
+ "no_phone",
1720
+ "no_consent",
1721
+ "no_customer_identity",
1722
+ "missing_customer_name",
1723
+ "placeholder_customer_name",
1724
+ "opted_out",
1725
+ "already_messaged",
1726
+ "sender_not_ready",
1727
+ "missing_review_url",
1728
+ "no_handler",
1729
+ "dispatch_already_recorded",
1730
+ "text_back_disabled",
1731
+ "number_not_active",
1732
+ "a2p_registration_required",
1733
+ "alert_recipient_cannot_receive_sms",
1734
+ "line_type_unresolved"
1735
+ ]);
1736
+ var zSaleSmsStatusSchema = z2.object({
1737
+ can_send_now: z2._default(z2.boolean(), false),
1738
+ last_message_at: z2.nullable(z2.iso.datetime({ offset: true })),
1739
+ reason_detail: z2.nullable(z2.string()),
1740
+ state: zSmsAutomationState,
1741
+ suppressed_by_other_sale: z2._default(z2.boolean(), false),
1742
+ withheld_reason: z2.nullable(zSmsWithheldReason)
1743
+ });
1744
+ var zSupportedCurrency = z2.enum(["USD", "CAD"]);
1745
+ var zTrackingEnvironment = z2.enum(["production", "development"]);
1746
+ var zSaleCreateSchema = z2.strictObject({
1747
+ amount_total_cents: z2.nullish(z2.int().check(z2.gte(0))),
1748
+ currency: zSupportedCurrency,
1749
+ customer_email: z2.nullish(z2.email().check(z2.maxLength(320))),
1750
+ customer_name: z2.nullish(z2.string().check(z2.maxLength(200))),
1751
+ customer_phone: z2.nullish(z2.string().check(z2.maxLength(64))),
1752
+ description: z2.nullish(z2.string()),
1753
+ environment: z2._default(z2.optional(zTrackingEnvironment), "production"),
1754
+ external_id: z2.nullish(z2.string()),
1755
+ items: z2.optional(z2.array(zSaleItemInputSchema)),
1756
+ metadata: z2.nullish(z2.record(z2.string(), z2.unknown())),
1757
+ occurred_at: z2.iso.datetime({ offset: true }),
1758
+ service: z2.nullish(z2.string()),
1759
+ services: z2.nullish(z2.array(zSaleServiceInputSchema)),
1760
+ sms_consent: z2.nullish(z2.boolean())
1761
+ });
1762
+ var zValidationError = z2.object({
1763
+ ctx: z2.optional(z2.record(z2.string(), z2.unknown())),
1764
+ input: z2.optional(z2.unknown()),
1765
+ loc: z2.array(z2.union([z2.string(), z2.int()])),
1766
+ msg: z2.string(),
1767
+ type: z2.string()
1768
+ });
1769
+ var zHttpValidationError = z2.object({
1770
+ detail: z2.optional(z2.array(zValidationError))
1771
+ });
1772
+ var zValidationErrorItem = z2.object({
1773
+ loc: z2.array(z2.union([z2.string(), z2.int()])),
1774
+ msg: z2.string(),
1775
+ type: z2.string()
1776
+ });
1777
+ var zApiErrorSchema = z2.object({
1778
+ code: zErrorCode,
1779
+ context: z2._default(z2.nullish(z2.record(z2.string(), z2.unknown())), null),
1780
+ detail: z2.string(),
1781
+ errors: z2._default(z2.nullish(z2.array(zValidationErrorItem)), null),
1782
+ request_id: z2._default(z2.nullish(z2.string()), null)
1783
+ });
1784
+ var zWritebackEmailSource = z2.enum(["NONE", "SALE", "CUSTOMER", "HARVESTED"]);
1785
+ var zWritebackEnrichmentStatus = z2.enum(["NONE", "MATCHED", "AMBIGUOUS"]);
1786
+ var zWritebackSaleUploadCounts = z2.object({
1787
+ failed: z2._default(z2.int(), 0),
1788
+ pending: z2._default(z2.int(), 0),
1789
+ skipped: z2._default(z2.int(), 0),
1790
+ submitted: z2._default(z2.int(), 0),
1791
+ total: z2._default(z2.int(), 0),
1792
+ uploaded: z2._default(z2.int(), 0)
1793
+ });
1794
+ var zSaleWritebackStatusSchema = z2.object({
1795
+ blocked_reason: z2.nullable(z2.string()),
1796
+ can_dispatch: z2._default(z2.boolean(), false),
1797
+ email_source: z2.nullable(zWritebackEmailSource),
1798
+ enrichment_status: z2.nullable(zWritebackEnrichmentStatus),
1799
+ gclid_attached: z2._default(z2.boolean(), false),
1800
+ identifiers_sent: z2.nullable(z2.string()),
1801
+ mapped_service_ids: z2.array(z2.uuid()),
1802
+ matched_submit_count: z2.nullable(z2.int()),
1803
+ needs_force: z2._default(z2.boolean(), false),
1804
+ rollup: z2.enum([
1805
+ "failed",
1806
+ "skipped",
1807
+ "pending",
1808
+ "submitted",
1809
+ "uploaded",
1810
+ "not_uploaded",
1811
+ "out_of_window",
1812
+ "blocked"
1813
+ ]),
1814
+ stale: z2._default(z2.boolean(), false),
1815
+ uncovered_service_ids: z2.array(z2.uuid()),
1816
+ uploads: zWritebackSaleUploadCounts
1817
+ });
1818
+ var zSaleEntitySchema = z2.object({
1819
+ amount_total_cents: z2.int(),
1820
+ business_id: z2.uuid(),
1821
+ business_name: z2.nullable(z2.string()),
1822
+ created_at: z2.iso.datetime({ offset: true }),
1823
+ currency: z2.string(),
1824
+ customer_email: z2.nullable(z2.string()),
1825
+ customer_name: z2.nullable(z2.string()),
1826
+ customer_name_placeholder_confirmed: z2._default(z2.boolean(), false),
1827
+ customer_name_placeholder_confirmed_at: z2.nullable(z2.iso.datetime({ offset: true })),
1828
+ customer_phone: z2.nullable(z2.string()),
1829
+ description: z2.nullable(z2.string()),
1830
+ environment: zTrackingEnvironment,
1831
+ external_id: z2.nullable(z2.string()),
1832
+ id: z2.uuid(),
1833
+ items: z2.array(zSaleItemEntitySchema),
1834
+ metadata: z2.nullable(z2.record(z2.string(), z2.unknown())),
1835
+ occurred_at: z2.iso.datetime({ offset: true }),
1836
+ service_id: z2.nullable(z2.uuid()),
1837
+ service_key: z2.nullable(z2.string()),
1838
+ service_label: z2.nullable(z2.string()),
1839
+ services: z2.array(zSaleServiceEntitySchema),
1840
+ sms_automation: z2.nullable(zSaleSmsStatusSchema),
1841
+ sms_consent: z2._default(z2.boolean(), false),
1842
+ sms_consent_granted_at: z2.nullable(z2.iso.datetime({ offset: true })),
1843
+ updated_at: z2.iso.datetime({ offset: true }),
1844
+ writeback: z2.nullable(zSaleWritebackStatusSchema)
1845
+ });
1846
+
1847
+ // ../tracking-core/src/resources/sales/schema.ts
1848
+ var saleItemSchema = zSaleItemInputSchema;
1849
+ var saleServiceSchema = zSaleServiceInputSchema;
1850
+ var currencySchema = zSupportedCurrency;
1851
+ var SUPPORTED_CURRENCIES = currencySchema.options;
1852
+ var centsSchema = z3.int().check(z3.gte(0));
1853
+ var metadataSchema = z3.record(z3.string(), z3.unknown());
1854
+ var customerNameSchema = z3.string().check(z3.maxLength(200));
1855
+ var customerPhoneSchema = z3.string().check(z3.maxLength(64));
1856
+ var customerEmailSchema = z3.email().check(z3.maxLength(320));
1857
+ function addIssue(ctx, path, message) {
1858
+ ctx.issues.push({ code: "custom", input: ctx.value, path, message });
1859
+ }
1890
1860
  function refineServiceXor(val, ctx, { requireAmount }) {
1891
1861
  if (val.services != null) {
1892
1862
  if (val.service != null) {
1893
- ctx.addIssue({
1894
- code: z12.ZodIssueCode.custom,
1895
- message: "pass either `service` or `services`, not both",
1896
- path: ["services"]
1897
- });
1863
+ addIssue(ctx, ["services"], "pass either `service` or `services`, not both");
1898
1864
  }
1899
1865
  if (val.services.length === 0) {
1900
- ctx.addIssue({
1901
- code: z12.ZodIssueCode.custom,
1902
- message: "`services` must not be empty",
1903
- path: ["services"]
1904
- });
1866
+ addIssue(ctx, ["services"], "`services` must not be empty");
1905
1867
  }
1906
1868
  const keys = val.services.map((s) => s.service);
1907
1869
  if (new Set(keys).size !== keys.length) {
1908
- ctx.addIssue({
1909
- code: z12.ZodIssueCode.custom,
1910
- message: "`services` must not list the same service more than once",
1911
- path: ["services"]
1912
- });
1870
+ addIssue(ctx, ["services"], "`services` must not list the same service more than once");
1913
1871
  }
1914
1872
  if (val.amount_total_cents != null) {
1915
1873
  const sum = val.services.reduce((acc, s) => acc + s.amount_cents, 0);
1916
1874
  if (val.amount_total_cents !== sum) {
1917
- ctx.addIssue({
1918
- code: z12.ZodIssueCode.custom,
1919
- message: "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)",
1920
- path: ["amount_total_cents"]
1921
- });
1875
+ addIssue(
1876
+ ctx,
1877
+ ["amount_total_cents"],
1878
+ "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)"
1879
+ );
1922
1880
  }
1923
1881
  }
1924
1882
  } else if (requireAmount && val.amount_total_cents == null) {
1925
- ctx.addIssue({
1926
- code: z12.ZodIssueCode.custom,
1927
- message: "amount_total_cents is required unless `services` is provided",
1928
- path: ["amount_total_cents"]
1929
- });
1883
+ addIssue(
1884
+ ctx,
1885
+ ["amount_total_cents"],
1886
+ "amount_total_cents is required unless `services` is provided"
1887
+ );
1930
1888
  }
1931
1889
  }
1932
- var saleCreateSchema = z12.object({
1933
- external_id: z12.string().nullable().optional(),
1934
- description: z12.string().nullable().optional(),
1935
- service: z12.string().nullable().optional(),
1936
- services: z12.array(saleServiceSchema).nullable().optional(),
1937
- currency: currencySchema,
1938
- // Optional only because the plural `services` form derives it from the sum
1939
- // (see refineServiceXor); the singular/serviceless path still requires it.
1940
- amount_total_cents: centsSchema.nullable().optional(),
1941
- occurred_at: z12.string().datetime(),
1942
- environment: z12.enum(TRACKING_ENVIRONMENTS).default("production"),
1943
- items: z12.array(saleItemSchema).default([]),
1944
- metadata: metadataSchema.nullable().optional(),
1945
- customer_name: customerNameSchema.nullable().optional(),
1946
- customer_phone: customerPhoneSchema.nullable().optional(),
1947
- customer_email: customerEmailSchema.nullable().optional(),
1948
- // CASL consent attestation: the customer agreed to receive SMS. Recorded
1949
- // with a timestamp server-side; every SMS send path gates on it.
1950
- //
1951
- // Tri-state: omit it (or send null) to let the server apply the business's
1952
- // configured default-opt-in policy, honouring a returning customer's
1953
- // remembered preference. Send an explicit boolean to assert consent state
1954
- // yourself — `false` records a deliberate opt-out.
1955
- sms_consent: z12.boolean().nullable().optional()
1956
- }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: true }));
1957
- var saleUpdateSchema = z12.object({
1958
- description: z12.string().nullable().optional(),
1959
- service: z12.string().nullable().optional(),
1960
- services: z12.array(saleServiceSchema).nullable().optional(),
1961
- currency: currencySchema.optional(),
1962
- amount_total_cents: centsSchema.optional(),
1963
- occurred_at: z12.string().datetime().optional(),
1964
- items: z12.array(saleItemSchema).optional(),
1965
- metadata: metadataSchema.nullable().optional(),
1966
- customer_name: customerNameSchema.nullable().optional(),
1890
+ var saleCreateSchema = z3.extend(zSaleCreateSchema, { items: z3._default(z3.array(saleItemSchema), []) }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: true }));
1891
+ var saleUpdateSchema = z3.strictObject({
1892
+ description: z3.nullish(z3.string()),
1893
+ service: z3.nullish(z3.string()),
1894
+ services: z3.nullish(z3.array(saleServiceSchema)),
1895
+ currency: z3.optional(currencySchema),
1896
+ amount_total_cents: z3.optional(centsSchema),
1897
+ occurred_at: z3.optional(z3.iso.datetime()),
1898
+ items: z3.optional(z3.array(saleItemSchema)),
1899
+ metadata: z3.nullish(metadataSchema),
1900
+ customer_name: z3.nullish(customerNameSchema),
1967
1901
  // Re-attest when changing a filler-looking name; the server clears the
1968
1902
  // prior attestation whenever `customer_name` changes.
1969
- customer_name_placeholder_confirmed: z12.boolean().optional(),
1970
- customer_phone: customerPhoneSchema.nullable().optional(),
1971
- customer_email: customerEmailSchema.nullable().optional(),
1903
+ customer_name_placeholder_confirmed: z3.optional(z3.boolean()),
1904
+ customer_phone: z3.nullish(customerPhoneSchema),
1905
+ customer_email: z3.nullish(customerEmailSchema),
1972
1906
  // NOT NULL server-side: omit to leave unchanged (explicit null is rejected).
1973
- sms_consent: z12.boolean().optional()
1974
- }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: false }));
1907
+ sms_consent: z3.optional(z3.boolean())
1908
+ }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: false }));
1975
1909
  var TRACKING_RANGES = ["24h", "7d", "30d"];
1976
1910
  var NAMED_RANGES = [
1977
1911
  "today",
@@ -2023,6 +1957,7 @@ export {
2023
1957
  createTrackingClientContext,
2024
1958
  createTrackingEventCreatePayload,
2025
1959
  createTrackingSessionUpsertPayload,
1960
+ currencySchema,
2026
1961
  fetchServices,
2027
1962
  formatDateInTz,
2028
1963
  formatMoney,