Guia de Implementação de Rastreamento de Eventos de Assinatura
Implemente o rastreamento abrangente de assinaturas para medir a receita de assinaturas, a retenção de usuários e o desempenho de campanhas em todas as plataformas usando o SDK da Singular, integração server-to-server ou parceiros terceiros.
A Singular possibilita a atribuição precisa de eventos de assinatura—incluindo novas assinaturas, renovações, testes, cancelamentos e reembolsos—às campanhas de marketing que geraram os usuários, oferecendo visibilidade completa do ciclo de vida da assinatura e da geração de receita.
Opções de Implementação
Escolha o método de implementação que melhor se adequa à arquitetura do seu app e aos requisitos do seu negócio.
| Consideração | Integração por SDK | Server-to-Server (S2S) | Integração com Terceiros |
|---|---|---|---|
| Implementação | Envie eventos de assinatura por meio de métodos de receita personalizados no SDK da Singular | Envie eventos do seu backend para a REST API da Singular com as propriedades de dispositivo móvel necessárias | Configure integrações com RevenueCat, Adapty, Superwall, Xsolla ou outras plataformas de assinatura |
| Dependência da Atividade do App | O app precisa ser iniciado para que o SDK envie os eventos | Eventos enviados em tempo real, independentemente do estado do app | Eventos enviados em tempo real pela plataforma parceira |
| Momento do Evento | O horário do evento pode diferir do horário real da assinatura, dependendo da inicialização do app | Rastreamento de eventos em tempo real conforme processados no backend | Rastreamento em tempo quase real após o processamento do parceiro |
| Complexidade | Implementação simples no lado do cliente | Requer uma infraestrutura de backend segura | Requer conta e configuração do parceiro |
Importante: A maioria dos clientes que usa integrações S2S ou de terceiros para eventos de assinatura ainda deve integrar o SDK da Singular para gerenciar sessões e eventos que não são de assinatura, para um rastreamento de atribuição completo.
Android: Integração com o Google Play Billing
Integre a Google Play Billing Library 8.0.0 para consultar informações de assinatura e gerenciar o estado da assinatura diretamente no dispositivo para a integração com o SDK da Singular.
Pré-requisitos
Configurar o Google Play Console
Configure produtos in-app e itens de assinatura no Google Play Console antes de implementar o billing no seu app.
- Criar Produtos de Assinatura: Defina os níveis de assinatura, os períodos de cobrança e os preços no Play Console
- Configurar Ofertas: Configure planos base, tokens de oferta e preços promocionais
- Configurar Testes: Crie contas de teste e verifique a disponibilidade dos produtos
Adicionar a Dependência da Billing Library
Atualizar o build.gradle
Adicione a Google Play Billing Library 8.0.0 às dependências do seu app com as extensões Kotlin para suporte a coroutines.
dependencies {
val billingVersion = "8.0.0"
// Google Play Billing Library
implementation("com.android.billingclient:billing:$billingVersion")
// Kotlin extensions and coroutines support
implementation("com.android.billingclient:billing-ktx:$billingVersion")
}
Recursos da Versão 8.0.0:
Esta versão introduz
a reconexão automática de serviço com
enableAutoServiceReconnection()
, APIs de consulta de compras aprimoradas
e um tratamento melhorado de transações pendentes.
Inicializar o BillingClient
Criar o Billing Manager
Configure uma classe de billing manager para lidar com todas as operações de assinatura e integrar com o SDK da Singular para o rastreamento de eventos.
class SubscriptionManager(private val context: Context) {
private val purchasesUpdatedListener = PurchasesUpdatedListener { billingResult, purchases ->
when (billingResult.responseCode) {
BillingResponseCode.OK -> {
purchases?.forEach { purchase ->
handlePurchaseUpdate(purchase)
}
}
BillingResponseCode.USER_CANCELED -> {
Log.d(TAG, "User canceled the purchase")
}
else -> {
Log.e(TAG, "Purchase error: ${billingResult.debugMessage}")
}
}
}
private val billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases() // Required for all purchases
.enableAutoServiceReconnection() // NEW in 8.0.0 - handles reconnection automatically
.build()
fun initialize() {
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingResponseCode.OK) {
Log.d(TAG, "Billing client ready")
// Query existing subscriptions
queryExistingSubscriptions()
} else {
Log.e(TAG, "Billing setup failed: ${billingResult.debugMessage}")
}
}
override fun onBillingServiceDisconnected() {
// With enableAutoServiceReconnection(), SDK handles reconnection
// Manual retry is no longer required
Log.d(TAG, "Billing service disconnected - auto-reconnection enabled")
}
})
}
companion object {
private const val TAG = "SubscriptionManager"
}
}
Recursos Principais:
-
Reconexão Automática:
O
enableAutoServiceReconnection()da versão 8.0.0 restabelece automaticamente as conexões quando necessário - Purchase Listener: Recebe callbacks para todas as atualizações de compra, incluindo renovações e transações pendentes
- Tratamento de Erros: Tratamento abrangente para cancelamentos de usuários e erros de billing
Consultar Informações de Assinatura
Recuperar Assinaturas Ativas
Consulte assinaturas existentes usando
queryPurchasesAsync()
para lidar com renovações e assinaturas compradas fora do seu app.
private suspend fun queryExistingSubscriptions() {
val params = QueryPurchasesParams.newBuilder()
.setProductType(BillingClient.ProductType.SUBS)
.build()
withContext(Dispatchers.IO) {
val result = billingClient.queryPurchasesAsync(params)
if (result.billingResult.responseCode == BillingResponseCode.OK) {
result.purchasesList.forEach { purchase ->
when (purchase.purchaseState) {
Purchase.PurchaseState.PURCHASED -> {
// Active subscription - process it
handleSubscriptionPurchase(purchase)
}
Purchase.PurchaseState.PENDING -> {
// Pending payment - notify user
Log.d(TAG, "Subscription pending: ${purchase.products}")
}
}
}
} else {
Log.e(TAG, "Query failed: ${result.billingResult.debugMessage}")
}
}
}
Boa Prática:
Chame
queryPurchasesAsync()
em
onResume()
para capturar renovações de assinatura que ocorreram
enquanto seu app estava em segundo plano ou fechado.
Consultar Detalhes do Produto
Recupere os detalhes do produto de assinatura, incluindo preços, períodos de cobrança e tokens de oferta, antes de exibi-los aos usuários.
private suspend fun querySubscriptionProducts() {
val productList = listOf(
QueryProductDetailsParams.Product.newBuilder()
.setProductId("premium_monthly")
.setProductType(BillingClient.ProductType.SUBS)
.build(),
QueryProductDetailsParams.Product.newBuilder()
.setProductId("premium_yearly")
.setProductType(BillingClient.ProductType.SUBS)
.build()
)
val params = QueryProductDetailsParams.newBuilder()
.setProductList(productList)
.build()
withContext(Dispatchers.IO) {
val productDetailsResult = billingClient.queryProductDetails(params)
if (productDetailsResult.billingResult.responseCode == BillingResponseCode.OK) {
// Process successfully retrieved product details
productDetailsResult.productDetailsList?.forEach { productDetails ->
// Extract subscription offers
productDetails.subscriptionOfferDetails?.forEach { offer ->
val price = offer.pricingPhases.pricingPhaseList.firstOrNull()
Log.d(TAG, "Product: ${productDetails.productId}, Price: ${price?.formattedPrice}")
}
}
// Handle unfetched products
productDetailsResult.unfetchedProductList?.forEach { unfetchedProduct ->
Log.w(TAG, "Unfetched: ${unfetchedProduct.productId}")
}
}
}
}
Processar Atualizações de Compra
Tratar Eventos de Assinatura
Processe as mudanças de estado da compra e envie os eventos apropriados para a Singular com base no ciclo de vida da assinatura.
private fun handlePurchaseUpdate(purchase: Purchase) {
when (purchase.purchaseState) {
Purchase.PurchaseState.PURCHASED -> {
if (!purchase.isAcknowledged) {
// Verify purchase on your backend first
verifyPurchaseOnBackend(purchase) { isValid ->
if (isValid) {
// Send subscription event to Singular
trackSubscriptionToSingular(purchase)
// Grant entitlement to user
grantSubscriptionAccess(purchase)
// Acknowledge purchase to Google
acknowledgePurchase(purchase)
}
}
}
}
Purchase.PurchaseState.PENDING -> {
// Notify user that payment is pending
Log.d(TAG, "Purchase pending approval: ${purchase.products}")
notifyUserPendingPayment(purchase)
}
}
}
private fun trackSubscriptionToSingular(purchase: Purchase) {
// Get cached product details for pricing information
val productDetails = getCachedProductDetails(purchase.products.first())
productDetails?.let { details ->
val subscriptionOffer = details.subscriptionOfferDetails?.firstOrNull()
val pricingPhase = subscriptionOffer?.pricingPhases?.pricingPhaseList?.firstOrNull()
val price = pricingPhase?.priceAmountMicros?.div(1_000_000.0) ?: 0.0
val currency = pricingPhase?.priceCurrencyCode ?: "USD"
// Determine event name based on purchase type
val eventName = if (isNewSubscription(purchase)) {
"sng_subscribe"
} else {
"subscription_renewed"
}
// Send to Singular WITHOUT receipt
Singular.customRevenue(
eventName,
currency,
price,
mapOf(
"subscription_id" to purchase.products.first(),
"order_id" to (purchase.orderId ?: ""),
"purchase_time" to purchase.purchaseTime.toString()
)
)
Log.d(TAG, "Tracked $eventName to Singular: $price $currency")
}
}
private fun acknowledgePurchase(purchase: Purchase) {
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
.build()
lifecycleScope.launch {
val ackResult = withContext(Dispatchers.IO) {
billingClient.acknowledgePurchase(acknowledgePurchaseParams)
}
if (ackResult.responseCode == BillingResponseCode.OK) {
Log.d(TAG, "Purchase acknowledged successfully")
} else {
Log.e(TAG, "Acknowledgement failed: ${ackResult.debugMessage}")
}
}
}
Crítico:
NÃO envie o recibo do Google Play para a
Singular ao rastrear eventos de assinatura. Use o método
customRevenue()
sem validação de recibo. Confirme as
compras dentro de 3 dias, ou elas serão reembolsadas automaticamente.
iOS: Integração com o StoreKit
Integre o framework StoreKit da Apple para gerenciar assinaturas e enviar eventos para a Singular em apps iOS.
Pré-requisitos
Configurar o App Store Connect
Configure produtos de assinatura e grupos de assinatura no App Store Connect antes de implementar o StoreKit no seu app.
- Criar Grupos de Assinatura: Organize as assinaturas em grupos com base nos níveis de acesso
- Definir Produtos de Assinatura: Configure os níveis de assinatura, as durações e os preços
- Configurar Ofertas: Crie ofertas introdutórias, ofertas promocionais e códigos de assinatura
- Ambiente de Teste: Configure contas de teste sandbox para o desenvolvimento
Implementar o StoreKit
Configurar o Transaction Observer
Implemente o
SKPaymentTransactionObserver
para receber notificações
de compra de assinatura e renovações.
import StoreKit
class SubscriptionManager: NSObject, SKPaymentTransactionObserver {
static let shared = SubscriptionManager()
private override init() {
super.init()
// Add transaction observer
SKPaymentQueue.default().add(self)
}
deinit {
SKPaymentQueue.default().remove(self)
}
// MARK: - SKPaymentTransactionObserver
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .purchased:
// New subscription or renewal
handlePurchasedTransaction(transaction)
case .restored:
// Subscription restored from another device
handleRestoredTransaction(transaction)
case .failed:
// Purchase failed
handleFailedTransaction(transaction)
case .deferred:
// Purchase awaiting approval (family sharing)
print("Transaction deferred: \(transaction.payment.productIdentifier)")
case .purchasing:
// Transaction in progress
break
@unknown default:
break
}
}
}
private func handlePurchasedTransaction(_ transaction: SKPaymentTransaction) {
// Verify receipt with your backend
verifyReceipt { isValid in
if isValid {
// Send to Singular
self.trackSubscriptionToSingular(transaction)
// Grant entitlement
self.grantSubscriptionAccess(transaction)
// Finish transaction
SKPaymentQueue.default().finishTransaction(transaction)
}
}
}
private func trackSubscriptionToSingular(_ transaction: SKPaymentTransaction) {
// Get product details for pricing
let productId = transaction.payment.productIdentifier
// You should cache product details from SKProductsRequest
if let product = getCachedProduct(productId) {
let price = product.price.doubleValue
let currency = product.priceLocale.currencyCode ?? "USD"
// Determine event name
let eventName = isNewSubscription(transaction) ? "sng_subscribe" : "subscription_renewed"
// Send to Singular WITHOUT receipt
Singular.customRevenue(
eventName,
currency: currency,
amount: price,
withAttributes: [
"subscription_id": productId,
"transaction_id": transaction.transactionIdentifier ?? "",
"transaction_date": transaction.transactionDate?.timeIntervalSince1970 ?? 0
]
)
}
}
}
Consultar o Status da Assinatura
Use a validação de recibo para verificar o status atual da assinatura e tratar as renovações.
func refreshSubscriptionStatus() {
let request = SKReceiptRefreshRequest()
request.delegate = self
request.start()
}
extension SubscriptionManager: SKRequestDelegate {
func requestDidFinish(_ request: SKRequest) {
// Receipt refreshed successfully
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
// Send receipt to your backend for validation
validateReceiptOnServer()
}
}
func request(_ request: SKRequest, didFailWithError error: Error) {
print("Receipt refresh failed: \(error.localizedDescription)")
}
}
Método de Integração por SDK
Envie eventos de assinatura a partir do seu app usando os métodos de receita personalizados do SDK da Singular, sem validação de recibo.
Métodos de SDK Específicos por Plataforma
Use o método de SDK apropriado para a sua plataforma para rastrear os eventos de assinatura.
SDK do Android
// Track subscription without receipt
Singular.customRevenue(
"sng_subscribe", // Event name
"USD", // Currency
9.99, // Amount
mapOf( // Additional attributes
"subscription_id" to "premium_monthly",
"billing_period" to "monthly"
)
)
Documentação: Rastreamento de Receita do SDK do Android
SDK do iOS
// Track subscription without receipt
Singular.customRevenue(
"sng_subscribe", // Event name
currency: "USD", // Currency
amount: 9.99, // Amount
withAttributes: [ // Additional attributes
"subscription_id": "premium_monthly",
"billing_period": "monthly"
]
)
Documentação: Rastreamento de Receita do SDK do iOS
SDK do React Native
// Track subscription without receipt
Singular.customRevenueWithArgs(
"sng_subscribe", // Event name
"USD", // Currency
9.99, // Amount
{ // Additional attributes
subscription_id: "premium_monthly",
billing_period: "monthly"
}
);
Documentação: Rastreamento de Receita do SDK do React Native
SDK do Unity
// Track subscription without receipt
SingularSDK.CustomRevenue(
"sng_subscribe", // Event name
"USD", // Currency
9.99, // Amount
new Dictionary<string, object> { // Additional attributes
{ "subscription_id", "premium_monthly" },
{ "billing_period", "monthly" }
}
);
Documentação: Rastreamento de Receita do SDK do Unity
SDK do Flutter
// Track subscription without receipt
Singular.customRevenueWithAttributes(
"sng_subscribe", // Event name
"USD", // Currency
9.99, // Amount
{ // Additional attributes
"subscription_id": "premium_monthly",
"billing_period": "monthly"
}
);
Documentação: Rastreamento de Receita do SDK do Flutter
SDK do Cordova
// Track subscription without receipt
cordova.plugins.SingularCordovaSdk.customRevenueWithArgs(
"sng_subscribe", // Event name
"USD", // Currency
9.99, // Amount
{ // Additional attributes
subscription_id: "premium_monthly",
billing_period: "monthly"
}
);
Documentação: Rastreamento de Receita do SDK do Cordova
Crítico:
NÃO use métodos de IAP (In-App Purchase)
nem envie valores de recibo para a Singular no rastreamento de assinaturas. Use apenas
os métodos
customRevenue()
sem recibos.
Integração Server-to-Server
Envie eventos de assinatura em tempo real do seu backend para a REST API da Singular para um rastreamento imediato, independente do estado do app.
Requisitos de Implementação
Use o Event Endpoint da Singular para enviar eventos de assinatura com parâmetros de receita a partir do seu backend seguro.
Event Endpoint
Envie requisições POST para a Event API da Singular com os dados do evento de assinatura e as propriedades de dispositivo móvel necessárias.
Endpoint:
POST https://api.singular.net/api/v1/evt
Parâmetros Obrigatórios:
-
SDK Key:
Sua chave SDK da Singular (parâmetro
a) -
Event Name:
Nome do evento de assinatura (parâmetro
n) -
Revenue:
Valor da assinatura (parâmetro
amt) -
Currency:
Código de moeda ISO 4217 (parâmetro
cur) - Device Identifiers: IDFA (iOS) ou GAID (Android) para atribuição
-
Platform:
Sistema operacional (parâmetro
p)
Documentação: Referência do Event Endpoint e Parâmetros de Receita
Exemplo de Requisição
curl -X POST 'https://api.singular.net/api/v1/evt' \
-H 'Content-Type: application/json' \
-d '{
"a": "YOUR_SDK_KEY",
"n": "sng_subscribe",
"r": 9.99,
"pcc": "USD",
"idfa": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"p": "iOS",
"install_time": 1697000000000,
"extra": {
"subscription_id": "premium_monthly",
"order_id": "GPA.1234.5678.9012"
}
}'
SDK Não Necessário: Se você usar S2S para eventos de assinatura, não precisa enviar esses eventos pelo SDK. No entanto, a maioria dos apps ainda deve integrar o SDK para o rastreamento de sessões e eventos que não são de assinatura.
Integrações com Terceiros
Configure o rastreamento de assinaturas por meio de plataformas de terceiros que gerenciam a infraestrutura de assinatura e enviam eventos diretamente para a Singular.
Parceiros Suportados
Integre com plataformas de gerenciamento de assinaturas que têm suporte nativo à Singular.
Integração com o RevenueCat
O RevenueCat gerencia a infraestrutura de assinatura e envia automaticamente os eventos de assinatura para a REST API da Singular.
Etapas de Configuração:
- Criar Conta no RevenueCat: Configure seu app no dashboard do RevenueCat
- Configurar a Integração com a Singular: Adicione a chave SDK da Singular nas configurações de integrações do RevenueCat
- Mapear Eventos: Configure quais eventos do RevenueCat devem ser enviados para a Singular
- Testar a Integração: Verifique se os eventos aparecem no dashboard da Singular
Documentação: Integração RevenueCat com Singular
Integração com o Adapty
O Adapty fornece análises de assinatura e envia eventos para a Singular por meio da integração dele.
Etapas de Configuração:
- Criar Conta no Adapty: Registre e configure seu app no Adapty
- Habilitar a Integração com a Singular: Acesse as integrações e adicione as credenciais da Singular
- Configurar o Mapeamento de Eventos: Selecione quais eventos de assinatura encaminhar
- Verificar o Fluxo de Dados: Confirme se os eventos chegam à Singular com sucesso
Documentação: Integração Adapty com Singular
Integração com o Superwall
Conecte a Singular para receber eventos de ciclo de vida de assinatura e de receita do Superwall, com suporte a SDID para uma atribuição mais robusta.
Etapas de Configuração:
- Integrar o SDK da Singular: Adicione o SDK da Singular ao seu app para o rastreamento de sessões e eventos
- Configurar o Singular SDID (Opcional): Configure o Singular SDID e atualize os atributos de usuário do Superwall com o SDID no seu app para uma atribuição mais robusta
- Adicionar a Integração com a Singular no Superwall: Habilite e configure a integração com a Singular no seu dashboard do Superwall
Documentação: Integração Superwall com Singular
Integração com o Xsolla
O Xsolla envia informações sobre compras no Web Shop para a Singular como eventos in-app móveis, que a Singular então atribui a instalações de aplicativos móveis, aquisição de usuários e campanhas de re-engajamento.
Etapas de Configuração:
- Integrar a Singular nos Seus Apps Móveis: Adicione o SDK da Singular aos seus apps móveis
- Configurar um Evento In-App: Envie um evento in-app para a Singular, por exemplo, login, ou qualquer outro evento que inclua o CUID
- Configurar a Partner Configuration da Singular: Configure a partner configuration da Singular para o Xsolla
- Adicionar a Singular na Sua Conta Xsolla: Habilite a Singular na sua conta Xsolla
Documentação: Integração Xsolla com Singular
Observação: As integrações com terceiros são gerenciadas pelas plataformas parceiras. A configuração deve ser concluída nos respectivos dashboards delas. O SDK da Singular ainda deve ser integrado para o rastreamento de sessões e de eventos que não são de assinatura.
Tipos de Eventos de Assinatura
Rastreie diversos eventos do ciclo de vida da assinatura para medir o engajamento dos usuários, a retenção e a receita ao longo de toda a jornada de assinatura.
Nomes de Eventos Padrão
Use os nomes de eventos padrão da Singular para relatórios consistentes entre plataformas, ou defina nomes de eventos personalizados com base nos seus requisitos de rastreamento.
| Estado da Assinatura | Nome do Evento | Método do SDK | Integração S2S |
|---|---|---|---|
| Nova Assinatura |
sng_subscribe
|
customRevenue() com valor de receita (sem recibo) | Event endpoint com parâmetros de receita |
| Início do Teste |
sng_start_trial
|
método event() sem receita | Event endpoint padrão sem receita |
| Fim do Teste |
sng_end_trial
|
método event() sem receita | Event endpoint padrão sem receita |
| Renovação da Assinatura |
subscription_renewed
|
customRevenue() com valor de receita (sem recibo) | Event endpoint com parâmetros de receita |
| Cancelamento |
subscription_cancelled
|
método event() sem receita | Event endpoint padrão sem receita |
| Reembolso |
subscription_refunded
|
customRevenue() com valor negativo (opcional) OU event() sem receita | Event endpoint com receita negativa (opcional) OU evento padrão |
Importante:
Ao enviar eventos de assinatura via
customRevenue(), envie apenas eventos em que
isRestored
seja
false
. Compras restauradas representam assinaturas existentes,
não uma nova receita.
Exemplos de Implementação de Eventos
Nova Assinatura
Rastreie quando os usuários compram uma nova assinatura pela primeira vez.
// New subscription purchase
Singular.customRevenue(
"sng_subscribe",
"USD",
9.99,
mapOf(
"subscription_tier" to "premium",
"billing_period" to "monthly",
"product_id" to "premium_monthly"
)
)
Início do Teste
Rastreie quando os usuários iniciam um período de teste gratuito, sem receita.
// Trial start (no revenue)
Singular.event(
"sng_start_trial",
mapOf(
"trial_duration" to "7_days",
"subscription_tier" to "premium"
)
)
Renovação da Assinatura
Rastreie renovações automáticas de assinatura com o valor de receita.
// Subscription renewal
Singular.customRevenue(
"subscription_renewed",
"USD",
9.99,
mapOf(
"subscription_tier" to "premium",
"renewal_count" to 3,
"product_id" to "premium_monthly"
)
)
Cancelamento
Rastreie quando os usuários cancelam a assinatura (evento sem receita).
// Subscription cancelled (no revenue)
Singular.event(
"subscription_cancelled",
mapOf(
"cancellation_reason" to "too_expensive",
"days_active" to 45,
"subscription_tier" to "premium"
)
)
Medição pelo SKAdNetwork
Meça eventos de assinatura por meio do SKAdNetwork da Apple para uma atribuição no iOS em conformidade com a privacidade.
Suporte a Assinaturas no SKAN
A Singular pode medir dados de eventos de assinatura por todos os métodos de integração (SDK, S2S e terceiros). A medição de eventos pode ser limitada pelas janelas de tempo dos postbacks do SKAN, dependendo da versão do SKAN.
Implementação de SKAN Híbrido
Para apps que usam o SDK da Singular para eventos de ciclo de vida e integrações S2S/de terceiros para assinaturas, habilite o SKAN Híbrido para combinar as duas fontes de dados.
Entre em Contato com o Suporte: Fale com seu Customer Success Manager (CSM) para habilitar o SKAN Híbrido para o seu app. Isso garante que os eventos de assinatura de fontes de backend sejam devidamente atribuídos aos conversion values do SKAN.
Janelas de Postback do SKAN:
- SKAN 4.0: Três janelas de postback (0-2 dias, 3-7 dias, 8-35 dias) possibilitam a medição de eventos de assinatura iniciais e renovações de curto prazo
- SKAN 3.0: Uma única janela de postback de 24 horas limita a medição apenas às assinaturas imediatas
- Conversion Values: Configure eventos de assinatura no seu esquema de conversion value do SKAN para priorizar eventos de alto valor
Boas Práticas e Validação
Siga as boas práticas de implementação e verifique se o rastreamento de assinaturas está funcionando corretamente antes da implantação em produção.
Boas Práticas de Implementação
Diretrizes Principais
- Sem Validação de Recibo: Nunca envie recibos da plataforma (Google Play, App Store) para a Singular ao rastrear assinaturas—use customRevenue() sem recibos
- Filtrar Compras Restauradas: Envie apenas eventos em que isRestored seja false, para evitar relatórios de receita duplicados
- Verificação no Backend: Sempre verifique as compras no seu backend seguro antes de enviar os eventos para a Singular
- Confirmação Oportuna: Confirme as compras do Google Play dentro de 3 dias para evitar reembolsos automáticos
- Consultar no Resume: Chame queryPurchasesAsync() em onResume() para capturar renovações que ocorreram enquanto o app estava fechado
- Nomes de Eventos Consistentes: Use os nomes de eventos padrão da Singular (sng_subscribe, subscription_renewed) para relatórios unificados
- Incluir Metadados: Adicione atributos como subscription_tier, billing_period e product_id para uma análise detalhada
Testes e Validação
Checklist de Testes
- Configuração do Ambiente de Teste: Use contas sandbox/de teste para o Google Play e a App Store
- Nova Assinatura: Verifique se o evento sng_subscribe é enviado corretamente, com o valor e a moeda adequados
- Fluxo de Teste: Teste os eventos de início e fim do teste sem receita
- Tratamento de Renovação: Confirme que as renovações disparam eventos subscription_renewed com a receita correta
- Rastreamento de Cancelamento: Verifique se os eventos de cancelamento disparam quando os usuários cancelam as assinaturas
- Filtragem de Restauração: Garanta que as compras restauradas não enviem eventos duplicados
- Dashboard da Singular: Verifique se os eventos aparecem na Singular com a atribuição correta
- Entre Dispositivos: Teste a sincronização de assinaturas em vários dispositivos
Problemas Comuns
- Eventos Ausentes: Verifique se a conexão do billing client está ativa e se queryPurchasesAsync() é chamado ao retomar o app
- Eventos Duplicados: Verifique se as compras restauradas estão devidamente filtradas com a verificação de isRestored
- Receita Incorreta: Garanta que a extração de preço do ProductDetails divide corretamente os micros por 1.000.000
- Problemas de Atribuição: Confirme que os identificadores de dispositivo (IDFA/GAID) estão devidamente incluídos nas requisições S2S
- Falhas de Confirmação: Verifique se a validação de recibo no backend é concluída antes da confirmação
Recursos de Suporte: Para assistência na resolução de problemas, entre em contato com o Suporte da Singular com a versão do SDK, os detalhes da plataforma, payloads de eventos de exemplo e capturas de tela do dashboard da Singular mostrando o problema.