Conformidade com as leis de privacidade de dados
Implementar a recolha de dados em conformidade com a privacidade, notificando a Singular das escolhas de consentimento do utilizador para GDPR, CCPA, COPPA e outros regulamentos de privacidade do consumidor.
Quando os utilizadores consentirem ou recusarem a partilha das suas informações com terceiros, utilize os métodos de privacidade da Singular para comunicar a sua escolha. Isto assegura a conformidade com regulamentos como o California Consumer Privacy Act (CCPA)e permite que os parceiros respeitem as preferências de privacidade dos utilizadores.
Saiba mais: Consulte Privacidade do usuário e Limitar compartilhamento de dadospara obter informações detalhadas sobre como a Singular processa o consentimento de privacidade.
Limitar a partilha de dados
Controlar o compartilhamento de dados de terceiros
Notificar a Singular se os usuários consentiram em compartilhar seus dados pessoais com parceiros terceiros usando o método limitDataSharing().
Assinatura do método:
static limitDataSharing(shouldLimitDataSharing: boolean): void
Parâmetros:
- false: O utilizador optou e consentiu a partilha dos seus dados
- true: O utilizador optou por não participar e não consente a partilha dos seus dados
Importante: Embora opcional, este método afecta a partilha de dados de atribuição. Alguns parceiros só partilham informações de atribuição completas quando são explicitamente notificados de que os utilizadores optaram por participar.
Para obter a documentação completa do método, consulte a referência limitDataSharing.
Exemplos de utilização
Implementar controlos de partilha de dados com base nas preferências de privacidade do utilizador.
// 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'}`);
};
Como funciona:
A Singular usa essa configuração em Postbacks de privacidade do usuárioe a passa para parceiros que a exigem para conformidade regulatória.
Métodos de conformidade com o GDPR
Gerencie o consentimento de rastreamento do usuário e controle a funcionalidade do SDK para estar em conformidade com o GDPR (Regulamento Geral de Proteção de Dados) e outros regulamentos de privacidade.
Gestão do consentimento de rastreio
TrackingOptIn
Regista o consentimento explícito do utilizador para o rastreio, enviando um evento GDPR opt-in para os servidores Singular.
Assinatura do método:
static trackingOptIn(): void
Quando usar:
- Conformidade com o GDPR: Chamar quando os usuários consentirem explicitamente com o rastreamento em regiões regulamentadas pelo GDPR
- Registro de consentimento: Marca os usuários como tendo fornecido consentimento GDPR nos sistemas da Singular
- Comportamento padrão: Sem esta chamada, o SDK continua a rastrear mas não regista especificamente o consentimento
Para obter a documentação completa do método, consulte a referência trackingOptIn.
Exemplo de implementação
Chame trackingOptIn() depois de os utilizadores aceitarem o consentimento de rastreio através da caixa de diálogo de consentimento da sua aplicação.
// 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 controlo de rastreio
StopAllTracking
Desactiva completamente todas as actividades de rastreio do SDK para o utilizador atual neste dispositivo.
Assinatura do método:
static stopAllTracking(): void
Crítico Aviso: Este método desactiva permanentemente o SDK até que resumeAllTracking() seja chamado. O estado de desativação persiste durante as reinicializações da aplicação e só pode ser revertido programaticamente.
Comportamento:
- Efeito imediato: Interrompe todo o rastreamento, relatório de eventos e coleta de dados instantaneamente
- Estado persistente: Permanece desativado mesmo depois de a aplicação ser fechada e reaberta
-
Sem reinicialização automática: Tem de chamar explicitamente
resumeAllTracking()para voltar a ativar
Para obter a documentação completa do método, consulte a referência stopAllTracking.
Exemplo de implementação
Parar o rastreio quando os utilizadores recusam o consentimento ou optam por sair através das definições de privacidade.
// 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');
}
};
RetomarTudoRastreio
Reativar o rastreio depois de ter sido interrompido com stopAllTracking().
Assinatura do método:
static resumeAllTracking(): void
Casos de utilização:
- Alteração de consentimento: O utilizador altera as preferências de privacidade e volta a optar pelo rastreio
- Definições de privacidade: O utilizador actualiza o consentimento através do menu de definições da aplicação
- Conformidade regional: Voltar a ativar o rastreio quando o utilizador se desloca para regiões não regulamentadas
Para obter a documentação completa do método, consulte a referência resumeAllTracking.
Exemplo de implementação
Retomar o rastreio quando os utilizadores optarem por voltar a participar ou actualizarem as suas preferências de privacidade.
// 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
Verificar se o rastreio foi desativado para o utilizador atual.
Assinatura do método:
static isAllTrackingStopped(): Promise<boolean>
Retorna:
-
Promise<true>: O rastreamento está atualmente parado via
stopAllTracking() - Promessa<false>: O rastreio está ativo (nunca parou ou foi retomado)
Para obter a documentação completa do método, consulte a referência isAllTrackingStopped.
Exemplo de implementação
Verificar o estado do rastreio para sincronizar o estado da IU com o estado do rastreio do 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>
);
}
Proteção da privacidade das crianças
TrackingUnder13
Notifica a Singular de que o utilizador tem menos de 13 anos de idade para cumprir a COPPA (Children's Online Privacy Protection Act) e outros regulamentos de privacidade infantil.
Assinatura do método:
static trackingUnder13(): void
Requisitos de conformidade:
- Conformidade com a COPPA: Necessário para aplicações que recolhem dados de crianças com menos de 13 anos nos Estados Unidos
- Conteúdo com limite de idade: Utilizar quando os utilizadores se identificam como tendo menos de 13 anos durante o registo ou a verificação da idade
- Rastreio restrito: Limita a recolha de dados para cumprir as leis de proteção da privacidade das crianças
Para obter a documentação completa do método, consulte a referência trackingUnder13.
Exemplo de implementação
Chame trackingUnder13() imediatamente após determinar que o utilizador tem menos de 13 anos através da verificação da idade.
// 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: Chame este método o mais cedo possível depois de determinar que o utilizador tem menos de 13 anos, idealmente durante a inicialização da aplicação ou imediatamente após a verificação da idade. Isso garante que todo o rastreamento subsequente respeite os regulamentos de privacidade das crianças.
SetLimitAdvertisingIdentifiers
Restringe a coleta e o uso de identificadores de publicidade (GAID no Android, IDFA no iOS) após a inicialização do SDK para aplicativos de público misto.
Assinatura do método:
static setLimitAdvertisingIdentifiers(isEnabled: boolean): void
Parâmetros:
- true: Ativar o modo de identificadores de publicidade limitados (restringir a recolha)
- false: Desativar o modo de identificadores de publicidade limitados (recolha normal)
Casos de uso:
- Aplicações de público misto: Aplicações que servem tanto adultos como crianças, em que a idade é determinada após o lançamento da aplicação
- Controlos de privacidade dinâmicos: Ajustar o rastreio com base nas acções do utilizador ou no conteúdo acedido
- Restrições de tempo de execução: Aplicar limitações de identificadores de publicidade após a configuração inicial do SDK
Para obter a documentação completa do método, consulte a referência setLimitAdvertisingIdentifiers.
Exemplo de implementação
Limitar dinamicamente os identificadores de publicidade com base na idade do utilizador, no tipo de conteúdo ou no modo de aplicação.
// 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 configuração: Também pode limitar os identificadores de publicidade durante a inicialização do SDK definindo a opção de configuração limitAdvertisingIdentifiers se conhecer os requisitos de privacidade antes do início do SDK.
Propriedade de configuração
Defina limitações de identificadores de publicidade durante a inicialização do SDK para aplicações que conhecem os requisitos de privacidade antecipadamente.
// 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 obter a documentação de configuração completa, consulte a referência withLimitAdvertisingIdentifiers.
Melhores práticas de implementação
Exemplo de gestão de privacidade completa
Implemente controlos de privacidade abrangentes que respeitem as preferências do utilizador e cumpram os regulamentos.
// 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;
}
Principais diretrizes de implementação
Melhores práticas:
- Armazenamento persistente: Guardar as preferências do utilizador utilizando o AsyncStorage ou uma solução de armazenamento seguro
- Inicialização antecipada: Aplicar configurações de privacidade antes da inicialização do SDK, quando possível
-
Sincronização da IU: Manter as configurações da interface do usuário sincronizadas com o estado real do SDK usando
isAllTrackingStopped() - Comunicação clara: Fornecer controlos de privacidade claros e acessíveis nas definições da aplicação
-
Lógica inversa: Lembre-se de que
limitDataSharing(false)significa que a partilha de dados está activada, enquantotruesignifica que está limitada -
Prioridade COPPA: Aplicar as protecções de privacidade das crianças (
trackingUnder13()) antes de outras definições de privacidade - Documentação de conformidade: Manter registos de quando e como os utilizadores fornecem ou revogam o consentimento