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