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