@brainfish-ai/web-tracker 0.0.28 → 0.0.30

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.
@@ -3574,7 +3574,7 @@ const _TrackerSdk = class _TrackerSdk {
3574
3574
  delete this.eventListeners[event];
3575
3575
  }
3576
3576
  }
3577
- async send(payload, responseCallback) {
3577
+ async send(payload) {
3578
3578
  if (this.options.disabled) {
3579
3579
  return Promise.resolve();
3580
3580
  }
@@ -3588,7 +3588,7 @@ const _TrackerSdk = class _TrackerSdk {
3588
3588
  this.queue.push(payload);
3589
3589
  return Promise.resolve();
3590
3590
  }
3591
- return this.client.send("t", payload, responseCallback);
3591
+ return this.client.send("t", payload);
3592
3592
  }
3593
3593
  setGlobalProperties(properties) {
3594
3594
  this.global = {
@@ -3663,6 +3663,18 @@ const _TrackerSdk = class _TrackerSdk {
3663
3663
  });
3664
3664
  }
3665
3665
  }
3666
+ async getSessionId() {
3667
+ if (this.options.disabled) {
3668
+ return Promise.resolve(null);
3669
+ }
3670
+ if (this.trackingDisabled) {
3671
+ return Promise.resolve(null);
3672
+ }
3673
+ const response = await this.httpClient.send("/sid", {
3674
+ userId: this.userId
3675
+ });
3676
+ return response?.sessionId || null;
3677
+ }
3666
3678
  async record(events) {
3667
3679
  if (this.options.disabled) {
3668
3680
  return Promise.resolve(null);
@@ -24456,6 +24468,212 @@ class Stasher {
24456
24468
  });
24457
24469
  }
24458
24470
  }
24471
+ const USER_ACTIONS = [
24472
+ IncrementalSource.MouseMove,
24473
+ IncrementalSource.MouseInteraction,
24474
+ IncrementalSource.Scroll,
24475
+ IncrementalSource.ViewportResize,
24476
+ IncrementalSource.Input,
24477
+ IncrementalSource.TouchMove,
24478
+ IncrementalSource.MediaInteraction,
24479
+ IncrementalSource.Drag
24480
+ ];
24481
+ class RecordingManager {
24482
+ constructor(agent) {
24483
+ __publicField(this, "agent");
24484
+ __publicField(this, "recorder");
24485
+ __publicField(this, "stasher");
24486
+ this.agent = agent;
24487
+ this.recorder = new Recorder(this.handleEvent.bind(this));
24488
+ this.stasher = new Stasher(this);
24489
+ }
24490
+ start() {
24491
+ this.recorder.start();
24492
+ }
24493
+ handleEvent(event) {
24494
+ const url2 = new URL(window.location.href);
24495
+ const cleanUrl = url2.origin + url2.pathname;
24496
+ if (this.agent.sessionManager.isIdle) {
24497
+ if (this.isInteractiveEvent(event)) {
24498
+ this.agent.handleActivityDuringIdle();
24499
+ } else {
24500
+ return;
24501
+ }
24502
+ }
24503
+ if (this.isClick(event)) {
24504
+ let clickedNode = record.mirror.getNode(event.data.id);
24505
+ if (clickedNode && this.nodeIsInteresting(clickedNode)) {
24506
+ event["conversionData"] = {};
24507
+ event.conversionData.eventType = "click";
24508
+ event.conversionData.textContent = clickedNode.textContent;
24509
+ event.conversionData.htmlElement = clickedNode.nodeName?.toLowerCase();
24510
+ event.conversionData.location = cleanUrl;
24511
+ }
24512
+ }
24513
+ if (this.isCustom(event)) {
24514
+ event["conversionData"] = {};
24515
+ event.conversionData.eventType = "custom";
24516
+ event.conversionData.customEventType = event.data.tag;
24517
+ event.conversionData.location = cleanUrl;
24518
+ }
24519
+ if (this.stasher.isRunning) {
24520
+ this.stasher.handle(event);
24521
+ return;
24522
+ }
24523
+ this.publishEvent(event);
24524
+ }
24525
+ publishEvent(event) {
24526
+ this.agent.sender.handle(event);
24527
+ if (this.agent.timer) {
24528
+ this.agent.timer.restart();
24529
+ }
24530
+ }
24531
+ startRecorderWithStasher() {
24532
+ this.stasher.start();
24533
+ this.recorder = new Recorder(this.handleEvent.bind(this));
24534
+ this.recorder.start();
24535
+ }
24536
+ isClick(event) {
24537
+ return event.type === EventType.IncrementalSnapshot && // incremental snapshot event
24538
+ event.data.source === IncrementalSource.MouseInteraction && // source of incremental snapshot is a mouse action
24539
+ event.data.type === MouseInteractions.Click;
24540
+ }
24541
+ nodeIsInteresting(clickedNode) {
24542
+ return clickedNode.nodeName === "BUTTON" || clickedNode.nodeName === "ANCHOR";
24543
+ }
24544
+ isCustom(event) {
24545
+ return event.type === EventType.Custom;
24546
+ }
24547
+ isInteractiveEvent(event) {
24548
+ return event.type === EventType.IncrementalSnapshot && USER_ACTIONS.includes(event.data?.source);
24549
+ }
24550
+ }
24551
+ class Timer {
24552
+ constructor(agent, MAX_IDLE_TIME2) {
24553
+ __publicField(this, "agent");
24554
+ __publicField(this, "MAX_IDLE_TIME");
24555
+ __publicField(this, "timeoutId");
24556
+ this.agent = agent;
24557
+ this.MAX_IDLE_TIME = MAX_IDLE_TIME2;
24558
+ this.timeoutId = 0;
24559
+ }
24560
+ restart() {
24561
+ this.stop();
24562
+ this.start();
24563
+ }
24564
+ stop() {
24565
+ clearTimeout(this.timeoutId);
24566
+ }
24567
+ start() {
24568
+ this.timeoutId = window.setTimeout(
24569
+ this.agent.handleTimeout.bind(this.agent),
24570
+ this.MAX_IDLE_TIME
24571
+ );
24572
+ }
24573
+ }
24574
+ const _SessionManager = class _SessionManager {
24575
+ constructor() {
24576
+ __publicField(this, "sessionId", null);
24577
+ __publicField(this, "lastScreenViewEventTime", 0);
24578
+ __publicField(this, "isIdle", false);
24579
+ }
24580
+ static getInstance() {
24581
+ if (!_SessionManager.instance) {
24582
+ _SessionManager.instance = new _SessionManager();
24583
+ }
24584
+ return _SessionManager.instance;
24585
+ }
24586
+ /**
24587
+ * Determines the current session state based on previous and current session IDs
24588
+ */
24589
+ determineSessionState(newSessionId) {
24590
+ if (!this.sessionId && newSessionId) {
24591
+ return "new";
24592
+ }
24593
+ if (this.sessionId && newSessionId && this.sessionId !== newSessionId) {
24594
+ return "changed";
24595
+ }
24596
+ if (this.sessionId === newSessionId && this.sessionId !== null) {
24597
+ return "active";
24598
+ }
24599
+ return "expired";
24600
+ }
24601
+ /**
24602
+ * Handles session state transitions and triggers appropriate actions
24603
+ */
24604
+ handleSessionTransition(state, callbacks) {
24605
+ switch (state) {
24606
+ case "new":
24607
+ case "changed":
24608
+ this.updateIdleStatus(false);
24609
+ callbacks.takeFullSnapshot?.();
24610
+ break;
24611
+ }
24612
+ }
24613
+ /**
24614
+ * Updates the session state based on a new session ID
24615
+ * @param newSessionId The new session ID from the server
24616
+ * @param callbacks Optional callbacks for session state changes
24617
+ */
24618
+ updateSession(newSessionId, callbacks = {}) {
24619
+ const sessionState = this.determineSessionState(newSessionId);
24620
+ this.handleSessionTransition(sessionState, callbacks);
24621
+ this.sessionId = newSessionId;
24622
+ }
24623
+ updateLastScreenViewEventTime() {
24624
+ this.lastScreenViewEventTime = Date.now();
24625
+ }
24626
+ updateIdleStatus(isIdle) {
24627
+ this.isIdle = isIdle;
24628
+ }
24629
+ getLastScreenViewEventTime() {
24630
+ return this.lastScreenViewEventTime;
24631
+ }
24632
+ getCurrentSessionId() {
24633
+ return this.sessionId;
24634
+ }
24635
+ };
24636
+ __publicField(_SessionManager, "instance");
24637
+ let SessionManager = _SessionManager;
24638
+ class UrlMonitor {
24639
+ constructor(callback) {
24640
+ __publicField(this, "currentUrl");
24641
+ __publicField(this, "callback");
24642
+ __publicField(this, "originalPushState");
24643
+ __publicField(this, "originalReplaceState");
24644
+ __publicField(this, "handlePopState", () => {
24645
+ this.checkUrlChange();
24646
+ });
24647
+ this.currentUrl = window.location.href;
24648
+ this.callback = callback;
24649
+ this.originalPushState = history.pushState;
24650
+ this.originalReplaceState = history.replaceState;
24651
+ this.setupListeners();
24652
+ }
24653
+ setupListeners() {
24654
+ window.addEventListener("popstate", this.handlePopState);
24655
+ history.pushState = (...args) => {
24656
+ this.originalPushState.apply(history, args);
24657
+ this.checkUrlChange();
24658
+ };
24659
+ history.replaceState = (...args) => {
24660
+ this.originalReplaceState.apply(history, args);
24661
+ this.checkUrlChange();
24662
+ };
24663
+ }
24664
+ checkUrlChange() {
24665
+ const newUrl = window.location.href;
24666
+ if (newUrl !== this.currentUrl) {
24667
+ this.currentUrl = newUrl;
24668
+ this.callback();
24669
+ }
24670
+ }
24671
+ destroy() {
24672
+ history.pushState = this.originalPushState;
24673
+ history.replaceState = this.originalReplaceState;
24674
+ window.removeEventListener("popstate", this.handlePopState);
24675
+ }
24676
+ }
24459
24677
  function lexer(str) {
24460
24678
  var tokens = [];
24461
24679
  var i = 0;
@@ -24795,181 +25013,9 @@ function canDiscover(recordingBlocklist, allowLocalhostRecording) {
24795
25013
  }
24796
25014
  return true;
24797
25015
  }
24798
- const USER_ACTIONS = [
24799
- IncrementalSource.MouseMove,
24800
- IncrementalSource.MouseInteraction,
24801
- IncrementalSource.Scroll,
24802
- IncrementalSource.ViewportResize,
24803
- IncrementalSource.Input,
24804
- IncrementalSource.TouchMove,
24805
- IncrementalSource.MediaInteraction,
24806
- IncrementalSource.Drag
24807
- ];
24808
- class RecordingManager {
24809
- constructor(agent) {
24810
- __publicField(this, "agent");
24811
- __publicField(this, "recorder");
24812
- __publicField(this, "stasher");
24813
- this.agent = agent;
24814
- this.recorder = new Recorder(this.handleEvent.bind(this));
24815
- this.stasher = new Stasher(this);
24816
- }
24817
- start() {
24818
- this.recorder.start();
24819
- }
24820
- handleEvent(event) {
24821
- const url2 = new URL(window.location.href);
24822
- const cleanUrl = url2.origin + url2.pathname;
24823
- if (!canDiscover(
24824
- this.agent.recordingBlocklist,
24825
- this.agent._allowLocalhostRecording
24826
- )) {
24827
- return;
24828
- }
24829
- if (this.agent.sessionManager.isIdle) {
24830
- if (this.isInteractiveEvent(event)) {
24831
- this.agent.handleActivityDuringIdle();
24832
- } else {
24833
- return;
24834
- }
24835
- }
24836
- if (this.isClick(event)) {
24837
- let clickedNode = record.mirror.getNode(event.data.id);
24838
- if (clickedNode && this.nodeIsInteresting(clickedNode)) {
24839
- event["conversionData"] = {};
24840
- event.conversionData.eventType = "click";
24841
- event.conversionData.textContent = clickedNode.textContent;
24842
- event.conversionData.htmlElement = clickedNode.nodeName?.toLowerCase();
24843
- event.conversionData.location = cleanUrl;
24844
- }
24845
- }
24846
- if (this.isCustom(event)) {
24847
- event["conversionData"] = {};
24848
- event.conversionData.eventType = "custom";
24849
- event.conversionData.customEventType = event.data.tag;
24850
- event.conversionData.location = cleanUrl;
24851
- }
24852
- if (this.stasher.isRunning) {
24853
- this.stasher.handle(event);
24854
- return;
24855
- }
24856
- this.publishEvent(event);
24857
- }
24858
- publishEvent(event) {
24859
- this.agent.sender.handle(event);
24860
- if (this.agent.timer) {
24861
- this.agent.timer.restart();
24862
- }
24863
- }
24864
- startRecorderWithStasher() {
24865
- this.stasher.start();
24866
- this.recorder = new Recorder(this.handleEvent.bind(this));
24867
- this.recorder.start();
24868
- }
24869
- isClick(event) {
24870
- return event.type === EventType.IncrementalSnapshot && // incremental snapshot event
24871
- event.data.source === IncrementalSource.MouseInteraction && // source of incremental snapshot is a mouse action
24872
- event.data.type === MouseInteractions.Click;
24873
- }
24874
- nodeIsInteresting(clickedNode) {
24875
- return clickedNode.nodeName === "BUTTON" || clickedNode.nodeName === "ANCHOR";
24876
- }
24877
- isCustom(event) {
24878
- return event.type === EventType.Custom;
24879
- }
24880
- isInteractiveEvent(event) {
24881
- return event.type === EventType.IncrementalSnapshot && USER_ACTIONS.includes(event.data?.source);
24882
- }
24883
- }
24884
- class Timer {
24885
- constructor(agent, MAX_IDLE_TIME2) {
24886
- __publicField(this, "agent");
24887
- __publicField(this, "MAX_IDLE_TIME");
24888
- __publicField(this, "timeoutId");
24889
- this.agent = agent;
24890
- this.MAX_IDLE_TIME = MAX_IDLE_TIME2;
24891
- this.timeoutId = 0;
24892
- }
24893
- restart() {
24894
- this.stop();
24895
- this.start();
24896
- }
24897
- stop() {
24898
- clearTimeout(this.timeoutId);
24899
- }
24900
- start() {
24901
- this.timeoutId = window.setTimeout(
24902
- this.agent.handleTimeout.bind(this.agent),
24903
- this.MAX_IDLE_TIME
24904
- );
24905
- }
24906
- }
24907
- const _SessionManager = class _SessionManager {
24908
- constructor() {
24909
- __publicField(this, "sessionId", null);
24910
- __publicField(this, "lastScreenViewEventTime", 0);
24911
- __publicField(this, "isIdle", false);
24912
- }
24913
- static getInstance() {
24914
- if (!_SessionManager.instance) {
24915
- _SessionManager.instance = new _SessionManager();
24916
- }
24917
- return _SessionManager.instance;
24918
- }
24919
- /**
24920
- * Determines the current session state based on previous and current session IDs
24921
- */
24922
- determineSessionState(newSessionId) {
24923
- if (!this.sessionId && newSessionId) {
24924
- return "new";
24925
- }
24926
- if (this.sessionId && newSessionId && this.sessionId !== newSessionId) {
24927
- return "changed";
24928
- }
24929
- if (this.sessionId === newSessionId && this.sessionId !== null) {
24930
- return "active";
24931
- }
24932
- return "expired";
24933
- }
24934
- /**
24935
- * Handles session state transitions and triggers appropriate actions
24936
- */
24937
- handleSessionTransition(state, callbacks) {
24938
- switch (state) {
24939
- case "new":
24940
- case "changed":
24941
- this.updateIdleStatus(false);
24942
- callbacks.takeFullSnapshot?.();
24943
- break;
24944
- }
24945
- }
24946
- /**
24947
- * Updates the session state based on a new session ID
24948
- * @param newSessionId The new session ID from the server
24949
- * @param callbacks Optional callbacks for session state changes
24950
- */
24951
- updateSession(newSessionId, callbacks = {}) {
24952
- const sessionState = this.determineSessionState(newSessionId);
24953
- this.handleSessionTransition(sessionState, callbacks);
24954
- this.sessionId = newSessionId;
24955
- }
24956
- updateLastScreenViewEventTime() {
24957
- this.lastScreenViewEventTime = Date.now();
24958
- }
24959
- updateIdleStatus(isIdle) {
24960
- this.isIdle = isIdle;
24961
- }
24962
- getLastScreenViewEventTime() {
24963
- return this.lastScreenViewEventTime;
24964
- }
24965
- getCurrentSessionId() {
24966
- return this.sessionId;
24967
- }
24968
- };
24969
- __publicField(_SessionManager, "instance");
24970
- let SessionManager = _SessionManager;
24971
25016
  const MAX_IDLE_TIME = 60 * 1e3;
24972
25017
  const SCREEN_VIEW_EVENT_COOLDOWN = 5 * 1e3;
25018
+ const RESUME_RECORDING_DEBOUNCE_MS = 3e3;
24973
25019
  const _Agent = class _Agent {
24974
25020
  constructor() {
24975
25021
  __publicField(this, "recordingManager");
@@ -24981,6 +25027,9 @@ const _Agent = class _Agent {
24981
25027
  __publicField(this, "recordingBlocklist", []);
24982
25028
  __publicField(this, "_allowLocalhostRecording");
24983
25029
  __publicField(this, "sessionCreationPromise", null);
25030
+ __publicField(this, "urlMonitor");
25031
+ __publicField(this, "isRecordingStopped", false);
25032
+ __publicField(this, "resumeRecordingTimer");
24984
25033
  this.recordingManager = new RecordingManager(this);
24985
25034
  this.sender = new Sender(this);
24986
25035
  }
@@ -25000,7 +25049,61 @@ const _Agent = class _Agent {
25000
25049
  this.MAX_IDLE_TIME = MAX_IDLE_TIME;
25001
25050
  this.timer = new Timer(this, this.MAX_IDLE_TIME);
25002
25051
  this.sender.start();
25003
- this.recordingManager.start();
25052
+ const shouldRecordInitialPage = canDiscover(
25053
+ this.recordingBlocklist,
25054
+ this._allowLocalhostRecording
25055
+ );
25056
+ if (shouldRecordInitialPage) {
25057
+ this.recordingManager.start();
25058
+ this.isRecordingStopped = false;
25059
+ } else {
25060
+ this.isRecordingStopped = true;
25061
+ }
25062
+ this.urlMonitor = new UrlMonitor(() => this.handleUrlChange());
25063
+ }
25064
+ handleUrlChange() {
25065
+ const shouldRecord = canDiscover(
25066
+ this.recordingBlocklist,
25067
+ this._allowLocalhostRecording
25068
+ );
25069
+ if (!shouldRecord) {
25070
+ if (this.resumeRecordingTimer) {
25071
+ clearTimeout(this.resumeRecordingTimer);
25072
+ this.resumeRecordingTimer = void 0;
25073
+ }
25074
+ if (!this.isRecordingStopped) {
25075
+ this.stopRecording();
25076
+ }
25077
+ } else {
25078
+ if (this.isRecordingStopped) {
25079
+ if (this.resumeRecordingTimer) {
25080
+ clearTimeout(this.resumeRecordingTimer);
25081
+ }
25082
+ this.resumeRecordingTimer = window.setTimeout(() => {
25083
+ this.resumeRecording();
25084
+ this.resumeRecordingTimer = void 0;
25085
+ }, RESUME_RECORDING_DEBOUNCE_MS);
25086
+ }
25087
+ }
25088
+ }
25089
+ stopRecording() {
25090
+ record.addCustomEvent("recording_stopped_blocklist", {
25091
+ url: window.location.href,
25092
+ timestamp: Date.now()
25093
+ });
25094
+ if (this.recordingManager.recorder.stop) {
25095
+ this.recordingManager.recorder.stop();
25096
+ }
25097
+ this.sender.send();
25098
+ this.isRecordingStopped = true;
25099
+ }
25100
+ resumeRecording() {
25101
+ this.recordingManager.recorder.start();
25102
+ record.addCustomEvent("recording_resumed_blocklist", {
25103
+ url: window.location.href,
25104
+ timestamp: Date.now()
25105
+ });
25106
+ this.isRecordingStopped = false;
25004
25107
  }
25005
25108
  handleTimeout() {
25006
25109
  if (this.recordingManager.recorder.stop) {
@@ -25044,16 +25147,45 @@ const _Agent = class _Agent {
25044
25147
  console.error("Failed to send screen_view event:", error);
25045
25148
  }
25046
25149
  }
25150
+ stop() {
25151
+ if (this.resumeRecordingTimer) {
25152
+ clearTimeout(this.resumeRecordingTimer);
25153
+ this.resumeRecordingTimer = void 0;
25154
+ }
25155
+ if (this.urlMonitor) {
25156
+ this.urlMonitor.destroy();
25157
+ this.urlMonitor = void 0;
25158
+ }
25159
+ if (!this.isRecordingStopped && this.recordingManager.recorder.stop) {
25160
+ this.recordingManager.recorder.stop();
25161
+ }
25162
+ if (this.timer) {
25163
+ this.timer.stop();
25164
+ }
25165
+ }
25047
25166
  };
25048
25167
  __publicField(_Agent, "_sessionManager", SessionManager.getInstance());
25049
25168
  let Agent = _Agent;
25169
+ const DEFAULT_SAMPLE_RATE = 5;
25170
+ function shouldSampleRecording(sampleRate, sessionId) {
25171
+ if (sampleRate === void 0 || sampleRate === null || typeof sampleRate !== "number" || isNaN(sampleRate) || sampleRate < 0 || sampleRate > 100) {
25172
+ sampleRate = DEFAULT_SAMPLE_RATE;
25173
+ }
25174
+ let hash = 0;
25175
+ for (let i = 0; i < sessionId.length; i++) {
25176
+ hash = (hash << 5) - hash + sessionId.charCodeAt(i);
25177
+ hash = hash & hash;
25178
+ }
25179
+ const bucket = Math.abs(hash) % 100;
25180
+ return bucket < sampleRate;
25181
+ }
25050
25182
  function toCamelCase(str) {
25051
25183
  return str.replace(
25052
25184
  /([-_][a-z])/gi,
25053
25185
  ($1) => $1.toUpperCase().replace("-", "").replace("_", "")
25054
25186
  );
25055
25187
  }
25056
- const VERSION = "0.0.28";
25188
+ const VERSION = "0.0.30";
25057
25189
  class Tracker extends TrackerSdk {
25058
25190
  constructor(options) {
25059
25191
  super({
@@ -25067,9 +25199,10 @@ class Tracker extends TrackerSdk {
25067
25199
  __publicField(this, "sessionManager", SessionManager.getInstance());
25068
25200
  __publicField(this, "recordingBlocklist", []);
25069
25201
  __publicField(this, "isRecordingActive", false);
25202
+ __publicField(this, "onFirstScreenViewTracked", null);
25070
25203
  this.options = options;
25071
25204
  this.agent = new Agent();
25072
- this.recordingBlocklist = options.recordingBlocklist || [];
25205
+ this.recordingBlocklist = options.recordingOptions?.blocklist ?? options.recordingBlocklist ?? [];
25073
25206
  if (!this.isServer()) {
25074
25207
  this.setGlobalProperties({
25075
25208
  __referrer: document.referrer
@@ -25078,17 +25211,17 @@ class Tracker extends TrackerSdk {
25078
25211
  if (this.options.trackOutgoingLinks && !trackingDisabled) {
25079
25212
  this.trackOutgoingLinks();
25080
25213
  }
25214
+ if (this.options.enableRecording && !trackingDisabled) {
25215
+ this.onFirstScreenViewTracked = () => {
25216
+ this.initializeRecordingWithSessionId();
25217
+ };
25218
+ }
25081
25219
  if (this.options.trackScreenViews) {
25082
25220
  this.trackScreenViews();
25083
25221
  }
25084
25222
  if (this.options.trackAttributes && !trackingDisabled) {
25085
25223
  this.trackAttributes();
25086
25224
  }
25087
- if (this.options.enableRecording && !trackingDisabled) {
25088
- this.startRecording();
25089
- this.isRecordingActive = true;
25090
- console.log("Brainfish has started ambient learning");
25091
- }
25092
25225
  }
25093
25226
  }
25094
25227
  debounce(func, delay) {
@@ -25176,7 +25309,7 @@ class Tracker extends TrackerSdk {
25176
25309
  sendEvents: this.recordEventsToServer.bind(this),
25177
25310
  sendScreenViewEvent: this.sendScreenViewEvent.bind(this),
25178
25311
  recordingBlocklist: this.recordingBlocklist,
25179
- _allowLocalhostRecording: this.options._allowLocalhostRecording
25312
+ _allowLocalhostRecording: this.options.recordingOptions?._allowLocalhostRecording ?? this.options._allowLocalhostRecording
25180
25313
  });
25181
25314
  }
25182
25315
  async screenView(pathOrProperties, propertiesOrUndefined) {
@@ -25216,21 +25349,45 @@ class Tracker extends TrackerSdk {
25216
25349
  }
25217
25350
  });
25218
25351
  }
25352
+ async initializeRecordingWithSessionId() {
25353
+ try {
25354
+ const sessionId = await super.getSessionId();
25355
+ if (this.isTrackingDisabled()) {
25356
+ return;
25357
+ }
25358
+ if (!sessionId) {
25359
+ console.warn("No sid found");
25360
+ return;
25361
+ }
25362
+ if (shouldSampleRecording(
25363
+ this.options.recordingOptions?.sampleRate,
25364
+ sessionId
25365
+ )) {
25366
+ this.startRecording();
25367
+ this.isRecordingActive = true;
25368
+ console.log("Brainfish has started ambient learning");
25369
+ }
25370
+ } catch (error) {
25371
+ console.warn("Error initializing ambient learning:", error);
25372
+ }
25373
+ }
25219
25374
  sendScreenViewEvent(props) {
25220
- super.track("screen_view", props);
25221
25375
  this.sessionManager.updateLastScreenViewEventTime();
25376
+ super.track("screen_view", props);
25377
+ if (this.onFirstScreenViewTracked) {
25378
+ this.onFirstScreenViewTracked();
25379
+ this.onFirstScreenViewTracked = null;
25380
+ }
25222
25381
  }
25223
25382
  /**
25224
25383
  * Disables privacy-sensitive tracking features and stops active recording.
25225
25384
  */
25226
25385
  disableTracking() {
25227
25386
  super.disableTracking();
25387
+ console.log("Brainfish has stopped ambient learning");
25228
25388
  if (this.isRecordingActive) {
25229
- if (this.agent.recordingManager.recorder.stop) {
25230
- this.agent.recordingManager.recorder.stop();
25231
- }
25389
+ this.agent.stop();
25232
25390
  this.isRecordingActive = false;
25233
- console.log("Brainfish has stopped ambient learning");
25234
25391
  }
25235
25392
  }
25236
25393
  /**
@@ -25239,6 +25396,7 @@ class Tracker extends TrackerSdk {
25239
25396
  */
25240
25397
  enableTracking() {
25241
25398
  super.enableTracking();
25399
+ console.log("Brainfish has started ambient learning");
25242
25400
  }
25243
25401
  }
25244
25402
  ((window2) => {
Binary file