@dataxamas/tracker-js 2.5.0 → 2.7.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/CHANGELOG.md ADDED
@@ -0,0 +1,54 @@
1
+ ## 2.7.0
2
+
3
+ - Web Vitals also collect FCP (First Contentful Paint) and TTFB (Time to First Byte), sent in the same batch as
4
+ LCP, INP and CLS. Needs a Dataxamas server that already accepts both metrics.
5
+ - Session replay pauses the recorder after 1 minute without a gesture and resumes on the next one, in the same
6
+ recording. Limits now match the `dataxamas.js` script: 10 minutes, 15,000 events and 5 MB per recording.
7
+ - Element scroll no longer counts as activity, so an auto-scrolling carousel does not keep the recorder running.
8
+
9
+ ## 2.6.0
10
+
11
+ - No code changes; same build as 2.5.0.
12
+
13
+ ## 2.5.0
14
+
15
+ - `tracking.identify(userId | null)` links the visitor to your own user id for retention cohorts; the server stores
16
+ only a hash of it.
17
+
18
+ ## 2.4.0
19
+
20
+ - Visitors are identified server-side: the SDK no longer creates a session id and stores nothing in the browser
21
+ besides the replay key in `sessionStorage`.
22
+ - Replay sampling is decided by the server.
23
+
24
+ ## 2.3.0
25
+
26
+ - UTM attribution: only `utm_*` query params are sent.
27
+ - Web Vitals (LCP, INP, CLS), flushed on `visibilitychange` / `pagehide`.
28
+ - `tracking.track(name, data)` custom events for goals and funnels.
29
+
30
+ ## 2.1.3
31
+
32
+ - Tuned the replay idle timeout and recording limit.
33
+
34
+ ## 2.1.2
35
+
36
+ - Session replay keeps one recording per tab visit across route changes and reloads, closed after idle time or at the
37
+ size cap.
38
+ - Per-site replay sample rate.
39
+ - Skips automated browsers (`navigator.webdriver`).
40
+
41
+ ## 2.1.0
42
+
43
+ - Crawler tracking: `DataxamasCrawlers` (`trackRequest`, `track`), `isCrawlerUserAgent`, `withCrawlerTracking` and
44
+ `createExpressCrawlerMiddleware`.
45
+ - Default base URL is now `https://dataxamas.com`.
46
+
47
+ ## 2.0.1
48
+
49
+ - Packaging fix, no code changes.
50
+
51
+ ## 2.0.0
52
+
53
+ - Renamed to `@dataxamas/tracker-js` (was `dataxamas`).
54
+ - `apiKey` replaces `websiteId`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dataxamas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs CHANGED
@@ -314,21 +314,25 @@ var DataxamasLogs = class {
314
314
  }
315
315
  };
316
316
 
317
+ // ../tracker-shared/src/constants.ts
318
+ var MAX_RECORDING_MS = 10 * 60 * 1e3;
319
+ var MAX_EVENTS_PER_RECORDING = 15e3;
320
+ var MAX_BYTES_PER_RECORDING = 5 * 1024 * 1024;
321
+ var REPLAY_IDLE_TIMEOUT_MS = 10 * 60 * 1e3;
322
+ var REPLAY_IDLE_SUSPEND_MS = 60 * 1e3;
323
+
317
324
  // src/tracking.ts
318
325
  var QUEUE_DELAY_MS = 4e3;
319
326
  var STORAGE_PREFIX = "@dataxamas";
320
327
  var REPLAY_FLUSH_SIZE = 100;
321
328
  var REPLAY_FLUSH_INTERVAL_MS = 5e3;
322
329
  var CAP_CHECK_MS = 1e3;
323
- var MAX_RECORDING_MS = 30 * 60 * 1e3;
324
- var MAX_EVENTS_PER_RECORDING = 5e4;
325
- var REPLAY_IDLE_TIMEOUT_MS = 30 * 60 * 1e3;
326
330
  var ACTIVITY_SAVE_THROTTLE_MS = 5e3;
327
331
  var REPLAY_RECORDING_KEY = `${STORAGE_PREFIX}/replay-recording`;
328
332
  function isStoredRecording(value) {
329
333
  if (typeof value !== "object" || value === null) return false;
330
334
  const stored = value;
331
- return typeof stored.id === "string" && typeof stored.startedAt === "string" && typeof stored.startedAtMs === "number" && typeof stored.seq === "number" && typeof stored.events === "number" && typeof stored.lastActivityAt === "number" && typeof stored.capped === "boolean";
335
+ return typeof stored.id === "string" && typeof stored.startedAt === "string" && typeof stored.startedAtMs === "number" && typeof stored.seq === "number" && typeof stored.events === "number" && typeof stored.bytes === "number" && typeof stored.lastActivityAt === "number" && typeof stored.capped === "boolean";
332
336
  }
333
337
  var KEEPALIVE_LIMIT_BYTES = 60 * 1024;
334
338
  var DataxamasTracking = class {
@@ -381,6 +385,7 @@ var DataxamasTracking = class {
381
385
  this.recordingStartedAtMs = 0;
382
386
  this.recordingSeq = 0;
383
387
  this.recordingEvents = 0;
388
+ this.recordingBytes = 0;
384
389
  this.lastActivityAt = 0;
385
390
  this.lastActivitySavedAt = 0;
386
391
  }
@@ -571,6 +576,8 @@ var DataxamasTracking = class {
571
576
  webVitals.onLCP(queue);
572
577
  webVitals.onINP(queue);
573
578
  webVitals.onCLS(queue);
579
+ webVitals.onFCP(queue);
580
+ webVitals.onTTFB(queue);
574
581
  document.addEventListener("visibilitychange", () => {
575
582
  if (document.visibilityState === "hidden") this.flushVitals();
576
583
  });
@@ -589,7 +596,7 @@ var DataxamasTracking = class {
589
596
  return Boolean(this.stopRrweb);
590
597
  }
591
598
  exceededReplayCaps() {
592
- return this.recordingEvents >= MAX_EVENTS_PER_RECORDING || Date.now() - this.recordingStartedAtMs >= MAX_RECORDING_MS;
599
+ return this.recordingEvents >= MAX_EVENTS_PER_RECORDING || this.recordingBytes >= MAX_BYTES_PER_RECORDING || Date.now() - this.recordingStartedAtMs >= MAX_RECORDING_MS;
593
600
  }
594
601
  loadRecording() {
595
602
  try {
@@ -607,6 +614,7 @@ var DataxamasTracking = class {
607
614
  startedAtMs: this.recordingStartedAtMs,
608
615
  seq: this.recordingSeq,
609
616
  events: this.recordingEvents,
617
+ bytes: this.recordingBytes,
610
618
  lastActivityAt: this.lastActivityAt,
611
619
  capped: this.replayCapped
612
620
  };
@@ -622,6 +630,7 @@ var DataxamasTracking = class {
622
630
  this.recordingStartedAtMs = Date.now();
623
631
  this.recordingSeq = 0;
624
632
  this.recordingEvents = 0;
633
+ this.recordingBytes = 0;
625
634
  this.lastActivityAt = Date.now();
626
635
  this.saveRecording();
627
636
  }
@@ -638,6 +647,7 @@ var DataxamasTracking = class {
638
647
  this.recordingStartedAtMs = stored.startedAtMs;
639
648
  this.recordingSeq = stored.seq;
640
649
  this.recordingEvents = stored.events;
650
+ this.recordingBytes = stored.bytes;
641
651
  this.lastActivityAt = stored.lastActivityAt;
642
652
  }
643
653
  touchActivity(now) {
@@ -659,6 +669,7 @@ var DataxamasTracking = class {
659
669
  ...this.measureReplay(),
660
670
  events
661
671
  });
672
+ this.recordingBytes += payload.length;
662
673
  this.saveRecording();
663
674
  void this.sendReplayBatch(payload, urgent);
664
675
  }
@@ -732,7 +743,7 @@ var DataxamasTracking = class {
732
743
  setupReplayLifecycle() {
733
744
  if (this.lifecycleReady) return;
734
745
  this.lifecycleReady = true;
735
- for (const type of ["pointerdown", "keydown", "wheel", "touchstart", "scroll"]) {
746
+ for (const type of ["pointerdown", "keydown", "wheel", "touchstart"]) {
736
747
  window.addEventListener(type, this.markReplayActivity, { passive: true, capture: true });
737
748
  }
738
749
  setInterval(() => {
@@ -740,7 +751,11 @@ var DataxamasTracking = class {
740
751
  }, REPLAY_FLUSH_INTERVAL_MS);
741
752
  setInterval(() => {
742
753
  if (!this.isRecording()) return;
743
- if (this.exceededReplayCaps()) this.scheduleReplayCutoff();
754
+ if (this.exceededReplayCaps()) {
755
+ this.scheduleReplayCutoff();
756
+ return;
757
+ }
758
+ if (Date.now() - this.lastActivityAt >= REPLAY_IDLE_SUSPEND_MS) this.stopReplayRecorder(false);
744
759
  }, CAP_CHECK_MS);
745
760
  window.addEventListener("pagehide", () => this.stopReplayRecorder(true));
746
761
  document.addEventListener("visibilitychange", () => {
package/dist/index.d.cts CHANGED
@@ -134,6 +134,7 @@ declare class DataxamasTracking {
134
134
  private recordingStartedAtMs;
135
135
  private recordingSeq;
136
136
  private recordingEvents;
137
+ private recordingBytes;
137
138
  private lastActivityAt;
138
139
  private lastActivitySavedAt;
139
140
  constructor(options: DataxamasTrackingOptions);
package/dist/index.d.ts CHANGED
@@ -134,6 +134,7 @@ declare class DataxamasTracking {
134
134
  private recordingStartedAtMs;
135
135
  private recordingSeq;
136
136
  private recordingEvents;
137
+ private recordingBytes;
137
138
  private lastActivityAt;
138
139
  private lastActivitySavedAt;
139
140
  constructor(options: DataxamasTrackingOptions);
package/dist/index.js CHANGED
@@ -314,21 +314,25 @@ var DataxamasLogs = class {
314
314
  }
315
315
  };
316
316
 
317
+ // ../tracker-shared/src/constants.ts
318
+ var MAX_RECORDING_MS = 10 * 60 * 1e3;
319
+ var MAX_EVENTS_PER_RECORDING = 15e3;
320
+ var MAX_BYTES_PER_RECORDING = 5 * 1024 * 1024;
321
+ var REPLAY_IDLE_TIMEOUT_MS = 10 * 60 * 1e3;
322
+ var REPLAY_IDLE_SUSPEND_MS = 60 * 1e3;
323
+
317
324
  // src/tracking.ts
318
325
  var QUEUE_DELAY_MS = 4e3;
319
326
  var STORAGE_PREFIX = "@dataxamas";
320
327
  var REPLAY_FLUSH_SIZE = 100;
321
328
  var REPLAY_FLUSH_INTERVAL_MS = 5e3;
322
329
  var CAP_CHECK_MS = 1e3;
323
- var MAX_RECORDING_MS = 30 * 60 * 1e3;
324
- var MAX_EVENTS_PER_RECORDING = 5e4;
325
- var REPLAY_IDLE_TIMEOUT_MS = 30 * 60 * 1e3;
326
330
  var ACTIVITY_SAVE_THROTTLE_MS = 5e3;
327
331
  var REPLAY_RECORDING_KEY = `${STORAGE_PREFIX}/replay-recording`;
328
332
  function isStoredRecording(value) {
329
333
  if (typeof value !== "object" || value === null) return false;
330
334
  const stored = value;
331
- return typeof stored.id === "string" && typeof stored.startedAt === "string" && typeof stored.startedAtMs === "number" && typeof stored.seq === "number" && typeof stored.events === "number" && typeof stored.lastActivityAt === "number" && typeof stored.capped === "boolean";
335
+ return typeof stored.id === "string" && typeof stored.startedAt === "string" && typeof stored.startedAtMs === "number" && typeof stored.seq === "number" && typeof stored.events === "number" && typeof stored.bytes === "number" && typeof stored.lastActivityAt === "number" && typeof stored.capped === "boolean";
332
336
  }
333
337
  var KEEPALIVE_LIMIT_BYTES = 60 * 1024;
334
338
  var DataxamasTracking = class {
@@ -381,6 +385,7 @@ var DataxamasTracking = class {
381
385
  this.recordingStartedAtMs = 0;
382
386
  this.recordingSeq = 0;
383
387
  this.recordingEvents = 0;
388
+ this.recordingBytes = 0;
384
389
  this.lastActivityAt = 0;
385
390
  this.lastActivitySavedAt = 0;
386
391
  }
@@ -571,6 +576,8 @@ var DataxamasTracking = class {
571
576
  webVitals.onLCP(queue);
572
577
  webVitals.onINP(queue);
573
578
  webVitals.onCLS(queue);
579
+ webVitals.onFCP(queue);
580
+ webVitals.onTTFB(queue);
574
581
  document.addEventListener("visibilitychange", () => {
575
582
  if (document.visibilityState === "hidden") this.flushVitals();
576
583
  });
@@ -589,7 +596,7 @@ var DataxamasTracking = class {
589
596
  return Boolean(this.stopRrweb);
590
597
  }
591
598
  exceededReplayCaps() {
592
- return this.recordingEvents >= MAX_EVENTS_PER_RECORDING || Date.now() - this.recordingStartedAtMs >= MAX_RECORDING_MS;
599
+ return this.recordingEvents >= MAX_EVENTS_PER_RECORDING || this.recordingBytes >= MAX_BYTES_PER_RECORDING || Date.now() - this.recordingStartedAtMs >= MAX_RECORDING_MS;
593
600
  }
594
601
  loadRecording() {
595
602
  try {
@@ -607,6 +614,7 @@ var DataxamasTracking = class {
607
614
  startedAtMs: this.recordingStartedAtMs,
608
615
  seq: this.recordingSeq,
609
616
  events: this.recordingEvents,
617
+ bytes: this.recordingBytes,
610
618
  lastActivityAt: this.lastActivityAt,
611
619
  capped: this.replayCapped
612
620
  };
@@ -622,6 +630,7 @@ var DataxamasTracking = class {
622
630
  this.recordingStartedAtMs = Date.now();
623
631
  this.recordingSeq = 0;
624
632
  this.recordingEvents = 0;
633
+ this.recordingBytes = 0;
625
634
  this.lastActivityAt = Date.now();
626
635
  this.saveRecording();
627
636
  }
@@ -638,6 +647,7 @@ var DataxamasTracking = class {
638
647
  this.recordingStartedAtMs = stored.startedAtMs;
639
648
  this.recordingSeq = stored.seq;
640
649
  this.recordingEvents = stored.events;
650
+ this.recordingBytes = stored.bytes;
641
651
  this.lastActivityAt = stored.lastActivityAt;
642
652
  }
643
653
  touchActivity(now) {
@@ -659,6 +669,7 @@ var DataxamasTracking = class {
659
669
  ...this.measureReplay(),
660
670
  events
661
671
  });
672
+ this.recordingBytes += payload.length;
662
673
  this.saveRecording();
663
674
  void this.sendReplayBatch(payload, urgent);
664
675
  }
@@ -732,7 +743,7 @@ var DataxamasTracking = class {
732
743
  setupReplayLifecycle() {
733
744
  if (this.lifecycleReady) return;
734
745
  this.lifecycleReady = true;
735
- for (const type of ["pointerdown", "keydown", "wheel", "touchstart", "scroll"]) {
746
+ for (const type of ["pointerdown", "keydown", "wheel", "touchstart"]) {
736
747
  window.addEventListener(type, this.markReplayActivity, { passive: true, capture: true });
737
748
  }
738
749
  setInterval(() => {
@@ -740,7 +751,11 @@ var DataxamasTracking = class {
740
751
  }, REPLAY_FLUSH_INTERVAL_MS);
741
752
  setInterval(() => {
742
753
  if (!this.isRecording()) return;
743
- if (this.exceededReplayCaps()) this.scheduleReplayCutoff();
754
+ if (this.exceededReplayCaps()) {
755
+ this.scheduleReplayCutoff();
756
+ return;
757
+ }
758
+ if (Date.now() - this.lastActivityAt >= REPLAY_IDLE_SUSPEND_MS) this.stopReplayRecorder(false);
744
759
  }, CAP_CHECK_MS);
745
760
  window.addEventListener("pagehide", () => this.stopReplayRecorder(true));
746
761
  document.addEventListener("visibilitychange", () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dataxamas/tracker-js",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "type": "module",
5
5
  "description": "Node.js SDK for Dataxamas Analytics API",
6
6
  "license": "MIT",
@@ -14,7 +14,8 @@
14
14
  "module": "./dist/index.js",
15
15
  "types": "./dist/index.d.ts",
16
16
  "files": [
17
- "dist"
17
+ "dist",
18
+ "CHANGELOG.md"
18
19
  ],
19
20
  "exports": {
20
21
  ".": {
@@ -26,14 +27,11 @@
26
27
  "types": "./dist/index.d.cts",
27
28
  "default": "./dist/index.cjs"
28
29
  }
29
- },
30
- "./script": "./src/script/bundle.ts",
31
- "./script/vite": "./src/script/vite.ts",
32
- "./script/virtual": "./src/script/virtual.d.ts"
30
+ }
33
31
  },
34
32
  "scripts": {
35
33
  "build": "tsup",
36
- "types": "tsc --noEmit && tsc --noEmit -p tsconfig.script.json",
34
+ "types": "tsc --noEmit",
37
35
  "lint": "biome lint",
38
36
  "lint:fix": "biome lint --write",
39
37
  "check": "biome check",
@@ -48,13 +46,12 @@
48
46
  ],
49
47
  "devDependencies": {
50
48
  "@dataxamas/biome-config": "workspace:*",
49
+ "@dataxamas/tracker-shared": "workspace:*",
51
50
  "@dataxamas/tsconfig": "workspace:*",
52
51
  "@types/node": "^26.1.0",
53
- "esbuild": "^0.28.1",
54
52
  "rrweb": "^2.1.0",
55
53
  "tsup": "^8.5.1",
56
54
  "typescript": "^5",
57
- "vite": "^8.0.16",
58
55
  "web-vitals": "^6.2.3"
59
56
  },
60
57
  "dependencies": {