Cumplir con las leyes de privacidad de datos
Implemente la recopilación de datos que cumpla con la privacidad notificando a Singular las opciones de consentimiento del usuario para GDPR, CCPA, COPPA y otras regulaciones de privacidad del consumidor.
Cuando los usuarios consientan o rechacen compartir su información con terceros, utilice los métodos de privacidad de Singular para comunicar su elección. Esto garantiza el cumplimiento de normativas como la Ley de Privacidad del Consumidor de California (CCPA)y permite a los socios respetar las preferencias de privacidad del usuario.
Más información: Consulte Privacidad del usuario y Limitar el uso compartido dedatos para obtener información detallada sobre cómo Singular procesa el consentimiento de privacidad.
Limitar el uso compartido de datos
Control del intercambio de datos con terceros
Notifique a Singular si los usuarios han dado su consentimiento para compartir sus datos personales con socios terceros utilizando el método limitDataSharing().
Firma del método:
static limitDataSharing(shouldLimitDataSharing: boolean): void
Parámetros:
- false: El usuario ha optado y consentido compartir sus datos
- true: El usuario ha optado por no participar y no consiente compartir sus datos
Importante: Aunque es opcional, este método afecta a la compartición de datos de atribución. Algunos socios sólo comparten la información de atribución completa cuando se notifica explícitamente que los usuarios han optado por ella.
Para obtener la documentación completa del método, consulte la referencia limitDataSharing.
Ejemplos de uso
Implemente controles de compartición de datos basados en las preferencias de privacidad del usuario.
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
// User has opted in to share their data
export const onUserOptedInToDataSharing = () => {
NativeSingular.limitDataSharing(false);
console.log('Data sharing enabled');
};
// User has opted out and declined to share their data
export const onUserOptedOutOfDataSharing = () => {
NativeSingular.limitDataSharing(true);
console.log('Data sharing limited');
};
// Set based on user preference
export const handlePrivacyConsent = (userConsented) => {
// Pass inverse: false = opted in, true = opted out
NativeSingular.limitDataSharing(!userConsented);
console.log(`Data sharing: ${userConsented ? 'Enabled' : 'Limited'}`);
};
import { Singular } from 'singular-react-native';
// User has opted in to share their data
export const onUserOptedInToDataSharing = () => {
Singular.limitDataSharing(false);
console.log('Data sharing enabled');
};
// User has opted out and declined to share their data
export const onUserOptedOutOfDataSharing = () => {
Singular.limitDataSharing(true);
console.log('Data sharing limited');
};
// Set based on user preference
export const handlePrivacyConsent = (userConsented) => {
// Pass inverse: false = opted in, true = opted out
Singular.limitDataSharing(!userConsented);
console.log(`Data sharing: ${userConsented ? 'Enabled' : 'Limited'}`);
};
Cómo funciona:
Singular utiliza esta configuración en las devoluciones de privacidad del usuarioy la pasa a los socios que la requieren para el cumplimiento normativo.
Métodos de cumplimiento de GDPR
Gestione el consentimiento de seguimiento del usuario y controle la funcionalidad del SDK para cumplir con el GDPR (Reglamento General de Protección de Datos) y otras normativas de privacidad.
Gestión del consentimiento de seguimiento
TrackingOptIn
Registre el consentimiento explícito del usuario para el seguimiento enviando un evento GDPR opt-in a los servidores de Singular.
Firma del método:
static trackingOptIn(): void
Cuándo Usar:
- Cumplimiento GDPR: Llamada cuando los usuarios consienten explícitamente el seguimiento en regiones reguladas por GDPR.
- Registro de consentimiento: Marca a los usuarios como que han dado su consentimiento GDPR en los sistemas de Singular
- Comportamiento por defecto: Sin esta llamada, el SDK continúa el seguimiento pero no registra específicamente el consentimiento.
Para obtener la documentación completa del método, consulte la referencia trackingOptIn.
Ejemplo de implementación
Llame a trackingOptIn() después de que los usuarios acepten el consentimiento de seguimiento a través del diálogo de consentimiento de su aplicación.
// TurboModule direct API (React Native 0.76+ New Architecture)
import React, { useState, useEffect } from 'react';
import { View, Text, Button, Alert } from 'react-native';
import NativeSingular from 'singular-react-native/jsNativeSingular';
import AsyncStorage from '@react-native-async-storage/async-storage';
export default function GDPRManager() {
const [hasConsent, setHasConsent] = useState(null);
useEffect(() => {
checkStoredConsent();
}, []);
const checkStoredConsent = async () => {
try {
const consent = await AsyncStorage.getItem('gdpr_consent');
if (consent === null) {
// Show consent dialog
showGDPRConsentDialog();
} else {
setHasConsent(consent === 'true');
}
} catch (error) {
console.error('Error checking consent:', error);
}
};
const showGDPRConsentDialog = () => {
Alert.alert(
'Privacy Consent',
'We would like your permission to track app usage and improve your experience.',
[
{
text: 'Accept',
onPress: onUserAcceptedTracking
},
{
text: 'Decline',
style: 'cancel',
onPress: () => setHasConsent(false)
}
]
);
};
const onUserAcceptedTracking = async () => {
// Record user consent
NativeSingular.trackingOptIn();
console.log('User opted in to tracking');
// Save preference
await AsyncStorage.setItem('gdpr_consent', 'true');
setHasConsent(true);
};
return (
<View>
{hasConsent !== null && (
<Text>Privacy Status: {hasConsent ? 'Opted In' : 'Declined'}</Text>
)}
</View>
);
}
import React, { useState, useEffect } from 'react';
import { View, Text, Button, Alert } from 'react-native';
import { Singular } from 'singular-react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
export default function GDPRManager() {
const [hasConsent, setHasConsent] = useState(null);
useEffect(() => {
checkStoredConsent();
}, []);
const checkStoredConsent = async () => {
try {
const consent = await AsyncStorage.getItem('gdpr_consent');
if (consent === null) {
// Show consent dialog
showGDPRConsentDialog();
} else {
setHasConsent(consent === 'true');
}
} catch (error) {
console.error('Error checking consent:', error);
}
};
const showGDPRConsentDialog = () => {
Alert.alert(
'Privacy Consent',
'We would like your permission to track app usage and improve your experience.',
[
{
text: 'Accept',
onPress: onUserAcceptedTracking
},
{
text: 'Decline',
style: 'cancel',
onPress: () => setHasConsent(false)
}
]
);
};
const onUserAcceptedTracking = async () => {
// Record user consent
Singular.trackingOptIn();
console.log('User opted in to tracking');
// Save preference
await AsyncStorage.setItem('gdpr_consent', 'true');
setHasConsent(true);
};
return (
<View>
{hasConsent !== null && (
<Text>Privacy Status: {hasConsent ? 'Opted In' : 'Declined'}</Text>
)}
</View>
);
}
Métodos de control de seguimiento
StopAllTracking
Desactiva completamente todas las actividades de seguimiento del SDK para el usuario actual en este dispositivo.
Firma del método:
static stopAllTracking(): void
Crítico Advertencia: Este método desactiva permanentemente el SDK hasta que se llame a resumeAllTracking(). El estado deshabilitado persiste durante los reinicios de la aplicación y sólo puede revertirse mediante programación.
Comportamiento:
- Efecto inmediato: Detiene todo el seguimiento, la notificación de eventos y la recopilación de datos al instante.
- Estado persistente: Permanece desactivado incluso después de cerrar y volver a abrir la aplicación.
-
Sin restablecimiento automático: Debe llamar explícitamente a
resumeAllTracking()para volver a habilitarlo
Para obtener la documentación completa del método, consulte la referencia stopAllTracking.
Ejemplo de implementación
Detener el seguimiento cuando los usuarios deniegan el consentimiento o se excluyen a través de la configuración de privacidad.
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
import AsyncStorage from '@react-native-async-storage/async-storage';
// User declined all tracking
export const onUserDeclinedTracking = async () => {
NativeSingular.stopAllTracking();
console.log('All tracking stopped');
// Store preference
await AsyncStorage.setItem('tracking_enabled', 'false');
};
// Handle user opt-out from settings menu
export const handlePrivacySettingsChange = (trackingEnabled) => {
if (!trackingEnabled) {
NativeSingular.stopAllTracking();
console.log('Privacy settings: Tracking disabled');
}
};
import { Singular } from 'singular-react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
// User declined all tracking
export const onUserDeclinedTracking = async () => {
Singular.stopAllTracking();
console.log('All tracking stopped');
// Store preference
await AsyncStorage.setItem('tracking_enabled', 'false');
};
// Handle user opt-out from settings menu
export const handlePrivacySettingsChange = (trackingEnabled) => {
if (!trackingEnabled) {
Singular.stopAllTracking();
console.log('Privacy settings: Tracking disabled');
}
};
ReanudarTodoElSeguimiento
Volver a activar el seguimiento después de haberlo detenido con stopAllTracking().
Firma del método:
static resumeAllTracking(): void
Casos de uso:
- Cambio de consentimiento: El usuario cambia sus preferencias de privacidad y vuelve a activar el seguimiento
- Ajustes de privacidad: El usuario actualiza su consentimiento a través del menú de configuración de la aplicación
- Cumplimiento regional: Volver a activar el seguimiento cuando el usuario se traslada a regiones no reguladas
Para ver la documentación completa del método, consulte la referencia resumeAllTracking.
Ejemplo de implementación
Reanudar el seguimiento cuando los usuarios vuelven a optar por él o actualizan sus preferencias de privacidad.
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
import AsyncStorage from '@react-native-async-storage/async-storage';
// User opted back in to tracking
export const onUserResumedTracking = async () => {
NativeSingular.resumeAllTracking();
console.log('Tracking resumed');
// Update stored preference
await AsyncStorage.setItem('tracking_enabled', 'true');
};
// Handle consent update from settings
export const handlePrivacySettingsChange = (trackingEnabled) => {
if (trackingEnabled) {
NativeSingular.resumeAllTracking();
console.log('Privacy settings: Tracking enabled');
}
};
import { Singular } from 'singular-react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
// User opted back in to tracking
export const onUserResumedTracking = async () => {
Singular.resumeAllTracking();
console.log('Tracking resumed');
// Update stored preference
await AsyncStorage.setItem('tracking_enabled', 'true');
};
// Handle consent update from settings
export const handlePrivacySettingsChange = (trackingEnabled) => {
if (trackingEnabled) {
Singular.resumeAllTracking();
console.log('Privacy settings: Tracking enabled');
}
};
IsAllTrackingStopped
Comprueba si se ha desactivado el seguimiento para el usuario actual.
Firma del método:
static isAllTrackingStopped(): Promise<boolean>
Devuelve:
-
Promise<true>: El seguimiento se ha detenido actualmente a través de
stopAllTracking() - Promise<false>: El seguimiento está activo (no se ha detenido nunca o se ha reanudado)
Para la documentación completa del método, consulte la referencia isAllTrackingStopped.
Ejemplo de implementación
Comprueba el estado de seguimiento para sincronizar el estado de la interfaz de usuario con el estado de seguimiento del SDK.
// TurboModule direct API (React Native 0.76+ New Architecture)
import React, { useState, useEffect } from 'react';
import { View, Text, Switch } from 'react-native';
import NativeSingular from 'singular-react-native/jsNativeSingular';
export default function PrivacySettingsUI() {
const [trackingEnabled, setTrackingEnabled] = useState(false);
const [statusText, setStatusText] = useState('Checking...');
useEffect(() => {
updatePrivacyUI();
}, []);
// Check current tracking status
const isTrackingEnabled = async () => {
const isStopped = await NativeSingular.isAllTrackingStopped();
return !isStopped;
};
// Display privacy status in settings
const getPrivacyStatusText = async () => {
const isStopped = await NativeSingular.isAllTrackingStopped();
return isStopped ? 'Tracking: Disabled' : 'Tracking: Enabled';
};
// Sync UI with tracking state
const updatePrivacyUI = async () => {
const isStopped = await NativeSingular.isAllTrackingStopped();
setTrackingEnabled(!isStopped);
const status = await getPrivacyStatusText();
setStatusText(status);
console.log(`Current tracking state: ${isStopped ? 'Stopped' : 'Active'}`);
};
// Handle toggle change from UI
const onTrackingToggleChanged = async (enabled) => {
if (enabled) {
NativeSingular.resumeAllTracking();
} else {
NativeSingular.stopAllTracking();
}
await updatePrivacyUI();
};
return (
<View>
<Text>{statusText}</Text>
<Switch
value={trackingEnabled}
onValueChange={onTrackingToggleChanged}
/>
</View>
);
}
import React, { useState, useEffect } from 'react';
import { View, Text, Switch } from 'react-native';
import { Singular } from 'singular-react-native';
export default function PrivacySettingsUI() {
const [trackingEnabled, setTrackingEnabled] = useState(false);
const [statusText, setStatusText] = useState('Checking...');
useEffect(() => {
updatePrivacyUI();
}, []);
// Check current tracking status
const isTrackingEnabled = async () => {
const isStopped = await Singular.isAllTrackingStopped();
return !isStopped;
};
// Display privacy status in settings
const getPrivacyStatusText = async () => {
const isStopped = await Singular.isAllTrackingStopped();
return isStopped ? 'Tracking: Disabled' : 'Tracking: Enabled';
};
// Sync UI with tracking state
const updatePrivacyUI = async () => {
const isStopped = await Singular.isAllTrackingStopped();
setTrackingEnabled(!isStopped);
const status = await getPrivacyStatusText();
setStatusText(status);
console.log(`Current tracking state: ${isStopped ? 'Stopped' : 'Active'}`);
};
// Handle toggle change from UI
const onTrackingToggleChanged = async (enabled) => {
if (enabled) {
Singular.resumeAllTracking();
} else {
Singular.stopAllTracking();
}
await updatePrivacyUI();
};
return (
<View>
<Text>{statusText}</Text>
<Switch
value={trackingEnabled}
onValueChange={onTrackingToggleChanged}
/>
</View>
);
}
Protección de la privacidad de los niños
TrackingUnder13
Notifica a Singular que el usuario es menor de 13 años para cumplir con la ley COPPA (Children's Online Privacy Protection Act) y otras normativas de privacidad infantil.
Firma del método:
static trackingUnder13(): void
Requisitos de cumplimiento:
- Cumplimiento de COPPA: Obligatorio para apps que recopilen datos de menores de 13 años en Estados Unidos.
- Contenido restringido por edad: Se utiliza cuando los usuarios se identifican como menores de 13 años durante el registro o la verificación de la edad
- Seguimiento restringido: Limita la recopilación de datos para cumplir las leyes de protección de la privacidad de los niños
Para obtener la documentación completa del método, consulte la referencia trackingUnder13.
Ejemplo de implementación
Llame a trackingUnder13() inmediatamente después de determinar que el usuario es menor de 13 años mediante la verificación de la edad.
// TurboModule direct API (React Native 0.76+ New Architecture)
import React, { useState } from 'react';
import { View, TextInput, Button, Alert } from 'react-native';
import NativeSingular from 'singular-react-native/jsNativeSingular';
import AsyncStorage from '@react-native-async-storage/async-storage';
export default function COPPAManager() {
const [age, setAge] = useState('');
// User identified as under 13
const onUserUnder13 = async () => {
NativeSingular.trackingUnder13();
console.log('COPPA mode enabled for user under 13');
// Store age category for app restart
await AsyncStorage.setItem('user_age_category', 'under_13');
};
// Call after age verification
const onAgeVerified = async (userAge) => {
if (userAge < 13) {
NativeSingular.trackingUnder13();
console.log('COPPA restrictions applied');
// Also limit advertising identifiers
NativeSingular.setLimitAdvertisingIdentifiers(true);
await AsyncStorage.setItem('user_age_category', 'under_13');
Alert.alert('Child Account', 'Special privacy protections have been applied.');
} else {
await AsyncStorage.setItem('user_age_category', 'adult');
console.log('Adult account - standard tracking');
}
};
const handleAgeSubmit = () => {
const userAge = parseInt(age, 10);
if (isNaN(userAge) || userAge < 1 || userAge > 120) {
Alert.alert('Invalid Age', 'Please enter a valid age.');
return;
}
onAgeVerified(userAge);
};
return (
<View>
<TextInput
placeholder="Enter your age"
value={age}
onChangeText={setAge}
keyboardType="number-pad"
/>
<Button title="Submit" onPress={handleAgeSubmit} />
</View>
);
}
import React, { useState } from 'react';
import { View, TextInput, Button, Alert } from 'react-native';
import { Singular } from 'singular-react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
export default function COPPAManager() {
const [age, setAge] = useState('');
// User identified as under 13
const onUserUnder13 = async () => {
Singular.trackingUnder13();
console.log('COPPA mode enabled for user under 13');
// Store age category for app restart
await AsyncStorage.setItem('user_age_category', 'under_13');
};
// Call after age verification
const onAgeVerified = async (userAge) => {
if (userAge < 13) {
Singular.trackingUnder13();
console.log('COPPA restrictions applied');
// Also limit advertising identifiers
Singular.setLimitAdvertisingIdentifiers(true);
await AsyncStorage.setItem('user_age_category', 'under_13');
Alert.alert('Child Account', 'Special privacy protections have been applied.');
} else {
await AsyncStorage.setItem('user_age_category', 'adult');
console.log('Adult account - standard tracking');
}
};
const handleAgeSubmit = () => {
const userAge = parseInt(age, 10);
if (isNaN(userAge) || userAge < 1 || userAge > 120) {
Alert.alert('Invalid Age', 'Please enter a valid age.');
return;
}
onAgeVerified(userAge);
};
return (
<View>
<TextInput
placeholder="Enter your age"
value={age}
onChangeText={setAge}
keyboardType="number-pad"
/>
<Button title="Submit" onPress={handleAgeSubmit} />
</View>
);
}
Importante: Llame a este método lo antes posible después de determinar que el usuario es menor de 13 años, idealmente durante la inicialización de la aplicación o inmediatamente después de la verificación de la edad. Esto garantiza que todo el seguimiento posterior respete la normativa sobre privacidad infantil.
SetLimitAdvertisingIdentifiers
Restringe la recopilación y el uso de identificadores de publicidad (GAID en Android, IDFA en iOS) tras la inicialización del SDK para aplicaciones de audiencia mixta.
Firma del método:
static setLimitAdvertisingIdentifiers(isEnabled: boolean): void
Parámetros:
- true: Habilitar el modo de identificadores publicitarios limitados (restringir la recopilación).
- false: Desactivar el modo de identificadores publicitarios limitados (recopilación normal)
Casos de uso:
- Aplicaciones de público mixto: Apps que sirven tanto a adultos como a niños en las que la edad se determina tras el lanzamiento de la app.
- Controles dinámicos de privacidad: Ajustar el seguimiento en función de las acciones del usuario o del contenido al que se accede
- Restricciones de tiempo de ejecución: Aplicar limitaciones de identificadores de publicidad tras la configuración inicial del SDK
Para obtener la documentación completa del método, consulte la referencia setLimitAdvertisingIdentifiers.
Ejemplo de implementación
Limite dinámicamente los identificadores de publicidad en función de la edad del usuario, el tipo de contenido o el modo de aplicación.
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
// Limit advertising identifiers after initialization
export const enableLimitedMode = () => {
NativeSingular.setLimitAdvertisingIdentifiers(true);
console.log('Advertising identifiers limited');
};
// Mixed audience app with age gate
export const onKidsModeSwitched = (isKidsMode) => {
if (isKidsMode) {
NativeSingular.setLimitAdvertisingIdentifiers(true);
console.log('Advertising identifiers limited for kids mode');
} else {
NativeSingular.setLimitAdvertisingIdentifiers(false);
console.log('Advertising identifiers unrestricted for adult mode');
}
};
// Content-based restrictions
export const onViewingChildrensContent = () => {
NativeSingular.setLimitAdvertisingIdentifiers(true);
console.log('Ad identifiers restricted for children\'s content');
};
// Combined with TrackingUnder13
export const onAgeVerified = (age) => {
if (age < 13) {
NativeSingular.trackingUnder13();
NativeSingular.setLimitAdvertisingIdentifiers(true);
console.log('Full COPPA restrictions applied');
}
};
import { Singular } from 'singular-react-native';
// Limit advertising identifiers after initialization
export const enableLimitedMode = () => {
Singular.setLimitAdvertisingIdentifiers(true);
console.log('Advertising identifiers limited');
};
// Mixed audience app with age gate
export const onKidsModeSwitched = (isKidsMode) => {
if (isKidsMode) {
Singular.setLimitAdvertisingIdentifiers(true);
console.log('Advertising identifiers limited for kids mode');
} else {
Singular.setLimitAdvertisingIdentifiers(false);
console.log('Advertising identifiers unrestricted for adult mode');
}
};
// Content-based restrictions
export const onViewingChildrensContent = () => {
Singular.setLimitAdvertisingIdentifiers(true);
console.log('Ad identifiers restricted for children\'s content');
};
// Combined with TrackingUnder13
export const onAgeVerified = (age) => {
if (age < 13) {
Singular.trackingUnder13();
Singular.setLimitAdvertisingIdentifiers(true);
console.log('Full COPPA restrictions applied');
}
};
Alternativa de configuración: También puede limitar los identificadores de publicidad durante la inicialización del SDK estableciendo la opción de configuración limitAdvertisingIdentifiers si conoce los requisitos de privacidad antes de que se inicie el SDK.
Propiedad de configuración
Establezca limitaciones de identificadores publicitarios durante la inicialización del SDK para aplicaciones que conozcan los requisitos de privacidad de antemano.
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
// Limit advertising identifiers at initialization
const config: SingularConfig = {
apikey: 'YOUR_SDK_KEY',
secret: 'YOUR_SDK_SECRET',
limitAdvertisingIdentifiers: true
};
NativeSingular.init(config);
import { Singular, SingularConfig } from 'singular-react-native';
// Limit advertising identifiers at initialization
const config = new SingularConfig(
'YOUR_SDK_KEY',
'YOUR_SDK_SECRET'
)
.withLimitAdvertisingIdentifiers(true);
Singular.init(config);
Para obtener documentación completa sobre la configuración, consulte la referencia withLimitAdvertisingIdentifiers.
Mejores prácticas de implementación
Ejemplo de gestión completa de la privacidad
Implemente controles de privacidad completos que respeten las preferencias de los usuarios y cumplan la normativa.
// TurboModule direct API (React Native 0.76+ New Architecture)
import React, { useEffect } from 'react';
import NativeSingular from 'singular-react-native/jsNativeSingular';
import AsyncStorage from '@react-native-async-storage/async-storage';
const PREF_USER_CONSENT = 'privacy_user_consent';
const PREF_DATA_SHARING = 'privacy_data_sharing';
const PREF_AGE_CATEGORY = 'user_age_category';
/**
* Initialize privacy settings on app startup based on stored preferences
*/
export const initializePrivacySettings = async () => {
const hasUserConsent = await getUserConsent();
const allowDataSharing = await getDataSharingPreference();
const ageCategory = await getAgeCategory();
// Apply age-based restrictions first
if (ageCategory === 'under_13') {
NativeSingular.trackingUnder13();
NativeSingular.setLimitAdvertisingIdentifiers(true);
console.log('COPPA restrictions applied on startup');
}
// Apply stored tracking preference
if (hasUserConsent) {
NativeSingular.trackingOptIn();
NativeSingular.resumeAllTracking();
console.log('Privacy initialized: Tracking enabled with consent');
} else {
NativeSingular.stopAllTracking();
console.log('Privacy initialized: Tracking disabled');
}
// Set data sharing preference (inverse logic)
NativeSingular.limitDataSharing(!allowDataSharing);
console.log(`Privacy initialized: consent=${hasUserConsent}, sharing=${allowDataSharing}`);
};
/**
* User accepts tracking via consent dialog
*/
export const onUserAcceptedTracking = async () => {
await saveUserConsent(true);
NativeSingular.trackingOptIn();
NativeSingular.resumeAllTracking();
console.log('User accepted tracking');
};
/**
* User declines tracking
*/
export const onUserDeclinedTracking = async () => {
await saveUserConsent(false);
NativeSingular.stopAllTracking();
console.log('User declined tracking');
};
/**
* User updates data sharing preference
*/
export const setDataSharingEnabled = async (enabled) => {
await saveDataSharingPreference(enabled);
// Note: LimitDataSharing uses inverse logic
// false = data sharing enabled, true = data sharing limited
NativeSingular.limitDataSharing(!enabled);
console.log(`Data sharing: ${enabled ? 'Enabled' : 'Limited'}`);
};
/**
* Check if tracking is currently enabled
*/
export const isTrackingEnabled = async () => {
const isStopped = await NativeSingular.isAllTrackingStopped();
return !isStopped;
};
/**
* Get current privacy status as readable text
*/
export const getPrivacyStatus = async () => {
const isEnabled = await isTrackingEnabled();
const dataSharingEnabled = await getDataSharingPreference();
const ageCategory = await getAgeCategory();
let status = `Tracking: ${isEnabled ? 'Enabled' : 'Disabled'}\n`;
status += `Data Sharing: ${dataSharingEnabled ? 'Enabled' : 'Limited'}`;
if (ageCategory === 'under_13') {
status += '\nCOPPA: Restrictions Applied';
}
return status;
};
// Private helper methods for AsyncStorage
const getUserConsent = async () => {
const value = await AsyncStorage.getItem(PREF_USER_CONSENT);
return value === 'true';
};
const saveUserConsent = async (consent) => {
await AsyncStorage.setItem(PREF_USER_CONSENT, consent.toString());
};
const getDataSharingPreference = async () => {
const value = await AsyncStorage.getItem(PREF_DATA_SHARING);
return value === 'true';
};
const saveDataSharingPreference = async (enabled) => {
await AsyncStorage.setItem(PREF_DATA_SHARING, enabled.toString());
};
const getAgeCategory = async () => {
return await AsyncStorage.getItem(PREF_AGE_CATEGORY);
};
// React component example
export default function PrivacyInitializer() {
useEffect(() => {
initializePrivacySettings();
}, []);
return null;
}
import React, { useEffect } from 'react';
import { Singular } from 'singular-react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
const PREF_USER_CONSENT = 'privacy_user_consent';
const PREF_DATA_SHARING = 'privacy_data_sharing';
const PREF_AGE_CATEGORY = 'user_age_category';
/**
* Initialize privacy settings on app startup based on stored preferences
*/
export const initializePrivacySettings = async () => {
const hasUserConsent = await getUserConsent();
const allowDataSharing = await getDataSharingPreference();
const ageCategory = await getAgeCategory();
// Apply age-based restrictions first
if (ageCategory === 'under_13') {
Singular.trackingUnder13();
Singular.setLimitAdvertisingIdentifiers(true);
console.log('COPPA restrictions applied on startup');
}
// Apply stored tracking preference
if (hasUserConsent) {
Singular.trackingOptIn();
Singular.resumeAllTracking();
console.log('Privacy initialized: Tracking enabled with consent');
} else {
Singular.stopAllTracking();
console.log('Privacy initialized: Tracking disabled');
}
// Set data sharing preference (inverse logic)
Singular.limitDataSharing(!allowDataSharing);
console.log(`Privacy initialized: consent=${hasUserConsent}, sharing=${allowDataSharing}`);
};
/**
* User accepts tracking via consent dialog
*/
export const onUserAcceptedTracking = async () => {
await saveUserConsent(true);
Singular.trackingOptIn();
Singular.resumeAllTracking();
console.log('User accepted tracking');
};
/**
* User declines tracking
*/
export const onUserDeclinedTracking = async () => {
await saveUserConsent(false);
Singular.stopAllTracking();
console.log('User declined tracking');
};
/**
* User updates data sharing preference
*/
export const setDataSharingEnabled = async (enabled) => {
await saveDataSharingPreference(enabled);
// Note: LimitDataSharing uses inverse logic
// false = data sharing enabled, true = data sharing limited
Singular.limitDataSharing(!enabled);
console.log(`Data sharing: ${enabled ? 'Enabled' : 'Limited'}`);
};
/**
* Check if tracking is currently enabled
*/
export const isTrackingEnabled = async () => {
const isStopped = await Singular.isAllTrackingStopped();
return !isStopped;
};
/**
* Get current privacy status as readable text
*/
export const getPrivacyStatus = async () => {
const isEnabled = await isTrackingEnabled();
const dataSharingEnabled = await getDataSharingPreference();
const ageCategory = await getAgeCategory();
let status = `Tracking: ${isEnabled ? 'Enabled' : 'Disabled'}\n`;
status += `Data Sharing: ${dataSharingEnabled ? 'Enabled' : 'Limited'}`;
if (ageCategory === 'under_13') {
status += '\nCOPPA: Restrictions Applied';
}
return status;
};
// Private helper methods for AsyncStorage
const getUserConsent = async () => {
const value = await AsyncStorage.getItem(PREF_USER_CONSENT);
return value === 'true';
};
const saveUserConsent = async (consent) => {
await AsyncStorage.setItem(PREF_USER_CONSENT, consent.toString());
};
const getDataSharingPreference = async () => {
const value = await AsyncStorage.getItem(PREF_DATA_SHARING);
return value === 'true';
};
const saveDataSharingPreference = async (enabled) => {
await AsyncStorage.setItem(PREF_DATA_SHARING, enabled.toString());
};
const getAgeCategory = async () => {
return await AsyncStorage.getItem(PREF_AGE_CATEGORY);
};
// React component example
export default function PrivacyInitializer() {
useEffect(() => {
initializePrivacySettings();
}, []);
return null;
}
Directrices clave de implantación
Mejoresprácticas:
- Almacenamiento persistente: Guarde las preferencias del usuario utilizando AsyncStorage o una solución de almacenamiento seguro.
- Inicialización temprana: Aplique la configuración de privacidad antes de la inicialización del SDK cuando sea posible
-
Sincronización de la interfaz de usuario: Mantenga la interfaz de usuario sincronizada con el estado real del SDK utilizando
isAllTrackingStopped() - Comunicación clara: Proporcionar controles de privacidad claros y accesibles en la configuración de la aplicación
-
Lógica inversa: Recuerde que
limitDataSharing(false)significa que el intercambio de datos está activado, mientras quetruesignifica que está limitado. -
Prioridad COPPA: Aplicar las protecciones de la privacidad infantil (
trackingUnder13()) antes que otros ajustes de privacidad - Documentación de cumplimiento: Mantener registros de cuándo y cómo los usuarios dan o revocan su consentimiento