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