@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.js CHANGED
@@ -26,25 +26,6 @@ module.exports = __toCommonJS(server_exports);
26
26
  var import_server_only = require("server-only");
27
27
  var import_headers = require("next/headers");
28
28
 
29
- // ../tracking-core/src/consent.ts
30
- var CONSENT_STATE_KEY = "consent_state";
31
- var grantedListeners = /* @__PURE__ */ new Set();
32
- function onConsentGranted(listener) {
33
- grantedListeners.add(listener);
34
- return () => {
35
- grantedListeners.delete(listener);
36
- };
37
- }
38
- function getConsentState() {
39
- if (typeof window === "undefined") return "pending";
40
- try {
41
- const storedState = window.localStorage.getItem(CONSENT_STATE_KEY);
42
- if (storedState === "granted" || storedState === "denied") return storedState;
43
- } catch {
44
- }
45
- return "pending";
46
- }
47
-
48
29
  // ../tracking-core/src/tracking.ts
49
30
  var TRACKING_PARAM_KEYS = [
50
31
  "gclid",
@@ -76,60 +57,6 @@ function getTrackingParamsFromCookieReader(readCookie) {
76
57
  }, createEmptyTrackingParams());
77
58
  }
78
59
 
79
- // ../tracking-core/src/gtag.ts
80
- var SEND_TO_RE = /^AW-[A-Za-z0-9]+\/[A-Za-z0-9_-]+$/;
81
- function isValidSendTo(sendTo) {
82
- return SEND_TO_RE.test(sendTo);
83
- }
84
- function fireGtagConversion(input) {
85
- if (typeof window === "undefined" || typeof window.gtag !== "function") return false;
86
- if (!isValidSendTo(input.sendTo)) return false;
87
- const params = { send_to: input.sendTo };
88
- if (input.value != null) params.value = input.value;
89
- if (input.currency) params.currency = input.currency;
90
- if (input.transactionId) params.transaction_id = input.transactionId;
91
- try {
92
- window.gtag("event", "conversion", params);
93
- return true;
94
- } catch {
95
- return false;
96
- }
97
- }
98
-
99
- // ../tracking-core/src/resources/conversion-firing.ts
100
- var DEDUP_PREFIX = "_aranova_conv_";
101
- var pendingQueue = [];
102
- function dedupKey(input) {
103
- return `${DEDUP_PREFIX}${input.transactionId ?? ""}:${input.sendTo}`;
104
- }
105
- function alreadyFired(input) {
106
- if (!input.transactionId || typeof window === "undefined") return false;
107
- try {
108
- return window.sessionStorage.getItem(dedupKey(input)) !== null;
109
- } catch {
110
- return false;
111
- }
112
- }
113
- function markFired(input) {
114
- if (!input.transactionId || typeof window === "undefined") return;
115
- try {
116
- window.sessionStorage.setItem(dedupKey(input), "1");
117
- } catch {
118
- }
119
- }
120
- function fireOnce(input) {
121
- if (alreadyFired(input)) return;
122
- if (fireGtagConversion(input)) markFired(input);
123
- }
124
- function flushPendingConversions() {
125
- if (getConsentState() !== "granted") return;
126
- while (pendingQueue.length > 0) {
127
- const input = pendingQueue.shift();
128
- if (input) fireOnce(input);
129
- }
130
- }
131
- if (typeof window !== "undefined") onConsentGranted(flushPendingConversions);
132
-
133
60
  // ../tracking-core/src/session.ts
134
61
  var SESSION_IDLE_MS = 30 * 60 * 1e3;
135
62
 
@@ -161,9 +88,17 @@ var ctaClickMetadataSchema = import_zod2.z.object({
161
88
  path: import_zod2.z.string()
162
89
  }).strict(),
163
90
  section: import_zod2.z.string().nullable().optional(),
164
- destination_url: import_zod2.z.string().nullable().optional()
91
+ destination_url: import_zod2.z.string().nullable().optional(),
92
+ // Set by auto-capture (and available to manual callers): the link target
93
+ // and a short element descriptor (tag#id) for tying clicks to specific UI.
94
+ href: import_zod2.z.string().nullable().optional(),
95
+ element: import_zod2.z.string().nullable().optional()
96
+ }).strict();
97
+ var ctaClickConfigSchema = import_zod2.z.object({
98
+ autoCapture: import_zod2.z.object({
99
+ selector: import_zod2.z.string().optional()
100
+ }).strict().optional()
165
101
  }).strict();
166
- var ctaClickConfigSchema = import_zod2.z.object({}).strict();
167
102
 
168
103
  // ../tracking-core/src/events/sdk-heartbeat.ts
169
104
  var import_zod3 = require("zod");
@@ -239,31 +174,44 @@ var multiPageSessionConfigSchema = import_zod6.z.object({
239
174
  pageThreshold: import_zod6.z.number().int().min(2)
240
175
  }).strict();
241
176
 
242
- // ../tracking-core/src/events/phone-click.ts
177
+ // ../tracking-core/src/events/page-exit.ts
243
178
  var import_zod7 = require("zod");
244
- var phoneClickMetadataSchema = import_zod7.z.object({
245
- phone_number: import_zod7.z.string(),
179
+ var pageExitMetadataSchema = import_zod7.z.object({
180
+ dwell_ms: import_zod7.z.number().int().min(0),
181
+ // null = left without any scroll signal; floor is 0 so a valid 0% is never
182
+ // rejected (a single bad field 422s the whole keepalive beacon batch).
183
+ max_scroll_percent: import_zod7.z.number().int().min(0).max(100).nullable(),
246
184
  page: import_zod7.z.object({
247
185
  path: import_zod7.z.string()
248
- }).strict(),
249
- section: import_zod7.z.string().nullable().optional()
186
+ }).strict()
250
187
  }).strict();
251
- var phoneClickConfigSchema = import_zod7.z.object({}).strict();
188
+ var pageExitConfigSchema = import_zod7.z.object({}).strict();
252
189
 
253
- // ../tracking-core/src/events/scroll-depth.ts
190
+ // ../tracking-core/src/events/phone-click.ts
254
191
  var import_zod8 = require("zod");
255
- var scrollDepthMetadataSchema = import_zod8.z.object({
256
- depth_percent: import_zod8.z.number().int().min(1).max(100),
192
+ var phoneClickMetadataSchema = import_zod8.z.object({
193
+ phone_number: import_zod8.z.string(),
257
194
  page: import_zod8.z.object({
258
195
  path: import_zod8.z.string()
196
+ }).strict(),
197
+ section: import_zod8.z.string().nullable().optional()
198
+ }).strict();
199
+ var phoneClickConfigSchema = import_zod8.z.object({}).strict();
200
+
201
+ // ../tracking-core/src/events/scroll-depth.ts
202
+ var import_zod9 = require("zod");
203
+ var scrollDepthMetadataSchema = import_zod9.z.object({
204
+ depth_percent: import_zod9.z.number().int().min(1).max(100),
205
+ page: import_zod9.z.object({
206
+ path: import_zod9.z.string()
259
207
  }).strict()
260
208
  }).strict();
261
- var scrollDepthConfigSchema = import_zod8.z.object({
262
- thresholds: import_zod8.z.array(import_zod8.z.number().int().min(1).max(100)).min(1)
209
+ var scrollDepthConfigSchema = import_zod9.z.object({
210
+ thresholds: import_zod9.z.array(import_zod9.z.number().int().min(1).max(100)).min(1)
263
211
  }).strict();
264
212
 
265
213
  // ../tracking-core/src/events/specific-page-visit.ts
266
- var import_zod9 = require("zod");
214
+ var import_zod10 = require("zod");
267
215
  var SPECIFIC_PAGE_NAMES = [
268
216
  "contact_page",
269
217
  "about_page",
@@ -274,18 +222,18 @@ var SPECIFIC_PAGE_NAMES = [
274
222
  "faq_page",
275
223
  "testimonials_page"
276
224
  ];
277
- var specificPageNameSchema = import_zod9.z.enum(SPECIFIC_PAGE_NAMES);
278
- var specificPageVisitMetadataSchema = import_zod9.z.object({
225
+ var specificPageNameSchema = import_zod10.z.enum(SPECIFIC_PAGE_NAMES);
226
+ var specificPageVisitMetadataSchema = import_zod10.z.object({
279
227
  page_name: specificPageNameSchema,
280
- page: import_zod9.z.object({
281
- path: import_zod9.z.string()
228
+ page: import_zod10.z.object({
229
+ path: import_zod10.z.string()
282
230
  }).strict()
283
231
  }).strict();
284
- var specificPageVisitConfigSchema = import_zod9.z.object({
285
- pages: import_zod9.z.array(
286
- import_zod9.z.object({
232
+ var specificPageVisitConfigSchema = import_zod10.z.object({
233
+ pages: import_zod10.z.array(
234
+ import_zod10.z.object({
287
235
  name: specificPageNameSchema,
288
- pathPattern: import_zod9.z.custom((value) => value instanceof RegExp, {
236
+ pathPattern: import_zod10.z.custom((value) => value instanceof RegExp, {
289
237
  message: "pathPattern must be a RegExp"
290
238
  })
291
239
  }).strict()
@@ -293,15 +241,15 @@ var specificPageVisitConfigSchema = import_zod9.z.object({
293
241
  }).strict();
294
242
 
295
243
  // ../tracking-core/src/events/time-on-site.ts
296
- var import_zod10 = require("zod");
297
- var timeOnSiteMetadataSchema = import_zod10.z.object({
298
- duration_ms: import_zod10.z.number().int().nonnegative(),
299
- page: import_zod10.z.object({
300
- path: import_zod10.z.string()
244
+ var import_zod11 = require("zod");
245
+ var timeOnSiteMetadataSchema = import_zod11.z.object({
246
+ duration_ms: import_zod11.z.number().int().nonnegative(),
247
+ page: import_zod11.z.object({
248
+ path: import_zod11.z.string()
301
249
  }).strict()
302
250
  }).strict();
303
- var timeOnSiteConfigSchema = import_zod10.z.object({
304
- thresholdSeconds: import_zod10.z.number().int().positive()
251
+ var timeOnSiteConfigSchema = import_zod11.z.object({
252
+ thresholdSeconds: import_zod11.z.number().int().positive()
305
253
  }).strict();
306
254
 
307
255
  // ../tracking-core/src/events/registry.ts
@@ -343,6 +291,11 @@ var EVENT_REGISTRY = {
343
291
  metadataSchema: sdkHeartbeatMetadataSchema,
344
292
  configSchema: sdkHeartbeatConfigSchema
345
293
  },
294
+ page_exit: {
295
+ kind: "automatic",
296
+ metadataSchema: pageExitMetadataSchema,
297
+ configSchema: pageExitConfigSchema
298
+ },
346
299
  // --- manual triggers ---
347
300
  form_submit: {
348
301
  kind: "manual",
@@ -364,42 +317,42 @@ var ALL_AUTOMATIC_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def])
364
317
  var ALL_MANUAL_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.kind === "manual").map(([name]) => name);
365
318
 
366
319
  // ../tracking-core/src/resources/sales/schema.ts
367
- var import_zod11 = require("zod");
320
+ var import_zod12 = require("zod");
368
321
  var SUPPORTED_CURRENCIES = ["USD", "CAD"];
369
322
  var TRACKING_ENVIRONMENTS = ["production", "development"];
370
- var currencySchema = import_zod11.z.enum(SUPPORTED_CURRENCIES);
371
- var centsSchema = import_zod11.z.number().int().nonnegative();
372
- var quantitySchema = import_zod11.z.string().regex(/^\d+(\.\d{1,3})?$/);
373
- var metadataSchema = import_zod11.z.record(import_zod11.z.unknown());
374
- var saleItemSchema = import_zod11.z.object({
375
- external_item_id: import_zod11.z.string().nullable().optional(),
376
- name: import_zod11.z.string().nullable().optional(),
377
- category: import_zod11.z.string().nullable().optional(),
323
+ var currencySchema = import_zod12.z.enum(SUPPORTED_CURRENCIES);
324
+ var centsSchema = import_zod12.z.number().int().nonnegative();
325
+ var quantitySchema = import_zod12.z.string().regex(/^\d+(\.\d{1,3})?$/);
326
+ var metadataSchema = import_zod12.z.record(import_zod12.z.unknown());
327
+ var saleItemSchema = import_zod12.z.object({
328
+ external_item_id: import_zod12.z.string().nullable().optional(),
329
+ name: import_zod12.z.string().nullable().optional(),
330
+ category: import_zod12.z.string().nullable().optional(),
378
331
  quantity: quantitySchema,
379
332
  unit_price_cents: centsSchema,
380
333
  // Non-negativity validated on the wire — same contract as the other cents
381
334
  // fields — and backstopped by the DB CHECK.
382
335
  unit_cost_cents: centsSchema.nullable().optional()
383
336
  }).strict();
384
- var saleServiceSchema = import_zod11.z.object({
385
- service: import_zod11.z.string(),
337
+ var saleServiceSchema = import_zod12.z.object({
338
+ service: import_zod12.z.string(),
386
339
  amount_cents: centsSchema
387
340
  }).strict();
388
- var customerNameSchema = import_zod11.z.string().max(200);
389
- var customerPhoneSchema = import_zod11.z.string().max(64);
390
- var customerEmailSchema = import_zod11.z.string().max(320).email();
341
+ var customerNameSchema = import_zod12.z.string().max(200);
342
+ var customerPhoneSchema = import_zod12.z.string().max(64);
343
+ var customerEmailSchema = import_zod12.z.string().max(320).email();
391
344
  function refineServiceXor(val, ctx, { requireAmount }) {
392
345
  if (val.services != null) {
393
346
  if (val.service != null) {
394
347
  ctx.addIssue({
395
- code: import_zod11.z.ZodIssueCode.custom,
348
+ code: import_zod12.z.ZodIssueCode.custom,
396
349
  message: "pass either `service` or `services`, not both",
397
350
  path: ["services"]
398
351
  });
399
352
  }
400
353
  if (val.services.length === 0) {
401
354
  ctx.addIssue({
402
- code: import_zod11.z.ZodIssueCode.custom,
355
+ code: import_zod12.z.ZodIssueCode.custom,
403
356
  message: "`services` must not be empty",
404
357
  path: ["services"]
405
358
  });
@@ -407,7 +360,7 @@ function refineServiceXor(val, ctx, { requireAmount }) {
407
360
  const keys = val.services.map((s) => s.service);
408
361
  if (new Set(keys).size !== keys.length) {
409
362
  ctx.addIssue({
410
- code: import_zod11.z.ZodIssueCode.custom,
363
+ code: import_zod12.z.ZodIssueCode.custom,
411
364
  message: "`services` must not list the same service more than once",
412
365
  path: ["services"]
413
366
  });
@@ -416,7 +369,7 @@ function refineServiceXor(val, ctx, { requireAmount }) {
416
369
  const sum = val.services.reduce((acc, s) => acc + s.amount_cents, 0);
417
370
  if (val.amount_total_cents !== sum) {
418
371
  ctx.addIssue({
419
- code: import_zod11.z.ZodIssueCode.custom,
372
+ code: import_zod12.z.ZodIssueCode.custom,
420
373
  message: "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)",
421
374
  path: ["amount_total_cents"]
422
375
  });
@@ -424,37 +377,37 @@ function refineServiceXor(val, ctx, { requireAmount }) {
424
377
  }
425
378
  } else if (requireAmount && val.amount_total_cents == null) {
426
379
  ctx.addIssue({
427
- code: import_zod11.z.ZodIssueCode.custom,
380
+ code: import_zod12.z.ZodIssueCode.custom,
428
381
  message: "amount_total_cents is required unless `services` is provided",
429
382
  path: ["amount_total_cents"]
430
383
  });
431
384
  }
432
385
  }
433
- var saleCreateSchema = import_zod11.z.object({
434
- external_id: import_zod11.z.string().nullable().optional(),
435
- description: import_zod11.z.string().nullable().optional(),
436
- service: import_zod11.z.string().nullable().optional(),
437
- services: import_zod11.z.array(saleServiceSchema).nullable().optional(),
386
+ var saleCreateSchema = import_zod12.z.object({
387
+ external_id: import_zod12.z.string().nullable().optional(),
388
+ description: import_zod12.z.string().nullable().optional(),
389
+ service: import_zod12.z.string().nullable().optional(),
390
+ services: import_zod12.z.array(saleServiceSchema).nullable().optional(),
438
391
  currency: currencySchema,
439
392
  // Optional only because the plural `services` form derives it from the sum
440
393
  // (see refineServiceXor); the singular/serviceless path still requires it.
441
394
  amount_total_cents: centsSchema.nullable().optional(),
442
- occurred_at: import_zod11.z.string().datetime(),
443
- environment: import_zod11.z.enum(TRACKING_ENVIRONMENTS).default("production"),
444
- items: import_zod11.z.array(saleItemSchema).default([]),
395
+ occurred_at: import_zod12.z.string().datetime(),
396
+ environment: import_zod12.z.enum(TRACKING_ENVIRONMENTS).default("production"),
397
+ items: import_zod12.z.array(saleItemSchema).default([]),
445
398
  metadata: metadataSchema.nullable().optional(),
446
399
  customer_name: customerNameSchema.nullable().optional(),
447
400
  customer_phone: customerPhoneSchema.nullable().optional(),
448
401
  customer_email: customerEmailSchema.nullable().optional()
449
402
  }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: true }));
450
- var saleUpdateSchema = import_zod11.z.object({
451
- description: import_zod11.z.string().nullable().optional(),
452
- service: import_zod11.z.string().nullable().optional(),
453
- services: import_zod11.z.array(saleServiceSchema).nullable().optional(),
403
+ var saleUpdateSchema = import_zod12.z.object({
404
+ description: import_zod12.z.string().nullable().optional(),
405
+ service: import_zod12.z.string().nullable().optional(),
406
+ services: import_zod12.z.array(saleServiceSchema).nullable().optional(),
454
407
  currency: currencySchema.optional(),
455
408
  amount_total_cents: centsSchema.optional(),
456
- occurred_at: import_zod11.z.string().datetime().optional(),
457
- items: import_zod11.z.array(saleItemSchema).optional(),
409
+ occurred_at: import_zod12.z.string().datetime().optional(),
410
+ items: import_zod12.z.array(saleItemSchema).optional(),
458
411
  metadata: metadataSchema.nullable().optional(),
459
412
  customer_name: customerNameSchema.nullable().optional(),
460
413
  customer_phone: customerPhoneSchema.nullable().optional(),