@zaplier/sdk 1.7.2 → 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.cjs +165 -144
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -6
- package/dist/index.esm.js +165 -144
- package/dist/index.esm.js.map +1 -1
- package/dist/sdk.js +165 -144
- package/dist/sdk.js.map +1 -1
- package/dist/sdk.min.js +1 -1
- package/dist/src/modules/auto-tracker.d.ts +0 -2
- package/dist/src/modules/auto-tracker.d.ts.map +1 -1
- package/dist/src/modules/visitor-persistence.d.ts.map +1 -1
- package/dist/src/sdk.d.ts +1 -6
- package/dist/src/sdk.d.ts.map +1 -1
- package/dist/src/utils/session-utils.d.ts +34 -0
- package/dist/src/utils/session-utils.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -19276,85 +19276,6 @@ class AutoTracker {
|
|
|
19276
19276
|
*/
|
|
19277
19277
|
this.cachedScrollElements = null;
|
|
19278
19278
|
this.lastScrollElementsCheck = 0;
|
|
19279
|
-
this.handleScroll = () => {
|
|
19280
|
-
if (!this.config.trackScrolls)
|
|
19281
|
-
return;
|
|
19282
|
-
// Throttle scroll events for performance
|
|
19283
|
-
const now = Date.now();
|
|
19284
|
-
if (now - this.scrollThrottle < 100)
|
|
19285
|
-
return; // 100ms throttle
|
|
19286
|
-
this.scrollThrottle = now;
|
|
19287
|
-
const scrollElements = document.querySelectorAll('[data-track-scroll]');
|
|
19288
|
-
if (this.config.debug && scrollElements.length > 0) {
|
|
19289
|
-
console.log(`[AutoTracker] Checking ${scrollElements.length} scroll elements`, {
|
|
19290
|
-
scrollY: window.scrollY,
|
|
19291
|
-
innerHeight: window.innerHeight
|
|
19292
|
-
});
|
|
19293
|
-
}
|
|
19294
|
-
scrollElements.forEach((element) => {
|
|
19295
|
-
let hasTriggered = element.getAttribute('data-scroll-triggered') === 'true';
|
|
19296
|
-
if (hasTriggered)
|
|
19297
|
-
return;
|
|
19298
|
-
const threshold = parseFloat(element.getAttribute("data-scroll-threshold") || "0.5");
|
|
19299
|
-
const rect = element.getBoundingClientRect();
|
|
19300
|
-
const elementHeight = rect.height;
|
|
19301
|
-
const visibleHeight = Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0);
|
|
19302
|
-
const visibilityRatio = Math.max(0, visibleHeight) / elementHeight;
|
|
19303
|
-
if (this.config.debug) {
|
|
19304
|
-
console.log(`[AutoTracker] Element check:`, {
|
|
19305
|
-
elementId: element.id || element.className,
|
|
19306
|
-
visibilityRatio: Math.round(visibilityRatio * 100) / 100,
|
|
19307
|
-
threshold,
|
|
19308
|
-
triggered: hasTriggered
|
|
19309
|
-
});
|
|
19310
|
-
}
|
|
19311
|
-
if (visibilityRatio >= threshold) {
|
|
19312
|
-
element.setAttribute('data-scroll-triggered', 'true');
|
|
19313
|
-
const eventName = element.getAttribute("data-track-scroll");
|
|
19314
|
-
if (!eventName)
|
|
19315
|
-
return;
|
|
19316
|
-
const metadata = this.extractMetadata(element);
|
|
19317
|
-
this.trackEvent(eventName, {
|
|
19318
|
-
type: "scroll",
|
|
19319
|
-
element: element.tagName.toLowerCase(),
|
|
19320
|
-
threshold,
|
|
19321
|
-
scrollDepth: window.scrollY,
|
|
19322
|
-
visibilityRatio: Math.round(visibilityRatio * 100) / 100,
|
|
19323
|
-
...metadata,
|
|
19324
|
-
});
|
|
19325
|
-
if (this.config.debug) {
|
|
19326
|
-
console.log(`[AutoTracker] Scroll tracked: ${eventName}`, {
|
|
19327
|
-
threshold,
|
|
19328
|
-
visibilityRatio,
|
|
19329
|
-
scrollDepth: window.scrollY,
|
|
19330
|
-
...metadata
|
|
19331
|
-
});
|
|
19332
|
-
}
|
|
19333
|
-
}
|
|
19334
|
-
});
|
|
19335
|
-
};
|
|
19336
|
-
this.handleClick = (event) => {
|
|
19337
|
-
if (!this.config.trackClicks)
|
|
19338
|
-
return;
|
|
19339
|
-
const target = event.target;
|
|
19340
|
-
if (!target || !target.hasAttribute("data-track-click"))
|
|
19341
|
-
return;
|
|
19342
|
-
const eventName = target.getAttribute("data-track-click");
|
|
19343
|
-
if (!eventName)
|
|
19344
|
-
return;
|
|
19345
|
-
const metadata = this.extractMetadata(target);
|
|
19346
|
-
this.trackEvent(eventName, {
|
|
19347
|
-
type: "click",
|
|
19348
|
-
element: target.tagName.toLowerCase(),
|
|
19349
|
-
...metadata,
|
|
19350
|
-
});
|
|
19351
|
-
if (this.config.debug) {
|
|
19352
|
-
console.log(`[AutoTracker] Click tracked: ${eventName}`, {
|
|
19353
|
-
element: target.tagName.toLowerCase(),
|
|
19354
|
-
...metadata
|
|
19355
|
-
});
|
|
19356
|
-
}
|
|
19357
|
-
};
|
|
19358
19279
|
this.sdkInstance = sdkInstance;
|
|
19359
19280
|
this.config = {
|
|
19360
19281
|
enabled: true,
|
|
@@ -19645,18 +19566,44 @@ class AutoTracker {
|
|
|
19645
19566
|
const clickHandler = this.createReactCompatibleClickHandler();
|
|
19646
19567
|
this.delegationHandlers.set('click', clickHandler);
|
|
19647
19568
|
delegationTarget.addEventListener('click', clickHandler, this.getEventOptions('click'));
|
|
19569
|
+
if (this.config.debug) {
|
|
19570
|
+
console.log("[👆 AutoTracker] Click delegation handler added");
|
|
19571
|
+
}
|
|
19648
19572
|
}
|
|
19649
|
-
// Scroll delegation with enhanced detection
|
|
19573
|
+
// CRITICAL FIX: Scroll delegation with enhanced detection
|
|
19650
19574
|
if (this.config.trackScrolls) {
|
|
19651
19575
|
const scrollHandler = this.createEnhancedScrollHandler();
|
|
19652
19576
|
this.delegationHandlers.set('scroll', scrollHandler);
|
|
19577
|
+
// Always use document for scroll events (window doesn't work with removeEventListener)
|
|
19653
19578
|
document.addEventListener('scroll', scrollHandler, this.getEventOptions('scroll'));
|
|
19579
|
+
if (this.config.debug) {
|
|
19580
|
+
console.log("[📜 AutoTracker] Scroll delegation handler added to document");
|
|
19581
|
+
// Immediate test of element detection
|
|
19582
|
+
setTimeout(() => {
|
|
19583
|
+
const scrollElements = this.getCachedScrollElements();
|
|
19584
|
+
console.log(`[📜 AutoTracker] Initial scroll elements check: ${scrollElements.length} found`);
|
|
19585
|
+
if (scrollElements.length > 0) {
|
|
19586
|
+
Array.from(scrollElements).forEach((element, index) => {
|
|
19587
|
+
console.log(`[📜 AutoTracker] Element ${index + 1}:`, {
|
|
19588
|
+
id: element.id || 'no-id',
|
|
19589
|
+
trackEvent: element.getAttribute('data-track-scroll'),
|
|
19590
|
+
threshold: element.getAttribute('data-scroll-threshold') || '0.5',
|
|
19591
|
+
tagName: element.tagName
|
|
19592
|
+
});
|
|
19593
|
+
});
|
|
19594
|
+
}
|
|
19595
|
+
}, 100);
|
|
19596
|
+
}
|
|
19654
19597
|
}
|
|
19655
19598
|
// Setup debounced mutation observer for dynamic content
|
|
19656
19599
|
this.setupIntelligentMutationObserver();
|
|
19657
19600
|
this.isInitialized = true;
|
|
19658
19601
|
if (this.config.debug) {
|
|
19659
|
-
console.log("[✅ AutoTracker] Event delegation setup complete"
|
|
19602
|
+
console.log("[✅ AutoTracker] Event delegation setup complete", {
|
|
19603
|
+
clickHandler: this.delegationHandlers.has('click'),
|
|
19604
|
+
scrollHandler: this.delegationHandlers.has('scroll'),
|
|
19605
|
+
totalHandlers: this.delegationHandlers.size
|
|
19606
|
+
});
|
|
19660
19607
|
}
|
|
19661
19608
|
}
|
|
19662
19609
|
/**
|
|
@@ -19795,33 +19742,50 @@ class AutoTracker {
|
|
|
19795
19742
|
this.scrollThrottle = now;
|
|
19796
19743
|
// Enhanced element finding with caching
|
|
19797
19744
|
const scrollElements = this.getCachedScrollElements();
|
|
19798
|
-
if (this.config.debug
|
|
19799
|
-
console.log(`[📜 AutoTracker]
|
|
19745
|
+
if (this.config.debug) {
|
|
19746
|
+
console.log(`[📜 AutoTracker] Enhanced scroll handler triggered`, {
|
|
19747
|
+
scrollElementsFound: scrollElements.length,
|
|
19748
|
+
scrollY: window.scrollY,
|
|
19800
19749
|
throttleDelay,
|
|
19801
|
-
timeDelta
|
|
19802
|
-
scrollY: window.scrollY
|
|
19750
|
+
timeDelta
|
|
19803
19751
|
});
|
|
19804
19752
|
}
|
|
19805
19753
|
// Process elements with enhanced visibility detection
|
|
19806
|
-
scrollElements.
|
|
19807
|
-
|
|
19808
|
-
|
|
19754
|
+
if (scrollElements.length > 0) {
|
|
19755
|
+
scrollElements.forEach((element) => {
|
|
19756
|
+
this.processScrollElementEnhanced(element);
|
|
19757
|
+
});
|
|
19758
|
+
}
|
|
19759
|
+
else if (this.config.debug) {
|
|
19760
|
+
console.log(`[📜 AutoTracker] No scroll elements found to process`);
|
|
19761
|
+
}
|
|
19809
19762
|
}
|
|
19810
19763
|
catch (error) {
|
|
19811
19764
|
if (this.config.debug) {
|
|
19812
|
-
console.error('[❌ AutoTracker]
|
|
19765
|
+
console.error('[❌ AutoTracker] Enhanced scroll handler error:', error);
|
|
19813
19766
|
}
|
|
19814
19767
|
}
|
|
19815
19768
|
};
|
|
19816
19769
|
}
|
|
19817
19770
|
getCachedScrollElements() {
|
|
19818
19771
|
const now = Date.now();
|
|
19819
|
-
const cacheExpiry =
|
|
19772
|
+
const cacheExpiry = 2000; // Reduced to 2 seconds for faster detection
|
|
19820
19773
|
if (!this.cachedScrollElements || (now - this.lastScrollElementsCheck) > cacheExpiry) {
|
|
19821
19774
|
this.cachedScrollElements = document.querySelectorAll('[data-track-scroll]');
|
|
19822
19775
|
this.lastScrollElementsCheck = now;
|
|
19823
19776
|
if (this.config.debug) {
|
|
19824
|
-
console.log(`[🔄 AutoTracker] Refreshed scroll elements cache: ${this.cachedScrollElements.length} elements`);
|
|
19777
|
+
console.log(`[🔄 AutoTracker] Refreshed scroll elements cache: ${this.cachedScrollElements.length} elements found`);
|
|
19778
|
+
// Log each element found for debugging
|
|
19779
|
+
Array.from(this.cachedScrollElements).forEach((element, index) => {
|
|
19780
|
+
console.log(`[🔄 AutoTracker] Cached element ${index + 1}:`, {
|
|
19781
|
+
id: element.id || 'no-id',
|
|
19782
|
+
className: element.className || 'no-class',
|
|
19783
|
+
trackEvent: element.getAttribute('data-track-scroll'),
|
|
19784
|
+
threshold: element.getAttribute('data-scroll-threshold') || '0.5',
|
|
19785
|
+
tagName: element.tagName,
|
|
19786
|
+
triggered: element.getAttribute('data-scroll-triggered') === 'true'
|
|
19787
|
+
});
|
|
19788
|
+
});
|
|
19825
19789
|
}
|
|
19826
19790
|
}
|
|
19827
19791
|
return this.cachedScrollElements;
|
|
@@ -19832,43 +19796,63 @@ class AutoTracker {
|
|
|
19832
19796
|
processScrollElementEnhanced(element) {
|
|
19833
19797
|
try {
|
|
19834
19798
|
const hasTriggered = element.getAttribute('data-scroll-triggered') === 'true';
|
|
19835
|
-
if (hasTriggered)
|
|
19799
|
+
if (hasTriggered) {
|
|
19800
|
+
if (this.config.debug) {
|
|
19801
|
+
console.log(`[⏭️ AutoTracker] Element already triggered, skipping:`, element.id || element.className || 'no-id');
|
|
19802
|
+
}
|
|
19836
19803
|
return;
|
|
19804
|
+
}
|
|
19837
19805
|
const threshold = parseFloat(element.getAttribute('data-scroll-threshold') || '0.5');
|
|
19838
19806
|
// Enhanced visibility calculation
|
|
19839
19807
|
const rect = element.getBoundingClientRect();
|
|
19840
19808
|
const elementHeight = rect.height;
|
|
19841
19809
|
const windowHeight = window.innerHeight;
|
|
19842
19810
|
// Handle edge cases
|
|
19843
|
-
if (elementHeight <= 0)
|
|
19811
|
+
if (elementHeight <= 0) {
|
|
19812
|
+
if (this.config.debug) {
|
|
19813
|
+
console.log(`[⚠️ AutoTracker] Element has no height, skipping:`, element.id || 'no-id');
|
|
19814
|
+
}
|
|
19844
19815
|
return;
|
|
19816
|
+
}
|
|
19845
19817
|
const visibleTop = Math.max(rect.top, 0);
|
|
19846
19818
|
const visibleBottom = Math.min(rect.bottom, windowHeight);
|
|
19847
19819
|
const visibleHeight = Math.max(0, visibleBottom - visibleTop);
|
|
19848
19820
|
const visibilityRatio = visibleHeight / elementHeight;
|
|
19821
|
+
const eventName = element.getAttribute('data-track-scroll');
|
|
19822
|
+
if (!eventName) {
|
|
19823
|
+
if (this.config.debug) {
|
|
19824
|
+
console.log(`[⚠️ AutoTracker] Element missing data-track-scroll attribute:`, element.id || 'no-id');
|
|
19825
|
+
}
|
|
19826
|
+
return;
|
|
19827
|
+
}
|
|
19849
19828
|
if (this.config.debug) {
|
|
19850
|
-
console.log(`[📊 AutoTracker] Enhanced scroll check:`, {
|
|
19829
|
+
console.log(`[📊 AutoTracker] Enhanced scroll check for "${eventName}":`, {
|
|
19851
19830
|
elementId: element.id || element.className || 'no-id',
|
|
19852
19831
|
rect: {
|
|
19853
19832
|
top: Math.round(rect.top),
|
|
19854
19833
|
bottom: Math.round(rect.bottom),
|
|
19855
19834
|
height: Math.round(elementHeight)
|
|
19856
19835
|
},
|
|
19836
|
+
window: {
|
|
19837
|
+
height: windowHeight,
|
|
19838
|
+
scrollY: window.scrollY
|
|
19839
|
+
},
|
|
19857
19840
|
visibility: {
|
|
19841
|
+
visibleTop,
|
|
19842
|
+
visibleBottom,
|
|
19843
|
+
visibleHeight,
|
|
19858
19844
|
ratio: Math.round(visibilityRatio * 1000) / 1000,
|
|
19859
19845
|
threshold,
|
|
19860
|
-
triggered: hasTriggered
|
|
19861
|
-
|
|
19862
|
-
|
|
19846
|
+
triggered: hasTriggered,
|
|
19847
|
+
shouldTrigger: visibilityRatio >= threshold
|
|
19848
|
+
}
|
|
19863
19849
|
});
|
|
19864
19850
|
}
|
|
19865
19851
|
if (visibilityRatio >= threshold) {
|
|
19852
|
+
// Mark as triggered to prevent duplicate events
|
|
19866
19853
|
element.setAttribute('data-scroll-triggered', 'true');
|
|
19867
|
-
const eventName = element.getAttribute('data-track-scroll');
|
|
19868
|
-
if (!eventName)
|
|
19869
|
-
return;
|
|
19870
19854
|
const metadata = this.extractMetadata(element);
|
|
19871
|
-
|
|
19855
|
+
const eventData = {
|
|
19872
19856
|
type: 'scroll',
|
|
19873
19857
|
element: element.tagName.toLowerCase(),
|
|
19874
19858
|
threshold,
|
|
@@ -19876,20 +19860,22 @@ class AutoTracker {
|
|
|
19876
19860
|
visibilityRatio: Math.round(visibilityRatio * 1000) / 1000,
|
|
19877
19861
|
enhanced: true,
|
|
19878
19862
|
...metadata,
|
|
19879
|
-
}
|
|
19863
|
+
};
|
|
19880
19864
|
if (this.config.debug) {
|
|
19881
|
-
console.log(`[🎯 AutoTracker]
|
|
19882
|
-
|
|
19883
|
-
|
|
19884
|
-
|
|
19885
|
-
|
|
19886
|
-
});
|
|
19865
|
+
console.log(`[🎯 AutoTracker] TRIGGERING scroll event "${eventName}":`, eventData);
|
|
19866
|
+
}
|
|
19867
|
+
this.trackEvent(eventName, eventData);
|
|
19868
|
+
if (this.config.debug) {
|
|
19869
|
+
console.log(`[✅ AutoTracker] Scroll event "${eventName}" sent successfully`);
|
|
19887
19870
|
}
|
|
19888
19871
|
}
|
|
19889
19872
|
}
|
|
19890
19873
|
catch (error) {
|
|
19891
19874
|
if (this.config.debug) {
|
|
19892
|
-
console.error('[❌ AutoTracker] Scroll element processing error:', error
|
|
19875
|
+
console.error('[❌ AutoTracker] Scroll element processing error:', error, {
|
|
19876
|
+
element: element.id || element.className || 'no-id',
|
|
19877
|
+
tagName: element.tagName
|
|
19878
|
+
});
|
|
19893
19879
|
}
|
|
19894
19880
|
}
|
|
19895
19881
|
}
|
|
@@ -20271,6 +20257,8 @@ class AutoTracker {
|
|
|
20271
20257
|
errors
|
|
20272
20258
|
};
|
|
20273
20259
|
}
|
|
20260
|
+
// Legacy handlers removed - now using enhanced event delegation system
|
|
20261
|
+
// All tracking is now handled by createEnhancedScrollHandler and createReactCompatibleClickHandler
|
|
20274
20262
|
/**
|
|
20275
20263
|
* Modern API: Refresh tracking for dynamic content (React/SPA support)
|
|
20276
20264
|
* Industry best practice for SPA route changes
|
|
@@ -20396,6 +20384,33 @@ class AutoTracker {
|
|
|
20396
20384
|
}
|
|
20397
20385
|
}
|
|
20398
20386
|
|
|
20387
|
+
/**
|
|
20388
|
+
* Centralized Session Utilities
|
|
20389
|
+
* Standardized session ID generation for consistency across SDK and backend
|
|
20390
|
+
*/
|
|
20391
|
+
/**
|
|
20392
|
+
* Generate standardized session ID
|
|
20393
|
+
* Format: visitorId_YYYYMMDD_HH
|
|
20394
|
+
* Example: f697a6e1-1aae-48db-bc6a-afc1d2c01852_20251231_03
|
|
20395
|
+
*/
|
|
20396
|
+
function generateSessionId(visitorId, date) {
|
|
20397
|
+
const sessionDate = date || new Date();
|
|
20398
|
+
// Format: YYYYMMDD
|
|
20399
|
+
const year = sessionDate.getFullYear();
|
|
20400
|
+
const month = (sessionDate.getMonth() + 1).toString().padStart(2, '0');
|
|
20401
|
+
const day = sessionDate.getDate().toString().padStart(2, '0');
|
|
20402
|
+
const dateStr = `${year}${month}${day}`;
|
|
20403
|
+
// Format: HH (24-hour format)
|
|
20404
|
+
const hour = sessionDate.getHours().toString().padStart(2, '0');
|
|
20405
|
+
return `${visitorId}_${dateStr}_${hour}`;
|
|
20406
|
+
}
|
|
20407
|
+
/**
|
|
20408
|
+
* Generate session ID for current time
|
|
20409
|
+
*/
|
|
20410
|
+
function generateCurrentSessionId(visitorId) {
|
|
20411
|
+
return generateSessionId(visitorId, new Date());
|
|
20412
|
+
}
|
|
20413
|
+
|
|
20399
20414
|
/**
|
|
20400
20415
|
* Visitor Persistence Manager for SDK
|
|
20401
20416
|
* Implements client-side visitor identification with localStorage camouflage
|
|
@@ -20555,9 +20570,23 @@ class VisitorIdentityManager {
|
|
|
20555
20570
|
// REMOVED: generateVisitorId() and generateVisitorIdFromHash() methods
|
|
20556
20571
|
// SDK no longer generates visitor IDs - only backend does
|
|
20557
20572
|
generateSessionId() {
|
|
20558
|
-
|
|
20559
|
-
|
|
20560
|
-
|
|
20573
|
+
// Try to get existing visitor identity from storage
|
|
20574
|
+
const { value: storedData } = PersistenceManager.get(STORAGE_KEYS.prefs);
|
|
20575
|
+
if (storedData) {
|
|
20576
|
+
try {
|
|
20577
|
+
const parsed = JSON.parse(storedData);
|
|
20578
|
+
if (parsed._v && parsed._vb === true) {
|
|
20579
|
+
// We have a valid visitor ID from backend
|
|
20580
|
+
return generateCurrentSessionId(parsed._v);
|
|
20581
|
+
}
|
|
20582
|
+
}
|
|
20583
|
+
catch (e) {
|
|
20584
|
+
// Invalid data, continue to fallback
|
|
20585
|
+
}
|
|
20586
|
+
}
|
|
20587
|
+
// Fallback for cases where visitor ID is not available yet
|
|
20588
|
+
const tempVisitorId = "temp-" + Date.now().toString(36);
|
|
20589
|
+
return generateCurrentSessionId(tempVisitorId);
|
|
20561
20590
|
}
|
|
20562
20591
|
createCamouflageData(visitorId, sessionId, stableCoreHash, fromBackend = false) {
|
|
20563
20592
|
return {
|
|
@@ -20567,7 +20596,7 @@ class VisitorIdentityManager {
|
|
|
20567
20596
|
analytics: true,
|
|
20568
20597
|
cookies: true,
|
|
20569
20598
|
_v: visitorId, // Hidden visitor ID
|
|
20570
|
-
_s: sessionId, // Hidden session ID
|
|
20599
|
+
_s: sessionId, // Hidden session ID
|
|
20571
20600
|
_sc: stableCoreHash, // Hidden stable core
|
|
20572
20601
|
_vb: fromBackend ? true : undefined, // Flag: visitor ID from backend (v1.7.0+)
|
|
20573
20602
|
ts: Date.now(),
|
|
@@ -20611,7 +20640,9 @@ class VisitorIdentityManager {
|
|
|
20611
20640
|
const { value: storedData, method } = PersistenceManager.get(STORAGE_KEYS.prefs);
|
|
20612
20641
|
if (storedData) {
|
|
20613
20642
|
const existingIdentity = this.extractFromCamouflage(storedData);
|
|
20614
|
-
if (existingIdentity &&
|
|
20643
|
+
if (existingIdentity &&
|
|
20644
|
+
existingIdentity.stableCoreHash === stableCoreHash &&
|
|
20645
|
+
existingIdentity.visitorId) {
|
|
20615
20646
|
// Update last seen time only if we have a valid visitor ID from backend
|
|
20616
20647
|
const updatedCamouflage = this.createCamouflageData(existingIdentity.visitorId, existingIdentity.sessionId, stableCoreHash);
|
|
20617
20648
|
PersistenceManager.set(STORAGE_KEYS.prefs, JSON.stringify(updatedCamouflage));
|
|
@@ -20631,7 +20662,7 @@ class VisitorIdentityManager {
|
|
|
20631
20662
|
stableCoreHash,
|
|
20632
20663
|
deviceFingerprint: params.deviceFingerprint,
|
|
20633
20664
|
persistenceMethod: "memory", // Start with memory, upgrade after backend response
|
|
20634
|
-
confidence: 0.
|
|
20665
|
+
confidence: 0.9,
|
|
20635
20666
|
createdAt: Date.now(),
|
|
20636
20667
|
lastSeen: Date.now(),
|
|
20637
20668
|
reused: false,
|
|
@@ -20646,7 +20677,12 @@ class VisitorIdentityManager {
|
|
|
20646
20677
|
async updateVisitorIdFromBackend(visitorId, stableCoreHash, sessionId) {
|
|
20647
20678
|
try {
|
|
20648
20679
|
// Create or update camouflaged data with backend visitor ID
|
|
20649
|
-
|
|
20680
|
+
// Regenerate session ID with proper visitor ID if needed
|
|
20681
|
+
let currentSessionId = sessionId || this.getCurrentSessionId();
|
|
20682
|
+
// If we have a temp session ID or no session ID, generate a new one with the proper visitor ID
|
|
20683
|
+
if (!currentSessionId || currentSessionId.includes("temp-")) {
|
|
20684
|
+
currentSessionId = generateCurrentSessionId(visitorId);
|
|
20685
|
+
}
|
|
20650
20686
|
const camouflageData = this.createCamouflageData(visitorId, currentSessionId, stableCoreHash, true // Mark as coming from backend
|
|
20651
20687
|
);
|
|
20652
20688
|
const { success, method } = PersistenceManager.set(STORAGE_KEYS.prefs, JSON.stringify(camouflageData));
|
|
@@ -20658,7 +20694,7 @@ class VisitorIdentityManager {
|
|
|
20658
20694
|
return false;
|
|
20659
20695
|
}
|
|
20660
20696
|
catch (error) {
|
|
20661
|
-
console.error(
|
|
20697
|
+
console.error("[VisitorIdentityManager] Failed to update visitor ID from backend:", error);
|
|
20662
20698
|
return false;
|
|
20663
20699
|
}
|
|
20664
20700
|
}
|
|
@@ -21112,36 +21148,17 @@ class ZaplierSDK {
|
|
|
21112
21148
|
}
|
|
21113
21149
|
}
|
|
21114
21150
|
/**
|
|
21115
|
-
* Generate session ID
|
|
21151
|
+
* Generate session ID using standardized format
|
|
21116
21152
|
*/
|
|
21117
21153
|
generateSessionId() {
|
|
21118
|
-
//
|
|
21119
|
-
|
|
21120
|
-
|
|
21121
|
-
// Use page load time + browser fingerprint for session uniqueness within same page load
|
|
21122
|
-
return pageLoadTime.toString(36) + browserFingerprint.substring(0, 8);
|
|
21123
|
-
}
|
|
21124
|
-
/**
|
|
21125
|
-
* Get stable browser characteristics for session ID generation
|
|
21126
|
-
* Uses only stable, privacy-safe values that don't change during session
|
|
21127
|
-
*/
|
|
21128
|
-
getBrowserFingerprint() {
|
|
21129
|
-
const components = [
|
|
21130
|
-
navigator.userAgent || "",
|
|
21131
|
-
navigator.platform || "",
|
|
21132
|
-
screen.width || 0,
|
|
21133
|
-
screen.height || 0,
|
|
21134
|
-
new Date(2024, 0, 1).getTimezoneOffset(),
|
|
21135
|
-
navigator.language || "",
|
|
21136
|
-
navigator.hardwareConcurrency || 0,
|
|
21137
|
-
];
|
|
21138
|
-
const combined = components.join("|");
|
|
21139
|
-
let hash = 0;
|
|
21140
|
-
for (let i = 0; i < combined.length; i++) {
|
|
21141
|
-
const char = combined.charCodeAt(i);
|
|
21142
|
-
hash = ((hash << 5) - hash + char) & 0xffffffff;
|
|
21154
|
+
// Use centralized session generation with current visitor ID
|
|
21155
|
+
if (this.backendVisitorId) {
|
|
21156
|
+
return generateCurrentSessionId(this.backendVisitorId);
|
|
21143
21157
|
}
|
|
21144
|
-
|
|
21158
|
+
// Fallback for cases where backendVisitorId is not available yet
|
|
21159
|
+
// This should be rare and will be updated when visitor ID is available
|
|
21160
|
+
const tempVisitorId = this.visitorId || 'temp-' + Date.now().toString(36);
|
|
21161
|
+
return generateCurrentSessionId(tempVisitorId);
|
|
21145
21162
|
}
|
|
21146
21163
|
/**
|
|
21147
21164
|
* Initialize Anti-Adblock Manager
|
|
@@ -21400,6 +21417,10 @@ class ZaplierSDK {
|
|
|
21400
21417
|
if (response.sessionId) {
|
|
21401
21418
|
this.sessionId = response.sessionId;
|
|
21402
21419
|
}
|
|
21420
|
+
else if (this.backendVisitorId && (!this.sessionId || this.sessionId.includes('temp-'))) {
|
|
21421
|
+
// Generate new session ID now that we have the proper visitor ID
|
|
21422
|
+
this.sessionId = generateCurrentSessionId(this.backendVisitorId);
|
|
21423
|
+
}
|
|
21403
21424
|
return response;
|
|
21404
21425
|
}
|
|
21405
21426
|
catch (error) {
|