Catch at-risk Ghost members the moment Stripe flags trouble

When a Ghost member's payment fails or they cancel, label them in Ghost and post a retention brief to Slack so you can win them back before they leave.

Agentic Task
GhostStripeSlackMarketingOperationsNotifications & AlertsData Sync

Build me an agent workflow that catches paid Ghost members the moment Stripe flags trouble, so I can intervene before they're gone.

Trigger: a Stripe webhook for the events invoice.payment_failed and customer.subscription.deleted. The same workflow should handle both event types.

For each incoming event:

1. If the Stripe event has livemode: false (i.e. test mode), stop and do nothing. We do not want test events polluting the retention channel.

2. Pull the customer id from the event (it lives at data.object.customer for invoice.payment_failed and data.object.customer for customer.subscription.deleted). Use Stripe's Retrieve Customer operation to fetch the customer's email, name, and any metadata or balance info that can stand in for lifetime value (e.g. total_spend metadata if present, otherwise the customer's balance or the invoice amount).

3. Use Ghost's Browse Members (Admin API) operation with the NQL filter email:"<that email>" to find the matching Ghost member. Capture their name, id, current labels, subscription tier (the plan or product name from the member's subscriptions array), and, if available on the member record, the URL of the most recently opened post.

4. Use Ghost's Update Member (Admin API) operation to add a label to that member. Use "at-risk" if the event was invoice.payment_failed, and "churned" if the event was customer.subscription.deleted. Preserve the member's existing labels rather than overwriting them.

5. Compose and send a Slack message via Send a Message to the channel #retention. Keep it short and skimmable. Include: the member's name and email, their tier, their lifetime value (or best available proxy from Stripe), the event reason in plain English ("payment failed on $X invoice" vs "subscription canceled"), the URL of the most recent Ghost post they opened if visible on the member record, and a one-sentence suggested next step (for example: "Send a 20% win-back offer" for a small failed payment, "Manual outreach worth it" for a high-LTV cancellation). The agent should pick the suggestion based on lifetime value and event type.

Edge cases:

- If no matching Ghost member is found for that email, skip the Update Member step but still post to Slack with whatever Stripe details we have, and note in the message that the member could not be located in Ghost. - If the same member triggers multiple events in quick succession (e.g. a payment_failed followed by a subscription_deleted), it's fine to post both messages, but make sure the labels in Ghost are additive, not overwritten. - Never include raw Stripe ids or JSON in the Slack message. Write it like a person would: short paragraph or 4-5 bullet lines.

Additional information

What does this prompt do?
  • Listens for Stripe billing trouble in real time, including failed invoice payments and canceled subscriptions, so you hear about churn risk the same minute Stripe does.
  • Finds the matching member in Ghost by email and quietly tags them as at-risk or churned, keeping your internal segments and win-back lists honest without manual cleanup.
  • Posts a short, human-readable brief to your retention channel in Slack with the member's name, tier, lifetime value, why they're slipping, and a one-line suggested next move.
  • Ignores test-mode events from Stripe so your retention channel never gets polluted with noise from sandbox transactions.
What do I need to use this?
  • A Ghost site with Admin API access (a Custom Integration set up under Settings, Integrations).
  • A Stripe account connected to your Ghost membership, with permission to receive webhooks.
  • A Slack workspace and the name of the channel where you want retention alerts to land (for example, #retention).
How can I customize it?
  • Change the Slack channel, or send to multiple channels if growth and support both want a copy.
  • Adjust the labels that get applied in Ghost, for example payment-failed versus canceled, or add tier-specific tags like vip-at-risk.
  • Tune the suggested next step language so it matches your playbook, for example a 20% win-back offer for paid tiers and a personal note for VIPs.
  • Add a value threshold so only members above a certain lifetime value trigger a Slack ping, and silently label the rest.

Frequently asked questions

Does this work for Ghost sites that bill through Stripe?
Yes. Ghost uses Stripe as its only payment processor for paid memberships, so every paid Ghost member already has a matching Stripe customer. This workflow connects the two using the shared email address.
Will I get pinged for test payments?
No. The workflow checks whether each Stripe event came from live mode or test mode, and silently skips test events so your Slack channel only shows real customer activity.
What if a member's email in Ghost doesn't match their Stripe email?
The workflow looks up the Ghost member using the email on the Stripe customer record. If no match is found, it still posts to Slack with the Stripe details and a note that the member could not be located in Ghost, so you can investigate manually.
Can I use this without Slack?
Yes. The Ghost labeling step works on its own, so you can keep just the at-risk tagging and skip the Slack message. You can also swap Slack for email or another channel during setup.
How fast is the alert?
Stripe delivers these events within seconds of the failure or cancellation, so your Slack message typically arrives in under a minute. That gives you a real shot at reaching out before the member fully disengages.

Stop losing paid members you could have saved.

Connect Ghost, Stripe, and Slack once, and Geni pings your retention channel the moment a member's payment fails or cancels.