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