@zaplier/sdk 1.4.1 → 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,21 +19044,18 @@ class SessionReplayEngine {
19038
19044
  // Simple rrweb recording configuration like official example
19039
19045
  this.rrwebStopRecord = record({
19040
19046
  emit: (event) => {
19041
- // CRITICAL: Ensure FullSnapshot is always first event
19042
- if (this.events.length === 0 && event.type !== 2) {
19043
- console.warn(`[Zaplier] First event is type ${event.type}, not FullSnapshot (2). Skipping until FullSnapshot.`);
19044
- return; // Skip non-FullSnapshot events if no FullSnapshot captured yet
19045
- }
19046
- // Simple event capture
19047
- this.events.push(event);
19048
- if (event.type === 2) {
19049
- console.log(`[Zaplier] ✅ FullSnapshot captured as event #${this.events.length}`);
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);
19050
19052
  }
19051
19053
  },
19052
19054
  });
19053
19055
  this.isActive = true;
19054
19056
  this.startBatchTimer();
19055
- console.log("[Zaplier] Session replay started - simple mode");
19057
+ this.startInactivityTracking();
19058
+ console.log("[Zaplier] Session replay started - with inactivity detection");
19056
19059
  return true;
19057
19060
  }
19058
19061
  catch (error) {
@@ -19076,6 +19079,10 @@ class SessionReplayEngine {
19076
19079
  clearInterval(this.batchTimer);
19077
19080
  this.batchTimer = undefined;
19078
19081
  }
19082
+ if (this.inactivityTimer) {
19083
+ clearTimeout(this.inactivityTimer);
19084
+ this.inactivityTimer = undefined;
19085
+ }
19079
19086
  // Send final batch
19080
19087
  this.sendBatch();
19081
19088
  }
@@ -19094,17 +19101,21 @@ class SessionReplayEngine {
19094
19101
  if (this.events.length === 0) {
19095
19102
  return;
19096
19103
  }
19097
- // Simple payload structure like official example
19104
+ // Enhanced payload structure with visitor linking
19098
19105
  const payload = {
19099
19106
  sessionId: this.sessionId,
19107
+ visitorId: this.visitorId,
19100
19108
  events: [...this.events], // Copy events array
19101
19109
  metadata: {
19102
19110
  userAgent: navigator.userAgent,
19103
19111
  timestamp: Date.now(),
19104
19112
  startUrl: window.location.href,
19105
- duration: Date.now() - (performance.timeOrigin || Date.now()),
19113
+ duration: Date.now() - this.sessionStartTime,
19114
+ activeTime: this.getActiveTime(),
19106
19115
  funnelSteps: [],
19107
19116
  hasConversion: false,
19117
+ eventsCount: this.events.length,
19118
+ isPaused: this.isPaused,
19108
19119
  },
19109
19120
  };
19110
19121
  // Reset events array like official example
@@ -19153,6 +19164,448 @@ class SessionReplayEngine {
19153
19164
  isRecording() {
19154
19165
  return this.isActive;
19155
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
+ }
19156
19609
  }
19157
19610
 
19158
19611
  /**
@@ -19186,7 +19639,7 @@ const DEFAULT_CONFIG = {
19186
19639
  */
19187
19640
  class ZaplierSDK {
19188
19641
  constructor(userConfig) {
19189
- this.version = "1.3.7";
19642
+ this.version = "1.6.0";
19190
19643
  this.isInitialized = false;
19191
19644
  this.eventQueue = [];
19192
19645
  /**
@@ -19257,8 +19710,10 @@ class ZaplierSDK {
19257
19710
  }
19258
19711
  const sessionId = this.sessionId;
19259
19712
  // When explicitly enabled, use 100% sample rate
19260
- this.replayEngine = new SessionReplayEngine(sessionId, {
19713
+ this.replayEngine = new SessionReplayEngine(sessionId, this.backendVisitorId || 'unknown', {
19261
19714
  sampleRate: 1.0, // Force 100% when explicitly enabled
19715
+ inactivityTimeout: 30000,
19716
+ pauseOnInactive: true,
19262
19717
  });
19263
19718
  // Connect to anti-adblock manager
19264
19719
  if (this.antiAdblockManager) {
@@ -19283,8 +19738,10 @@ class ZaplierSDK {
19283
19738
  this.sessionId = this.generateSessionId();
19284
19739
  }
19285
19740
  const sessionId = this.sessionId;
19286
- this.replayEngine = new SessionReplayEngine(sessionId, {
19741
+ this.replayEngine = new SessionReplayEngine(sessionId, this.backendVisitorId || 'unknown', {
19287
19742
  sampleRate: 1.0, // Force 100% when explicitly enabled
19743
+ inactivityTimeout: 30000,
19744
+ pauseOnInactive: true,
19288
19745
  });
19289
19746
  // Connect to anti-adblock manager
19290
19747
  if (this.antiAdblockManager) {
@@ -19323,8 +19780,10 @@ class ZaplierSDK {
19323
19780
  this.sessionId = this.generateSessionId();
19324
19781
  }
19325
19782
  const sessionId = this.sessionId;
19326
- this.replayEngine = new SessionReplayEngine(sessionId, {
19783
+ this.replayEngine = new SessionReplayEngine(sessionId, this.backendVisitorId || 'unknown', {
19327
19784
  sampleRate: 1.0, // Force recording when manually started
19785
+ inactivityTimeout: 30000,
19786
+ pauseOnInactive: true,
19328
19787
  });
19329
19788
  // Connect to anti-adblock manager
19330
19789
  if (this.antiAdblockManager) {
@@ -19356,6 +19815,45 @@ class ZaplierSDK {
19356
19815
  this.trackConversion("funnel_conversion", data.value, data.currency, data);
19357
19816
  },
19358
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
+ };
19359
19857
  // Validate required config
19360
19858
  if (!userConfig.token) {
19361
19859
  throw new Error("Zaplier: token is required");
@@ -19397,6 +19895,8 @@ class ZaplierSDK {
19397
19895
  this.initializeAntiAdblock();
19398
19896
  // Then initialize tracking engines (they'll connect to anti-adblock)
19399
19897
  this.initializeTrackingEngines();
19898
+ // Initialize auto tracker
19899
+ this.initializeAutoTracker();
19400
19900
  // Process queued events
19401
19901
  this.processEventQueue();
19402
19902
  if (this.config.debug) {
@@ -19427,8 +19927,10 @@ class ZaplierSDK {
19427
19927
  // When replay is explicitly enabled, use 100% sample rate to ensure recording
19428
19928
  // The default replaySampling (0.1) is only for automatic/production sampling
19429
19929
  const sampleRate = this.config.replay === true ? 1.0 : this.config.replaySampling;
19430
- this.replayEngine = new SessionReplayEngine(this.sessionId, {
19930
+ this.replayEngine = new SessionReplayEngine(this.sessionId, this.backendVisitorId || 'unknown', {
19431
19931
  sampleRate: sampleRate,
19932
+ inactivityTimeout: 30000,
19933
+ pauseOnInactive: true,
19432
19934
  });
19433
19935
  // Connect SDK instance for transport
19434
19936
  this.replayEngine.setSDKInstance(this);
@@ -19463,6 +19965,29 @@ class ZaplierSDK {
19463
19965
  console.error("[Zaplier] Failed to initialize tracking engines:", error);
19464
19966
  }
19465
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
+ }
19466
19991
  /**
19467
19992
  * Generate session ID
19468
19993
  */
@@ -20405,6 +20930,44 @@ const Zaplier = {
20405
20930
  globalInstance.replay.markConversion(data);
20406
20931
  }
20407
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
+ },
20408
20971
  /**
20409
20972
  * Debug and utility functions
20410
20973
  */
@@ -20431,7 +20994,7 @@ const Zaplier = {
20431
20994
  /**
20432
20995
  * Version info
20433
20996
  */
20434
- version: '3.0.0'
20997
+ version: '1.6.0'
20435
20998
  };
20436
20999
  /**
20437
21000
  * Auto-initialization from script tag data attributes