Misurare il churn con i webhook di Polar
Quali eventi webhook di Polar segnano disdetta, revoca, pagamento fallito o recupero, come funzionano consegna e firme e come costruire un log del churn.
Polar mostra già il churn nella sua dashboard. Ma se vuoi il churn accanto ai dati del tuo prodotto (utilizzo, piano, fonte di iscrizione), ti servono gli eventi grezzi nel tuo database. I webhook di Polar ti danno tutto, a patto di leggerli come Polar prevede.
Questa guida collega gli eventi di abbonamento di Polar al churn, spiega le regole di consegna e firma che mettono in difficoltà gli handler e mostra come costruire un log del churn affidabile. Si attiene alla documentazione di Polar: webhook events, handling and monitoring deliveries, Managing subscriptions, Recovering failed payments, Analytics e la Get Metrics API (tutti consultati a novembre 2026).
Gli eventi di abbonamento
La pagina webhook events di Polar descrive questi eventi di abbonamento:
| Evento | Cosa significa secondo Polar | Significato per il churn |
|---|---|---|
subscription.created |
Un nuovo abbonamento | Cliente nuovo o di ritorno |
subscription.active |
Un abbonamento diventa attivo: un nuovo abbonamento a pagamento, o un pagamento recuperato | Paga |
subscription.updated |
Qualsiasi modifica all’abbonamento, compresi i rinnovi | Da usare per sincronizzare lo stato |
subscription.canceled |
Disdetto; il cliente può mantenere l’accesso fino a fine periodo | Churn programmato |
subscription.uncanceled |
Il cliente ha annullato una disdetta in sospeso | Churn programmato annullato |
subscription.past_due |
Un pagamento di rinnovo è fallito e può ancora essere recuperato | Rischio di churn involontario |
subscription.revoked |
L’accesso termina ora: il periodo di un abbonamento disdetto è finito, il commerciante l’ha revocato o i nuovi tentativi di pagamento sono esauriti | Churn avvenuto |
Polar precisa che subscription.updated scatta a ogni modifica e suggerisce di ascoltare gli eventi specifici quando ti servono solo certe transizioni. Per il churn, gli eventi specifici sono più chiari.
L’ordine degli eventi
Polar documenta le sequenze, e contano per il conteggio:
- Disdetta a fine periodo:
subscription.updatedesubscription.canceledarrivano subito. Quando il periodo finisce, seguonosubscription.updatedesubscription.revoked. - Revoca immediata:
subscription.updated,subscription.canceledesubscription.revokedarrivano insieme.
Quindi ogni abbonamento in churn produce sia un subscription.canceled sia un subscription.revoked, a volte a un mese o un anno di distanza. Conta il churn su subscription.revoked. Conta subscription.canceled a parte come «disdette programmate», un indicatore anticipatore.
Volontario e involontario
subscription.revoked copre sia il churn volontario (una disdetta arrivata a scadenza) sia quello involontario (nuovi tentativi di pagamento esauriti). Per distinguerli:
- Se l’abbonamento aveva
cancel_at_period_endimpostato e unsubscription.canceledsenza unsubscription.uncanceledsuccessivo, è volontario. - Se è passato da
subscription.past_duesenza tornare asubscription.active, è involontario.
La pagina sui pagamenti falliti di Polar spiega il percorso involontario: dopo un rinnovo fallito l’abbonamento passa a past_due e Polar scrive al cliente con un link al Customer Portal. Riprova 4 volte, a 2, 5, 7 e 7 giorni dal tentativo precedente (2, 7, 14 e 21 giorni dopo il primo fallimento), e revoca se tutti i tentativi falliscono o se il codice di rifiuto indica che il metodo di pagamento non funzionerà mai, come lost_card. Si può impostare un grace period per i benefit (immediato, 2, 7, 14 o 21 giorni da past_due_at); non cambia il calendario dei nuovi tentativi.
Un’incoerenza da conoscere: la documentazione di Polar sulla revoca e il suo riferimento sui webhook descrivono in modo diverso lo stato finale dopo i nuovi tentativi esauriti (canceled nell’una, unpaid nell’altro). Non scrivere nessuno dei due nel codice; affidati all’evento subscription.revoked e al tuo log di ciò che è successo prima.
I motivi arrivano con l’abbonamento
Quando una disdetta ha un motivo, si trova sull’abbonamento: customer_cancellation_reason (valori too_expensive, missing_features, switched_service, unused, customer_service, low_quality, too_complex, other) e customer_cancellation_comment (Managing subscriptions). Salvali dal payload di subscription.canceled così puoi dividere il churn per motivo.
Regole di consegna
Secondo la pagina sulla consegna di Polar:
- Nuovi tentativi: le consegne fallite vengono riprovate fino a 10 volte con backoff esponenziale.
- Timeout: 10 secondi, con la raccomandazione di rispondere entro 2 secondi e fare il lavoro pesante in un job in background, perché il timeout potrebbe essere ridotto.
- Endpoint disattivati: dopo 10 risposte non-2xx consecutive, l’endpoint viene disattivato e tutti i membri dell’organizzazione ricevono un’email. La riattivazione è manuale, nelle impostazioni dei webhook.
- Firewall: il Bot Fight Mode di Cloudflare può causare errori 403; consenti le richieste di Polar con una regola WAF.
Il terzo punto è quello da pianificare. Un deploy che rompe il tuo handler per un pomeriggio può disattivare l’endpoint, e non ti arriva più nulla finché qualcuno non lo riattiva.
Firme
La stessa pagina spiega che lo schema di firma dipende da quando è stato creato il secret dell’endpoint. I secret creati dall’8 settembre 2026 (00:00 UTC) in poi usano lo schema Standard Webhooks e vanno passati così come sono a una libreria Standard Webhooks. I secret più vecchi usano l’HMAC originale di Polar, in cui l’intera stringa del secret whsec_ viene codificata in base64 prima di essere passata alla libreria. Il campo uses_standard_webhook_signature dell’endpoint ti dice quale si applica, e gli SDK di Polar dalla 1.0.0-alpha.19 provano entrambi.
Se hai dubbi, controlla quel campo prima di passare ore a fare debug di un «signature mismatch».
Test in locale
Il comando polar webhook listen della CLI di Polar inoltra gli eventi della tua organizzazione a un URL locale e mostra il secret da usare per la verifica (CLI webhooks).
Costruire un log del churn
- Un endpoint, eventi specifici. Iscriviti ai sette eventi della tabella qui sopra.
- Verifica, salva, rispondi. Controlla la firma, scrivi il payload grezzo con tipo di evento, ID dell’abbonamento, ID del cliente e timestamp, e rispondi con un 2xx entro un paio di secondi.
- Deduplica. I nuovi tentativi significano ripetizioni. Se le tue consegne portano un ID messaggio univoco, usalo; altrimenti costruisci una chiave da tipo di evento, ID dell’abbonamento e timestamp dell’ultima modifica dell’abbonamento, e salta tutto ciò che hai già salvato.
- Elabora in background. Aggiorna le schede dei clienti dall’evento salvato, mai durante la richiesta.
- Solo in aggiunta. Ricava stato attuale e metriche dal log, così puoi rigiocarlo dopo un bug.
- Sorveglia l’endpoint. Imposta un allarme sulle risposte non-2xx prima che si raggiunga il limite di 10 fallimenti di Polar.
- Riconcilia. Ogni settimana, elenca gli abbonamenti tramite l’API e confrontali con il tuo log.
Confronta con i numeri di Polar
Gli Analytics di Polar definiscono le metriche con precisione, il che li rende un buon controllo incrociato:
- Canceled subscriptions: disdette avviate dai clienti nell’intervallo; l’abbonamento può essere ancora attivo.
- Churned subscriptions: abbonamenti il cui periodo pagato è terminato nell’intervallo.
- Churn rate: abbonamenti in churn nell’intervallo divisi per gli abbonamenti attivi all’inizio dell’intervallo.
- MRR: esclude gli abbonamenti in prova; include quelli in pausa e past due finché non terminano davvero.
La Get Metrics API restituisce campi come active_subscriptions, churned_subscriptions, canceled_subscriptions, churn_rate e monthly_recurring_revenue per intervallo, con una ripartizione dei motivi di disdetta.
Se adotti le stesse definizioni nel tuo log, il tuo tasso di churn e quello di Polar dovrebbero coincidere per lo stesso periodo. Quando non coincidono, probabilmente hai perso degli eventi, spesso perché l’endpoint è rimasto disattivato per un po’.
Cosa aggiunge il tuo log
Gli analytics di Polar rispondono a «quanto churn». Il tuo log, unito ai dati del prodotto, risponde a «il churn di chi e perché»: churn per fonte di iscrizione, per attivazione, per piano, per motivo di disdetta, volontario o involontario. È lì che si trova il lavoro su cui agire.
Farlo con NoChurn
Polar resta la fonte di verità per abbonamenti, pagamenti e il suo calendario dei nuovi tentativi, e i suoi analytics restano utili. NoChurn si iscrive ai tuoi webhook Polar, salva e deduplica gli eventi, separa il churn volontario da quello involontario e li unisce ai dati personalizzati che invii via API. Aggiunge un churn score da 0 a 100 per cliente e i motivi raccolti nel suo flusso di disdetta. Le contestazioni restano a Polar come merchant of record e sono mostrate in sola lettura. Vedi NoChurn + Polar.