Conformidade com leis de privacidade de dados
Implemente a coleta de dados em conformidade com a privacidade notificando o Singular sobre as escolhas de consentimento dos usuários para GDPR, CCPA e outras regulamentações de privacidade do consumidor.
Quando os usuários consentem ou recusam o compartilhamento de suas informações com terceiros, utilize os métodos de privacidade do Singular para comunicar essa escolha. Isso garante a conformidade com regulamentações como a California Consumer Privacy Act (CCPA) e permite que os parceiros respeitem as preferências de privacidade do usuário.
Saiba mais: Consulte Privacidade do usuário e limitação do compartilhamento de dados para obter informações detalhadas sobre como o Singular processa o consentimento de privacidade.
Limitar o compartilhamento de dados
Controlar o compartilhamento de dados com terceiros
Notifique o Singular sobre se os usuários consentiram em compartilhar seus dados pessoais com parceiros terceirizados usando o método
limitDataSharing
.
Assinatura do método:
+ (void)limitDataSharing:(BOOL)shouldLimitDataSharing;
Parâmetros:
- NO (false): O usuário optou por participar e consentiu em compartilhar seus dados
- YES (true): O usuário optou por não participar e não consente em compartilhar seus dados
Importante: Embora opcional, este método afeta o compartilhamento de dados de atribuição. Alguns parceiros só compartilham informações completas de atribuição quando são notificados explicitamente de que os usuários optaram por participar.
Exemplos de uso
// User has opted in to share their data
Singular.limitDataSharing(false)
// User has opted out and declined to share their data
Singular.limitDataSharing(true)
// Example: Set based on user preference
func handlePrivacyConsent(userConsented: Bool) {
// Pass inverse: false = opted in, true = opted out
Singular.limitDataSharing(!userConsented)
print("Data sharing: \(userConsented ? "Enabled" : "Limited")")
}
// User has opted in to share their data
[Singular limitDataSharing:NO];
// User has opted out and declined to share their data
[Singular limitDataSharing:YES];
// Example: Set based on user preference
- (void)handlePrivacyConsent:(BOOL)userConsented {
// Pass inverse: NO = opted in, YES = opted out
[Singular limitDataSharing:!userConsented];
NSLog(@"Data sharing: %@", userConsented ? @"Enabled" : @"Limited");
}
Como funciona:
O Singular usa essa configuração em postbacks de privacidade do usuário e a repassa para os parceiros que a exigem para conformidade regulatória.
Limitação do compartilhamento de dados por evento
Substituir o compartilhamento de dados em um único evento
Você pode substituir a configuração global
limitDataSharing
para um único evento ou chamada de receita personalizada passando o atributo
ATTRIBUTE_SNG_LIMIT_DATA_SHARING
junto com os demais argumentos do evento. Isso é útil quando o usuário atualiza o consentimento de forma simultânea a uma ação e deseja que esse evento específico reflita a nova escolha imediatamente, sem alterar a configuração global do SDK para os eventos subsequentes.
Valores aceitos:
- NO (false): O usuário optou por participar apenas neste evento
- YES (true): O usuário optou por não participar apenas neste evento
Importante:
O atributo deve ser um valor booleano (
BOOL
em Objective-C,
Bool
em Swift). Entradas que não sejam booleanas são ignoradas e a requisição recorre à configuração global
limitDataSharing
. Em qualquer caso, o atributo é removido dos argumentos do evento antes do envio da requisição, de modo que nunca aparece no payload do evento.
Exemplos de uso
// Example 1: Standard event, opt out only for this event
var dic: [AnyHashable: Any] = [:]
dic[ATTRIBUTE_SNG_LIMIT_DATA_SHARING] = true
dic["order_id"] = "12345"
Singular.event("checkout_completed", withArgs: dic)
// Example 2: Custom revenue, opt in only for this event
var attributes: [AnyHashable: Any] = [:]
attributes[ATTRIBUTE_SNG_LIMIT_DATA_SHARING] = false
attributes["sku"] = "premium_monthly"
Singular.customRevenue("premium_purchase",
currency: "USD",
amount: 9.99,
withAttributes: attributes)
// Example 1: Standard event, opt out only for this event
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:@YES forKey:ATTRIBUTE_SNG_LIMIT_DATA_SHARING];
[dic setValue:@"12345" forKey:@"order_id"];
[Singular event:@"checkout_completed" withArgs:dic];
// Example 2: Custom revenue, opt in only for this event
NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
[attributes setValue:@NO forKey:ATTRIBUTE_SNG_LIMIT_DATA_SHARING];
[attributes setValue:@"premium_monthly" forKey:@"sku"];
[Singular customRevenue:@"premium_purchase"
currency:@"USD"
amount:9.99
withAttributes:attributes];
Como funciona:
Quando um valor booleano válido é fornecido, o SDK remove o atributo dos argumentos do evento e o grava no campo
data_sharing_options.limit_data_sharing
da requisição — substituindo a configuração global
limitDataSharing
apenas para essa requisição. A configuração global e o resultado de
getLimitDataSharing
não são modificados, de modo que os eventos subsequentes que não fornecerem o atributo continuarão a usar a escolha global.
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 sobre a Proteção de Dados) e outras regulamentações de privacidade.
Gerenciamento de consentimento de rastreamento
trackingOptIn
Registre o consentimento explícito do usuário para rastreamento enviando um evento de opt-in do GDPR para os servidores do Singular.
Pré-requisito de Info.plist:
Se o seu app usa o App Tracking Transparency da Apple (iOS 14.5+) — necessário para acessar o IDFA em usuários que consentem — declare
NSUserTrackingUsageDescription
no seu
Info.plist
com uma explicação clara voltada ao usuário antes de exibir o prompt do ATT ou chamar
+trackingOptIn
. Apps que solicitam rastreamento sem essa chave são rejeitados na App Review.
Assinatura do método:
+ (void)trackingOptIn;
Quando usar:
- Conformidade com o GDPR: Chame quando os usuários consentirem explicitamente o rastreamento em regiões regulamentadas pelo GDPR
- Registro de consentimento: Marca os usuários como tendo fornecido consentimento do GDPR nos sistemas do Singular
- Comportamento padrão: Sem essa chamada, o SDK continua rastreando, mas não registra o consentimento de forma específica
// User accepted tracking consent
Singular.trackingOptIn()
// Example: Call after consent dialog
func onUserAcceptedTracking() {
Singular.trackingOptIn()
print("User opted in to tracking")
}
// User accepted tracking consent
[Singular trackingOptIn];
// Example: Call after consent dialog
- (void)onUserAcceptedTracking {
[Singular trackingOptIn];
NSLog(@"User opted in to tracking");
}
Métodos de controle de rastreamento
stopAllTracking
Desative completamente todas as atividades de rastreamento do SDK para o usuário atual neste dispositivo.
Assinatura do método:
+ (void)stopAllTracking;
Aviso crítico:
Este método desativa o SDK permanentemente até que
resumeAllTracking
seja chamado. O estado desativado persiste após reinicializações do app e só pode ser revertido por programação.
Comportamento:
- Efeito imediato: Interrompe todo o rastreamento, o envio de eventos e a coleta de dados instantaneamente
- Estado persistente: Permanece desativado mesmo após o app ser fechado e reaberto
-
Sem reinicialização automática:
É preciso chamar explicitamente
resumeAllTrackingpara reativar
// User declined all tracking
Singular.stopAllTracking()
// Example: Handle user opt-out
func onUserDeclinedTracking() {
Singular.stopAllTracking()
print("All tracking stopped")
// Optionally store preference
saveUserTrackingPreference(false)
}
// User declined all tracking
[Singular stopAllTracking];
// Example: Handle user opt-out
- (void)onUserDeclinedTracking {
[Singular stopAllTracking];
NSLog(@"All tracking stopped");
// Optionally store preference
[self saveUserTrackingPreference:NO];
}
resumeAllTracking
Reative o rastreamento depois que ele foi interrompido com
stopAllTracking
.
Assinatura do método:
+ (void)resumeAllTracking;
Casos de uso:
- Alteração do consentimento: O usuário altera as preferências de privacidade e opta novamente pelo rastreamento
- Configurações de privacidade: O usuário atualiza o consentimento por meio do menu de configurações do app
- Conformidade regional: Reativa o rastreamento quando o usuário muda para regiões não regulamentadas
// User opted back in to tracking
Singular.resumeAllTracking()
// Example: Handle consent update
func onUserResumedTracking() {
Singular.resumeAllTracking()
print("Tracking resumed")
// Optionally update stored preference
saveUserTrackingPreference(true)
}
// User opted back in to tracking
[Singular resumeAllTracking];
// Example: Handle consent update
- (void)onUserResumedTracking {
[Singular resumeAllTracking];
NSLog(@"Tracking resumed");
// Optionally update stored preference
[self saveUserTrackingPreference:YES];
}
isAllTrackingStopped
Verifique se o rastreamento foi desativado para o usuário atual.
Assinatura do método:
+ (BOOL)isAllTrackingStopped;
Retorna:
-
YES (true):
O rastreamento está atualmente interrompido por
stopAllTracking - NO (false): O rastreamento está ativo (nunca foi interrompido ou foi retomado)
Retorna
NO
se o SDK não tiver sido inicializado, independentemente de qualquer estado de rastreamento anterior. Sempre confirme que
+start:
foi concluído antes de confiar nesse valor e interprete
NO
como "não interrompido ou ainda não inicializado", e não como "rastreando ativamente".
// Check current tracking status
let isTrackingStopped = Singular.isAllTrackingStopped()
// Example: Display privacy status in settings
func getPrivacyStatusText() -> String {
return Singular.isAllTrackingStopped() ? "Tracking: Disabled" : "Tracking: Enabled"
}
// Example: Sync UI with tracking state
func updatePrivacyToggle() {
let isStopped = Singular.isAllTrackingStopped()
privacyToggle.isOn = !isStopped
print("Current tracking state: \(isStopped ? "Stopped" : "Active")")
}
// Check current tracking status
BOOL isTrackingStopped = [Singular isAllTrackingStopped];
// Example: Display privacy status in settings
- (NSString *)getPrivacyStatusText {
return [Singular isAllTrackingStopped] ? @"Tracking: Disabled" : @"Tracking: Enabled";
}
// Example: Sync UI with tracking state
- (void)updatePrivacyToggle {
BOOL isStopped = [Singular isAllTrackingStopped];
self.privacyToggle.on = !isStopped;
NSLog(@"Current tracking state: %@", isStopped ? @"Stopped" : @"Active");
}
Proteção da privacidade infantil
trackingUnder13
Notifique o Singular de que o usuário tem menos de 13 anos para estar em conformidade com a COPPA (Lei de Proteção da Privacidade Online de Crianças) e outras regulamentações de privacidade infantil.
Assinatura do método:
+ (void)trackingUnder13;
Requisitos de conformidade:
- Conformidade com a COPPA: Necessário para apps que coletam dados de crianças menores de 13 anos nos Estados Unidos
- Conteúdo com restrição de idade: Use quando os usuários se identificarem como menores de 13 anos durante o registro ou a verificação de idade
- Rastreamento restrito: Limita a coleta de dados para estar em conformidade com as leis de proteção da privacidade infantil
// User identified as under 13
Singular.trackingUnder13()
// Example: Call after age verification
func onAgeVerified(userAge: Int) {
if userAge < 13 {
Singular.trackingUnder13()
print("COPPA mode enabled for user under 13")
}
}
// User identified as under 13
[Singular trackingUnder13];
// Example: Call after age verification
- (void)onAgeVerified:(int)userAge {
if (userAge < 13) {
[Singular trackingUnder13];
NSLog(@"COPPA mode enabled for user under 13");
}
}
Importante: Chame este método o quanto antes após determinar que o usuário tem menos de 13 anos, idealmente durante a inicialização do app ou imediatamente após a verificação de idade. Isso garante que todo o rastreamento subsequente respeite as regulamentações de privacidade infantil.
limitAdvertisingIdentifiers
Restrinja a coleta e o uso de identificadores de publicidade (IDFA no iOS) durante a inicialização do SDK em apps de audiência mista.
Propriedade de configuração:
@property (assign) BOOL limitAdvertisingIdentifiers;
Casos de uso:
- Apps de audiência mista: Apps que atendem tanto adultos quanto crianças, em que a idade é determinada antes do lançamento do app
- Usuários COPPA conhecidos: Quando você já sabe, no momento da inicialização, que o usuário tem menos de 13 anos
- Abordagem de privacidade em primeiro lugar: Aplica as limitações ao identificador de publicidade desde a primeira sessão do SDK
Método de configuração
Defina as limitações dos identificadores de publicidade durante a inicialização do SDK para apps que conhecem os requisitos de privacidade antecipadamente.
// Limit advertising identifiers at initialization
let config = SingularConfig(apiKey: "SDK_KEY", andSecret: "SDK_SECRET")
config?.limitAdvertisingIdentifiers = true
Singular.start(config)
// Limit advertising identifiers at initialization
SingularConfig *config = [[SingularConfig alloc]
initWithApiKey:@"SDK_KEY"
andSecret:@"SDK_SECRET"];
config.limitAdvertisingIdentifiers = YES;
[Singular start:config];
Build do Kids SDK:
limitAdvertisingIdentifiers
é excluído da compilação no build do Singular Kids SDK (protegido por
#ifndef SINGULAR_KIDS
). Se você está integrando o
Singular-Kids-SDK
, essa propriedade não está disponível — o Kids SDK aplica automaticamente um tratamento mais rigoroso dos identificadores. Para marcação de COPPA em tempo de execução, use
trackingUnder13
.
Método em tempo de execução
Ative ou desative a coleta de identificadores de publicidade a qualquer momento após
+start:
. Útil para apps de audiência mista em que o gate de idade, o prompt de consentimento ou a seleção de conteúdo ocorre depois que o SDK já foi iniciado.
+ (void)setLimitAdvertisingIdentifiers:(BOOL)enabled;
// Apply identifier limit after the user enters kids mode
func onKidsModeSwitched(isKidsMode: Bool) {
Singular.setLimitAdvertisingIdentifiers(isKidsMode)
}
// Apply identifier limit after the user enters kids mode
- (void)onKidsModeSwitched:(BOOL)isKidsMode {
[Singular setLimitAdvertisingIdentifiers:isKidsMode];
}
O método em tempo de execução também exige um argumento
BOOL
— chamar
+setLimitAdvertisingIdentifiers
sem argumentos não compila. Assim como a propriedade em tempo de configuração, esse método não está disponível no build do Kids SDK.
Boa prática:
Para uma conformidade abrangente com a COPPA, use
limitAdvertisingIdentifiers
na inicialização e chame
trackingUnder13()
quando a idade do usuário for verificada. Isso garante proteção completa desde a primeira sessão.
Boas práticas de implementação
Exemplo completo de gerenciamento de privacidade
Implemente controles de privacidade abrangentes que respeitem as preferências do usuário e estejam em conformidade com as regulamentações.
import Foundation
class PrivacyManager {
private let userDefaults = UserDefaults.standard
private let consentKey = "user_consent"
private let dataSharingKey = "data_sharing"
// Initialize privacy settings on app start
func initializePrivacy() {
let hasUserConsent = getUserConsent()
let allowDataSharing = getDataSharingPreference()
// Apply stored preferences
if hasUserConsent {
Singular.trackingOptIn()
Singular.resumeAllTracking()
} else {
Singular.stopAllTracking()
}
// Set data sharing preference
Singular.limitDataSharing(!allowDataSharing)
print("Privacy initialized: consent=\(hasUserConsent), sharing=\(allowDataSharing)")
}
// User accepts tracking via consent dialog
func userAcceptedTracking() {
saveUserConsent(true)
Singular.trackingOptIn()
Singular.resumeAllTracking()
print("User accepted tracking")
}
// User declines tracking
func userDeclinedTracking() {
saveUserConsent(false)
Singular.stopAllTracking()
print("User declined tracking")
}
// User updates data sharing preference
func setDataSharingEnabled(_ enabled: Bool) {
saveDataSharingPreference(enabled)
// Note: limitDataSharing uses inverse logic
Singular.limitDataSharing(!enabled)
print("Data sharing: \(enabled ? "Enabled" : "Limited")")
}
// Get current tracking status
func isTrackingEnabled() -> Bool {
return !Singular.isAllTrackingStopped()
}
// Private helper methods
private func getUserConsent() -> Bool {
return userDefaults.bool(forKey: consentKey)
}
private func saveUserConsent(_ consent: Bool) {
userDefaults.set(consent, forKey: consentKey)
}
private func getDataSharingPreference() -> Bool {
return userDefaults.bool(forKey: dataSharingKey)
}
private func saveDataSharingPreference(_ enabled: Bool) {
userDefaults.set(enabled, forKey: dataSharingKey)
}
}
#import <Foundation/Foundation.h>
#import <Singular/Singular.h>
@interface PrivacyManager : NSObject
- (void)initializePrivacy;
- (void)userAcceptedTracking;
- (void)userDeclinedTracking;
- (void)setDataSharingEnabled:(BOOL)enabled;
- (BOOL)isTrackingEnabled;
@end
@implementation PrivacyManager
static NSString *const kConsentKey = @"user_consent";
static NSString *const kDataSharingKey = @"data_sharing";
// Initialize privacy settings on app start
- (void)initializePrivacy {
BOOL hasUserConsent = [self getUserConsent];
BOOL allowDataSharing = [self getDataSharingPreference];
// Apply stored preferences
if (hasUserConsent) {
[Singular trackingOptIn];
[Singular resumeAllTracking];
} else {
[Singular stopAllTracking];
}
// Set data sharing preference
[Singular limitDataSharing:!allowDataSharing];
NSLog(@"Privacy initialized: consent=%d, sharing=%d", hasUserConsent, allowDataSharing);
}
// User accepts tracking via consent dialog
- (void)userAcceptedTracking {
[self saveUserConsent:YES];
[Singular trackingOptIn];
[Singular resumeAllTracking];
NSLog(@"User accepted tracking");
}
// User declines tracking
- (void)userDeclinedTracking {
[self saveUserConsent:NO];
[Singular stopAllTracking];
NSLog(@"User declined tracking");
}
// User updates data sharing preference
- (void)setDataSharingEnabled:(BOOL)enabled {
[self saveDataSharingPreference:enabled];
// Note: limitDataSharing uses inverse logic
[Singular limitDataSharing:!enabled];
NSLog(@"Data sharing: %@", enabled ? @"Enabled" : @"Limited");
}
// Get current tracking status
- (BOOL)isTrackingEnabled {
return ![Singular isAllTrackingStopped];
}
// Private helper methods
- (BOOL)getUserConsent {
return [[NSUserDefaults standardUserDefaults] boolForKey:kConsentKey];
}
- (void)saveUserConsent:(BOOL)consent {
[[NSUserDefaults standardUserDefaults] setBool:consent forKey:kConsentKey];
}
- (BOOL)getDataSharingPreference {
return [[NSUserDefaults standardUserDefaults] boolForKey:kDataSharingKey];
}
- (void)saveDataSharingPreference:(BOOL)enabled {
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:kDataSharingKey];
}
@end
Boas práticas:
- Armazenamento persistente: Salve as preferências do usuário no UserDefaults ou em armazenamento seguro
- Inicialização antecipada: Aplique as configurações de privacidade antes da inicialização do SDK sempre que possível
-
Sincronização da UI:
Mantenha a UI de configurações sincronizada com o estado real do SDK usando
isAllTrackingStopped - Comunicação clara: Forneça controles de privacidade claros e acessíveis nas configurações do app
- Documentação de conformidade: Mantenha registros claros da implementação de privacidade para auditorias regulatórias