@zaplier/sdk 1.3.7 → 1.4.1
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/index.cjs +30 -197
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +30 -197
- package/dist/index.esm.js.map +1 -1
- package/dist/sdk.js +30 -197
- package/dist/sdk.js.map +1 -1
- package/dist/sdk.min.js +1 -1
- package/dist/src/modules/session-replay.d.ts +4 -22
- package/dist/src/modules/session-replay.d.ts.map +1 -1
- package/dist/src/sdk.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -19010,35 +19010,25 @@ var n;
|
|
|
19010
19010
|
!function(t2) {
|
|
19011
19011
|
t2[t2.NotStarted = 0] = "NotStarted", t2[t2.Running = 1] = "Running", t2[t2.Stopped = 2] = "Stopped";
|
|
19012
19012
|
}(n || (n = {}));
|
|
19013
|
-
const { takeFullSnapshot } = record;
|
|
19014
19013
|
|
|
19015
19014
|
/**
|
|
19016
|
-
* Session Replay Engine
|
|
19017
|
-
*
|
|
19015
|
+
* Session Replay Engine - Simplified Implementation
|
|
19016
|
+
* Based on official rrweb example for maximum compatibility
|
|
19018
19017
|
*/
|
|
19019
19018
|
class SessionReplayEngine {
|
|
19020
19019
|
constructor(sessionId, config = {}) {
|
|
19021
19020
|
this.events = [];
|
|
19022
19021
|
this.isActive = false;
|
|
19023
|
-
this.hasFullSnapshot = false;
|
|
19024
|
-
this.startTime = 0;
|
|
19025
19022
|
this.sessionId = sessionId;
|
|
19026
19023
|
this.config = {
|
|
19027
19024
|
enabled: true,
|
|
19028
|
-
sampleRate: 1.0,
|
|
19029
|
-
|
|
19030
|
-
maxEventBuffer: 1000,
|
|
19031
|
-
batchInterval: 2000, // Send every 2 seconds for faster testing
|
|
19032
|
-
captureClicks: true,
|
|
19033
|
-
captureScrolls: true,
|
|
19034
|
-
captureInputs: true,
|
|
19035
|
-
captureMouseMoves: false, // Disabled by default for performance
|
|
19036
|
-
compressionEnabled: true,
|
|
19025
|
+
sampleRate: 1.0,
|
|
19026
|
+
batchInterval: 10000, // 10 seconds like official example
|
|
19037
19027
|
...config,
|
|
19038
19028
|
};
|
|
19039
19029
|
}
|
|
19040
19030
|
/**
|
|
19041
|
-
* Start session replay recording
|
|
19031
|
+
* Start session replay recording - Simplified like official example
|
|
19042
19032
|
*/
|
|
19043
19033
|
start() {
|
|
19044
19034
|
if (!this.config.enabled || this.isActive) {
|
|
@@ -19049,60 +19039,24 @@ class SessionReplayEngine {
|
|
|
19049
19039
|
return false;
|
|
19050
19040
|
}
|
|
19051
19041
|
try {
|
|
19052
|
-
//
|
|
19053
|
-
// Using minimal configuration to avoid known bugs in alpha versions
|
|
19054
|
-
// blockSelector and maskTextSelector removed due to node.matches error
|
|
19042
|
+
// Simple rrweb recording configuration like official example
|
|
19055
19043
|
this.rrwebStopRecord = record({
|
|
19056
19044
|
emit: (event) => {
|
|
19057
|
-
|
|
19045
|
+
// CRITICAL: Ensure FullSnapshot is always first event
|
|
19046
|
+
if (this.events.length === 0 && event.type !== 2) {
|
|
19047
|
+
console.warn(`[Zaplier] First event is type ${event.type}, not FullSnapshot (2). Skipping until FullSnapshot.`);
|
|
19048
|
+
return; // Skip non-FullSnapshot events if no FullSnapshot captured yet
|
|
19049
|
+
}
|
|
19050
|
+
// Simple event capture
|
|
19051
|
+
this.events.push(event);
|
|
19052
|
+
if (event.type === 2) {
|
|
19053
|
+
console.log(`[Zaplier] ✅ FullSnapshot captured as event #${this.events.length}`);
|
|
19054
|
+
}
|
|
19058
19055
|
},
|
|
19059
|
-
maskAllInputs: this.config.maskSensitiveFields,
|
|
19060
|
-
// maskTextSelector removed - causes node.matches error in some cases
|
|
19061
|
-
// blockSelector removed - causes node.matches error
|
|
19062
|
-
recordCanvas: false, // Disable canvas recording for performance
|
|
19063
|
-
recordCrossOriginIframes: false,
|
|
19064
|
-
inlineStylesheet: true,
|
|
19065
|
-
collectFonts: false, // Disable font collection for smaller payloads
|
|
19066
19056
|
});
|
|
19067
19057
|
this.isActive = true;
|
|
19068
|
-
this.hasFullSnapshot = false;
|
|
19069
|
-
this.startTime = Date.now();
|
|
19070
19058
|
this.startBatchTimer();
|
|
19071
|
-
|
|
19072
|
-
// where FullSnapshot is sometimes not created as the first event
|
|
19073
|
-
setTimeout(() => {
|
|
19074
|
-
if (!this.hasFullSnapshot) {
|
|
19075
|
-
console.log("[Zaplier] Forcing immediate FullSnapshot to ensure correct event order...");
|
|
19076
|
-
try {
|
|
19077
|
-
takeFullSnapshot(true); // Force a new FullSnapshot immediately
|
|
19078
|
-
console.log("[Zaplier] FullSnapshot manually triggered");
|
|
19079
|
-
}
|
|
19080
|
-
catch (error) {
|
|
19081
|
-
console.error("[Zaplier] Failed to force FullSnapshot:", error);
|
|
19082
|
-
}
|
|
19083
|
-
}
|
|
19084
|
-
}, 50); // Very short delay but let natural events come first
|
|
19085
|
-
// Set timeout to check if FullSnapshot was captured
|
|
19086
|
-
this.snapshotTimeout = window.setTimeout(() => {
|
|
19087
|
-
if (!this.hasFullSnapshot) {
|
|
19088
|
-
console.error("[Zaplier] CRITICAL: FullSnapshot not captured after 5 seconds!", {
|
|
19089
|
-
eventsReceived: this.events.length,
|
|
19090
|
-
eventTypes: this.events.map((e) => e.type).slice(0, 10),
|
|
19091
|
-
});
|
|
19092
|
-
// Try one more forced snapshot as last resort
|
|
19093
|
-
try {
|
|
19094
|
-
console.warn("[Zaplier] Last resort: forcing FullSnapshot...");
|
|
19095
|
-
takeFullSnapshot(true);
|
|
19096
|
-
}
|
|
19097
|
-
catch (error) {
|
|
19098
|
-
console.error("[Zaplier] Failed to create emergency FullSnapshot:", error);
|
|
19099
|
-
}
|
|
19100
|
-
}
|
|
19101
|
-
else {
|
|
19102
|
-
console.log("[Zaplier] ✅ FullSnapshot confirmed captured");
|
|
19103
|
-
}
|
|
19104
|
-
}, 5000);
|
|
19105
|
-
console.log("[Zaplier] Session replay started with rrweb");
|
|
19059
|
+
console.log("[Zaplier] Session replay started - simple mode");
|
|
19106
19060
|
return true;
|
|
19107
19061
|
}
|
|
19108
19062
|
catch (error) {
|
|
@@ -19126,87 +19080,9 @@ class SessionReplayEngine {
|
|
|
19126
19080
|
clearInterval(this.batchTimer);
|
|
19127
19081
|
this.batchTimer = undefined;
|
|
19128
19082
|
}
|
|
19129
|
-
if (this.snapshotTimeout) {
|
|
19130
|
-
clearTimeout(this.snapshotTimeout);
|
|
19131
|
-
this.snapshotTimeout = undefined;
|
|
19132
|
-
}
|
|
19133
19083
|
// Send final batch
|
|
19134
19084
|
this.sendBatch();
|
|
19135
19085
|
}
|
|
19136
|
-
/**
|
|
19137
|
-
* Handle events from rrweb
|
|
19138
|
-
*/
|
|
19139
|
-
handleRRWebEvent(event) {
|
|
19140
|
-
try {
|
|
19141
|
-
// Log ALL events until we get FullSnapshot, then log first 5
|
|
19142
|
-
const shouldLog = !this.hasFullSnapshot || this.events.length < 5;
|
|
19143
|
-
if (shouldLog) {
|
|
19144
|
-
const eventTypeNames = {
|
|
19145
|
-
[EventType.DomContentLoaded]: "DomContentLoaded",
|
|
19146
|
-
[EventType.Load]: "Load",
|
|
19147
|
-
[EventType.FullSnapshot]: "FullSnapshot",
|
|
19148
|
-
[EventType.IncrementalSnapshot]: "IncrementalSnapshot",
|
|
19149
|
-
[EventType.Meta]: "Meta",
|
|
19150
|
-
[EventType.Custom]: "Custom",
|
|
19151
|
-
[EventType.Plugin]: "Plugin",
|
|
19152
|
-
};
|
|
19153
|
-
console.log(`[Zaplier] Received event type ${event.type} (${eventTypeNames[event.type] || "Unknown"})`, {
|
|
19154
|
-
timestamp: new Date(event.timestamp).toISOString(),
|
|
19155
|
-
isFirst: this.events.length === 0,
|
|
19156
|
-
totalEvents: this.events.length + 1,
|
|
19157
|
-
});
|
|
19158
|
-
}
|
|
19159
|
-
// Check if this is a FullSnapshot
|
|
19160
|
-
if (event.type === EventType.FullSnapshot) {
|
|
19161
|
-
this.hasFullSnapshot = true;
|
|
19162
|
-
console.log("[Zaplier] ✅ FullSnapshot captured! Replay will work correctly.");
|
|
19163
|
-
// Clear timeout since we got the snapshot
|
|
19164
|
-
if (this.snapshotTimeout) {
|
|
19165
|
-
clearTimeout(this.snapshotTimeout);
|
|
19166
|
-
this.snapshotTimeout = undefined;
|
|
19167
|
-
}
|
|
19168
|
-
}
|
|
19169
|
-
else if (this.events.length === 0) {
|
|
19170
|
-
// First event is NOT a FullSnapshot - this is a problem!
|
|
19171
|
-
console.error(`[Zaplier] ⚠️ WARNING: First event is type ${event.type}, not FullSnapshot! Replay may not work.`);
|
|
19172
|
-
}
|
|
19173
|
-
// Add event to buffer
|
|
19174
|
-
this.addEvent(event);
|
|
19175
|
-
// If we just got the FullSnapshot and have events, try sending immediately
|
|
19176
|
-
if (event.type === EventType.FullSnapshot && this.events.length > 0) {
|
|
19177
|
-
// Small delay to ensure all initial events are captured
|
|
19178
|
-
setTimeout(() => {
|
|
19179
|
-
this.sendBatch();
|
|
19180
|
-
}, 100);
|
|
19181
|
-
}
|
|
19182
|
-
}
|
|
19183
|
-
catch (error) {
|
|
19184
|
-
// Silently ignore errors from rrweb to prevent breaking the app
|
|
19185
|
-
// The error is likely from rrweb's internal processing
|
|
19186
|
-
console.warn("[Zaplier] Error handling rrweb event:", error);
|
|
19187
|
-
}
|
|
19188
|
-
}
|
|
19189
|
-
/**
|
|
19190
|
-
* Add event to buffer
|
|
19191
|
-
*/
|
|
19192
|
-
addEvent(event) {
|
|
19193
|
-
this.events.push(event);
|
|
19194
|
-
// Prevent memory overflow
|
|
19195
|
-
if (this.events.length > this.config.maxEventBuffer) {
|
|
19196
|
-
// Keep FullSnapshot if present
|
|
19197
|
-
const fullSnapshotIndex = this.events.findIndex((e) => e.type === EventType.FullSnapshot);
|
|
19198
|
-
if (fullSnapshotIndex >= 0 &&
|
|
19199
|
-
fullSnapshotIndex < this.events.length - this.config.maxEventBuffer) {
|
|
19200
|
-
// Keep snapshot and recent events
|
|
19201
|
-
const snapshot = this.events[fullSnapshotIndex];
|
|
19202
|
-
const recentEvents = this.events.slice(-this.config.maxEventBuffer + 1);
|
|
19203
|
-
this.events = [snapshot, ...recentEvents];
|
|
19204
|
-
}
|
|
19205
|
-
else {
|
|
19206
|
-
this.events = this.events.slice(-this.config.maxEventBuffer);
|
|
19207
|
-
}
|
|
19208
|
-
}
|
|
19209
|
-
}
|
|
19210
19086
|
/**
|
|
19211
19087
|
* Start batch timer
|
|
19212
19088
|
*/
|
|
@@ -19216,48 +19092,29 @@ class SessionReplayEngine {
|
|
|
19216
19092
|
}, this.config.batchInterval);
|
|
19217
19093
|
}
|
|
19218
19094
|
/**
|
|
19219
|
-
* Send batch of events
|
|
19095
|
+
* Send batch of events - Simplified like official example
|
|
19220
19096
|
*/
|
|
19221
19097
|
sendBatch() {
|
|
19222
19098
|
if (this.events.length === 0) {
|
|
19223
19099
|
return;
|
|
19224
19100
|
}
|
|
19225
|
-
//
|
|
19226
|
-
if (!this.hasFullSnapshot) {
|
|
19227
|
-
const waitTime = Date.now() - this.startTime;
|
|
19228
|
-
// Only log every 2 seconds to avoid spam
|
|
19229
|
-
if (waitTime % 2000 < 100) {
|
|
19230
|
-
console.warn(`[Zaplier] Waiting for FullSnapshot before sending batch... (${Math.floor(waitTime / 1000)}s). Events so far: ${this.events.length}, types:`, this.events.map((e) => e.type).slice(0, 5));
|
|
19231
|
-
}
|
|
19232
|
-
return; // Don't send without FullSnapshot
|
|
19233
|
-
}
|
|
19234
|
-
const batch = [...this.events];
|
|
19235
|
-
this.events = [];
|
|
19236
|
-
// IMPORTANT: Ensure FullSnapshot comes first in the batch
|
|
19237
|
-
const fullSnapshotIndex = batch.findIndex((e) => e.type === EventType.FullSnapshot);
|
|
19238
|
-
if (fullSnapshotIndex > 0) {
|
|
19239
|
-
console.log("[Zaplier] Reordering events - moving FullSnapshot to first position");
|
|
19240
|
-
const fullSnapshot = batch.splice(fullSnapshotIndex, 1)[0];
|
|
19241
|
-
if (fullSnapshot) {
|
|
19242
|
-
batch.unshift(fullSnapshot);
|
|
19243
|
-
}
|
|
19244
|
-
}
|
|
19245
|
-
// Verify batch has FullSnapshot
|
|
19246
|
-
const hasSnapshot = batch.some((e) => e.type === EventType.FullSnapshot);
|
|
19247
|
-
if (!hasSnapshot && this.hasFullSnapshot) {
|
|
19248
|
-
console.warn("[Zaplier] Batch missing FullSnapshot, but one was captured earlier");
|
|
19249
|
-
}
|
|
19250
|
-
console.log(`[Zaplier] Sending batch with ${batch.length} events for session ${this.sessionId}`, { hasSnapshot, firstEventType: batch[0]?.type, eventTypes: batch.slice(0, 5).map(e => e.type) });
|
|
19101
|
+
// Simple payload structure like official example
|
|
19251
19102
|
const payload = {
|
|
19252
19103
|
sessionId: this.sessionId,
|
|
19253
|
-
events:
|
|
19104
|
+
events: [...this.events], // Copy events array
|
|
19254
19105
|
metadata: {
|
|
19255
19106
|
userAgent: navigator.userAgent,
|
|
19256
19107
|
timestamp: Date.now(),
|
|
19257
|
-
|
|
19108
|
+
startUrl: window.location.href,
|
|
19109
|
+
duration: Date.now() - (performance.timeOrigin || Date.now()),
|
|
19110
|
+
funnelSteps: [],
|
|
19111
|
+
hasConversion: false,
|
|
19258
19112
|
},
|
|
19259
19113
|
};
|
|
19260
|
-
//
|
|
19114
|
+
// Reset events array like official example
|
|
19115
|
+
this.events = [];
|
|
19116
|
+
console.log(`[Zaplier] Sending batch with ${payload.events.length} events`);
|
|
19117
|
+
// Send to backend
|
|
19261
19118
|
this.sendToBackend(payload);
|
|
19262
19119
|
}
|
|
19263
19120
|
/**
|
|
@@ -19275,24 +19132,8 @@ class SessionReplayEngine {
|
|
|
19275
19132
|
console.error("[Zaplier] No SDK instance available for replay transport");
|
|
19276
19133
|
return;
|
|
19277
19134
|
}
|
|
19278
|
-
|
|
19279
|
-
|
|
19280
|
-
sessionId: payload.sessionId,
|
|
19281
|
-
eventCount: payload.events.length,
|
|
19282
|
-
hasMetadata: !!payload.metadata,
|
|
19283
|
-
});
|
|
19284
|
-
// Use SDK's sendReplayBatch method
|
|
19285
|
-
const result = await this.sdkInstance.sendReplayBatch({
|
|
19286
|
-
sessionId: payload.sessionId,
|
|
19287
|
-
events: payload.events,
|
|
19288
|
-
metadata: {
|
|
19289
|
-
startUrl: window.location.href,
|
|
19290
|
-
duration: Date.now() - (performance.timeOrigin || Date.now()),
|
|
19291
|
-
funnelSteps: [],
|
|
19292
|
-
hasConversion: false,
|
|
19293
|
-
...payload.metadata,
|
|
19294
|
-
},
|
|
19295
|
-
});
|
|
19135
|
+
// Use SDK's sendReplayBatch method with simplified payload
|
|
19136
|
+
const result = await this.sdkInstance.sendReplayBatch(payload);
|
|
19296
19137
|
if (result && result.success) {
|
|
19297
19138
|
console.log("[Zaplier] Session replay batch sent successfully");
|
|
19298
19139
|
}
|
|
@@ -19422,8 +19263,6 @@ class ZaplierSDK {
|
|
|
19422
19263
|
// When explicitly enabled, use 100% sample rate
|
|
19423
19264
|
this.replayEngine = new SessionReplayEngine(sessionId, {
|
|
19424
19265
|
sampleRate: 1.0, // Force 100% when explicitly enabled
|
|
19425
|
-
maskSensitiveFields: this.config.replayMaskInputs,
|
|
19426
|
-
compressionEnabled: true,
|
|
19427
19266
|
});
|
|
19428
19267
|
// Connect to anti-adblock manager
|
|
19429
19268
|
if (this.antiAdblockManager) {
|
|
@@ -19450,8 +19289,6 @@ class ZaplierSDK {
|
|
|
19450
19289
|
const sessionId = this.sessionId;
|
|
19451
19290
|
this.replayEngine = new SessionReplayEngine(sessionId, {
|
|
19452
19291
|
sampleRate: 1.0, // Force 100% when explicitly enabled
|
|
19453
|
-
maskSensitiveFields: this.config.replayMaskInputs,
|
|
19454
|
-
compressionEnabled: true,
|
|
19455
19292
|
});
|
|
19456
19293
|
// Connect to anti-adblock manager
|
|
19457
19294
|
if (this.antiAdblockManager) {
|
|
@@ -19492,8 +19329,6 @@ class ZaplierSDK {
|
|
|
19492
19329
|
const sessionId = this.sessionId;
|
|
19493
19330
|
this.replayEngine = new SessionReplayEngine(sessionId, {
|
|
19494
19331
|
sampleRate: 1.0, // Force recording when manually started
|
|
19495
|
-
maskSensitiveFields: this.config.replayMaskInputs,
|
|
19496
|
-
compressionEnabled: true,
|
|
19497
19332
|
});
|
|
19498
19333
|
// Connect to anti-adblock manager
|
|
19499
19334
|
if (this.antiAdblockManager) {
|
|
@@ -19598,8 +19433,6 @@ class ZaplierSDK {
|
|
|
19598
19433
|
const sampleRate = this.config.replay === true ? 1.0 : this.config.replaySampling;
|
|
19599
19434
|
this.replayEngine = new SessionReplayEngine(this.sessionId, {
|
|
19600
19435
|
sampleRate: sampleRate,
|
|
19601
|
-
maskSensitiveFields: this.config.replayMaskInputs,
|
|
19602
|
-
compressionEnabled: true,
|
|
19603
19436
|
});
|
|
19604
19437
|
// Connect SDK instance for transport
|
|
19605
19438
|
this.replayEngine.setSDKInstance(this);
|