@zaplier/sdk 1.3.6 → 1.4.0

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.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
- * Uses rrweb to capture DOM snapshots and events for session replay
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, // 100% for development/testing
19025
- maskSensitiveFields: true,
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 using rrweb
19027
+ * Start session replay recording - Simplified like official example
19038
19028
  */
19039
19029
  start() {
19040
19030
  if (!this.config.enabled || this.isActive) {
@@ -19045,58 +19035,16 @@ class SessionReplayEngine {
19045
19035
  return false;
19046
19036
  }
19047
19037
  try {
19048
- // Start rrweb recording
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
- this.handleRRWebEvent(event);
19041
+ // Simple event capture - no processing
19042
+ this.events.push(event);
19054
19043
  },
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
19044
  });
19063
19045
  this.isActive = true;
19064
- this.hasFullSnapshot = false;
19065
- this.startTime = Date.now();
19066
19046
  this.startBatchTimer();
19067
- // WORKAROUND: Force FullSnapshot creation IMMEDIATELY to fix rrweb 2.0.0-alpha bug
19068
- // where FullSnapshot is sometimes not created as the first event
19069
- setTimeout(() => {
19070
- console.log("[Zaplier] Forcing immediate FullSnapshot to ensure correct event order...");
19071
- try {
19072
- takeFullSnapshot(true); // Force a new FullSnapshot immediately
19073
- console.log("[Zaplier] FullSnapshot manually triggered");
19074
- }
19075
- catch (error) {
19076
- console.error("[Zaplier] Failed to force FullSnapshot:", error);
19077
- }
19078
- }, 100); // Very short delay to ensure it comes first
19079
- // Set timeout to check if FullSnapshot was captured
19080
- this.snapshotTimeout = window.setTimeout(() => {
19081
- if (!this.hasFullSnapshot) {
19082
- console.error("[Zaplier] CRITICAL: FullSnapshot not captured after 5 seconds!", {
19083
- eventsReceived: this.events.length,
19084
- eventTypes: this.events.map((e) => e.type).slice(0, 10),
19085
- });
19086
- // Try one more forced snapshot as last resort
19087
- try {
19088
- console.warn("[Zaplier] Last resort: forcing FullSnapshot...");
19089
- takeFullSnapshot(true);
19090
- }
19091
- catch (error) {
19092
- console.error("[Zaplier] Failed to create emergency FullSnapshot:", error);
19093
- }
19094
- }
19095
- else {
19096
- console.log("[Zaplier] ✅ FullSnapshot confirmed captured");
19097
- }
19098
- }, 5000);
19099
- console.log("[Zaplier] Session replay started with rrweb");
19047
+ console.log("[Zaplier] Session replay started - simple mode");
19100
19048
  return true;
19101
19049
  }
19102
19050
  catch (error) {
@@ -19120,87 +19068,9 @@ class SessionReplayEngine {
19120
19068
  clearInterval(this.batchTimer);
19121
19069
  this.batchTimer = undefined;
19122
19070
  }
19123
- if (this.snapshotTimeout) {
19124
- clearTimeout(this.snapshotTimeout);
19125
- this.snapshotTimeout = undefined;
19126
- }
19127
19071
  // Send final batch
19128
19072
  this.sendBatch();
19129
19073
  }
19130
- /**
19131
- * Handle events from rrweb
19132
- */
19133
- handleRRWebEvent(event) {
19134
- try {
19135
- // Log ALL events until we get FullSnapshot, then log first 5
19136
- const shouldLog = !this.hasFullSnapshot || this.events.length < 5;
19137
- if (shouldLog) {
19138
- const eventTypeNames = {
19139
- [EventType.DomContentLoaded]: "DomContentLoaded",
19140
- [EventType.Load]: "Load",
19141
- [EventType.FullSnapshot]: "FullSnapshot",
19142
- [EventType.IncrementalSnapshot]: "IncrementalSnapshot",
19143
- [EventType.Meta]: "Meta",
19144
- [EventType.Custom]: "Custom",
19145
- [EventType.Plugin]: "Plugin",
19146
- };
19147
- console.log(`[Zaplier] Received event type ${event.type} (${eventTypeNames[event.type] || "Unknown"})`, {
19148
- timestamp: new Date(event.timestamp).toISOString(),
19149
- isFirst: this.events.length === 0,
19150
- totalEvents: this.events.length + 1,
19151
- });
19152
- }
19153
- // Check if this is a FullSnapshot
19154
- if (event.type === EventType.FullSnapshot) {
19155
- this.hasFullSnapshot = true;
19156
- console.log("[Zaplier] ✅ FullSnapshot captured! Replay will work correctly.");
19157
- // Clear timeout since we got the snapshot
19158
- if (this.snapshotTimeout) {
19159
- clearTimeout(this.snapshotTimeout);
19160
- this.snapshotTimeout = undefined;
19161
- }
19162
- }
19163
- else if (this.events.length === 0) {
19164
- // First event is NOT a FullSnapshot - this is a problem!
19165
- console.error(`[Zaplier] ⚠️ WARNING: First event is type ${event.type}, not FullSnapshot! Replay may not work.`);
19166
- }
19167
- // Add event to buffer
19168
- this.addEvent(event);
19169
- // If we just got the FullSnapshot and have events, try sending immediately
19170
- if (event.type === EventType.FullSnapshot && this.events.length > 0) {
19171
- // Small delay to ensure all initial events are captured
19172
- setTimeout(() => {
19173
- this.sendBatch();
19174
- }, 100);
19175
- }
19176
- }
19177
- catch (error) {
19178
- // Silently ignore errors from rrweb to prevent breaking the app
19179
- // The error is likely from rrweb's internal processing
19180
- console.warn("[Zaplier] Error handling rrweb event:", error);
19181
- }
19182
- }
19183
- /**
19184
- * Add event to buffer
19185
- */
19186
- addEvent(event) {
19187
- this.events.push(event);
19188
- // Prevent memory overflow
19189
- if (this.events.length > this.config.maxEventBuffer) {
19190
- // Keep FullSnapshot if present
19191
- const fullSnapshotIndex = this.events.findIndex((e) => e.type === EventType.FullSnapshot);
19192
- if (fullSnapshotIndex >= 0 &&
19193
- fullSnapshotIndex < this.events.length - this.config.maxEventBuffer) {
19194
- // Keep snapshot and recent events
19195
- const snapshot = this.events[fullSnapshotIndex];
19196
- const recentEvents = this.events.slice(-this.config.maxEventBuffer + 1);
19197
- this.events = [snapshot, ...recentEvents];
19198
- }
19199
- else {
19200
- this.events = this.events.slice(-this.config.maxEventBuffer);
19201
- }
19202
- }
19203
- }
19204
19074
  /**
19205
19075
  * Start batch timer
19206
19076
  */
@@ -19210,39 +19080,29 @@ class SessionReplayEngine {
19210
19080
  }, this.config.batchInterval);
19211
19081
  }
19212
19082
  /**
19213
- * Send batch of events
19083
+ * Send batch of events - Simplified like official example
19214
19084
  */
19215
19085
  sendBatch() {
19216
19086
  if (this.events.length === 0) {
19217
19087
  return;
19218
19088
  }
19219
- // CRITICAL: Never send batches without FullSnapshot - replay won't work!
19220
- if (!this.hasFullSnapshot) {
19221
- const waitTime = Date.now() - this.startTime;
19222
- // Only log every 2 seconds to avoid spam
19223
- if (waitTime % 2000 < 100) {
19224
- 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));
19225
- }
19226
- return; // Don't send without FullSnapshot
19227
- }
19228
- const batch = [...this.events];
19229
- this.events = [];
19230
- // Verify batch has FullSnapshot
19231
- const hasSnapshot = batch.some((e) => e.type === EventType.FullSnapshot);
19232
- if (!hasSnapshot && this.hasFullSnapshot) {
19233
- console.warn("[Zaplier] Batch missing FullSnapshot, but one was captured earlier");
19234
- }
19235
- console.log(`[Zaplier] Sending batch with ${batch.length} events for session ${this.sessionId}`, { hasSnapshot, firstEventType: batch[0]?.type });
19089
+ // Simple payload structure like official example
19236
19090
  const payload = {
19237
19091
  sessionId: this.sessionId,
19238
- events: batch,
19092
+ events: [...this.events], // Copy events array
19239
19093
  metadata: {
19240
19094
  userAgent: navigator.userAgent,
19241
19095
  timestamp: Date.now(),
19242
- compression: this.config.compressionEnabled,
19096
+ startUrl: window.location.href,
19097
+ duration: Date.now() - (performance.timeOrigin || Date.now()),
19098
+ funnelSteps: [],
19099
+ hasConversion: false,
19243
19100
  },
19244
19101
  };
19245
- // This will be handled by the anti-adblock manager
19102
+ // Reset events array like official example
19103
+ this.events = [];
19104
+ console.log(`[Zaplier] Sending batch with ${payload.events.length} events`);
19105
+ // Send to backend
19246
19106
  this.sendToBackend(payload);
19247
19107
  }
19248
19108
  /**
@@ -19260,24 +19120,8 @@ class SessionReplayEngine {
19260
19120
  console.error("[Zaplier] No SDK instance available for replay transport");
19261
19121
  return;
19262
19122
  }
19263
- console.log(`[Zaplier] Sending replay batch via SDK transport`);
19264
- console.log(`[Zaplier] Payload:`, {
19265
- sessionId: payload.sessionId,
19266
- eventCount: payload.events.length,
19267
- hasMetadata: !!payload.metadata,
19268
- });
19269
- // Use SDK's sendReplayBatch method
19270
- const result = await this.sdkInstance.sendReplayBatch({
19271
- sessionId: payload.sessionId,
19272
- events: payload.events,
19273
- metadata: {
19274
- startUrl: window.location.href,
19275
- duration: Date.now() - (performance.timeOrigin || Date.now()),
19276
- funnelSteps: [],
19277
- hasConversion: false,
19278
- ...payload.metadata,
19279
- },
19280
- });
19123
+ // Use SDK's sendReplayBatch method with simplified payload
19124
+ const result = await this.sdkInstance.sendReplayBatch(payload);
19281
19125
  if (result && result.success) {
19282
19126
  console.log("[Zaplier] Session replay batch sent successfully");
19283
19127
  }
@@ -19334,7 +19178,7 @@ const DEFAULT_CONFIG = {
19334
19178
  */
19335
19179
  class ZaplierSDK {
19336
19180
  constructor(userConfig) {
19337
- this.version = "1.3.5";
19181
+ this.version = "1.3.7";
19338
19182
  this.isInitialized = false;
19339
19183
  this.eventQueue = [];
19340
19184
  /**
@@ -19407,8 +19251,6 @@ class ZaplierSDK {
19407
19251
  // When explicitly enabled, use 100% sample rate
19408
19252
  this.replayEngine = new SessionReplayEngine(sessionId, {
19409
19253
  sampleRate: 1.0, // Force 100% when explicitly enabled
19410
- maskSensitiveFields: this.config.replayMaskInputs,
19411
- compressionEnabled: true,
19412
19254
  });
19413
19255
  // Connect to anti-adblock manager
19414
19256
  if (this.antiAdblockManager) {
@@ -19435,8 +19277,6 @@ class ZaplierSDK {
19435
19277
  const sessionId = this.sessionId;
19436
19278
  this.replayEngine = new SessionReplayEngine(sessionId, {
19437
19279
  sampleRate: 1.0, // Force 100% when explicitly enabled
19438
- maskSensitiveFields: this.config.replayMaskInputs,
19439
- compressionEnabled: true,
19440
19280
  });
19441
19281
  // Connect to anti-adblock manager
19442
19282
  if (this.antiAdblockManager) {
@@ -19477,8 +19317,6 @@ class ZaplierSDK {
19477
19317
  const sessionId = this.sessionId;
19478
19318
  this.replayEngine = new SessionReplayEngine(sessionId, {
19479
19319
  sampleRate: 1.0, // Force recording when manually started
19480
- maskSensitiveFields: this.config.replayMaskInputs,
19481
- compressionEnabled: true,
19482
19320
  });
19483
19321
  // Connect to anti-adblock manager
19484
19322
  if (this.antiAdblockManager) {
@@ -19583,8 +19421,6 @@ class ZaplierSDK {
19583
19421
  const sampleRate = this.config.replay === true ? 1.0 : this.config.replaySampling;
19584
19422
  this.replayEngine = new SessionReplayEngine(this.sessionId, {
19585
19423
  sampleRate: sampleRate,
19586
- maskSensitiveFields: this.config.replayMaskInputs,
19587
- compressionEnabled: true,
19588
19424
  });
19589
19425
  // Connect SDK instance for transport
19590
19426
  this.replayEngine.setSDKInstance(this);