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