@aranova/tracking-react 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
@@ -267,7 +267,7 @@ function getVisitorId() {
267
267
  }
268
268
  function getOrRotateSessionId(now = Date.now()) {
269
269
  if (typeof window === "undefined")
270
- return safeUuid();
270
+ return { id: safeUuid(), isNew: true };
271
271
  const raw = readLocalStorage(SESSION_STORAGE_KEY);
272
272
  if (raw) {
273
273
  try {
@@ -276,7 +276,7 @@ function getOrRotateSessionId(now = Date.now()) {
276
276
  if (now - parsed.last_event_at <= SESSION_IDLE_MS) {
277
277
  const refreshed = { id: parsed.id, last_event_at: now };
278
278
  writeLocalStorage(SESSION_STORAGE_KEY, JSON.stringify(refreshed));
279
- return parsed.id;
279
+ return { id: parsed.id, isNew: false };
280
280
  }
281
281
  }
282
282
  } catch {
@@ -284,7 +284,7 @@ function getOrRotateSessionId(now = Date.now()) {
284
284
  }
285
285
  const fresh = { id: safeUuid(), last_event_at: now };
286
286
  writeLocalStorage(SESSION_STORAGE_KEY, JSON.stringify(fresh));
287
- return fresh.id;
287
+ return { id: fresh.id, isNew: true };
288
288
  }
289
289
 
290
290
  // ../tracking-core/src/events/page-view.ts
@@ -424,6 +424,56 @@ function attachAutoPageView(client, options = {}) {
424
424
  };
425
425
  }
426
426
 
427
+ // ../tracking-core/src/heartbeat.ts
428
+ function serializeValue(value) {
429
+ if (value instanceof RegExp) return value.source;
430
+ if (Array.isArray(value)) return value.map(serializeValue);
431
+ if (value !== null && typeof value === "object") {
432
+ const out = {};
433
+ for (const [k, v] of Object.entries(value)) {
434
+ out[k] = serializeValue(v);
435
+ }
436
+ return out;
437
+ }
438
+ return value;
439
+ }
440
+ function buildHeartbeatMetadata(surface, sdkVersion, packageName, triggers) {
441
+ const automaticNames = triggers ? Object.keys(triggers.automatic) : [];
442
+ const manualNames = triggers?.manual ? Object.keys(triggers.manual) : [];
443
+ let triggerConfig = null;
444
+ if (triggers) {
445
+ const cfg = {};
446
+ for (const [name, config] of Object.entries(triggers.automatic)) {
447
+ const serialized = serializeValue(config);
448
+ if (Object.keys(serialized).length > 0) {
449
+ cfg[name] = serialized;
450
+ }
451
+ }
452
+ if (triggers.manual) {
453
+ for (const [name, config] of Object.entries(triggers.manual)) {
454
+ if (config === void 0) continue;
455
+ const serialized = serializeValue(config);
456
+ if (Object.keys(serialized).length > 0) {
457
+ cfg[name] = serialized;
458
+ }
459
+ }
460
+ }
461
+ if (Object.keys(cfg).length > 0) {
462
+ triggerConfig = cfg;
463
+ }
464
+ }
465
+ return {
466
+ sdk_version: sdkVersion ?? "unknown",
467
+ package_name: packageName,
468
+ surface,
469
+ triggers: {
470
+ automatic: automaticNames,
471
+ manual: manualNames
472
+ },
473
+ trigger_config: triggerConfig
474
+ };
475
+ }
476
+
427
477
  // ../tracking-core/src/ingest.ts
428
478
  var DEFAULT_FLUSH_INTERVAL_MS = 2e3;
429
479
  var DEFAULT_MAX_QUEUE_SIZE = 10;
@@ -503,11 +553,33 @@ function createTrackingClient(config) {
503
553
  let firstPage = null;
504
554
  let destroyed = false;
505
555
  const visitorId = getVisitorId();
506
- let sessionId = getOrRotateSessionId();
556
+ const initialSession = getOrRotateSessionId();
557
+ let sessionId = initialSession.id;
507
558
  if (typeof window !== "undefined")
508
559
  firstPage = window.location.href;
560
+ function enqueueHeartbeat() {
561
+ const metadata = buildHeartbeatMetadata(
562
+ config.surface,
563
+ sdkVersion,
564
+ packageName,
565
+ config.triggers ?? null
566
+ );
567
+ queue.push({
568
+ event_type: "sdk_heartbeat",
569
+ page_url: typeof window === "undefined" ? null : window.location.href,
570
+ metadata,
571
+ occurred_at: (/* @__PURE__ */ new Date()).toISOString()
572
+ });
573
+ }
574
+ if (initialSession.isNew) {
575
+ enqueueHeartbeat();
576
+ }
509
577
  function buildSessionPayload() {
510
- sessionId = getOrRotateSessionId();
578
+ const rotated = getOrRotateSessionId();
579
+ if (rotated.isNew && rotated.id !== sessionId) {
580
+ enqueueHeartbeat();
581
+ }
582
+ sessionId = rotated.id;
511
583
  const params = readTrackingParams();
512
584
  const context = buildContext(config.surface, sdkVersion, packageName);
513
585
  return {
@@ -620,79 +692,94 @@ var ctaClickMetadataSchema = import_zod2.z.object({
620
692
  }).strict();
621
693
  var ctaClickConfigSchema = import_zod2.z.object({}).strict();
622
694
 
623
- // ../tracking-core/src/events/form-start.ts
695
+ // ../tracking-core/src/events/sdk-heartbeat.ts
624
696
  var import_zod3 = require("zod");
625
- var formStartMetadataSchema = import_zod3.z.object({
626
- form: import_zod3.z.object({
627
- id: import_zod3.z.string(),
628
- action: import_zod3.z.string().nullable()
629
- }),
630
- page: import_zod3.z.object({
631
- path: import_zod3.z.string()
632
- })
697
+ var sdkHeartbeatTriggersSchema = import_zod3.z.object({
698
+ automatic: import_zod3.z.array(import_zod3.z.string()),
699
+ manual: import_zod3.z.array(import_zod3.z.string())
633
700
  }).strict();
634
- var formStartConfigSchema = import_zod3.z.object({
635
- selector: import_zod3.z.string().optional()
701
+ var sdkHeartbeatMetadataSchema = import_zod3.z.object({
702
+ sdk_version: import_zod3.z.string(),
703
+ package_name: import_zod3.z.string().nullable(),
704
+ surface: import_zod3.z.enum(["next", "react", "script"]),
705
+ triggers: sdkHeartbeatTriggersSchema,
706
+ trigger_config: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown())).nullable().optional()
636
707
  }).strict();
708
+ var sdkHeartbeatConfigSchema = import_zod3.z.object({}).strict();
637
709
 
638
- // ../tracking-core/src/events/form-submit.ts
710
+ // ../tracking-core/src/events/form-start.ts
639
711
  var import_zod4 = require("zod");
640
- var formSubmitMetadataSchema = import_zod4.z.object({
712
+ var formStartMetadataSchema = import_zod4.z.object({
641
713
  form: import_zod4.z.object({
642
714
  id: import_zod4.z.string(),
643
- action: import_zod4.z.string().nullable(),
644
- fields: import_zod4.z.array(
645
- import_zod4.z.object({
646
- name: import_zod4.z.string(),
647
- type: import_zod4.z.string(),
648
- label: import_zod4.z.string().nullable(),
649
- has_value: import_zod4.z.boolean()
650
- })
651
- ).optional()
715
+ action: import_zod4.z.string().nullable()
652
716
  }),
653
717
  page: import_zod4.z.object({
654
718
  path: import_zod4.z.string()
655
719
  })
656
720
  }).strict();
657
- var formSubmitConfigSchema = import_zod4.z.object({}).strict();
721
+ var formStartConfigSchema = import_zod4.z.object({
722
+ selector: import_zod4.z.string().optional()
723
+ }).strict();
658
724
 
659
- // ../tracking-core/src/events/multi-page-session.ts
725
+ // ../tracking-core/src/events/form-submit.ts
660
726
  var import_zod5 = require("zod");
661
- var multiPageSessionMetadataSchema = import_zod5.z.object({
662
- page_count: import_zod5.z.number().int().min(2),
727
+ var formSubmitMetadataSchema = import_zod5.z.object({
728
+ form: import_zod5.z.object({
729
+ id: import_zod5.z.string(),
730
+ action: import_zod5.z.string().nullable(),
731
+ fields: import_zod5.z.array(
732
+ import_zod5.z.object({
733
+ name: import_zod5.z.string(),
734
+ type: import_zod5.z.string(),
735
+ label: import_zod5.z.string().nullable(),
736
+ has_value: import_zod5.z.boolean()
737
+ })
738
+ ).optional()
739
+ }),
663
740
  page: import_zod5.z.object({
664
741
  path: import_zod5.z.string()
665
742
  })
666
743
  }).strict();
667
- var multiPageSessionConfigSchema = import_zod5.z.object({
668
- pageThreshold: import_zod5.z.number().int().min(2)
669
- }).strict();
744
+ var formSubmitConfigSchema = import_zod5.z.object({}).strict();
670
745
 
671
- // ../tracking-core/src/events/phone-click.ts
746
+ // ../tracking-core/src/events/multi-page-session.ts
672
747
  var import_zod6 = require("zod");
673
- var phoneClickMetadataSchema = import_zod6.z.object({
674
- phone_number: import_zod6.z.string(),
748
+ var multiPageSessionMetadataSchema = import_zod6.z.object({
749
+ page_count: import_zod6.z.number().int().min(2),
675
750
  page: import_zod6.z.object({
676
751
  path: import_zod6.z.string()
677
- }),
678
- section: import_zod6.z.string().nullable().optional()
752
+ })
753
+ }).strict();
754
+ var multiPageSessionConfigSchema = import_zod6.z.object({
755
+ pageThreshold: import_zod6.z.number().int().min(2)
679
756
  }).strict();
680
- var phoneClickConfigSchema = import_zod6.z.object({}).strict();
681
757
 
682
- // ../tracking-core/src/events/scroll-depth.ts
758
+ // ../tracking-core/src/events/phone-click.ts
683
759
  var import_zod7 = require("zod");
684
- var scrollDepthMetadataSchema = import_zod7.z.object({
685
- depth_percent: import_zod7.z.number().int().min(1).max(100),
760
+ var phoneClickMetadataSchema = import_zod7.z.object({
761
+ phone_number: import_zod7.z.string(),
686
762
  page: import_zod7.z.object({
687
763
  path: import_zod7.z.string()
764
+ }),
765
+ section: import_zod7.z.string().nullable().optional()
766
+ }).strict();
767
+ var phoneClickConfigSchema = import_zod7.z.object({}).strict();
768
+
769
+ // ../tracking-core/src/events/scroll-depth.ts
770
+ var import_zod8 = require("zod");
771
+ var scrollDepthMetadataSchema = import_zod8.z.object({
772
+ depth_percent: import_zod8.z.number().int().min(1).max(100),
773
+ page: import_zod8.z.object({
774
+ path: import_zod8.z.string()
688
775
  })
689
776
  }).strict();
690
- var scrollDepthConfigSchema = import_zod7.z.object({
691
- thresholds: import_zod7.z.array(import_zod7.z.number().int().min(1).max(100)).min(1)
777
+ var scrollDepthConfigSchema = import_zod8.z.object({
778
+ thresholds: import_zod8.z.array(import_zod8.z.number().int().min(1).max(100)).min(1)
692
779
  }).strict();
693
780
 
694
781
  // ../tracking-core/src/events/specific-page-visit.ts
695
- var import_zod8 = require("zod");
782
+ var import_zod9 = require("zod");
696
783
  var SPECIFIC_PAGE_NAMES = [
697
784
  "contact_page",
698
785
  "about_page",
@@ -703,18 +790,18 @@ var SPECIFIC_PAGE_NAMES = [
703
790
  "faq_page",
704
791
  "testimonials_page"
705
792
  ];
706
- var specificPageNameSchema = import_zod8.z.enum(SPECIFIC_PAGE_NAMES);
707
- var specificPageVisitMetadataSchema = import_zod8.z.object({
793
+ var specificPageNameSchema = import_zod9.z.enum(SPECIFIC_PAGE_NAMES);
794
+ var specificPageVisitMetadataSchema = import_zod9.z.object({
708
795
  page_name: specificPageNameSchema,
709
- page: import_zod8.z.object({
710
- path: import_zod8.z.string()
796
+ page: import_zod9.z.object({
797
+ path: import_zod9.z.string()
711
798
  })
712
799
  }).strict();
713
- var specificPageVisitConfigSchema = import_zod8.z.object({
714
- pages: import_zod8.z.array(
715
- import_zod8.z.object({
800
+ var specificPageVisitConfigSchema = import_zod9.z.object({
801
+ pages: import_zod9.z.array(
802
+ import_zod9.z.object({
716
803
  name: specificPageNameSchema,
717
- pathPattern: import_zod8.z.custom((value) => value instanceof RegExp, {
804
+ pathPattern: import_zod9.z.custom((value) => value instanceof RegExp, {
718
805
  message: "pathPattern must be a RegExp"
719
806
  })
720
807
  })
@@ -722,15 +809,15 @@ var specificPageVisitConfigSchema = import_zod8.z.object({
722
809
  }).strict();
723
810
 
724
811
  // ../tracking-core/src/events/time-on-site.ts
725
- var import_zod9 = require("zod");
726
- var timeOnSiteMetadataSchema = import_zod9.z.object({
727
- duration_ms: import_zod9.z.number().int().nonnegative(),
728
- page: import_zod9.z.object({
729
- path: import_zod9.z.string()
812
+ var import_zod10 = require("zod");
813
+ var timeOnSiteMetadataSchema = import_zod10.z.object({
814
+ duration_ms: import_zod10.z.number().int().nonnegative(),
815
+ page: import_zod10.z.object({
816
+ path: import_zod10.z.string()
730
817
  })
731
818
  }).strict();
732
- var timeOnSiteConfigSchema = import_zod9.z.object({
733
- thresholdSeconds: import_zod9.z.number().int().positive()
819
+ var timeOnSiteConfigSchema = import_zod10.z.object({
820
+ thresholdSeconds: import_zod10.z.number().int().positive()
734
821
  }).strict();
735
822
 
736
823
  // ../tracking-core/src/events/registry.ts
@@ -766,6 +853,12 @@ var EVENT_REGISTRY = {
766
853
  metadataSchema: formStartMetadataSchema,
767
854
  configSchema: formStartConfigSchema
768
855
  },
856
+ // --- SDK-internal automatic (not consumer-configurable) ---
857
+ sdk_heartbeat: {
858
+ kind: "automatic",
859
+ metadataSchema: sdkHeartbeatMetadataSchema,
860
+ configSchema: sdkHeartbeatConfigSchema
861
+ },
769
862
  // --- manual triggers ---
770
863
  form_submit: {
771
864
  kind: "manual",
@@ -1025,7 +1118,7 @@ function attachMultiPageSession(client, config) {
1025
1118
  }
1026
1119
  }
1027
1120
  function resetIfSessionChanged() {
1028
- const currentSession = getOrRotateSessionId();
1121
+ const currentSession = getOrRotateSessionId().id;
1029
1122
  const storedSession = storage.getItem(SESSION_KEY);
1030
1123
  if (storedSession !== currentSession) {
1031
1124
  storage.setItem(SESSION_KEY, currentSession);
@@ -1233,7 +1326,7 @@ function useConsentState() {
1233
1326
  var import_react4 = require("react");
1234
1327
 
1235
1328
  // package.json
1236
- var version = "0.5.0";
1329
+ var version = "0.5.1";
1237
1330
 
1238
1331
  // src/factory.tsx
1239
1332
  var import_jsx_runtime2 = require("react/jsx-runtime");
@@ -1269,6 +1362,7 @@ function createTracking(options) {
1269
1362
  surface: "react",
1270
1363
  packageName: "@aranova/tracking-react",
1271
1364
  sdkVersion: version,
1365
+ triggers,
1272
1366
  debug
1273
1367
  }),
1274
1368
  triggers,
@@ -1287,6 +1381,7 @@ function createTracking(options) {
1287
1381
  endpoint,
1288
1382
  surface: "react",
1289
1383
  packageName: "@aranova/tracking-react",
1384
+ triggers,
1290
1385
  debug
1291
1386
  });
1292
1387
  detachers.push(attachAutoPageView(rawClient));