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