@zaplier/sdk 1.7.0 → 1.7.3

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
@@ -19264,85 +19264,14 @@ class AutoTracker {
19264
19264
  this.scrollThrottle = 0;
19265
19265
  this.isInitialized = false;
19266
19266
  this.delegationHandlers = new Map();
19267
- this.handleScroll = () => {
19268
- if (!this.config.trackScrolls)
19269
- return;
19270
- // Throttle scroll events for performance
19271
- const now = Date.now();
19272
- if (now - this.scrollThrottle < 100)
19273
- return; // 100ms throttle
19274
- this.scrollThrottle = now;
19275
- const scrollElements = document.querySelectorAll('[data-track-scroll]');
19276
- if (this.config.debug && scrollElements.length > 0) {
19277
- console.log(`[AutoTracker] Checking ${scrollElements.length} scroll elements`, {
19278
- scrollY: window.scrollY,
19279
- innerHeight: window.innerHeight
19280
- });
19281
- }
19282
- scrollElements.forEach((element) => {
19283
- let hasTriggered = element.getAttribute('data-scroll-triggered') === 'true';
19284
- if (hasTriggered)
19285
- return;
19286
- const threshold = parseFloat(element.getAttribute("data-scroll-threshold") || "0.5");
19287
- const rect = element.getBoundingClientRect();
19288
- const elementHeight = rect.height;
19289
- const visibleHeight = Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0);
19290
- const visibilityRatio = Math.max(0, visibleHeight) / elementHeight;
19291
- if (this.config.debug) {
19292
- console.log(`[AutoTracker] Element check:`, {
19293
- elementId: element.id || element.className,
19294
- visibilityRatio: Math.round(visibilityRatio * 100) / 100,
19295
- threshold,
19296
- triggered: hasTriggered
19297
- });
19298
- }
19299
- if (visibilityRatio >= threshold) {
19300
- element.setAttribute('data-scroll-triggered', 'true');
19301
- const eventName = element.getAttribute("data-track-scroll");
19302
- if (!eventName)
19303
- return;
19304
- const metadata = this.extractMetadata(element);
19305
- this.trackEvent(eventName, {
19306
- type: "scroll",
19307
- element: element.tagName.toLowerCase(),
19308
- threshold,
19309
- scrollDepth: window.scrollY,
19310
- visibilityRatio: Math.round(visibilityRatio * 100) / 100,
19311
- ...metadata,
19312
- });
19313
- if (this.config.debug) {
19314
- console.log(`[AutoTracker] Scroll tracked: ${eventName}`, {
19315
- threshold,
19316
- visibilityRatio,
19317
- scrollDepth: window.scrollY,
19318
- ...metadata
19319
- });
19320
- }
19321
- }
19322
- });
19323
- };
19324
- this.handleClick = (event) => {
19325
- if (!this.config.trackClicks)
19326
- return;
19327
- const target = event.target;
19328
- if (!target || !target.hasAttribute("data-track-click"))
19329
- return;
19330
- const eventName = target.getAttribute("data-track-click");
19331
- if (!eventName)
19332
- return;
19333
- const metadata = this.extractMetadata(target);
19334
- this.trackEvent(eventName, {
19335
- type: "click",
19336
- element: target.tagName.toLowerCase(),
19337
- ...metadata,
19338
- });
19339
- if (this.config.debug) {
19340
- console.log(`[AutoTracker] Click tracked: ${eventName}`, {
19341
- element: target.tagName.toLowerCase(),
19342
- ...metadata
19343
- });
19344
- }
19345
- };
19267
+ this.initializationAttempts = 0;
19268
+ this.maxInitializationAttempts = 3;
19269
+ this.diagnostics = {};
19270
+ /**
19271
+ * Cache scroll elements for better performance
19272
+ */
19273
+ this.cachedScrollElements = null;
19274
+ this.lastScrollElementsCheck = 0;
19346
19275
  this.sdkInstance = sdkInstance;
19347
19276
  this.config = {
19348
19277
  enabled: true,
@@ -19361,33 +19290,208 @@ class AutoTracker {
19361
19290
  start() {
19362
19291
  if (!this.config.enabled)
19363
19292
  return;
19293
+ this.initializationAttempts++;
19294
+ // Enhanced diagnostics
19295
+ this.runDiagnostics();
19364
19296
  if (this.config.debug) {
19365
- console.log("[Zaplier AutoTracker] Iniciando auto tracking", {
19366
- enabled: this.config.enabled,
19367
- trackClicks: this.config.trackClicks,
19368
- trackScrolls: this.config.trackScrolls,
19369
- trackViews: this.config.trackViews,
19370
- trackHovers: this.config.trackHovers,
19371
- trackForms: this.config.trackForms,
19372
- domReady: document.readyState
19373
- });
19297
+ console.log("[🔥 AutoTracker ENHANCED] Starting auto tracking", this.diagnostics);
19374
19298
  }
19375
- // Aguardar DOM ready se necessário
19376
- if (document.readyState === 'loading') {
19377
- if (this.config.debug) {
19378
- console.log("[Zaplier AutoTracker] DOM still loading, waiting for DOMContentLoaded...");
19299
+ // Multiple initialization strategies
19300
+ this.tryInitialization();
19301
+ }
19302
+ /**
19303
+ * Run comprehensive diagnostics
19304
+ */
19305
+ runDiagnostics() {
19306
+ this.diagnostics = {
19307
+ timestamp: new Date().toISOString(),
19308
+ attempt: this.initializationAttempts,
19309
+ environment: {
19310
+ domReady: document.readyState,
19311
+ reactDetected: this.detectReact(),
19312
+ reactVersion: this.getReactVersion(),
19313
+ userAgent: navigator.userAgent,
19314
+ isMobile: /Mobile|Android|iPhone|iPad/.test(navigator.userAgent),
19315
+ isSafari: /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent),
19316
+ protocol: window.location.protocol,
19317
+ isLocalhost: window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'
19318
+ },
19319
+ dom: {
19320
+ documentElement: !!document.documentElement,
19321
+ body: !!document.body,
19322
+ querySelector: typeof document.querySelector === 'function',
19323
+ addEventListener: typeof document.addEventListener === 'function',
19324
+ elementsFound: this.getElementCounts(),
19325
+ hasReactRoot: this.findReactRoot()
19326
+ },
19327
+ tracking: {
19328
+ sdkInstance: !!this.sdkInstance,
19329
+ trackCustomEvent: typeof this.sdkInstance?.trackCustomEvent === 'function',
19330
+ config: this.config,
19331
+ isInitialized: this.isInitialized,
19332
+ activeHandlers: Array.from(this.delegationHandlers.keys())
19379
19333
  }
19334
+ };
19335
+ }
19336
+ /**
19337
+ * Detect React presence
19338
+ */
19339
+ detectReact() {
19340
+ return !!(window.__REACT_DEVTOOLS_GLOBAL_HOOK__ ||
19341
+ window.React ||
19342
+ document.querySelector('[data-reactroot]') ||
19343
+ document.querySelector('#root') ||
19344
+ document.querySelector('#__next'));
19345
+ }
19346
+ /**
19347
+ * Get React version if available
19348
+ */
19349
+ getReactVersion() {
19350
+ try {
19351
+ const reactInstance = window.React;
19352
+ return reactInstance?.version || null;
19353
+ }
19354
+ catch {
19355
+ return null;
19356
+ }
19357
+ }
19358
+ /**
19359
+ * Find React root element
19360
+ */
19361
+ findReactRoot() {
19362
+ const reactRoot = document.querySelector('[data-reactroot]') ||
19363
+ document.querySelector('#root') ||
19364
+ document.querySelector('#__next') ||
19365
+ document.querySelector('div[data-react-helmet]');
19366
+ return reactRoot ? reactRoot.tagName + (reactRoot.id ? '#' + reactRoot.id : '') : null;
19367
+ }
19368
+ /**
19369
+ * Get element counts for all tracking types
19370
+ */
19371
+ getElementCounts() {
19372
+ return {
19373
+ click: document.querySelectorAll('[data-track-click]').length,
19374
+ scroll: document.querySelectorAll('[data-track-scroll]').length,
19375
+ view: document.querySelectorAll('[data-track-view]').length,
19376
+ hover: document.querySelectorAll('[data-track-hover]').length,
19377
+ form: document.querySelectorAll('[data-track-form]').length
19378
+ };
19379
+ }
19380
+ /**
19381
+ * Try multiple initialization strategies
19382
+ */
19383
+ tryInitialization() {
19384
+ const strategies = [
19385
+ () => this.immediateInitialization(),
19386
+ () => this.delayedInitialization(100),
19387
+ () => this.delayedInitialization(500),
19388
+ () => this.delayedInitialization(1000),
19389
+ () => this.reactReadyInitialization()
19390
+ ];
19391
+ // Try immediate initialization first
19392
+ if (document.readyState === 'complete') {
19393
+ this.attemptStrategy(0, strategies);
19394
+ }
19395
+ else if (document.readyState === 'interactive') {
19396
+ // DOM ready but resources still loading
19397
+ this.attemptStrategy(1, strategies);
19398
+ }
19399
+ else {
19400
+ // DOM still loading
19380
19401
  document.addEventListener('DOMContentLoaded', () => {
19381
- if (this.config.debug) {
19382
- console.log("[Zaplier AutoTracker] DOMContentLoaded fired, initializing tracking...");
19383
- }
19384
- this.initializeTracking();
19402
+ this.attemptStrategy(0, strategies);
19385
19403
  }, { once: true });
19386
19404
  }
19387
- else {
19405
+ }
19406
+ /**
19407
+ * Attempt initialization strategy with fallback
19408
+ */
19409
+ attemptStrategy(index, strategies) {
19410
+ if (index >= strategies.length || this.isInitialized)
19411
+ return;
19412
+ if (this.config.debug) {
19413
+ console.log(`[🔄 AutoTracker] Trying initialization strategy ${index + 1}/${strategies.length}`);
19414
+ }
19415
+ try {
19416
+ const strategy = strategies[index];
19417
+ if (strategy && typeof strategy === 'function') {
19418
+ strategy();
19419
+ // Verify initialization after a short delay
19420
+ setTimeout(() => {
19421
+ if (!this.verifyInitialization()) {
19422
+ if (this.config.debug) {
19423
+ console.log(`[⚠️ AutoTracker] Strategy ${index + 1} failed verification, trying next...`);
19424
+ }
19425
+ this.attemptStrategy(index + 1, strategies);
19426
+ }
19427
+ else {
19428
+ if (this.config.debug) {
19429
+ console.log(`[✅ AutoTracker] Strategy ${index + 1} successful!`);
19430
+ }
19431
+ }
19432
+ }, 50);
19433
+ }
19434
+ else {
19435
+ // Strategy is undefined or not a function, try next
19436
+ this.attemptStrategy(index + 1, strategies);
19437
+ }
19438
+ }
19439
+ catch (error) {
19440
+ if (this.config.debug) {
19441
+ console.error(`[❌ AutoTracker] Strategy ${index + 1} error:`, error);
19442
+ }
19443
+ this.attemptStrategy(index + 1, strategies);
19444
+ }
19445
+ }
19446
+ /**
19447
+ * Immediate initialization
19448
+ */
19449
+ immediateInitialization() {
19450
+ this.initializeTracking();
19451
+ }
19452
+ /**
19453
+ * Delayed initialization
19454
+ */
19455
+ delayedInitialization(delay) {
19456
+ setTimeout(() => {
19388
19457
  this.initializeTracking();
19458
+ }, delay);
19459
+ }
19460
+ /**
19461
+ * React-specific initialization timing
19462
+ */
19463
+ reactReadyInitialization() {
19464
+ // Wait for React to finish rendering
19465
+ if (typeof window.requestAnimationFrame === 'function') {
19466
+ window.requestAnimationFrame(() => {
19467
+ setTimeout(() => {
19468
+ this.initializeTracking();
19469
+ }, 0);
19470
+ });
19471
+ }
19472
+ else {
19473
+ setTimeout(() => {
19474
+ this.initializeTracking();
19475
+ }, 16); // ~60fps fallback
19389
19476
  }
19390
19477
  }
19478
+ /**
19479
+ * Verify initialization was successful
19480
+ */
19481
+ verifyInitialization() {
19482
+ const elementsFound = this.getElementCounts();
19483
+ const totalElements = Object.values(elementsFound).reduce((sum, count) => sum + count, 0);
19484
+ const hasActiveHandlers = this.delegationHandlers.size > 0;
19485
+ if (this.config.debug) {
19486
+ console.log('[🔍 AutoTracker] Verification:', {
19487
+ isInitialized: this.isInitialized,
19488
+ elementsFound: totalElements,
19489
+ hasActiveHandlers,
19490
+ handlersActive: Array.from(this.delegationHandlers.keys())
19491
+ });
19492
+ }
19493
+ return this.isInitialized && (totalElements > 0 || hasActiveHandlers);
19494
+ }
19391
19495
  initializeTracking() {
19392
19496
  if (this.config.debug) {
19393
19497
  console.log("[Zaplier AutoTracker] Initializing tracking...");
@@ -19446,119 +19550,337 @@ class AutoTracker {
19446
19550
  */
19447
19551
  setupEventDelegation() {
19448
19552
  if (this.config.debug) {
19449
- console.log("[AutoTracker] Setting up event delegation...");
19553
+ console.log("[🚀 AutoTracker] Setting up enhanced event delegation...");
19450
19554
  }
19451
- // Click delegation
19555
+ // Determine optimal delegation target based on React setup
19556
+ const delegationTarget = this.getOptimalDelegationTarget();
19557
+ if (this.config.debug) {
19558
+ console.log("[🎯 AutoTracker] Using delegation target:", delegationTarget);
19559
+ }
19560
+ // Click delegation with React compatibility
19452
19561
  if (this.config.trackClicks) {
19453
- const clickHandler = this.createDelegatedClickHandler();
19562
+ const clickHandler = this.createReactCompatibleClickHandler();
19454
19563
  this.delegationHandlers.set('click', clickHandler);
19455
- document.addEventListener('click', clickHandler, { passive: true });
19564
+ delegationTarget.addEventListener('click', clickHandler, this.getEventOptions('click'));
19565
+ if (this.config.debug) {
19566
+ console.log("[👆 AutoTracker] Click delegation handler added");
19567
+ }
19456
19568
  }
19457
- // Scroll delegation (using global handler with element detection)
19569
+ // CRITICAL FIX: Scroll delegation with enhanced detection
19458
19570
  if (this.config.trackScrolls) {
19459
- const scrollHandler = this.createDelegatedScrollHandler();
19571
+ const scrollHandler = this.createEnhancedScrollHandler();
19460
19572
  this.delegationHandlers.set('scroll', scrollHandler);
19461
- document.addEventListener('scroll', scrollHandler, { passive: true });
19573
+ // Always use document for scroll events (window doesn't work with removeEventListener)
19574
+ document.addEventListener('scroll', scrollHandler, this.getEventOptions('scroll'));
19575
+ if (this.config.debug) {
19576
+ console.log("[📜 AutoTracker] Scroll delegation handler added to document");
19577
+ // Immediate test of element detection
19578
+ setTimeout(() => {
19579
+ const scrollElements = this.getCachedScrollElements();
19580
+ console.log(`[📜 AutoTracker] Initial scroll elements check: ${scrollElements.length} found`);
19581
+ if (scrollElements.length > 0) {
19582
+ Array.from(scrollElements).forEach((element, index) => {
19583
+ console.log(`[📜 AutoTracker] Element ${index + 1}:`, {
19584
+ id: element.id || 'no-id',
19585
+ trackEvent: element.getAttribute('data-track-scroll'),
19586
+ threshold: element.getAttribute('data-scroll-threshold') || '0.5',
19587
+ tagName: element.tagName
19588
+ });
19589
+ });
19590
+ }
19591
+ }, 100);
19592
+ }
19462
19593
  }
19463
19594
  // Setup debounced mutation observer for dynamic content
19464
19595
  this.setupIntelligentMutationObserver();
19465
19596
  this.isInitialized = true;
19597
+ if (this.config.debug) {
19598
+ console.log("[✅ AutoTracker] Event delegation setup complete", {
19599
+ clickHandler: this.delegationHandlers.has('click'),
19600
+ scrollHandler: this.delegationHandlers.has('scroll'),
19601
+ totalHandlers: this.delegationHandlers.size
19602
+ });
19603
+ }
19466
19604
  }
19467
19605
  /**
19468
- * Create delegated click handler (no individual listeners needed)
19606
+ * Get optimal delegation target based on React setup
19469
19607
  */
19470
- createDelegatedClickHandler() {
19471
- return (event) => {
19472
- const target = event.target;
19473
- if (!target || !this.config.trackClicks)
19474
- return;
19475
- // Check if target or any parent has data-track-click
19476
- const trackingElement = target.closest('[data-track-click]');
19477
- if (!trackingElement)
19478
- return;
19479
- const eventName = trackingElement.getAttribute('data-track-click');
19480
- if (!eventName)
19481
- return;
19482
- const metadata = this.extractMetadata(trackingElement);
19483
- this.trackEvent(eventName, {
19484
- type: 'click',
19485
- element: trackingElement.tagName.toLowerCase(),
19486
- ...metadata,
19487
- });
19608
+ getOptimalDelegationTarget() {
19609
+ // For React 17+, prefer root container over document
19610
+ const reactRoot = document.querySelector('#root') ||
19611
+ document.querySelector('#__next') ||
19612
+ document.querySelector('[data-reactroot]');
19613
+ if (reactRoot && this.diagnostics.environment?.reactDetected) {
19488
19614
  if (this.config.debug) {
19489
- console.log(`[AutoTracker] Click tracked via delegation: ${eventName}`, {
19615
+ console.log("[⚛️ AutoTracker] Using React root for delegation:", reactRoot);
19616
+ }
19617
+ return reactRoot;
19618
+ }
19619
+ return document;
19620
+ }
19621
+ /**
19622
+ * Get optimized event options for different browsers
19623
+ */
19624
+ getEventOptions(eventType) {
19625
+ this.diagnostics.environment?.isMobile;
19626
+ const isSafari = this.diagnostics.environment?.isSafari;
19627
+ let options = {};
19628
+ switch (eventType) {
19629
+ case 'click':
19630
+ // Safari iOS requires non-passive click events for proper delegation
19631
+ options = {
19632
+ passive: !isSafari,
19633
+ capture: false
19634
+ };
19635
+ break;
19636
+ case 'scroll':
19637
+ options = {
19638
+ passive: true,
19639
+ capture: false
19640
+ };
19641
+ break;
19642
+ default:
19643
+ options = { passive: true };
19644
+ }
19645
+ if (this.config.debug) {
19646
+ console.log(`[⚙️ AutoTracker] Event options for ${eventType}:`, options);
19647
+ }
19648
+ return options;
19649
+ }
19650
+ /**
19651
+ * Create React-compatible click handler
19652
+ */
19653
+ createReactCompatibleClickHandler() {
19654
+ return (event) => {
19655
+ try {
19656
+ if (!this.config.trackClicks)
19657
+ return;
19658
+ // Enhanced target detection for nested React components
19659
+ const target = event.target;
19660
+ if (!target)
19661
+ return;
19662
+ // Multiple strategies to find tracking element
19663
+ let trackingElement = null;
19664
+ // Strategy 1: Direct closest (most common)
19665
+ trackingElement = target.closest('[data-track-click]');
19666
+ // Strategy 2: Check if target itself has the attribute (React edge case)
19667
+ if (!trackingElement && target.hasAttribute && target.hasAttribute('data-track-click')) {
19668
+ trackingElement = target;
19669
+ }
19670
+ // Strategy 3: Walk up DOM tree manually (React portal handling)
19671
+ if (!trackingElement) {
19672
+ trackingElement = this.findTrackingElementManually(target, 'data-track-click');
19673
+ }
19674
+ if (!trackingElement) {
19675
+ if (this.config.debug) {
19676
+ console.log('[🔍 AutoTracker] No tracking element found for click:', {
19677
+ target: target.tagName,
19678
+ hasClosest: typeof target.closest === 'function',
19679
+ hasAttribute: typeof target.hasAttribute === 'function'
19680
+ });
19681
+ }
19682
+ return;
19683
+ }
19684
+ const eventName = trackingElement.getAttribute('data-track-click');
19685
+ if (!eventName)
19686
+ return;
19687
+ const metadata = this.extractMetadata(trackingElement);
19688
+ this.trackEvent(eventName, {
19689
+ type: 'click',
19490
19690
  element: trackingElement.tagName.toLowerCase(),
19491
- ...metadata
19691
+ reactCompatible: true,
19692
+ ...metadata,
19492
19693
  });
19694
+ if (this.config.debug) {
19695
+ console.log(`[🎯 AutoTracker] Click tracked (React-compatible): ${eventName}`, {
19696
+ element: trackingElement.tagName.toLowerCase(),
19697
+ strategy: 'enhanced_delegation',
19698
+ ...metadata
19699
+ });
19700
+ }
19701
+ }
19702
+ catch (error) {
19703
+ if (this.config.debug) {
19704
+ console.error('[❌ AutoTracker] Click handler error:', error);
19705
+ }
19493
19706
  }
19494
19707
  };
19495
19708
  }
19496
19709
  /**
19497
- * Create delegated scroll handler (efficient global approach)
19710
+ * Manually walk up DOM tree to find tracking element
19498
19711
  */
19499
- createDelegatedScrollHandler() {
19712
+ findTrackingElementManually(element, attribute, maxDepth = 10) {
19713
+ let current = element;
19714
+ let depth = 0;
19715
+ while (current && current !== document.documentElement && depth < maxDepth) {
19716
+ if (current.hasAttribute && current.hasAttribute(attribute)) {
19717
+ return current;
19718
+ }
19719
+ current = current.parentElement;
19720
+ depth++;
19721
+ }
19722
+ return null;
19723
+ }
19724
+ /**
19725
+ * Create enhanced scroll handler with better performance
19726
+ */
19727
+ createEnhancedScrollHandler() {
19500
19728
  return () => {
19501
- if (!this.config.trackScrolls)
19502
- return;
19503
- // Throttle scroll events for performance
19504
- const now = Date.now();
19505
- if (now - this.scrollThrottle < 100)
19506
- return;
19507
- this.scrollThrottle = now;
19508
- // Find all scroll tracking elements and check visibility
19509
- const scrollElements = document.querySelectorAll('[data-track-scroll]');
19510
- if (this.config.debug && scrollElements.length > 0) {
19511
- console.log(`[AutoTracker] Checking ${scrollElements.length} scroll elements via delegation`);
19512
- }
19513
- scrollElements.forEach((element) => {
19514
- this.processScrollElement(element);
19515
- });
19729
+ try {
19730
+ if (!this.config.trackScrolls)
19731
+ return;
19732
+ // Adaptive throttling based on scroll frequency
19733
+ const now = Date.now();
19734
+ const timeDelta = now - this.scrollThrottle;
19735
+ const throttleDelay = this.diagnostics.environment?.isMobile ? 150 : 100;
19736
+ if (timeDelta < throttleDelay)
19737
+ return;
19738
+ this.scrollThrottle = now;
19739
+ // Enhanced element finding with caching
19740
+ const scrollElements = this.getCachedScrollElements();
19741
+ if (this.config.debug) {
19742
+ console.log(`[📜 AutoTracker] Enhanced scroll handler triggered`, {
19743
+ scrollElementsFound: scrollElements.length,
19744
+ scrollY: window.scrollY,
19745
+ throttleDelay,
19746
+ timeDelta
19747
+ });
19748
+ }
19749
+ // Process elements with enhanced visibility detection
19750
+ if (scrollElements.length > 0) {
19751
+ scrollElements.forEach((element) => {
19752
+ this.processScrollElementEnhanced(element);
19753
+ });
19754
+ }
19755
+ else if (this.config.debug) {
19756
+ console.log(`[📜 AutoTracker] No scroll elements found to process`);
19757
+ }
19758
+ }
19759
+ catch (error) {
19760
+ if (this.config.debug) {
19761
+ console.error('[❌ AutoTracker] Enhanced scroll handler error:', error);
19762
+ }
19763
+ }
19516
19764
  };
19517
19765
  }
19766
+ getCachedScrollElements() {
19767
+ const now = Date.now();
19768
+ const cacheExpiry = 2000; // Reduced to 2 seconds for faster detection
19769
+ if (!this.cachedScrollElements || (now - this.lastScrollElementsCheck) > cacheExpiry) {
19770
+ this.cachedScrollElements = document.querySelectorAll('[data-track-scroll]');
19771
+ this.lastScrollElementsCheck = now;
19772
+ if (this.config.debug) {
19773
+ console.log(`[🔄 AutoTracker] Refreshed scroll elements cache: ${this.cachedScrollElements.length} elements found`);
19774
+ // Log each element found for debugging
19775
+ Array.from(this.cachedScrollElements).forEach((element, index) => {
19776
+ console.log(`[🔄 AutoTracker] Cached element ${index + 1}:`, {
19777
+ id: element.id || 'no-id',
19778
+ className: element.className || 'no-class',
19779
+ trackEvent: element.getAttribute('data-track-scroll'),
19780
+ threshold: element.getAttribute('data-scroll-threshold') || '0.5',
19781
+ tagName: element.tagName,
19782
+ triggered: element.getAttribute('data-scroll-triggered') === 'true'
19783
+ });
19784
+ });
19785
+ }
19786
+ }
19787
+ return this.cachedScrollElements;
19788
+ }
19518
19789
  /**
19519
- * Process individual scroll element (extracted for reusability)
19790
+ * Process scroll element with enhanced detection
19520
19791
  */
19521
- processScrollElement(element) {
19522
- const hasTriggered = element.getAttribute('data-scroll-triggered') === 'true';
19523
- if (hasTriggered)
19524
- return;
19525
- const threshold = parseFloat(element.getAttribute('data-scroll-threshold') || '0.5');
19526
- const rect = element.getBoundingClientRect();
19527
- const elementHeight = rect.height;
19528
- const visibleHeight = Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0);
19529
- const visibilityRatio = Math.max(0, visibleHeight) / elementHeight;
19530
- if (this.config.debug) {
19531
- console.log(`[AutoTracker] Scroll element check via delegation:`, {
19532
- elementId: element.id || element.className,
19533
- visibilityRatio: Math.round(visibilityRatio * 100) / 100,
19534
- threshold,
19535
- triggered: hasTriggered
19536
- });
19537
- }
19538
- if (visibilityRatio >= threshold) {
19539
- element.setAttribute('data-scroll-triggered', 'true');
19792
+ processScrollElementEnhanced(element) {
19793
+ try {
19794
+ const hasTriggered = element.getAttribute('data-scroll-triggered') === 'true';
19795
+ if (hasTriggered) {
19796
+ if (this.config.debug) {
19797
+ console.log(`[⏭️ AutoTracker] Element already triggered, skipping:`, element.id || element.className || 'no-id');
19798
+ }
19799
+ return;
19800
+ }
19801
+ const threshold = parseFloat(element.getAttribute('data-scroll-threshold') || '0.5');
19802
+ // Enhanced visibility calculation
19803
+ const rect = element.getBoundingClientRect();
19804
+ const elementHeight = rect.height;
19805
+ const windowHeight = window.innerHeight;
19806
+ // Handle edge cases
19807
+ if (elementHeight <= 0) {
19808
+ if (this.config.debug) {
19809
+ console.log(`[⚠️ AutoTracker] Element has no height, skipping:`, element.id || 'no-id');
19810
+ }
19811
+ return;
19812
+ }
19813
+ const visibleTop = Math.max(rect.top, 0);
19814
+ const visibleBottom = Math.min(rect.bottom, windowHeight);
19815
+ const visibleHeight = Math.max(0, visibleBottom - visibleTop);
19816
+ const visibilityRatio = visibleHeight / elementHeight;
19540
19817
  const eventName = element.getAttribute('data-track-scroll');
19541
- if (!eventName)
19818
+ if (!eventName) {
19819
+ if (this.config.debug) {
19820
+ console.log(`[⚠️ AutoTracker] Element missing data-track-scroll attribute:`, element.id || 'no-id');
19821
+ }
19542
19822
  return;
19543
- const metadata = this.extractMetadata(element);
19544
- this.trackEvent(eventName, {
19545
- type: 'scroll',
19546
- element: element.tagName.toLowerCase(),
19547
- threshold,
19548
- scrollDepth: window.scrollY,
19549
- visibilityRatio: Math.round(visibilityRatio * 100) / 100,
19550
- ...metadata,
19551
- });
19823
+ }
19552
19824
  if (this.config.debug) {
19553
- console.log(`[AutoTracker] Scroll tracked via delegation: ${eventName}`, {
19825
+ console.log(`[📊 AutoTracker] Enhanced scroll check for "${eventName}":`, {
19826
+ elementId: element.id || element.className || 'no-id',
19827
+ rect: {
19828
+ top: Math.round(rect.top),
19829
+ bottom: Math.round(rect.bottom),
19830
+ height: Math.round(elementHeight)
19831
+ },
19832
+ window: {
19833
+ height: windowHeight,
19834
+ scrollY: window.scrollY
19835
+ },
19836
+ visibility: {
19837
+ visibleTop,
19838
+ visibleBottom,
19839
+ visibleHeight,
19840
+ ratio: Math.round(visibilityRatio * 1000) / 1000,
19841
+ threshold,
19842
+ triggered: hasTriggered,
19843
+ shouldTrigger: visibilityRatio >= threshold
19844
+ }
19845
+ });
19846
+ }
19847
+ if (visibilityRatio >= threshold) {
19848
+ // Mark as triggered to prevent duplicate events
19849
+ element.setAttribute('data-scroll-triggered', 'true');
19850
+ const metadata = this.extractMetadata(element);
19851
+ const eventData = {
19852
+ type: 'scroll',
19853
+ element: element.tagName.toLowerCase(),
19554
19854
  threshold,
19555
- visibilityRatio,
19556
19855
  scrollDepth: window.scrollY,
19557
- ...metadata
19856
+ visibilityRatio: Math.round(visibilityRatio * 1000) / 1000,
19857
+ enhanced: true,
19858
+ ...metadata,
19859
+ };
19860
+ if (this.config.debug) {
19861
+ console.log(`[🎯 AutoTracker] TRIGGERING scroll event "${eventName}":`, eventData);
19862
+ }
19863
+ this.trackEvent(eventName, eventData);
19864
+ if (this.config.debug) {
19865
+ console.log(`[✅ AutoTracker] Scroll event "${eventName}" sent successfully`);
19866
+ }
19867
+ }
19868
+ }
19869
+ catch (error) {
19870
+ if (this.config.debug) {
19871
+ console.error('[❌ AutoTracker] Scroll element processing error:', error, {
19872
+ element: element.id || element.className || 'no-id',
19873
+ tagName: element.tagName
19558
19874
  });
19559
19875
  }
19560
19876
  }
19561
19877
  }
19878
+ /**
19879
+ * Legacy method for compatibility
19880
+ */
19881
+ processScrollElement(element) {
19882
+ this.processScrollElementEnhanced(element);
19883
+ }
19562
19884
  /**
19563
19885
  * Setup intelligent mutation observer (debounced for performance)
19564
19886
  */
@@ -19849,43 +20171,90 @@ class AutoTracker {
19849
20171
  /**
19850
20172
  * Enviar evento para o SDK
19851
20173
  */
20174
+ /**
20175
+ * Enhanced event tracking with comprehensive debugging
20176
+ */
19852
20177
  trackEvent(eventName, metadata) {
20178
+ const trackingStart = performance.now();
19853
20179
  if (this.config.debug) {
19854
- console.log("[AutoTracker] trackEvent called:", { eventName, metadata });
19855
- }
19856
- if (!this.sdkInstance) {
19857
- if (this.config.debug) {
19858
- console.error("[AutoTracker] SDK instance is null!");
19859
- }
19860
- return;
20180
+ console.log("[🚀 AutoTracker] Enhanced trackEvent called:", {
20181
+ eventName,
20182
+ metadata,
20183
+ timestamp: new Date().toISOString()
20184
+ });
19861
20185
  }
19862
- if (typeof this.sdkInstance.trackCustomEvent !== 'function') {
20186
+ // Comprehensive validation
20187
+ const validation = this.validateTrackingCall(eventName, metadata);
20188
+ if (!validation.isValid) {
19863
20189
  if (this.config.debug) {
19864
- console.error("[AutoTracker] trackCustomEvent is not a function:", typeof this.sdkInstance.trackCustomEvent);
20190
+ console.error("[AutoTracker] Validation failed:", validation.errors);
19865
20191
  }
19866
20192
  return;
19867
20193
  }
19868
20194
  try {
19869
20195
  const eventData = {
20196
+ // Core tracking data
19870
20197
  autoTracked: true,
20198
+ enhanced: true,
19871
20199
  timestamp: Date.now(),
19872
20200
  url: window.location.href,
20201
+ userAgent: navigator.userAgent,
20202
+ // Performance data
20203
+ trackingLatency: Math.round((performance.now() - trackingStart) * 100) / 100,
20204
+ // Environment data
20205
+ isReactApp: this.diagnostics.environment?.reactDetected,
20206
+ isMobile: this.diagnostics.environment?.isMobile,
20207
+ // Event metadata
19873
20208
  ...metadata,
19874
20209
  };
19875
20210
  if (this.config.debug) {
19876
- console.log("[AutoTracker] Calling trackCustomEvent:", { eventName, eventData });
20211
+ console.log("[📡 AutoTracker] Sending enhanced event:", { eventName, eventData });
19877
20212
  }
19878
20213
  const result = this.sdkInstance.trackCustomEvent(eventName, eventData);
19879
20214
  if (this.config.debug) {
19880
- console.log("[AutoTracker] trackCustomEvent result:", result);
20215
+ const trackingEnd = performance.now();
20216
+ console.log("[✅ AutoTracker] Event sent successfully:", {
20217
+ eventName,
20218
+ result,
20219
+ totalLatency: Math.round((trackingEnd - trackingStart) * 100) / 100 + 'ms'
20220
+ });
19881
20221
  }
19882
20222
  }
19883
20223
  catch (error) {
19884
20224
  if (this.config.debug) {
19885
- console.error("[AutoTracker] Error sending event:", error);
20225
+ console.error("[💥 AutoTracker] Critical tracking error:", {
20226
+ eventName,
20227
+ error: error instanceof Error ? error.message : error,
20228
+ stack: error instanceof Error ? error.stack : undefined,
20229
+ metadata
20230
+ });
19886
20231
  }
19887
20232
  }
19888
20233
  }
20234
+ /**
20235
+ * Validate tracking call before sending
20236
+ */
20237
+ validateTrackingCall(eventName, metadata) {
20238
+ const errors = [];
20239
+ if (!eventName || typeof eventName !== 'string') {
20240
+ errors.push('Event name is required and must be a string');
20241
+ }
20242
+ if (!this.sdkInstance) {
20243
+ errors.push('SDK instance is null or undefined');
20244
+ }
20245
+ if (this.sdkInstance && typeof this.sdkInstance.trackCustomEvent !== 'function') {
20246
+ errors.push(`trackCustomEvent is not a function: ${typeof this.sdkInstance.trackCustomEvent}`);
20247
+ }
20248
+ if (!window || typeof window !== 'object') {
20249
+ errors.push('Window object is not available');
20250
+ }
20251
+ return {
20252
+ isValid: errors.length === 0,
20253
+ errors
20254
+ };
20255
+ }
20256
+ // Legacy handlers removed - now using enhanced event delegation system
20257
+ // All tracking is now handled by createEnhancedScrollHandler and createReactCompatibleClickHandler
19889
20258
  /**
19890
20259
  * Modern API: Refresh tracking for dynamic content (React/SPA support)
19891
20260
  * Industry best practice for SPA route changes
@@ -19915,26 +20284,83 @@ class AutoTracker {
19915
20284
  this.refreshTracking();
19916
20285
  }
19917
20286
  /**
19918
- * Get diagnostic information for debugging
20287
+ * Get comprehensive diagnostic information for debugging
19919
20288
  */
19920
20289
  getDiagnostics() {
19921
20290
  return {
19922
- isInitialized: this.isInitialized,
19923
- hasClickHandler: this.delegationHandlers.has('click'),
19924
- hasScrollHandler: this.delegationHandlers.has('scroll'),
19925
- observedElements: this.observedElements.size,
19926
- hasMutationObserver: !!this.mutationObserver,
19927
- hasIntersectionObserver: !!this.intersectionObserver,
20291
+ // Initialization status
20292
+ initialization: {
20293
+ isInitialized: this.isInitialized,
20294
+ attempts: this.initializationAttempts,
20295
+ maxAttempts: this.maxInitializationAttempts,
20296
+ timestamp: new Date().toISOString()
20297
+ },
20298
+ // Event handlers status
20299
+ eventHandlers: {
20300
+ hasClickHandler: this.delegationHandlers.has('click'),
20301
+ hasScrollHandler: this.delegationHandlers.has('scroll'),
20302
+ activeHandlers: Array.from(this.delegationHandlers.keys()),
20303
+ delegationTarget: this.getOptimalDelegationTarget() === document ? 'document' : 'react-root'
20304
+ },
20305
+ // Observers status
20306
+ observers: {
20307
+ observedElements: this.observedElements.size,
20308
+ hasMutationObserver: !!this.mutationObserver,
20309
+ hasIntersectionObserver: !!this.intersectionObserver,
20310
+ scrollElementsCache: !!this.cachedScrollElements,
20311
+ cacheExpiry: new Date(this.lastScrollElementsCheck + 5000).toISOString()
20312
+ },
20313
+ // Configuration
19928
20314
  config: this.config,
19929
- elementsFound: {
19930
- click: document.querySelectorAll('[data-track-click]').length,
19931
- scroll: document.querySelectorAll('[data-track-scroll]').length,
19932
- view: document.querySelectorAll('[data-track-view]').length,
19933
- hover: document.querySelectorAll('[data-track-hover]').length,
19934
- form: document.querySelectorAll('[data-track-form]').length
19935
- }
20315
+ // Current environment diagnostics
20316
+ environment: this.diagnostics.environment || {},
20317
+ // DOM state
20318
+ dom: this.diagnostics.dom || {},
20319
+ // SDK state
20320
+ tracking: this.diagnostics.tracking || {},
20321
+ // Real-time element detection
20322
+ elementsFound: this.getElementCounts(),
20323
+ // Performance metrics
20324
+ performance: {
20325
+ lastScrollThrottle: this.scrollThrottle,
20326
+ cacheLastUpdate: this.lastScrollElementsCheck
20327
+ },
20328
+ // Validation status
20329
+ validation: this.validateTrackingCall('test', {}),
20330
+ // Debug recommendations
20331
+ recommendations: this.generateRecommendations()
19936
20332
  };
19937
20333
  }
20334
+ /**
20335
+ * Generate diagnostic recommendations
20336
+ */
20337
+ generateRecommendations() {
20338
+ const recommendations = [];
20339
+ const elementsFound = this.getElementCounts();
20340
+ const totalElements = Object.values(elementsFound).reduce((sum, count) => sum + count, 0);
20341
+ if (!this.isInitialized) {
20342
+ recommendations.push('AutoTracker is not initialized. Check console for errors.');
20343
+ }
20344
+ if (totalElements === 0) {
20345
+ recommendations.push('No trackable elements found. Ensure data-track-* attributes are present in the DOM.');
20346
+ }
20347
+ if (!this.sdkInstance) {
20348
+ recommendations.push('SDK instance is missing. Ensure the SDK is properly initialized.');
20349
+ }
20350
+ if (this.sdkInstance && typeof this.sdkInstance.trackCustomEvent !== 'function') {
20351
+ recommendations.push('trackCustomEvent method is not available on SDK instance.');
20352
+ }
20353
+ if (!this.diagnostics.environment?.reactDetected && window.location.hostname.includes('localhost')) {
20354
+ recommendations.push('React not detected. If using React, ensure proper setup and try refreshTracking() after route changes.');
20355
+ }
20356
+ if (this.diagnostics.environment?.isMobile && !this.delegationHandlers.has('scroll')) {
20357
+ recommendations.push('Mobile device detected but scroll tracking not active. Check scroll tracking configuration.');
20358
+ }
20359
+ if (this.initializationAttempts > 1) {
20360
+ recommendations.push(`AutoTracker required ${this.initializationAttempts} initialization attempts. Consider adding delay before enabling.`);
20361
+ }
20362
+ return recommendations;
20363
+ }
19938
20364
  /**
19939
20365
  * Configurar tracking
19940
20366
  */
@@ -19954,6 +20380,33 @@ class AutoTracker {
19954
20380
  }
19955
20381
  }
19956
20382
 
20383
+ /**
20384
+ * Centralized Session Utilities
20385
+ * Standardized session ID generation for consistency across SDK and backend
20386
+ */
20387
+ /**
20388
+ * Generate standardized session ID
20389
+ * Format: visitorId_YYYYMMDD_HH
20390
+ * Example: f697a6e1-1aae-48db-bc6a-afc1d2c01852_20251231_03
20391
+ */
20392
+ function generateSessionId(visitorId, date) {
20393
+ const sessionDate = date || new Date();
20394
+ // Format: YYYYMMDD
20395
+ const year = sessionDate.getFullYear();
20396
+ const month = (sessionDate.getMonth() + 1).toString().padStart(2, '0');
20397
+ const day = sessionDate.getDate().toString().padStart(2, '0');
20398
+ const dateStr = `${year}${month}${day}`;
20399
+ // Format: HH (24-hour format)
20400
+ const hour = sessionDate.getHours().toString().padStart(2, '0');
20401
+ return `${visitorId}_${dateStr}_${hour}`;
20402
+ }
20403
+ /**
20404
+ * Generate session ID for current time
20405
+ */
20406
+ function generateCurrentSessionId(visitorId) {
20407
+ return generateSessionId(visitorId, new Date());
20408
+ }
20409
+
19957
20410
  /**
19958
20411
  * Visitor Persistence Manager for SDK
19959
20412
  * Implements client-side visitor identification with localStorage camouflage
@@ -20113,9 +20566,23 @@ class VisitorIdentityManager {
20113
20566
  // REMOVED: generateVisitorId() and generateVisitorIdFromHash() methods
20114
20567
  // SDK no longer generates visitor IDs - only backend does
20115
20568
  generateSessionId() {
20116
- return "ses_" + Array.from(crypto.getRandomValues(new Uint8Array(8)))
20117
- .map(b => b.toString(16).padStart(2, '0'))
20118
- .join('') + "_" + Date.now().toString(36);
20569
+ // Try to get existing visitor identity from storage
20570
+ const { value: storedData } = PersistenceManager.get(STORAGE_KEYS.prefs);
20571
+ if (storedData) {
20572
+ try {
20573
+ const parsed = JSON.parse(storedData);
20574
+ if (parsed._v && parsed._vb === true) {
20575
+ // We have a valid visitor ID from backend
20576
+ return generateCurrentSessionId(parsed._v);
20577
+ }
20578
+ }
20579
+ catch (e) {
20580
+ // Invalid data, continue to fallback
20581
+ }
20582
+ }
20583
+ // Fallback for cases where visitor ID is not available yet
20584
+ const tempVisitorId = "temp-" + Date.now().toString(36);
20585
+ return generateCurrentSessionId(tempVisitorId);
20119
20586
  }
20120
20587
  createCamouflageData(visitorId, sessionId, stableCoreHash, fromBackend = false) {
20121
20588
  return {
@@ -20125,7 +20592,7 @@ class VisitorIdentityManager {
20125
20592
  analytics: true,
20126
20593
  cookies: true,
20127
20594
  _v: visitorId, // Hidden visitor ID
20128
- _s: sessionId, // Hidden session ID
20595
+ _s: sessionId, // Hidden session ID
20129
20596
  _sc: stableCoreHash, // Hidden stable core
20130
20597
  _vb: fromBackend ? true : undefined, // Flag: visitor ID from backend (v1.7.0+)
20131
20598
  ts: Date.now(),
@@ -20169,7 +20636,9 @@ class VisitorIdentityManager {
20169
20636
  const { value: storedData, method } = PersistenceManager.get(STORAGE_KEYS.prefs);
20170
20637
  if (storedData) {
20171
20638
  const existingIdentity = this.extractFromCamouflage(storedData);
20172
- if (existingIdentity && existingIdentity.stableCoreHash === stableCoreHash && existingIdentity.visitorId) {
20639
+ if (existingIdentity &&
20640
+ existingIdentity.stableCoreHash === stableCoreHash &&
20641
+ existingIdentity.visitorId) {
20173
20642
  // Update last seen time only if we have a valid visitor ID from backend
20174
20643
  const updatedCamouflage = this.createCamouflageData(existingIdentity.visitorId, existingIdentity.sessionId, stableCoreHash);
20175
20644
  PersistenceManager.set(STORAGE_KEYS.prefs, JSON.stringify(updatedCamouflage));
@@ -20189,7 +20658,7 @@ class VisitorIdentityManager {
20189
20658
  stableCoreHash,
20190
20659
  deviceFingerprint: params.deviceFingerprint,
20191
20660
  persistenceMethod: "memory", // Start with memory, upgrade after backend response
20192
- confidence: 0.90,
20661
+ confidence: 0.9,
20193
20662
  createdAt: Date.now(),
20194
20663
  lastSeen: Date.now(),
20195
20664
  reused: false,
@@ -20204,7 +20673,12 @@ class VisitorIdentityManager {
20204
20673
  async updateVisitorIdFromBackend(visitorId, stableCoreHash, sessionId) {
20205
20674
  try {
20206
20675
  // Create or update camouflaged data with backend visitor ID
20207
- const currentSessionId = sessionId || this.getCurrentSessionId() || this.generateSessionId();
20676
+ // Regenerate session ID with proper visitor ID if needed
20677
+ let currentSessionId = sessionId || this.getCurrentSessionId();
20678
+ // If we have a temp session ID or no session ID, generate a new one with the proper visitor ID
20679
+ if (!currentSessionId || currentSessionId.includes("temp-")) {
20680
+ currentSessionId = generateCurrentSessionId(visitorId);
20681
+ }
20208
20682
  const camouflageData = this.createCamouflageData(visitorId, currentSessionId, stableCoreHash, true // Mark as coming from backend
20209
20683
  );
20210
20684
  const { success, method } = PersistenceManager.set(STORAGE_KEYS.prefs, JSON.stringify(camouflageData));
@@ -20216,7 +20690,7 @@ class VisitorIdentityManager {
20216
20690
  return false;
20217
20691
  }
20218
20692
  catch (error) {
20219
- console.error('[VisitorIdentityManager] Failed to update visitor ID from backend:', error);
20693
+ console.error("[VisitorIdentityManager] Failed to update visitor ID from backend:", error);
20220
20694
  return false;
20221
20695
  }
20222
20696
  }
@@ -20670,36 +21144,17 @@ class ZaplierSDK {
20670
21144
  }
20671
21145
  }
20672
21146
  /**
20673
- * Generate session ID
21147
+ * Generate session ID using standardized format
20674
21148
  */
20675
21149
  generateSessionId() {
20676
- // Create deterministic session ID based on page load time and stable browser characteristics
20677
- const pageLoadTime = performance.timeOrigin || Date.now();
20678
- const browserFingerprint = this.getBrowserFingerprint();
20679
- // Use page load time + browser fingerprint for session uniqueness within same page load
20680
- return pageLoadTime.toString(36) + browserFingerprint.substring(0, 8);
20681
- }
20682
- /**
20683
- * Get stable browser characteristics for session ID generation
20684
- * Uses only stable, privacy-safe values that don't change during session
20685
- */
20686
- getBrowserFingerprint() {
20687
- const components = [
20688
- navigator.userAgent || "",
20689
- navigator.platform || "",
20690
- screen.width || 0,
20691
- screen.height || 0,
20692
- new Date(2024, 0, 1).getTimezoneOffset(),
20693
- navigator.language || "",
20694
- navigator.hardwareConcurrency || 0,
20695
- ];
20696
- const combined = components.join("|");
20697
- let hash = 0;
20698
- for (let i = 0; i < combined.length; i++) {
20699
- const char = combined.charCodeAt(i);
20700
- hash = ((hash << 5) - hash + char) & 0xffffffff;
21150
+ // Use centralized session generation with current visitor ID
21151
+ if (this.backendVisitorId) {
21152
+ return generateCurrentSessionId(this.backendVisitorId);
20701
21153
  }
20702
- return Math.abs(hash).toString(36);
21154
+ // Fallback for cases where backendVisitorId is not available yet
21155
+ // This should be rare and will be updated when visitor ID is available
21156
+ const tempVisitorId = this.visitorId || 'temp-' + Date.now().toString(36);
21157
+ return generateCurrentSessionId(tempVisitorId);
20703
21158
  }
20704
21159
  /**
20705
21160
  * Initialize Anti-Adblock Manager
@@ -20958,6 +21413,10 @@ class ZaplierSDK {
20958
21413
  if (response.sessionId) {
20959
21414
  this.sessionId = response.sessionId;
20960
21415
  }
21416
+ else if (this.backendVisitorId && (!this.sessionId || this.sessionId.includes('temp-'))) {
21417
+ // Generate new session ID now that we have the proper visitor ID
21418
+ this.sessionId = generateCurrentSessionId(this.backendVisitorId);
21419
+ }
20961
21420
  return response;
20962
21421
  }
20963
21422
  catch (error) {