@devskin/browser-sdk 1.0.26 → 1.0.28
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/devskin.cjs.js +78 -37
- package/dist/devskin.cjs.js.map +1 -1
- package/dist/devskin.esm.js +78 -37
- package/dist/devskin.esm.js.map +1 -1
- package/dist/devskin.umd.js +78 -37
- package/dist/devskin.umd.js.map +1 -1
- package/dist/devskin.umd.min.js +3 -3
- package/dist/devskin.umd.min.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/transport.d.ts +1 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/types.d.ts +21 -20
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/devskin.esm.js
CHANGED
|
@@ -511,7 +511,7 @@ class ErrorCollector {
|
|
|
511
511
|
stack: error.stack,
|
|
512
512
|
type: error.name || 'Error',
|
|
513
513
|
timestamp: new Date().toISOString(),
|
|
514
|
-
|
|
514
|
+
sessionId: '', // Will be set by transport
|
|
515
515
|
url: window.location.href,
|
|
516
516
|
breadcrumbs: [...this.breadcrumbs],
|
|
517
517
|
context: Object.assign(Object.assign({}, context), { userAgent: navigator.userAgent, viewport: {
|
|
@@ -534,7 +534,7 @@ class ErrorCollector {
|
|
|
534
534
|
message: String(error),
|
|
535
535
|
type: 'Error',
|
|
536
536
|
timestamp: new Date().toISOString(),
|
|
537
|
-
|
|
537
|
+
sessionId: '',
|
|
538
538
|
url: window.location.href,
|
|
539
539
|
breadcrumbs: [...this.breadcrumbs],
|
|
540
540
|
context,
|
|
@@ -13480,8 +13480,8 @@ class RRWebRecorder {
|
|
|
13480
13480
|
// Send immediately to ensure FullSnapshot reaches backend first
|
|
13481
13481
|
this.flush();
|
|
13482
13482
|
}
|
|
13483
|
-
else if (this.hasFullSnapshot && this.events.length >=
|
|
13484
|
-
// After FullSnapshot, batch other events
|
|
13483
|
+
else if (this.hasFullSnapshot && this.events.length >= 20) {
|
|
13484
|
+
// After FullSnapshot, batch other events (reduced from 50 to 20)
|
|
13485
13485
|
this.flush();
|
|
13486
13486
|
}
|
|
13487
13487
|
},
|
|
@@ -13520,13 +13520,13 @@ class RRWebRecorder {
|
|
|
13520
13520
|
// Capture iframe content
|
|
13521
13521
|
recordCrossOriginIframes: false, // Security: don't record cross-origin iframes
|
|
13522
13522
|
});
|
|
13523
|
-
// Set up periodic flush (every
|
|
13523
|
+
// Set up periodic flush (every 2 seconds)
|
|
13524
13524
|
// Only flush if we have FullSnapshot to ensure first batch is complete
|
|
13525
13525
|
this.flushInterval = window.setInterval(() => {
|
|
13526
13526
|
if (this.hasFullSnapshot && this.events.length > 0) {
|
|
13527
13527
|
this.flush();
|
|
13528
13528
|
}
|
|
13529
|
-
},
|
|
13529
|
+
}, 2000); // Reduced from 10s to 2s
|
|
13530
13530
|
// Safety check: After 2 seconds, force a full snapshot if none captured
|
|
13531
13531
|
setTimeout(() => {
|
|
13532
13532
|
if (!this.hasFullSnapshot) {
|
|
@@ -13584,8 +13584,8 @@ class Transport {
|
|
|
13584
13584
|
this.config = config;
|
|
13585
13585
|
this.queue = [];
|
|
13586
13586
|
this.flushInterval = null;
|
|
13587
|
-
this.maxQueueSize = 50
|
|
13588
|
-
this.flushIntervalMs =
|
|
13587
|
+
this.maxQueueSize = 20; // Reduced from 50
|
|
13588
|
+
this.flushIntervalMs = 2000; // 2 seconds (reduced from 5s)
|
|
13589
13589
|
this.apiUrl = config.apiUrl || 'https://api.devskin.com';
|
|
13590
13590
|
// Start periodic flush
|
|
13591
13591
|
this.startPeriodicFlush();
|
|
@@ -13610,8 +13610,8 @@ class Transport {
|
|
|
13610
13610
|
this.sendToBackend('/v1/analytics/identify', user);
|
|
13611
13611
|
}
|
|
13612
13612
|
startSession(session) {
|
|
13613
|
-
// Send session start immediately
|
|
13614
|
-
this.sendToBackend('/v1/
|
|
13613
|
+
// Send session start immediately to RUM endpoint
|
|
13614
|
+
this.sendToBackend('/v1/rum/sessions', session);
|
|
13615
13615
|
}
|
|
13616
13616
|
sendError(error) {
|
|
13617
13617
|
this.enqueue('error', error);
|
|
@@ -13622,6 +13622,12 @@ class Transport {
|
|
|
13622
13622
|
sendPerformanceMetric(metric) {
|
|
13623
13623
|
this.enqueue('performance', metric);
|
|
13624
13624
|
}
|
|
13625
|
+
sendPageView(pageViewData) {
|
|
13626
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
13627
|
+
// Send page view immediately to RUM endpoint (don't queue)
|
|
13628
|
+
this.sendToBackend('/v1/rum/page-views', pageViewData);
|
|
13629
|
+
});
|
|
13630
|
+
}
|
|
13625
13631
|
sendRecordingEvents(sessionId, events) {
|
|
13626
13632
|
return __awaiter$1(this, void 0, void 0, function* () {
|
|
13627
13633
|
// Calculate payload size
|
|
@@ -13722,23 +13728,23 @@ class Transport {
|
|
|
13722
13728
|
getEndpointForType(type) {
|
|
13723
13729
|
switch (type) {
|
|
13724
13730
|
case 'event':
|
|
13725
|
-
return '/v1/
|
|
13731
|
+
return '/v1/rum/events';
|
|
13726
13732
|
case 'error':
|
|
13727
|
-
return '/v1/
|
|
13733
|
+
return '/v1/errors/errors';
|
|
13728
13734
|
case 'network':
|
|
13729
|
-
return '/v1/
|
|
13735
|
+
return '/v1/rum/network-requests';
|
|
13730
13736
|
case 'performance':
|
|
13731
|
-
return '/v1/
|
|
13737
|
+
return '/v1/rum/web-vitals';
|
|
13732
13738
|
case 'heatmap':
|
|
13733
13739
|
return '/v1/sdk/heatmap';
|
|
13734
13740
|
default:
|
|
13735
|
-
return '/v1/
|
|
13741
|
+
return '/v1/rum/events';
|
|
13736
13742
|
}
|
|
13737
13743
|
}
|
|
13738
13744
|
sendToBackendXHR(endpoint, data) {
|
|
13739
13745
|
return __awaiter$1(this, void 0, void 0, function* () {
|
|
13740
13746
|
const url = `${this.apiUrl}${endpoint}`;
|
|
13741
|
-
const payload = Object.assign(Object.assign({}, data), { apiKey: this.config.apiKey,
|
|
13747
|
+
const payload = Object.assign(Object.assign({}, data), { apiKey: this.config.apiKey, applicationId: this.config.appId, environment: this.config.environment, release: this.config.release });
|
|
13742
13748
|
// Apply beforeSend hook if provided
|
|
13743
13749
|
if (this.config.beforeSend) {
|
|
13744
13750
|
const processed = this.config.beforeSend(payload);
|
|
@@ -13788,7 +13794,7 @@ class Transport {
|
|
|
13788
13794
|
sendToBackend(endpoint_1, data_1) {
|
|
13789
13795
|
return __awaiter$1(this, arguments, void 0, function* (endpoint, data, useBeacon = false) {
|
|
13790
13796
|
const url = `${this.apiUrl}${endpoint}`;
|
|
13791
|
-
const payload = Object.assign(Object.assign({}, data), { apiKey: this.config.apiKey,
|
|
13797
|
+
const payload = Object.assign(Object.assign({}, data), { apiKey: this.config.apiKey, applicationId: this.config.appId, environment: this.config.environment, release: this.config.release });
|
|
13792
13798
|
// Apply beforeSend hook if provided
|
|
13793
13799
|
if (this.config.beforeSend) {
|
|
13794
13800
|
const processed = this.config.beforeSend(payload);
|
|
@@ -13972,15 +13978,15 @@ class DevSkinSDK {
|
|
|
13972
13978
|
return;
|
|
13973
13979
|
}
|
|
13974
13980
|
const eventData = {
|
|
13975
|
-
|
|
13976
|
-
|
|
13981
|
+
eventName: eventName,
|
|
13982
|
+
eventType: 'track',
|
|
13977
13983
|
timestamp: new Date().toISOString(),
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13984
|
+
sessionId: this.sessionId,
|
|
13985
|
+
userId: this.userId || undefined,
|
|
13986
|
+
anonymousId: this.anonymousId || undefined,
|
|
13981
13987
|
properties: Object.assign(Object.assign({}, properties), this.getContextData()),
|
|
13982
|
-
|
|
13983
|
-
|
|
13988
|
+
pageUrl: window.location.href,
|
|
13989
|
+
pageTitle: document.title,
|
|
13984
13990
|
};
|
|
13985
13991
|
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.sendEvent(eventData);
|
|
13986
13992
|
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
|
|
@@ -13991,7 +13997,24 @@ class DevSkinSDK {
|
|
|
13991
13997
|
* Track a page view
|
|
13992
13998
|
*/
|
|
13993
13999
|
trackPageView(properties) {
|
|
14000
|
+
var _a, _b;
|
|
14001
|
+
if (!this.initialized) {
|
|
14002
|
+
console.warn('[DevSkin] SDK not initialized. Call init() first.');
|
|
14003
|
+
return;
|
|
14004
|
+
}
|
|
14005
|
+
// Generate unique page view ID
|
|
14006
|
+
const pageViewId = this.generateId();
|
|
14007
|
+
// Send to RUM page-views endpoint
|
|
14008
|
+
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.sendPageView(Object.assign({ sessionId: this.sessionId, pageViewId: pageViewId, url: window.location.href, path: window.location.pathname, queryParams: window.location.search, referrer: document.referrer, title: document.title, timestamp: new Date().toISOString() }, properties));
|
|
14009
|
+
// Also track as analytics event for backwards compatibility
|
|
13994
14010
|
this.track('page_view', Object.assign({ path: window.location.pathname, search: window.location.search, hash: window.location.hash, referrer: document.referrer }, properties));
|
|
14011
|
+
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
|
|
14012
|
+
console.log('[DevSkin] Page view tracked:', {
|
|
14013
|
+
sessionId: this.sessionId,
|
|
14014
|
+
pageViewId: pageViewId,
|
|
14015
|
+
url: window.location.href,
|
|
14016
|
+
});
|
|
14017
|
+
}
|
|
13995
14018
|
}
|
|
13996
14019
|
/**
|
|
13997
14020
|
* Identify a user
|
|
@@ -14004,10 +14027,10 @@ class DevSkinSDK {
|
|
|
14004
14027
|
}
|
|
14005
14028
|
this.userId = userId;
|
|
14006
14029
|
const userData = {
|
|
14007
|
-
|
|
14008
|
-
|
|
14030
|
+
userId: userId,
|
|
14031
|
+
anonymousId: this.anonymousId || undefined,
|
|
14009
14032
|
traits: Object.assign(Object.assign({}, traits), this.getContextData()),
|
|
14010
|
-
|
|
14033
|
+
sessionId: this.sessionId,
|
|
14011
14034
|
timestamp: new Date().toISOString(),
|
|
14012
14035
|
};
|
|
14013
14036
|
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.identifyUser(userData);
|
|
@@ -14081,7 +14104,7 @@ class DevSkinSDK {
|
|
|
14081
14104
|
// Store in sessionStorage (persists across page navigations in same tab)
|
|
14082
14105
|
sessionStorage.setItem('devskin_session_id', this.sessionId);
|
|
14083
14106
|
sessionStorage.setItem('devskin_session_start', this.sessionStartTime.toString());
|
|
14084
|
-
const sessionData = Object.assign({
|
|
14107
|
+
const sessionData = Object.assign({ sessionId: this.sessionId, userId: this.userId || undefined, anonymousId: this.anonymousId, startedAt: new Date().toISOString(), platform: 'web' }, this.getContextData());
|
|
14085
14108
|
(_b = this.transport) === null || _b === void 0 ? void 0 : _b.startSession(sessionData);
|
|
14086
14109
|
if ((_c = this.config) === null || _c === void 0 ? void 0 : _c.debug) {
|
|
14087
14110
|
console.log('[DevSkin] New session created:', this.sessionId);
|
|
@@ -14122,27 +14145,45 @@ class DevSkinSDK {
|
|
|
14122
14145
|
});
|
|
14123
14146
|
}
|
|
14124
14147
|
setupUnloadTracking() {
|
|
14125
|
-
//
|
|
14126
|
-
|
|
14148
|
+
// CRITICAL: Flush data BEFORE page unloads to avoid losing final events
|
|
14149
|
+
// 1. visibilitychange - fires when tab is hidden (most reliable)
|
|
14150
|
+
document.addEventListener('visibilitychange', () => {
|
|
14127
14151
|
var _a, _b;
|
|
14128
|
-
|
|
14129
|
-
|
|
14130
|
-
|
|
14152
|
+
if (document.hidden) {
|
|
14153
|
+
// User switched tabs or minimized - flush immediately
|
|
14154
|
+
(_a = this.rrwebRecorder) === null || _a === void 0 ? void 0 : _a.stop(); // Stop recording and flush
|
|
14155
|
+
(_b = this.transport) === null || _b === void 0 ? void 0 : _b.flush(true); // Use beacon
|
|
14156
|
+
}
|
|
14157
|
+
});
|
|
14158
|
+
// 2. pagehide - fires when page is being unloaded
|
|
14159
|
+
window.addEventListener('pagehide', (event) => {
|
|
14160
|
+
var _a, _b, _c;
|
|
14131
14161
|
const isActualClose = !event.persisted;
|
|
14132
14162
|
if (isActualClose) {
|
|
14163
|
+
// Tab is closing - end session
|
|
14133
14164
|
this.track('page_unload');
|
|
14134
|
-
// Only send session end if tab is actually closing
|
|
14135
14165
|
if (this.sessionId && this.sessionStartTime) {
|
|
14136
14166
|
const endedAt = new Date();
|
|
14137
14167
|
const durationMs = Date.now() - this.sessionStartTime;
|
|
14138
|
-
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.startSession(Object.assign({
|
|
14168
|
+
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.startSession(Object.assign({ sessionId: this.sessionId, userId: this.userId || undefined, anonymousId: this.anonymousId, endedAt: endedAt.toISOString(), durationMs: durationMs, platform: 'web' }, this.getContextData()));
|
|
14139
14169
|
// Clear session storage since session is ending
|
|
14140
14170
|
sessionStorage.removeItem('devskin_session_id');
|
|
14141
14171
|
sessionStorage.removeItem('devskin_session_start');
|
|
14142
14172
|
}
|
|
14143
14173
|
}
|
|
14144
|
-
|
|
14145
|
-
|
|
14174
|
+
else {
|
|
14175
|
+
// Navigation - track page change
|
|
14176
|
+
this.track('page_navigation');
|
|
14177
|
+
}
|
|
14178
|
+
// ALWAYS flush (whether navigation or close)
|
|
14179
|
+
(_b = this.rrwebRecorder) === null || _b === void 0 ? void 0 : _b.stop(); // Stop recording and flush remaining events
|
|
14180
|
+
(_c = this.transport) === null || _c === void 0 ? void 0 : _c.flush(true); // Use beacon for reliability
|
|
14181
|
+
});
|
|
14182
|
+
// 3. beforeunload - backup for older browsers
|
|
14183
|
+
window.addEventListener('beforeunload', () => {
|
|
14184
|
+
var _a, _b;
|
|
14185
|
+
(_a = this.rrwebRecorder) === null || _a === void 0 ? void 0 : _a.stop();
|
|
14186
|
+
(_b = this.transport) === null || _b === void 0 ? void 0 : _b.flush(true);
|
|
14146
14187
|
});
|
|
14147
14188
|
}
|
|
14148
14189
|
}
|