@dataxamas/tracker-js 2.6.0 → 2.8.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,61 @@
1
+ ## 2.8.0
2
+
3
+ - Session replay records at most 30 seconds per visit, counted from the visitor's first gesture instead of page
4
+ load. After the cap the visit is not recorded again; a new recording only starts after 10 minutes without
5
+ interaction.
6
+ - The 1-minute idle pause is gone: the 30-second cap already ends the recording first.
7
+
8
+ ## 2.7.0
9
+
10
+ - Web Vitals also collect FCP (First Contentful Paint) and TTFB (Time to First Byte), sent in the same batch as
11
+ LCP, INP and CLS. Needs a Dataxamas server that already accepts both metrics.
12
+ - Session replay pauses the recorder after 1 minute without a gesture and resumes on the next one, in the same
13
+ recording. Limits now match the `dataxamas.js` script: 10 minutes, 15,000 events and 5 MB per recording.
14
+ - Element scroll no longer counts as activity, so an auto-scrolling carousel does not keep the recorder running.
15
+
16
+ ## 2.6.0
17
+
18
+ - No code changes; same build as 2.5.0.
19
+
20
+ ## 2.5.0
21
+
22
+ - `tracking.identify(userId | null)` links the visitor to your own user id for retention cohorts; the server stores
23
+ only a hash of it.
24
+
25
+ ## 2.4.0
26
+
27
+ - Visitors are identified server-side: the SDK no longer creates a session id and stores nothing in the browser
28
+ besides the replay key in `sessionStorage`.
29
+ - Replay sampling is decided by the server.
30
+
31
+ ## 2.3.0
32
+
33
+ - UTM attribution: only `utm_*` query params are sent.
34
+ - Web Vitals (LCP, INP, CLS), flushed on `visibilitychange` / `pagehide`.
35
+ - `tracking.track(name, data)` custom events for goals and funnels.
36
+
37
+ ## 2.1.3
38
+
39
+ - Tuned the replay idle timeout and recording limit.
40
+
41
+ ## 2.1.2
42
+
43
+ - Session replay keeps one recording per tab visit across route changes and reloads, closed after idle time or at the
44
+ size cap.
45
+ - Per-site replay sample rate.
46
+ - Skips automated browsers (`navigator.webdriver`).
47
+
48
+ ## 2.1.0
49
+
50
+ - Crawler tracking: `DataxamasCrawlers` (`trackRequest`, `track`), `isCrawlerUserAgent`, `withCrawlerTracking` and
51
+ `createExpressCrawlerMiddleware`.
52
+ - Default base URL is now `https://dataxamas.com`.
53
+
54
+ ## 2.0.1
55
+
56
+ - Packaging fix, no code changes.
57
+
58
+ ## 2.0.0
59
+
60
+ - Renamed to `@dataxamas/tracker-js` (was `dataxamas`).
61
+ - `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,40 +314,43 @@ var DataxamasLogs = class {
314
314
  }
315
315
  };
316
316
 
317
+ // ../tracker-shared/src/constants.ts
318
+ var MAX_RECORDING_MS = 30 * 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
+
317
323
  // src/tracking.ts
318
324
  var QUEUE_DELAY_MS = 4e3;
319
325
  var STORAGE_PREFIX = "@dataxamas";
320
326
  var REPLAY_FLUSH_SIZE = 100;
321
327
  var REPLAY_FLUSH_INTERVAL_MS = 5e3;
322
328
  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
329
  var ACTIVITY_SAVE_THROTTLE_MS = 5e3;
327
330
  var REPLAY_RECORDING_KEY = `${STORAGE_PREFIX}/replay-recording`;
328
331
  function isStoredRecording(value) {
329
332
  if (typeof value !== "object" || value === null) return false;
330
333
  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";
334
+ 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
335
  }
333
336
  var KEEPALIVE_LIMIT_BYTES = 60 * 1024;
334
337
  var DataxamasTracking = class {
335
338
  constructor(options) {
336
339
  /**
337
340
  * Primeiro gesto liga o gravador; os seguintes só o religam se ele tiver parado (aba que foi
338
- * para segundo plano, reload), no mesmo `recordingId`. Depois do teto ou de muito tempo parado,
339
- * o gesto abre uma gravação nova.
341
+ * para segundo plano, reload), no mesmo `recordingId`. Depois do teto a visita não grava mais;
342
+ * só um gesto depois de muito tempo parado abre uma gravação nova.
340
343
  */
341
344
  this.markReplayActivity = () => {
342
345
  if (this.replayHalted || this.cutoffPending) return;
343
346
  if (document.visibilityState === "hidden") return;
344
347
  const now = Date.now();
345
- if (this.replayCapped || now - this.lastActivityAt >= REPLAY_IDLE_TIMEOUT_MS) {
348
+ if (now - this.lastActivityAt >= REPLAY_IDLE_TIMEOUT_MS) {
346
349
  if (this.isRecording()) this.stopReplayRecorder(false);
347
350
  this.rotateRecording();
348
351
  }
349
352
  this.touchActivity(now);
350
- if (this.isRecording()) return;
353
+ if (this.replayCapped || this.isRecording()) return;
351
354
  this.startReplayRecorder();
352
355
  };
353
356
  if (!options.apiKey) {
@@ -381,6 +384,7 @@ var DataxamasTracking = class {
381
384
  this.recordingStartedAtMs = 0;
382
385
  this.recordingSeq = 0;
383
386
  this.recordingEvents = 0;
387
+ this.recordingBytes = 0;
384
388
  this.lastActivityAt = 0;
385
389
  this.lastActivitySavedAt = 0;
386
390
  }
@@ -571,6 +575,8 @@ var DataxamasTracking = class {
571
575
  webVitals.onLCP(queue);
572
576
  webVitals.onINP(queue);
573
577
  webVitals.onCLS(queue);
578
+ webVitals.onFCP(queue);
579
+ webVitals.onTTFB(queue);
574
580
  document.addEventListener("visibilitychange", () => {
575
581
  if (document.visibilityState === "hidden") this.flushVitals();
576
582
  });
@@ -589,7 +595,7 @@ var DataxamasTracking = class {
589
595
  return Boolean(this.stopRrweb);
590
596
  }
591
597
  exceededReplayCaps() {
592
- return this.recordingEvents >= MAX_EVENTS_PER_RECORDING || Date.now() - this.recordingStartedAtMs >= MAX_RECORDING_MS;
598
+ return this.recordingEvents >= MAX_EVENTS_PER_RECORDING || this.recordingBytes >= MAX_BYTES_PER_RECORDING || Date.now() - this.recordingStartedAtMs >= MAX_RECORDING_MS;
593
599
  }
594
600
  loadRecording() {
595
601
  try {
@@ -607,6 +613,7 @@ var DataxamasTracking = class {
607
613
  startedAtMs: this.recordingStartedAtMs,
608
614
  seq: this.recordingSeq,
609
615
  events: this.recordingEvents,
616
+ bytes: this.recordingBytes,
610
617
  lastActivityAt: this.lastActivityAt,
611
618
  capped: this.replayCapped
612
619
  };
@@ -622,22 +629,27 @@ var DataxamasTracking = class {
622
629
  this.recordingStartedAtMs = Date.now();
623
630
  this.recordingSeq = 0;
624
631
  this.recordingEvents = 0;
632
+ this.recordingBytes = 0;
625
633
  this.lastActivityAt = Date.now();
626
634
  this.saveRecording();
627
635
  }
628
- /** Reload ou navegação completa na mesma aba continua a gravação, se a visita ainda estiver ativa. */
636
+ /**
637
+ * Reload ou navegação completa na mesma aba continua a gravação, se a visita ainda estiver ativa.
638
+ * Se ela já bateu o teto, segue sem gravar.
639
+ */
629
640
  resumeOrRotateRecording() {
630
641
  const stored = this.loadRecording();
631
- if (!stored || stored.capped || Date.now() - stored.lastActivityAt >= REPLAY_IDLE_TIMEOUT_MS) {
642
+ if (!stored || Date.now() - stored.lastActivityAt >= REPLAY_IDLE_TIMEOUT_MS) {
632
643
  this.rotateRecording();
633
644
  return;
634
645
  }
635
- this.replayCapped = false;
646
+ this.replayCapped = stored.capped;
636
647
  this.recordingId = stored.id;
637
648
  this.recordingStartedAt = stored.startedAt;
638
649
  this.recordingStartedAtMs = stored.startedAtMs;
639
650
  this.recordingSeq = stored.seq;
640
651
  this.recordingEvents = stored.events;
652
+ this.recordingBytes = stored.bytes;
641
653
  this.lastActivityAt = stored.lastActivityAt;
642
654
  }
643
655
  touchActivity(now) {
@@ -659,6 +671,7 @@ var DataxamasTracking = class {
659
671
  ...this.measureReplay(),
660
672
  events
661
673
  });
674
+ this.recordingBytes += payload.length;
662
675
  this.saveRecording();
663
676
  void this.sendReplayBatch(payload, urgent);
664
677
  }
@@ -716,8 +729,8 @@ var DataxamasTracking = class {
716
729
  }
717
730
  }
718
731
  /**
719
- * Bateu o teto: encerra a gravação e fica parado até a próxima interação, em vez de emendar um
720
- * clipe atrás do outro enquanto a página só anima sozinha.
732
+ * Bateu o teto: encerra a gravação e a visita não grava mais, em vez de emendar um clipe atrás do
733
+ * outro.
721
734
  */
722
735
  scheduleReplayCutoff() {
723
736
  if (this.cutoffPending) return;
@@ -732,7 +745,7 @@ var DataxamasTracking = class {
732
745
  setupReplayLifecycle() {
733
746
  if (this.lifecycleReady) return;
734
747
  this.lifecycleReady = true;
735
- for (const type of ["pointerdown", "keydown", "wheel", "touchstart", "scroll"]) {
748
+ for (const type of ["pointerdown", "keydown", "wheel", "touchstart"]) {
736
749
  window.addEventListener(type, this.markReplayActivity, { passive: true, capture: true });
737
750
  }
738
751
  setInterval(() => {
@@ -762,9 +775,17 @@ var DataxamasTracking = class {
762
775
  }
763
776
  if (this.isRecording() || this.replayHalted) return;
764
777
  if (!this.recordingId) this.rotateRecording();
778
+ if (this.recordingSeq === 0) {
779
+ this.recordingStartedAt = (/* @__PURE__ */ new Date()).toISOString();
780
+ this.recordingStartedAtMs = Date.now();
781
+ }
765
782
  this.snapshotFlushed = false;
766
783
  this.stopRrweb = this.rrwebRecord({
767
784
  emit: (event) => {
785
+ if (this.exceededReplayCaps()) {
786
+ this.scheduleReplayCutoff();
787
+ return;
788
+ }
768
789
  this.replayBuffer.push(event);
769
790
  this.recordingEvents++;
770
791
  if (!this.snapshotFlushed && event.type === 2) {
@@ -772,10 +793,6 @@ var DataxamasTracking = class {
772
793
  this.flushReplay(false);
773
794
  return;
774
795
  }
775
- if (this.exceededReplayCaps()) {
776
- this.scheduleReplayCutoff();
777
- return;
778
- }
779
796
  if (this.replayBuffer.length >= REPLAY_FLUSH_SIZE) this.flushReplay(false);
780
797
  },
781
798
  maskAllInputs: true,
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);
@@ -157,7 +158,10 @@ declare class DataxamasTracking {
157
158
  private loadRecording;
158
159
  private saveRecording;
159
160
  private rotateRecording;
160
- /** Reload ou navegação completa na mesma aba continua a gravação, se a visita ainda estiver ativa. */
161
+ /**
162
+ * Reload ou navegação completa na mesma aba continua a gravação, se a visita ainda estiver ativa.
163
+ * Se ela já bateu o teto, segue sem gravar.
164
+ */
161
165
  private resumeOrRotateRecording;
162
166
  private touchActivity;
163
167
  private flushReplay;
@@ -169,14 +173,14 @@ declare class DataxamasTracking {
169
173
  private sendReplayBatch;
170
174
  private stopReplayRecorder;
171
175
  /**
172
- * Bateu o teto: encerra a gravação e fica parado até a próxima interação, em vez de emendar um
173
- * clipe atrás do outro enquanto a página só anima sozinha.
176
+ * Bateu o teto: encerra a gravação e a visita não grava mais, em vez de emendar um clipe atrás do
177
+ * outro.
174
178
  */
175
179
  private scheduleReplayCutoff;
176
180
  /**
177
181
  * Primeiro gesto liga o gravador; os seguintes só o religam se ele tiver parado (aba que foi
178
- * para segundo plano, reload), no mesmo `recordingId`. Depois do teto ou de muito tempo parado,
179
- * o gesto abre uma gravação nova.
182
+ * para segundo plano, reload), no mesmo `recordingId`. Depois do teto a visita não grava mais;
183
+ * só um gesto depois de muito tempo parado abre uma gravação nova.
180
184
  */
181
185
  private markReplayActivity;
182
186
  private setupReplayLifecycle;
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);
@@ -157,7 +158,10 @@ declare class DataxamasTracking {
157
158
  private loadRecording;
158
159
  private saveRecording;
159
160
  private rotateRecording;
160
- /** Reload ou navegação completa na mesma aba continua a gravação, se a visita ainda estiver ativa. */
161
+ /**
162
+ * Reload ou navegação completa na mesma aba continua a gravação, se a visita ainda estiver ativa.
163
+ * Se ela já bateu o teto, segue sem gravar.
164
+ */
161
165
  private resumeOrRotateRecording;
162
166
  private touchActivity;
163
167
  private flushReplay;
@@ -169,14 +173,14 @@ declare class DataxamasTracking {
169
173
  private sendReplayBatch;
170
174
  private stopReplayRecorder;
171
175
  /**
172
- * Bateu o teto: encerra a gravação e fica parado até a próxima interação, em vez de emendar um
173
- * clipe atrás do outro enquanto a página só anima sozinha.
176
+ * Bateu o teto: encerra a gravação e a visita não grava mais, em vez de emendar um clipe atrás do
177
+ * outro.
174
178
  */
175
179
  private scheduleReplayCutoff;
176
180
  /**
177
181
  * Primeiro gesto liga o gravador; os seguintes só o religam se ele tiver parado (aba que foi
178
- * para segundo plano, reload), no mesmo `recordingId`. Depois do teto ou de muito tempo parado,
179
- * o gesto abre uma gravação nova.
182
+ * para segundo plano, reload), no mesmo `recordingId`. Depois do teto a visita não grava mais;
183
+ * só um gesto depois de muito tempo parado abre uma gravação nova.
180
184
  */
181
185
  private markReplayActivity;
182
186
  private setupReplayLifecycle;
package/dist/index.js CHANGED
@@ -314,40 +314,43 @@ var DataxamasLogs = class {
314
314
  }
315
315
  };
316
316
 
317
+ // ../tracker-shared/src/constants.ts
318
+ var MAX_RECORDING_MS = 30 * 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
+
317
323
  // src/tracking.ts
318
324
  var QUEUE_DELAY_MS = 4e3;
319
325
  var STORAGE_PREFIX = "@dataxamas";
320
326
  var REPLAY_FLUSH_SIZE = 100;
321
327
  var REPLAY_FLUSH_INTERVAL_MS = 5e3;
322
328
  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
329
  var ACTIVITY_SAVE_THROTTLE_MS = 5e3;
327
330
  var REPLAY_RECORDING_KEY = `${STORAGE_PREFIX}/replay-recording`;
328
331
  function isStoredRecording(value) {
329
332
  if (typeof value !== "object" || value === null) return false;
330
333
  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";
334
+ 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
335
  }
333
336
  var KEEPALIVE_LIMIT_BYTES = 60 * 1024;
334
337
  var DataxamasTracking = class {
335
338
  constructor(options) {
336
339
  /**
337
340
  * Primeiro gesto liga o gravador; os seguintes só o religam se ele tiver parado (aba que foi
338
- * para segundo plano, reload), no mesmo `recordingId`. Depois do teto ou de muito tempo parado,
339
- * o gesto abre uma gravação nova.
341
+ * para segundo plano, reload), no mesmo `recordingId`. Depois do teto a visita não grava mais;
342
+ * só um gesto depois de muito tempo parado abre uma gravação nova.
340
343
  */
341
344
  this.markReplayActivity = () => {
342
345
  if (this.replayHalted || this.cutoffPending) return;
343
346
  if (document.visibilityState === "hidden") return;
344
347
  const now = Date.now();
345
- if (this.replayCapped || now - this.lastActivityAt >= REPLAY_IDLE_TIMEOUT_MS) {
348
+ if (now - this.lastActivityAt >= REPLAY_IDLE_TIMEOUT_MS) {
346
349
  if (this.isRecording()) this.stopReplayRecorder(false);
347
350
  this.rotateRecording();
348
351
  }
349
352
  this.touchActivity(now);
350
- if (this.isRecording()) return;
353
+ if (this.replayCapped || this.isRecording()) return;
351
354
  this.startReplayRecorder();
352
355
  };
353
356
  if (!options.apiKey) {
@@ -381,6 +384,7 @@ var DataxamasTracking = class {
381
384
  this.recordingStartedAtMs = 0;
382
385
  this.recordingSeq = 0;
383
386
  this.recordingEvents = 0;
387
+ this.recordingBytes = 0;
384
388
  this.lastActivityAt = 0;
385
389
  this.lastActivitySavedAt = 0;
386
390
  }
@@ -571,6 +575,8 @@ var DataxamasTracking = class {
571
575
  webVitals.onLCP(queue);
572
576
  webVitals.onINP(queue);
573
577
  webVitals.onCLS(queue);
578
+ webVitals.onFCP(queue);
579
+ webVitals.onTTFB(queue);
574
580
  document.addEventListener("visibilitychange", () => {
575
581
  if (document.visibilityState === "hidden") this.flushVitals();
576
582
  });
@@ -589,7 +595,7 @@ var DataxamasTracking = class {
589
595
  return Boolean(this.stopRrweb);
590
596
  }
591
597
  exceededReplayCaps() {
592
- return this.recordingEvents >= MAX_EVENTS_PER_RECORDING || Date.now() - this.recordingStartedAtMs >= MAX_RECORDING_MS;
598
+ return this.recordingEvents >= MAX_EVENTS_PER_RECORDING || this.recordingBytes >= MAX_BYTES_PER_RECORDING || Date.now() - this.recordingStartedAtMs >= MAX_RECORDING_MS;
593
599
  }
594
600
  loadRecording() {
595
601
  try {
@@ -607,6 +613,7 @@ var DataxamasTracking = class {
607
613
  startedAtMs: this.recordingStartedAtMs,
608
614
  seq: this.recordingSeq,
609
615
  events: this.recordingEvents,
616
+ bytes: this.recordingBytes,
610
617
  lastActivityAt: this.lastActivityAt,
611
618
  capped: this.replayCapped
612
619
  };
@@ -622,22 +629,27 @@ var DataxamasTracking = class {
622
629
  this.recordingStartedAtMs = Date.now();
623
630
  this.recordingSeq = 0;
624
631
  this.recordingEvents = 0;
632
+ this.recordingBytes = 0;
625
633
  this.lastActivityAt = Date.now();
626
634
  this.saveRecording();
627
635
  }
628
- /** Reload ou navegação completa na mesma aba continua a gravação, se a visita ainda estiver ativa. */
636
+ /**
637
+ * Reload ou navegação completa na mesma aba continua a gravação, se a visita ainda estiver ativa.
638
+ * Se ela já bateu o teto, segue sem gravar.
639
+ */
629
640
  resumeOrRotateRecording() {
630
641
  const stored = this.loadRecording();
631
- if (!stored || stored.capped || Date.now() - stored.lastActivityAt >= REPLAY_IDLE_TIMEOUT_MS) {
642
+ if (!stored || Date.now() - stored.lastActivityAt >= REPLAY_IDLE_TIMEOUT_MS) {
632
643
  this.rotateRecording();
633
644
  return;
634
645
  }
635
- this.replayCapped = false;
646
+ this.replayCapped = stored.capped;
636
647
  this.recordingId = stored.id;
637
648
  this.recordingStartedAt = stored.startedAt;
638
649
  this.recordingStartedAtMs = stored.startedAtMs;
639
650
  this.recordingSeq = stored.seq;
640
651
  this.recordingEvents = stored.events;
652
+ this.recordingBytes = stored.bytes;
641
653
  this.lastActivityAt = stored.lastActivityAt;
642
654
  }
643
655
  touchActivity(now) {
@@ -659,6 +671,7 @@ var DataxamasTracking = class {
659
671
  ...this.measureReplay(),
660
672
  events
661
673
  });
674
+ this.recordingBytes += payload.length;
662
675
  this.saveRecording();
663
676
  void this.sendReplayBatch(payload, urgent);
664
677
  }
@@ -716,8 +729,8 @@ var DataxamasTracking = class {
716
729
  }
717
730
  }
718
731
  /**
719
- * Bateu o teto: encerra a gravação e fica parado até a próxima interação, em vez de emendar um
720
- * clipe atrás do outro enquanto a página só anima sozinha.
732
+ * Bateu o teto: encerra a gravação e a visita não grava mais, em vez de emendar um clipe atrás do
733
+ * outro.
721
734
  */
722
735
  scheduleReplayCutoff() {
723
736
  if (this.cutoffPending) return;
@@ -732,7 +745,7 @@ var DataxamasTracking = class {
732
745
  setupReplayLifecycle() {
733
746
  if (this.lifecycleReady) return;
734
747
  this.lifecycleReady = true;
735
- for (const type of ["pointerdown", "keydown", "wheel", "touchstart", "scroll"]) {
748
+ for (const type of ["pointerdown", "keydown", "wheel", "touchstart"]) {
736
749
  window.addEventListener(type, this.markReplayActivity, { passive: true, capture: true });
737
750
  }
738
751
  setInterval(() => {
@@ -762,9 +775,17 @@ var DataxamasTracking = class {
762
775
  }
763
776
  if (this.isRecording() || this.replayHalted) return;
764
777
  if (!this.recordingId) this.rotateRecording();
778
+ if (this.recordingSeq === 0) {
779
+ this.recordingStartedAt = (/* @__PURE__ */ new Date()).toISOString();
780
+ this.recordingStartedAtMs = Date.now();
781
+ }
765
782
  this.snapshotFlushed = false;
766
783
  this.stopRrweb = this.rrwebRecord({
767
784
  emit: (event) => {
785
+ if (this.exceededReplayCaps()) {
786
+ this.scheduleReplayCutoff();
787
+ return;
788
+ }
768
789
  this.replayBuffer.push(event);
769
790
  this.recordingEvents++;
770
791
  if (!this.snapshotFlushed && event.type === 2) {
@@ -772,10 +793,6 @@ var DataxamasTracking = class {
772
793
  this.flushReplay(false);
773
794
  return;
774
795
  }
775
- if (this.exceededReplayCaps()) {
776
- this.scheduleReplayCutoff();
777
- return;
778
- }
779
796
  if (this.replayBuffer.length >= REPLAY_FLUSH_SIZE) this.flushReplay(false);
780
797
  },
781
798
  maskAllInputs: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dataxamas/tracker-js",
3
- "version": "2.6.0",
3
+ "version": "2.8.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": {