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