@devskin/browser-sdk 1.0.39 → 1.0.41
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/collectors/heatmap.d.ts +3 -1
- package/dist/collectors/heatmap.d.ts.map +1 -1
- package/dist/devskin.cjs.js +122 -96
- package/dist/devskin.cjs.js.map +1 -1
- package/dist/devskin.esm.js +122 -96
- package/dist/devskin.esm.js.map +1 -1
- package/dist/devskin.umd.js +122 -96
- package/dist/devskin.umd.js.map +1 -1
- package/dist/devskin.umd.min.js +2 -2
- package/dist/devskin.umd.min.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/devskin.esm.js
CHANGED
|
@@ -857,9 +857,11 @@ class NetworkCollector {
|
|
|
857
857
|
}
|
|
858
858
|
|
|
859
859
|
class HeatmapCollector {
|
|
860
|
-
constructor(config, transport) {
|
|
860
|
+
constructor(config, transport, anonymousId, sessionId) {
|
|
861
861
|
this.config = config;
|
|
862
862
|
this.transport = transport;
|
|
863
|
+
this.anonymousId = anonymousId;
|
|
864
|
+
this.sessionId = sessionId;
|
|
863
865
|
this.clickData = [];
|
|
864
866
|
this.scrollData = [];
|
|
865
867
|
this.mouseMoveData = [];
|
|
@@ -1003,21 +1005,21 @@ class HeatmapCollector {
|
|
|
1003
1005
|
// Send clicks individually (backend expects one click event per item)
|
|
1004
1006
|
if (this.clickData.length > 0) {
|
|
1005
1007
|
this.clickData.forEach(click => {
|
|
1006
|
-
this.transport.sendHeatmapData(Object.assign({ type: 'click' }, click));
|
|
1008
|
+
this.transport.sendHeatmapData(Object.assign({ type: 'click', anonymousId: this.anonymousId, sessionId: this.sessionId }, click));
|
|
1007
1009
|
});
|
|
1008
1010
|
this.clickData = [];
|
|
1009
1011
|
}
|
|
1010
1012
|
// Send scroll data individually
|
|
1011
1013
|
if (this.scrollData.length > 0) {
|
|
1012
1014
|
this.scrollData.forEach(scroll => {
|
|
1013
|
-
this.transport.sendHeatmapData(Object.assign({ type: 'scroll' }, scroll));
|
|
1015
|
+
this.transport.sendHeatmapData(Object.assign({ type: 'scroll', anonymousId: this.anonymousId, sessionId: this.sessionId }, scroll));
|
|
1014
1016
|
});
|
|
1015
1017
|
this.scrollData = [];
|
|
1016
1018
|
}
|
|
1017
1019
|
// Send mouse moves individually
|
|
1018
1020
|
if (this.mouseMoveData.length > 0) {
|
|
1019
1021
|
this.mouseMoveData.forEach(move => {
|
|
1020
|
-
this.transport.sendHeatmapData(Object.assign({ type: 'mousemove' }, move));
|
|
1022
|
+
this.transport.sendHeatmapData(Object.assign({ type: 'mousemove', anonymousId: this.anonymousId, sessionId: this.sessionId }, move));
|
|
1021
1023
|
});
|
|
1022
1024
|
this.mouseMoveData = [];
|
|
1023
1025
|
}
|
|
@@ -13872,6 +13874,7 @@ class DevSkinSDK {
|
|
|
13872
13874
|
this.anonymousId = null;
|
|
13873
13875
|
this.sessionStartTime = 0;
|
|
13874
13876
|
this.initialized = false;
|
|
13877
|
+
this.initializing = false;
|
|
13875
13878
|
this.heartbeatInterval = null;
|
|
13876
13879
|
// Collectors
|
|
13877
13880
|
this.deviceCollector = null;
|
|
@@ -13887,12 +13890,15 @@ class DevSkinSDK {
|
|
|
13887
13890
|
}
|
|
13888
13891
|
/**
|
|
13889
13892
|
* Initialize the DevSkin SDK
|
|
13893
|
+
* Uses requestIdleCallback to defer heavy initialization without blocking the page
|
|
13890
13894
|
*/
|
|
13891
13895
|
init(config) {
|
|
13892
|
-
if (this.initialized) {
|
|
13893
|
-
console.warn('[DevSkin] SDK already initialized');
|
|
13896
|
+
if (this.initialized || this.initializing) {
|
|
13897
|
+
console.warn('[DevSkin] SDK already initialized or initializing');
|
|
13894
13898
|
return;
|
|
13895
13899
|
}
|
|
13900
|
+
// Mark as initializing to prevent duplicate init() calls
|
|
13901
|
+
this.initializing = true;
|
|
13896
13902
|
this.config = Object.assign({ debug: false, captureWebVitals: true, captureNetworkRequests: true, captureErrors: true, captureUserAgent: true, captureLocation: true, captureDevice: true, heatmapOptions: {
|
|
13897
13903
|
enabled: true,
|
|
13898
13904
|
trackClicks: true,
|
|
@@ -13902,99 +13908,118 @@ class DevSkinSDK {
|
|
|
13902
13908
|
if (this.config.debug) {
|
|
13903
13909
|
console.log('[DevSkin] Initializing SDK with config:', this.config);
|
|
13904
13910
|
}
|
|
13905
|
-
// Initialize
|
|
13911
|
+
// Initialize lightweight components immediately (needed for session context)
|
|
13906
13912
|
this.transport = new Transport(this.config);
|
|
13907
|
-
// Generate anonymous ID if not exists
|
|
13908
13913
|
this.anonymousId = this.getOrCreateAnonymousId();
|
|
13909
|
-
// Initialize collectors BEFORE starting session (so getContextData works)
|
|
13910
13914
|
this.deviceCollector = new DeviceCollector(this.config);
|
|
13911
13915
|
this.locationCollector = new LocationCollector(this.config);
|
|
13912
13916
|
this.browserCollector = new BrowserCollector(this.config);
|
|
13913
|
-
//
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
//
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
this.
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
this.
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
this.
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
//
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
:
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13917
|
+
// Defer heavy initialization to avoid blocking page load/rendering
|
|
13918
|
+
const initHeavyCollectors = () => {
|
|
13919
|
+
// Start session (will now include device/browser/location data)
|
|
13920
|
+
// Wait for session creation to complete before starting collectors
|
|
13921
|
+
this.startSession().then(() => {
|
|
13922
|
+
// Session created, now safe to start collectors that send data
|
|
13923
|
+
var _a, _b;
|
|
13924
|
+
if (this.config.captureWebVitals) {
|
|
13925
|
+
this.performanceCollector = new PerformanceCollector(this.config, this.transport);
|
|
13926
|
+
this.performanceCollector.start();
|
|
13927
|
+
}
|
|
13928
|
+
if (this.config.captureErrors) {
|
|
13929
|
+
this.errorCollector = new ErrorCollector(this.config, this.transport);
|
|
13930
|
+
this.errorCollector.start();
|
|
13931
|
+
}
|
|
13932
|
+
if (this.config.captureNetworkRequests) {
|
|
13933
|
+
this.networkCollector = new NetworkCollector(this.config, this.transport);
|
|
13934
|
+
this.networkCollector.start();
|
|
13935
|
+
}
|
|
13936
|
+
// Initialize heatmap collector - SEMPRE habilitado
|
|
13937
|
+
// Merge default heatmap config with user config
|
|
13938
|
+
const heatmapConfig = Object.assign({ enabled: true, trackClicks: true, trackScroll: true, trackMouseMovement: true, mouseMoveSampling: 0.1 }, this.config.heatmapOptions);
|
|
13939
|
+
this.config.heatmapOptions = heatmapConfig;
|
|
13940
|
+
this.heatmapCollector = new HeatmapCollector(this.config, this.transport, this.anonymousId, this.sessionId);
|
|
13941
|
+
this.heatmapCollector.start();
|
|
13942
|
+
// Initialize screenshot collector and capture page
|
|
13943
|
+
this.screenshotCollector = new ScreenshotCollector(this.config, this.transport);
|
|
13944
|
+
this.screenshotCollector.captureAndSend(this.sessionId, window.location.href);
|
|
13945
|
+
if (this.config.debug) {
|
|
13946
|
+
console.log('[DevSkin] Heatmap collection enabled (always on)');
|
|
13947
|
+
}
|
|
13948
|
+
// Initialize session recording with rrweb
|
|
13949
|
+
if ((_a = this.config.sessionRecording) === null || _a === void 0 ? void 0 : _a.enabled) {
|
|
13950
|
+
// Use RRWebRecorder for complete DOM recording
|
|
13951
|
+
// Pass sessionStartTime to ensure timestamp continuity across page navigations
|
|
13952
|
+
this.rrwebRecorder = new RRWebRecorder(this.sessionId, {
|
|
13953
|
+
enabled: true,
|
|
13954
|
+
sampleRate: this.config.sessionRecording.sampling || 0.5,
|
|
13955
|
+
blockClass: 'rr-block',
|
|
13956
|
+
ignoreClass: this.config.sessionRecording.ignoreClass || 'rr-ignore',
|
|
13957
|
+
maskAllInputs: this.config.sessionRecording.maskAllInputs !== undefined
|
|
13958
|
+
? this.config.sessionRecording.maskAllInputs
|
|
13959
|
+
: true,
|
|
13960
|
+
maskInputOptions: {
|
|
13961
|
+
password: true,
|
|
13962
|
+
email: true,
|
|
13963
|
+
tel: true,
|
|
13964
|
+
},
|
|
13965
|
+
recordCanvas: this.config.sessionRecording.recordCanvas || false,
|
|
13966
|
+
collectFonts: true,
|
|
13967
|
+
inlineStylesheet: true,
|
|
13968
|
+
checkoutEveryNms: 5 * 60 * 1000, // Every 5 minutes
|
|
13969
|
+
checkoutEveryNth: 200, // Every 200 events
|
|
13970
|
+
}, (events) => {
|
|
13971
|
+
var _a;
|
|
13972
|
+
// Send rrweb events to backend
|
|
13973
|
+
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.sendRecordingEvents(this.sessionId, events);
|
|
13974
|
+
}, this.sessionStartTime // Pass session start time for timestamp continuity
|
|
13975
|
+
);
|
|
13976
|
+
// Start recording immediately (session already created)
|
|
13977
|
+
this.rrwebRecorder.start();
|
|
13978
|
+
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
|
|
13979
|
+
console.log('[DevSkin] RRWeb recording started for session:', this.sessionId);
|
|
13980
|
+
}
|
|
13974
13981
|
}
|
|
13982
|
+
// Track initial page view
|
|
13983
|
+
this.trackPageView();
|
|
13984
|
+
// Start heartbeat to update session duration every 30 seconds
|
|
13985
|
+
this.startHeartbeat();
|
|
13986
|
+
}).catch((err) => {
|
|
13987
|
+
console.error('[DevSkin] Failed to create session:', err);
|
|
13988
|
+
});
|
|
13989
|
+
// Track page visibility changes
|
|
13990
|
+
this.setupVisibilityTracking();
|
|
13991
|
+
// Track page unload
|
|
13992
|
+
this.setupUnloadTracking();
|
|
13993
|
+
// Mark as fully initialized only after everything is loaded
|
|
13994
|
+
this.initialized = true;
|
|
13995
|
+
this.initializing = false;
|
|
13996
|
+
};
|
|
13997
|
+
// Use requestIdleCallback to defer heavy initialization (non-blocking)
|
|
13998
|
+
// Falls back to setTimeout for browsers that don't support it
|
|
13999
|
+
if (typeof window !== 'undefined') {
|
|
14000
|
+
if ('requestIdleCallback' in window) {
|
|
14001
|
+
window.requestIdleCallback(initHeavyCollectors, { timeout: 2000 });
|
|
13975
14002
|
}
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
}
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
// Track page unload
|
|
13986
|
-
this.setupUnloadTracking();
|
|
13987
|
-
this.initialized = true;
|
|
14003
|
+
else {
|
|
14004
|
+
// Fallback for older browsers
|
|
14005
|
+
setTimeout(initHeavyCollectors, 1);
|
|
14006
|
+
}
|
|
14007
|
+
}
|
|
14008
|
+
else {
|
|
14009
|
+
// Node.js environment (SSR)
|
|
14010
|
+
initHeavyCollectors();
|
|
14011
|
+
}
|
|
13988
14012
|
if (this.config.debug) {
|
|
13989
|
-
console.log('[DevSkin] SDK
|
|
14013
|
+
console.log('[DevSkin] SDK initialization started (heavy collectors loading in background)');
|
|
13990
14014
|
}
|
|
13991
14015
|
}
|
|
13992
14016
|
/**
|
|
13993
14017
|
* Track a custom event
|
|
14018
|
+
* Works immediately after init() even if heavy collectors are still loading
|
|
13994
14019
|
*/
|
|
13995
14020
|
track(eventName, properties) {
|
|
13996
|
-
var _a, _b;
|
|
13997
|
-
if (!this.
|
|
14021
|
+
var _a, _b, _c, _d;
|
|
14022
|
+
if (!this.transport) {
|
|
13998
14023
|
console.warn('[DevSkin] SDK not initialized. Call init() first.');
|
|
13999
14024
|
return;
|
|
14000
14025
|
}
|
|
@@ -14002,15 +14027,15 @@ class DevSkinSDK {
|
|
|
14002
14027
|
eventName: eventName,
|
|
14003
14028
|
eventType: 'track',
|
|
14004
14029
|
timestamp: new Date().toISOString(),
|
|
14005
|
-
sessionId: this.sessionId,
|
|
14006
|
-
userId: this.userId
|
|
14007
|
-
anonymousId: this.anonymousId
|
|
14030
|
+
sessionId: (_a = this.sessionId) !== null && _a !== void 0 ? _a : undefined,
|
|
14031
|
+
userId: (_b = this.userId) !== null && _b !== void 0 ? _b : undefined,
|
|
14032
|
+
anonymousId: (_c = this.anonymousId) !== null && _c !== void 0 ? _c : undefined,
|
|
14008
14033
|
properties: Object.assign(Object.assign({}, properties), this.getContextData()),
|
|
14009
14034
|
pageUrl: window.location.href,
|
|
14010
14035
|
pageTitle: document.title,
|
|
14011
14036
|
};
|
|
14012
|
-
|
|
14013
|
-
if ((
|
|
14037
|
+
this.transport.sendEvent(eventData);
|
|
14038
|
+
if ((_d = this.config) === null || _d === void 0 ? void 0 : _d.debug) {
|
|
14014
14039
|
console.log('[DevSkin] Event tracked:', eventData);
|
|
14015
14040
|
}
|
|
14016
14041
|
}
|
|
@@ -14039,23 +14064,24 @@ class DevSkinSDK {
|
|
|
14039
14064
|
}
|
|
14040
14065
|
/**
|
|
14041
14066
|
* Identify a user
|
|
14067
|
+
* Works immediately after init() even if heavy collectors are still loading
|
|
14042
14068
|
*/
|
|
14043
14069
|
identify(userId, traits) {
|
|
14044
|
-
var _a, _b;
|
|
14045
|
-
if (!this.
|
|
14070
|
+
var _a, _b, _c;
|
|
14071
|
+
if (!this.transport) {
|
|
14046
14072
|
console.warn('[DevSkin] SDK not initialized. Call init() first.');
|
|
14047
14073
|
return;
|
|
14048
14074
|
}
|
|
14049
14075
|
this.userId = userId;
|
|
14050
14076
|
const userData = {
|
|
14051
14077
|
userId: userId,
|
|
14052
|
-
anonymousId: this.anonymousId
|
|
14078
|
+
anonymousId: (_a = this.anonymousId) !== null && _a !== void 0 ? _a : undefined,
|
|
14053
14079
|
traits: Object.assign(Object.assign({}, traits), this.getContextData()),
|
|
14054
|
-
sessionId: this.sessionId,
|
|
14080
|
+
sessionId: (_b = this.sessionId) !== null && _b !== void 0 ? _b : undefined,
|
|
14055
14081
|
timestamp: new Date().toISOString(),
|
|
14056
14082
|
};
|
|
14057
|
-
|
|
14058
|
-
if ((
|
|
14083
|
+
this.transport.identifyUser(userData);
|
|
14084
|
+
if ((_c = this.config) === null || _c === void 0 ? void 0 : _c.debug) {
|
|
14059
14085
|
console.log('[DevSkin] User identified:', userData);
|
|
14060
14086
|
}
|
|
14061
14087
|
}
|