Suporte a SKAdNetwork
SKAdNetwork é a estrutura de atribuição focada na privacidade da Apple para campanhas de instalação de aplicativos iOS. O Singular SDK do React Native habilita a SKAdNetwork por padrão no Managed Mode, onde o Singular atualiza automaticamente os valores de conversão com base no modelo de conversão configurado no dashboard.
Não é necessária nenhuma configuração adicional: Se você estiver usando o SDK do React Native mais recente, a SKAdNetwork funcionará imediatamente. Não são necessárias alterações de código ou configurações adicionais para a funcionalidade básica.
Entendendo os modos SKAN
Modo gerenciado (padrão)
No Managed Mode, a Singular lida automaticamente com as atualizações de valores de conversão com base no modelo de conversão configurado no seu painel. Esta é a abordagem recomendada para a maioria das aplicações, uma vez que requer um código mínimo e fornece um rastreamento de conversão ideal.
- Atualizações automáticas: O Singular gerencia todas as atualizações de valores de conversão com base nos eventos do usuário e no seu modelo configurado.
- Configuração do painel: Projete seu modelo de conversão no dashboard do Singular sem alterações de código.
- Otimização: Beneficie-se da experiência da Singular em maximizar as atualizações do valor de conversão dentro das restrições da Apple.
- Gestão de janelas 24 horas: A Singular gere a janela de atualização de 24 horas da SKAdNetwork de forma inteligente para maximizar a recolha de dados.
Modo manual (avançado)
O Modo manual oferece controle total sobre as atualizações de valores de conversão, permitindo implementar uma lógica personalizada para determinar quando e como atualizar os valores de conversão do SKAN. Utilize este modo apenas se tiver requisitos específicos que o Modo Gerido não possa cumprir.
Funcionalidade avançada: O Modo manual requer uma implementação cuidadosa e a compreensão das restrições da SKAdNetwork da Apple, incluindo janelas e limitações de atualização de valores de conversão. A maioria das aplicações deve utilizar o Managed Mode.
Desativar o suporte de SKAdNetwork
O rastreio de SKAdNetwork está ativado por predefinição. Para o desativar, defina a propriedade de configuração skAdNetworkEnabled como false ao criar o objeto SingularConfig.
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
const config: SingularConfig = {
apikey: 'API_KEY',
secret: 'SECRET',
skAdNetworkEnabled: false // Disable SKAdNetwork
};
import { SingularConfig } from 'singular-react-native';
const config = new SingularConfig('API_KEY', 'SECRET')
.withSkAdNetworkEnabled(false); // Disable SKAdNetwork
Configurando o modo manual
Para implementar uma lógica de valor de conversão personalizada, active o Modo manual e utilize os métodos SDK fornecidos para atualizar e monitorizar os valores de conversão ao longo do ciclo de vida da aplicação.
Ativar o Modo manual
Defina a propriedade de configuração manualSkanConversionManagement como true ao criar seu objeto SingularConfig para assumir o controle das atualizações de valores de conversão.
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
const config: SingularConfig = {
apikey: 'API_KEY',
secret: 'SECRET',
manualSkanConversionManagement: true // Enable manual SKAN conversion mode
};
import { SingularConfig } from 'singular-react-native';
const config = new SingularConfig('API_KEY', 'SECRET')
.withManualSkanConversionManagement(); // Enable manual mode
Importante: Os métodos de atualização manual só funcionam quando manualSkanConversionManagement está ativado. Se o Modo gerido estiver ativo, as actualizações manuais serão ignoradas.
Atualizar valor de conversão (SKAN 2.0-3.0)
Utilize o método skanUpdateConversionValue para atualizar manualmente o valor de conversão SKAdNetwork com base na sua lógica personalizada. O valor de conversão tem de ser um número inteiro entre 0 e 63.
Assinatura do método
static skanUpdateConversionValue(conversionValue)
Exemplo de utilização
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
import { Platform } from 'react-native';
// User completed signup - update conversion value to 7
async function onUserSignUp() {
if (Platform.OS === 'ios') {
// Track the sign-up event
NativeSingular.event('SignUp');
// Update SKAN conversion value
const success = await NativeSingular.skanUpdateConversionValue(7);
if (success) {
console.log('Conversion value updated successfully');
} else {
console.warn('Failed to update conversion value');
}
}
}
// User completed purchase - update based on purchase amount
async function onPurchaseComplete(purchaseAmount) {
if (Platform.OS === 'ios') {
// Track revenue event
NativeSingular.revenue('USD', purchaseAmount);
// Calculate conversion value based on purchase tier
const conversionValue = calculateConversionValue(purchaseAmount);
await NativeSingular.skanUpdateConversionValue(conversionValue);
}
}
function calculateConversionValue(amount) {
// Your custom logic to determine conversion value
if (amount >= 100) return 63; // High value
if (amount >= 50) return 40; // Medium value
if (amount >= 10) return 20; // Low value
return 10; // Minimal value
}
import { Singular } from 'singular-react-native';
import { Platform } from 'react-native';
// User completed signup - update conversion value to 7
async function onUserSignUp() {
if (Platform.OS === 'ios') {
// Track the sign-up event
Singular.event('SignUp');
// Update SKAN conversion value
const success = await Singular.skanUpdateConversionValue(7);
if (success) {
console.log('Conversion value updated successfully');
} else {
console.warn('Failed to update conversion value');
}
}
}
// User completed purchase - update based on purchase amount
async function onPurchaseComplete(purchaseAmount) {
if (Platform.OS === 'ios') {
// Track revenue event
Singular.revenue('USD', purchaseAmount);
// Calculate conversion value based on purchase tier
const conversionValue = calculateConversionValue(purchaseAmount);
await Singular.skanUpdateConversionValue(conversionValue);
}
}
function calculateConversionValue(amount) {
// Your custom logic to determine conversion value
if (amount >= 100) return 63; // High value
if (amount >= 50) return 40; // Medium value
if (amount >= 10) return 20; // Low value
return 10; // Minimal value
}
Atualizar valores de conversão (SKAN 4.0)
Para iOS 16.1+, utilize o método skanUpdateConversionValues para atualizar os valores de conversão SKAdNetwork 4.0 com parâmetros de valor fino, valor grosso e bloqueio. Isto proporciona um controlo mais granular sobre as actualizações dos valores de conversão.
Assinatura
static skanUpdateConversionValues(
conversionValue, // Fine value (0-63)
coarse, // Coarse value (0=low, 1=medium, 2=high)
lock // Lock status
)
Exemplo de utilização
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
import { Platform } from 'react-native';
async function updateSKAN4ConversionValue(fineValue, coarseValue, shouldLock) {
if (Platform.OS === 'ios') {
// Map coarse value string to number
const coarseMap = { low: 0, medium: 1, high: 2 };
// Update SKAdNetwork 4.0 conversion values
await NativeSingular.skanUpdateConversionValues(
fineValue,
coarseMap[coarseValue],
shouldLock
);
console.log(`SKAN 4.0 updated: fine=${fineValue}, coarse=${coarseValue}, lock=${shouldLock}`);
}
}
// Example: High-value user completes tutorial
async function onTutorialComplete() {
await updateSKAN4ConversionValue(15, 'medium', false);
}
// Example: Premium purchase - lock the value
async function onPremiumPurchase() {
await updateSKAN4ConversionValue(63, 'high', true);
}
import { Singular } from 'singular-react-native';
import { Platform } from 'react-native';
async function updateSKAN4ConversionValue(fineValue, coarseValue, shouldLock) {
if (Platform.OS === 'ios') {
// Map coarse value string to number
const coarseMap = { low: 0, medium: 1, high: 2 };
// Update SKAdNetwork 4.0 conversion values
Singular.skanUpdateConversionValues(
fineValue,
coarseMap[coarseValue],
shouldLock
);
console.log(`SKAN 4.0 updated: fine=${fineValue}, coarse=${coarseValue}, lock=${shouldLock}`);
}
}
// Example: High-value user completes tutorial
async function onTutorialComplete() {
await updateSKAN4ConversionValue(15, 'medium', false);
}
// Example: Premium purchase - lock the value
async function onPremiumPurchase() {
await updateSKAN4ConversionValue(63, 'high', true);
}
Obter valor de conversão atual
Recupera o valor de conversão atual monitorizado pelo SDK Singular. Isso é útil para implementar a lógica condicional com base no estado atual e funciona nos modos Gerenciado e Manual.
Assinatura
static skanGetConversionValue()
Exemplo de uso
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
import { Platform } from 'react-native';
async function checkAndUpdateConversionValue() {
if (Platform.OS === 'ios') {
const currentValue = await NativeSingular.skanGetConversionValue();
if (currentValue !== null) {
console.log(`Current conversion value: ${currentValue}`);
// Only update if current value is below threshold
if (currentValue < 30) {
await NativeSingular.skanUpdateConversionValue(30);
console.log('Updated conversion value to 30');
}
} else {
console.warn('Conversion value not available');
}
}
}
import { Singular } from 'singular-react-native';
import { Platform } from 'react-native';
async function checkAndUpdateConversionValue() {
if (Platform.OS === 'ios') {
const currentValue = await Singular.skanGetConversionValue();
if (currentValue !== null) {
console.log(`Current conversion value: ${currentValue}`);
// Only update if current value is below threshold
if (currentValue < 30) {
await Singular.skanUpdateConversionValue(30);
console.log('Updated conversion value to 30');
}
} else {
console.warn('Conversion value not available');
}
}
}
Monitorar atualizações de valor de conversão
Configure um manipulador para receber notificações em tempo real sempre que o valor de conversão for alterado. Isto permite-lhe reagir às actualizações do valor de conversão e registar análises ou desencadear outros comportamentos da aplicação.
Configuração
Configure o manipulador de atualização do valor de conversão usando o método withConversionValueUpdatedHandler ao inicializar o SDK.
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
import { NativeEventEmitter } from 'react-native';
const config: SingularConfig = {
apikey: 'API_KEY',
secret: 'SECRET'
};
NativeSingular.init(config);
const emitter = new NativeEventEmitter(NativeSingular);
// Listen for conversion value updates
emitter.addListener('ConversionValueUpdatedHandler', (conversionValue) => {
console.log(`Conversion value updated to: ${conversionValue}`);
// Log the update to your analytics
logConversionValueUpdate(conversionValue);
// Trigger app-specific behavior
if (conversionValue >= 50) {
unlockPremiumFeature();
}
});
function logConversionValueUpdate(value) {
// Your analytics logging logic
console.log(`Analytics: SKAN CV = ${value}`);
}
function unlockPremiumFeature() {
// Your custom logic
console.log('Premium feature unlocked based on high conversion value');
}
import { Singular, SingularConfig } from 'singular-react-native';
const config = new SingularConfig('API_KEY', 'SECRET')
.withConversionValueUpdatedHandler((conversionValue) => {
console.log(`Conversion value updated to: ${conversionValue}`);
// Log the update to your analytics
logConversionValueUpdate(conversionValue);
// Trigger app-specific behavior
if (conversionValue >= 50) {
unlockPremiumFeature();
}
});
Singular.init(config);
function logConversionValueUpdate(value) {
// Your analytics logging logic
console.log(`Analytics: SKAN CV = ${value}`);
}
function unlockPremiumFeature() {
// Your custom logic
console.log('Premium feature unlocked based on high conversion value');
}
Melhores práticas: Use o manipulador de valor de conversão para manter uma exibição sincronizada do estado de conversão atual em todo o aplicativo. Isso é especialmente útil para depurar e garantir que sua lógica personalizada funcione corretamente.
Suporte ao App Tracking Transparency (ATT)
O App Tracking Transparency (ATT) é a estrutura de privacidade da Apple que requer o consentimento do utilizador antes de aceder ao IDFA (Identificador para Anunciantes) do dispositivo e partilhar dados do utilizador. A implementação correta da ATT é fundamental para a atribuição do iOS e para maximizar a precisão das suas campanhas de aquisição de utilizadores.
Por que a ATT é importante para a atribuição
A partir do iOS 14.5, os aplicativos devem solicitar permissão do usuário por meio da estrutura ATT antes de acessar o IDFA. Embora a atribuição ainda seja possível sem o IDFA usando impressão digital e métodos probabilísticos, ter o IDFA melhora significativamente a precisão da atribuição e fornece correspondência determinística.
- Atribuição determinística: O IDFA permite uma atribuição precisa, ao nível do dispositivo, que liga as impressões de anúncios diretamente às instalações.
- Otimização da rede de anúncios: As redes de anúncios podem otimizar melhor as campanhas e fornecer relatórios mais precisos com o acesso ao IDFA.
- Informações ao nível do utilizador: O acesso ao IDFA permite uma análise mais granular do comportamento do utilizador e um acompanhamento de coortes.
Recomendação: A Singular recomenda vivamente a implementação do prompt ATT e o pedido de consentimento do utilizador. Explique os benefícios aos utilizadores (anúncios personalizados, melhor experiência de aplicação) para maximizar as taxas de aceitação.
Requisitos de implementação
Para iOS 14.5+ (incluindo iOS 18), use a estrutura ATTrackingManager para solicitar o consentimento do usuário antes de acessar o IDFA para rastreamento. O SDK Singular é compatível com ATT, permitindo a inicialização antes do consentimento e atrasando eventos até que o consentimento seja concedido ou ocorra um tempo limite.
Etapa 1: Adicionar configuração de estrutura ATT
Configure seu aplicativo iOS para oferecer suporte à estrutura ATT atualizando seu arquivo Info.plist com uma descrição de uso voltada para o usuário.
-
Abra o Info.plist: Navegue até ao ficheiro Info.plist do seu projeto iOS (localizado em
ios/[YourAppName]/Info.plist). -
Adicionar descrição de utilização: Adicione a chave
NSUserTrackingUsageDescriptioncom uma explicação clara do motivo pelo qual a sua aplicação necessita de permissão de rastreio.
<key>NSUserTrackingUsageDescription</key>
<string>This app uses tracking to provide personalized ads and improve your experience.</string>
Importante: A descrição de utilização será apresentada aos utilizadores no prompt ATT. Seja claro, conciso e honesto sobre como o rastreio os beneficia.
Etapa 2: Instalar o pacote de suporte da ATT
Instale o pacote de suporte React Native ATT para ativar a funcionalidade ATT na sua aplicação.
npm install react-native-tracking-transparency --save
Após a instalação, execute pod install a partir do seu diretório iOS para ligar as dependências nativas.
cd ios && pod install && cd ..
Etapa 3: Configurar o tempo limite de espera do SDK
Configure o Singular SDK para aguardar a resposta ATT do usuário antes de inicializar, definindo a propriedade waitForTrackingAuthorizationWithTimeoutInterval. Esse atraso garante que o IDFA seja capturado se o usuário conceder permissão.
Crítico: Sempre solicite o consentimento ATT e recupere o IDFA antes que o Singular SDK envie sua primeira sessão. Se não o fizer, perderá permanentemente o IDFA para os dados de atribuição desse dispositivo.
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
const config: SingularConfig = {
apikey: 'API_KEY',
secret: 'SECRET',
waitForTrackingAuthorizationWithTimeoutInterval: 300 // Wait up to 5 minutes
};
import { SingularConfig } from 'singular-react-native';
const config = new SingularConfig('API_KEY', 'SECRET')
.withWaitForTrackingAuthorizationWithTimeoutInterval(300); // Wait up to 5 minutes
Valor recomendado: Defina o tempo limite para 300 segundos (5 minutos) se seu aplicativo exibir o prompt ATT. Isto proporciona tempo suficiente para que o utilizador veja e responda à mensagem sem criar uma má experiência de utilização se a mensagem for atrasada ou não for apresentada.
Passo 4: Pedir o consentimento da ATT
Implemente o fluxo de pedidos ATT na sua aplicação, solicitando aos utilizadores a permissão de rastreio num momento adequado da sua experiência de utilizador.
// TurboModule direct API (React Native 0.76+ New Architecture)
import React, { useEffect } from 'react';
import { Platform } from 'react-native';
import NativeSingular from 'singular-react-native/jsNativeSingular';
import { requestTrackingPermission } from 'react-native-tracking-transparency';
export default function App() {
useEffect(() => {
initializeApp();
}, []);
async function initializeApp() {
if (Platform.OS === 'ios') {
// Request ATT authorization
const trackingStatus = await requestTrackingPermission();
// Log the user's response
console.log('ATT Status:', trackingStatus);
// Possible values: 'authorized', 'denied', 'restricted', 'unavailable'
}
// Initialize Singular SDK (configured with wait timeout)
const config: SingularConfig = {
apikey: 'API_KEY',
secret: 'SECRET',
waitForTrackingAuthorizationWithTimeoutInterval: 300,
loggingEnabled: true,
};
NativeSingular.init(config);
}
return (
// Your app components go here
null
);
}
import React, { useEffect } from 'react';
import { Platform } from 'react-native';
import { Singular, SingularConfig } from 'singular-react-native';
import { requestTrackingPermission, getTrackingStatus } from 'react-native-tracking-transparency';
export default function App() {
useEffect(() => {
initializeApp();
}, []);
async function initializeApp() {
if (Platform.OS === 'ios') {
// Request ATT authorization
const trackingStatus = await requestTrackingPermission();
// Log the user's response
console.log('ATT Status:', trackingStatus);
// Possible values: 'authorized', 'denied', 'restricted', 'unavailable'
}
// Initialize Singular SDK (configured with wait timeout)
const config = new SingularConfig('API_KEY', 'SECRET')
.withWaitForTrackingAuthorizationWithTimeoutInterval(300)
.withLoggingEnabled();
Singular.init(config);
}
return (
// Your app components
);
}
Melhores práticas da ATT
- Mensagens pré-prompt: Mostre aos utilizadores um ecrã pré-ATT que explique por que motivo necessita de permissão de seguimento e como isso os beneficia (melhores anúncios, experiência melhorada). Isto pode aumentar significativamente as taxas de aceitação.
- O momento é importante: Mostre o prompt ATT em um momento natural no fluxo do aplicativo, não imediatamente no primeiro lançamento. Deixe que os utilizadores experimentem a sua aplicação primeiro para criar confiança.
-
Configuração do tempo limite: Defina
waitForTrackingAuthorizationWithTimeoutIntervalpara 30-300 segundos. Após o tempo limite, o Singular prossegue com a atribuição SKAN 4.0 (sem IDFA). - Teste minuciosamente: Teste cenários autorizados e negados para garantir que seu aplicativo funcione corretamente, independentemente da escolha do usuário.
- Respeitar a escolha do utilizador: Nunca solicite repetidamente aos utilizadores que tenham negado o rastreio ou mostre mensagens agressivas que os pressionem a aceitar.
-
Tratamento de erros: Verifique o estado do rastreio para
restricted(por exemplo, controlos parentais) ouunavailableestados e registe para análise.
Revisão da App Store: As aplicações que não implementem corretamente a ATT ou que tentem contornar a estrutura podem ser rejeitadas durante a revisão da App Store. Certifique-se de que a sua implementação segue as diretrizes da Apple e respeita as opções de privacidade do utilizador.