aurea-tracking-sdk 1.1.0 → 1.1.2

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.d.mts CHANGED
@@ -33,6 +33,12 @@ declare class AureaSDK {
33
33
  private eventQueue;
34
34
  private batchTimer?;
35
35
  private initialized;
36
+ private sessionStartTime;
37
+ private pageStartTime;
38
+ private activeTime;
39
+ private lastActiveTimestamp;
40
+ private isPageVisible;
41
+ private webVitalsCollected;
36
42
  constructor(config: AureaConfig);
37
43
  /**
38
44
  * Initialize the SDK
@@ -43,7 +49,7 @@ declare class AureaSDK {
43
49
  */
44
50
  track(eventName: string, properties?: Record<string, any>): void;
45
51
  /**
46
- * Identify a user
52
+ * Identify a user (links anonymous user to known user)
47
53
  */
48
54
  identify(userId: string, traits?: Record<string, any>): void;
49
55
  /**
@@ -111,6 +117,14 @@ declare class AureaSDK {
111
117
  * Check if user has completed a purchase
112
118
  */
113
119
  private checkForPurchase;
120
+ /**
121
+ * Track Core Web Vitals
122
+ */
123
+ private trackWebVitals;
124
+ /**
125
+ * Track session timing (active time, duration)
126
+ */
127
+ private trackSessionTiming;
114
128
  /**
115
129
  * Generate unique ID
116
130
  */
package/dist/index.d.ts CHANGED
@@ -33,6 +33,12 @@ declare class AureaSDK {
33
33
  private eventQueue;
34
34
  private batchTimer?;
35
35
  private initialized;
36
+ private sessionStartTime;
37
+ private pageStartTime;
38
+ private activeTime;
39
+ private lastActiveTimestamp;
40
+ private isPageVisible;
41
+ private webVitalsCollected;
36
42
  constructor(config: AureaConfig);
37
43
  /**
38
44
  * Initialize the SDK
@@ -43,7 +49,7 @@ declare class AureaSDK {
43
49
  */
44
50
  track(eventName: string, properties?: Record<string, any>): void;
45
51
  /**
46
- * Identify a user
52
+ * Identify a user (links anonymous user to known user)
47
53
  */
48
54
  identify(userId: string, traits?: Record<string, any>): void;
49
55
  /**
@@ -111,6 +117,14 @@ declare class AureaSDK {
111
117
  * Check if user has completed a purchase
112
118
  */
113
119
  private checkForPurchase;
120
+ /**
121
+ * Track Core Web Vitals
122
+ */
123
+ private trackWebVitals;
124
+ /**
125
+ * Track session timing (active time, duration)
126
+ */
127
+ private trackSessionTiming;
114
128
  /**
115
129
  * Generate unique ID
116
130
  */
package/dist/index.js CHANGED
@@ -28,10 +28,23 @@ __export(index_exports, {
28
28
  });
29
29
  module.exports = __toCommonJS(index_exports);
30
30
  var import_ua_parser_js = require("ua-parser-js");
31
+ var import_web_vitals = require("web-vitals");
31
32
  var AureaSDK = class {
32
33
  constructor(config) {
33
34
  this.eventQueue = [];
34
35
  this.initialized = false;
36
+ this.sessionStartTime = Date.now();
37
+ this.pageStartTime = Date.now();
38
+ this.activeTime = 0;
39
+ this.lastActiveTimestamp = Date.now();
40
+ this.isPageVisible = true;
41
+ this.webVitalsCollected = {
42
+ lcp: false,
43
+ inp: false,
44
+ cls: false,
45
+ fcp: false,
46
+ ttfb: false
47
+ };
35
48
  this.config = {
36
49
  apiUrl: "http://localhost:3000/api",
37
50
  debug: false,
@@ -64,9 +77,9 @@ var AureaSDK = class {
64
77
  console.warn("[Aurea SDK] Already initialized");
65
78
  return;
66
79
  }
67
- if (this.config.respectDoNotTrack && typeof navigator !== "undefined" && (navigator.doNotTrack === "1" || navigator.msDoNotTrack === "1")) {
80
+ if (this.config.respectDoNotTrack && typeof navigator !== "undefined" && (navigator.doNotTrack === "1" || navigator.msDoNotTrack === "1" || navigator.globalPrivacyControl === true)) {
68
81
  if (this.config.debug) {
69
- console.log("[Aurea SDK] Do Not Track enabled, skipping initialization");
82
+ console.log("[Aurea SDK] Do Not Track or Global Privacy Control enabled, skipping initialization");
70
83
  }
71
84
  return;
72
85
  }
@@ -83,6 +96,8 @@ var AureaSDK = class {
83
96
  }
84
97
  this.startBatchTimer();
85
98
  this.startPurchasePolling();
99
+ this.trackWebVitals();
100
+ this.trackSessionTiming();
86
101
  if (this.config.debug) {
87
102
  console.log("[Aurea SDK] Initialized", {
88
103
  sessionId: this.sessionId,
@@ -108,9 +123,10 @@ var AureaSDK = class {
108
123
  }
109
124
  }
110
125
  /**
111
- * Identify a user
126
+ * Identify a user (links anonymous user to known user)
112
127
  */
113
128
  identify(userId, traits) {
129
+ const previousUserId = this.userId;
114
130
  this.userId = userId;
115
131
  if (typeof window !== "undefined") {
116
132
  localStorage.setItem("aurea_user_id", userId);
@@ -120,10 +136,17 @@ var AureaSDK = class {
120
136
  }
121
137
  this.track("user_identified", {
122
138
  userId,
123
- traits
139
+ anonymousId: this.anonymousId,
140
+ previousUserId,
141
+ traits: traits || {},
142
+ timestamp: Date.now()
124
143
  });
125
144
  if (this.config.debug) {
126
- console.log("[Aurea SDK] User identified:", userId);
145
+ console.log("[Aurea SDK] User identified:", {
146
+ userId,
147
+ anonymousId: this.anonymousId,
148
+ traits
149
+ });
127
150
  }
128
151
  }
129
152
  /**
@@ -437,6 +460,173 @@ var AureaSDK = class {
437
460
  }
438
461
  }
439
462
  }
463
+ /**
464
+ * Track Core Web Vitals
465
+ */
466
+ trackWebVitals() {
467
+ if (typeof window === "undefined") return;
468
+ const getVitalRating = (name, value) => {
469
+ const thresholds = {
470
+ LCP: [2500, 4e3],
471
+ INP: [200, 500],
472
+ CLS: [0.1, 0.25],
473
+ FCP: [1800, 3e3],
474
+ TTFB: [800, 1800]
475
+ };
476
+ const [good, needsImprovement] = thresholds[name] || [0, 0];
477
+ if (value <= good) return "good";
478
+ if (value <= needsImprovement) return "needs-improvement";
479
+ return "poor";
480
+ };
481
+ (0, import_web_vitals.onLCP)((metric) => {
482
+ if (!this.webVitalsCollected.lcp) {
483
+ this.webVitalsCollected.lcp = true;
484
+ this.track("web_vital", {
485
+ metric: "lcp",
486
+ value: metric.value,
487
+ rating: getVitalRating("LCP", metric.value),
488
+ delta: metric.delta,
489
+ id: metric.id
490
+ });
491
+ }
492
+ });
493
+ (0, import_web_vitals.onINP)((metric) => {
494
+ if (!this.webVitalsCollected.inp) {
495
+ this.webVitalsCollected.inp = true;
496
+ this.track("web_vital", {
497
+ metric: "inp",
498
+ value: metric.value,
499
+ rating: getVitalRating("INP", metric.value),
500
+ delta: metric.delta,
501
+ id: metric.id
502
+ });
503
+ }
504
+ });
505
+ (0, import_web_vitals.onCLS)((metric) => {
506
+ if (!this.webVitalsCollected.cls) {
507
+ this.webVitalsCollected.cls = true;
508
+ this.track("web_vital", {
509
+ metric: "cls",
510
+ value: metric.value,
511
+ rating: getVitalRating("CLS", metric.value),
512
+ delta: metric.delta,
513
+ id: metric.id
514
+ });
515
+ }
516
+ });
517
+ (0, import_web_vitals.onFCP)((metric) => {
518
+ if (!this.webVitalsCollected.fcp) {
519
+ this.webVitalsCollected.fcp = true;
520
+ this.track("web_vital", {
521
+ metric: "fcp",
522
+ value: metric.value,
523
+ rating: getVitalRating("FCP", metric.value),
524
+ delta: metric.delta,
525
+ id: metric.id
526
+ });
527
+ }
528
+ });
529
+ (0, import_web_vitals.onTTFB)((metric) => {
530
+ if (!this.webVitalsCollected.ttfb) {
531
+ this.webVitalsCollected.ttfb = true;
532
+ this.track("web_vital", {
533
+ metric: "ttfb",
534
+ value: metric.value,
535
+ rating: getVitalRating("TTFB", metric.value),
536
+ delta: metric.delta,
537
+ id: metric.id
538
+ });
539
+ }
540
+ });
541
+ if (this.config.debug) {
542
+ console.log("[Aurea SDK] Core Web Vitals tracking enabled");
543
+ }
544
+ }
545
+ /**
546
+ * Track session timing (active time, duration)
547
+ */
548
+ trackSessionTiming() {
549
+ if (typeof window === "undefined") return;
550
+ document.addEventListener("visibilitychange", () => {
551
+ const now = Date.now();
552
+ if (document.hidden) {
553
+ if (this.isPageVisible) {
554
+ this.activeTime += now - this.lastActiveTimestamp;
555
+ this.isPageVisible = false;
556
+ }
557
+ } else {
558
+ this.isPageVisible = true;
559
+ this.lastActiveTimestamp = now;
560
+ }
561
+ });
562
+ let interactionTimeout;
563
+ const resetInactivityTimer = () => {
564
+ const now = Date.now();
565
+ if (!this.isPageVisible) {
566
+ this.isPageVisible = true;
567
+ this.lastActiveTimestamp = now;
568
+ }
569
+ clearTimeout(interactionTimeout);
570
+ interactionTimeout = setTimeout(() => {
571
+ if (this.isPageVisible) {
572
+ this.activeTime += Date.now() - this.lastActiveTimestamp;
573
+ this.isPageVisible = false;
574
+ }
575
+ }, 3e4);
576
+ };
577
+ window.addEventListener("mousemove", resetInactivityTimer, { passive: true });
578
+ window.addEventListener("keydown", resetInactivityTimer, { passive: true });
579
+ window.addEventListener("scroll", resetInactivityTimer, { passive: true });
580
+ window.addEventListener("click", resetInactivityTimer, { passive: true });
581
+ window.addEventListener("touchstart", resetInactivityTimer, { passive: true });
582
+ window.addEventListener("beforeunload", () => {
583
+ const now = Date.now();
584
+ if (this.isPageVisible) {
585
+ this.activeTime += now - this.lastActiveTimestamp;
586
+ }
587
+ const totalDuration = Math.floor((now - this.sessionStartTime) / 1e3);
588
+ const activeTimeSeconds = Math.floor(this.activeTime / 1e3);
589
+ const sessionEndEvent = {
590
+ eventId: this.generateEventId(),
591
+ eventName: "session_end",
592
+ properties: {
593
+ duration: totalDuration,
594
+ activeTime: activeTimeSeconds,
595
+ idleTime: totalDuration - activeTimeSeconds,
596
+ engagementRate: totalDuration > 0 ? activeTimeSeconds / totalDuration * 100 : 0
597
+ },
598
+ context: this.buildContext(),
599
+ timestamp: Date.now()
600
+ };
601
+ const url = `${this.config.apiUrl}/track/events`;
602
+ const payload = JSON.stringify({
603
+ events: [sessionEndEvent],
604
+ batch: false
605
+ });
606
+ try {
607
+ fetch(url, {
608
+ method: "POST",
609
+ headers: {
610
+ "Content-Type": "application/json",
611
+ "X-Aurea-API-Key": this.config.apiKey,
612
+ "X-Aurea-Funnel-ID": this.config.funnelId
613
+ },
614
+ body: payload,
615
+ keepalive: true
616
+ // Critical: ensures request completes even if page unloads
617
+ }).catch(() => {
618
+ });
619
+ if (this.config.debug) {
620
+ console.log("[Aurea SDK] Session end sent with keepalive");
621
+ }
622
+ } catch (error) {
623
+ }
624
+ this.flushEvents();
625
+ });
626
+ if (this.config.debug) {
627
+ console.log("[Aurea SDK] Session timing tracking enabled");
628
+ }
629
+ }
440
630
  /**
441
631
  * Generate unique ID
442
632
  */
package/dist/index.mjs CHANGED
@@ -1,9 +1,22 @@
1
1
  // src/index.ts
2
2
  import { UAParser } from "ua-parser-js";
3
+ import { onLCP, onINP, onCLS, onFCP, onTTFB } from "web-vitals";
3
4
  var AureaSDK = class {
4
5
  constructor(config) {
5
6
  this.eventQueue = [];
6
7
  this.initialized = false;
8
+ this.sessionStartTime = Date.now();
9
+ this.pageStartTime = Date.now();
10
+ this.activeTime = 0;
11
+ this.lastActiveTimestamp = Date.now();
12
+ this.isPageVisible = true;
13
+ this.webVitalsCollected = {
14
+ lcp: false,
15
+ inp: false,
16
+ cls: false,
17
+ fcp: false,
18
+ ttfb: false
19
+ };
7
20
  this.config = {
8
21
  apiUrl: "http://localhost:3000/api",
9
22
  debug: false,
@@ -36,9 +49,9 @@ var AureaSDK = class {
36
49
  console.warn("[Aurea SDK] Already initialized");
37
50
  return;
38
51
  }
39
- if (this.config.respectDoNotTrack && typeof navigator !== "undefined" && (navigator.doNotTrack === "1" || navigator.msDoNotTrack === "1")) {
52
+ if (this.config.respectDoNotTrack && typeof navigator !== "undefined" && (navigator.doNotTrack === "1" || navigator.msDoNotTrack === "1" || navigator.globalPrivacyControl === true)) {
40
53
  if (this.config.debug) {
41
- console.log("[Aurea SDK] Do Not Track enabled, skipping initialization");
54
+ console.log("[Aurea SDK] Do Not Track or Global Privacy Control enabled, skipping initialization");
42
55
  }
43
56
  return;
44
57
  }
@@ -55,6 +68,8 @@ var AureaSDK = class {
55
68
  }
56
69
  this.startBatchTimer();
57
70
  this.startPurchasePolling();
71
+ this.trackWebVitals();
72
+ this.trackSessionTiming();
58
73
  if (this.config.debug) {
59
74
  console.log("[Aurea SDK] Initialized", {
60
75
  sessionId: this.sessionId,
@@ -80,9 +95,10 @@ var AureaSDK = class {
80
95
  }
81
96
  }
82
97
  /**
83
- * Identify a user
98
+ * Identify a user (links anonymous user to known user)
84
99
  */
85
100
  identify(userId, traits) {
101
+ const previousUserId = this.userId;
86
102
  this.userId = userId;
87
103
  if (typeof window !== "undefined") {
88
104
  localStorage.setItem("aurea_user_id", userId);
@@ -92,10 +108,17 @@ var AureaSDK = class {
92
108
  }
93
109
  this.track("user_identified", {
94
110
  userId,
95
- traits
111
+ anonymousId: this.anonymousId,
112
+ previousUserId,
113
+ traits: traits || {},
114
+ timestamp: Date.now()
96
115
  });
97
116
  if (this.config.debug) {
98
- console.log("[Aurea SDK] User identified:", userId);
117
+ console.log("[Aurea SDK] User identified:", {
118
+ userId,
119
+ anonymousId: this.anonymousId,
120
+ traits
121
+ });
99
122
  }
100
123
  }
101
124
  /**
@@ -409,6 +432,173 @@ var AureaSDK = class {
409
432
  }
410
433
  }
411
434
  }
435
+ /**
436
+ * Track Core Web Vitals
437
+ */
438
+ trackWebVitals() {
439
+ if (typeof window === "undefined") return;
440
+ const getVitalRating = (name, value) => {
441
+ const thresholds = {
442
+ LCP: [2500, 4e3],
443
+ INP: [200, 500],
444
+ CLS: [0.1, 0.25],
445
+ FCP: [1800, 3e3],
446
+ TTFB: [800, 1800]
447
+ };
448
+ const [good, needsImprovement] = thresholds[name] || [0, 0];
449
+ if (value <= good) return "good";
450
+ if (value <= needsImprovement) return "needs-improvement";
451
+ return "poor";
452
+ };
453
+ onLCP((metric) => {
454
+ if (!this.webVitalsCollected.lcp) {
455
+ this.webVitalsCollected.lcp = true;
456
+ this.track("web_vital", {
457
+ metric: "lcp",
458
+ value: metric.value,
459
+ rating: getVitalRating("LCP", metric.value),
460
+ delta: metric.delta,
461
+ id: metric.id
462
+ });
463
+ }
464
+ });
465
+ onINP((metric) => {
466
+ if (!this.webVitalsCollected.inp) {
467
+ this.webVitalsCollected.inp = true;
468
+ this.track("web_vital", {
469
+ metric: "inp",
470
+ value: metric.value,
471
+ rating: getVitalRating("INP", metric.value),
472
+ delta: metric.delta,
473
+ id: metric.id
474
+ });
475
+ }
476
+ });
477
+ onCLS((metric) => {
478
+ if (!this.webVitalsCollected.cls) {
479
+ this.webVitalsCollected.cls = true;
480
+ this.track("web_vital", {
481
+ metric: "cls",
482
+ value: metric.value,
483
+ rating: getVitalRating("CLS", metric.value),
484
+ delta: metric.delta,
485
+ id: metric.id
486
+ });
487
+ }
488
+ });
489
+ onFCP((metric) => {
490
+ if (!this.webVitalsCollected.fcp) {
491
+ this.webVitalsCollected.fcp = true;
492
+ this.track("web_vital", {
493
+ metric: "fcp",
494
+ value: metric.value,
495
+ rating: getVitalRating("FCP", metric.value),
496
+ delta: metric.delta,
497
+ id: metric.id
498
+ });
499
+ }
500
+ });
501
+ onTTFB((metric) => {
502
+ if (!this.webVitalsCollected.ttfb) {
503
+ this.webVitalsCollected.ttfb = true;
504
+ this.track("web_vital", {
505
+ metric: "ttfb",
506
+ value: metric.value,
507
+ rating: getVitalRating("TTFB", metric.value),
508
+ delta: metric.delta,
509
+ id: metric.id
510
+ });
511
+ }
512
+ });
513
+ if (this.config.debug) {
514
+ console.log("[Aurea SDK] Core Web Vitals tracking enabled");
515
+ }
516
+ }
517
+ /**
518
+ * Track session timing (active time, duration)
519
+ */
520
+ trackSessionTiming() {
521
+ if (typeof window === "undefined") return;
522
+ document.addEventListener("visibilitychange", () => {
523
+ const now = Date.now();
524
+ if (document.hidden) {
525
+ if (this.isPageVisible) {
526
+ this.activeTime += now - this.lastActiveTimestamp;
527
+ this.isPageVisible = false;
528
+ }
529
+ } else {
530
+ this.isPageVisible = true;
531
+ this.lastActiveTimestamp = now;
532
+ }
533
+ });
534
+ let interactionTimeout;
535
+ const resetInactivityTimer = () => {
536
+ const now = Date.now();
537
+ if (!this.isPageVisible) {
538
+ this.isPageVisible = true;
539
+ this.lastActiveTimestamp = now;
540
+ }
541
+ clearTimeout(interactionTimeout);
542
+ interactionTimeout = setTimeout(() => {
543
+ if (this.isPageVisible) {
544
+ this.activeTime += Date.now() - this.lastActiveTimestamp;
545
+ this.isPageVisible = false;
546
+ }
547
+ }, 3e4);
548
+ };
549
+ window.addEventListener("mousemove", resetInactivityTimer, { passive: true });
550
+ window.addEventListener("keydown", resetInactivityTimer, { passive: true });
551
+ window.addEventListener("scroll", resetInactivityTimer, { passive: true });
552
+ window.addEventListener("click", resetInactivityTimer, { passive: true });
553
+ window.addEventListener("touchstart", resetInactivityTimer, { passive: true });
554
+ window.addEventListener("beforeunload", () => {
555
+ const now = Date.now();
556
+ if (this.isPageVisible) {
557
+ this.activeTime += now - this.lastActiveTimestamp;
558
+ }
559
+ const totalDuration = Math.floor((now - this.sessionStartTime) / 1e3);
560
+ const activeTimeSeconds = Math.floor(this.activeTime / 1e3);
561
+ const sessionEndEvent = {
562
+ eventId: this.generateEventId(),
563
+ eventName: "session_end",
564
+ properties: {
565
+ duration: totalDuration,
566
+ activeTime: activeTimeSeconds,
567
+ idleTime: totalDuration - activeTimeSeconds,
568
+ engagementRate: totalDuration > 0 ? activeTimeSeconds / totalDuration * 100 : 0
569
+ },
570
+ context: this.buildContext(),
571
+ timestamp: Date.now()
572
+ };
573
+ const url = `${this.config.apiUrl}/track/events`;
574
+ const payload = JSON.stringify({
575
+ events: [sessionEndEvent],
576
+ batch: false
577
+ });
578
+ try {
579
+ fetch(url, {
580
+ method: "POST",
581
+ headers: {
582
+ "Content-Type": "application/json",
583
+ "X-Aurea-API-Key": this.config.apiKey,
584
+ "X-Aurea-Funnel-ID": this.config.funnelId
585
+ },
586
+ body: payload,
587
+ keepalive: true
588
+ // Critical: ensures request completes even if page unloads
589
+ }).catch(() => {
590
+ });
591
+ if (this.config.debug) {
592
+ console.log("[Aurea SDK] Session end sent with keepalive");
593
+ }
594
+ } catch (error) {
595
+ }
596
+ this.flushEvents();
597
+ });
598
+ if (this.config.debug) {
599
+ console.log("[Aurea SDK] Session timing tracking enabled");
600
+ }
601
+ }
412
602
  /**
413
603
  * Generate unique ID
414
604
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aurea-tracking-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Standalone tracking SDK for Aurea CRM external funnels",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -26,18 +26,19 @@
26
26
  "license": "MIT",
27
27
  "repository": {
28
28
  "type": "git",
29
- "url": "https://github.com/yourusername/aurea-tracking-sdk.git"
29
+ "url": "git+https://github.com/akal0/aurea-tracking-sdk.git"
30
30
  },
31
31
  "bugs": {
32
- "url": "https://github.com/yourusername/aurea-tracking-sdk/issues"
32
+ "url": "https://github.com/akal0/aurea-tracking-sdk/issues"
33
33
  },
34
- "homepage": "https://github.com/yourusername/aurea-tracking-sdk#readme",
34
+ "homepage": "https://github.com/akal0/aurea-tracking-sdk#readme",
35
35
  "devDependencies": {
36
36
  "@types/node": "^25.0.3",
37
37
  "tsup": "^8.0.1",
38
38
  "typescript": "^5.3.3"
39
39
  },
40
40
  "dependencies": {
41
- "ua-parser-js": "^2.0.7"
41
+ "ua-parser-js": "^2.0.7",
42
+ "web-vitals": "^5.1.0"
42
43
  }
43
44
  }