@zaplier/sdk 1.6.8 → 1.7.0
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 +404 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +18 -0
- package/dist/index.esm.js +404 -84
- package/dist/index.esm.js.map +1 -1
- package/dist/sdk.js +404 -84
- package/dist/sdk.js.map +1 -1
- package/dist/sdk.min.js +1 -1
- package/dist/src/modules/auto-tracker.d.ts +59 -11
- package/dist/src/modules/auto-tracker.d.ts.map +1 -1
- package/dist/src/modules/global-interface.d.ts +2 -0
- package/dist/src/modules/global-interface.d.ts.map +1 -1
- package/dist/src/sdk.d.ts +16 -0
- package/dist/src/sdk.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/sdk.js
CHANGED
|
@@ -19268,6 +19268,8 @@
|
|
|
19268
19268
|
constructor(sdkInstance, config = {}) {
|
|
19269
19269
|
this.observedElements = new Set();
|
|
19270
19270
|
this.scrollThrottle = 0;
|
|
19271
|
+
this.isInitialized = false;
|
|
19272
|
+
this.delegationHandlers = new Map();
|
|
19271
19273
|
this.handleScroll = () => {
|
|
19272
19274
|
if (!this.config.trackScrolls)
|
|
19273
19275
|
return;
|
|
@@ -19278,7 +19280,10 @@
|
|
|
19278
19280
|
this.scrollThrottle = now;
|
|
19279
19281
|
const scrollElements = document.querySelectorAll('[data-track-scroll]');
|
|
19280
19282
|
if (this.config.debug && scrollElements.length > 0) {
|
|
19281
|
-
console.log(`[AutoTracker] Checking ${scrollElements.length} scroll elements
|
|
19283
|
+
console.log(`[AutoTracker] Checking ${scrollElements.length} scroll elements`, {
|
|
19284
|
+
scrollY: window.scrollY,
|
|
19285
|
+
innerHeight: window.innerHeight
|
|
19286
|
+
});
|
|
19282
19287
|
}
|
|
19283
19288
|
scrollElements.forEach((element) => {
|
|
19284
19289
|
let hasTriggered = element.getAttribute('data-scroll-triggered') === 'true';
|
|
@@ -19322,6 +19327,28 @@
|
|
|
19322
19327
|
}
|
|
19323
19328
|
});
|
|
19324
19329
|
};
|
|
19330
|
+
this.handleClick = (event) => {
|
|
19331
|
+
if (!this.config.trackClicks)
|
|
19332
|
+
return;
|
|
19333
|
+
const target = event.target;
|
|
19334
|
+
if (!target || !target.hasAttribute("data-track-click"))
|
|
19335
|
+
return;
|
|
19336
|
+
const eventName = target.getAttribute("data-track-click");
|
|
19337
|
+
if (!eventName)
|
|
19338
|
+
return;
|
|
19339
|
+
const metadata = this.extractMetadata(target);
|
|
19340
|
+
this.trackEvent(eventName, {
|
|
19341
|
+
type: "click",
|
|
19342
|
+
element: target.tagName.toLowerCase(),
|
|
19343
|
+
...metadata,
|
|
19344
|
+
});
|
|
19345
|
+
if (this.config.debug) {
|
|
19346
|
+
console.log(`[AutoTracker] Click tracked: ${eventName}`, {
|
|
19347
|
+
element: target.tagName.toLowerCase(),
|
|
19348
|
+
...metadata
|
|
19349
|
+
});
|
|
19350
|
+
}
|
|
19351
|
+
};
|
|
19325
19352
|
this.sdkInstance = sdkInstance;
|
|
19326
19353
|
this.config = {
|
|
19327
19354
|
enabled: true,
|
|
@@ -19347,9 +19374,30 @@
|
|
|
19347
19374
|
trackScrolls: this.config.trackScrolls,
|
|
19348
19375
|
trackViews: this.config.trackViews,
|
|
19349
19376
|
trackHovers: this.config.trackHovers,
|
|
19350
|
-
trackForms: this.config.trackForms
|
|
19377
|
+
trackForms: this.config.trackForms,
|
|
19378
|
+
domReady: document.readyState
|
|
19351
19379
|
});
|
|
19352
19380
|
}
|
|
19381
|
+
// Aguardar DOM ready se necessário
|
|
19382
|
+
if (document.readyState === 'loading') {
|
|
19383
|
+
if (this.config.debug) {
|
|
19384
|
+
console.log("[Zaplier AutoTracker] DOM still loading, waiting for DOMContentLoaded...");
|
|
19385
|
+
}
|
|
19386
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
19387
|
+
if (this.config.debug) {
|
|
19388
|
+
console.log("[Zaplier AutoTracker] DOMContentLoaded fired, initializing tracking...");
|
|
19389
|
+
}
|
|
19390
|
+
this.initializeTracking();
|
|
19391
|
+
}, { once: true });
|
|
19392
|
+
}
|
|
19393
|
+
else {
|
|
19394
|
+
this.initializeTracking();
|
|
19395
|
+
}
|
|
19396
|
+
}
|
|
19397
|
+
initializeTracking() {
|
|
19398
|
+
if (this.config.debug) {
|
|
19399
|
+
console.log("[Zaplier AutoTracker] Initializing tracking...");
|
|
19400
|
+
}
|
|
19353
19401
|
// Observer para novos elementos no DOM
|
|
19354
19402
|
this.observeDOM();
|
|
19355
19403
|
// Processar elementos já existentes
|
|
@@ -19358,38 +19406,269 @@
|
|
|
19358
19406
|
if (this.config.trackViews) {
|
|
19359
19407
|
this.setupViewTracking();
|
|
19360
19408
|
}
|
|
19361
|
-
// Setup
|
|
19409
|
+
// Setup event delegation (modern approach)
|
|
19410
|
+
this.setupEventDelegation();
|
|
19411
|
+
// Debug: Log elementos encontrados após inicialização
|
|
19412
|
+
if (this.config.debug) {
|
|
19413
|
+
this.logFoundElements();
|
|
19414
|
+
// Também agendar uma verificação após delay para elementos React
|
|
19415
|
+
setTimeout(() => {
|
|
19416
|
+
console.log("[Zaplier AutoTracker] Re-checking elements after 500ms...");
|
|
19417
|
+
this.logFoundElements();
|
|
19418
|
+
}, 500);
|
|
19419
|
+
setTimeout(() => {
|
|
19420
|
+
console.log("[Zaplier AutoTracker] Re-checking elements after 2s...");
|
|
19421
|
+
this.logFoundElements();
|
|
19422
|
+
}, 2000);
|
|
19423
|
+
}
|
|
19424
|
+
}
|
|
19425
|
+
logFoundElements() {
|
|
19426
|
+
const clickElements = document.querySelectorAll('[data-track-click]');
|
|
19427
|
+
const scrollElements = document.querySelectorAll('[data-track-scroll]');
|
|
19428
|
+
const viewElements = document.querySelectorAll('[data-track-view]');
|
|
19429
|
+
const hoverElements = document.querySelectorAll('[data-track-hover]');
|
|
19430
|
+
const formElements = document.querySelectorAll('[data-track-form]');
|
|
19431
|
+
console.log("[Zaplier AutoTracker] Elementos encontrados:", {
|
|
19432
|
+
clickElements: clickElements.length,
|
|
19433
|
+
scrollElements: scrollElements.length,
|
|
19434
|
+
viewElements: viewElements.length,
|
|
19435
|
+
hoverElements: hoverElements.length,
|
|
19436
|
+
formElements: formElements.length,
|
|
19437
|
+
totalElements: clickElements.length + scrollElements.length + viewElements.length + hoverElements.length + formElements.length
|
|
19438
|
+
});
|
|
19439
|
+
if (scrollElements.length > 0) {
|
|
19440
|
+
console.log("[Zaplier AutoTracker] Elementos de scroll:", Array.from(scrollElements).map(el => ({
|
|
19441
|
+
tagName: el.tagName,
|
|
19442
|
+
trackEvent: el.getAttribute('data-track-scroll'),
|
|
19443
|
+
threshold: el.getAttribute('data-scroll-threshold') || '0.5',
|
|
19444
|
+
id: el.id || 'no-id',
|
|
19445
|
+
classes: el.className || 'no-classes'
|
|
19446
|
+
})));
|
|
19447
|
+
}
|
|
19448
|
+
}
|
|
19449
|
+
/**
|
|
19450
|
+
* Setup Event Delegation (Industry Best Practice)
|
|
19451
|
+
* Uses single document-level listeners instead of individual element listeners
|
|
19452
|
+
*/
|
|
19453
|
+
setupEventDelegation() {
|
|
19454
|
+
if (this.config.debug) {
|
|
19455
|
+
console.log("[AutoTracker] Setting up event delegation...");
|
|
19456
|
+
}
|
|
19457
|
+
// Click delegation
|
|
19458
|
+
if (this.config.trackClicks) {
|
|
19459
|
+
const clickHandler = this.createDelegatedClickHandler();
|
|
19460
|
+
this.delegationHandlers.set('click', clickHandler);
|
|
19461
|
+
document.addEventListener('click', clickHandler, { passive: true });
|
|
19462
|
+
}
|
|
19463
|
+
// Scroll delegation (using global handler with element detection)
|
|
19362
19464
|
if (this.config.trackScrolls) {
|
|
19363
|
-
|
|
19465
|
+
const scrollHandler = this.createDelegatedScrollHandler();
|
|
19466
|
+
this.delegationHandlers.set('scroll', scrollHandler);
|
|
19467
|
+
document.addEventListener('scroll', scrollHandler, { passive: true });
|
|
19364
19468
|
}
|
|
19469
|
+
// Setup debounced mutation observer for dynamic content
|
|
19470
|
+
this.setupIntelligentMutationObserver();
|
|
19471
|
+
this.isInitialized = true;
|
|
19365
19472
|
}
|
|
19366
19473
|
/**
|
|
19367
|
-
*
|
|
19474
|
+
* Create delegated click handler (no individual listeners needed)
|
|
19368
19475
|
*/
|
|
19369
|
-
|
|
19370
|
-
|
|
19371
|
-
|
|
19372
|
-
this.
|
|
19476
|
+
createDelegatedClickHandler() {
|
|
19477
|
+
return (event) => {
|
|
19478
|
+
const target = event.target;
|
|
19479
|
+
if (!target || !this.config.trackClicks)
|
|
19480
|
+
return;
|
|
19481
|
+
// Check if target or any parent has data-track-click
|
|
19482
|
+
const trackingElement = target.closest('[data-track-click]');
|
|
19483
|
+
if (!trackingElement)
|
|
19484
|
+
return;
|
|
19485
|
+
const eventName = trackingElement.getAttribute('data-track-click');
|
|
19486
|
+
if (!eventName)
|
|
19487
|
+
return;
|
|
19488
|
+
const metadata = this.extractMetadata(trackingElement);
|
|
19489
|
+
this.trackEvent(eventName, {
|
|
19490
|
+
type: 'click',
|
|
19491
|
+
element: trackingElement.tagName.toLowerCase(),
|
|
19492
|
+
...metadata,
|
|
19493
|
+
});
|
|
19494
|
+
if (this.config.debug) {
|
|
19495
|
+
console.log(`[AutoTracker] Click tracked via delegation: ${eventName}`, {
|
|
19496
|
+
element: trackingElement.tagName.toLowerCase(),
|
|
19497
|
+
...metadata
|
|
19498
|
+
});
|
|
19499
|
+
}
|
|
19500
|
+
};
|
|
19501
|
+
}
|
|
19502
|
+
/**
|
|
19503
|
+
* Create delegated scroll handler (efficient global approach)
|
|
19504
|
+
*/
|
|
19505
|
+
createDelegatedScrollHandler() {
|
|
19506
|
+
return () => {
|
|
19507
|
+
if (!this.config.trackScrolls)
|
|
19508
|
+
return;
|
|
19509
|
+
// Throttle scroll events for performance
|
|
19510
|
+
const now = Date.now();
|
|
19511
|
+
if (now - this.scrollThrottle < 100)
|
|
19512
|
+
return;
|
|
19513
|
+
this.scrollThrottle = now;
|
|
19514
|
+
// Find all scroll tracking elements and check visibility
|
|
19515
|
+
const scrollElements = document.querySelectorAll('[data-track-scroll]');
|
|
19516
|
+
if (this.config.debug && scrollElements.length > 0) {
|
|
19517
|
+
console.log(`[AutoTracker] Checking ${scrollElements.length} scroll elements via delegation`);
|
|
19518
|
+
}
|
|
19519
|
+
scrollElements.forEach((element) => {
|
|
19520
|
+
this.processScrollElement(element);
|
|
19521
|
+
});
|
|
19522
|
+
};
|
|
19523
|
+
}
|
|
19524
|
+
/**
|
|
19525
|
+
* Process individual scroll element (extracted for reusability)
|
|
19526
|
+
*/
|
|
19527
|
+
processScrollElement(element) {
|
|
19528
|
+
const hasTriggered = element.getAttribute('data-scroll-triggered') === 'true';
|
|
19529
|
+
if (hasTriggered)
|
|
19530
|
+
return;
|
|
19531
|
+
const threshold = parseFloat(element.getAttribute('data-scroll-threshold') || '0.5');
|
|
19532
|
+
const rect = element.getBoundingClientRect();
|
|
19533
|
+
const elementHeight = rect.height;
|
|
19534
|
+
const visibleHeight = Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0);
|
|
19535
|
+
const visibilityRatio = Math.max(0, visibleHeight) / elementHeight;
|
|
19536
|
+
if (this.config.debug) {
|
|
19537
|
+
console.log(`[AutoTracker] Scroll element check via delegation:`, {
|
|
19538
|
+
elementId: element.id || element.className,
|
|
19539
|
+
visibilityRatio: Math.round(visibilityRatio * 100) / 100,
|
|
19540
|
+
threshold,
|
|
19541
|
+
triggered: hasTriggered
|
|
19542
|
+
});
|
|
19543
|
+
}
|
|
19544
|
+
if (visibilityRatio >= threshold) {
|
|
19545
|
+
element.setAttribute('data-scroll-triggered', 'true');
|
|
19546
|
+
const eventName = element.getAttribute('data-track-scroll');
|
|
19547
|
+
if (!eventName)
|
|
19548
|
+
return;
|
|
19549
|
+
const metadata = this.extractMetadata(element);
|
|
19550
|
+
this.trackEvent(eventName, {
|
|
19551
|
+
type: 'scroll',
|
|
19552
|
+
element: element.tagName.toLowerCase(),
|
|
19553
|
+
threshold,
|
|
19554
|
+
scrollDepth: window.scrollY,
|
|
19555
|
+
visibilityRatio: Math.round(visibilityRatio * 100) / 100,
|
|
19556
|
+
...metadata,
|
|
19557
|
+
});
|
|
19558
|
+
if (this.config.debug) {
|
|
19559
|
+
console.log(`[AutoTracker] Scroll tracked via delegation: ${eventName}`, {
|
|
19560
|
+
threshold,
|
|
19561
|
+
visibilityRatio,
|
|
19562
|
+
scrollDepth: window.scrollY,
|
|
19563
|
+
...metadata
|
|
19564
|
+
});
|
|
19565
|
+
}
|
|
19373
19566
|
}
|
|
19374
|
-
this.observedElements.clear();
|
|
19375
19567
|
}
|
|
19376
19568
|
/**
|
|
19377
|
-
*
|
|
19569
|
+
* Setup intelligent mutation observer (debounced for performance)
|
|
19378
19570
|
*/
|
|
19379
|
-
|
|
19380
|
-
|
|
19381
|
-
|
|
19382
|
-
|
|
19571
|
+
setupIntelligentMutationObserver() {
|
|
19572
|
+
if (this.mutationObserver)
|
|
19573
|
+
return; // Already setup
|
|
19574
|
+
const debouncedCallback = this.debounce((mutations) => {
|
|
19575
|
+
let hasRelevantChanges = false;
|
|
19576
|
+
mutations.forEach(mutation => {
|
|
19577
|
+
mutation.addedNodes.forEach(node => {
|
|
19383
19578
|
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
19384
|
-
|
|
19579
|
+
const element = node;
|
|
19580
|
+
if (this.hasTrackingAttributes(element) || this.hasTrackingDescendants(element)) {
|
|
19581
|
+
hasRelevantChanges = true;
|
|
19582
|
+
if (this.config.debug) {
|
|
19583
|
+
console.log('[AutoTracker] New trackable element detected via mutation observer:', element);
|
|
19584
|
+
}
|
|
19585
|
+
}
|
|
19385
19586
|
}
|
|
19386
19587
|
});
|
|
19387
19588
|
});
|
|
19388
|
-
|
|
19389
|
-
|
|
19589
|
+
if (hasRelevantChanges) {
|
|
19590
|
+
if (this.config.debug) {
|
|
19591
|
+
console.log('[AutoTracker] Processing new elements from mutations...');
|
|
19592
|
+
}
|
|
19593
|
+
// Process elements for view tracking (only thing that needs setup)
|
|
19594
|
+
this.processExistingElements();
|
|
19595
|
+
}
|
|
19596
|
+
}, 150);
|
|
19597
|
+
this.mutationObserver = new MutationObserver(debouncedCallback);
|
|
19598
|
+
this.mutationObserver.observe(document.body, {
|
|
19390
19599
|
childList: true,
|
|
19391
19600
|
subtree: true,
|
|
19392
19601
|
});
|
|
19602
|
+
if (this.config.debug) {
|
|
19603
|
+
console.log('[AutoTracker] Intelligent mutation observer setup complete');
|
|
19604
|
+
}
|
|
19605
|
+
}
|
|
19606
|
+
/**
|
|
19607
|
+
* Check if element has tracking attributes
|
|
19608
|
+
*/
|
|
19609
|
+
hasTrackingAttributes(element) {
|
|
19610
|
+
return element.hasAttribute && (element.hasAttribute('data-track-click') ||
|
|
19611
|
+
element.hasAttribute('data-track-scroll') ||
|
|
19612
|
+
element.hasAttribute('data-track-view') ||
|
|
19613
|
+
element.hasAttribute('data-track-hover') ||
|
|
19614
|
+
element.hasAttribute('data-track-form'));
|
|
19615
|
+
}
|
|
19616
|
+
/**
|
|
19617
|
+
* Check if element has tracking descendants
|
|
19618
|
+
*/
|
|
19619
|
+
hasTrackingDescendants(element) {
|
|
19620
|
+
if (!element.querySelector)
|
|
19621
|
+
return false;
|
|
19622
|
+
return !!(element.querySelector('[data-track-click]') ||
|
|
19623
|
+
element.querySelector('[data-track-scroll]') ||
|
|
19624
|
+
element.querySelector('[data-track-view]') ||
|
|
19625
|
+
element.querySelector('[data-track-hover]') ||
|
|
19626
|
+
element.querySelector('[data-track-form]'));
|
|
19627
|
+
}
|
|
19628
|
+
/**
|
|
19629
|
+
* Utility: Debounce function for performance optimization
|
|
19630
|
+
*/
|
|
19631
|
+
debounce(func, wait) {
|
|
19632
|
+
let timeout;
|
|
19633
|
+
return (...args) => {
|
|
19634
|
+
clearTimeout(timeout);
|
|
19635
|
+
timeout = setTimeout(() => func.apply(this, args), wait);
|
|
19636
|
+
};
|
|
19637
|
+
}
|
|
19638
|
+
/**
|
|
19639
|
+
* Parar auto tracking (with proper cleanup)
|
|
19640
|
+
*/
|
|
19641
|
+
stop() {
|
|
19642
|
+
if (this.config.debug) {
|
|
19643
|
+
console.log('[AutoTracker] Stopping auto tracking and cleaning up...');
|
|
19644
|
+
}
|
|
19645
|
+
// Remove delegation handlers
|
|
19646
|
+
this.delegationHandlers.forEach((handler, eventType) => {
|
|
19647
|
+
document.removeEventListener(eventType, handler);
|
|
19648
|
+
});
|
|
19649
|
+
this.delegationHandlers.clear();
|
|
19650
|
+
// Disconnect observers
|
|
19651
|
+
if (this.intersectionObserver) {
|
|
19652
|
+
this.intersectionObserver.disconnect();
|
|
19653
|
+
this.intersectionObserver = undefined;
|
|
19654
|
+
}
|
|
19655
|
+
if (this.mutationObserver) {
|
|
19656
|
+
this.mutationObserver.disconnect();
|
|
19657
|
+
this.mutationObserver = undefined;
|
|
19658
|
+
}
|
|
19659
|
+
// Clear caches
|
|
19660
|
+
this.observedElements.clear();
|
|
19661
|
+
this.isInitialized = false;
|
|
19662
|
+
}
|
|
19663
|
+
/**
|
|
19664
|
+
* Legacy method - now handled by intelligent mutation observer
|
|
19665
|
+
* @deprecated Use setupIntelligentMutationObserver instead
|
|
19666
|
+
*/
|
|
19667
|
+
observeDOM() {
|
|
19668
|
+
// This is now handled by setupIntelligentMutationObserver in setupEventDelegation
|
|
19669
|
+
if (this.config.debug) {
|
|
19670
|
+
console.log('[AutoTracker] observeDOM() is deprecated - using intelligent mutation observer');
|
|
19671
|
+
}
|
|
19393
19672
|
}
|
|
19394
19673
|
/**
|
|
19395
19674
|
* Processar elementos já existentes no DOM
|
|
@@ -19405,14 +19684,8 @@
|
|
|
19405
19684
|
* Processar um elemento específico
|
|
19406
19685
|
*/
|
|
19407
19686
|
processElement(element) {
|
|
19408
|
-
// Click tracking
|
|
19409
|
-
|
|
19410
|
-
this.setupClickTracking(element);
|
|
19411
|
-
}
|
|
19412
|
-
// Scroll tracking
|
|
19413
|
-
if (this.config.trackScrolls && element.hasAttribute("data-track-scroll")) {
|
|
19414
|
-
this.setupScrollTracking(element);
|
|
19415
|
-
}
|
|
19687
|
+
// Click tracking - handled by global listener
|
|
19688
|
+
// Scroll tracking - handled by global listener
|
|
19416
19689
|
// View tracking
|
|
19417
19690
|
if (this.config.trackViews && element.hasAttribute("data-track-view")) {
|
|
19418
19691
|
this.setupElementViewTracking(element);
|
|
@@ -19426,60 +19699,6 @@
|
|
|
19426
19699
|
this.setupFormTracking(element);
|
|
19427
19700
|
}
|
|
19428
19701
|
}
|
|
19429
|
-
/**
|
|
19430
|
-
* Setup click tracking
|
|
19431
|
-
*/
|
|
19432
|
-
setupClickTracking(element) {
|
|
19433
|
-
element.addEventListener("click", (event) => {
|
|
19434
|
-
const eventName = element.getAttribute("data-track-click");
|
|
19435
|
-
if (!eventName)
|
|
19436
|
-
return;
|
|
19437
|
-
const metadata = this.extractMetadata(element);
|
|
19438
|
-
this.trackEvent(eventName, {
|
|
19439
|
-
type: "click",
|
|
19440
|
-
element: element.tagName.toLowerCase(),
|
|
19441
|
-
...metadata,
|
|
19442
|
-
});
|
|
19443
|
-
if (this.config.debug) {
|
|
19444
|
-
console.log(`[AutoTracker] Click tracked: ${eventName}`, metadata);
|
|
19445
|
-
}
|
|
19446
|
-
});
|
|
19447
|
-
}
|
|
19448
|
-
/**
|
|
19449
|
-
* Setup scroll tracking
|
|
19450
|
-
*/
|
|
19451
|
-
setupScrollTracking(element) {
|
|
19452
|
-
let hasTriggered = false;
|
|
19453
|
-
const threshold = parseFloat(element.getAttribute("data-scroll-threshold") || "0.5");
|
|
19454
|
-
const handleScroll = () => {
|
|
19455
|
-
if (hasTriggered)
|
|
19456
|
-
return;
|
|
19457
|
-
const rect = element.getBoundingClientRect();
|
|
19458
|
-
const elementHeight = rect.height;
|
|
19459
|
-
const visibleHeight = Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0);
|
|
19460
|
-
const visibilityRatio = Math.max(0, visibleHeight) / elementHeight;
|
|
19461
|
-
if (visibilityRatio >= threshold) {
|
|
19462
|
-
hasTriggered = true;
|
|
19463
|
-
const eventName = element.getAttribute("data-track-scroll");
|
|
19464
|
-
if (!eventName)
|
|
19465
|
-
return;
|
|
19466
|
-
const metadata = this.extractMetadata(element);
|
|
19467
|
-
this.trackEvent(eventName, {
|
|
19468
|
-
type: "scroll",
|
|
19469
|
-
element: element.tagName.toLowerCase(),
|
|
19470
|
-
threshold,
|
|
19471
|
-
scrollDepth: window.scrollY,
|
|
19472
|
-
...metadata,
|
|
19473
|
-
});
|
|
19474
|
-
if (this.config.debug) {
|
|
19475
|
-
console.log(`[AutoTracker] Scroll tracked: ${eventName}`, metadata);
|
|
19476
|
-
}
|
|
19477
|
-
}
|
|
19478
|
-
};
|
|
19479
|
-
document.addEventListener("scroll", handleScroll, { passive: true });
|
|
19480
|
-
// Check immediately in case element is already in view
|
|
19481
|
-
setTimeout(handleScroll, 100);
|
|
19482
|
-
}
|
|
19483
19702
|
/**
|
|
19484
19703
|
* Setup view tracking usando Intersection Observer
|
|
19485
19704
|
*/
|
|
@@ -19637,15 +19856,35 @@
|
|
|
19637
19856
|
* Enviar evento para o SDK
|
|
19638
19857
|
*/
|
|
19639
19858
|
trackEvent(eventName, metadata) {
|
|
19640
|
-
if (
|
|
19859
|
+
if (this.config.debug) {
|
|
19860
|
+
console.log("[AutoTracker] trackEvent called:", { eventName, metadata });
|
|
19861
|
+
}
|
|
19862
|
+
if (!this.sdkInstance) {
|
|
19863
|
+
if (this.config.debug) {
|
|
19864
|
+
console.error("[AutoTracker] SDK instance is null!");
|
|
19865
|
+
}
|
|
19641
19866
|
return;
|
|
19867
|
+
}
|
|
19868
|
+
if (typeof this.sdkInstance.trackCustomEvent !== 'function') {
|
|
19869
|
+
if (this.config.debug) {
|
|
19870
|
+
console.error("[AutoTracker] trackCustomEvent is not a function:", typeof this.sdkInstance.trackCustomEvent);
|
|
19871
|
+
}
|
|
19872
|
+
return;
|
|
19873
|
+
}
|
|
19642
19874
|
try {
|
|
19643
|
-
|
|
19875
|
+
const eventData = {
|
|
19644
19876
|
autoTracked: true,
|
|
19645
19877
|
timestamp: Date.now(),
|
|
19646
19878
|
url: window.location.href,
|
|
19647
19879
|
...metadata,
|
|
19648
|
-
}
|
|
19880
|
+
};
|
|
19881
|
+
if (this.config.debug) {
|
|
19882
|
+
console.log("[AutoTracker] Calling trackCustomEvent:", { eventName, eventData });
|
|
19883
|
+
}
|
|
19884
|
+
const result = this.sdkInstance.trackCustomEvent(eventName, eventData);
|
|
19885
|
+
if (this.config.debug) {
|
|
19886
|
+
console.log("[AutoTracker] trackCustomEvent result:", result);
|
|
19887
|
+
}
|
|
19649
19888
|
}
|
|
19650
19889
|
catch (error) {
|
|
19651
19890
|
if (this.config.debug) {
|
|
@@ -19653,6 +19892,55 @@
|
|
|
19653
19892
|
}
|
|
19654
19893
|
}
|
|
19655
19894
|
}
|
|
19895
|
+
/**
|
|
19896
|
+
* Modern API: Refresh tracking for dynamic content (React/SPA support)
|
|
19897
|
+
* Industry best practice for SPA route changes
|
|
19898
|
+
*/
|
|
19899
|
+
refreshTracking() {
|
|
19900
|
+
if (!this.isInitialized) {
|
|
19901
|
+
if (this.config.debug) {
|
|
19902
|
+
console.log('[AutoTracker] Not initialized, cannot refresh tracking');
|
|
19903
|
+
}
|
|
19904
|
+
return;
|
|
19905
|
+
}
|
|
19906
|
+
if (this.config.debug) {
|
|
19907
|
+
console.log('[AutoTracker] Refreshing tracking for dynamic content...');
|
|
19908
|
+
}
|
|
19909
|
+
// Re-process elements for view tracking (only thing that needs setup)
|
|
19910
|
+
this.processExistingElements();
|
|
19911
|
+
// Log current state
|
|
19912
|
+
if (this.config.debug) {
|
|
19913
|
+
this.logFoundElements();
|
|
19914
|
+
}
|
|
19915
|
+
}
|
|
19916
|
+
/**
|
|
19917
|
+
* Legacy method - use refreshTracking() instead
|
|
19918
|
+
* @deprecated Use refreshTracking() for better performance
|
|
19919
|
+
*/
|
|
19920
|
+
rescan() {
|
|
19921
|
+
this.refreshTracking();
|
|
19922
|
+
}
|
|
19923
|
+
/**
|
|
19924
|
+
* Get diagnostic information for debugging
|
|
19925
|
+
*/
|
|
19926
|
+
getDiagnostics() {
|
|
19927
|
+
return {
|
|
19928
|
+
isInitialized: this.isInitialized,
|
|
19929
|
+
hasClickHandler: this.delegationHandlers.has('click'),
|
|
19930
|
+
hasScrollHandler: this.delegationHandlers.has('scroll'),
|
|
19931
|
+
observedElements: this.observedElements.size,
|
|
19932
|
+
hasMutationObserver: !!this.mutationObserver,
|
|
19933
|
+
hasIntersectionObserver: !!this.intersectionObserver,
|
|
19934
|
+
config: this.config,
|
|
19935
|
+
elementsFound: {
|
|
19936
|
+
click: document.querySelectorAll('[data-track-click]').length,
|
|
19937
|
+
scroll: document.querySelectorAll('[data-track-scroll]').length,
|
|
19938
|
+
view: document.querySelectorAll('[data-track-view]').length,
|
|
19939
|
+
hover: document.querySelectorAll('[data-track-hover]').length,
|
|
19940
|
+
form: document.querySelectorAll('[data-track-form]').length
|
|
19941
|
+
}
|
|
19942
|
+
};
|
|
19943
|
+
}
|
|
19656
19944
|
/**
|
|
19657
19945
|
* Configurar tracking
|
|
19658
19946
|
*/
|
|
@@ -19660,12 +19948,14 @@
|
|
|
19660
19948
|
this.config = { ...this.config, ...config };
|
|
19661
19949
|
}
|
|
19662
19950
|
/**
|
|
19663
|
-
*
|
|
19951
|
+
* Enhanced stats with diagnostic information
|
|
19664
19952
|
*/
|
|
19665
19953
|
getStats() {
|
|
19666
19954
|
return {
|
|
19667
19955
|
observedElements: this.observedElements.size,
|
|
19668
19956
|
config: this.config,
|
|
19957
|
+
isModern: this.isInitialized, // Indicates if using new delegation system
|
|
19958
|
+
diagnostics: this.config.debug ? this.getDiagnostics() : undefined
|
|
19669
19959
|
};
|
|
19670
19960
|
}
|
|
19671
19961
|
}
|
|
@@ -20214,6 +20504,36 @@
|
|
|
20214
20504
|
console.log("[Zaplier] Auto tracking configured:", config);
|
|
20215
20505
|
}
|
|
20216
20506
|
},
|
|
20507
|
+
/**
|
|
20508
|
+
* Refresh tracking for dynamic content (React/SPA route changes)
|
|
20509
|
+
* Modern alternative to rescan() - follows GA4/industry best practices
|
|
20510
|
+
*/
|
|
20511
|
+
refreshTracking: () => {
|
|
20512
|
+
if (this.autoTracker) {
|
|
20513
|
+
this.autoTracker.refreshTracking();
|
|
20514
|
+
}
|
|
20515
|
+
if (this.config.debug) {
|
|
20516
|
+
console.log("[Zaplier] Auto tracking refreshed");
|
|
20517
|
+
}
|
|
20518
|
+
},
|
|
20519
|
+
/**
|
|
20520
|
+
* Legacy rescan method - use refreshTracking() instead
|
|
20521
|
+
* @deprecated Use refreshTracking() for better performance
|
|
20522
|
+
*/
|
|
20523
|
+
rescan: () => {
|
|
20524
|
+
if (this.autoTracker) {
|
|
20525
|
+
this.autoTracker.rescan();
|
|
20526
|
+
}
|
|
20527
|
+
if (this.config.debug) {
|
|
20528
|
+
console.log("[Zaplier] Auto tracking rescanned (deprecated - use refreshTracking)");
|
|
20529
|
+
}
|
|
20530
|
+
},
|
|
20531
|
+
/**
|
|
20532
|
+
* Get diagnostic information for debugging
|
|
20533
|
+
*/
|
|
20534
|
+
getDiagnostics: () => {
|
|
20535
|
+
return this.autoTracker ? this.autoTracker.getDiagnostics() : null;
|
|
20536
|
+
},
|
|
20217
20537
|
getStats: () => {
|
|
20218
20538
|
return this.autoTracker ? this.autoTracker.getStats() : null;
|
|
20219
20539
|
},
|