@aranova/tracking-next 0.5.0 → 0.5.1

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.js CHANGED
@@ -254,7 +254,7 @@ function getVisitorId() {
254
254
  }
255
255
  function getOrRotateSessionId(now = Date.now()) {
256
256
  if (typeof window === "undefined")
257
- return safeUuid();
257
+ return { id: safeUuid(), isNew: true };
258
258
  const raw = readLocalStorage(SESSION_STORAGE_KEY);
259
259
  if (raw) {
260
260
  try {
@@ -263,7 +263,7 @@ function getOrRotateSessionId(now = Date.now()) {
263
263
  if (now - parsed.last_event_at <= SESSION_IDLE_MS) {
264
264
  const refreshed = { id: parsed.id, last_event_at: now };
265
265
  writeLocalStorage(SESSION_STORAGE_KEY, JSON.stringify(refreshed));
266
- return parsed.id;
266
+ return { id: parsed.id, isNew: false };
267
267
  }
268
268
  }
269
269
  } catch {
@@ -271,7 +271,7 @@ function getOrRotateSessionId(now = Date.now()) {
271
271
  }
272
272
  const fresh = { id: safeUuid(), last_event_at: now };
273
273
  writeLocalStorage(SESSION_STORAGE_KEY, JSON.stringify(fresh));
274
- return fresh.id;
274
+ return { id: fresh.id, isNew: true };
275
275
  }
276
276
 
277
277
  // ../tracking-core/src/events/page-view.ts
@@ -371,6 +371,56 @@ function attachBfcacheRestore(client) {
371
371
  };
372
372
  }
373
373
 
374
+ // ../tracking-core/src/heartbeat.ts
375
+ function serializeValue(value) {
376
+ if (value instanceof RegExp) return value.source;
377
+ if (Array.isArray(value)) return value.map(serializeValue);
378
+ if (value !== null && typeof value === "object") {
379
+ const out = {};
380
+ for (const [k, v] of Object.entries(value)) {
381
+ out[k] = serializeValue(v);
382
+ }
383
+ return out;
384
+ }
385
+ return value;
386
+ }
387
+ function buildHeartbeatMetadata(surface, sdkVersion, packageName, triggers) {
388
+ const automaticNames = triggers ? Object.keys(triggers.automatic) : [];
389
+ const manualNames = triggers?.manual ? Object.keys(triggers.manual) : [];
390
+ let triggerConfig = null;
391
+ if (triggers) {
392
+ const cfg = {};
393
+ for (const [name, config] of Object.entries(triggers.automatic)) {
394
+ const serialized = serializeValue(config);
395
+ if (Object.keys(serialized).length > 0) {
396
+ cfg[name] = serialized;
397
+ }
398
+ }
399
+ if (triggers.manual) {
400
+ for (const [name, config] of Object.entries(triggers.manual)) {
401
+ if (config === void 0) continue;
402
+ const serialized = serializeValue(config);
403
+ if (Object.keys(serialized).length > 0) {
404
+ cfg[name] = serialized;
405
+ }
406
+ }
407
+ }
408
+ if (Object.keys(cfg).length > 0) {
409
+ triggerConfig = cfg;
410
+ }
411
+ }
412
+ return {
413
+ sdk_version: sdkVersion ?? "unknown",
414
+ package_name: packageName,
415
+ surface,
416
+ triggers: {
417
+ automatic: automaticNames,
418
+ manual: manualNames
419
+ },
420
+ trigger_config: triggerConfig
421
+ };
422
+ }
423
+
374
424
  // ../tracking-core/src/ingest.ts
375
425
  var DEFAULT_FLUSH_INTERVAL_MS = 2e3;
376
426
  var DEFAULT_MAX_QUEUE_SIZE = 10;
@@ -450,11 +500,33 @@ function createTrackingClient(config) {
450
500
  let firstPage = null;
451
501
  let destroyed = false;
452
502
  const visitorId = getVisitorId();
453
- let sessionId = getOrRotateSessionId();
503
+ const initialSession = getOrRotateSessionId();
504
+ let sessionId = initialSession.id;
454
505
  if (typeof window !== "undefined")
455
506
  firstPage = window.location.href;
507
+ function enqueueHeartbeat() {
508
+ const metadata = buildHeartbeatMetadata(
509
+ config.surface,
510
+ sdkVersion,
511
+ packageName,
512
+ config.triggers ?? null
513
+ );
514
+ queue.push({
515
+ event_type: "sdk_heartbeat",
516
+ page_url: typeof window === "undefined" ? null : window.location.href,
517
+ metadata,
518
+ occurred_at: (/* @__PURE__ */ new Date()).toISOString()
519
+ });
520
+ }
521
+ if (initialSession.isNew) {
522
+ enqueueHeartbeat();
523
+ }
456
524
  function buildSessionPayload() {
457
- sessionId = getOrRotateSessionId();
525
+ const rotated = getOrRotateSessionId();
526
+ if (rotated.isNew && rotated.id !== sessionId) {
527
+ enqueueHeartbeat();
528
+ }
529
+ sessionId = rotated.id;
458
530
  const params = readTrackingParams();
459
531
  const context = buildContext(config.surface, sdkVersion, packageName);
460
532
  return {
@@ -567,79 +639,94 @@ var ctaClickMetadataSchema = import_zod2.z.object({
567
639
  }).strict();
568
640
  var ctaClickConfigSchema = import_zod2.z.object({}).strict();
569
641
 
570
- // ../tracking-core/src/events/form-start.ts
642
+ // ../tracking-core/src/events/sdk-heartbeat.ts
571
643
  var import_zod3 = require("zod");
572
- var formStartMetadataSchema = import_zod3.z.object({
573
- form: import_zod3.z.object({
574
- id: import_zod3.z.string(),
575
- action: import_zod3.z.string().nullable()
576
- }),
577
- page: import_zod3.z.object({
578
- path: import_zod3.z.string()
579
- })
644
+ var sdkHeartbeatTriggersSchema = import_zod3.z.object({
645
+ automatic: import_zod3.z.array(import_zod3.z.string()),
646
+ manual: import_zod3.z.array(import_zod3.z.string())
580
647
  }).strict();
581
- var formStartConfigSchema = import_zod3.z.object({
582
- selector: import_zod3.z.string().optional()
648
+ var sdkHeartbeatMetadataSchema = import_zod3.z.object({
649
+ sdk_version: import_zod3.z.string(),
650
+ package_name: import_zod3.z.string().nullable(),
651
+ surface: import_zod3.z.enum(["next", "react", "script"]),
652
+ triggers: sdkHeartbeatTriggersSchema,
653
+ trigger_config: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown())).nullable().optional()
583
654
  }).strict();
655
+ var sdkHeartbeatConfigSchema = import_zod3.z.object({}).strict();
584
656
 
585
- // ../tracking-core/src/events/form-submit.ts
657
+ // ../tracking-core/src/events/form-start.ts
586
658
  var import_zod4 = require("zod");
587
- var formSubmitMetadataSchema = import_zod4.z.object({
659
+ var formStartMetadataSchema = import_zod4.z.object({
588
660
  form: import_zod4.z.object({
589
661
  id: import_zod4.z.string(),
590
- action: import_zod4.z.string().nullable(),
591
- fields: import_zod4.z.array(
592
- import_zod4.z.object({
593
- name: import_zod4.z.string(),
594
- type: import_zod4.z.string(),
595
- label: import_zod4.z.string().nullable(),
596
- has_value: import_zod4.z.boolean()
597
- })
598
- ).optional()
662
+ action: import_zod4.z.string().nullable()
599
663
  }),
600
664
  page: import_zod4.z.object({
601
665
  path: import_zod4.z.string()
602
666
  })
603
667
  }).strict();
604
- var formSubmitConfigSchema = import_zod4.z.object({}).strict();
668
+ var formStartConfigSchema = import_zod4.z.object({
669
+ selector: import_zod4.z.string().optional()
670
+ }).strict();
605
671
 
606
- // ../tracking-core/src/events/multi-page-session.ts
672
+ // ../tracking-core/src/events/form-submit.ts
607
673
  var import_zod5 = require("zod");
608
- var multiPageSessionMetadataSchema = import_zod5.z.object({
609
- page_count: import_zod5.z.number().int().min(2),
674
+ var formSubmitMetadataSchema = import_zod5.z.object({
675
+ form: import_zod5.z.object({
676
+ id: import_zod5.z.string(),
677
+ action: import_zod5.z.string().nullable(),
678
+ fields: import_zod5.z.array(
679
+ import_zod5.z.object({
680
+ name: import_zod5.z.string(),
681
+ type: import_zod5.z.string(),
682
+ label: import_zod5.z.string().nullable(),
683
+ has_value: import_zod5.z.boolean()
684
+ })
685
+ ).optional()
686
+ }),
610
687
  page: import_zod5.z.object({
611
688
  path: import_zod5.z.string()
612
689
  })
613
690
  }).strict();
614
- var multiPageSessionConfigSchema = import_zod5.z.object({
615
- pageThreshold: import_zod5.z.number().int().min(2)
616
- }).strict();
691
+ var formSubmitConfigSchema = import_zod5.z.object({}).strict();
617
692
 
618
- // ../tracking-core/src/events/phone-click.ts
693
+ // ../tracking-core/src/events/multi-page-session.ts
619
694
  var import_zod6 = require("zod");
620
- var phoneClickMetadataSchema = import_zod6.z.object({
621
- phone_number: import_zod6.z.string(),
695
+ var multiPageSessionMetadataSchema = import_zod6.z.object({
696
+ page_count: import_zod6.z.number().int().min(2),
622
697
  page: import_zod6.z.object({
623
698
  path: import_zod6.z.string()
624
- }),
625
- section: import_zod6.z.string().nullable().optional()
699
+ })
700
+ }).strict();
701
+ var multiPageSessionConfigSchema = import_zod6.z.object({
702
+ pageThreshold: import_zod6.z.number().int().min(2)
626
703
  }).strict();
627
- var phoneClickConfigSchema = import_zod6.z.object({}).strict();
628
704
 
629
- // ../tracking-core/src/events/scroll-depth.ts
705
+ // ../tracking-core/src/events/phone-click.ts
630
706
  var import_zod7 = require("zod");
631
- var scrollDepthMetadataSchema = import_zod7.z.object({
632
- depth_percent: import_zod7.z.number().int().min(1).max(100),
707
+ var phoneClickMetadataSchema = import_zod7.z.object({
708
+ phone_number: import_zod7.z.string(),
633
709
  page: import_zod7.z.object({
634
710
  path: import_zod7.z.string()
711
+ }),
712
+ section: import_zod7.z.string().nullable().optional()
713
+ }).strict();
714
+ var phoneClickConfigSchema = import_zod7.z.object({}).strict();
715
+
716
+ // ../tracking-core/src/events/scroll-depth.ts
717
+ var import_zod8 = require("zod");
718
+ var scrollDepthMetadataSchema = import_zod8.z.object({
719
+ depth_percent: import_zod8.z.number().int().min(1).max(100),
720
+ page: import_zod8.z.object({
721
+ path: import_zod8.z.string()
635
722
  })
636
723
  }).strict();
637
- var scrollDepthConfigSchema = import_zod7.z.object({
638
- thresholds: import_zod7.z.array(import_zod7.z.number().int().min(1).max(100)).min(1)
724
+ var scrollDepthConfigSchema = import_zod8.z.object({
725
+ thresholds: import_zod8.z.array(import_zod8.z.number().int().min(1).max(100)).min(1)
639
726
  }).strict();
640
727
 
641
728
  // ../tracking-core/src/events/specific-page-visit.ts
642
- var import_zod8 = require("zod");
729
+ var import_zod9 = require("zod");
643
730
  var SPECIFIC_PAGE_NAMES = [
644
731
  "contact_page",
645
732
  "about_page",
@@ -650,18 +737,18 @@ var SPECIFIC_PAGE_NAMES = [
650
737
  "faq_page",
651
738
  "testimonials_page"
652
739
  ];
653
- var specificPageNameSchema = import_zod8.z.enum(SPECIFIC_PAGE_NAMES);
654
- var specificPageVisitMetadataSchema = import_zod8.z.object({
740
+ var specificPageNameSchema = import_zod9.z.enum(SPECIFIC_PAGE_NAMES);
741
+ var specificPageVisitMetadataSchema = import_zod9.z.object({
655
742
  page_name: specificPageNameSchema,
656
- page: import_zod8.z.object({
657
- path: import_zod8.z.string()
743
+ page: import_zod9.z.object({
744
+ path: import_zod9.z.string()
658
745
  })
659
746
  }).strict();
660
- var specificPageVisitConfigSchema = import_zod8.z.object({
661
- pages: import_zod8.z.array(
662
- import_zod8.z.object({
747
+ var specificPageVisitConfigSchema = import_zod9.z.object({
748
+ pages: import_zod9.z.array(
749
+ import_zod9.z.object({
663
750
  name: specificPageNameSchema,
664
- pathPattern: import_zod8.z.custom((value) => value instanceof RegExp, {
751
+ pathPattern: import_zod9.z.custom((value) => value instanceof RegExp, {
665
752
  message: "pathPattern must be a RegExp"
666
753
  })
667
754
  })
@@ -669,15 +756,15 @@ var specificPageVisitConfigSchema = import_zod8.z.object({
669
756
  }).strict();
670
757
 
671
758
  // ../tracking-core/src/events/time-on-site.ts
672
- var import_zod9 = require("zod");
673
- var timeOnSiteMetadataSchema = import_zod9.z.object({
674
- duration_ms: import_zod9.z.number().int().nonnegative(),
675
- page: import_zod9.z.object({
676
- path: import_zod9.z.string()
759
+ var import_zod10 = require("zod");
760
+ var timeOnSiteMetadataSchema = import_zod10.z.object({
761
+ duration_ms: import_zod10.z.number().int().nonnegative(),
762
+ page: import_zod10.z.object({
763
+ path: import_zod10.z.string()
677
764
  })
678
765
  }).strict();
679
- var timeOnSiteConfigSchema = import_zod9.z.object({
680
- thresholdSeconds: import_zod9.z.number().int().positive()
766
+ var timeOnSiteConfigSchema = import_zod10.z.object({
767
+ thresholdSeconds: import_zod10.z.number().int().positive()
681
768
  }).strict();
682
769
 
683
770
  // ../tracking-core/src/events/registry.ts
@@ -713,6 +800,12 @@ var EVENT_REGISTRY = {
713
800
  metadataSchema: formStartMetadataSchema,
714
801
  configSchema: formStartConfigSchema
715
802
  },
803
+ // --- SDK-internal automatic (not consumer-configurable) ---
804
+ sdk_heartbeat: {
805
+ kind: "automatic",
806
+ metadataSchema: sdkHeartbeatMetadataSchema,
807
+ configSchema: sdkHeartbeatConfigSchema
808
+ },
716
809
  // --- manual triggers ---
717
810
  form_submit: {
718
811
  kind: "manual",
@@ -1055,7 +1148,7 @@ function GoogleAdsTracking({ gtagId }) {
1055
1148
  var import_navigation = require("next/navigation");
1056
1149
 
1057
1150
  // package.json
1058
- var version = "0.5.0";
1151
+ var version = "0.5.1";
1059
1152
 
1060
1153
  // src/factory.tsx
1061
1154
  var import_react3 = require("react");
@@ -1095,6 +1188,7 @@ function createTracking(options) {
1095
1188
  surface: "next",
1096
1189
  packageName: "@aranova/tracking-next",
1097
1190
  sdkVersion: version,
1191
+ triggers,
1098
1192
  debug
1099
1193
  }),
1100
1194
  triggers,
@@ -1108,6 +1202,7 @@ function createTracking(options) {
1108
1202
  endpoint,
1109
1203
  surface: "next",
1110
1204
  packageName: "@aranova/tracking-next",
1205
+ triggers,
1111
1206
  debug
1112
1207
  });
1113
1208
  fireManualPageView(rawClient);
@@ -1120,6 +1215,7 @@ function createTracking(options) {
1120
1215
  endpoint,
1121
1216
  surface: "next",
1122
1217
  packageName: "@aranova/tracking-next",
1218
+ triggers,
1123
1219
  debug
1124
1220
  });
1125
1221
  for (const { name, pathPattern } of specificPageVisitConfig.pages) {
@@ -1141,6 +1237,7 @@ function createTracking(options) {
1141
1237
  endpoint,
1142
1238
  surface: "next",
1143
1239
  packageName: "@aranova/tracking-next",
1240
+ triggers,
1144
1241
  debug
1145
1242
  });
1146
1243
  return attachBfcacheRestore(rawClient);
@@ -1152,6 +1249,7 @@ function createTracking(options) {
1152
1249
  endpoint,
1153
1250
  surface: "next",
1154
1251
  packageName: "@aranova/tracking-next",
1252
+ triggers,
1155
1253
  debug
1156
1254
  });
1157
1255
  return attachTimeOnSite(rawClient, timeOnSiteConfig);
@@ -1167,7 +1265,7 @@ function createTracking(options) {
1167
1265
  const MPS_FIRED_KEY = "aranova_tracking_mps_fired";
1168
1266
  try {
1169
1267
  const store = window.sessionStorage;
1170
- const currentSession = getOrRotateSessionId();
1268
+ const currentSession = getOrRotateSessionId().id;
1171
1269
  const storedSession = store.getItem(MPS_SESSION_KEY);
1172
1270
  if (storedSession !== currentSession) {
1173
1271
  store.setItem(MPS_SESSION_KEY, currentSession);
@@ -1186,6 +1284,7 @@ function createTracking(options) {
1186
1284
  endpoint,
1187
1285
  surface: "next",
1188
1286
  packageName: "@aranova/tracking-next",
1287
+ triggers,
1189
1288
  debug
1190
1289
  });
1191
1290
  rawClient.trackEvent({
@@ -1208,6 +1307,7 @@ function createTracking(options) {
1208
1307
  endpoint,
1209
1308
  surface: "next",
1210
1309
  packageName: "@aranova/tracking-next",
1310
+ triggers,
1211
1311
  debug
1212
1312
  });
1213
1313
  const scrollDepth = triggers.automatic.scroll_depth;