MÉTRICAS DE CHURNAPP STORE

Medir o churn com as App Store Server Notifications V2

Como medir o churn de subscrições iOS com as App Store Server Notifications V2: configuração, significado de cada notificação, churn voluntário vs faturação.

Publicado a 6 min de leitura

O App Store Connect dá-lhe relatórios de vendas e de subscrições, mas se quiser números de churn em que possa confiar e sobre os quais possa agir (quem saiu, porquê e quem está prestes a sair), precisa do seu próprio registo de eventos. No iOS, esse registo vem das App Store Server Notifications V2: o servidor da Apple chama o seu sempre que uma subscrição muda de estado.

Este guia mostra como configurá-las de forma fiável, como cada notificação corresponde a uma métrica de churn e como preencher as lacunas. Baseia-se na documentação da Apple: Enabling App Store Server Notifications, Responding to App Store Server Notifications, a referência de notificationType e Get Notification History (todos consultados em novembro de 2026).

Configurar o endpoint

Os requisitos da Apple são curtos:

  1. Um URL HTTPS no seu servidor, com TLS 1.2 ou posterior. Se indicar uma porta, tem de ser 443 ou 1024 e superiores.
  2. Escolha a versão 2 para o URL no App Store Connect. A Apple recomenda a V2 para todas as novas implementações. Pode definir um URL separado para sandbox, ou reutilizar o mesmo.
  3. Se a sua firewall usar uma lista de permissões, adicione 17.0.0.0/8, que cobre sandbox e produção.
  4. Devolva HTTP 200 a 206 quando tiver guardado a notificação. Qualquer outro código conta como falha.
  5. Teste com o endpoint Request a Test Notification, que envia uma notificação TEST, e depois verifique o resultado com Get Test Notification Status.

Cada notificação chega como um signedPayload em formato JWS. Verifique a assinatura antes de confiar em qualquer coisa que contenha e depois descodifique o payload.

Entrega, novas tentativas e duplicados

As coisas correm mal: deploys, indisponibilidades, timeouts. A documentação da Apple descreve o que acontece nesses casos.

  • Novas tentativas. Na V2, se o seu servidor não devolver um código de sucesso, a Apple tenta de novo cinco vezes, 1, 12, 24, 48 e 72 horas depois da tentativa anterior. As novas tentativas só acontecem em produção; em sandbox, a Apple envia cada notificação uma vez.
  • Duplicados. Cada payload tem um notificationUUID, que a Apple diz para usar na identificação de duplicados. Guarde-o com uma restrição de unicidade e ignore as repetições.
  • Histórico. O Get Notification History devolve as notificações que a Apple tentou enviar nos últimos 180 dias em produção (30 dias em sandbox), 20 registos por página, com filtro opcional por tipo, subtype ou transação. Execute-o depois de qualquer indisponibilidade.
  • Estado atual. Os registos do histórico refletem o estado no momento do envio. Para o estado atual de uma subscrição, a Apple remete para o Get All Subscription Statuses.

Um bom padrão: guarde primeiro a notificação em bruto, devolva 200 e depois processe-a a partir de uma fila. Nunca faça trabalho lento antes de responder à Apple.

O que está numa notificação

O payload descodificado tem um notificationType, um subtype opcional, um signedDate e um objeto data. Para subscrições, data contém:

  • signedTransactionInfo: a transação (produto, datas, oferta usada, revogação se existir).
  • signedRenewalInfo: o que vai acontecer na próxima renovação, incluindo autoRenewStatus, expirationIntent, isInBillingRetryPeriod, gracePeriodExpiresDate e eligibleWinBackOfferIds.
  • status: o estado da subscrição à data de signedDate: 1 ativa, 2 expirada, 3 em billing retry, 4 em Billing Grace Period, 5 revogada.

Para associar uma subscrição a um dos seus utilizadores, defina um appAccountToken na compra. A Apple devolve-o na informação da transação e da renovação. Sem ele, só tem os IDs de transação da Apple.

Associar as notificações às métricas de churn

Eis como os tipos de notificação da Apple se traduzem nos números que a maioria das equipas acompanha. As descrições seguem a tabela de notificationType da Apple.

Métrica Notificação Subtype
Novo subscritor SUBSCRIBED INITIAL_BUY
Subscritor que regressa (incluindo win-back offers) SUBSCRIBED RESUBSCRIBE
Renovação DID_RENEW nenhum
Intenção de cancelamento (renovação desativada) DID_CHANGE_RENEWAL_STATUS AUTO_RENEW_DISABLED
Cancelamento revertido DID_CHANGE_RENEWAL_STATUS AUTO_RENEW_ENABLED
Falha de faturação DID_FAIL_TO_RENEW GRACE_PERIOD ou nenhum
Faturação recuperada DID_RENEW BILLING_RECOVERY
Churn voluntário EXPIRED VOLUNTARY
Churn involuntário (faturação) EXPIRED BILLING_RETRY
Churn por aumento de preço EXPIRED PRICE_INCREASE
Produto retirado de venda EXPIRED PRODUCT_NOT_FOR_SALE
Reembolso REFUND nenhum, ou SEATS para multiseat
Downgrade agendado DID_CHANGE_RENEWAL_PREF DOWNGRADE

O expirationIntent na informação de renovação dá a mesma divisão sob forma de número: 1 o cliente cancelou, 2 erro de faturação, 3 sem consentimento para um aumento de preço ou conversão de oferta, 4 produto indisponível, 5 outro (referência).

Conte o churn na expiração, não no cancelamento

Na App Store, um cancelamento apenas interrompe a renovação. O cliente mantém o acesso até ao fim do período e pode voltar a ativar a renovação. Assim:

  • Use AUTO_RENEW_DISABLED como indicador antecipado: subscrições em risco neste período.
  • Use EXPIRED como o evento de churn: subscrições que terminaram realmente.

Se contar o churn em AUTO_RENEW_DISABLED, vai sobrestimá-lo e perder todos os clientes que mudaram de ideias.

O churn de faturação tem uma cauda longa

A referência da Apple diz que, depois de uma renovação falhada, a App Store continua a tentar cobrar durante 60 dias, ou até o cliente corrigir a faturação ou cancelar. Com o Billing Grace Period ativo, o cliente mantém o acesso durante o período de carência; GRACE_PERIOD_EXPIRED marca o seu fim enquanto as novas tentativas continuam. Uma subscrição em billing retry ainda não está nem ativa nem perdida. Reporte-a numa categoria própria, e só a conte como churn quando chegar EXPIRED com BILLING_RETRY.

Note também o recentSubscriptionStartDate na informação de renovação: a Apple calcula-o ignorando interrupções de 60 dias ou menos, o que é prático para antiguidade e coortes.

Um relatório de churn simples a partir das notificações

Com todas as notificações guardadas, um relatório mensal resume-se a meia dúzia de queries:

  1. Ativas no início do mês: subscrições cujo último estado antes do mês era ativa, em período de carência ou em billing retry (decida uma vez se o retry conta como ativo e mantenha a decisão).
  2. Perdidas: notificações EXPIRED no mês, divididas por subtype.
  3. Taxa de churn voluntário: EXPIRED/VOLUNTARY a dividir pelas ativas no início.
  4. Taxa de churn involuntário: EXPIRED/BILLING_RETRY a dividir pelas ativas no início.
  5. Recuperação de faturação: DID_RENEW/BILLING_RECOVERY a dividir por DID_FAIL_TO_RENEW na mesma coorte.
  6. Em risco agora: subscrições cuja última informação de renovação tem a renovação automática desativada e uma expiração futura.
  7. Reativações: SUBSCRIBED/RESUBSCRIBE.

Para as fórmulas gerais e as armadilhas (misturar planos mensais e anuais, contar períodos de teste), veja como calcular a taxa de churn.

Lacunas comuns

  • Ouvir só a V1, ou só a produção. Teste a V2 em sandbox antes de mudar a produção; a Apple recomenda exatamente essa ordem.
  • Nenhum job de reconciliação. Mesmo com novas tentativas, execute o Get Notification History periodicamente e depois de incidentes.
  • Ignorar a Partilha com a família e os grupos. SUBSCRIBED e REVOKE também são disparados para membros da família e lugares de grupo. Decida se esses contam como subscritores nas suas métricas.
  • Tratar reembolsos como cancelamentos. Um REFUND termina o acesso e devolve dinheiro; reporte-o à parte.
  • Sem appAccountToken. Obtém números limpos da App Store, mas não os consegue cruzar com dados de utilização, de plano ou de aquisição, que é de onde vêm as explicações do churn.

Fazer isto com o NoChurn

O NoChurn dá-lhe um URL para colar como endpoint das App Store Server Notifications. Verifica e elimina duplicados de cada notificação, mantém a cronologia por cliente (associada pelo seu appAccountToken), separa o churn voluntário, de faturação e por aumento de preço, e assinala a renovação automática desativada como sinal de risco precoce no score de churn de 0 a 100. Pode adicionar os seus próprios atributos por API para ver o que provoca o churn. A Apple fica com a faturação, as novas tentativas e o botão de cancelar. Veja NoChurn + App Store.

PROMPT

Read https://www.nochurn.sh/llms.txt,
then follow https://www.nochurn.sh/docs/quickstart/
to add NoChurn to this app. Use a test key
(nc_test_…) until I say we go live.

Pare de perder receita.

  • Grátis até $300 de MRR
  • Sem cartão
  • Pronto em 10 minutos
  • Nunca uma comissão sobre o que recuperamos