For the complete documentation index, see llms.txt. This page is also available as Markdown.

Winback for at-risk users

Catch users whose behavior pattern is decaying — before they fully churn — and route them to a winback screen on their next session.

Use this when you have behavioral data — session frequency, feature usage, cohort baselines — that can flag "slowing down" before a calendar gap opens. Don't use this when you only have calendar signal (last-open timestamp); reach for Reactivation after inactivity instead. Also skip if the product is used every few days under normal conditions — the baseline is too shallow to drift against.

Goal

Churn prediction that waits for 30 days of inactivity is too late — by the time you act, the user has the app in an uninstall folder. This recipe fires on the next session after a behavioral drop (for example, weekly sessions fell from 5 to 1) and shows a winback surface: a value-recap screen, a small incentive, or a shortcut to the feature the user used to love. You are intervening while the user still has the app on their home screen.

Setup

In the dashboard

  • Create a campaign winback-at-risk.

  • Trigger: session start.

  • Conditions: risk_status = "at_risk" and subscription_status != "pro_new" (do not hassle users who just paid).

  • Action: fire yourapp://winback/welcome-back — a short screen that references the user's previous favorite feature and offers a small incentive if appropriate.

  • Frequency: once per transition into at_risk. When the user re-engages and risk_status flips back to healthy, the campaign can match again if they slip later.

  • Exclude users whose last_session_at is more than 30 days old — those need a different flow in a different channel.

In the app (engineering hand-off)

  • Compute the risk signal in the app or an upstream service. Keep the definition simple and stable:

    // Pseudocode: compare last 7 days to prior 28-day baseline
    const status = recentRate < baseline * 0.3 ? 'at_risk' : 'healthy';
    await Amply.setCustomProperty('risk_status', status);
    await Amply.setCustomProperty('last_core_feature', lastFeature);
  • Write risk_status before the session starts, so the first campaign evaluation sees the current value.

  • Track the outcome for measurement:

    await Amply.track({ name: 'WinbackShown' });
    await Amply.track({ name: 'WinbackConverted' });

How it runs

  1. User used the app ~5 times per week for a month, then dropped to ~1 per week.

  2. On the first session after the drop, the app recomputes the risk signal: risk_status = "at_risk".

  3. Session starts. Amply evaluates campaigns. winback-at-risk matches.

  4. Amply fires yourapp://winback/welcome-back. The screen shows "Your weekly streak is still here — one tap to pick up where you left off," referring to the user's last core feature. The app tracks WinbackShown.

  5. User taps through, uses the feature again. Over the next week, usage recovers. The app recomputes risk_status = "healthy".

  6. If usage drops again months later, the campaign can match again. If the user goes dark for 30+ days, they fall out of this campaign's audience and belong to reactivation or email instead.

Metrics to watch

  • Winback conversion rate: share of WinbackShown users who come back to healthy within 14 days. Compare to a hold-out that never saw the screen.

  • False-positive rate of the at-risk signal: users flagged at-risk who would have recovered anyway. A noisy signal burns the surface.

  • Long-term retention of winback-recovered users — 60 and 90 days out. A superficial recovery does not count.

  • Share of your free-to-paid users who ever hit at-risk. Rising share is a product-quality signal, not a campaign problem.

Last updated