@zaplier/sdk 1.7.0 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +560 -122
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +560 -122
- package/dist/index.esm.js.map +1 -1
- package/dist/sdk.js +560 -122
- package/dist/sdk.js.map +1 -1
- package/dist/sdk.min.js +1 -1
- package/dist/src/modules/auto-tracker.d.ts +86 -6
- package/dist/src/modules/auto-tracker.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -19268,6 +19268,14 @@ class AutoTracker {
|
|
|
19268
19268
|
this.scrollThrottle = 0;
|
|
19269
19269
|
this.isInitialized = false;
|
|
19270
19270
|
this.delegationHandlers = new Map();
|
|
19271
|
+
this.initializationAttempts = 0;
|
|
19272
|
+
this.maxInitializationAttempts = 3;
|
|
19273
|
+
this.diagnostics = {};
|
|
19274
|
+
/**
|
|
19275
|
+
* Cache scroll elements for better performance
|
|
19276
|
+
*/
|
|
19277
|
+
this.cachedScrollElements = null;
|
|
19278
|
+
this.lastScrollElementsCheck = 0;
|
|
19271
19279
|
this.handleScroll = () => {
|
|
19272
19280
|
if (!this.config.trackScrolls)
|
|
19273
19281
|
return;
|
|
@@ -19365,32 +19373,207 @@ class AutoTracker {
|
|
|
19365
19373
|
start() {
|
|
19366
19374
|
if (!this.config.enabled)
|
|
19367
19375
|
return;
|
|
19376
|
+
this.initializationAttempts++;
|
|
19377
|
+
// Enhanced diagnostics
|
|
19378
|
+
this.runDiagnostics();
|
|
19368
19379
|
if (this.config.debug) {
|
|
19369
|
-
console.log("[
|
|
19370
|
-
enabled: this.config.enabled,
|
|
19371
|
-
trackClicks: this.config.trackClicks,
|
|
19372
|
-
trackScrolls: this.config.trackScrolls,
|
|
19373
|
-
trackViews: this.config.trackViews,
|
|
19374
|
-
trackHovers: this.config.trackHovers,
|
|
19375
|
-
trackForms: this.config.trackForms,
|
|
19376
|
-
domReady: document.readyState
|
|
19377
|
-
});
|
|
19380
|
+
console.log("[🔥 AutoTracker ENHANCED] Starting auto tracking", this.diagnostics);
|
|
19378
19381
|
}
|
|
19379
|
-
//
|
|
19380
|
-
|
|
19381
|
-
|
|
19382
|
-
|
|
19382
|
+
// Multiple initialization strategies
|
|
19383
|
+
this.tryInitialization();
|
|
19384
|
+
}
|
|
19385
|
+
/**
|
|
19386
|
+
* Run comprehensive diagnostics
|
|
19387
|
+
*/
|
|
19388
|
+
runDiagnostics() {
|
|
19389
|
+
this.diagnostics = {
|
|
19390
|
+
timestamp: new Date().toISOString(),
|
|
19391
|
+
attempt: this.initializationAttempts,
|
|
19392
|
+
environment: {
|
|
19393
|
+
domReady: document.readyState,
|
|
19394
|
+
reactDetected: this.detectReact(),
|
|
19395
|
+
reactVersion: this.getReactVersion(),
|
|
19396
|
+
userAgent: navigator.userAgent,
|
|
19397
|
+
isMobile: /Mobile|Android|iPhone|iPad/.test(navigator.userAgent),
|
|
19398
|
+
isSafari: /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent),
|
|
19399
|
+
protocol: window.location.protocol,
|
|
19400
|
+
isLocalhost: window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'
|
|
19401
|
+
},
|
|
19402
|
+
dom: {
|
|
19403
|
+
documentElement: !!document.documentElement,
|
|
19404
|
+
body: !!document.body,
|
|
19405
|
+
querySelector: typeof document.querySelector === 'function',
|
|
19406
|
+
addEventListener: typeof document.addEventListener === 'function',
|
|
19407
|
+
elementsFound: this.getElementCounts(),
|
|
19408
|
+
hasReactRoot: this.findReactRoot()
|
|
19409
|
+
},
|
|
19410
|
+
tracking: {
|
|
19411
|
+
sdkInstance: !!this.sdkInstance,
|
|
19412
|
+
trackCustomEvent: typeof this.sdkInstance?.trackCustomEvent === 'function',
|
|
19413
|
+
config: this.config,
|
|
19414
|
+
isInitialized: this.isInitialized,
|
|
19415
|
+
activeHandlers: Array.from(this.delegationHandlers.keys())
|
|
19383
19416
|
}
|
|
19417
|
+
};
|
|
19418
|
+
}
|
|
19419
|
+
/**
|
|
19420
|
+
* Detect React presence
|
|
19421
|
+
*/
|
|
19422
|
+
detectReact() {
|
|
19423
|
+
return !!(window.__REACT_DEVTOOLS_GLOBAL_HOOK__ ||
|
|
19424
|
+
window.React ||
|
|
19425
|
+
document.querySelector('[data-reactroot]') ||
|
|
19426
|
+
document.querySelector('#root') ||
|
|
19427
|
+
document.querySelector('#__next'));
|
|
19428
|
+
}
|
|
19429
|
+
/**
|
|
19430
|
+
* Get React version if available
|
|
19431
|
+
*/
|
|
19432
|
+
getReactVersion() {
|
|
19433
|
+
try {
|
|
19434
|
+
const reactInstance = window.React;
|
|
19435
|
+
return reactInstance?.version || null;
|
|
19436
|
+
}
|
|
19437
|
+
catch {
|
|
19438
|
+
return null;
|
|
19439
|
+
}
|
|
19440
|
+
}
|
|
19441
|
+
/**
|
|
19442
|
+
* Find React root element
|
|
19443
|
+
*/
|
|
19444
|
+
findReactRoot() {
|
|
19445
|
+
const reactRoot = document.querySelector('[data-reactroot]') ||
|
|
19446
|
+
document.querySelector('#root') ||
|
|
19447
|
+
document.querySelector('#__next') ||
|
|
19448
|
+
document.querySelector('div[data-react-helmet]');
|
|
19449
|
+
return reactRoot ? reactRoot.tagName + (reactRoot.id ? '#' + reactRoot.id : '') : null;
|
|
19450
|
+
}
|
|
19451
|
+
/**
|
|
19452
|
+
* Get element counts for all tracking types
|
|
19453
|
+
*/
|
|
19454
|
+
getElementCounts() {
|
|
19455
|
+
return {
|
|
19456
|
+
click: document.querySelectorAll('[data-track-click]').length,
|
|
19457
|
+
scroll: document.querySelectorAll('[data-track-scroll]').length,
|
|
19458
|
+
view: document.querySelectorAll('[data-track-view]').length,
|
|
19459
|
+
hover: document.querySelectorAll('[data-track-hover]').length,
|
|
19460
|
+
form: document.querySelectorAll('[data-track-form]').length
|
|
19461
|
+
};
|
|
19462
|
+
}
|
|
19463
|
+
/**
|
|
19464
|
+
* Try multiple initialization strategies
|
|
19465
|
+
*/
|
|
19466
|
+
tryInitialization() {
|
|
19467
|
+
const strategies = [
|
|
19468
|
+
() => this.immediateInitialization(),
|
|
19469
|
+
() => this.delayedInitialization(100),
|
|
19470
|
+
() => this.delayedInitialization(500),
|
|
19471
|
+
() => this.delayedInitialization(1000),
|
|
19472
|
+
() => this.reactReadyInitialization()
|
|
19473
|
+
];
|
|
19474
|
+
// Try immediate initialization first
|
|
19475
|
+
if (document.readyState === 'complete') {
|
|
19476
|
+
this.attemptStrategy(0, strategies);
|
|
19477
|
+
}
|
|
19478
|
+
else if (document.readyState === 'interactive') {
|
|
19479
|
+
// DOM ready but resources still loading
|
|
19480
|
+
this.attemptStrategy(1, strategies);
|
|
19481
|
+
}
|
|
19482
|
+
else {
|
|
19483
|
+
// DOM still loading
|
|
19384
19484
|
document.addEventListener('DOMContentLoaded', () => {
|
|
19385
|
-
|
|
19386
|
-
console.log("[Zaplier AutoTracker] DOMContentLoaded fired, initializing tracking...");
|
|
19387
|
-
}
|
|
19388
|
-
this.initializeTracking();
|
|
19485
|
+
this.attemptStrategy(0, strategies);
|
|
19389
19486
|
}, { once: true });
|
|
19390
19487
|
}
|
|
19391
|
-
|
|
19488
|
+
}
|
|
19489
|
+
/**
|
|
19490
|
+
* Attempt initialization strategy with fallback
|
|
19491
|
+
*/
|
|
19492
|
+
attemptStrategy(index, strategies) {
|
|
19493
|
+
if (index >= strategies.length || this.isInitialized)
|
|
19494
|
+
return;
|
|
19495
|
+
if (this.config.debug) {
|
|
19496
|
+
console.log(`[🔄 AutoTracker] Trying initialization strategy ${index + 1}/${strategies.length}`);
|
|
19497
|
+
}
|
|
19498
|
+
try {
|
|
19499
|
+
const strategy = strategies[index];
|
|
19500
|
+
if (strategy && typeof strategy === 'function') {
|
|
19501
|
+
strategy();
|
|
19502
|
+
// Verify initialization after a short delay
|
|
19503
|
+
setTimeout(() => {
|
|
19504
|
+
if (!this.verifyInitialization()) {
|
|
19505
|
+
if (this.config.debug) {
|
|
19506
|
+
console.log(`[⚠️ AutoTracker] Strategy ${index + 1} failed verification, trying next...`);
|
|
19507
|
+
}
|
|
19508
|
+
this.attemptStrategy(index + 1, strategies);
|
|
19509
|
+
}
|
|
19510
|
+
else {
|
|
19511
|
+
if (this.config.debug) {
|
|
19512
|
+
console.log(`[✅ AutoTracker] Strategy ${index + 1} successful!`);
|
|
19513
|
+
}
|
|
19514
|
+
}
|
|
19515
|
+
}, 50);
|
|
19516
|
+
}
|
|
19517
|
+
else {
|
|
19518
|
+
// Strategy is undefined or not a function, try next
|
|
19519
|
+
this.attemptStrategy(index + 1, strategies);
|
|
19520
|
+
}
|
|
19521
|
+
}
|
|
19522
|
+
catch (error) {
|
|
19523
|
+
if (this.config.debug) {
|
|
19524
|
+
console.error(`[❌ AutoTracker] Strategy ${index + 1} error:`, error);
|
|
19525
|
+
}
|
|
19526
|
+
this.attemptStrategy(index + 1, strategies);
|
|
19527
|
+
}
|
|
19528
|
+
}
|
|
19529
|
+
/**
|
|
19530
|
+
* Immediate initialization
|
|
19531
|
+
*/
|
|
19532
|
+
immediateInitialization() {
|
|
19533
|
+
this.initializeTracking();
|
|
19534
|
+
}
|
|
19535
|
+
/**
|
|
19536
|
+
* Delayed initialization
|
|
19537
|
+
*/
|
|
19538
|
+
delayedInitialization(delay) {
|
|
19539
|
+
setTimeout(() => {
|
|
19392
19540
|
this.initializeTracking();
|
|
19541
|
+
}, delay);
|
|
19542
|
+
}
|
|
19543
|
+
/**
|
|
19544
|
+
* React-specific initialization timing
|
|
19545
|
+
*/
|
|
19546
|
+
reactReadyInitialization() {
|
|
19547
|
+
// Wait for React to finish rendering
|
|
19548
|
+
if (typeof window.requestAnimationFrame === 'function') {
|
|
19549
|
+
window.requestAnimationFrame(() => {
|
|
19550
|
+
setTimeout(() => {
|
|
19551
|
+
this.initializeTracking();
|
|
19552
|
+
}, 0);
|
|
19553
|
+
});
|
|
19393
19554
|
}
|
|
19555
|
+
else {
|
|
19556
|
+
setTimeout(() => {
|
|
19557
|
+
this.initializeTracking();
|
|
19558
|
+
}, 16); // ~60fps fallback
|
|
19559
|
+
}
|
|
19560
|
+
}
|
|
19561
|
+
/**
|
|
19562
|
+
* Verify initialization was successful
|
|
19563
|
+
*/
|
|
19564
|
+
verifyInitialization() {
|
|
19565
|
+
const elementsFound = this.getElementCounts();
|
|
19566
|
+
const totalElements = Object.values(elementsFound).reduce((sum, count) => sum + count, 0);
|
|
19567
|
+
const hasActiveHandlers = this.delegationHandlers.size > 0;
|
|
19568
|
+
if (this.config.debug) {
|
|
19569
|
+
console.log('[🔍 AutoTracker] Verification:', {
|
|
19570
|
+
isInitialized: this.isInitialized,
|
|
19571
|
+
elementsFound: totalElements,
|
|
19572
|
+
hasActiveHandlers,
|
|
19573
|
+
handlersActive: Array.from(this.delegationHandlers.keys())
|
|
19574
|
+
});
|
|
19575
|
+
}
|
|
19576
|
+
return this.isInitialized && (totalElements > 0 || hasActiveHandlers);
|
|
19394
19577
|
}
|
|
19395
19578
|
initializeTracking() {
|
|
19396
19579
|
if (this.config.debug) {
|
|
@@ -19450,118 +19633,271 @@ class AutoTracker {
|
|
|
19450
19633
|
*/
|
|
19451
19634
|
setupEventDelegation() {
|
|
19452
19635
|
if (this.config.debug) {
|
|
19453
|
-
console.log("[AutoTracker] Setting up event delegation...");
|
|
19636
|
+
console.log("[🚀 AutoTracker] Setting up enhanced event delegation...");
|
|
19454
19637
|
}
|
|
19455
|
-
//
|
|
19638
|
+
// Determine optimal delegation target based on React setup
|
|
19639
|
+
const delegationTarget = this.getOptimalDelegationTarget();
|
|
19640
|
+
if (this.config.debug) {
|
|
19641
|
+
console.log("[🎯 AutoTracker] Using delegation target:", delegationTarget);
|
|
19642
|
+
}
|
|
19643
|
+
// Click delegation with React compatibility
|
|
19456
19644
|
if (this.config.trackClicks) {
|
|
19457
|
-
const clickHandler = this.
|
|
19645
|
+
const clickHandler = this.createReactCompatibleClickHandler();
|
|
19458
19646
|
this.delegationHandlers.set('click', clickHandler);
|
|
19459
|
-
|
|
19647
|
+
delegationTarget.addEventListener('click', clickHandler, this.getEventOptions('click'));
|
|
19460
19648
|
}
|
|
19461
|
-
// Scroll delegation
|
|
19649
|
+
// Scroll delegation with enhanced detection
|
|
19462
19650
|
if (this.config.trackScrolls) {
|
|
19463
|
-
const scrollHandler = this.
|
|
19651
|
+
const scrollHandler = this.createEnhancedScrollHandler();
|
|
19464
19652
|
this.delegationHandlers.set('scroll', scrollHandler);
|
|
19465
|
-
document.addEventListener('scroll', scrollHandler,
|
|
19653
|
+
document.addEventListener('scroll', scrollHandler, this.getEventOptions('scroll'));
|
|
19466
19654
|
}
|
|
19467
19655
|
// Setup debounced mutation observer for dynamic content
|
|
19468
19656
|
this.setupIntelligentMutationObserver();
|
|
19469
19657
|
this.isInitialized = true;
|
|
19658
|
+
if (this.config.debug) {
|
|
19659
|
+
console.log("[✅ AutoTracker] Event delegation setup complete");
|
|
19660
|
+
}
|
|
19470
19661
|
}
|
|
19471
19662
|
/**
|
|
19472
|
-
*
|
|
19663
|
+
* Get optimal delegation target based on React setup
|
|
19473
19664
|
*/
|
|
19474
|
-
|
|
19475
|
-
|
|
19476
|
-
|
|
19477
|
-
|
|
19478
|
-
|
|
19479
|
-
|
|
19480
|
-
const trackingElement = target.closest('[data-track-click]');
|
|
19481
|
-
if (!trackingElement)
|
|
19482
|
-
return;
|
|
19483
|
-
const eventName = trackingElement.getAttribute('data-track-click');
|
|
19484
|
-
if (!eventName)
|
|
19485
|
-
return;
|
|
19486
|
-
const metadata = this.extractMetadata(trackingElement);
|
|
19487
|
-
this.trackEvent(eventName, {
|
|
19488
|
-
type: 'click',
|
|
19489
|
-
element: trackingElement.tagName.toLowerCase(),
|
|
19490
|
-
...metadata,
|
|
19491
|
-
});
|
|
19665
|
+
getOptimalDelegationTarget() {
|
|
19666
|
+
// For React 17+, prefer root container over document
|
|
19667
|
+
const reactRoot = document.querySelector('#root') ||
|
|
19668
|
+
document.querySelector('#__next') ||
|
|
19669
|
+
document.querySelector('[data-reactroot]');
|
|
19670
|
+
if (reactRoot && this.diagnostics.environment?.reactDetected) {
|
|
19492
19671
|
if (this.config.debug) {
|
|
19493
|
-
console.log(
|
|
19672
|
+
console.log("[⚛️ AutoTracker] Using React root for delegation:", reactRoot);
|
|
19673
|
+
}
|
|
19674
|
+
return reactRoot;
|
|
19675
|
+
}
|
|
19676
|
+
return document;
|
|
19677
|
+
}
|
|
19678
|
+
/**
|
|
19679
|
+
* Get optimized event options for different browsers
|
|
19680
|
+
*/
|
|
19681
|
+
getEventOptions(eventType) {
|
|
19682
|
+
this.diagnostics.environment?.isMobile;
|
|
19683
|
+
const isSafari = this.diagnostics.environment?.isSafari;
|
|
19684
|
+
let options = {};
|
|
19685
|
+
switch (eventType) {
|
|
19686
|
+
case 'click':
|
|
19687
|
+
// Safari iOS requires non-passive click events for proper delegation
|
|
19688
|
+
options = {
|
|
19689
|
+
passive: !isSafari,
|
|
19690
|
+
capture: false
|
|
19691
|
+
};
|
|
19692
|
+
break;
|
|
19693
|
+
case 'scroll':
|
|
19694
|
+
options = {
|
|
19695
|
+
passive: true,
|
|
19696
|
+
capture: false
|
|
19697
|
+
};
|
|
19698
|
+
break;
|
|
19699
|
+
default:
|
|
19700
|
+
options = { passive: true };
|
|
19701
|
+
}
|
|
19702
|
+
if (this.config.debug) {
|
|
19703
|
+
console.log(`[⚙️ AutoTracker] Event options for ${eventType}:`, options);
|
|
19704
|
+
}
|
|
19705
|
+
return options;
|
|
19706
|
+
}
|
|
19707
|
+
/**
|
|
19708
|
+
* Create React-compatible click handler
|
|
19709
|
+
*/
|
|
19710
|
+
createReactCompatibleClickHandler() {
|
|
19711
|
+
return (event) => {
|
|
19712
|
+
try {
|
|
19713
|
+
if (!this.config.trackClicks)
|
|
19714
|
+
return;
|
|
19715
|
+
// Enhanced target detection for nested React components
|
|
19716
|
+
const target = event.target;
|
|
19717
|
+
if (!target)
|
|
19718
|
+
return;
|
|
19719
|
+
// Multiple strategies to find tracking element
|
|
19720
|
+
let trackingElement = null;
|
|
19721
|
+
// Strategy 1: Direct closest (most common)
|
|
19722
|
+
trackingElement = target.closest('[data-track-click]');
|
|
19723
|
+
// Strategy 2: Check if target itself has the attribute (React edge case)
|
|
19724
|
+
if (!trackingElement && target.hasAttribute && target.hasAttribute('data-track-click')) {
|
|
19725
|
+
trackingElement = target;
|
|
19726
|
+
}
|
|
19727
|
+
// Strategy 3: Walk up DOM tree manually (React portal handling)
|
|
19728
|
+
if (!trackingElement) {
|
|
19729
|
+
trackingElement = this.findTrackingElementManually(target, 'data-track-click');
|
|
19730
|
+
}
|
|
19731
|
+
if (!trackingElement) {
|
|
19732
|
+
if (this.config.debug) {
|
|
19733
|
+
console.log('[🔍 AutoTracker] No tracking element found for click:', {
|
|
19734
|
+
target: target.tagName,
|
|
19735
|
+
hasClosest: typeof target.closest === 'function',
|
|
19736
|
+
hasAttribute: typeof target.hasAttribute === 'function'
|
|
19737
|
+
});
|
|
19738
|
+
}
|
|
19739
|
+
return;
|
|
19740
|
+
}
|
|
19741
|
+
const eventName = trackingElement.getAttribute('data-track-click');
|
|
19742
|
+
if (!eventName)
|
|
19743
|
+
return;
|
|
19744
|
+
const metadata = this.extractMetadata(trackingElement);
|
|
19745
|
+
this.trackEvent(eventName, {
|
|
19746
|
+
type: 'click',
|
|
19494
19747
|
element: trackingElement.tagName.toLowerCase(),
|
|
19495
|
-
|
|
19748
|
+
reactCompatible: true,
|
|
19749
|
+
...metadata,
|
|
19496
19750
|
});
|
|
19751
|
+
if (this.config.debug) {
|
|
19752
|
+
console.log(`[🎯 AutoTracker] Click tracked (React-compatible): ${eventName}`, {
|
|
19753
|
+
element: trackingElement.tagName.toLowerCase(),
|
|
19754
|
+
strategy: 'enhanced_delegation',
|
|
19755
|
+
...metadata
|
|
19756
|
+
});
|
|
19757
|
+
}
|
|
19758
|
+
}
|
|
19759
|
+
catch (error) {
|
|
19760
|
+
if (this.config.debug) {
|
|
19761
|
+
console.error('[❌ AutoTracker] Click handler error:', error);
|
|
19762
|
+
}
|
|
19497
19763
|
}
|
|
19498
19764
|
};
|
|
19499
19765
|
}
|
|
19500
19766
|
/**
|
|
19501
|
-
*
|
|
19767
|
+
* Manually walk up DOM tree to find tracking element
|
|
19502
19768
|
*/
|
|
19503
|
-
|
|
19769
|
+
findTrackingElementManually(element, attribute, maxDepth = 10) {
|
|
19770
|
+
let current = element;
|
|
19771
|
+
let depth = 0;
|
|
19772
|
+
while (current && current !== document.documentElement && depth < maxDepth) {
|
|
19773
|
+
if (current.hasAttribute && current.hasAttribute(attribute)) {
|
|
19774
|
+
return current;
|
|
19775
|
+
}
|
|
19776
|
+
current = current.parentElement;
|
|
19777
|
+
depth++;
|
|
19778
|
+
}
|
|
19779
|
+
return null;
|
|
19780
|
+
}
|
|
19781
|
+
/**
|
|
19782
|
+
* Create enhanced scroll handler with better performance
|
|
19783
|
+
*/
|
|
19784
|
+
createEnhancedScrollHandler() {
|
|
19504
19785
|
return () => {
|
|
19505
|
-
|
|
19506
|
-
|
|
19507
|
-
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
|
|
19512
|
-
|
|
19513
|
-
|
|
19514
|
-
|
|
19515
|
-
|
|
19786
|
+
try {
|
|
19787
|
+
if (!this.config.trackScrolls)
|
|
19788
|
+
return;
|
|
19789
|
+
// Adaptive throttling based on scroll frequency
|
|
19790
|
+
const now = Date.now();
|
|
19791
|
+
const timeDelta = now - this.scrollThrottle;
|
|
19792
|
+
const throttleDelay = this.diagnostics.environment?.isMobile ? 150 : 100;
|
|
19793
|
+
if (timeDelta < throttleDelay)
|
|
19794
|
+
return;
|
|
19795
|
+
this.scrollThrottle = now;
|
|
19796
|
+
// Enhanced element finding with caching
|
|
19797
|
+
const scrollElements = this.getCachedScrollElements();
|
|
19798
|
+
if (this.config.debug && scrollElements.length > 0) {
|
|
19799
|
+
console.log(`[📜 AutoTracker] Processing ${scrollElements.length} scroll elements`, {
|
|
19800
|
+
throttleDelay,
|
|
19801
|
+
timeDelta,
|
|
19802
|
+
scrollY: window.scrollY
|
|
19803
|
+
});
|
|
19804
|
+
}
|
|
19805
|
+
// Process elements with enhanced visibility detection
|
|
19806
|
+
scrollElements.forEach((element) => {
|
|
19807
|
+
this.processScrollElementEnhanced(element);
|
|
19808
|
+
});
|
|
19809
|
+
}
|
|
19810
|
+
catch (error) {
|
|
19811
|
+
if (this.config.debug) {
|
|
19812
|
+
console.error('[❌ AutoTracker] Scroll handler error:', error);
|
|
19813
|
+
}
|
|
19516
19814
|
}
|
|
19517
|
-
scrollElements.forEach((element) => {
|
|
19518
|
-
this.processScrollElement(element);
|
|
19519
|
-
});
|
|
19520
19815
|
};
|
|
19521
19816
|
}
|
|
19817
|
+
getCachedScrollElements() {
|
|
19818
|
+
const now = Date.now();
|
|
19819
|
+
const cacheExpiry = 5000; // 5 seconds
|
|
19820
|
+
if (!this.cachedScrollElements || (now - this.lastScrollElementsCheck) > cacheExpiry) {
|
|
19821
|
+
this.cachedScrollElements = document.querySelectorAll('[data-track-scroll]');
|
|
19822
|
+
this.lastScrollElementsCheck = now;
|
|
19823
|
+
if (this.config.debug) {
|
|
19824
|
+
console.log(`[🔄 AutoTracker] Refreshed scroll elements cache: ${this.cachedScrollElements.length} elements`);
|
|
19825
|
+
}
|
|
19826
|
+
}
|
|
19827
|
+
return this.cachedScrollElements;
|
|
19828
|
+
}
|
|
19522
19829
|
/**
|
|
19523
|
-
* Process
|
|
19830
|
+
* Process scroll element with enhanced detection
|
|
19524
19831
|
*/
|
|
19525
|
-
|
|
19526
|
-
|
|
19527
|
-
|
|
19528
|
-
|
|
19529
|
-
const threshold = parseFloat(element.getAttribute('data-scroll-threshold') || '0.5');
|
|
19530
|
-
const rect = element.getBoundingClientRect();
|
|
19531
|
-
const elementHeight = rect.height;
|
|
19532
|
-
const visibleHeight = Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0);
|
|
19533
|
-
const visibilityRatio = Math.max(0, visibleHeight) / elementHeight;
|
|
19534
|
-
if (this.config.debug) {
|
|
19535
|
-
console.log(`[AutoTracker] Scroll element check via delegation:`, {
|
|
19536
|
-
elementId: element.id || element.className,
|
|
19537
|
-
visibilityRatio: Math.round(visibilityRatio * 100) / 100,
|
|
19538
|
-
threshold,
|
|
19539
|
-
triggered: hasTriggered
|
|
19540
|
-
});
|
|
19541
|
-
}
|
|
19542
|
-
if (visibilityRatio >= threshold) {
|
|
19543
|
-
element.setAttribute('data-scroll-triggered', 'true');
|
|
19544
|
-
const eventName = element.getAttribute('data-track-scroll');
|
|
19545
|
-
if (!eventName)
|
|
19832
|
+
processScrollElementEnhanced(element) {
|
|
19833
|
+
try {
|
|
19834
|
+
const hasTriggered = element.getAttribute('data-scroll-triggered') === 'true';
|
|
19835
|
+
if (hasTriggered)
|
|
19546
19836
|
return;
|
|
19547
|
-
const
|
|
19548
|
-
|
|
19549
|
-
|
|
19550
|
-
|
|
19551
|
-
|
|
19552
|
-
|
|
19553
|
-
|
|
19554
|
-
|
|
19555
|
-
|
|
19837
|
+
const threshold = parseFloat(element.getAttribute('data-scroll-threshold') || '0.5');
|
|
19838
|
+
// Enhanced visibility calculation
|
|
19839
|
+
const rect = element.getBoundingClientRect();
|
|
19840
|
+
const elementHeight = rect.height;
|
|
19841
|
+
const windowHeight = window.innerHeight;
|
|
19842
|
+
// Handle edge cases
|
|
19843
|
+
if (elementHeight <= 0)
|
|
19844
|
+
return;
|
|
19845
|
+
const visibleTop = Math.max(rect.top, 0);
|
|
19846
|
+
const visibleBottom = Math.min(rect.bottom, windowHeight);
|
|
19847
|
+
const visibleHeight = Math.max(0, visibleBottom - visibleTop);
|
|
19848
|
+
const visibilityRatio = visibleHeight / elementHeight;
|
|
19556
19849
|
if (this.config.debug) {
|
|
19557
|
-
console.log(`[AutoTracker]
|
|
19850
|
+
console.log(`[📊 AutoTracker] Enhanced scroll check:`, {
|
|
19851
|
+
elementId: element.id || element.className || 'no-id',
|
|
19852
|
+
rect: {
|
|
19853
|
+
top: Math.round(rect.top),
|
|
19854
|
+
bottom: Math.round(rect.bottom),
|
|
19855
|
+
height: Math.round(elementHeight)
|
|
19856
|
+
},
|
|
19857
|
+
visibility: {
|
|
19858
|
+
ratio: Math.round(visibilityRatio * 1000) / 1000,
|
|
19859
|
+
threshold,
|
|
19860
|
+
triggered: hasTriggered
|
|
19861
|
+
},
|
|
19862
|
+
scroll: window.scrollY
|
|
19863
|
+
});
|
|
19864
|
+
}
|
|
19865
|
+
if (visibilityRatio >= threshold) {
|
|
19866
|
+
element.setAttribute('data-scroll-triggered', 'true');
|
|
19867
|
+
const eventName = element.getAttribute('data-track-scroll');
|
|
19868
|
+
if (!eventName)
|
|
19869
|
+
return;
|
|
19870
|
+
const metadata = this.extractMetadata(element);
|
|
19871
|
+
this.trackEvent(eventName, {
|
|
19872
|
+
type: 'scroll',
|
|
19873
|
+
element: element.tagName.toLowerCase(),
|
|
19558
19874
|
threshold,
|
|
19559
|
-
visibilityRatio,
|
|
19560
19875
|
scrollDepth: window.scrollY,
|
|
19561
|
-
|
|
19876
|
+
visibilityRatio: Math.round(visibilityRatio * 1000) / 1000,
|
|
19877
|
+
enhanced: true,
|
|
19878
|
+
...metadata,
|
|
19562
19879
|
});
|
|
19880
|
+
if (this.config.debug) {
|
|
19881
|
+
console.log(`[🎯 AutoTracker] Scroll tracked (enhanced): ${eventName}`, {
|
|
19882
|
+
threshold,
|
|
19883
|
+
visibilityRatio: Math.round(visibilityRatio * 1000) / 1000,
|
|
19884
|
+
scrollDepth: window.scrollY,
|
|
19885
|
+
...metadata
|
|
19886
|
+
});
|
|
19887
|
+
}
|
|
19563
19888
|
}
|
|
19564
19889
|
}
|
|
19890
|
+
catch (error) {
|
|
19891
|
+
if (this.config.debug) {
|
|
19892
|
+
console.error('[❌ AutoTracker] Scroll element processing error:', error);
|
|
19893
|
+
}
|
|
19894
|
+
}
|
|
19895
|
+
}
|
|
19896
|
+
/**
|
|
19897
|
+
* Legacy method for compatibility
|
|
19898
|
+
*/
|
|
19899
|
+
processScrollElement(element) {
|
|
19900
|
+
this.processScrollElementEnhanced(element);
|
|
19565
19901
|
}
|
|
19566
19902
|
/**
|
|
19567
19903
|
* Setup intelligent mutation observer (debounced for performance)
|
|
@@ -19853,43 +20189,88 @@ class AutoTracker {
|
|
|
19853
20189
|
/**
|
|
19854
20190
|
* Enviar evento para o SDK
|
|
19855
20191
|
*/
|
|
20192
|
+
/**
|
|
20193
|
+
* Enhanced event tracking with comprehensive debugging
|
|
20194
|
+
*/
|
|
19856
20195
|
trackEvent(eventName, metadata) {
|
|
20196
|
+
const trackingStart = performance.now();
|
|
19857
20197
|
if (this.config.debug) {
|
|
19858
|
-
console.log("[AutoTracker] trackEvent called:", {
|
|
19859
|
-
|
|
19860
|
-
|
|
19861
|
-
|
|
19862
|
-
|
|
19863
|
-
}
|
|
19864
|
-
return;
|
|
20198
|
+
console.log("[🚀 AutoTracker] Enhanced trackEvent called:", {
|
|
20199
|
+
eventName,
|
|
20200
|
+
metadata,
|
|
20201
|
+
timestamp: new Date().toISOString()
|
|
20202
|
+
});
|
|
19865
20203
|
}
|
|
19866
|
-
|
|
20204
|
+
// Comprehensive validation
|
|
20205
|
+
const validation = this.validateTrackingCall(eventName, metadata);
|
|
20206
|
+
if (!validation.isValid) {
|
|
19867
20207
|
if (this.config.debug) {
|
|
19868
|
-
console.error("[AutoTracker]
|
|
20208
|
+
console.error("[❌ AutoTracker] Validation failed:", validation.errors);
|
|
19869
20209
|
}
|
|
19870
20210
|
return;
|
|
19871
20211
|
}
|
|
19872
20212
|
try {
|
|
19873
20213
|
const eventData = {
|
|
20214
|
+
// Core tracking data
|
|
19874
20215
|
autoTracked: true,
|
|
20216
|
+
enhanced: true,
|
|
19875
20217
|
timestamp: Date.now(),
|
|
19876
20218
|
url: window.location.href,
|
|
20219
|
+
userAgent: navigator.userAgent,
|
|
20220
|
+
// Performance data
|
|
20221
|
+
trackingLatency: Math.round((performance.now() - trackingStart) * 100) / 100,
|
|
20222
|
+
// Environment data
|
|
20223
|
+
isReactApp: this.diagnostics.environment?.reactDetected,
|
|
20224
|
+
isMobile: this.diagnostics.environment?.isMobile,
|
|
20225
|
+
// Event metadata
|
|
19877
20226
|
...metadata,
|
|
19878
20227
|
};
|
|
19879
20228
|
if (this.config.debug) {
|
|
19880
|
-
console.log("[AutoTracker]
|
|
20229
|
+
console.log("[📡 AutoTracker] Sending enhanced event:", { eventName, eventData });
|
|
19881
20230
|
}
|
|
19882
20231
|
const result = this.sdkInstance.trackCustomEvent(eventName, eventData);
|
|
19883
20232
|
if (this.config.debug) {
|
|
19884
|
-
|
|
20233
|
+
const trackingEnd = performance.now();
|
|
20234
|
+
console.log("[✅ AutoTracker] Event sent successfully:", {
|
|
20235
|
+
eventName,
|
|
20236
|
+
result,
|
|
20237
|
+
totalLatency: Math.round((trackingEnd - trackingStart) * 100) / 100 + 'ms'
|
|
20238
|
+
});
|
|
19885
20239
|
}
|
|
19886
20240
|
}
|
|
19887
20241
|
catch (error) {
|
|
19888
20242
|
if (this.config.debug) {
|
|
19889
|
-
console.error("[AutoTracker]
|
|
20243
|
+
console.error("[💥 AutoTracker] Critical tracking error:", {
|
|
20244
|
+
eventName,
|
|
20245
|
+
error: error instanceof Error ? error.message : error,
|
|
20246
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
20247
|
+
metadata
|
|
20248
|
+
});
|
|
19890
20249
|
}
|
|
19891
20250
|
}
|
|
19892
20251
|
}
|
|
20252
|
+
/**
|
|
20253
|
+
* Validate tracking call before sending
|
|
20254
|
+
*/
|
|
20255
|
+
validateTrackingCall(eventName, metadata) {
|
|
20256
|
+
const errors = [];
|
|
20257
|
+
if (!eventName || typeof eventName !== 'string') {
|
|
20258
|
+
errors.push('Event name is required and must be a string');
|
|
20259
|
+
}
|
|
20260
|
+
if (!this.sdkInstance) {
|
|
20261
|
+
errors.push('SDK instance is null or undefined');
|
|
20262
|
+
}
|
|
20263
|
+
if (this.sdkInstance && typeof this.sdkInstance.trackCustomEvent !== 'function') {
|
|
20264
|
+
errors.push(`trackCustomEvent is not a function: ${typeof this.sdkInstance.trackCustomEvent}`);
|
|
20265
|
+
}
|
|
20266
|
+
if (!window || typeof window !== 'object') {
|
|
20267
|
+
errors.push('Window object is not available');
|
|
20268
|
+
}
|
|
20269
|
+
return {
|
|
20270
|
+
isValid: errors.length === 0,
|
|
20271
|
+
errors
|
|
20272
|
+
};
|
|
20273
|
+
}
|
|
19893
20274
|
/**
|
|
19894
20275
|
* Modern API: Refresh tracking for dynamic content (React/SPA support)
|
|
19895
20276
|
* Industry best practice for SPA route changes
|
|
@@ -19919,26 +20300,83 @@ class AutoTracker {
|
|
|
19919
20300
|
this.refreshTracking();
|
|
19920
20301
|
}
|
|
19921
20302
|
/**
|
|
19922
|
-
* Get diagnostic information for debugging
|
|
20303
|
+
* Get comprehensive diagnostic information for debugging
|
|
19923
20304
|
*/
|
|
19924
20305
|
getDiagnostics() {
|
|
19925
20306
|
return {
|
|
19926
|
-
|
|
19927
|
-
|
|
19928
|
-
|
|
19929
|
-
|
|
19930
|
-
|
|
19931
|
-
|
|
20307
|
+
// Initialization status
|
|
20308
|
+
initialization: {
|
|
20309
|
+
isInitialized: this.isInitialized,
|
|
20310
|
+
attempts: this.initializationAttempts,
|
|
20311
|
+
maxAttempts: this.maxInitializationAttempts,
|
|
20312
|
+
timestamp: new Date().toISOString()
|
|
20313
|
+
},
|
|
20314
|
+
// Event handlers status
|
|
20315
|
+
eventHandlers: {
|
|
20316
|
+
hasClickHandler: this.delegationHandlers.has('click'),
|
|
20317
|
+
hasScrollHandler: this.delegationHandlers.has('scroll'),
|
|
20318
|
+
activeHandlers: Array.from(this.delegationHandlers.keys()),
|
|
20319
|
+
delegationTarget: this.getOptimalDelegationTarget() === document ? 'document' : 'react-root'
|
|
20320
|
+
},
|
|
20321
|
+
// Observers status
|
|
20322
|
+
observers: {
|
|
20323
|
+
observedElements: this.observedElements.size,
|
|
20324
|
+
hasMutationObserver: !!this.mutationObserver,
|
|
20325
|
+
hasIntersectionObserver: !!this.intersectionObserver,
|
|
20326
|
+
scrollElementsCache: !!this.cachedScrollElements,
|
|
20327
|
+
cacheExpiry: new Date(this.lastScrollElementsCheck + 5000).toISOString()
|
|
20328
|
+
},
|
|
20329
|
+
// Configuration
|
|
19932
20330
|
config: this.config,
|
|
19933
|
-
|
|
19934
|
-
|
|
19935
|
-
|
|
19936
|
-
|
|
19937
|
-
|
|
19938
|
-
|
|
19939
|
-
|
|
20331
|
+
// Current environment diagnostics
|
|
20332
|
+
environment: this.diagnostics.environment || {},
|
|
20333
|
+
// DOM state
|
|
20334
|
+
dom: this.diagnostics.dom || {},
|
|
20335
|
+
// SDK state
|
|
20336
|
+
tracking: this.diagnostics.tracking || {},
|
|
20337
|
+
// Real-time element detection
|
|
20338
|
+
elementsFound: this.getElementCounts(),
|
|
20339
|
+
// Performance metrics
|
|
20340
|
+
performance: {
|
|
20341
|
+
lastScrollThrottle: this.scrollThrottle,
|
|
20342
|
+
cacheLastUpdate: this.lastScrollElementsCheck
|
|
20343
|
+
},
|
|
20344
|
+
// Validation status
|
|
20345
|
+
validation: this.validateTrackingCall('test', {}),
|
|
20346
|
+
// Debug recommendations
|
|
20347
|
+
recommendations: this.generateRecommendations()
|
|
19940
20348
|
};
|
|
19941
20349
|
}
|
|
20350
|
+
/**
|
|
20351
|
+
* Generate diagnostic recommendations
|
|
20352
|
+
*/
|
|
20353
|
+
generateRecommendations() {
|
|
20354
|
+
const recommendations = [];
|
|
20355
|
+
const elementsFound = this.getElementCounts();
|
|
20356
|
+
const totalElements = Object.values(elementsFound).reduce((sum, count) => sum + count, 0);
|
|
20357
|
+
if (!this.isInitialized) {
|
|
20358
|
+
recommendations.push('AutoTracker is not initialized. Check console for errors.');
|
|
20359
|
+
}
|
|
20360
|
+
if (totalElements === 0) {
|
|
20361
|
+
recommendations.push('No trackable elements found. Ensure data-track-* attributes are present in the DOM.');
|
|
20362
|
+
}
|
|
20363
|
+
if (!this.sdkInstance) {
|
|
20364
|
+
recommendations.push('SDK instance is missing. Ensure the SDK is properly initialized.');
|
|
20365
|
+
}
|
|
20366
|
+
if (this.sdkInstance && typeof this.sdkInstance.trackCustomEvent !== 'function') {
|
|
20367
|
+
recommendations.push('trackCustomEvent method is not available on SDK instance.');
|
|
20368
|
+
}
|
|
20369
|
+
if (!this.diagnostics.environment?.reactDetected && window.location.hostname.includes('localhost')) {
|
|
20370
|
+
recommendations.push('React not detected. If using React, ensure proper setup and try refreshTracking() after route changes.');
|
|
20371
|
+
}
|
|
20372
|
+
if (this.diagnostics.environment?.isMobile && !this.delegationHandlers.has('scroll')) {
|
|
20373
|
+
recommendations.push('Mobile device detected but scroll tracking not active. Check scroll tracking configuration.');
|
|
20374
|
+
}
|
|
20375
|
+
if (this.initializationAttempts > 1) {
|
|
20376
|
+
recommendations.push(`AutoTracker required ${this.initializationAttempts} initialization attempts. Consider adding delay before enabling.`);
|
|
20377
|
+
}
|
|
20378
|
+
return recommendations;
|
|
20379
|
+
}
|
|
19942
20380
|
/**
|
|
19943
20381
|
* Configurar tracking
|
|
19944
20382
|
*/
|