Cordova SDK - 数据隐私

文件

遵守数据隐私法

通过通知Singular用户同意选择GDPR、CCPA、COPPA和其他消费者隐私法规,实施符合隐私法规的数据收集。

当用户同意或拒绝与第三方共享其信息时,使用 Singular 的隐私方法来传达他们的选择。这将确保遵守《加州消费者隐私法案》(CCPA)等法规,并使合作伙伴尊重用户的隐私偏好。

了解更多信息:有关Singular如何处理隐私同意的详细信息,请参阅用户隐私和限制数据共享


限制数据共享

控制第三方数据共享

通知Singular用户是否同意使用limitDataSharing()方法与第三方合作伙伴共享个人数据。

方法签名

cordova.plugins.SingularCordovaSdk.limitDataSharing(
  shouldLimitDataSharing: boolean
): void

参数

  • false:用户已选择并同意共享其数据
  • true: true:用户已退出,不同意共享其数据

重要:虽然此方法是可选的,但它会影响属性数据的共享。有些合作伙伴只有在明确通知用户已选择加入时,才会共享完整的归因信息。

有关完整的方法文档,请参阅limitDataSharing 参考资料


使用示例

根据用户隐私偏好实施数据共享控制。

JavaScript
document.addEventListener('deviceready', onDeviceReady, false);

function onDeviceReady() {
  // User has opted in to share their data
  var onUserOptedInToDataSharing = function() {
    cordova.plugins.SingularCordovaSdk.limitDataSharing(false);
    console.log('Data sharing enabled');
  };
  
  // User has opted out and declined to share their data
  var onUserOptedOutOfDataSharing = function() {
    cordova.plugins.SingularCordovaSdk.limitDataSharing(true);
    console.log('Data sharing limited');
  };
  
  // Set based on user preference
  var handlePrivacyConsent = function(userConsented) {
    // Pass inverse: false = opted in, true = opted out
    cordova.plugins.SingularCordovaSdk.limitDataSharing(!userConsented);
    
    console.log('Data sharing: ' + (userConsented ? 'Enabled' : 'Limited'));
  };
  
  // Example: Ask user for consent
  askUserForPrivacyConsent(function(consented) {
    handlePrivacyConsent(consented);
  });
}

function askUserForPrivacyConsent(callback) {
  // Show custom dialog to user
  if (confirm('Do you consent to share your data with third parties?')) {
    callback(true);
  } else {
    callback(false);
  }
}

如何使用

Singular在用户隐私回邮中使用此设置,并将其传递给需要遵守法规的合作伙伴。


GDPR 合规方法

管理用户跟踪同意和控制 SDK 功能,以符合 GDPR(通用数据保护条例)和其他隐私法规。

跟踪同意管理

跟踪同意

通过向 Singular 服务器发送 GDPR 选入事件,记录用户对跟踪的明确同意。

方法签名

cordova.plugins.SingularCordovaSdk.trackingOptIn(): void

何时使用

  • GDPR 合规性:当用户明确同意在受 GDPR 监管的地区进行跟踪时调用
  • 同意记录:在 Singular 系统中将用户标记为已提供 GDPR 同意
  • 默认行为:如果没有此调用,SDK 会继续跟踪,但不会明确记录同意信息

有关完整的方法文档,请参阅trackingOptIn 参考资料


实施示例

在用户通过应用程序的同意对话框接受跟踪同意后调用trackingOptIn()

JavaScript
document.addEventListener('deviceready', initializeGDPR, false);

function initializeGDPR() {
  checkStoredConsent();
}

function checkStoredConsent() {
  // Check if user has previously provided consent
  var consent = localStorage.getItem('gdpr_consent');
  
  if (consent === null) {
    // No stored preference - show consent dialog
    showGDPRConsentDialog();
  } else if (consent === 'true') {
    // User previously consented - apply setting
    onUserAcceptedTracking();
  }
}

function showGDPRConsentDialog() {
  // Show custom dialog to user
  var message = 'We would like your permission to track app usage and improve your experience.';
  
  if (confirm(message)) {
    onUserAcceptedTracking();
  } else {
    onUserDeclinedTracking();
  }
}

function onUserAcceptedTracking() {
  // Record user consent with Singular
  cordova.plugins.SingularCordovaSdk.trackingOptIn();
  console.log('User opted in to tracking');
  
  // Save preference locally
  localStorage.setItem('gdpr_consent', 'true');
}

function onUserDeclinedTracking() {
  console.log('User declined tracking');
  localStorage.setItem('gdpr_consent', 'false');
}

跟踪控制方法

停止所有跟踪

完全禁用当前用户在此设备上的所有 SDK 跟踪活动。

方法签名

cordova.plugins.SingularCordovaSdk.stopAllTracking(): void

严重警告:此方法会永久禁用 SDK,直到调用resumeAllTracking() 。禁用状态会在应用程序重启时持续存在,只能通过编程方式逆转。

行为

  • 立即生效:立即停止所有跟踪、事件报告和数据收集功能
  • 持续状态:即使在应用程序关闭和重新打开后也会保持禁用状态
  • 无法自动重置:必须明确调用resumeAllTracking() 才能重新启用

有关完整的方法文档,请参阅stopAllTracking 参考资料


实施示例

当用户拒绝同意或通过隐私设置选择退出时停止跟踪。

JavaScript
// User declined all tracking
function onUserDeclinedTracking() {
  cordova.plugins.SingularCordovaSdk.stopAllTracking();
  console.log('All tracking stopped');
  
  // Store preference
  localStorage.setItem('tracking_enabled', 'false');
}

// Handle user opt-out from settings menu
function handlePrivacySettingsChange(trackingEnabled) {
  if (!trackingEnabled) {
    cordova.plugins.SingularCordovaSdk.stopAllTracking();
    console.log('Privacy settings: Tracking disabled');
    localStorage.setItem('tracking_enabled', 'false');
  }
}

恢复全部跟踪

在使用stopAllTracking() 停止跟踪后重新启用跟踪。

方法签名

cordova.plugins.SingularCordovaSdk.resumeAllTracking(): void

使用案例

  • 同意变更:用户更改隐私偏好并选择恢复跟踪
  • 隐私设置:用户通过应用程序设置菜单更新同意
  • 地区合规性:当用户转移到非监管区域时重新启用跟踪功能

有关完整的方法文档,请参阅resumeAllTracking 参考资料


实施示例

当用户重新选择或更新隐私偏好时恢复跟踪。

JavaScript
// User opted back in to tracking
function onUserResumedTracking() {
  cordova.plugins.SingularCordovaSdk.resumeAllTracking();
  console.log('Tracking resumed');
  
  // Update stored preference
  localStorage.setItem('tracking_enabled', 'true');
}

// Handle consent update from settings
function handlePrivacySettingsChange(trackingEnabled) {
  if (trackingEnabled) {
    cordova.plugins.SingularCordovaSdk.resumeAllTracking();
    console.log('Privacy settings: Tracking enabled');
    localStorage.setItem('tracking_enabled', 'true');
  }
}

IsAllTrackingStopped

检查当前用户的跟踪是否已被禁用。

方法签名

cordova.plugins.SingularCordovaSdk.isAllTrackingStopped(
  success: Function
): void

返回值

  • true:当前已通过stopAllTracking()停止跟踪
  • false:跟踪处于活动状态(从未停止或恢复

有关该方法的完整文档,请参阅isAllTrackingStopped 参考资料


实现示例

检查跟踪状态,使 UI 状态与 SDK 跟踪状态同步。

JavaScript
document.addEventListener('deviceready', initializePrivacyUI, false);

function initializePrivacyUI() {
  updatePrivacyUI();
}

// Check current tracking status
function isTrackingEnabled(callback) {
  cordova.plugins.SingularCordovaSdk.isAllTrackingStopped(function(isStopped) {
    callback(!isStopped);
  });
}

// Display privacy status in settings
function getPrivacyStatusText(callback) {
  cordova.plugins.SingularCordovaSdk.isAllTrackingStopped(function(isStopped) {
    var text = isStopped ? 'Tracking: Disabled' : 'Tracking: Enabled';
    callback(text);
  });
}

// Sync UI with tracking state
function updatePrivacyUI() {
  cordova.plugins.SingularCordovaSdk.isAllTrackingStopped(function(isStopped) {
    var statusElement = document.getElementById('tracking-status');
    var toggleElement = document.getElementById('tracking-toggle');
    
    if (statusElement) {
      statusElement.textContent = isStopped ? 'Tracking: Disabled' : 'Tracking: Enabled';
    }
    
    if (toggleElement) {
      toggleElement.checked = !isStopped;
    }
    
    console.log('Current tracking state: ' + (isStopped ? 'Stopped' : 'Active'));
  });
}

// Handle toggle change from UI
function onTrackingToggleChanged(enabled) {
  if (enabled) {
    cordova.plugins.SingularCordovaSdk.resumeAllTracking();
  } else {
    cordova.plugins.SingularCordovaSdk.stopAllTracking();
  }
  
  updatePrivacyUI();
}

儿童隐私保护

执行 COPPA(儿童在线隐私保护法案)合规性,并在用户未满 13 周岁时通知 Singular 以保护儿童隐私。

跟踪 13 岁以下用户

启用儿童隐私保护

通知Singular用户未满13岁,以遵守COPPA和其他儿童隐私法规。

方法签名

cordova.plugins.SingularCordovaSdk.trackingUnder13(): void

合规要求

  • COPPA 合规性:收集美国 13 岁以下儿童数据的应用程序必须遵守
  • 有年龄限制的内容:当用户在注册或年龄验证时表明自己未满 13 岁时使用
  • 限制跟踪:限制数据收集,以遵守儿童隐私保护法

有关完整的方法文档,请参阅trackingUnder13 参考资料


实施示例

通过年龄验证确定用户未满 13 岁后,立即调用trackingUnder13()

JavaScript
document.addEventListener('deviceready', initializeCOPPA, false);

function initializeCOPPA() {
  // Check if user's age was previously verified
  var ageCategory = localStorage.getItem('user_age_category');
  
  if (ageCategory === 'under_13') {
    applyChildPrivacyProtections();
  }
}

// User identified as under 13
function onUserUnder13() {
  cordova.plugins.SingularCordovaSdk.trackingUnder13();
  console.log('COPPA mode enabled for user under 13');
  
  // Store age category for app restart
  localStorage.setItem('user_age_category', 'under_13');
}

// Call after age verification
function onAgeVerified(userAge) {
  if (userAge < 13) {
    cordova.plugins.SingularCordovaSdk.trackingUnder13();
    console.log('COPPA restrictions applied');
    
    // Also limit advertising identifiers
    cordova.plugins.SingularCordovaSdk.setLimitAdvertisingIdentifiers(true);
    
    localStorage.setItem('user_age_category', 'under_13');
    
    alert('Special privacy protections have been applied to your account.');
  } else {
    localStorage.setItem('user_age_category', 'adult');
    console.log('Adult account - standard tracking');
  }
}

// Example: Age verification form
function handleAgeSubmit() {
  var ageInput = document.getElementById('age-input');
  var userAge = parseInt(ageInput.value, 10);
  
  if (isNaN(userAge) || userAge < 1 || userAge > 120) {
    alert('Please enter a valid age.');
    return;
  }
  
  onAgeVerified(userAge);
}

// Apply all child privacy protections
function applyChildPrivacyProtections() {
  cordova.plugins.SingularCordovaSdk.trackingUnder13();
  cordova.plugins.SingularCordovaSdk.setLimitAdvertisingIdentifiers(true);
  console.log('Child privacy protections applied');
}

最佳做法:在确定用户年龄后尽早调用trackingUnder13()。与setLimitAdvertisingIdentifiers(true) 结合使用,实现全面的儿童隐私保护。


全面实施隐私保护

通过持久存储和用户界面同步,实施涵盖 GDPR、CCPA 和 COPPA 合规性的全面隐私管理。

完整实施示例

隐私管理器模块

创建一个可重复使用的隐私管理模块,处理所有隐私设置的初始化和持久化。

JavaScript
// Privacy Manager Module
var PrivacyManager = {
  // Storage keys
  PREF_USER_CONSENT: 'privacy_user_consent',
  PREF_DATA_SHARING: 'privacy_data_sharing',
  PREF_AGE_CATEGORY: 'user_age_category',
  
  /**
   * Initialize privacy settings on app startup
   */
  initialize: function() {
    var hasUserConsent = this.getUserConsent();
    var allowDataSharing = this.getDataSharingPreference();
    var ageCategory = this.getAgeCategory();
    
    // Apply age-based restrictions first
    if (ageCategory === 'under_13') {
      cordova.plugins.SingularCordovaSdk.trackingUnder13();
      cordova.plugins.SingularCordovaSdk.setLimitAdvertisingIdentifiers(true);
      console.log('COPPA restrictions applied on startup');
    }
    
    // Apply stored tracking preference
    if (hasUserConsent) {
      cordova.plugins.SingularCordovaSdk.trackingOptIn();
      cordova.plugins.SingularCordovaSdk.resumeAllTracking();
      console.log('Privacy initialized: Tracking enabled with consent');
    } else {
      cordova.plugins.SingularCordovaSdk.stopAllTracking();
      console.log('Privacy initialized: Tracking disabled');
    }
    
    // Set data sharing preference (inverse logic)
    cordova.plugins.SingularCordovaSdk.limitDataSharing(!allowDataSharing);
    
    console.log('Privacy initialized: consent=' + hasUserConsent + ', sharing=' + allowDataSharing);
  },
  
  /**
   * User accepts tracking via consent dialog
   */
  onUserAcceptedTracking: function() {
    this.saveUserConsent(true);
    
    cordova.plugins.SingularCordovaSdk.trackingOptIn();
    cordova.plugins.SingularCordovaSdk.resumeAllTracking();
    
    console.log('User accepted tracking');
  },
  
  /**
   * User declines tracking
   */
  onUserDeclinedTracking: function() {
    this.saveUserConsent(false);
    
    cordova.plugins.SingularCordovaSdk.stopAllTracking();
    
    console.log('User declined tracking');
  },
  
  /**
   * User updates data sharing preference
   */
  setDataSharingEnabled: function(enabled) {
    this.saveDataSharingPreference(enabled);
    
    // Note: LimitDataSharing uses inverse logic
    // false = data sharing enabled, true = data sharing limited
    cordova.plugins.SingularCordovaSdk.limitDataSharing(!enabled);
    
    console.log('Data sharing: ' + (enabled ? 'Enabled' : 'Limited'));
  },
  
  /**
   * Check if tracking is currently enabled
   */
  isTrackingEnabled: function(callback) {
    cordova.plugins.SingularCordovaSdk.isAllTrackingStopped(function(isStopped) {
      callback(!isStopped);
    });
  },
  
  /**
   * Get current privacy status as readable text
   */
  getPrivacyStatus: function(callback) {
    var self = this;
    
    this.isTrackingEnabled(function(isEnabled) {
      var dataSharingEnabled = self.getDataSharingPreference();
      var ageCategory = self.getAgeCategory();
      
      var status = 'Tracking: ' + (isEnabled ? 'Enabled' : 'Disabled') + '\n';
      status += 'Data Sharing: ' + (dataSharingEnabled ? 'Enabled' : 'Limited');
      
      if (ageCategory === 'under_13') {
        status += '\nCOPPA: Restrictions Applied';
      }
      
      callback(status);
    });
  },
  
  /**
   * Set user's age and apply appropriate protections
   */
  setUserAge: function(age) {
    if (age < 13) {
      cordova.plugins.SingularCordovaSdk.trackingUnder13();
      cordova.plugins.SingularCordovaSdk.setLimitAdvertisingIdentifiers(true);
      localStorage.setItem(this.PREF_AGE_CATEGORY, 'under_13');
      console.log('Age set to under 13 - COPPA protections applied');
    } else {
      localStorage.setItem(this.PREF_AGE_CATEGORY, 'adult');
      console.log('Age set to adult - standard tracking');
    }
  },
  
  // Private helper methods
  getUserConsent: function() {
    var value = localStorage.getItem(this.PREF_USER_CONSENT);
    return value === 'true';
  },
  
  saveUserConsent: function(consent) {
    localStorage.setItem(this.PREF_USER_CONSENT, consent.toString());
  },
  
  getDataSharingPreference: function() {
    var value = localStorage.getItem(this.PREF_DATA_SHARING);
    return value === 'true';
  },
  
  saveDataSharingPreference: function(enabled) {
    localStorage.setItem(this.PREF_DATA_SHARING, enabled.toString());
  },
  
  getAgeCategory: function() {
    return localStorage.getItem(this.PREF_AGE_CATEGORY);
  }
};

// Initialize on device ready
document.addEventListener('deviceready', function() {
  PrivacyManager.initialize();
}, false);

关键实施指南

最佳实践

  • 持久存储:使用本地存储或安全存储解决方案保存用户偏好设置
  • 早期初始化:在 SDK 初始化后立即应用隐私设置
  • UI 同步:使用isAllTrackingStopped()保持设置 UI 与实际 SDK 状态同步
  • 清晰沟通:在应用设置中提供清晰、易用的隐私控制
  • 反向逻辑:请记住,limitDataSharing(false) 意味着启用数据共享,而true 则意味着限制数据共享
  • COPPA 优先级:在其他隐私设置之前应用儿童隐私保护 (trackingUnder13())
  • 合规文档:保留用户何时以及如何提供或撤销同意的记录

验证清单

确保您的隐私实施符合合规要求:

  1. 收集同意:在跟踪开始前征求用户的明确同意
  2. 同意记录:当用户提供 GDPR 同意时,调用trackingOptIn()
  3. 数据共享控制:使用limitDataSharing() 向合作伙伴传达用户偏好
  4. 退出机制:用户可通过stopAllTracking() 在隐私设置中停止跟踪
  5. 年龄验证:对儿童实施年龄门和呼叫trackingUnder13()
  6. 持久设置:保存隐私偏好,并在重新启动应用程序时重新应用
  7. 用户界面透明:隐私设置屏幕清晰显示当前跟踪状态