@zaplier/sdk 1.1.2 → 1.1.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/dist/index.esm.js CHANGED
@@ -5690,156 +5690,51 @@ async function collectFingerprint(options = {}) {
5690
5690
  timezone: browser?.timezone || "unknown",
5691
5691
  // PRIORITY 3: Primary language only (most stable language preference)
5692
5692
  // Remove secondary languages as they can change more frequently
5693
- primaryLanguage: Array.isArray(browser?.languages) &&
5694
- browser.languages.length > 0 &&
5695
- browser.languages[0]
5696
- ? browser.languages[0].toLowerCase().split("-")[0] // Only language code (en, pt, fr), not region
5697
- : "unknown",
5693
+ primaryLanguage: (() => {
5694
+ try {
5695
+ const languages = browser?.languages;
5696
+ if (Array.isArray(languages) && languages.length > 0 && languages[0]) {
5697
+ return languages[0].toLowerCase().split("-")[0]; // Only language code (en, pt, fr), not region
5698
+ }
5699
+ // Fallback to navigator.language if browser.languages is not available
5700
+ if (typeof navigator !== 'undefined' && navigator.language) {
5701
+ return navigator.language.toLowerCase().split("-")[0];
5702
+ }
5703
+ return "unknown";
5704
+ }
5705
+ catch {
5706
+ return "unknown";
5707
+ }
5708
+ })(),
5698
5709
  // PRIORITY 4: Platform (ultra-stable - OS doesn't change)
5699
5710
  platform: (browser?.platform || "unknown").toLowerCase(),
5700
5711
  // PRIORITY 5: Device type (critical for differentiation, ultra-stable)
5701
5712
  deviceType,
5702
- // PRIORITY 6: Enhanced screen resolution - ONLY for mobile/tablet
5703
- // CRITICAL: Desktop screen detection is UNSTABLE with DevTools (viewport changes)
5704
- // For desktop, we rely on hardware + display + platform for differentiation
5705
- // For mobile/tablet, screen is STABLE (no DevTools viewport issues)
5706
- screen: screen && (deviceType === "mobile" || deviceType === "tablet")
5707
- ? (() => {
5708
- // Use enhanced screen buckets for modern display landscape
5709
- const dims = [screen.width, screen.height].sort((a, b) => b - a);
5710
- const w = dims[0];
5711
- const h = dims[1];
5712
- // Enhanced screen bucketing based on 2024 display standards
5713
- const getScreenBucket = (width, height) => {
5714
- // Ultra-high resolution displays (2024: 8K, 5K, etc.)
5715
- if (width >= 7680)
5716
- return "8k"; // 8K displays
5717
- if (width >= 5120)
5718
- return "5k"; // 5K displays (iMac, etc.)
5719
- if (width >= 4096)
5720
- return "4k_cinema"; // Cinema 4K
5721
- if (width >= 3840)
5722
- return "4k_uhd"; // 4K UHD standard
5723
- if (width >= 3440)
5724
- return "ultrawide"; // Ultrawide QHD
5725
- if (width >= 2880)
5726
- return "retina_4k"; // Retina 4K/5K scaled
5727
- if (width >= 2560)
5728
- return "qhd"; // QHD/WQHD
5729
- // Standard high-resolution displays
5730
- if (width >= 2048)
5731
- return "qxga"; // QXGA
5732
- if (width >= 1920)
5733
- return "fhd"; // Full HD 1080p
5734
- if (width >= 1680)
5735
- return "wsxga+"; // WSXGA+
5736
- if (width >= 1600)
5737
- return "uxga"; // UXGA
5738
- if (width >= 1440)
5739
- return "wxga++"; // WXGA++
5740
- if (width >= 1366)
5741
- return "hd"; // HD 720p
5742
- if (width >= 1280)
5743
- return "sxga"; // SXGA
5744
- // Tablet and mobile displays
5745
- if (width >= 1024)
5746
- return "xga"; // XGA (tablets)
5747
- if (width >= 768)
5748
- return "svga"; // SVGA (small tablets)
5749
- if (width >= 640)
5750
- return "vga"; // VGA (phones)
5751
- if (width >= 480)
5752
- return "hvga"; // HVGA (older phones)
5753
- if (width >= 320)
5754
- return "qvga"; // QVGA (legacy phones)
5755
- return "minimal"; // Sub-QVGA
5756
- };
5757
- // Enhanced aspect ratio classification for device type hints
5758
- const getAspectRatioClass = (width, height) => {
5759
- if (height === 0)
5760
- return "unknown";
5761
- const ratio = width / height;
5762
- // Ultra-wide displays (gaming, productivity)
5763
- if (ratio >= 3.0)
5764
- return "super_ultrawide"; // 32:9+
5765
- if (ratio >= 2.3)
5766
- return "ultrawide"; // 21:9
5767
- if (ratio >= 2.0)
5768
- return "wide"; // 18:9
5769
- // Standard desktop ratios
5770
- if (ratio >= 1.7 && ratio <= 1.8)
5771
- return "standard"; // 16:9
5772
- if (ratio >= 1.6 && ratio <= 1.67)
5773
- return "classic"; // 16:10, 5:3
5774
- if (ratio >= 1.3 && ratio <= 1.35)
5775
- return "traditional"; // 4:3
5776
- // Mobile/portrait ratios
5777
- if (ratio >= 0.5 && ratio <= 0.8)
5778
- return "mobile_portrait"; // Phones in portrait
5779
- if (ratio >= 0.4 && ratio <= 0.5)
5780
- return "tall_mobile"; // Modern tall phones
5781
- return "custom"; // Non-standard ratio
5782
- };
5783
- // Ensure w and h are valid numbers
5784
- const width = w || 0;
5785
- const height = h || 0;
5786
- // Screen density class based on common DPR patterns
5787
- const getDensityClass = (pixelRatio) => {
5788
- if (!pixelRatio)
5789
- return "standard";
5790
- if (pixelRatio >= 3.0)
5791
- return "ultra_high"; // iPhone Plus, high-end Android
5792
- if (pixelRatio >= 2.0)
5793
- return "high"; // Retina, standard high-DPI
5794
- if (pixelRatio >= 1.5)
5795
- return "medium"; // Mid-range displays
5796
- if (pixelRatio >= 1.25)
5797
- return "enhanced"; // Slightly enhanced DPI
5798
- return "standard"; // Standard 1x displays
5799
- };
5800
- // CRITICAL: Do NOT include exact dimensions in stableCoreVector for mobile!
5801
- // Reason: Screen dimensions change when:
5802
- // - Chrome address bar appears/disappears (scroll behavior)
5803
- // - Virtual keyboard opens/closes
5804
- // - Screen rotates (portrait ↔ landscape)
5805
- // - Browser zoom changes
5806
- // These changes would cause stableCoreHash to change, breaking visitor identification
5807
- //
5808
- // INSTEAD: Use ONLY stable screen characteristics (bucket, aspect, density)
5809
- // For device differentiation (S22 vs A54), use:
5810
- // - screenFrame (bezel measurements)
5811
- // - Combination of bucket + hardware + display
5812
- // - Vector similarity in IdentityResolver
5813
- return {
5814
- bucket: getScreenBucket(width),
5815
- aspectClass: getAspectRatioClass(width, height),
5816
- densityClass: getDensityClass(screen.pixelRatio || window.devicePixelRatio),
5817
- // Simplified ratio for matching (rounded to prevent micro-variations)
5818
- ratio: height > 0 ? Math.round((width / height) * 100) / 100 : 0,
5819
- // Size category for general device classification
5820
- sizeCategory: width >= 2560
5821
- ? "large"
5822
- : width >= 1920
5823
- ? "desktop"
5824
- : width >= 1024
5825
- ? "laptop"
5826
- : width >= 768
5827
- ? "tablet"
5828
- : "mobile",
5829
- // ❌ REMOVED: exact dimensions (causes instability on mobile)
5830
- // Device differentiation is now handled by:
5831
- // 1. screenFrame (bezel measurements - stable)
5832
- // 2. hardware + display combination
5833
- // 3. Vector similarity in IdentityResolver
5834
- };
5835
- })()
5836
- : {
5837
- bucket: "unknown",
5838
- aspectClass: "unknown",
5839
- densityClass: "unknown",
5840
- ratio: 0,
5841
- sizeCategory: "unknown",
5842
- },
5713
+ // PRIORITY 6: Screen - REMOVED FROM stableCoreVector
5714
+ // REASON: Screen properties are UNSTABLE across all device types:
5715
+ //
5716
+ // Desktop:
5717
+ // - DevTools changes viewport (lateral vs bottom)
5718
+ // - Browser zoom changes dimensions
5719
+ // - Window resize changes available space
5720
+ //
5721
+ // Mobile:
5722
+ // - Address bar appears/disappears on scroll
5723
+ // - Virtual keyboard opens/closes
5724
+ // - Screen rotation (portrait ↔ landscape)
5725
+ // - Pull-to-refresh changes viewport
5726
+ //
5727
+ // RESULT: Even "bucket" detection is unreliable due to viewport changes
5728
+ //
5729
+ // SOLUTION: Device differentiation now relies ONLY on:
5730
+ // 1. screenFrame (bezel measurements - MORE stable)
5731
+ // 2. hardware (cores, memory, arch - STABLE)
5732
+ // 3. display (color depth, gamut - STABLE)
5733
+ // 4. platform + deviceType + ua (ULTRA-STABLE)
5734
+ // 5. timezone + primaryLanguage (USER-STABLE)
5735
+ //
5736
+ // Note: screen is still collected in full fingerprint for analytics,
5737
+ // but excluded from stableCoreHash to ensure visitor identification stability
5843
5738
  // CRITICAL: Do NOT include availability flags (canvas/webgl/audio) in stableCoreVector
5844
5739
  // These flags can change between requests due to timeouts, permissions, or hardware issues
5845
5740
  // and would cause the stableCoreHash to change, breaking visitor identification
@@ -6030,12 +5925,13 @@ async function collectFingerprint(options = {}) {
6030
5925
  };
6031
5926
  // ADDITIONAL ENTROPY: Add a deterministic but unique component based on ultra-stable signals
6032
5927
  // This helps prevent collisions while maintaining deterministic behavior
5928
+ // Note: screen removed as it's unstable (viewport changes)
6033
5929
  const entropyComponents = [
6034
5930
  coreVector.ua || "",
6035
5931
  coreVector.platform || "",
6036
5932
  coreVector.deviceType || "",
6037
- coreVector.screen?.bucket || "",
6038
5933
  coreVector.timezone || "",
5934
+ coreVector.primaryLanguage || "",
6039
5935
  ].filter(Boolean);
6040
5936
  if (entropyComponents.length >= 3) {
6041
5937
  // Create a stable entropy string from the most stable components
@@ -6060,15 +5956,18 @@ async function collectFingerprint(options = {}) {
6060
5956
  // - Screen frame (can vary slightly)
6061
5957
  // - Vendor flavors (can change)
6062
5958
  // - Exact hardware values (use buckets)
6063
- // DEBUG: Log coreVector components to identify DevTools instability
5959
+ // DEBUG: Log coreVector components for monitoring
6064
5960
  if (opts.debug ||
6065
5961
  (typeof window !== "undefined" && window._rabbitTrackerDebug)) {
6066
5962
  console.log("[RabbitTracker DEBUG] coreVector components:", {
6067
5963
  ua: coreVector.ua,
6068
5964
  platform: coreVector.platform,
6069
5965
  deviceType: coreVector.deviceType,
6070
- screenBucket: coreVector.screen?.bucket,
6071
5966
  timezone: coreVector.timezone,
5967
+ primaryLanguage: coreVector.primaryLanguage,
5968
+ hasHardware: !!coreVector.hardware,
5969
+ hasDisplay: !!coreVector.display,
5970
+ hasScreenFrame: !!coreVector.screenFrame,
6072
5971
  _entropy: coreVector._entropy,
6073
5972
  });
6074
5973
  }
@@ -6114,7 +6013,10 @@ async function collectFingerprint(options = {}) {
6114
6013
  ua: coreVector.ua,
6115
6014
  deviceType: coreVector.deviceType,
6116
6015
  platform: coreVector.platform,
6117
- screenBucket: coreVector.screen?.bucket,
6016
+ timezone: coreVector.timezone,
6017
+ hasScreenFrame: !!coreVector.screenFrame,
6018
+ hardwareClass: coreVector.hardware?.class,
6019
+ displayClass: coreVector.display?.class,
6118
6020
  totalComponentsInHash: Object.keys(enhancedComponentValues).length,
6119
6021
  });
6120
6022
  }