@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/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
- * Uses rrweb to capture DOM snapshots and events for session replay
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, // 100% for development/testing
19031
- maskSensitiveFields: true,
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 using rrweb
19033
+ * Start session replay recording - Simplified like official example
19044
19034
  */
19045
19035
  start() {
19046
19036
  if (!this.config.enabled || this.isActive) {
@@ -19051,58 +19041,16 @@
19051
19041
  return false;
19052
19042
  }
19053
19043
  try {
19054
- // Start rrweb recording
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
- this.handleRRWebEvent(event);
19047
+ // Simple event capture - no processing
19048
+ this.events.push(event);
19060
19049
  },
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
19050
  });
19069
19051
  this.isActive = true;
19070
- this.hasFullSnapshot = false;
19071
- this.startTime = Date.now();
19072
19052
  this.startBatchTimer();
19073
- // WORKAROUND: Force FullSnapshot creation IMMEDIATELY to fix rrweb 2.0.0-alpha bug
19074
- // where FullSnapshot is sometimes not created as the first event
19075
- setTimeout(() => {
19076
- console.log("[Zaplier] Forcing immediate FullSnapshot to ensure correct event order...");
19077
- try {
19078
- takeFullSnapshot(true); // Force a new FullSnapshot immediately
19079
- console.log("[Zaplier] FullSnapshot manually triggered");
19080
- }
19081
- catch (error) {
19082
- console.error("[Zaplier] Failed to force FullSnapshot:", error);
19083
- }
19084
- }, 100); // Very short delay to ensure it comes 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");
19053
+ console.log("[Zaplier] Session replay started - simple mode");
19106
19054
  return true;
19107
19055
  }
19108
19056
  catch (error) {
@@ -19126,87 +19074,9 @@
19126
19074
  clearInterval(this.batchTimer);
19127
19075
  this.batchTimer = undefined;
19128
19076
  }
19129
- if (this.snapshotTimeout) {
19130
- clearTimeout(this.snapshotTimeout);
19131
- this.snapshotTimeout = undefined;
19132
- }
19133
19077
  // Send final batch
19134
19078
  this.sendBatch();
19135
19079
  }
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
19080
  /**
19211
19081
  * Start batch timer
19212
19082
  */
@@ -19216,39 +19086,29 @@
19216
19086
  }, this.config.batchInterval);
19217
19087
  }
19218
19088
  /**
19219
- * Send batch of events
19089
+ * Send batch of events - Simplified like official example
19220
19090
  */
19221
19091
  sendBatch() {
19222
19092
  if (this.events.length === 0) {
19223
19093
  return;
19224
19094
  }
19225
- // CRITICAL: Never send batches without FullSnapshot - replay won't work!
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
- // Verify batch has FullSnapshot
19237
- const hasSnapshot = batch.some((e) => e.type === EventType.FullSnapshot);
19238
- if (!hasSnapshot && this.hasFullSnapshot) {
19239
- console.warn("[Zaplier] Batch missing FullSnapshot, but one was captured earlier");
19240
- }
19241
- console.log(`[Zaplier] Sending batch with ${batch.length} events for session ${this.sessionId}`, { hasSnapshot, firstEventType: batch[0]?.type });
19095
+ // Simple payload structure like official example
19242
19096
  const payload = {
19243
19097
  sessionId: this.sessionId,
19244
- events: batch,
19098
+ events: [...this.events], // Copy events array
19245
19099
  metadata: {
19246
19100
  userAgent: navigator.userAgent,
19247
19101
  timestamp: Date.now(),
19248
- compression: this.config.compressionEnabled,
19102
+ startUrl: window.location.href,
19103
+ duration: Date.now() - (performance.timeOrigin || Date.now()),
19104
+ funnelSteps: [],
19105
+ hasConversion: false,
19249
19106
  },
19250
19107
  };
19251
- // This will be handled by the anti-adblock manager
19108
+ // Reset events array like official example
19109
+ this.events = [];
19110
+ console.log(`[Zaplier] Sending batch with ${payload.events.length} events`);
19111
+ // Send to backend
19252
19112
  this.sendToBackend(payload);
19253
19113
  }
19254
19114
  /**
@@ -19266,24 +19126,8 @@
19266
19126
  console.error("[Zaplier] No SDK instance available for replay transport");
19267
19127
  return;
19268
19128
  }
19269
- console.log(`[Zaplier] Sending replay batch via SDK transport`);
19270
- console.log(`[Zaplier] Payload:`, {
19271
- sessionId: payload.sessionId,
19272
- eventCount: payload.events.length,
19273
- hasMetadata: !!payload.metadata,
19274
- });
19275
- // Use SDK's sendReplayBatch method
19276
- const result = await this.sdkInstance.sendReplayBatch({
19277
- sessionId: payload.sessionId,
19278
- events: payload.events,
19279
- metadata: {
19280
- startUrl: window.location.href,
19281
- duration: Date.now() - (performance.timeOrigin || Date.now()),
19282
- funnelSteps: [],
19283
- hasConversion: false,
19284
- ...payload.metadata,
19285
- },
19286
- });
19129
+ // Use SDK's sendReplayBatch method with simplified payload
19130
+ const result = await this.sdkInstance.sendReplayBatch(payload);
19287
19131
  if (result && result.success) {
19288
19132
  console.log("[Zaplier] Session replay batch sent successfully");
19289
19133
  }
@@ -19340,7 +19184,7 @@
19340
19184
  */
19341
19185
  class ZaplierSDK {
19342
19186
  constructor(userConfig) {
19343
- this.version = "1.3.5";
19187
+ this.version = "1.3.7";
19344
19188
  this.isInitialized = false;
19345
19189
  this.eventQueue = [];
19346
19190
  /**
@@ -19413,8 +19257,6 @@
19413
19257
  // When explicitly enabled, use 100% sample rate
19414
19258
  this.replayEngine = new SessionReplayEngine(sessionId, {
19415
19259
  sampleRate: 1.0, // Force 100% when explicitly enabled
19416
- maskSensitiveFields: this.config.replayMaskInputs,
19417
- compressionEnabled: true,
19418
19260
  });
19419
19261
  // Connect to anti-adblock manager
19420
19262
  if (this.antiAdblockManager) {
@@ -19441,8 +19283,6 @@
19441
19283
  const sessionId = this.sessionId;
19442
19284
  this.replayEngine = new SessionReplayEngine(sessionId, {
19443
19285
  sampleRate: 1.0, // Force 100% when explicitly enabled
19444
- maskSensitiveFields: this.config.replayMaskInputs,
19445
- compressionEnabled: true,
19446
19286
  });
19447
19287
  // Connect to anti-adblock manager
19448
19288
  if (this.antiAdblockManager) {
@@ -19483,8 +19323,6 @@
19483
19323
  const sessionId = this.sessionId;
19484
19324
  this.replayEngine = new SessionReplayEngine(sessionId, {
19485
19325
  sampleRate: 1.0, // Force recording when manually started
19486
- maskSensitiveFields: this.config.replayMaskInputs,
19487
- compressionEnabled: true,
19488
19326
  });
19489
19327
  // Connect to anti-adblock manager
19490
19328
  if (this.antiAdblockManager) {
@@ -19589,8 +19427,6 @@
19589
19427
  const sampleRate = this.config.replay === true ? 1.0 : this.config.replaySampling;
19590
19428
  this.replayEngine = new SessionReplayEngine(this.sessionId, {
19591
19429
  sampleRate: sampleRate,
19592
- maskSensitiveFields: this.config.replayMaskInputs,
19593
- compressionEnabled: true,
19594
19430
  });
19595
19431
  // Connect SDK instance for transport
19596
19432
  this.replayEngine.setSDKInstance(this);