@aranova/tracking-react 0.14.2 → 0.16.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/phone.mjs CHANGED
@@ -1,76 +1,3 @@
1
- // ../tracking-core/src/consent.ts
2
- var CONSENT_STATE_KEY = "consent_state";
3
- var grantedListeners = /* @__PURE__ */ new Set();
4
- function onConsentGranted(listener) {
5
- grantedListeners.add(listener);
6
- return () => {
7
- grantedListeners.delete(listener);
8
- };
9
- }
10
- function getConsentState() {
11
- if (typeof window === "undefined") return "pending";
12
- try {
13
- const storedState = window.localStorage.getItem(CONSENT_STATE_KEY);
14
- if (storedState === "granted" || storedState === "denied") return storedState;
15
- } catch {
16
- }
17
- return "pending";
18
- }
19
-
20
- // ../tracking-core/src/gtag.ts
21
- var SEND_TO_RE = /^AW-[A-Za-z0-9]+\/[A-Za-z0-9_-]+$/;
22
- function isValidSendTo(sendTo) {
23
- return SEND_TO_RE.test(sendTo);
24
- }
25
- function fireGtagConversion(input) {
26
- if (typeof window === "undefined" || typeof window.gtag !== "function") return false;
27
- if (!isValidSendTo(input.sendTo)) return false;
28
- const params = { send_to: input.sendTo };
29
- if (input.value != null) params.value = input.value;
30
- if (input.currency) params.currency = input.currency;
31
- if (input.transactionId) params.transaction_id = input.transactionId;
32
- try {
33
- window.gtag("event", "conversion", params);
34
- return true;
35
- } catch {
36
- return false;
37
- }
38
- }
39
-
40
- // ../tracking-core/src/resources/conversion-firing.ts
41
- var DEDUP_PREFIX = "_aranova_conv_";
42
- var pendingQueue = [];
43
- function dedupKey(input) {
44
- return `${DEDUP_PREFIX}${input.transactionId ?? ""}:${input.sendTo}`;
45
- }
46
- function alreadyFired(input) {
47
- if (!input.transactionId || typeof window === "undefined") return false;
48
- try {
49
- return window.sessionStorage.getItem(dedupKey(input)) !== null;
50
- } catch {
51
- return false;
52
- }
53
- }
54
- function markFired(input) {
55
- if (!input.transactionId || typeof window === "undefined") return;
56
- try {
57
- window.sessionStorage.setItem(dedupKey(input), "1");
58
- } catch {
59
- }
60
- }
61
- function fireOnce(input) {
62
- if (alreadyFired(input)) return;
63
- if (fireGtagConversion(input)) markFired(input);
64
- }
65
- function flushPendingConversions() {
66
- if (getConsentState() !== "granted") return;
67
- while (pendingQueue.length > 0) {
68
- const input = pendingQueue.shift();
69
- if (input) fireOnce(input);
70
- }
71
- }
72
- if (typeof window !== "undefined") onConsentGranted(flushPendingConversions);
73
-
74
1
  // ../tracking-core/src/session.ts
75
2
  var SESSION_IDLE_MS = 30 * 60 * 1e3;
76
3
 
@@ -102,9 +29,17 @@ var ctaClickMetadataSchema = z2.object({
102
29
  path: z2.string()
103
30
  }).strict(),
104
31
  section: z2.string().nullable().optional(),
105
- destination_url: z2.string().nullable().optional()
32
+ destination_url: z2.string().nullable().optional(),
33
+ // Set by auto-capture (and available to manual callers): the link target
34
+ // and a short element descriptor (tag#id) for tying clicks to specific UI.
35
+ href: z2.string().nullable().optional(),
36
+ element: z2.string().nullable().optional()
37
+ }).strict();
38
+ var ctaClickConfigSchema = z2.object({
39
+ autoCapture: z2.object({
40
+ selector: z2.string().optional()
41
+ }).strict().optional()
106
42
  }).strict();
107
- var ctaClickConfigSchema = z2.object({}).strict();
108
43
 
109
44
  // ../tracking-core/src/events/sdk-heartbeat.ts
110
45
  import { z as z3 } from "zod";
@@ -180,31 +115,44 @@ var multiPageSessionConfigSchema = z6.object({
180
115
  pageThreshold: z6.number().int().min(2)
181
116
  }).strict();
182
117
 
183
- // ../tracking-core/src/events/phone-click.ts
118
+ // ../tracking-core/src/events/page-exit.ts
184
119
  import { z as z7 } from "zod";
185
- var phoneClickMetadataSchema = z7.object({
186
- phone_number: z7.string(),
120
+ var pageExitMetadataSchema = z7.object({
121
+ dwell_ms: z7.number().int().min(0),
122
+ // null = left without any scroll signal; floor is 0 so a valid 0% is never
123
+ // rejected (a single bad field 422s the whole keepalive beacon batch).
124
+ max_scroll_percent: z7.number().int().min(0).max(100).nullable(),
187
125
  page: z7.object({
188
126
  path: z7.string()
189
- }).strict(),
190
- section: z7.string().nullable().optional()
127
+ }).strict()
191
128
  }).strict();
192
- var phoneClickConfigSchema = z7.object({}).strict();
129
+ var pageExitConfigSchema = z7.object({}).strict();
193
130
 
194
- // ../tracking-core/src/events/scroll-depth.ts
131
+ // ../tracking-core/src/events/phone-click.ts
195
132
  import { z as z8 } from "zod";
196
- var scrollDepthMetadataSchema = z8.object({
197
- depth_percent: z8.number().int().min(1).max(100),
133
+ var phoneClickMetadataSchema = z8.object({
134
+ phone_number: z8.string(),
198
135
  page: z8.object({
199
136
  path: z8.string()
137
+ }).strict(),
138
+ section: z8.string().nullable().optional()
139
+ }).strict();
140
+ var phoneClickConfigSchema = z8.object({}).strict();
141
+
142
+ // ../tracking-core/src/events/scroll-depth.ts
143
+ import { z as z9 } from "zod";
144
+ var scrollDepthMetadataSchema = z9.object({
145
+ depth_percent: z9.number().int().min(1).max(100),
146
+ page: z9.object({
147
+ path: z9.string()
200
148
  }).strict()
201
149
  }).strict();
202
- var scrollDepthConfigSchema = z8.object({
203
- thresholds: z8.array(z8.number().int().min(1).max(100)).min(1)
150
+ var scrollDepthConfigSchema = z9.object({
151
+ thresholds: z9.array(z9.number().int().min(1).max(100)).min(1)
204
152
  }).strict();
205
153
 
206
154
  // ../tracking-core/src/events/specific-page-visit.ts
207
- import { z as z9 } from "zod";
155
+ import { z as z10 } from "zod";
208
156
  var SPECIFIC_PAGE_NAMES = [
209
157
  "contact_page",
210
158
  "about_page",
@@ -215,18 +163,18 @@ var SPECIFIC_PAGE_NAMES = [
215
163
  "faq_page",
216
164
  "testimonials_page"
217
165
  ];
218
- var specificPageNameSchema = z9.enum(SPECIFIC_PAGE_NAMES);
219
- var specificPageVisitMetadataSchema = z9.object({
166
+ var specificPageNameSchema = z10.enum(SPECIFIC_PAGE_NAMES);
167
+ var specificPageVisitMetadataSchema = z10.object({
220
168
  page_name: specificPageNameSchema,
221
- page: z9.object({
222
- path: z9.string()
169
+ page: z10.object({
170
+ path: z10.string()
223
171
  }).strict()
224
172
  }).strict();
225
- var specificPageVisitConfigSchema = z9.object({
226
- pages: z9.array(
227
- z9.object({
173
+ var specificPageVisitConfigSchema = z10.object({
174
+ pages: z10.array(
175
+ z10.object({
228
176
  name: specificPageNameSchema,
229
- pathPattern: z9.custom((value) => value instanceof RegExp, {
177
+ pathPattern: z10.custom((value) => value instanceof RegExp, {
230
178
  message: "pathPattern must be a RegExp"
231
179
  })
232
180
  }).strict()
@@ -234,15 +182,15 @@ var specificPageVisitConfigSchema = z9.object({
234
182
  }).strict();
235
183
 
236
184
  // ../tracking-core/src/events/time-on-site.ts
237
- import { z as z10 } from "zod";
238
- var timeOnSiteMetadataSchema = z10.object({
239
- duration_ms: z10.number().int().nonnegative(),
240
- page: z10.object({
241
- path: z10.string()
185
+ import { z as z11 } from "zod";
186
+ var timeOnSiteMetadataSchema = z11.object({
187
+ duration_ms: z11.number().int().nonnegative(),
188
+ page: z11.object({
189
+ path: z11.string()
242
190
  }).strict()
243
191
  }).strict();
244
- var timeOnSiteConfigSchema = z10.object({
245
- thresholdSeconds: z10.number().int().positive()
192
+ var timeOnSiteConfigSchema = z11.object({
193
+ thresholdSeconds: z11.number().int().positive()
246
194
  }).strict();
247
195
 
248
196
  // ../tracking-core/src/events/registry.ts
@@ -284,6 +232,11 @@ var EVENT_REGISTRY = {
284
232
  metadataSchema: sdkHeartbeatMetadataSchema,
285
233
  configSchema: sdkHeartbeatConfigSchema
286
234
  },
235
+ page_exit: {
236
+ kind: "automatic",
237
+ metadataSchema: pageExitMetadataSchema,
238
+ configSchema: pageExitConfigSchema
239
+ },
287
240
  // --- manual triggers ---
288
241
  form_submit: {
289
242
  kind: "manual",
@@ -305,42 +258,42 @@ var ALL_AUTOMATIC_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def])
305
258
  var ALL_MANUAL_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.kind === "manual").map(([name]) => name);
306
259
 
307
260
  // ../tracking-core/src/resources/sales/schema.ts
308
- import { z as z11 } from "zod";
261
+ import { z as z12 } from "zod";
309
262
  var SUPPORTED_CURRENCIES = ["USD", "CAD"];
310
263
  var TRACKING_ENVIRONMENTS = ["production", "development"];
311
- var currencySchema = z11.enum(SUPPORTED_CURRENCIES);
312
- var centsSchema = z11.number().int().nonnegative();
313
- var quantitySchema = z11.string().regex(/^\d+(\.\d{1,3})?$/);
314
- var metadataSchema = z11.record(z11.unknown());
315
- var saleItemSchema = z11.object({
316
- external_item_id: z11.string().nullable().optional(),
317
- name: z11.string().nullable().optional(),
318
- category: z11.string().nullable().optional(),
264
+ var currencySchema = z12.enum(SUPPORTED_CURRENCIES);
265
+ var centsSchema = z12.number().int().nonnegative();
266
+ var quantitySchema = z12.string().regex(/^\d+(\.\d{1,3})?$/);
267
+ var metadataSchema = z12.record(z12.unknown());
268
+ var saleItemSchema = z12.object({
269
+ external_item_id: z12.string().nullable().optional(),
270
+ name: z12.string().nullable().optional(),
271
+ category: z12.string().nullable().optional(),
319
272
  quantity: quantitySchema,
320
273
  unit_price_cents: centsSchema,
321
274
  // Non-negativity validated on the wire — same contract as the other cents
322
275
  // fields — and backstopped by the DB CHECK.
323
276
  unit_cost_cents: centsSchema.nullable().optional()
324
277
  }).strict();
325
- var saleServiceSchema = z11.object({
326
- service: z11.string(),
278
+ var saleServiceSchema = z12.object({
279
+ service: z12.string(),
327
280
  amount_cents: centsSchema
328
281
  }).strict();
329
- var customerNameSchema = z11.string().max(200);
330
- var customerPhoneSchema = z11.string().max(64);
331
- var customerEmailSchema = z11.string().max(320).email();
282
+ var customerNameSchema = z12.string().max(200);
283
+ var customerPhoneSchema = z12.string().max(64);
284
+ var customerEmailSchema = z12.string().max(320).email();
332
285
  function refineServiceXor(val, ctx, { requireAmount }) {
333
286
  if (val.services != null) {
334
287
  if (val.service != null) {
335
288
  ctx.addIssue({
336
- code: z11.ZodIssueCode.custom,
289
+ code: z12.ZodIssueCode.custom,
337
290
  message: "pass either `service` or `services`, not both",
338
291
  path: ["services"]
339
292
  });
340
293
  }
341
294
  if (val.services.length === 0) {
342
295
  ctx.addIssue({
343
- code: z11.ZodIssueCode.custom,
296
+ code: z12.ZodIssueCode.custom,
344
297
  message: "`services` must not be empty",
345
298
  path: ["services"]
346
299
  });
@@ -348,7 +301,7 @@ function refineServiceXor(val, ctx, { requireAmount }) {
348
301
  const keys = val.services.map((s) => s.service);
349
302
  if (new Set(keys).size !== keys.length) {
350
303
  ctx.addIssue({
351
- code: z11.ZodIssueCode.custom,
304
+ code: z12.ZodIssueCode.custom,
352
305
  message: "`services` must not list the same service more than once",
353
306
  path: ["services"]
354
307
  });
@@ -357,7 +310,7 @@ function refineServiceXor(val, ctx, { requireAmount }) {
357
310
  const sum = val.services.reduce((acc, s) => acc + s.amount_cents, 0);
358
311
  if (val.amount_total_cents !== sum) {
359
312
  ctx.addIssue({
360
- code: z11.ZodIssueCode.custom,
313
+ code: z12.ZodIssueCode.custom,
361
314
  message: "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)",
362
315
  path: ["amount_total_cents"]
363
316
  });
@@ -365,37 +318,37 @@ function refineServiceXor(val, ctx, { requireAmount }) {
365
318
  }
366
319
  } else if (requireAmount && val.amount_total_cents == null) {
367
320
  ctx.addIssue({
368
- code: z11.ZodIssueCode.custom,
321
+ code: z12.ZodIssueCode.custom,
369
322
  message: "amount_total_cents is required unless `services` is provided",
370
323
  path: ["amount_total_cents"]
371
324
  });
372
325
  }
373
326
  }
374
- var saleCreateSchema = z11.object({
375
- external_id: z11.string().nullable().optional(),
376
- description: z11.string().nullable().optional(),
377
- service: z11.string().nullable().optional(),
378
- services: z11.array(saleServiceSchema).nullable().optional(),
327
+ var saleCreateSchema = z12.object({
328
+ external_id: z12.string().nullable().optional(),
329
+ description: z12.string().nullable().optional(),
330
+ service: z12.string().nullable().optional(),
331
+ services: z12.array(saleServiceSchema).nullable().optional(),
379
332
  currency: currencySchema,
380
333
  // Optional only because the plural `services` form derives it from the sum
381
334
  // (see refineServiceXor); the singular/serviceless path still requires it.
382
335
  amount_total_cents: centsSchema.nullable().optional(),
383
- occurred_at: z11.string().datetime(),
384
- environment: z11.enum(TRACKING_ENVIRONMENTS).default("production"),
385
- items: z11.array(saleItemSchema).default([]),
336
+ occurred_at: z12.string().datetime(),
337
+ environment: z12.enum(TRACKING_ENVIRONMENTS).default("production"),
338
+ items: z12.array(saleItemSchema).default([]),
386
339
  metadata: metadataSchema.nullable().optional(),
387
340
  customer_name: customerNameSchema.nullable().optional(),
388
341
  customer_phone: customerPhoneSchema.nullable().optional(),
389
342
  customer_email: customerEmailSchema.nullable().optional()
390
343
  }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: true }));
391
- var saleUpdateSchema = z11.object({
392
- description: z11.string().nullable().optional(),
393
- service: z11.string().nullable().optional(),
394
- services: z11.array(saleServiceSchema).nullable().optional(),
344
+ var saleUpdateSchema = z12.object({
345
+ description: z12.string().nullable().optional(),
346
+ service: z12.string().nullable().optional(),
347
+ services: z12.array(saleServiceSchema).nullable().optional(),
395
348
  currency: currencySchema.optional(),
396
349
  amount_total_cents: centsSchema.optional(),
397
- occurred_at: z11.string().datetime().optional(),
398
- items: z11.array(saleItemSchema).optional(),
350
+ occurred_at: z12.string().datetime().optional(),
351
+ items: z12.array(saleItemSchema).optional(),
399
352
  metadata: metadataSchema.nullable().optional(),
400
353
  customer_name: customerNameSchema.nullable().optional(),
401
354
  customer_phone: customerPhoneSchema.nullable().optional(),