Suivre le churn avec les App Store Server Notifications V2
Mesurer le churn iOS avec les App Store Server Notifications V2 : mise en place, sens de chaque notification, churn de facturation ou volontaire, manques.
App Store Connect vous donne des rapports de ventes et d’abonnements, mais si vous voulez des chiffres de churn fiables et exploitables (qui est parti, pourquoi, et qui est sur le point de partir), il vous faut votre propre journal d’événements. Sur iOS, ce journal vient des App Store Server Notifications V2 : le serveur d’Apple appelle le vôtre chaque fois qu’un abonnement change d’état.
Ce guide montre comment les mettre en place de façon fiable, à quelle métrique de churn correspond chaque notification et comment combler les manques. Il s’appuie sur la documentation d’Apple : Enabling App Store Server Notifications, Responding to App Store Server Notifications, la référence notificationType et Get Notification History (tous consultés en novembre 2026).
Mettre en place l’endpoint
Les exigences d’Apple sont courtes :
- Une URL HTTPS sur votre serveur, en TLS 1.2 ou plus. Si vous indiquez un port, ce doit être 443 ou 1024 et au-delà.
- Choisissez la version 2 pour l’URL dans App Store Connect. Apple recommande la V2 pour toutes les nouvelles intégrations. Vous pouvez définir une URL sandbox séparée, ou réutiliser la même.
- Si votre pare-feu utilise une liste d’autorisation, ajoutez
17.0.0.0/8, qui couvre la sandbox et la production. - Renvoyez un HTTP 200 à 206 une fois la notification enregistrée. Tout autre code compte comme un échec.
- Testez avec l’endpoint Request a Test Notification, qui envoie une notification
TEST, puis vérifiez le résultat avec Get Test Notification Status.
Chaque notification arrive sous forme de signedPayload au format JWS. Vérifiez la signature avant de vous fier à quoi que ce soit dedans, puis décodez le contenu.
Livraison, nouvelles tentatives et doublons
Il arrive que les choses tournent mal : déploiements, pannes, délais dépassés. La documentation d’Apple décrit ce qui se passe alors.
- Nouvelles tentatives. En V2, si votre serveur ne renvoie pas de code de succès, Apple réessaie cinq fois, à 1, 12, 24, 48 et 72 heures après la tentative précédente. Les nouvelles tentatives n’ont lieu qu’en production ; en sandbox, Apple envoie chaque notification une seule fois.
- Doublons. Chaque contenu a un
notificationUUID, qu’Apple dit d’utiliser pour repérer les doublons. Enregistrez-le avec une contrainte d’unicité et ignorez les répétitions. - Historique. Get Notification History renvoie les notifications qu’Apple a tenté d’envoyer sur les 180 derniers jours en production (30 jours en sandbox), 20 par page, avec un filtre facultatif par type, subtype ou transaction. Lancez-le après chaque panne.
- L’état actuel. Les entrées de l’historique reflètent l’état au moment de l’envoi. Pour l’état actuel d’un abonnement, Apple renvoie vers Get All Subscription Statuses.
Un bon schéma : enregistrez d’abord la notification brute, renvoyez 200, puis traitez-la depuis une file. Ne faites jamais de travail lent avant de répondre à Apple.
Ce que contient une notification
Le contenu décodé a un notificationType, un subtype facultatif, un signedDate et un objet data. Pour les abonnements, data contient :
signedTransactionInfo: la transaction (produit, dates, offre utilisée, révocation éventuelle).signedRenewalInfo: ce qui se passera au prochain renouvellement, dontautoRenewStatus,expirationIntent,isInBillingRetryPeriod,gracePeriodExpiresDateeteligibleWinBackOfferIds.status: l’état de l’abonnement à la datesignedDate:1actif,2expiré,3en billing retry,4en Billing Grace Period,5révoqué.
Pour relier un abonnement à l’un de vos utilisateurs, définissez un appAccountToken à l’achat. Apple le renvoie dans les informations de transaction et de renouvellement. Sans lui, vous n’avez que les ID de transaction d’Apple.
Faire correspondre notifications et métriques de churn
Voici comment les types de notification d’Apple se traduisent dans les chiffres que suivent la plupart des équipes. Les descriptions suivent le tableau notificationType d’Apple.
| Métrique | Notification | Subtype |
|---|---|---|
| Nouvel abonné | SUBSCRIBED |
INITIAL_BUY |
| Abonné qui revient (y compris via les win-back offers) | SUBSCRIBED |
RESUBSCRIBE |
| Renouvellement | DID_RENEW |
aucun |
| Intention de résilier (renouvellement désactivé) | DID_CHANGE_RENEWAL_STATUS |
AUTO_RENEW_DISABLED |
| Résiliation annulée | DID_CHANGE_RENEWAL_STATUS |
AUTO_RENEW_ENABLED |
| Échec de facturation | DID_FAIL_TO_RENEW |
GRACE_PERIOD ou aucun |
| Facturation récupérée | DID_RENEW |
BILLING_RECOVERY |
| Churn volontaire | EXPIRED |
VOLUNTARY |
| Churn involontaire (facturation) | EXPIRED |
BILLING_RETRY |
| Churn dû à une hausse de prix | EXPIRED |
PRICE_INCREASE |
| Produit retiré de la vente | EXPIRED |
PRODUCT_NOT_FOR_SALE |
| Remboursement | REFUND |
aucun, ou SEATS pour le multi-sièges |
| Passage à une offre inférieure programmé | DID_CHANGE_RENEWAL_PREF |
DOWNGRADE |
L’expirationIntent des informations de renouvellement donne la même répartition sous forme de nombre : 1 le client a résilié, 2 erreur de facturation, 3 pas d’accord sur une hausse de prix ou une conversion d’offre, 4 produit indisponible, 5 autre (référence).
Comptez le churn à l’expiration, pas à la résiliation
Sur l’App Store, une résiliation ne fait qu’arrêter le renouvellement. Le client garde l’accès jusqu’à la fin de la période et peut réactiver le renouvellement. Donc :
- Utilisez
AUTO_RENEW_DISABLEDcomme indicateur avancé : les abonnements à risque sur la période. - Utilisez
EXPIREDcomme événement de churn : les abonnements réellement terminés.
Si vous comptez le churn sur AUTO_RENEW_DISABLED, vous le surestimerez et raterez chaque client qui a changé d’avis.
Le churn de facturation a une longue traîne
La référence d’Apple indique qu’après un renouvellement échoué, l’App Store continue de tenter la facturation pendant 60 jours, ou jusqu’à ce que le client corrige sa facturation ou résilie. Avec la Billing Grace Period activée, le client garde l’accès pendant la grace period ; GRACE_PERIOD_EXPIRED en marque la fin alors que les tentatives continuent. Un abonnement en billing retry n’est ni actif ni encore churné. Présentez-le comme une catégorie à part, et ne le comptez comme churn qu’à l’arrivée d’EXPIRED avec BILLING_RETRY.
Notez aussi recentSubscriptionStartDate dans les informations de renouvellement : Apple le calcule en ignorant les interruptions de 60 jours ou moins, ce qui est pratique pour l’ancienneté et les cohortes.
Un rapport de churn simple à partir des notifications
Avec toutes les notifications enregistrées, un rapport mensuel tient en quelques requêtes :
- Actifs en début de mois : les abonnements dont le dernier état avant le mois était actif, en grace period ou en billing retry (décidez une fois pour toutes si le retry compte comme actif et tenez-vous-y).
- Churnés : les notifications
EXPIREDdu mois, réparties par subtype. - Taux de churn volontaire :
EXPIRED/VOLUNTARYdivisé par les actifs en début de mois. - Taux de churn involontaire :
EXPIRED/BILLING_RETRYdivisé par les actifs en début de mois. - Récupération de facturation :
DID_RENEW/BILLING_RECOVERYdivisé parDID_FAIL_TO_RENEWsur la même cohorte. - À risque maintenant : les abonnements dont les dernières informations de renouvellement ont le renouvellement automatique désactivé et une expiration future.
- Réactivations :
SUBSCRIBED/RESUBSCRIBE.
Pour les formules générales et les pièges (mélanger offres mensuelles et annuelles, compter les essais), voir comment calculer le taux de churn.
Manques fréquents
- N’écouter que la V1, ou que la production. Testez la V2 en sandbox avant de basculer la production ; Apple recommande exactement cet ordre.
- Pas de tâche de rapprochement. Même avec les nouvelles tentatives, lancez Get Notification History régulièrement et après les incidents.
- Ignorer le Partage familial et les groupes.
SUBSCRIBEDetREVOKEse déclenchent aussi pour les membres de la famille et les sièges de groupe. Décidez s’ils comptent comme abonnés dans vos métriques. - Traiter les remboursements comme des résiliations. Un
REFUNDmet fin à l’accès et rend l’argent ; suivez-le séparément. - Pas d’
appAccountToken. Vous obtenez des chiffres App Store propres mais ne pouvez pas les croiser avec l’usage, l’offre ou les données d’acquisition, qui sont pourtant la source des explications du churn.
Le faire avec NoChurn
NoChurn vous donne une URL à coller comme endpoint App Store Server Notifications. Il vérifie et dédoublonne chaque notification, tient la chronologie par client (rattachée par votre appAccountToken), sépare churn volontaire, churn de facturation et churn dû à une hausse de prix, et signale le renouvellement automatique désactivé comme signal de risque précoce dans le score de churn de 0 à 100. Vous pouvez ajouter vos propres attributs par API pour voir ce qui fait churner. Apple garde la facturation, les relances et le bouton d’annulation. Voir NoChurn + App Store.