@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.
- package/dist/common/recordingSampler.d.ts +16 -0
- package/dist/index.d.ts +11 -1
- package/dist/record/index.d.ts +7 -0
- package/dist/record/urlMonitor.d.ts +15 -0
- package/dist/tracker.cjs.js +1 -1
- package/dist/tracker.cjs.js.gz +0 -0
- package/dist/tracker.cjs.js.map +1 -1
- package/dist/tracker.es.js +347 -189
- package/dist/tracker.es.js.gz +0 -0
- package/dist/tracker.es.js.map +1 -1
- package/dist/tracker.js +1 -1
- package/dist/tracker.js.gz +0 -0
- package/dist/tracker.js.map +1 -1
- package/package.json +2 -2
package/dist/tracker.es.js
CHANGED
|
@@ -3574,7 +3574,7 @@ const _TrackerSdk = class _TrackerSdk {
|
|
|
3574
3574
|
delete this.eventListeners[event];
|
|
3575
3575
|
}
|
|
3576
3576
|
}
|
|
3577
|
-
async send(payload
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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) => {
|
package/dist/tracker.es.js.gz
CHANGED
|
Binary file
|