
Event-triggered win-back: email, push, and webhooks in one journey
Build a unified win-back journey with Rheo Engage: email, push, and webhooks triggered by churn and return events, paired with in-app Convert flows.
Win-back fails when channels fight each other: a push offers 50% off while email still says "last chance" at full price, and support has no idea the user canceled for "missing feature" yesterday. Subscription teams need one journey keyed off events: cancel, expire, return session, offer accept: not three spreadsheets.
This post designs an event-triggered win-back program using Rheo Engage (email, push, webhooks) plus Convert in-app flows. It builds on in-app win-back flows after churn and subscription win-back: email vs in-app, with a focus on orchestration rather than channel theory alone.
Events that should start (or resume) win-back
| Event source | Example signal | Journey branch |
|---|---|---|
| In-app cancel flow | cancel_survey_submitted with reason | Voluntary win-back |
| RevenueCat webhook | EXPIRATION, CANCELLATION | Confirm churn state on profile |
| App open after lapse | session_start + entitlement_inactive | In-app flow priority |
| Billing | BILLING_ISSUE | Payment recovery, not discount |
| Engage | email_clicked / no open | Push or in-app fallback |
Server truth from RevenueCat or Stripe should set subscription_status. SDK events time UX and messages.
One journey, four channels
Think in stages, not channel silos.
Stage 0: Immediate (0-2 hours)
- In-app (Convert): if user opens app after cancel, show empathetic confirm + optional save offer: not a generic paywall.
- Webhook: notify CS or Slack for high-LTV segments (
mrr> threshold). - Email: hold unless transactional cancel receipt is separate.
Voluntary churners who stay in-app are highest intent; lead with UI, not inbox.
Stage 1: Short window (day 1-3)
- Email: acknowledge cancel, one clear CTA (return to app or web resubscribe). Personalize on
cancel_reasonmerge field from survey event. - Push (if marketing consent): single nudge, not daily spam.
- Webhook: update external CRM
churn_reasonfor roadmap analytics (cancellation surveys).
Stage 2: Medium window (day 7-14)
- Email: value narrative or feature shipped since churn: only if true.
- In-app: on return, branch offer by reason (price vs missing feature).
- Push: optional second touch if email unopened and user opened app without converting.
Stage 3: Long window (day 30+)
- Email: stronger offer if unit economics allow; cap frequency.
- In-app: Apple win-back offer presentation where eligible (iOS win-back offers).
- Webhook: fan-out to ads suppression list: stop paying for users who resubscribed.
Exit every stage on subscription_reactivated, trial_restarted, or explicit opt-out.
Channel roles in the same automation
| Channel | Role in win-back | Suppress when |
|---|---|---|
| Story, offers, deep links | Unsubscribed, no marketing consent | |
| Push | Timely return nudge | OS permission denied |
| Webhook | Ops, CRM, ads, data warehouse | Handler returns error (retry policy) |
| In-app Convert | Rich UI, native purchase | User not in app |
Engage can run parallel actions on one segment entry: send email, schedule push, POST webhook: in one definition.
Example Engage definition (conceptual)
Segment enter: subscription_status = expired AND churn_type = voluntary AND marketing_consent = true
Actions:
- Wait 2 hours
- If no
session_startsince expire → send emailwinback_d1_value - Wait 24 hours
- If no
subscription_reactivated→ send pushwinback_push_return - On any
session_startwhile expired → trigger Convert flowwinback_in_app_reason_branch - Webhook
POST /internal/churn-campaign-enrolledfor analytics
Exit: subscription_reactivated or 60 days elapsed
Duplicate the structure for involuntary churn with payment-update copy and no discount email.
Avoiding channel conflict
| Rule | Why |
|---|---|
| One active win-back automation per user | Prevents double discounts |
| Shared offer id across email and in-app | Consistent pricing |
| Push only if email unopened OR high app openers | Reduces fatigue |
| Webhook idempotency | Retries do not triple Slack noise |
Document in Notion: priority in-app > push > email when user is simultaneously reachable.
Measurement
| Metric | Channel attribution |
|---|---|
| Resubscribe rate | RevenueCat (source of truth) |
| Email assist | Click → resub within 7d |
| Push assist | Open → in-app flow complete |
| In-app | Flow completion → purchase |
| Webhook | Ops response time (optional) |
Do not judge win-back only by email opens; many recoveries are in-app only after a silent churn period.
What Rheo does not replace
- Store billing and offer eligibility rules (RevenueCat, native StoreKit)
- Legal review of promotional email in your jurisdictions
- Paid retargeting (webhooks can feed audiences, but ads are separate spend)
Rheo does replace duct-tape between "user canceled" in RC and three zapier zaps to email, push, and Slack.
Personalization without creepy data hoarding
Win-back performs when messages reference stated cancel reason and tenure, not when you dump entire event histories into email merge fields.
| Attribute | Source | Use in copy |
|---|---|---|
cancel_reason | In-app cancel survey | One sentence empathy + targeted offer |
plan_interval | RevenueCat | Annual vs monthly repositioning |
last_active_feature | SDK | "Your projects are still saved" |
ltv_tier | Warehouse or RC | Webhook to CS, not bragging in email |
Avoid discounting power users who canceled for missing features: route them to "we shipped X" campaigns when the feature actually ships (cancellation surveys for roadmap).
Testing win-back before Black Friday
Run a holdout on voluntary expire: 80% receive journey, 20% receive no promotional touch for 30 days. Compare resubscribe rate and refund complaints. If holdout resubscribes equally, your journey may be noise: or your product already wins back organically.
For in-app variants, use Convert experiments on the win-back flow: offer presentation, social proof block, length of survey. Email can point to the same flow_variant id so analytics stay coherent.
Failure modes to script in advance
| Failure | User impact | Mitigation |
|---|---|---|
| Webhook endpoint down | CS misses alert | Retry + dead-letter queue |
| Email domain throttled | No win-back reach | Warm domain; separate transactional |
| Offer expired in StoreKit | Broken CTA | RC eligibility check before send |
| User resubscribed on web | Annoying "come back" | RC webhook exits all channels within minutes |
Document an incident runbook: one engineer can disable automation id globally from the dashboard without deleting templates.
Coordinating with paid acquisition
Users who churn from paid install campaigns should not receive the same copy as organic subscribers. Pass media_source or campaign id into the profile at signup; branch win-back email to reference the value prop they first saw. Webhooks can pause Meta or Google audiences when subscription_reactivated fires so you do not pay to re-acquire someone already back on a monthly plan.
Related reading
- In-app win-back flows after subscription churn
- Subscription win-back: email vs in-app
- Eight cancellation flow examples
Start for free and map your first event-triggered win-back journey across email, push, and webhooks.