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