@zaplier/sdk 1.6.1 → 1.6.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 +293 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +293 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/sdk.js +293 -1
- package/dist/sdk.js.map +1 -1
- package/dist/sdk.min.js +1 -1
- package/dist/src/modules/visitor-persistence.d.ts +20 -88
- package/dist/src/modules/visitor-persistence.d.ts.map +1 -1
- package/dist/src/sdk.d.ts +2 -1
- package/dist/src/sdk.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -19612,6 +19612,272 @@ class AutoTracker {
|
|
|
19612
19612
|
}
|
|
19613
19613
|
}
|
|
19614
19614
|
|
|
19615
|
+
/**
|
|
19616
|
+
* Visitor Persistence Manager for SDK
|
|
19617
|
+
* Implements client-side visitor identification with localStorage camouflage
|
|
19618
|
+
*/
|
|
19619
|
+
// Camuflaged storage keys to avoid detection/blocking
|
|
19620
|
+
const STORAGE_KEYS = {
|
|
19621
|
+
session: "__zp_s", // Session identifier
|
|
19622
|
+
visitor: "__zp_v", // Visitor identifier (camuflado)
|
|
19623
|
+
device: "__zp_d", // Device fingerprint cache
|
|
19624
|
+
prefs: "__zp_p", // User preferences (decoy storage)
|
|
19625
|
+
analytics: "__zp_a", // Analytics preferences (additional decoy)
|
|
19626
|
+
};
|
|
19627
|
+
/**
|
|
19628
|
+
* Multi-layer persistence manager with fallbacks
|
|
19629
|
+
*/
|
|
19630
|
+
class PersistenceManager {
|
|
19631
|
+
// 1. LocalStorage (primary) - Most persistent
|
|
19632
|
+
static setLocal(key, value) {
|
|
19633
|
+
try {
|
|
19634
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
19635
|
+
localStorage.setItem(key, value);
|
|
19636
|
+
return true;
|
|
19637
|
+
}
|
|
19638
|
+
}
|
|
19639
|
+
catch (e) {
|
|
19640
|
+
// Storage disabled/private mode
|
|
19641
|
+
}
|
|
19642
|
+
return false;
|
|
19643
|
+
}
|
|
19644
|
+
static getLocal(key) {
|
|
19645
|
+
try {
|
|
19646
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
19647
|
+
return localStorage.getItem(key);
|
|
19648
|
+
}
|
|
19649
|
+
}
|
|
19650
|
+
catch (e) {
|
|
19651
|
+
// Storage disabled/private mode
|
|
19652
|
+
}
|
|
19653
|
+
return null;
|
|
19654
|
+
}
|
|
19655
|
+
// 2. SessionStorage (secondary) - Session-only
|
|
19656
|
+
static setSession(key, value) {
|
|
19657
|
+
try {
|
|
19658
|
+
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
19659
|
+
sessionStorage.setItem(key, value);
|
|
19660
|
+
return true;
|
|
19661
|
+
}
|
|
19662
|
+
}
|
|
19663
|
+
catch (e) {
|
|
19664
|
+
// Storage disabled/private mode
|
|
19665
|
+
}
|
|
19666
|
+
return false;
|
|
19667
|
+
}
|
|
19668
|
+
static getSession(key) {
|
|
19669
|
+
try {
|
|
19670
|
+
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
19671
|
+
return sessionStorage.getItem(key);
|
|
19672
|
+
}
|
|
19673
|
+
}
|
|
19674
|
+
catch (e) {
|
|
19675
|
+
// Storage disabled/private mode
|
|
19676
|
+
}
|
|
19677
|
+
return null;
|
|
19678
|
+
}
|
|
19679
|
+
// 3. Cookie (tertiary) - Cross-session with expiration
|
|
19680
|
+
static setCookie(key, value, days = 365) {
|
|
19681
|
+
try {
|
|
19682
|
+
if (typeof document !== "undefined") {
|
|
19683
|
+
const expires = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toUTCString();
|
|
19684
|
+
document.cookie = `${key}=${value}; expires=${expires}; path=/; SameSite=Lax`;
|
|
19685
|
+
return true;
|
|
19686
|
+
}
|
|
19687
|
+
}
|
|
19688
|
+
catch (e) {
|
|
19689
|
+
// Cookies disabled
|
|
19690
|
+
}
|
|
19691
|
+
return false;
|
|
19692
|
+
}
|
|
19693
|
+
static getCookie(key) {
|
|
19694
|
+
try {
|
|
19695
|
+
if (typeof document !== "undefined") {
|
|
19696
|
+
const name = key + "=";
|
|
19697
|
+
const decodedCookie = decodeURIComponent(document.cookie);
|
|
19698
|
+
const ca = decodedCookie.split(";");
|
|
19699
|
+
for (let i = 0; i < ca.length; i++) {
|
|
19700
|
+
let c = ca[i];
|
|
19701
|
+
if (c) {
|
|
19702
|
+
while (c.charAt(0) === " ") {
|
|
19703
|
+
c = c.substring(1);
|
|
19704
|
+
}
|
|
19705
|
+
if (c.indexOf(name) === 0) {
|
|
19706
|
+
return c.substring(name.length, c.length);
|
|
19707
|
+
}
|
|
19708
|
+
}
|
|
19709
|
+
}
|
|
19710
|
+
}
|
|
19711
|
+
}
|
|
19712
|
+
catch (e) {
|
|
19713
|
+
// Cookies disabled
|
|
19714
|
+
}
|
|
19715
|
+
return null;
|
|
19716
|
+
}
|
|
19717
|
+
// 4. Memory (fallback) - Current session only
|
|
19718
|
+
static setMemory(key, value) {
|
|
19719
|
+
this.memoryStore.set(key, value);
|
|
19720
|
+
return true;
|
|
19721
|
+
}
|
|
19722
|
+
static getMemory(key) {
|
|
19723
|
+
return this.memoryStore.get(key) || null;
|
|
19724
|
+
}
|
|
19725
|
+
// Multi-layer get with fallbacks
|
|
19726
|
+
static get(key) {
|
|
19727
|
+
// Try localStorage first (most persistent)
|
|
19728
|
+
let value = this.getLocal(key);
|
|
19729
|
+
if (value)
|
|
19730
|
+
return { value, method: "localStorage" };
|
|
19731
|
+
// Try sessionStorage (session-only)
|
|
19732
|
+
value = this.getSession(key);
|
|
19733
|
+
if (value)
|
|
19734
|
+
return { value, method: "sessionStorage" };
|
|
19735
|
+
// Try cookies (cross-session)
|
|
19736
|
+
value = this.getCookie(key);
|
|
19737
|
+
if (value)
|
|
19738
|
+
return { value, method: "cookie" };
|
|
19739
|
+
// Try memory (current session)
|
|
19740
|
+
value = this.getMemory(key);
|
|
19741
|
+
if (value)
|
|
19742
|
+
return { value, method: "memory" };
|
|
19743
|
+
return { value: null, method: "none" };
|
|
19744
|
+
}
|
|
19745
|
+
// Multi-layer set with fallbacks
|
|
19746
|
+
static set(key, value) {
|
|
19747
|
+
// Try localStorage first (most persistent)
|
|
19748
|
+
if (this.setLocal(key, value)) {
|
|
19749
|
+
return { success: true, method: "localStorage" };
|
|
19750
|
+
}
|
|
19751
|
+
// Try sessionStorage (session-only)
|
|
19752
|
+
if (this.setSession(key, value)) {
|
|
19753
|
+
return { success: true, method: "sessionStorage" };
|
|
19754
|
+
}
|
|
19755
|
+
// Try cookies (cross-session)
|
|
19756
|
+
if (this.setCookie(key, value)) {
|
|
19757
|
+
return { success: true, method: "cookie" };
|
|
19758
|
+
}
|
|
19759
|
+
// Fallback to memory (current session)
|
|
19760
|
+
this.setMemory(key, value);
|
|
19761
|
+
return { success: true, method: "memory" };
|
|
19762
|
+
}
|
|
19763
|
+
}
|
|
19764
|
+
PersistenceManager.memoryStore = new Map();
|
|
19765
|
+
/**
|
|
19766
|
+
* Advanced Visitor Identity Manager with Camouflaged Storage
|
|
19767
|
+
*/
|
|
19768
|
+
class VisitorIdentityManager {
|
|
19769
|
+
generateVisitorId() {
|
|
19770
|
+
return "vis_" + Array.from(crypto.getRandomValues(new Uint8Array(16)))
|
|
19771
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
19772
|
+
.join('');
|
|
19773
|
+
}
|
|
19774
|
+
generateSessionId() {
|
|
19775
|
+
return "ses_" + Array.from(crypto.getRandomValues(new Uint8Array(8)))
|
|
19776
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
19777
|
+
.join('') + "_" + Date.now().toString(36);
|
|
19778
|
+
}
|
|
19779
|
+
createCamouflageData(visitorId, sessionId, stableCoreHash) {
|
|
19780
|
+
return {
|
|
19781
|
+
theme: "auto",
|
|
19782
|
+
lang: (navigator.language || "en-US").substring(0, 2),
|
|
19783
|
+
tz: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
19784
|
+
analytics: true,
|
|
19785
|
+
cookies: true,
|
|
19786
|
+
_v: visitorId, // Hidden visitor ID
|
|
19787
|
+
_s: sessionId, // Hidden session ID
|
|
19788
|
+
_sc: stableCoreHash, // Hidden stable core
|
|
19789
|
+
ts: Date.now(),
|
|
19790
|
+
};
|
|
19791
|
+
}
|
|
19792
|
+
extractFromCamouflage(data) {
|
|
19793
|
+
try {
|
|
19794
|
+
const parsed = JSON.parse(data);
|
|
19795
|
+
if (parsed._v && parsed._s && parsed._sc) {
|
|
19796
|
+
return {
|
|
19797
|
+
visitorId: parsed._v,
|
|
19798
|
+
sessionId: parsed._s,
|
|
19799
|
+
stableCoreHash: parsed._sc,
|
|
19800
|
+
persistenceMethod: "localStorage",
|
|
19801
|
+
confidence: 0.95,
|
|
19802
|
+
createdAt: parsed.ts || Date.now(),
|
|
19803
|
+
lastSeen: Date.now(),
|
|
19804
|
+
reused: true,
|
|
19805
|
+
};
|
|
19806
|
+
}
|
|
19807
|
+
}
|
|
19808
|
+
catch (e) {
|
|
19809
|
+
// Invalid data
|
|
19810
|
+
}
|
|
19811
|
+
return null;
|
|
19812
|
+
}
|
|
19813
|
+
async getOrCreateVisitorIdentity(params) {
|
|
19814
|
+
const { stableCoreHash } = params;
|
|
19815
|
+
// Try to recover existing identity from camouflaged storage
|
|
19816
|
+
const { value: storedData, method } = PersistenceManager.get(STORAGE_KEYS.prefs);
|
|
19817
|
+
if (storedData) {
|
|
19818
|
+
const existingIdentity = this.extractFromCamouflage(storedData);
|
|
19819
|
+
if (existingIdentity && existingIdentity.stableCoreHash === stableCoreHash) {
|
|
19820
|
+
// Update last seen time
|
|
19821
|
+
const updatedCamouflage = this.createCamouflageData(existingIdentity.visitorId, existingIdentity.sessionId, stableCoreHash);
|
|
19822
|
+
PersistenceManager.set(STORAGE_KEYS.prefs, JSON.stringify(updatedCamouflage));
|
|
19823
|
+
return {
|
|
19824
|
+
...existingIdentity,
|
|
19825
|
+
persistenceMethod: method,
|
|
19826
|
+
lastSeen: Date.now(),
|
|
19827
|
+
reused: true,
|
|
19828
|
+
};
|
|
19829
|
+
}
|
|
19830
|
+
}
|
|
19831
|
+
// Create new visitor identity
|
|
19832
|
+
const newVisitorId = this.generateVisitorId();
|
|
19833
|
+
const newSessionId = params.sessionId || this.generateSessionId();
|
|
19834
|
+
const newIdentity = {
|
|
19835
|
+
visitorId: newVisitorId,
|
|
19836
|
+
sessionId: newSessionId,
|
|
19837
|
+
stableCoreHash,
|
|
19838
|
+
deviceFingerprint: params.deviceFingerprint,
|
|
19839
|
+
persistenceMethod: "localStorage",
|
|
19840
|
+
confidence: 0.90,
|
|
19841
|
+
createdAt: Date.now(),
|
|
19842
|
+
lastSeen: Date.now(),
|
|
19843
|
+
reused: false,
|
|
19844
|
+
};
|
|
19845
|
+
// Store in camouflaged format
|
|
19846
|
+
const camouflageData = this.createCamouflageData(newVisitorId, newSessionId, stableCoreHash);
|
|
19847
|
+
const { method: storageMethod } = PersistenceManager.set(STORAGE_KEYS.prefs, JSON.stringify(camouflageData));
|
|
19848
|
+
newIdentity.persistenceMethod = storageMethod;
|
|
19849
|
+
// Also store device fingerprint cache for faster lookups
|
|
19850
|
+
PersistenceManager.set(STORAGE_KEYS.device, params.deviceFingerprint);
|
|
19851
|
+
return newIdentity;
|
|
19852
|
+
}
|
|
19853
|
+
// Get current visitor ID without creating new one
|
|
19854
|
+
getCurrentVisitorId() {
|
|
19855
|
+
const { value: storedData } = PersistenceManager.get(STORAGE_KEYS.prefs);
|
|
19856
|
+
if (storedData) {
|
|
19857
|
+
const identity = this.extractFromCamouflage(storedData);
|
|
19858
|
+
return identity?.visitorId || null;
|
|
19859
|
+
}
|
|
19860
|
+
return null;
|
|
19861
|
+
}
|
|
19862
|
+
// Clear all stored identity data
|
|
19863
|
+
clearIdentity() {
|
|
19864
|
+
// Remove from all storage layers
|
|
19865
|
+
try {
|
|
19866
|
+
PersistenceManager.setLocal(STORAGE_KEYS.prefs, "");
|
|
19867
|
+
PersistenceManager.setLocal(STORAGE_KEYS.device, "");
|
|
19868
|
+
PersistenceManager.setSession(STORAGE_KEYS.prefs, "");
|
|
19869
|
+
PersistenceManager.setSession(STORAGE_KEYS.device, "");
|
|
19870
|
+
PersistenceManager.setCookie(STORAGE_KEYS.prefs, "", -1); // Expire immediately
|
|
19871
|
+
PersistenceManager.setCookie(STORAGE_KEYS.device, "", -1);
|
|
19872
|
+
PersistenceManager.setMemory(STORAGE_KEYS.prefs, "");
|
|
19873
|
+
PersistenceManager.setMemory(STORAGE_KEYS.device, "");
|
|
19874
|
+
}
|
|
19875
|
+
catch (e) {
|
|
19876
|
+
// Silent fail
|
|
19877
|
+
}
|
|
19878
|
+
}
|
|
19879
|
+
}
|
|
19880
|
+
|
|
19615
19881
|
/**
|
|
19616
19882
|
* Zaplier SDK v1.0.0
|
|
19617
19883
|
* 100% Cookieless Analytics Tracking
|
|
@@ -20047,10 +20313,12 @@ class ZaplierSDK {
|
|
|
20047
20313
|
}
|
|
20048
20314
|
/**
|
|
20049
20315
|
* Collect fingerprint and generate visitor ID (IMPROVED - 2024)
|
|
20050
|
-
* Enhanced with better incognito detection
|
|
20316
|
+
* Enhanced with better incognito detection and localStorage persistence
|
|
20051
20317
|
*/
|
|
20052
20318
|
async collectFingerprint() {
|
|
20053
20319
|
try {
|
|
20320
|
+
// Initialize visitor identity manager
|
|
20321
|
+
this.visitorIdentityManager = new VisitorIdentityManager();
|
|
20054
20322
|
// Use appropriate fingerprinting based on GDPR mode
|
|
20055
20323
|
const result = this.config.gdprMode
|
|
20056
20324
|
? await getLightweightFingerprint()
|
|
@@ -20068,6 +20336,26 @@ class ZaplierSDK {
|
|
|
20068
20336
|
sdkVersion: this.version,
|
|
20069
20337
|
};
|
|
20070
20338
|
}
|
|
20339
|
+
// Generate or retrieve visitor identity using persistent storage
|
|
20340
|
+
const visitorIdentity = await this.visitorIdentityManager.getOrCreateVisitorIdentity({
|
|
20341
|
+
fingerprintHash: result.data.hash,
|
|
20342
|
+
stableCoreHash: result.data.stableCoreHash,
|
|
20343
|
+
deviceFingerprint: result.data.hash,
|
|
20344
|
+
sessionId: this.sessionId,
|
|
20345
|
+
userAgent: navigator.userAgent,
|
|
20346
|
+
ipAddress: undefined, // Will be determined server-side
|
|
20347
|
+
});
|
|
20348
|
+
// Set the persistent visitor ID
|
|
20349
|
+
this.visitorId = visitorIdentity.visitorId;
|
|
20350
|
+
if (this.config.debug) {
|
|
20351
|
+
console.log("[Zaplier] Visitor identity resolved:", {
|
|
20352
|
+
visitorId: this.visitorId,
|
|
20353
|
+
sessionId: this.sessionId,
|
|
20354
|
+
persistenceMethod: visitorIdentity.persistenceMethod,
|
|
20355
|
+
confidence: visitorIdentity.confidence,
|
|
20356
|
+
isNewVisitor: !visitorIdentity.reused,
|
|
20357
|
+
});
|
|
20358
|
+
}
|
|
20071
20359
|
if (this.config.debug) {
|
|
20072
20360
|
console.log("[Zaplier] Fingerprint collected:", {
|
|
20073
20361
|
components: result.collectedComponents,
|
|
@@ -20174,6 +20462,10 @@ class ZaplierSDK {
|
|
|
20174
20462
|
try {
|
|
20175
20463
|
const payload = {
|
|
20176
20464
|
// workspaceId moved to query parameter
|
|
20465
|
+
// Visitor ID (persistido via localStorage camuflado)
|
|
20466
|
+
visitorId: this.visitorId,
|
|
20467
|
+
// Session ID (gerado por sessão)
|
|
20468
|
+
sessionId: this.sessionId,
|
|
20177
20469
|
fingerprintHash: this.fingerprint?.hash,
|
|
20178
20470
|
stableCoreHash: this.fingerprint?.stableCoreHash,
|
|
20179
20471
|
stableCoreVector: this.fingerprint?.stableCoreVector,
|