@zaplier/sdk 1.7.5 โ 1.7.7
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 +311 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.esm.js +311 -73
- package/dist/index.esm.js.map +1 -1
- package/dist/sdk.js +311 -73
- package/dist/sdk.js.map +1 -1
- package/dist/sdk.min.js +1 -1
- package/dist/src/modules/auto-tracker.d.ts +19 -1
- package/dist/src/modules/auto-tracker.d.ts.map +1 -1
- package/dist/src/sdk.d.ts +4 -0
- package/dist/src/sdk.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -19570,78 +19570,19 @@ class AutoTracker {
|
|
|
19570
19570
|
console.log("[๐ AutoTracker] Click delegation handler added");
|
|
19571
19571
|
}
|
|
19572
19572
|
}
|
|
19573
|
-
//
|
|
19573
|
+
// MODERN APPROACH: IntersectionObserver + Scroll Fallback (2025 Best Practice)
|
|
19574
19574
|
if (this.config.trackScrolls) {
|
|
19575
|
-
const scrollHandler = this.createEnhancedScrollHandler();
|
|
19576
|
-
this.delegationHandlers.set('scroll', scrollHandler);
|
|
19577
|
-
// MAJOR FIX: Use window instead of document for scroll events
|
|
19578
|
-
// Document doesn't reliably receive scroll events in all browsers
|
|
19579
|
-
const scrollTarget = window;
|
|
19580
|
-
const scrollOptions = {
|
|
19581
|
-
passive: false, // Changed from passive: true to ensure handler executes
|
|
19582
|
-
capture: false
|
|
19583
|
-
};
|
|
19584
|
-
scrollTarget.addEventListener('scroll', scrollHandler, scrollOptions);
|
|
19585
|
-
// Also add to document as backup (some scenarios need both)
|
|
19586
|
-
document.addEventListener('scroll', scrollHandler, scrollOptions);
|
|
19587
19575
|
if (this.config.debug) {
|
|
19588
|
-
console.log("[
|
|
19589
|
-
|
|
19590
|
-
|
|
19591
|
-
|
|
19592
|
-
|
|
19593
|
-
|
|
19594
|
-
|
|
19595
|
-
|
|
19596
|
-
|
|
19597
|
-
|
|
19598
|
-
const testHandler = () => {
|
|
19599
|
-
console.log("[๐ AutoTracker] ๐งช MANUAL SCROLL TEST - Handler should trigger");
|
|
19600
|
-
scrollHandler(new Event('scroll'));
|
|
19601
|
-
};
|
|
19602
|
-
const testRealScroll = () => {
|
|
19603
|
-
console.log("[๐ AutoTracker] ๐งช TESTING REAL SCROLL EVENT");
|
|
19604
|
-
window.scrollBy(0, 1); // Trigger real scroll
|
|
19605
|
-
setTimeout(() => {
|
|
19606
|
-
window.scrollBy(0, -1); // Scroll back
|
|
19607
|
-
}, 100);
|
|
19608
|
-
};
|
|
19609
|
-
// Expose test functions globally for manual testing
|
|
19610
|
-
if (typeof window !== 'undefined') {
|
|
19611
|
-
window.testScrollHandler = testHandler;
|
|
19612
|
-
window.testRealScroll = testRealScroll;
|
|
19613
|
-
console.log("[๐ AutoTracker] ๐งช Manual tests available:");
|
|
19614
|
-
console.log("[๐ AutoTracker] ๐งช - window.testScrollHandler() (direct handler test)");
|
|
19615
|
-
console.log("[๐ AutoTracker] ๐งช - window.testRealScroll() (real scroll test)");
|
|
19616
|
-
}
|
|
19617
|
-
// Add debug listener to verify scroll events are firing
|
|
19618
|
-
const debugScrollListener = () => {
|
|
19619
|
-
console.log("[๐ AutoTracker] ๐ DEBUG: Real scroll event detected!");
|
|
19620
|
-
};
|
|
19621
|
-
window.addEventListener('scroll', debugScrollListener, { once: true });
|
|
19622
|
-
console.log("[๐ AutoTracker] ๐ Debug scroll listener added (will fire once on next scroll)");
|
|
19623
|
-
// Immediate test of element detection
|
|
19624
|
-
setTimeout(() => {
|
|
19625
|
-
const scrollElements = this.getCachedScrollElements();
|
|
19626
|
-
console.log(`[๐ AutoTracker] ๐ Initial scroll elements check: ${scrollElements.length} found`);
|
|
19627
|
-
if (scrollElements.length > 0) {
|
|
19628
|
-
Array.from(scrollElements).forEach((element, index) => {
|
|
19629
|
-
console.log(`[๐ AutoTracker] Element ${index + 1}:`, {
|
|
19630
|
-
id: element.id || 'no-id',
|
|
19631
|
-
trackEvent: element.getAttribute('data-track-scroll'),
|
|
19632
|
-
threshold: element.getAttribute('data-scroll-threshold') || '0.5',
|
|
19633
|
-
tagName: element.tagName,
|
|
19634
|
-
rect: element.getBoundingClientRect(),
|
|
19635
|
-
isVisible: element.getBoundingClientRect().height > 0
|
|
19636
|
-
});
|
|
19637
|
-
});
|
|
19638
|
-
}
|
|
19639
|
-
// Test auto-scroll detection
|
|
19640
|
-
setTimeout(() => {
|
|
19641
|
-
console.log("[๐ AutoTracker] ๐งช Auto-testing scroll detection in 1 second...");
|
|
19642
|
-
testRealScroll();
|
|
19643
|
-
}, 1000);
|
|
19644
|
-
}, 100);
|
|
19576
|
+
console.log("[๐ AutoTracker] Setting up modern scroll tracking with IntersectionObserver");
|
|
19577
|
+
}
|
|
19578
|
+
// PRIMARY: Modern IntersectionObserver approach (recommended 2025)
|
|
19579
|
+
this.setupIntersectionObserverScrollTracking();
|
|
19580
|
+
// FALLBACK: Traditional scroll listener for edge cases
|
|
19581
|
+
this.setupFallbackScrollListener();
|
|
19582
|
+
if (this.config.debug) {
|
|
19583
|
+
console.log("[๐ AutoTracker] โ
Modern scroll tracking setup complete:");
|
|
19584
|
+
console.log("[๐ AutoTracker] ๐ Primary: IntersectionObserver (modern, performant)");
|
|
19585
|
+
console.log("[๐ AutoTracker] ๐ Fallback: Traditional scroll listener (compatibility)");
|
|
19645
19586
|
}
|
|
19646
19587
|
}
|
|
19647
19588
|
// Setup debounced mutation observer for dynamic content
|
|
@@ -19775,7 +19716,209 @@ class AutoTracker {
|
|
|
19775
19716
|
return null;
|
|
19776
19717
|
}
|
|
19777
19718
|
/**
|
|
19778
|
-
*
|
|
19719
|
+
* Modern IntersectionObserver-based scroll tracking (2025 Best Practice)
|
|
19720
|
+
* More performant and reliable than traditional scroll listeners
|
|
19721
|
+
*/
|
|
19722
|
+
setupIntersectionObserverScrollTracking() {
|
|
19723
|
+
if (typeof window === 'undefined' || !('IntersectionObserver' in window)) {
|
|
19724
|
+
if (this.config.debug) {
|
|
19725
|
+
console.log("[โ ๏ธ AutoTracker] IntersectionObserver not available, using fallback only");
|
|
19726
|
+
}
|
|
19727
|
+
return;
|
|
19728
|
+
}
|
|
19729
|
+
// Get all scroll elements
|
|
19730
|
+
const scrollElements = document.querySelectorAll('[data-track-scroll]');
|
|
19731
|
+
if (scrollElements.length === 0) {
|
|
19732
|
+
if (this.config.debug) {
|
|
19733
|
+
console.log("[๐ AutoTracker] No scroll elements found for IntersectionObserver");
|
|
19734
|
+
}
|
|
19735
|
+
return;
|
|
19736
|
+
}
|
|
19737
|
+
// Create observer with multiple thresholds for precise tracking
|
|
19738
|
+
const observerOptions = {
|
|
19739
|
+
root: null, // Use viewport as root
|
|
19740
|
+
rootMargin: '0px',
|
|
19741
|
+
threshold: [0, 0.1, 0.25, 0.5, 0.75, 0.9, 1.0] // Multiple thresholds for accuracy
|
|
19742
|
+
};
|
|
19743
|
+
const observer = new IntersectionObserver((entries) => {
|
|
19744
|
+
entries.forEach((entry) => {
|
|
19745
|
+
const element = entry.target;
|
|
19746
|
+
const eventName = element.getAttribute('data-track-scroll');
|
|
19747
|
+
const customThreshold = parseFloat(element.getAttribute('data-scroll-threshold') || '0.5');
|
|
19748
|
+
const hasTriggered = element.getAttribute('data-scroll-triggered') === 'true';
|
|
19749
|
+
if (!eventName || hasTriggered)
|
|
19750
|
+
return;
|
|
19751
|
+
const visibilityRatio = entry.intersectionRatio;
|
|
19752
|
+
if (this.config.debug) {
|
|
19753
|
+
console.log(`[๐ IntersectionObserver] Element "${eventName}":`, {
|
|
19754
|
+
elementId: element.id || 'no-id',
|
|
19755
|
+
visibilityRatio: Math.round(visibilityRatio * 1000) / 1000,
|
|
19756
|
+
threshold: customThreshold,
|
|
19757
|
+
isIntersecting: entry.isIntersecting,
|
|
19758
|
+
shouldTrigger: visibilityRatio >= customThreshold
|
|
19759
|
+
});
|
|
19760
|
+
}
|
|
19761
|
+
// Trigger event when visibility threshold is met
|
|
19762
|
+
if (visibilityRatio >= customThreshold) {
|
|
19763
|
+
element.setAttribute('data-scroll-triggered', 'true');
|
|
19764
|
+
const metadata = this.extractMetadata(element);
|
|
19765
|
+
this.trackEvent(eventName, {
|
|
19766
|
+
type: 'scroll',
|
|
19767
|
+
method: 'IntersectionObserver',
|
|
19768
|
+
element: element.tagName.toLowerCase(),
|
|
19769
|
+
threshold: customThreshold,
|
|
19770
|
+
visibilityRatio: Math.round(visibilityRatio * 1000) / 1000,
|
|
19771
|
+
enhanced: true,
|
|
19772
|
+
modern: true,
|
|
19773
|
+
...metadata,
|
|
19774
|
+
});
|
|
19775
|
+
if (this.config.debug) {
|
|
19776
|
+
console.log(`[๐ฏ IntersectionObserver] Event "${eventName}" triggered! (${Math.round(visibilityRatio * 100)}% visible)`);
|
|
19777
|
+
}
|
|
19778
|
+
// Unobserve after triggering (one-time trigger)
|
|
19779
|
+
observer.unobserve(element);
|
|
19780
|
+
}
|
|
19781
|
+
});
|
|
19782
|
+
}, observerOptions);
|
|
19783
|
+
// Observe all scroll elements
|
|
19784
|
+
scrollElements.forEach((element) => {
|
|
19785
|
+
observer.observe(element);
|
|
19786
|
+
if (this.config.debug) {
|
|
19787
|
+
console.log(`[๐๏ธ IntersectionObserver] Now observing: ${element.getAttribute('data-track-scroll')} (${element.id || 'no-id'})`);
|
|
19788
|
+
}
|
|
19789
|
+
});
|
|
19790
|
+
// Store observer for cleanup
|
|
19791
|
+
this.intersectionObserver = observer;
|
|
19792
|
+
if (this.config.debug) {
|
|
19793
|
+
console.log(`[โ
IntersectionObserver] Setup complete - observing ${scrollElements.length} elements`);
|
|
19794
|
+
}
|
|
19795
|
+
}
|
|
19796
|
+
/**
|
|
19797
|
+
* Fallback scroll listener for compatibility (React/Next.js issues)
|
|
19798
|
+
*/
|
|
19799
|
+
setupFallbackScrollListener() {
|
|
19800
|
+
if (typeof window === 'undefined')
|
|
19801
|
+
return;
|
|
19802
|
+
const fallbackHandler = this.createThrottledScrollHandler();
|
|
19803
|
+
// Try multiple attachment strategies for React/Next.js compatibility
|
|
19804
|
+
const attachStrategies = [
|
|
19805
|
+
() => window.addEventListener('scroll', fallbackHandler, { passive: true }),
|
|
19806
|
+
() => document.addEventListener('scroll', fallbackHandler, { passive: true }),
|
|
19807
|
+
() => window.addEventListener('scroll', fallbackHandler, { passive: true, capture: true }),
|
|
19808
|
+
() => {
|
|
19809
|
+
// Delayed attachment for React hydration
|
|
19810
|
+
setTimeout(() => {
|
|
19811
|
+
window.addEventListener('scroll', fallbackHandler, { passive: true });
|
|
19812
|
+
}, 100);
|
|
19813
|
+
},
|
|
19814
|
+
() => {
|
|
19815
|
+
// Document ready state check
|
|
19816
|
+
if (document.readyState === 'complete') {
|
|
19817
|
+
window.addEventListener('scroll', fallbackHandler, { passive: true });
|
|
19818
|
+
}
|
|
19819
|
+
else {
|
|
19820
|
+
window.addEventListener('load', () => {
|
|
19821
|
+
window.addEventListener('scroll', fallbackHandler, { passive: true });
|
|
19822
|
+
});
|
|
19823
|
+
}
|
|
19824
|
+
}
|
|
19825
|
+
];
|
|
19826
|
+
// Try each strategy
|
|
19827
|
+
attachStrategies.forEach((strategy, index) => {
|
|
19828
|
+
try {
|
|
19829
|
+
strategy();
|
|
19830
|
+
if (this.config.debug) {
|
|
19831
|
+
console.log(`[๐ AutoTracker] Fallback scroll strategy ${index + 1} attached`);
|
|
19832
|
+
}
|
|
19833
|
+
}
|
|
19834
|
+
catch (error) {
|
|
19835
|
+
if (this.config.debug) {
|
|
19836
|
+
console.log(`[โ ๏ธ AutoTracker] Fallback strategy ${index + 1} failed:`, error);
|
|
19837
|
+
}
|
|
19838
|
+
}
|
|
19839
|
+
});
|
|
19840
|
+
this.delegationHandlers.set('scroll', fallbackHandler);
|
|
19841
|
+
// Test scroll detection after setup
|
|
19842
|
+
if (this.config.debug) {
|
|
19843
|
+
setTimeout(() => {
|
|
19844
|
+
console.log("[๐งช AutoTracker] Testing fallback scroll in 2 seconds...");
|
|
19845
|
+
// Add one-time debug listener
|
|
19846
|
+
const testListener = () => {
|
|
19847
|
+
console.log("[โ
AutoTracker] Fallback scroll listener working!");
|
|
19848
|
+
};
|
|
19849
|
+
window.addEventListener('scroll', testListener, { once: true, passive: true });
|
|
19850
|
+
// Trigger test scroll
|
|
19851
|
+
const originalScrollY = window.scrollY;
|
|
19852
|
+
window.scrollBy(0, 1);
|
|
19853
|
+
setTimeout(() => window.scrollTo(0, originalScrollY), 50);
|
|
19854
|
+
}, 2000);
|
|
19855
|
+
}
|
|
19856
|
+
}
|
|
19857
|
+
/**
|
|
19858
|
+
* Create throttled scroll handler (optimized for performance)
|
|
19859
|
+
*/
|
|
19860
|
+
createThrottledScrollHandler() {
|
|
19861
|
+
let lastKnownScrollPosition = 0;
|
|
19862
|
+
let ticking = false;
|
|
19863
|
+
return () => {
|
|
19864
|
+
lastKnownScrollPosition = window.scrollY;
|
|
19865
|
+
if (!ticking) {
|
|
19866
|
+
// Use setTimeout throttling (MDN recommended 2025)
|
|
19867
|
+
setTimeout(() => {
|
|
19868
|
+
if (this.config.debug) {
|
|
19869
|
+
console.log(`[๐ AutoTracker] Fallback scroll handler triggered (scrollY: ${lastKnownScrollPosition})`);
|
|
19870
|
+
}
|
|
19871
|
+
this.processFallbackScroll(lastKnownScrollPosition);
|
|
19872
|
+
ticking = false;
|
|
19873
|
+
}, 20); // 20ms throttle (MDN recommendation)
|
|
19874
|
+
ticking = true;
|
|
19875
|
+
}
|
|
19876
|
+
};
|
|
19877
|
+
}
|
|
19878
|
+
/**
|
|
19879
|
+
* Process scroll for fallback handler (when IntersectionObserver fails)
|
|
19880
|
+
*/
|
|
19881
|
+
processFallbackScroll(scrollPosition) {
|
|
19882
|
+
// Only process if IntersectionObserver didn't handle it
|
|
19883
|
+
const scrollElements = document.querySelectorAll('[data-track-scroll]:not([data-scroll-triggered="true"])');
|
|
19884
|
+
if (scrollElements.length === 0)
|
|
19885
|
+
return;
|
|
19886
|
+
scrollElements.forEach((element) => {
|
|
19887
|
+
const eventName = element.getAttribute('data-track-scroll');
|
|
19888
|
+
const threshold = parseFloat(element.getAttribute('data-scroll-threshold') || '0.5');
|
|
19889
|
+
if (!eventName)
|
|
19890
|
+
return;
|
|
19891
|
+
const rect = element.getBoundingClientRect();
|
|
19892
|
+
const windowHeight = window.innerHeight;
|
|
19893
|
+
const elementHeight = rect.height;
|
|
19894
|
+
if (elementHeight <= 0)
|
|
19895
|
+
return;
|
|
19896
|
+
const visibleTop = Math.max(rect.top, 0);
|
|
19897
|
+
const visibleBottom = Math.min(rect.bottom, windowHeight);
|
|
19898
|
+
const visibleHeight = Math.max(0, visibleBottom - visibleTop);
|
|
19899
|
+
const visibilityRatio = visibleHeight / elementHeight;
|
|
19900
|
+
if (visibilityRatio >= threshold) {
|
|
19901
|
+
element.setAttribute('data-scroll-triggered', 'true');
|
|
19902
|
+
const metadata = this.extractMetadata(element);
|
|
19903
|
+
this.trackEvent(eventName, {
|
|
19904
|
+
type: 'scroll',
|
|
19905
|
+
method: 'fallback_scroll',
|
|
19906
|
+
element: element.tagName.toLowerCase(),
|
|
19907
|
+
threshold,
|
|
19908
|
+
visibilityRatio: Math.round(visibilityRatio * 1000) / 1000,
|
|
19909
|
+
scrollPosition,
|
|
19910
|
+
fallback: true,
|
|
19911
|
+
...metadata,
|
|
19912
|
+
});
|
|
19913
|
+
if (this.config.debug) {
|
|
19914
|
+
console.log(`[๐ฏ Fallback] Event "${eventName}" triggered! (${Math.round(visibilityRatio * 100)}% visible)`);
|
|
19915
|
+
}
|
|
19916
|
+
}
|
|
19917
|
+
});
|
|
19918
|
+
}
|
|
19919
|
+
/**
|
|
19920
|
+
* LEGACY: Create enhanced scroll handler with better performance
|
|
19921
|
+
* @deprecated Use IntersectionObserver approach instead
|
|
19779
19922
|
*/
|
|
19780
19923
|
createEnhancedScrollHandler() {
|
|
19781
19924
|
return () => {
|
|
@@ -20460,6 +20603,33 @@ class AutoTracker {
|
|
|
20460
20603
|
source: 'manual_diagnostic',
|
|
20461
20604
|
timestamp: Date.now()
|
|
20462
20605
|
});
|
|
20606
|
+
},
|
|
20607
|
+
testIntersectionObserver: () => {
|
|
20608
|
+
console.log(`[๐งช AutoTracker] Testing IntersectionObserver setup`);
|
|
20609
|
+
const scrollElements = document.querySelectorAll('[data-track-scroll]');
|
|
20610
|
+
console.log(`Found ${scrollElements.length} scroll elements for IntersectionObserver`);
|
|
20611
|
+
if (this.intersectionObserver && scrollElements.length > 0) {
|
|
20612
|
+
const firstElement = scrollElements[0];
|
|
20613
|
+
if (firstElement) {
|
|
20614
|
+
console.log('Testing first element:', firstElement.getAttribute('data-track-scroll'));
|
|
20615
|
+
// Temporarily remove triggered state for testing
|
|
20616
|
+
firstElement.removeAttribute('data-scroll-triggered');
|
|
20617
|
+
// Re-observe for testing
|
|
20618
|
+
this.intersectionObserver.observe(firstElement);
|
|
20619
|
+
console.log('Re-observing element for test...');
|
|
20620
|
+
}
|
|
20621
|
+
}
|
|
20622
|
+
},
|
|
20623
|
+
testScrollFallback: () => {
|
|
20624
|
+
console.log(`[๐งช AutoTracker] Testing scroll fallback mechanism`);
|
|
20625
|
+
const handler = this.delegationHandlers.get('scroll');
|
|
20626
|
+
if (handler) {
|
|
20627
|
+
console.log('Triggering fallback scroll handler...');
|
|
20628
|
+
handler(new Event('scroll'));
|
|
20629
|
+
}
|
|
20630
|
+
else {
|
|
20631
|
+
console.log('No scroll handler found in delegation handlers');
|
|
20632
|
+
}
|
|
20463
20633
|
}
|
|
20464
20634
|
};
|
|
20465
20635
|
// Expose tests globally for easy access
|
|
@@ -20514,7 +20684,9 @@ class AutoTracker {
|
|
|
20514
20684
|
usage: {
|
|
20515
20685
|
triggerScrollHandler: 'window.autoTrackerTests.triggerScrollHandler()',
|
|
20516
20686
|
forceScrollEvent: 'window.autoTrackerTests.forceScrollEvent("[data-track-scroll]")',
|
|
20517
|
-
testTrackEvent: 'window.autoTrackerTests.testTrackEvent("my_event")'
|
|
20687
|
+
testTrackEvent: 'window.autoTrackerTests.testTrackEvent("my_event")',
|
|
20688
|
+
testIntersectionObserver: 'window.autoTrackerTests.testIntersectionObserver()',
|
|
20689
|
+
testScrollFallback: 'window.autoTrackerTests.testScrollFallback()'
|
|
20518
20690
|
},
|
|
20519
20691
|
description: 'Use these functions in the browser console to manually test the AutoTracker'
|
|
20520
20692
|
}
|
|
@@ -21513,6 +21685,70 @@ class ZaplierSDK {
|
|
|
21513
21685
|
window.location.hostname.startsWith("10.") ||
|
|
21514
21686
|
window.location.hostname.includes("local"));
|
|
21515
21687
|
}
|
|
21688
|
+
/**
|
|
21689
|
+
* Extract UTM parameters from current URL
|
|
21690
|
+
*/
|
|
21691
|
+
extractUTMParameters() {
|
|
21692
|
+
const utmParams = {};
|
|
21693
|
+
if (typeof window === "undefined" || !window.location) {
|
|
21694
|
+
return utmParams;
|
|
21695
|
+
}
|
|
21696
|
+
try {
|
|
21697
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
21698
|
+
// Extract UTM parameters (camelCase for consistency with backend)
|
|
21699
|
+
const utmSource = urlParams.get('utm_source');
|
|
21700
|
+
const utmMedium = urlParams.get('utm_medium');
|
|
21701
|
+
const utmCampaign = urlParams.get('utm_campaign');
|
|
21702
|
+
const utmContent = urlParams.get('utm_content');
|
|
21703
|
+
const utmTerm = urlParams.get('utm_term');
|
|
21704
|
+
// Extract click IDs
|
|
21705
|
+
const fbclid = urlParams.get('fbclid');
|
|
21706
|
+
const gclid = urlParams.get('gclid');
|
|
21707
|
+
const ttclid = urlParams.get('ttclid');
|
|
21708
|
+
// Extract ad platform parameters
|
|
21709
|
+
const creativeId = urlParams.get('creative_id');
|
|
21710
|
+
const adId = urlParams.get('ad_id');
|
|
21711
|
+
const adsetId = urlParams.get('adset_id');
|
|
21712
|
+
const campaignId = urlParams.get('campaign_id');
|
|
21713
|
+
const platform = urlParams.get('platform');
|
|
21714
|
+
// Add to result object (only non-null values)
|
|
21715
|
+
if (utmSource)
|
|
21716
|
+
utmParams.utmSource = utmSource;
|
|
21717
|
+
if (utmMedium)
|
|
21718
|
+
utmParams.utmMedium = utmMedium;
|
|
21719
|
+
if (utmCampaign)
|
|
21720
|
+
utmParams.utmCampaign = utmCampaign;
|
|
21721
|
+
if (utmContent)
|
|
21722
|
+
utmParams.utmContent = utmContent;
|
|
21723
|
+
if (utmTerm)
|
|
21724
|
+
utmParams.utmTerm = utmTerm;
|
|
21725
|
+
if (fbclid)
|
|
21726
|
+
utmParams.fbclid = fbclid;
|
|
21727
|
+
if (gclid)
|
|
21728
|
+
utmParams.gclid = gclid;
|
|
21729
|
+
if (ttclid)
|
|
21730
|
+
utmParams.ttclid = ttclid;
|
|
21731
|
+
if (creativeId)
|
|
21732
|
+
utmParams.creativeId = creativeId;
|
|
21733
|
+
if (adId)
|
|
21734
|
+
utmParams.adId = adId;
|
|
21735
|
+
if (adsetId)
|
|
21736
|
+
utmParams.adsetId = adsetId;
|
|
21737
|
+
if (campaignId)
|
|
21738
|
+
utmParams.campaignId = campaignId;
|
|
21739
|
+
if (platform)
|
|
21740
|
+
utmParams.platform = platform;
|
|
21741
|
+
if (this.config.debug && Object.keys(utmParams).length > 0) {
|
|
21742
|
+
console.log("[Zaplier] UTM parameters extracted from URL:", utmParams);
|
|
21743
|
+
}
|
|
21744
|
+
}
|
|
21745
|
+
catch (error) {
|
|
21746
|
+
if (this.config.debug) {
|
|
21747
|
+
console.warn("[Zaplier] Failed to extract UTM parameters:", error);
|
|
21748
|
+
}
|
|
21749
|
+
}
|
|
21750
|
+
return utmParams;
|
|
21751
|
+
}
|
|
21516
21752
|
/**
|
|
21517
21753
|
* Send event to backend
|
|
21518
21754
|
*/
|
|
@@ -21554,7 +21790,9 @@ class ZaplierSDK {
|
|
|
21554
21790
|
}
|
|
21555
21791
|
: undefined,
|
|
21556
21792
|
fingerprintComponents: this.fingerprint?.components || {},
|
|
21557
|
-
|
|
21793
|
+
// CRITICAL: Auto-extract UTM parameters from URL, but allow eventData to override
|
|
21794
|
+
...this.extractUTMParameters(), // Auto-extracted UTM parameters (background)
|
|
21795
|
+
...eventData, // User-provided event data (can override UTM parameters)
|
|
21558
21796
|
timestamp: new Date().toISOString(),
|
|
21559
21797
|
url: typeof window !== "undefined" && window.location
|
|
21560
21798
|
? window.location.href
|