@zaplier/sdk 1.6.3 → 1.6.5

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 CHANGED
@@ -19773,31 +19773,12 @@ class PersistenceManager {
19773
19773
  PersistenceManager.memoryStore = new Map();
19774
19774
  /**
19775
19775
  * Advanced Visitor Identity Manager with Camouflaged Storage
19776
+ * REFACTORED: No longer generates visitor IDs locally - only manages persistence
19777
+ * Backend is the single source of truth for visitor IDs
19776
19778
  */
19777
19779
  class VisitorIdentityManager {
19778
- generateVisitorId() {
19779
- // Generate UUID v4 format instead of vis_ prefix
19780
- const bytes = crypto.getRandomValues(new Uint8Array(16));
19781
- // Set version 4
19782
- bytes[6] = (bytes[6] & 0x0f) | 0x40;
19783
- // Set variant
19784
- bytes[8] = (bytes[8] & 0x3f) | 0x80;
19785
- const hex = Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
19786
- return `${hex.substr(0, 8)}-${hex.substr(8, 4)}-${hex.substr(12, 4)}-${hex.substr(16, 4)}-${hex.substr(20, 12)}`;
19787
- }
19788
- generateVisitorIdFromHash(hash) {
19789
- // Generate deterministic UUID v4 format from fingerprint hash
19790
- // This ensures same fingerprint = same visitor ID
19791
- const hashExtended = hash.length >= 32 ? hash : (hash + hash + hash + hash).substring(0, 32);
19792
- // Extract hex characters for UUID construction
19793
- const hex = hashExtended.substring(0, 32);
19794
- const chars = hex.split('');
19795
- // Set version 4 and variant bits according to RFC 4122
19796
- chars[12] = '4'; // Version 4
19797
- chars[16] = (parseInt(chars[16] || '0', 16) & 0x3 | 0x8).toString(16); // Variant 10
19798
- // Format as UUID: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
19799
- return `${chars.slice(0, 8).join('')}-${chars.slice(8, 12).join('')}-${chars.slice(12, 16).join('')}-${chars.slice(16, 20).join('')}-${chars.slice(20, 32).join('')}`;
19800
- }
19780
+ // REMOVED: generateVisitorId() and generateVisitorIdFromHash() methods
19781
+ // SDK no longer generates visitor IDs - only backend does
19801
19782
  generateSessionId() {
19802
19783
  return "ses_" + Array.from(crypto.getRandomValues(new Uint8Array(8)))
19803
19784
  .map(b => b.toString(16).padStart(2, '0'))
@@ -19837,14 +19818,18 @@ class VisitorIdentityManager {
19837
19818
  }
19838
19819
  return null;
19839
19820
  }
19821
+ /**
19822
+ * REFACTORED: Get existing visitor identity or prepare for backend response
19823
+ * No longer generates visitor IDs - waits for backend to provide them
19824
+ */
19840
19825
  async getOrCreateVisitorIdentity(params) {
19841
19826
  const { stableCoreHash } = params;
19842
19827
  // Try to recover existing identity from camouflaged storage
19843
19828
  const { value: storedData, method } = PersistenceManager.get(STORAGE_KEYS.prefs);
19844
19829
  if (storedData) {
19845
19830
  const existingIdentity = this.extractFromCamouflage(storedData);
19846
- if (existingIdentity && existingIdentity.stableCoreHash === stableCoreHash) {
19847
- // Update last seen time
19831
+ if (existingIdentity && existingIdentity.stableCoreHash === stableCoreHash && existingIdentity.visitorId) {
19832
+ // Update last seen time only if we have a valid visitor ID from backend
19848
19833
  const updatedCamouflage = this.createCamouflageData(existingIdentity.visitorId, existingIdentity.sessionId, stableCoreHash);
19849
19834
  PersistenceManager.set(STORAGE_KEYS.prefs, JSON.stringify(updatedCamouflage));
19850
19835
  return {
@@ -19855,30 +19840,55 @@ class VisitorIdentityManager {
19855
19840
  };
19856
19841
  }
19857
19842
  }
19858
- // Create new visitor identity (deterministic from fingerprint)
19859
- // Use stableCoreHash for deterministic visitor ID generation
19860
- // This ensures same fingerprint = same visitor ID across devices and sessions
19861
- const deterministicVisitorId = this.generateVisitorIdFromHash(params.stableCoreHash);
19843
+ // CHANGED: Create identity without visitor ID - will be set by backend response
19862
19844
  const newSessionId = params.sessionId || this.generateSessionId();
19863
19845
  const newIdentity = {
19864
- visitorId: deterministicVisitorId,
19846
+ // visitorId: undefined, // Will be set when backend responds
19865
19847
  sessionId: newSessionId,
19866
19848
  stableCoreHash,
19867
19849
  deviceFingerprint: params.deviceFingerprint,
19868
- persistenceMethod: "localStorage",
19850
+ persistenceMethod: "memory", // Start with memory, upgrade after backend response
19869
19851
  confidence: 0.90,
19870
19852
  createdAt: Date.now(),
19871
19853
  lastSeen: Date.now(),
19872
19854
  reused: false,
19855
+ pendingBackendResponse: true, // Flag to indicate waiting for backend
19873
19856
  };
19874
- // Store in camouflaged format
19875
- const camouflageData = this.createCamouflageData(deterministicVisitorId, newSessionId, stableCoreHash);
19876
- const { method: storageMethod } = PersistenceManager.set(STORAGE_KEYS.prefs, JSON.stringify(camouflageData));
19877
- newIdentity.persistenceMethod = storageMethod;
19878
- // Also store device fingerprint cache for faster lookups
19879
- PersistenceManager.set(STORAGE_KEYS.device, params.deviceFingerprint);
19880
19857
  return newIdentity;
19881
19858
  }
19859
+ /**
19860
+ * NEW: Update visitor identity with visitor ID received from backend
19861
+ * This is called after backend responds with the definitive visitor ID
19862
+ */
19863
+ async updateVisitorIdFromBackend(visitorId, stableCoreHash, sessionId) {
19864
+ try {
19865
+ // Create or update camouflaged data with backend visitor ID
19866
+ const currentSessionId = sessionId || this.getCurrentSessionId() || this.generateSessionId();
19867
+ const camouflageData = this.createCamouflageData(visitorId, currentSessionId, stableCoreHash);
19868
+ const { success, method } = PersistenceManager.set(STORAGE_KEYS.prefs, JSON.stringify(camouflageData));
19869
+ if (success) {
19870
+ // Also update device fingerprint cache
19871
+ PersistenceManager.set(STORAGE_KEYS.device, stableCoreHash);
19872
+ return true;
19873
+ }
19874
+ return false;
19875
+ }
19876
+ catch (error) {
19877
+ console.error('[VisitorIdentityManager] Failed to update visitor ID from backend:', error);
19878
+ return false;
19879
+ }
19880
+ }
19881
+ /**
19882
+ * Get current session ID from storage
19883
+ */
19884
+ getCurrentSessionId() {
19885
+ const { value: storedData } = PersistenceManager.get(STORAGE_KEYS.prefs);
19886
+ if (storedData) {
19887
+ const identity = this.extractFromCamouflage(storedData);
19888
+ return identity?.sessionId || null;
19889
+ }
19890
+ return null;
19891
+ }
19882
19892
  // Get current visitor ID without creating new one
19883
19893
  getCurrentVisitorId() {
19884
19894
  const { value: storedData } = PersistenceManager.get(STORAGE_KEYS.prefs);
@@ -19938,7 +19948,7 @@ const DEFAULT_CONFIG = {
19938
19948
  */
19939
19949
  class ZaplierSDK {
19940
19950
  constructor(userConfig) {
19941
- this.version = "1.6.0";
19951
+ this.version = "1.7.0";
19942
19952
  this.isInitialized = false;
19943
19953
  this.eventQueue = [];
19944
19954
  /**
@@ -20365,7 +20375,8 @@ class ZaplierSDK {
20365
20375
  sdkVersion: this.version,
20366
20376
  };
20367
20377
  }
20368
- // Generate or retrieve visitor identity using persistent storage
20378
+ // CHANGED: Check for existing visitor identity but don't set local visitor ID
20379
+ // Only backend generates visitor IDs now
20369
20380
  const visitorIdentity = await this.visitorIdentityManager.getOrCreateVisitorIdentity({
20370
20381
  fingerprintHash: result.data.hash,
20371
20382
  stableCoreHash: result.data.stableCoreHash,
@@ -20374,8 +20385,13 @@ class ZaplierSDK {
20374
20385
  userAgent: navigator.userAgent,
20375
20386
  ipAddress: undefined, // Will be determined server-side
20376
20387
  });
20377
- // Set the persistent visitor ID
20378
- this.visitorId = visitorIdentity.visitorId;
20388
+ // CHANGED: Only use visitor ID if it exists from previous backend response
20389
+ // Do not generate any visitor IDs locally
20390
+ if (visitorIdentity.visitorId && !visitorIdentity.pendingBackendResponse) {
20391
+ this.visitorId = visitorIdentity.visitorId;
20392
+ this.backendVisitorId = visitorIdentity.visitorId; // Ensure consistency
20393
+ }
20394
+ // If no visitor ID exists, leave both null - backend will provide it
20379
20395
  if (this.config.debug) {
20380
20396
  console.log("[Zaplier] Visitor identity resolved:", {
20381
20397
  visitorId: this.visitorId,
@@ -20491,8 +20507,8 @@ class ZaplierSDK {
20491
20507
  try {
20492
20508
  const payload = {
20493
20509
  // workspaceId moved to query parameter
20494
- // Visitor ID (persistido via localStorage camuflado)
20495
- visitorId: this.visitorId,
20510
+ // CHANGED: Only send visitor ID if it came from backend (not locally generated)
20511
+ visitorId: this.backendVisitorId || this.getVisitorId(),
20496
20512
  // Session ID (gerado por sessão)
20497
20513
  sessionId: this.sessionId,
20498
20514
  fingerprintHash: this.fingerprint?.hash,
@@ -20544,11 +20560,25 @@ class ZaplierSDK {
20544
20560
  gdprMode: this.config.gdprMode,
20545
20561
  };
20546
20562
  const response = await this.makeRequest(`/tracking/event?token=${encodeURIComponent(this.config.token)}`, payload);
20547
- // Store backend visitor ID and session ID from response
20563
+ // ENHANCED: Store backend visitor ID in both memory and persistent storage
20548
20564
  if (response.visitorId) {
20549
20565
  this.backendVisitorId = response.visitorId;
20566
+ // Update persistent storage with backend visitor ID
20567
+ if (this.visitorIdentityManager && this.fingerprint?.stableCoreHash) {
20568
+ try {
20569
+ await this.visitorIdentityManager.updateVisitorIdFromBackend(response.visitorId, this.fingerprint.stableCoreHash, this.sessionId);
20570
+ if (this.config.debug) {
20571
+ console.log("[Zaplier] Backend visitor ID saved to localStorage:", response.visitorId);
20572
+ }
20573
+ }
20574
+ catch (error) {
20575
+ if (this.config.debug) {
20576
+ console.error("[Zaplier] Failed to save backend visitor ID to storage:", error);
20577
+ }
20578
+ }
20579
+ }
20550
20580
  if (this.config.debug) {
20551
- console.log("[Zaplier] Backend visitor ID received:", response.visitorId);
20581
+ console.log("[Zaplier] Backend visitor ID received and processed:", response.visitorId);
20552
20582
  }
20553
20583
  }
20554
20584
  if (response.sessionId) {
@@ -20876,10 +20906,30 @@ class ZaplierSDK {
20876
20906
  return this.config.enhancedTracking === "true" && !this.config.gdprMode;
20877
20907
  }
20878
20908
  /**
20879
- * Get visitor ID (real UUID from backend, or fallback)
20909
+ * Get visitor ID (prioritizes backend, then persistent storage)
20910
+ * ENHANCED: Checks persistent storage if memory values are missing
20880
20911
  */
20881
20912
  getVisitorId() {
20882
- return this.backendVisitorId || this.visitorId || null;
20913
+ // Priority 1: Backend visitor ID from memory (most recent)
20914
+ if (this.backendVisitorId) {
20915
+ return this.backendVisitorId;
20916
+ }
20917
+ // Priority 2: Local visitor ID from memory (deprecated but kept for compatibility)
20918
+ if (this.visitorId) {
20919
+ return this.visitorId;
20920
+ }
20921
+ // Priority 3: Check persistent storage for backend visitor ID
20922
+ if (this.visitorIdentityManager) {
20923
+ const storedVisitorId = this.visitorIdentityManager.getCurrentVisitorId();
20924
+ if (storedVisitorId) {
20925
+ // Update memory cache for future calls
20926
+ this.backendVisitorId = storedVisitorId;
20927
+ this.visitorId = storedVisitorId;
20928
+ return storedVisitorId;
20929
+ }
20930
+ }
20931
+ // No visitor ID available - will be set after first backend response
20932
+ return null;
20883
20933
  }
20884
20934
  /**
20885
20935
  * Get visitor information from backend