@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.mjs CHANGED
@@ -229,7 +229,7 @@ function getVisitorId() {
229
229
  }
230
230
  function getOrRotateSessionId(now = Date.now()) {
231
231
  if (typeof window === "undefined")
232
- return safeUuid();
232
+ return { id: safeUuid(), isNew: true };
233
233
  const raw = readLocalStorage(SESSION_STORAGE_KEY);
234
234
  if (raw) {
235
235
  try {
@@ -238,7 +238,7 @@ function getOrRotateSessionId(now = Date.now()) {
238
238
  if (now - parsed.last_event_at <= SESSION_IDLE_MS) {
239
239
  const refreshed = { id: parsed.id, last_event_at: now };
240
240
  writeLocalStorage(SESSION_STORAGE_KEY, JSON.stringify(refreshed));
241
- return parsed.id;
241
+ return { id: parsed.id, isNew: false };
242
242
  }
243
243
  }
244
244
  } catch {
@@ -246,7 +246,7 @@ function getOrRotateSessionId(now = Date.now()) {
246
246
  }
247
247
  const fresh = { id: safeUuid(), last_event_at: now };
248
248
  writeLocalStorage(SESSION_STORAGE_KEY, JSON.stringify(fresh));
249
- return fresh.id;
249
+ return { id: fresh.id, isNew: true };
250
250
  }
251
251
 
252
252
  // ../tracking-core/src/events/page-view.ts
@@ -386,6 +386,56 @@ function attachAutoPageView(client, options = {}) {
386
386
  };
387
387
  }
388
388
 
389
+ // ../tracking-core/src/heartbeat.ts
390
+ function serializeValue(value) {
391
+ if (value instanceof RegExp) return value.source;
392
+ if (Array.isArray(value)) return value.map(serializeValue);
393
+ if (value !== null && typeof value === "object") {
394
+ const out = {};
395
+ for (const [k, v] of Object.entries(value)) {
396
+ out[k] = serializeValue(v);
397
+ }
398
+ return out;
399
+ }
400
+ return value;
401
+ }
402
+ function buildHeartbeatMetadata(surface, sdkVersion, packageName, triggers) {
403
+ const automaticNames = triggers ? Object.keys(triggers.automatic) : [];
404
+ const manualNames = triggers?.manual ? Object.keys(triggers.manual) : [];
405
+ let triggerConfig = null;
406
+ if (triggers) {
407
+ const cfg = {};
408
+ for (const [name, config] of Object.entries(triggers.automatic)) {
409
+ const serialized = serializeValue(config);
410
+ if (Object.keys(serialized).length > 0) {
411
+ cfg[name] = serialized;
412
+ }
413
+ }
414
+ if (triggers.manual) {
415
+ for (const [name, config] of Object.entries(triggers.manual)) {
416
+ if (config === void 0) continue;
417
+ const serialized = serializeValue(config);
418
+ if (Object.keys(serialized).length > 0) {
419
+ cfg[name] = serialized;
420
+ }
421
+ }
422
+ }
423
+ if (Object.keys(cfg).length > 0) {
424
+ triggerConfig = cfg;
425
+ }
426
+ }
427
+ return {
428
+ sdk_version: sdkVersion ?? "unknown",
429
+ package_name: packageName,
430
+ surface,
431
+ triggers: {
432
+ automatic: automaticNames,
433
+ manual: manualNames
434
+ },
435
+ trigger_config: triggerConfig
436
+ };
437
+ }
438
+
389
439
  // ../tracking-core/src/ingest.ts
390
440
  var DEFAULT_FLUSH_INTERVAL_MS = 2e3;
391
441
  var DEFAULT_MAX_QUEUE_SIZE = 10;
@@ -465,11 +515,33 @@ function createTrackingClient(config) {
465
515
  let firstPage = null;
466
516
  let destroyed = false;
467
517
  const visitorId = getVisitorId();
468
- let sessionId = getOrRotateSessionId();
518
+ const initialSession = getOrRotateSessionId();
519
+ let sessionId = initialSession.id;
469
520
  if (typeof window !== "undefined")
470
521
  firstPage = window.location.href;
522
+ function enqueueHeartbeat() {
523
+ const metadata = buildHeartbeatMetadata(
524
+ config.surface,
525
+ sdkVersion,
526
+ packageName,
527
+ config.triggers ?? null
528
+ );
529
+ queue.push({
530
+ event_type: "sdk_heartbeat",
531
+ page_url: typeof window === "undefined" ? null : window.location.href,
532
+ metadata,
533
+ occurred_at: (/* @__PURE__ */ new Date()).toISOString()
534
+ });
535
+ }
536
+ if (initialSession.isNew) {
537
+ enqueueHeartbeat();
538
+ }
471
539
  function buildSessionPayload() {
472
- sessionId = getOrRotateSessionId();
540
+ const rotated = getOrRotateSessionId();
541
+ if (rotated.isNew && rotated.id !== sessionId) {
542
+ enqueueHeartbeat();
543
+ }
544
+ sessionId = rotated.id;
473
545
  const params = readTrackingParams();
474
546
  const context = buildContext(config.surface, sdkVersion, packageName);
475
547
  return {
@@ -582,79 +654,94 @@ var ctaClickMetadataSchema = z2.object({
582
654
  }).strict();
583
655
  var ctaClickConfigSchema = z2.object({}).strict();
584
656
 
585
- // ../tracking-core/src/events/form-start.ts
657
+ // ../tracking-core/src/events/sdk-heartbeat.ts
586
658
  import { z as z3 } from "zod";
587
- var formStartMetadataSchema = z3.object({
588
- form: z3.object({
589
- id: z3.string(),
590
- action: z3.string().nullable()
591
- }),
592
- page: z3.object({
593
- path: z3.string()
594
- })
659
+ var sdkHeartbeatTriggersSchema = z3.object({
660
+ automatic: z3.array(z3.string()),
661
+ manual: z3.array(z3.string())
595
662
  }).strict();
596
- var formStartConfigSchema = z3.object({
597
- selector: z3.string().optional()
663
+ var sdkHeartbeatMetadataSchema = z3.object({
664
+ sdk_version: z3.string(),
665
+ package_name: z3.string().nullable(),
666
+ surface: z3.enum(["next", "react", "script"]),
667
+ triggers: sdkHeartbeatTriggersSchema,
668
+ trigger_config: z3.record(z3.string(), z3.record(z3.string(), z3.unknown())).nullable().optional()
598
669
  }).strict();
670
+ var sdkHeartbeatConfigSchema = z3.object({}).strict();
599
671
 
600
- // ../tracking-core/src/events/form-submit.ts
672
+ // ../tracking-core/src/events/form-start.ts
601
673
  import { z as z4 } from "zod";
602
- var formSubmitMetadataSchema = z4.object({
674
+ var formStartMetadataSchema = z4.object({
603
675
  form: z4.object({
604
676
  id: z4.string(),
605
- action: z4.string().nullable(),
606
- fields: z4.array(
607
- z4.object({
608
- name: z4.string(),
609
- type: z4.string(),
610
- label: z4.string().nullable(),
611
- has_value: z4.boolean()
612
- })
613
- ).optional()
677
+ action: z4.string().nullable()
614
678
  }),
615
679
  page: z4.object({
616
680
  path: z4.string()
617
681
  })
618
682
  }).strict();
619
- var formSubmitConfigSchema = z4.object({}).strict();
683
+ var formStartConfigSchema = z4.object({
684
+ selector: z4.string().optional()
685
+ }).strict();
620
686
 
621
- // ../tracking-core/src/events/multi-page-session.ts
687
+ // ../tracking-core/src/events/form-submit.ts
622
688
  import { z as z5 } from "zod";
623
- var multiPageSessionMetadataSchema = z5.object({
624
- page_count: z5.number().int().min(2),
689
+ var formSubmitMetadataSchema = z5.object({
690
+ form: z5.object({
691
+ id: z5.string(),
692
+ action: z5.string().nullable(),
693
+ fields: z5.array(
694
+ z5.object({
695
+ name: z5.string(),
696
+ type: z5.string(),
697
+ label: z5.string().nullable(),
698
+ has_value: z5.boolean()
699
+ })
700
+ ).optional()
701
+ }),
625
702
  page: z5.object({
626
703
  path: z5.string()
627
704
  })
628
705
  }).strict();
629
- var multiPageSessionConfigSchema = z5.object({
630
- pageThreshold: z5.number().int().min(2)
631
- }).strict();
706
+ var formSubmitConfigSchema = z5.object({}).strict();
632
707
 
633
- // ../tracking-core/src/events/phone-click.ts
708
+ // ../tracking-core/src/events/multi-page-session.ts
634
709
  import { z as z6 } from "zod";
635
- var phoneClickMetadataSchema = z6.object({
636
- phone_number: z6.string(),
710
+ var multiPageSessionMetadataSchema = z6.object({
711
+ page_count: z6.number().int().min(2),
637
712
  page: z6.object({
638
713
  path: z6.string()
639
- }),
640
- section: z6.string().nullable().optional()
714
+ })
715
+ }).strict();
716
+ var multiPageSessionConfigSchema = z6.object({
717
+ pageThreshold: z6.number().int().min(2)
641
718
  }).strict();
642
- var phoneClickConfigSchema = z6.object({}).strict();
643
719
 
644
- // ../tracking-core/src/events/scroll-depth.ts
720
+ // ../tracking-core/src/events/phone-click.ts
645
721
  import { z as z7 } from "zod";
646
- var scrollDepthMetadataSchema = z7.object({
647
- depth_percent: z7.number().int().min(1).max(100),
722
+ var phoneClickMetadataSchema = z7.object({
723
+ phone_number: z7.string(),
648
724
  page: z7.object({
649
725
  path: z7.string()
726
+ }),
727
+ section: z7.string().nullable().optional()
728
+ }).strict();
729
+ var phoneClickConfigSchema = z7.object({}).strict();
730
+
731
+ // ../tracking-core/src/events/scroll-depth.ts
732
+ import { z as z8 } from "zod";
733
+ var scrollDepthMetadataSchema = z8.object({
734
+ depth_percent: z8.number().int().min(1).max(100),
735
+ page: z8.object({
736
+ path: z8.string()
650
737
  })
651
738
  }).strict();
652
- var scrollDepthConfigSchema = z7.object({
653
- thresholds: z7.array(z7.number().int().min(1).max(100)).min(1)
739
+ var scrollDepthConfigSchema = z8.object({
740
+ thresholds: z8.array(z8.number().int().min(1).max(100)).min(1)
654
741
  }).strict();
655
742
 
656
743
  // ../tracking-core/src/events/specific-page-visit.ts
657
- import { z as z8 } from "zod";
744
+ import { z as z9 } from "zod";
658
745
  var SPECIFIC_PAGE_NAMES = [
659
746
  "contact_page",
660
747
  "about_page",
@@ -665,18 +752,18 @@ var SPECIFIC_PAGE_NAMES = [
665
752
  "faq_page",
666
753
  "testimonials_page"
667
754
  ];
668
- var specificPageNameSchema = z8.enum(SPECIFIC_PAGE_NAMES);
669
- var specificPageVisitMetadataSchema = z8.object({
755
+ var specificPageNameSchema = z9.enum(SPECIFIC_PAGE_NAMES);
756
+ var specificPageVisitMetadataSchema = z9.object({
670
757
  page_name: specificPageNameSchema,
671
- page: z8.object({
672
- path: z8.string()
758
+ page: z9.object({
759
+ path: z9.string()
673
760
  })
674
761
  }).strict();
675
- var specificPageVisitConfigSchema = z8.object({
676
- pages: z8.array(
677
- z8.object({
762
+ var specificPageVisitConfigSchema = z9.object({
763
+ pages: z9.array(
764
+ z9.object({
678
765
  name: specificPageNameSchema,
679
- pathPattern: z8.custom((value) => value instanceof RegExp, {
766
+ pathPattern: z9.custom((value) => value instanceof RegExp, {
680
767
  message: "pathPattern must be a RegExp"
681
768
  })
682
769
  })
@@ -684,15 +771,15 @@ var specificPageVisitConfigSchema = z8.object({
684
771
  }).strict();
685
772
 
686
773
  // ../tracking-core/src/events/time-on-site.ts
687
- import { z as z9 } from "zod";
688
- var timeOnSiteMetadataSchema = z9.object({
689
- duration_ms: z9.number().int().nonnegative(),
690
- page: z9.object({
691
- path: z9.string()
774
+ import { z as z10 } from "zod";
775
+ var timeOnSiteMetadataSchema = z10.object({
776
+ duration_ms: z10.number().int().nonnegative(),
777
+ page: z10.object({
778
+ path: z10.string()
692
779
  })
693
780
  }).strict();
694
- var timeOnSiteConfigSchema = z9.object({
695
- thresholdSeconds: z9.number().int().positive()
781
+ var timeOnSiteConfigSchema = z10.object({
782
+ thresholdSeconds: z10.number().int().positive()
696
783
  }).strict();
697
784
 
698
785
  // ../tracking-core/src/events/registry.ts
@@ -728,6 +815,12 @@ var EVENT_REGISTRY = {
728
815
  metadataSchema: formStartMetadataSchema,
729
816
  configSchema: formStartConfigSchema
730
817
  },
818
+ // --- SDK-internal automatic (not consumer-configurable) ---
819
+ sdk_heartbeat: {
820
+ kind: "automatic",
821
+ metadataSchema: sdkHeartbeatMetadataSchema,
822
+ configSchema: sdkHeartbeatConfigSchema
823
+ },
731
824
  // --- manual triggers ---
732
825
  form_submit: {
733
826
  kind: "manual",
@@ -987,7 +1080,7 @@ function attachMultiPageSession(client, config) {
987
1080
  }
988
1081
  }
989
1082
  function resetIfSessionChanged() {
990
- const currentSession = getOrRotateSessionId();
1083
+ const currentSession = getOrRotateSessionId().id;
991
1084
  const storedSession = storage.getItem(SESSION_KEY);
992
1085
  if (storedSession !== currentSession) {
993
1086
  storage.setItem(SESSION_KEY, currentSession);
@@ -1200,7 +1293,7 @@ import {
1200
1293
  } from "react";
1201
1294
 
1202
1295
  // package.json
1203
- var version = "0.5.0";
1296
+ var version = "0.5.1";
1204
1297
 
1205
1298
  // src/factory.tsx
1206
1299
  import { jsx as jsx2 } from "react/jsx-runtime";
@@ -1236,6 +1329,7 @@ function createTracking(options) {
1236
1329
  surface: "react",
1237
1330
  packageName: "@aranova/tracking-react",
1238
1331
  sdkVersion: version,
1332
+ triggers,
1239
1333
  debug
1240
1334
  }),
1241
1335
  triggers,
@@ -1254,6 +1348,7 @@ function createTracking(options) {
1254
1348
  endpoint,
1255
1349
  surface: "react",
1256
1350
  packageName: "@aranova/tracking-react",
1351
+ triggers,
1257
1352
  debug
1258
1353
  });
1259
1354
  detachers.push(attachAutoPageView(rawClient));