cryptique-sdk 1.0.3 → 1.0.4

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/lib/cjs/index.js CHANGED
@@ -65,6 +65,7 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
65
65
  SESSION: 'cryptique_session', // Primary session storage (sessionStorage)
66
66
  SESSION_BACKUP: 'cryptique_session_backup', // Backup session (localStorage)
67
67
  USER_ID: 'mtm_user_id', // Persistent user ID (localStorage)
68
+ DISTINCT_ID: 'cryptique_distinct_id', // Primary identity (sessionStorage)
68
69
  CONSENT: 'mtm_consent', // User consent flag (localStorage)
69
70
  REFERRER: 'referrer', // Stored referrer (localStorage)
70
71
  LAST_SESSION: 'cryptique_last_session' // Last session backup (localStorage)
@@ -483,6 +484,71 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
483
484
  }
484
485
  },
485
486
 
487
+ /**
488
+ * Generate anonymous distinct_id (long and unique)
489
+ * Format: anon_{timestamp}_{userId}_{uuid}_{random}
490
+ *
491
+ * @param {string} userId - User ID to include in distinct_id
492
+ * @returns {string} Anonymous distinct_id
493
+ */
494
+ generateAnonymousDistinctId(userId) {
495
+ const timestamp = Date.now();
496
+ const random = Math.random().toString(36).substring(2, 18);
497
+ const uuid = this.generateUUIDv4();
498
+ return `anon_${timestamp}_${userId}_${uuid}_${random}`;
499
+ },
500
+
501
+ /**
502
+ * Generate identified distinct_id
503
+ * Format: id_{identifyId}
504
+ *
505
+ * @param {string} identifyId - Identify ID (email, username, etc.)
506
+ * @returns {string} Identified distinct_id
507
+ */
508
+ generateIdentifiedDistinctId(identifyId) {
509
+ return `id_${identifyId}`;
510
+ },
511
+
512
+ /**
513
+ * Get or create distinct_id
514
+ * Checks sessionStorage first, then generates new anonymous distinct_id if not found
515
+ *
516
+ * @returns {string} Current distinct_id
517
+ */
518
+ getDistinctId() {
519
+ try {
520
+ // Check sessionStorage first (primary source)
521
+ let distinctId = sessionStorage.getItem(CONFIG.STORAGE_KEYS.DISTINCT_ID);
522
+
523
+ if (!distinctId) {
524
+ // Generate new anonymous distinct_id
525
+ const userId = this.getUserId();
526
+ distinctId = this.generateAnonymousDistinctId(userId);
527
+ sessionStorage.setItem(CONFIG.STORAGE_KEYS.DISTINCT_ID, distinctId);
528
+ }
529
+
530
+ return distinctId;
531
+ } catch (err) {
532
+ // Fallback: generate temporary distinct_id
533
+ console.warn('Failed to access sessionStorage for distinct_id:', err);
534
+ const userId = this.getUserId();
535
+ return this.generateAnonymousDistinctId(userId);
536
+ }
537
+ },
538
+
539
+ /**
540
+ * Set distinct_id in sessionStorage
541
+ *
542
+ * @param {string} distinctId - Distinct ID to set
543
+ */
544
+ setDistinctId(distinctId) {
545
+ try {
546
+ sessionStorage.setItem(CONFIG.STORAGE_KEYS.DISTINCT_ID, distinctId);
547
+ } catch (err) {
548
+ console.warn('Failed to set distinct_id:', err);
549
+ }
550
+ },
551
+
486
552
  /**
487
553
  * Get user consent status
488
554
  *
@@ -5877,6 +5943,9 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5877
5943
  return { success: false, error: 'Site ID not found' };
5878
5944
  }
5879
5945
 
5946
+ // Get current distinct_id
5947
+ const currentDistinctId = StorageManager.getDistinctId();
5948
+
5880
5949
  // Call API endpoint
5881
5950
  const apiUrl = CONFIG.API.TRACK.replace('/track', '/identify');
5882
5951
  const response = await fetch(apiUrl, {
@@ -5889,6 +5958,7 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5889
5958
  siteId: getCurrentSiteId(),
5890
5959
  sessionId: session.id,
5891
5960
  userId: currentUserId,
5961
+ distinctId: currentDistinctId, // NEW: Pass distinct_id
5892
5962
  identifyId: identifyId.trim()
5893
5963
  })
5894
5964
  });
@@ -5905,20 +5975,31 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5905
5975
 
5906
5976
  const result = await response.json();
5907
5977
 
5908
- // If merge occurred, update localStorage and session data
5909
- if (result.merged && result.newUserId) {
5910
- // Update localStorage with new user ID
5911
- localStorage.setItem(CONFIG.STORAGE_KEYS.USER_ID, result.newUserId);
5978
+ // If merge occurred or distinct_id changed, update sessionStorage and session data
5979
+ if (result.merged && result.newDistinctId) {
5980
+ // Update sessionStorage with new distinct_id
5981
+ StorageManager.setDistinctId(result.newDistinctId);
5912
5982
 
5913
5983
  // Update session data
5914
- sessionData.userId = result.newUserId;
5915
- session.userId = result.newUserId;
5916
- StorageManager.saveSession(session);
5984
+ if (sessionData) {
5985
+ sessionData.distinctId = result.newDistinctId;
5986
+ sessionData.anonymous = false;
5987
+ sessionData.identified = true;
5988
+ }
5917
5989
 
5918
- // Update userSession
5919
- userSession.userId = result.newUserId;
5990
+ console.log(`✅ [Identity] Distinct ID merged: ${currentDistinctId} → ${result.newDistinctId}`);
5991
+ } else if (result.distinctId) {
5992
+ // Update to identified distinct_id
5993
+ StorageManager.setDistinctId(result.distinctId);
5994
+
5995
+ // Update session data
5996
+ if (sessionData) {
5997
+ sessionData.distinctId = result.distinctId;
5998
+ sessionData.anonymous = false;
5999
+ sessionData.identified = true;
6000
+ }
5920
6001
 
5921
- console.log(`✅ [Identity] User merged: ${currentUserId} → ${result.newUserId}`);
6002
+ console.log(`✅ [Identity] Distinct ID updated: ${currentDistinctId} → ${result.distinctId}`);
5922
6003
  }
5923
6004
 
5924
6005
  return result;
@@ -5928,6 +6009,53 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5928
6009
  }
5929
6010
  },
5930
6011
 
6012
+ /**
6013
+ * Reset identity (logout/anonymous)
6014
+ * Generates new anonymous distinct_id and clears identified state
6015
+ *
6016
+ * @returns {Promise<Object>} Result object with new distinct_id
6017
+ */
6018
+ async reset() {
6019
+ try {
6020
+ // Generate new anonymous distinct_id
6021
+ const userId = StorageManager.getUserId();
6022
+ const newDistinctId = StorageManager.generateAnonymousDistinctId(userId);
6023
+
6024
+ // Update sessionStorage
6025
+ StorageManager.setDistinctId(newDistinctId);
6026
+
6027
+ // Update session data
6028
+ const session = StorageManager.loadSession();
6029
+ if (session) {
6030
+ session.distinctId = newDistinctId;
6031
+ session.anonymous = true;
6032
+ session.identified = false;
6033
+ StorageManager.saveSession(session);
6034
+ }
6035
+
6036
+ // Update sessionData if available
6037
+ if (sessionData) {
6038
+ sessionData.distinctId = newDistinctId;
6039
+ sessionData.anonymous = true;
6040
+ sessionData.identified = false;
6041
+ }
6042
+
6043
+ // Clear identify_id from storage (if stored separately)
6044
+ try {
6045
+ sessionStorage.removeItem('cryptique_identify_id');
6046
+ } catch (err) {
6047
+ // Ignore errors
6048
+ }
6049
+
6050
+ console.log(`🔄 [Identity] Reset to anonymous: ${newDistinctId}`);
6051
+
6052
+ return { success: true, distinctId: newDistinctId };
6053
+ } catch (error) {
6054
+ console.error('❌ [Identity] Error in reset():', error);
6055
+ return { success: false, error: error.message };
6056
+ }
6057
+ },
6058
+
5931
6059
  /**
5932
6060
  * Set wallet address for current user
5933
6061
  *
@@ -5975,6 +6103,9 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5975
6103
 
5976
6104
  console.log(`✅ [Identity] Wallet address set in sessionData: ${trimmedWalletAddress}`);
5977
6105
 
6106
+ // Get current distinct_id
6107
+ const currentDistinctId = StorageManager.getDistinctId();
6108
+
5978
6109
  // Call API endpoint to update user_identity and session in database
5979
6110
  // This handles merging and immediate session update if session exists
5980
6111
  const apiUrl = CONFIG.API.TRACK.replace('/track', '/wallet-address');
@@ -5988,6 +6119,7 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5988
6119
  siteId: getCurrentSiteId(),
5989
6120
  sessionId: session.id,
5990
6121
  userId: currentUserId,
6122
+ distinctId: currentDistinctId, // NEW: Pass distinct_id
5991
6123
  walletAddress: trimmedWalletAddress
5992
6124
  })
5993
6125
  });
@@ -6976,6 +7108,7 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
6976
7108
  // Identity Functions
6977
7109
  identify: IdentityManager.identify.bind(IdentityManager),
6978
7110
  walletAddress: IdentityManager.walletAddress.bind(IdentityManager),
7111
+ reset: IdentityManager.reset.bind(IdentityManager),
6979
7112
 
6980
7113
  // People Functions (Custom Properties)
6981
7114
  people: {
@@ -7291,6 +7424,22 @@ const CryptiqueSDK = {
7291
7424
  throw new Error('SDK not initialized. Call init() first.');
7292
7425
  },
7293
7426
 
7427
+ /**
7428
+ * Reset user identity to anonymous
7429
+ *
7430
+ * Generates a new anonymous distinct_id and clears identification.
7431
+ * Useful for privacy/GDPR compliance when user wants to reset their identity.
7432
+ *
7433
+ * @returns {Promise<Object>} Result object with success status and new distinctId
7434
+ */
7435
+ async reset() {
7436
+ const instance = this.getInstance();
7437
+ if (instance && instance.reset) {
7438
+ return await instance.reset();
7439
+ }
7440
+ throw new Error('SDK not initialized. Call init() first.');
7441
+ },
7442
+
7294
7443
  /**
7295
7444
  * Track a custom event
7296
7445
  * @param {string} eventName - Name of the event
package/lib/esm/index.js CHANGED
@@ -63,6 +63,7 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
63
63
  SESSION: 'cryptique_session', // Primary session storage (sessionStorage)
64
64
  SESSION_BACKUP: 'cryptique_session_backup', // Backup session (localStorage)
65
65
  USER_ID: 'mtm_user_id', // Persistent user ID (localStorage)
66
+ DISTINCT_ID: 'cryptique_distinct_id', // Primary identity (sessionStorage)
66
67
  CONSENT: 'mtm_consent', // User consent flag (localStorage)
67
68
  REFERRER: 'referrer', // Stored referrer (localStorage)
68
69
  LAST_SESSION: 'cryptique_last_session' // Last session backup (localStorage)
@@ -481,6 +482,71 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
481
482
  }
482
483
  },
483
484
 
485
+ /**
486
+ * Generate anonymous distinct_id (long and unique)
487
+ * Format: anon_{timestamp}_{userId}_{uuid}_{random}
488
+ *
489
+ * @param {string} userId - User ID to include in distinct_id
490
+ * @returns {string} Anonymous distinct_id
491
+ */
492
+ generateAnonymousDistinctId(userId) {
493
+ const timestamp = Date.now();
494
+ const random = Math.random().toString(36).substring(2, 18);
495
+ const uuid = this.generateUUIDv4();
496
+ return `anon_${timestamp}_${userId}_${uuid}_${random}`;
497
+ },
498
+
499
+ /**
500
+ * Generate identified distinct_id
501
+ * Format: id_{identifyId}
502
+ *
503
+ * @param {string} identifyId - Identify ID (email, username, etc.)
504
+ * @returns {string} Identified distinct_id
505
+ */
506
+ generateIdentifiedDistinctId(identifyId) {
507
+ return `id_${identifyId}`;
508
+ },
509
+
510
+ /**
511
+ * Get or create distinct_id
512
+ * Checks sessionStorage first, then generates new anonymous distinct_id if not found
513
+ *
514
+ * @returns {string} Current distinct_id
515
+ */
516
+ getDistinctId() {
517
+ try {
518
+ // Check sessionStorage first (primary source)
519
+ let distinctId = sessionStorage.getItem(CONFIG.STORAGE_KEYS.DISTINCT_ID);
520
+
521
+ if (!distinctId) {
522
+ // Generate new anonymous distinct_id
523
+ const userId = this.getUserId();
524
+ distinctId = this.generateAnonymousDistinctId(userId);
525
+ sessionStorage.setItem(CONFIG.STORAGE_KEYS.DISTINCT_ID, distinctId);
526
+ }
527
+
528
+ return distinctId;
529
+ } catch (err) {
530
+ // Fallback: generate temporary distinct_id
531
+ console.warn('Failed to access sessionStorage for distinct_id:', err);
532
+ const userId = this.getUserId();
533
+ return this.generateAnonymousDistinctId(userId);
534
+ }
535
+ },
536
+
537
+ /**
538
+ * Set distinct_id in sessionStorage
539
+ *
540
+ * @param {string} distinctId - Distinct ID to set
541
+ */
542
+ setDistinctId(distinctId) {
543
+ try {
544
+ sessionStorage.setItem(CONFIG.STORAGE_KEYS.DISTINCT_ID, distinctId);
545
+ } catch (err) {
546
+ console.warn('Failed to set distinct_id:', err);
547
+ }
548
+ },
549
+
484
550
  /**
485
551
  * Get user consent status
486
552
  *
@@ -5875,6 +5941,9 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5875
5941
  return { success: false, error: 'Site ID not found' };
5876
5942
  }
5877
5943
 
5944
+ // Get current distinct_id
5945
+ const currentDistinctId = StorageManager.getDistinctId();
5946
+
5878
5947
  // Call API endpoint
5879
5948
  const apiUrl = CONFIG.API.TRACK.replace('/track', '/identify');
5880
5949
  const response = await fetch(apiUrl, {
@@ -5887,6 +5956,7 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5887
5956
  siteId: getCurrentSiteId(),
5888
5957
  sessionId: session.id,
5889
5958
  userId: currentUserId,
5959
+ distinctId: currentDistinctId, // NEW: Pass distinct_id
5890
5960
  identifyId: identifyId.trim()
5891
5961
  })
5892
5962
  });
@@ -5903,20 +5973,31 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5903
5973
 
5904
5974
  const result = await response.json();
5905
5975
 
5906
- // If merge occurred, update localStorage and session data
5907
- if (result.merged && result.newUserId) {
5908
- // Update localStorage with new user ID
5909
- localStorage.setItem(CONFIG.STORAGE_KEYS.USER_ID, result.newUserId);
5976
+ // If merge occurred or distinct_id changed, update sessionStorage and session data
5977
+ if (result.merged && result.newDistinctId) {
5978
+ // Update sessionStorage with new distinct_id
5979
+ StorageManager.setDistinctId(result.newDistinctId);
5910
5980
 
5911
5981
  // Update session data
5912
- sessionData.userId = result.newUserId;
5913
- session.userId = result.newUserId;
5914
- StorageManager.saveSession(session);
5982
+ if (sessionData) {
5983
+ sessionData.distinctId = result.newDistinctId;
5984
+ sessionData.anonymous = false;
5985
+ sessionData.identified = true;
5986
+ }
5915
5987
 
5916
- // Update userSession
5917
- userSession.userId = result.newUserId;
5988
+ console.log(`✅ [Identity] Distinct ID merged: ${currentDistinctId} → ${result.newDistinctId}`);
5989
+ } else if (result.distinctId) {
5990
+ // Update to identified distinct_id
5991
+ StorageManager.setDistinctId(result.distinctId);
5992
+
5993
+ // Update session data
5994
+ if (sessionData) {
5995
+ sessionData.distinctId = result.distinctId;
5996
+ sessionData.anonymous = false;
5997
+ sessionData.identified = true;
5998
+ }
5918
5999
 
5919
- console.log(`✅ [Identity] User merged: ${currentUserId} → ${result.newUserId}`);
6000
+ console.log(`✅ [Identity] Distinct ID updated: ${currentDistinctId} → ${result.distinctId}`);
5920
6001
  }
5921
6002
 
5922
6003
  return result;
@@ -5926,6 +6007,53 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5926
6007
  }
5927
6008
  },
5928
6009
 
6010
+ /**
6011
+ * Reset identity (logout/anonymous)
6012
+ * Generates new anonymous distinct_id and clears identified state
6013
+ *
6014
+ * @returns {Promise<Object>} Result object with new distinct_id
6015
+ */
6016
+ async reset() {
6017
+ try {
6018
+ // Generate new anonymous distinct_id
6019
+ const userId = StorageManager.getUserId();
6020
+ const newDistinctId = StorageManager.generateAnonymousDistinctId(userId);
6021
+
6022
+ // Update sessionStorage
6023
+ StorageManager.setDistinctId(newDistinctId);
6024
+
6025
+ // Update session data
6026
+ const session = StorageManager.loadSession();
6027
+ if (session) {
6028
+ session.distinctId = newDistinctId;
6029
+ session.anonymous = true;
6030
+ session.identified = false;
6031
+ StorageManager.saveSession(session);
6032
+ }
6033
+
6034
+ // Update sessionData if available
6035
+ if (sessionData) {
6036
+ sessionData.distinctId = newDistinctId;
6037
+ sessionData.anonymous = true;
6038
+ sessionData.identified = false;
6039
+ }
6040
+
6041
+ // Clear identify_id from storage (if stored separately)
6042
+ try {
6043
+ sessionStorage.removeItem('cryptique_identify_id');
6044
+ } catch (err) {
6045
+ // Ignore errors
6046
+ }
6047
+
6048
+ console.log(`🔄 [Identity] Reset to anonymous: ${newDistinctId}`);
6049
+
6050
+ return { success: true, distinctId: newDistinctId };
6051
+ } catch (error) {
6052
+ console.error('❌ [Identity] Error in reset():', error);
6053
+ return { success: false, error: error.message };
6054
+ }
6055
+ },
6056
+
5929
6057
  /**
5930
6058
  * Set wallet address for current user
5931
6059
  *
@@ -5973,6 +6101,9 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5973
6101
 
5974
6102
  console.log(`✅ [Identity] Wallet address set in sessionData: ${trimmedWalletAddress}`);
5975
6103
 
6104
+ // Get current distinct_id
6105
+ const currentDistinctId = StorageManager.getDistinctId();
6106
+
5976
6107
  // Call API endpoint to update user_identity and session in database
5977
6108
  // This handles merging and immediate session update if session exists
5978
6109
  const apiUrl = CONFIG.API.TRACK.replace('/track', '/wallet-address');
@@ -5986,6 +6117,7 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
5986
6117
  siteId: getCurrentSiteId(),
5987
6118
  sessionId: session.id,
5988
6119
  userId: currentUserId,
6120
+ distinctId: currentDistinctId, // NEW: Pass distinct_id
5989
6121
  walletAddress: trimmedWalletAddress
5990
6122
  })
5991
6123
  });
@@ -6974,6 +7106,7 @@ if (window.Cryptique && window.Cryptique.initialized) ; else {
6974
7106
  // Identity Functions
6975
7107
  identify: IdentityManager.identify.bind(IdentityManager),
6976
7108
  walletAddress: IdentityManager.walletAddress.bind(IdentityManager),
7109
+ reset: IdentityManager.reset.bind(IdentityManager),
6977
7110
 
6978
7111
  // People Functions (Custom Properties)
6979
7112
  people: {
@@ -7289,6 +7422,22 @@ const CryptiqueSDK = {
7289
7422
  throw new Error('SDK not initialized. Call init() first.');
7290
7423
  },
7291
7424
 
7425
+ /**
7426
+ * Reset user identity to anonymous
7427
+ *
7428
+ * Generates a new anonymous distinct_id and clears identification.
7429
+ * Useful for privacy/GDPR compliance when user wants to reset their identity.
7430
+ *
7431
+ * @returns {Promise<Object>} Result object with success status and new distinctId
7432
+ */
7433
+ async reset() {
7434
+ const instance = this.getInstance();
7435
+ if (instance && instance.reset) {
7436
+ return await instance.reset();
7437
+ }
7438
+ throw new Error('SDK not initialized. Call init() first.');
7439
+ },
7440
+
7292
7441
  /**
7293
7442
  * Track a custom event
7294
7443
  * @param {string} eventName - Name of the event
@@ -149,6 +149,12 @@ export default class CryptiqueSDK {
149
149
  */
150
150
  walletAddress(walletAddress: string): Promise<{ success: boolean; merged?: boolean; newUserId?: string; error?: string }>;
151
151
 
152
+ /**
153
+ * Reset user identity to anonymous
154
+ * Generates a new anonymous distinct_id and clears identification
155
+ */
156
+ reset(): Promise<{ success: boolean; distinctId?: string; error?: string }>;
157
+
152
158
  /**
153
159
  * Set tracking consent
154
160
  */
package/lib/umd/index.js CHANGED
@@ -69,6 +69,7 @@
69
69
  SESSION: 'cryptique_session', // Primary session storage (sessionStorage)
70
70
  SESSION_BACKUP: 'cryptique_session_backup', // Backup session (localStorage)
71
71
  USER_ID: 'mtm_user_id', // Persistent user ID (localStorage)
72
+ DISTINCT_ID: 'cryptique_distinct_id', // Primary identity (sessionStorage)
72
73
  CONSENT: 'mtm_consent', // User consent flag (localStorage)
73
74
  REFERRER: 'referrer', // Stored referrer (localStorage)
74
75
  LAST_SESSION: 'cryptique_last_session' // Last session backup (localStorage)
@@ -487,6 +488,71 @@
487
488
  }
488
489
  },
489
490
 
491
+ /**
492
+ * Generate anonymous distinct_id (long and unique)
493
+ * Format: anon_{timestamp}_{userId}_{uuid}_{random}
494
+ *
495
+ * @param {string} userId - User ID to include in distinct_id
496
+ * @returns {string} Anonymous distinct_id
497
+ */
498
+ generateAnonymousDistinctId(userId) {
499
+ const timestamp = Date.now();
500
+ const random = Math.random().toString(36).substring(2, 18);
501
+ const uuid = this.generateUUIDv4();
502
+ return `anon_${timestamp}_${userId}_${uuid}_${random}`;
503
+ },
504
+
505
+ /**
506
+ * Generate identified distinct_id
507
+ * Format: id_{identifyId}
508
+ *
509
+ * @param {string} identifyId - Identify ID (email, username, etc.)
510
+ * @returns {string} Identified distinct_id
511
+ */
512
+ generateIdentifiedDistinctId(identifyId) {
513
+ return `id_${identifyId}`;
514
+ },
515
+
516
+ /**
517
+ * Get or create distinct_id
518
+ * Checks sessionStorage first, then generates new anonymous distinct_id if not found
519
+ *
520
+ * @returns {string} Current distinct_id
521
+ */
522
+ getDistinctId() {
523
+ try {
524
+ // Check sessionStorage first (primary source)
525
+ let distinctId = sessionStorage.getItem(CONFIG.STORAGE_KEYS.DISTINCT_ID);
526
+
527
+ if (!distinctId) {
528
+ // Generate new anonymous distinct_id
529
+ const userId = this.getUserId();
530
+ distinctId = this.generateAnonymousDistinctId(userId);
531
+ sessionStorage.setItem(CONFIG.STORAGE_KEYS.DISTINCT_ID, distinctId);
532
+ }
533
+
534
+ return distinctId;
535
+ } catch (err) {
536
+ // Fallback: generate temporary distinct_id
537
+ console.warn('Failed to access sessionStorage for distinct_id:', err);
538
+ const userId = this.getUserId();
539
+ return this.generateAnonymousDistinctId(userId);
540
+ }
541
+ },
542
+
543
+ /**
544
+ * Set distinct_id in sessionStorage
545
+ *
546
+ * @param {string} distinctId - Distinct ID to set
547
+ */
548
+ setDistinctId(distinctId) {
549
+ try {
550
+ sessionStorage.setItem(CONFIG.STORAGE_KEYS.DISTINCT_ID, distinctId);
551
+ } catch (err) {
552
+ console.warn('Failed to set distinct_id:', err);
553
+ }
554
+ },
555
+
490
556
  /**
491
557
  * Get user consent status
492
558
  *
@@ -5881,6 +5947,9 @@
5881
5947
  return { success: false, error: 'Site ID not found' };
5882
5948
  }
5883
5949
 
5950
+ // Get current distinct_id
5951
+ const currentDistinctId = StorageManager.getDistinctId();
5952
+
5884
5953
  // Call API endpoint
5885
5954
  const apiUrl = CONFIG.API.TRACK.replace('/track', '/identify');
5886
5955
  const response = await fetch(apiUrl, {
@@ -5893,6 +5962,7 @@
5893
5962
  siteId: getCurrentSiteId(),
5894
5963
  sessionId: session.id,
5895
5964
  userId: currentUserId,
5965
+ distinctId: currentDistinctId, // NEW: Pass distinct_id
5896
5966
  identifyId: identifyId.trim()
5897
5967
  })
5898
5968
  });
@@ -5909,20 +5979,31 @@
5909
5979
 
5910
5980
  const result = await response.json();
5911
5981
 
5912
- // If merge occurred, update localStorage and session data
5913
- if (result.merged && result.newUserId) {
5914
- // Update localStorage with new user ID
5915
- localStorage.setItem(CONFIG.STORAGE_KEYS.USER_ID, result.newUserId);
5982
+ // If merge occurred or distinct_id changed, update sessionStorage and session data
5983
+ if (result.merged && result.newDistinctId) {
5984
+ // Update sessionStorage with new distinct_id
5985
+ StorageManager.setDistinctId(result.newDistinctId);
5916
5986
 
5917
5987
  // Update session data
5918
- sessionData.userId = result.newUserId;
5919
- session.userId = result.newUserId;
5920
- StorageManager.saveSession(session);
5988
+ if (sessionData) {
5989
+ sessionData.distinctId = result.newDistinctId;
5990
+ sessionData.anonymous = false;
5991
+ sessionData.identified = true;
5992
+ }
5921
5993
 
5922
- // Update userSession
5923
- userSession.userId = result.newUserId;
5994
+ console.log(`✅ [Identity] Distinct ID merged: ${currentDistinctId} → ${result.newDistinctId}`);
5995
+ } else if (result.distinctId) {
5996
+ // Update to identified distinct_id
5997
+ StorageManager.setDistinctId(result.distinctId);
5998
+
5999
+ // Update session data
6000
+ if (sessionData) {
6001
+ sessionData.distinctId = result.distinctId;
6002
+ sessionData.anonymous = false;
6003
+ sessionData.identified = true;
6004
+ }
5924
6005
 
5925
- console.log(`✅ [Identity] User merged: ${currentUserId} → ${result.newUserId}`);
6006
+ console.log(`✅ [Identity] Distinct ID updated: ${currentDistinctId} → ${result.distinctId}`);
5926
6007
  }
5927
6008
 
5928
6009
  return result;
@@ -5932,6 +6013,53 @@
5932
6013
  }
5933
6014
  },
5934
6015
 
6016
+ /**
6017
+ * Reset identity (logout/anonymous)
6018
+ * Generates new anonymous distinct_id and clears identified state
6019
+ *
6020
+ * @returns {Promise<Object>} Result object with new distinct_id
6021
+ */
6022
+ async reset() {
6023
+ try {
6024
+ // Generate new anonymous distinct_id
6025
+ const userId = StorageManager.getUserId();
6026
+ const newDistinctId = StorageManager.generateAnonymousDistinctId(userId);
6027
+
6028
+ // Update sessionStorage
6029
+ StorageManager.setDistinctId(newDistinctId);
6030
+
6031
+ // Update session data
6032
+ const session = StorageManager.loadSession();
6033
+ if (session) {
6034
+ session.distinctId = newDistinctId;
6035
+ session.anonymous = true;
6036
+ session.identified = false;
6037
+ StorageManager.saveSession(session);
6038
+ }
6039
+
6040
+ // Update sessionData if available
6041
+ if (sessionData) {
6042
+ sessionData.distinctId = newDistinctId;
6043
+ sessionData.anonymous = true;
6044
+ sessionData.identified = false;
6045
+ }
6046
+
6047
+ // Clear identify_id from storage (if stored separately)
6048
+ try {
6049
+ sessionStorage.removeItem('cryptique_identify_id');
6050
+ } catch (err) {
6051
+ // Ignore errors
6052
+ }
6053
+
6054
+ console.log(`🔄 [Identity] Reset to anonymous: ${newDistinctId}`);
6055
+
6056
+ return { success: true, distinctId: newDistinctId };
6057
+ } catch (error) {
6058
+ console.error('❌ [Identity] Error in reset():', error);
6059
+ return { success: false, error: error.message };
6060
+ }
6061
+ },
6062
+
5935
6063
  /**
5936
6064
  * Set wallet address for current user
5937
6065
  *
@@ -5979,6 +6107,9 @@
5979
6107
 
5980
6108
  console.log(`✅ [Identity] Wallet address set in sessionData: ${trimmedWalletAddress}`);
5981
6109
 
6110
+ // Get current distinct_id
6111
+ const currentDistinctId = StorageManager.getDistinctId();
6112
+
5982
6113
  // Call API endpoint to update user_identity and session in database
5983
6114
  // This handles merging and immediate session update if session exists
5984
6115
  const apiUrl = CONFIG.API.TRACK.replace('/track', '/wallet-address');
@@ -5992,6 +6123,7 @@
5992
6123
  siteId: getCurrentSiteId(),
5993
6124
  sessionId: session.id,
5994
6125
  userId: currentUserId,
6126
+ distinctId: currentDistinctId, // NEW: Pass distinct_id
5995
6127
  walletAddress: trimmedWalletAddress
5996
6128
  })
5997
6129
  });
@@ -6980,6 +7112,7 @@
6980
7112
  // Identity Functions
6981
7113
  identify: IdentityManager.identify.bind(IdentityManager),
6982
7114
  walletAddress: IdentityManager.walletAddress.bind(IdentityManager),
7115
+ reset: IdentityManager.reset.bind(IdentityManager),
6983
7116
 
6984
7117
  // People Functions (Custom Properties)
6985
7118
  people: {
@@ -7295,6 +7428,22 @@
7295
7428
  throw new Error('SDK not initialized. Call init() first.');
7296
7429
  },
7297
7430
 
7431
+ /**
7432
+ * Reset user identity to anonymous
7433
+ *
7434
+ * Generates a new anonymous distinct_id and clears identification.
7435
+ * Useful for privacy/GDPR compliance when user wants to reset their identity.
7436
+ *
7437
+ * @returns {Promise<Object>} Result object with success status and new distinctId
7438
+ */
7439
+ async reset() {
7440
+ const instance = this.getInstance();
7441
+ if (instance && instance.reset) {
7442
+ return await instance.reset();
7443
+ }
7444
+ throw new Error('SDK not initialized. Call init() first.');
7445
+ },
7446
+
7298
7447
  /**
7299
7448
  * Track a custom event
7300
7449
  * @param {string} eventName - Name of the event
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cryptique-sdk",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "type": "module",
5
5
  "description": "Cryptique Analytics SDK - Comprehensive web analytics and user tracking for modern web applications",
6
6
  "main": "lib/cjs/index.js",