@zaplier/sdk 1.4.2 → 1.6.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 CHANGED
@@ -19016,14 +19016,20 @@ var n;
19016
19016
  * Based on official rrweb example for maximum compatibility
19017
19017
  */
19018
19018
  class SessionReplayEngine {
19019
- constructor(sessionId, config = {}) {
19019
+ constructor(sessionId, visitorId, config = {}) {
19020
19020
  this.events = [];
19021
19021
  this.isActive = false;
19022
+ this.isPaused = false;
19023
+ this.lastActivityTime = Date.now();
19024
+ this.sessionStartTime = Date.now();
19022
19025
  this.sessionId = sessionId;
19026
+ this.visitorId = visitorId;
19023
19027
  this.config = {
19024
19028
  enabled: true,
19025
19029
  sampleRate: 1.0,
19026
19030
  batchInterval: 10000, // 10 seconds like official example
19031
+ inactivityTimeout: 30000, // 30 seconds of inactivity
19032
+ pauseOnInactive: true, // Pause recording during inactivity
19027
19033
  ...config,
19028
19034
  };
19029
19035
  }
@@ -19042,13 +19048,18 @@ class SessionReplayEngine {
19042
19048
  // Simple rrweb recording configuration like official example
19043
19049
  this.rrwebStopRecord = record({
19044
19050
  emit: (event) => {
19045
- // Simple event capture
19046
- this.events.push(event);
19051
+ // Update activity time on any event
19052
+ this.onActivity();
19053
+ // Only capture events if not paused
19054
+ if (!this.isPaused) {
19055
+ this.events.push(event);
19056
+ }
19047
19057
  },
19048
19058
  });
19049
19059
  this.isActive = true;
19050
19060
  this.startBatchTimer();
19051
- console.log("[Zaplier] Session replay started - simple mode");
19061
+ this.startInactivityTracking();
19062
+ console.log("[Zaplier] Session replay started - with inactivity detection");
19052
19063
  return true;
19053
19064
  }
19054
19065
  catch (error) {
@@ -19072,6 +19083,10 @@ class SessionReplayEngine {
19072
19083
  clearInterval(this.batchTimer);
19073
19084
  this.batchTimer = undefined;
19074
19085
  }
19086
+ if (this.inactivityTimer) {
19087
+ clearTimeout(this.inactivityTimer);
19088
+ this.inactivityTimer = undefined;
19089
+ }
19075
19090
  // Send final batch
19076
19091
  this.sendBatch();
19077
19092
  }
@@ -19090,17 +19105,21 @@ class SessionReplayEngine {
19090
19105
  if (this.events.length === 0) {
19091
19106
  return;
19092
19107
  }
19093
- // Simple payload structure like official example
19108
+ // Enhanced payload structure with visitor linking
19094
19109
  const payload = {
19095
19110
  sessionId: this.sessionId,
19111
+ visitorId: this.visitorId,
19096
19112
  events: [...this.events], // Copy events array
19097
19113
  metadata: {
19098
19114
  userAgent: navigator.userAgent,
19099
19115
  timestamp: Date.now(),
19100
19116
  startUrl: window.location.href,
19101
- duration: Date.now() - (performance.timeOrigin || Date.now()),
19117
+ duration: Date.now() - this.sessionStartTime,
19118
+ activeTime: this.getActiveTime(),
19102
19119
  funnelSteps: [],
19103
19120
  hasConversion: false,
19121
+ eventsCount: this.events.length,
19122
+ isPaused: this.isPaused,
19104
19123
  },
19105
19124
  };
19106
19125
  // Reset events array like official example
@@ -19149,6 +19168,448 @@ class SessionReplayEngine {
19149
19168
  isRecording() {
19150
19169
  return this.isActive;
19151
19170
  }
19171
+ /**
19172
+ * Check if recording is paused
19173
+ */
19174
+ isPausedState() {
19175
+ return this.isPaused;
19176
+ }
19177
+ /**
19178
+ * Start inactivity tracking
19179
+ */
19180
+ startInactivityTracking() {
19181
+ if (!this.config.pauseOnInactive)
19182
+ return;
19183
+ // Listen for user activity events
19184
+ const activityEvents = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'];
19185
+ activityEvents.forEach(event => {
19186
+ document.addEventListener(event, this.onActivity.bind(this), true);
19187
+ });
19188
+ this.resetInactivityTimer();
19189
+ }
19190
+ /**
19191
+ * Handle activity event
19192
+ */
19193
+ onActivity() {
19194
+ this.lastActivityTime = Date.now();
19195
+ // Resume if paused
19196
+ if (this.isPaused) {
19197
+ this.resume();
19198
+ }
19199
+ this.resetInactivityTimer();
19200
+ }
19201
+ /**
19202
+ * Reset inactivity timer
19203
+ */
19204
+ resetInactivityTimer() {
19205
+ if (this.inactivityTimer) {
19206
+ clearTimeout(this.inactivityTimer);
19207
+ }
19208
+ this.inactivityTimer = window.setTimeout(() => {
19209
+ this.pauseForInactivity();
19210
+ }, this.config.inactivityTimeout);
19211
+ }
19212
+ /**
19213
+ * Pause recording due to inactivity
19214
+ */
19215
+ pauseForInactivity() {
19216
+ if (this.isPaused)
19217
+ return;
19218
+ this.isPaused = true;
19219
+ console.log("[Zaplier] Session replay paused due to inactivity");
19220
+ }
19221
+ /**
19222
+ * Resume recording after activity
19223
+ */
19224
+ resume() {
19225
+ if (!this.isPaused)
19226
+ return;
19227
+ this.isPaused = false;
19228
+ console.log("[Zaplier] Session replay resumed after activity");
19229
+ }
19230
+ /**
19231
+ * Get total active time (excluding paused periods)
19232
+ */
19233
+ getActiveTime() {
19234
+ const totalTime = Date.now() - this.sessionStartTime;
19235
+ // For now, return total time. In production, track pause periods accurately
19236
+ return totalTime;
19237
+ }
19238
+ /**
19239
+ * Get visitor ID
19240
+ */
19241
+ getVisitorId() {
19242
+ return this.visitorId;
19243
+ }
19244
+ }
19245
+
19246
+ /**
19247
+ * Auto Tracker - Sistema de tracking automático via data-* attributes
19248
+ *
19249
+ * Suporta:
19250
+ * - data-track-click="event-name"
19251
+ * - data-track-scroll="event-name"
19252
+ * - data-track-view="event-name"
19253
+ * - data-track-hover="event-name"
19254
+ * - data-track-form="event-name"
19255
+ */
19256
+ class AutoTracker {
19257
+ constructor(sdkInstance, config = {}) {
19258
+ this.observedElements = new Set();
19259
+ /**
19260
+ * Event handlers (bound to this)
19261
+ */
19262
+ this.handleClick = (event) => {
19263
+ const target = event.target;
19264
+ if (target.hasAttribute("data-track-click")) ;
19265
+ };
19266
+ this.handleScroll = () => {
19267
+ // Scroll is handled by element-specific listeners
19268
+ };
19269
+ this.handleHover = (event) => {
19270
+ // Hover is handled by element-specific listeners
19271
+ };
19272
+ this.handleForm = (event) => {
19273
+ // Form is handled by element-specific listeners
19274
+ };
19275
+ this.sdkInstance = sdkInstance;
19276
+ this.config = {
19277
+ enabled: true,
19278
+ trackClicks: true,
19279
+ trackScrolls: true,
19280
+ trackViews: true,
19281
+ trackHovers: true,
19282
+ trackForms: true,
19283
+ debug: false,
19284
+ ...config,
19285
+ };
19286
+ }
19287
+ /**
19288
+ * Inicializar auto tracking
19289
+ */
19290
+ start() {
19291
+ if (!this.config.enabled)
19292
+ return;
19293
+ if (this.config.debug) {
19294
+ console.log("[Zaplier AutoTracker] Iniciando auto tracking");
19295
+ }
19296
+ // Observer para novos elementos no DOM
19297
+ this.observeDOM();
19298
+ // Processar elementos já existentes
19299
+ this.processExistingElements();
19300
+ // Setup intersection observer para views
19301
+ if (this.config.trackViews) {
19302
+ this.setupViewTracking();
19303
+ }
19304
+ }
19305
+ /**
19306
+ * Parar auto tracking
19307
+ */
19308
+ stop() {
19309
+ document.removeEventListener("click", this.handleClick);
19310
+ document.removeEventListener("scroll", this.handleScroll);
19311
+ document.removeEventListener("mouseover", this.handleHover);
19312
+ document.removeEventListener("submit", this.handleForm);
19313
+ if (this.intersectionObserver) {
19314
+ this.intersectionObserver.disconnect();
19315
+ }
19316
+ this.observedElements.clear();
19317
+ }
19318
+ /**
19319
+ * Observar mudanças no DOM para novos elementos
19320
+ */
19321
+ observeDOM() {
19322
+ const observer = new MutationObserver((mutations) => {
19323
+ mutations.forEach((mutation) => {
19324
+ mutation.addedNodes.forEach((node) => {
19325
+ if (node.nodeType === Node.ELEMENT_NODE) {
19326
+ this.processElement(node);
19327
+ }
19328
+ });
19329
+ });
19330
+ });
19331
+ observer.observe(document.body, {
19332
+ childList: true,
19333
+ subtree: true,
19334
+ });
19335
+ }
19336
+ /**
19337
+ * Processar elementos já existentes no DOM
19338
+ */
19339
+ processExistingElements() {
19340
+ // Buscar todos os elementos com data-track-*
19341
+ const trackElements = document.querySelectorAll("[data-track-click], [data-track-scroll], [data-track-view], [data-track-hover], [data-track-form]");
19342
+ trackElements.forEach((element) => {
19343
+ this.processElement(element);
19344
+ });
19345
+ }
19346
+ /**
19347
+ * Processar um elemento específico
19348
+ */
19349
+ processElement(element) {
19350
+ // Click tracking
19351
+ if (this.config.trackClicks && element.hasAttribute("data-track-click")) {
19352
+ this.setupClickTracking(element);
19353
+ }
19354
+ // Scroll tracking
19355
+ if (this.config.trackScrolls && element.hasAttribute("data-track-scroll")) {
19356
+ this.setupScrollTracking(element);
19357
+ }
19358
+ // View tracking
19359
+ if (this.config.trackViews && element.hasAttribute("data-track-view")) {
19360
+ this.setupElementViewTracking(element);
19361
+ }
19362
+ // Hover tracking
19363
+ if (this.config.trackHovers && element.hasAttribute("data-track-hover")) {
19364
+ this.setupHoverTracking(element);
19365
+ }
19366
+ // Form tracking
19367
+ if (this.config.trackForms && element.hasAttribute("data-track-form")) {
19368
+ this.setupFormTracking(element);
19369
+ }
19370
+ }
19371
+ /**
19372
+ * Setup click tracking
19373
+ */
19374
+ setupClickTracking(element) {
19375
+ element.addEventListener("click", (event) => {
19376
+ const eventName = element.getAttribute("data-track-click");
19377
+ if (!eventName)
19378
+ return;
19379
+ const metadata = this.extractMetadata(element);
19380
+ this.trackEvent(eventName, {
19381
+ type: "click",
19382
+ element: element.tagName.toLowerCase(),
19383
+ ...metadata,
19384
+ });
19385
+ if (this.config.debug) {
19386
+ console.log(`[AutoTracker] Click tracked: ${eventName}`, metadata);
19387
+ }
19388
+ });
19389
+ }
19390
+ /**
19391
+ * Setup scroll tracking
19392
+ */
19393
+ setupScrollTracking(element) {
19394
+ let hasTriggered = false;
19395
+ const threshold = parseFloat(element.getAttribute("data-scroll-threshold") || "0.5");
19396
+ const handleScroll = () => {
19397
+ if (hasTriggered)
19398
+ return;
19399
+ const rect = element.getBoundingClientRect();
19400
+ const elementHeight = rect.height;
19401
+ const visibleHeight = Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0);
19402
+ const visibilityRatio = Math.max(0, visibleHeight) / elementHeight;
19403
+ if (visibilityRatio >= threshold) {
19404
+ hasTriggered = true;
19405
+ const eventName = element.getAttribute("data-track-scroll");
19406
+ if (!eventName)
19407
+ return;
19408
+ const metadata = this.extractMetadata(element);
19409
+ this.trackEvent(eventName, {
19410
+ type: "scroll",
19411
+ element: element.tagName.toLowerCase(),
19412
+ threshold,
19413
+ scrollDepth: window.scrollY,
19414
+ ...metadata,
19415
+ });
19416
+ if (this.config.debug) {
19417
+ console.log(`[AutoTracker] Scroll tracked: ${eventName}`, metadata);
19418
+ }
19419
+ }
19420
+ };
19421
+ document.addEventListener("scroll", handleScroll, { passive: true });
19422
+ // Check immediately in case element is already in view
19423
+ setTimeout(handleScroll, 100);
19424
+ }
19425
+ /**
19426
+ * Setup view tracking usando Intersection Observer
19427
+ */
19428
+ setupViewTracking() {
19429
+ this.intersectionObserver = new IntersectionObserver((entries) => {
19430
+ entries.forEach((entry) => {
19431
+ if (entry.isIntersecting) {
19432
+ const element = entry.target;
19433
+ const eventName = element.getAttribute("data-track-view");
19434
+ if (!eventName)
19435
+ return;
19436
+ const metadata = this.extractMetadata(element);
19437
+ this.trackEvent(eventName, {
19438
+ type: "view",
19439
+ element: element.tagName.toLowerCase(),
19440
+ intersectionRatio: entry.intersectionRatio,
19441
+ ...metadata,
19442
+ });
19443
+ if (this.config.debug) {
19444
+ console.log(`[AutoTracker] View tracked: ${eventName}`, metadata);
19445
+ }
19446
+ // Remove from observation after first trigger
19447
+ this.intersectionObserver?.unobserve(element);
19448
+ }
19449
+ });
19450
+ }, {
19451
+ threshold: 0.5, // 50% visible
19452
+ rootMargin: "0px",
19453
+ });
19454
+ }
19455
+ /**
19456
+ * Setup view tracking para elemento específico
19457
+ */
19458
+ setupElementViewTracking(element) {
19459
+ if (!this.intersectionObserver)
19460
+ return;
19461
+ if (!this.observedElements.has(element)) {
19462
+ this.intersectionObserver.observe(element);
19463
+ this.observedElements.add(element);
19464
+ }
19465
+ }
19466
+ /**
19467
+ * Setup hover tracking
19468
+ */
19469
+ setupHoverTracking(element) {
19470
+ let hoverStartTime;
19471
+ const minHoverTime = parseInt(element.getAttribute("data-hover-time") || "1000");
19472
+ element.addEventListener("mouseenter", () => {
19473
+ hoverStartTime = Date.now();
19474
+ });
19475
+ element.addEventListener("mouseleave", () => {
19476
+ const hoverDuration = Date.now() - hoverStartTime;
19477
+ if (hoverDuration >= minHoverTime) {
19478
+ const eventName = element.getAttribute("data-track-hover");
19479
+ if (!eventName)
19480
+ return;
19481
+ const metadata = this.extractMetadata(element);
19482
+ this.trackEvent(eventName, {
19483
+ type: "hover",
19484
+ element: element.tagName.toLowerCase(),
19485
+ hoverDuration,
19486
+ minHoverTime,
19487
+ ...metadata,
19488
+ });
19489
+ if (this.config.debug) {
19490
+ console.log(`[AutoTracker] Hover tracked: ${eventName}`, metadata);
19491
+ }
19492
+ }
19493
+ });
19494
+ }
19495
+ /**
19496
+ * Setup form tracking
19497
+ */
19498
+ setupFormTracking(element) {
19499
+ if (element.tagName.toLowerCase() !== "form")
19500
+ return;
19501
+ element.addEventListener("submit", (event) => {
19502
+ const eventName = element.getAttribute("data-track-form");
19503
+ if (!eventName)
19504
+ return;
19505
+ const formData = new FormData(element);
19506
+ const metadata = this.extractMetadata(element);
19507
+ // Extract form fields (without sensitive data)
19508
+ const fields = {};
19509
+ for (const [key, value] of formData.entries()) {
19510
+ // Skip sensitive fields
19511
+ if (!this.isSensitiveField(key)) {
19512
+ fields[key] =
19513
+ typeof value === "string" ? value.substring(0, 100) : "file";
19514
+ }
19515
+ }
19516
+ this.trackEvent(eventName, {
19517
+ type: "form_submit",
19518
+ element: "form",
19519
+ fieldCount: Array.from(formData.entries()).length,
19520
+ fields,
19521
+ ...metadata,
19522
+ });
19523
+ if (this.config.debug) {
19524
+ console.log(`[AutoTracker] Form submit tracked: ${eventName}`, metadata);
19525
+ }
19526
+ });
19527
+ }
19528
+ /**
19529
+ * Extrair metadata do elemento
19530
+ */
19531
+ extractMetadata(element) {
19532
+ const metadata = {};
19533
+ // Extrair todos os data-meta-* attributes
19534
+ Array.from(element.attributes).forEach((attr) => {
19535
+ if (attr.name.startsWith("data-meta-")) {
19536
+ const key = attr.name.replace("data-meta-", "");
19537
+ metadata[key] = attr.value;
19538
+ }
19539
+ });
19540
+ // Adicionar informações básicas
19541
+ if (element.id)
19542
+ metadata.elementId = element.id;
19543
+ if (element.className)
19544
+ metadata.elementClass = element.className;
19545
+ // Text content (limitado)
19546
+ const textContent = element.textContent?.trim();
19547
+ if (textContent && textContent.length > 0) {
19548
+ metadata.textContent = textContent.substring(0, 50);
19549
+ }
19550
+ // Position info
19551
+ const rect = element.getBoundingClientRect();
19552
+ metadata.elementPosition = {
19553
+ x: Math.round(rect.left),
19554
+ y: Math.round(rect.top),
19555
+ width: Math.round(rect.width),
19556
+ height: Math.round(rect.height),
19557
+ };
19558
+ return metadata;
19559
+ }
19560
+ /**
19561
+ * Verificar se um campo é sensível
19562
+ */
19563
+ isSensitiveField(fieldName) {
19564
+ const sensitivePatterns = [
19565
+ /password/i,
19566
+ /pass/i,
19567
+ /pwd/i,
19568
+ /secret/i,
19569
+ /token/i,
19570
+ /api[_-]?key/i,
19571
+ /credit[_-]?card/i,
19572
+ /ssn/i,
19573
+ /social/i,
19574
+ /tax/i,
19575
+ ];
19576
+ return sensitivePatterns.some((pattern) => pattern.test(fieldName));
19577
+ }
19578
+ /**
19579
+ * Enviar evento para o SDK
19580
+ */
19581
+ trackEvent(eventName, metadata) {
19582
+ if (!this.sdkInstance)
19583
+ return;
19584
+ try {
19585
+ this.sdkInstance.trackCustomEvent(eventName, {
19586
+ autoTracked: true,
19587
+ timestamp: Date.now(),
19588
+ url: window.location.href,
19589
+ ...metadata,
19590
+ });
19591
+ }
19592
+ catch (error) {
19593
+ if (this.config.debug) {
19594
+ console.error("[AutoTracker] Error sending event:", error);
19595
+ }
19596
+ }
19597
+ }
19598
+ /**
19599
+ * Configurar tracking
19600
+ */
19601
+ configure(config) {
19602
+ this.config = { ...this.config, ...config };
19603
+ }
19604
+ /**
19605
+ * Obter estatísticas
19606
+ */
19607
+ getStats() {
19608
+ return {
19609
+ observedElements: this.observedElements.size,
19610
+ config: this.config,
19611
+ };
19612
+ }
19152
19613
  }
19153
19614
 
19154
19615
  /**
@@ -19182,7 +19643,7 @@ const DEFAULT_CONFIG = {
19182
19643
  */
19183
19644
  class ZaplierSDK {
19184
19645
  constructor(userConfig) {
19185
- this.version = "1.3.7";
19646
+ this.version = "1.6.0";
19186
19647
  this.isInitialized = false;
19187
19648
  this.eventQueue = [];
19188
19649
  /**
@@ -19253,8 +19714,10 @@ class ZaplierSDK {
19253
19714
  }
19254
19715
  const sessionId = this.sessionId;
19255
19716
  // When explicitly enabled, use 100% sample rate
19256
- this.replayEngine = new SessionReplayEngine(sessionId, {
19717
+ this.replayEngine = new SessionReplayEngine(sessionId, this.backendVisitorId || 'unknown', {
19257
19718
  sampleRate: 1.0, // Force 100% when explicitly enabled
19719
+ inactivityTimeout: 30000,
19720
+ pauseOnInactive: true,
19258
19721
  });
19259
19722
  // Connect to anti-adblock manager
19260
19723
  if (this.antiAdblockManager) {
@@ -19279,8 +19742,10 @@ class ZaplierSDK {
19279
19742
  this.sessionId = this.generateSessionId();
19280
19743
  }
19281
19744
  const sessionId = this.sessionId;
19282
- this.replayEngine = new SessionReplayEngine(sessionId, {
19745
+ this.replayEngine = new SessionReplayEngine(sessionId, this.backendVisitorId || 'unknown', {
19283
19746
  sampleRate: 1.0, // Force 100% when explicitly enabled
19747
+ inactivityTimeout: 30000,
19748
+ pauseOnInactive: true,
19284
19749
  });
19285
19750
  // Connect to anti-adblock manager
19286
19751
  if (this.antiAdblockManager) {
@@ -19319,8 +19784,10 @@ class ZaplierSDK {
19319
19784
  this.sessionId = this.generateSessionId();
19320
19785
  }
19321
19786
  const sessionId = this.sessionId;
19322
- this.replayEngine = new SessionReplayEngine(sessionId, {
19787
+ this.replayEngine = new SessionReplayEngine(sessionId, this.backendVisitorId || 'unknown', {
19323
19788
  sampleRate: 1.0, // Force recording when manually started
19789
+ inactivityTimeout: 30000,
19790
+ pauseOnInactive: true,
19324
19791
  });
19325
19792
  // Connect to anti-adblock manager
19326
19793
  if (this.antiAdblockManager) {
@@ -19352,6 +19819,45 @@ class ZaplierSDK {
19352
19819
  this.trackConversion("funnel_conversion", data.value, data.currency, data);
19353
19820
  },
19354
19821
  };
19822
+ /**
19823
+ * Auto Tracker API
19824
+ */
19825
+ this.autoTrack = {
19826
+ enable: () => {
19827
+ if (!this.autoTracker) {
19828
+ this.initializeAutoTracker();
19829
+ }
19830
+ else {
19831
+ this.autoTracker.configure({ enabled: true });
19832
+ }
19833
+ if (this.config.debug) {
19834
+ console.log("[Zaplier] Auto tracking enabled");
19835
+ }
19836
+ },
19837
+ disable: () => {
19838
+ if (this.autoTracker) {
19839
+ this.autoTracker.stop();
19840
+ this.autoTracker = undefined;
19841
+ }
19842
+ if (this.config.debug) {
19843
+ console.log("[Zaplier] Auto tracking disabled");
19844
+ }
19845
+ },
19846
+ configure: (config) => {
19847
+ if (this.autoTracker) {
19848
+ this.autoTracker.configure(config);
19849
+ }
19850
+ if (this.config.debug) {
19851
+ console.log("[Zaplier] Auto tracking configured:", config);
19852
+ }
19853
+ },
19854
+ getStats: () => {
19855
+ return this.autoTracker ? this.autoTracker.getStats() : null;
19856
+ },
19857
+ isEnabled: () => {
19858
+ return !!this.autoTracker;
19859
+ },
19860
+ };
19355
19861
  // Validate required config
19356
19862
  if (!userConfig.token) {
19357
19863
  throw new Error("Zaplier: token is required");
@@ -19393,6 +19899,8 @@ class ZaplierSDK {
19393
19899
  this.initializeAntiAdblock();
19394
19900
  // Then initialize tracking engines (they'll connect to anti-adblock)
19395
19901
  this.initializeTrackingEngines();
19902
+ // Initialize auto tracker
19903
+ this.initializeAutoTracker();
19396
19904
  // Process queued events
19397
19905
  this.processEventQueue();
19398
19906
  if (this.config.debug) {
@@ -19423,8 +19931,10 @@ class ZaplierSDK {
19423
19931
  // When replay is explicitly enabled, use 100% sample rate to ensure recording
19424
19932
  // The default replaySampling (0.1) is only for automatic/production sampling
19425
19933
  const sampleRate = this.config.replay === true ? 1.0 : this.config.replaySampling;
19426
- this.replayEngine = new SessionReplayEngine(this.sessionId, {
19934
+ this.replayEngine = new SessionReplayEngine(this.sessionId, this.backendVisitorId || 'unknown', {
19427
19935
  sampleRate: sampleRate,
19936
+ inactivityTimeout: 30000,
19937
+ pauseOnInactive: true,
19428
19938
  });
19429
19939
  // Connect SDK instance for transport
19430
19940
  this.replayEngine.setSDKInstance(this);
@@ -19459,6 +19969,29 @@ class ZaplierSDK {
19459
19969
  console.error("[Zaplier] Failed to initialize tracking engines:", error);
19460
19970
  }
19461
19971
  }
19972
+ /**
19973
+ * Initialize Auto Tracker for data-* attributes
19974
+ */
19975
+ initializeAutoTracker() {
19976
+ try {
19977
+ this.autoTracker = new AutoTracker(this, {
19978
+ enabled: true,
19979
+ trackClicks: true,
19980
+ trackScrolls: true,
19981
+ trackViews: true,
19982
+ trackHovers: true,
19983
+ trackForms: true,
19984
+ debug: this.config.debug,
19985
+ });
19986
+ this.autoTracker.start();
19987
+ if (this.config.debug) {
19988
+ console.log("[Zaplier] Auto Tracker initialized and started");
19989
+ }
19990
+ }
19991
+ catch (error) {
19992
+ console.error("[Zaplier] Failed to initialize Auto Tracker:", error);
19993
+ }
19994
+ }
19462
19995
  /**
19463
19996
  * Generate session ID
19464
19997
  */
@@ -20401,6 +20934,44 @@ const Zaplier = {
20401
20934
  globalInstance.replay.markConversion(data);
20402
20935
  }
20403
20936
  },
20937
+ /**
20938
+ * Auto Tracker API
20939
+ */
20940
+ autoTrack: {
20941
+ enable: () => {
20942
+ if (!globalInstance) {
20943
+ console.warn('[Zaplier] SDK not initialized. Call Zaplier.init() first');
20944
+ return;
20945
+ }
20946
+ globalInstance.autoTrack.enable();
20947
+ },
20948
+ disable: () => {
20949
+ if (!globalInstance) {
20950
+ console.warn('[Zaplier] SDK not initialized. Call Zaplier.init() first');
20951
+ return;
20952
+ }
20953
+ globalInstance.autoTrack.disable();
20954
+ },
20955
+ configure: (config) => {
20956
+ if (!globalInstance) {
20957
+ console.warn('[Zaplier] SDK not initialized. Call Zaplier.init() first');
20958
+ return;
20959
+ }
20960
+ globalInstance.autoTrack.configure(config);
20961
+ },
20962
+ getStats: () => {
20963
+ if (!globalInstance) {
20964
+ return null;
20965
+ }
20966
+ return globalInstance.autoTrack.getStats();
20967
+ },
20968
+ isEnabled: () => {
20969
+ if (!globalInstance) {
20970
+ return false;
20971
+ }
20972
+ return globalInstance.autoTrack.isEnabled();
20973
+ }
20974
+ },
20404
20975
  /**
20405
20976
  * Debug and utility functions
20406
20977
  */
@@ -20427,7 +20998,7 @@ const Zaplier = {
20427
20998
  /**
20428
20999
  * Version info
20429
21000
  */
20430
- version: '3.0.0'
21001
+ version: '1.6.0'
20431
21002
  };
20432
21003
  /**
20433
21004
  * Auto-initialization from script tag data attributes