Welcome, trial-to-paid, event-driven, retention, and win-back Journey playbooks for mobile-first apps, with both basic and advanced data integrations covered.
Use this file to discover all available pages before exploring further.
This guide implements the Mobile-first strategy as five lifecycle Journeys: welcome, trial-to-paid conversion, event-driven, retention, and win-back. Each Journey supports two implementation paths so you can ship value before all your Custom Event tracking is in place:
Case 1 – Basic: Use only the data the OneSignal SDK collects automatically — First session, Last session, and built-in Subscription attributes. No Custom Events or Tags required.
Case 2 – Advanced: Use Custom Events and Tags for behavior-triggered, per-user personalization.
Start with Case 1 and layer in Case 2 components as your data integrations mature.
This page covers the five core mobile-first Journey shapes. More examples can be found in Tutorials.
Starter segments: Active Trial, Trial Expiring, Core feature untouched, At-Risk Subscribers, Lapsed — see Segments.
If you don’t have Custom Events yet, build the Case 1 versions of welcome, retention, and win-back while your event tracking comes online. Trial-to-paid conversion requires a trial_end_date Tag in both cases.
The welcome Journey’s job is to set new users up for success — drive them to their “Aha!” moment before they churn. The first 7 days determine whether a new user becomes a long-term customer or a churn statistic, so the welcome Journey runs across the full week with gentle daily nudges. Four principles drive the structure:
Capture permissions early. Drive push opt-in via a Day 1 in-app message during or right after onboarding. Without push permission, every later welcome step that uses push goes unread.
Introduce the product. Pair the IAM with a Day 1 email for consenting users that introduces what the product does, what to do next, and what messages to expect from you.
Nudge toward the core feature daily. Days 2–6 each carry a single, gentle reminder tied to a feature, use case, or setup step — never a streak claim or a hollow “we miss you.”
End the week deliberately. A Day 7 closing email recaps the user’s first week and transitions them from “trying the product” to “part of the community.”
The “Aha moment” is the single core action most predictive of conversion or retention in your app. Identify it before you build the Journey. For a workout app it might be logging the first session; for a finance app, linking the first account.
Case 1: Built-in segment First Session < 1 day ago AND Last Session > 4 hours ago. The user matches the moment they cross 4 hours of inactivity inside their first day — exactly when the Day 1 message sequence should fire, not the moment of signup.
Case 2: Custom Event entry on signup_completed (or trial_started for trial-based apps), then a 4-hour Wait so the first message lands after the user finishes their initial session.
Recent activity check (Case 1 only):
Name: “Active in the last 12 hours”
Filter:Last Session < 12 hours ago
The Day 2–7 Yes/No branches use this segment to skip the daily push if the user has already been active. Twelve hours is a deliberate compromise — long enough that the user feels like they “just used” the app, short enough that yesterday’s evening session doesn’t suppress today’s nudge.Exit conditions:
Case 1: Time-based — Journey completes after the Day 7 closing email.
Case 2: Event-based — exit on core_feature_used = "1" or onboarding_completed. Users who activate stop receiving feature-nudge messages.
These templates are starting points — clone, edit, and re-use them in your own Journey. They use Liquid syntax for personalization.
Push templates
Email templates
In-app message templates
Day
Name
Purpose
1
Day 1 — First action
Deep link to the highest-leverage first action
2
Day 2 — Quick win
60-second action that reinforces value
3
Day 3 — Feature tip
A useful capability most users miss in week one
4
Day 4 — Use case
Connect the product to a realistic outcome
5
Day 5 — Setup nudge
Incomplete-profile or preferences reminder
6
Day 6 — Community
Soft invite to community, social, or share moments
7
Day 7 — Week 1 wrap
Final value reminder before the closing email
Keep copy short and benefit-led. Deep-link every push to the exact screen where the user can take the action — see Deep linking.
Templates
Create and manage reusable message templates.
Message personalization
Pull Tag values into push, email, and IAM copy with Liquid.
Two emails fire — one on Day 1, one on Day 7 — each playing a distinct role. See Email messaging for setup.Day 1 — Welcome and push opt-inPurpose: Open the Journey with a value-led welcome that also drives push opt-in for users who declined the install-time prompt.Content outline:
A short welcome and product framing — what the user can do, not a feature tour.
1–2 next-step CTAs deep-linking into the app (e.g., complete profile, try the core feature).
A turn-on-notifications CTA that deep-links to your in-app preference center or notification settings screen. This catches users who declined install-time push without forcing a fresh OS prompt — see Prompt for push permission with in-app messages for the in-app prompt pattern that pairs with this CTA.
Expectation-setting on what messages they’ll receive and how often.
Help center or support links so users don’t have to email you with questions.
Day 7 — First week recap and what’s nextThe closing email at the end of the Journey. Where Day 1 welcomes the user into the product, this email transitions them from “trying the product” to “part of the community.”Purpose: Reinforce progress, surface what’s still unexplored, and give the user a reason to look forward to Week 2.Content outline:
A first-week recap — actions completed, key features used. Personalize via Tags or Liquid syntax where you have the data.
A next chapter section: 2–3 things to try in Week 2 (advanced features, integrations, settings).
A community or social CTA — Discord, X, blog, or your customer community.
A teaser for what’s coming next (upcoming feature, content drop, or a Day 14 milestone).
Templates
Create and manage reusable message templates.
Email warm-up
Required if you’re sending Welcome email at scale on a new domain.
In-app messages fire when the user is already in the app — the highest-leverage moment to drive setup completion, push opt-in, and feature engagement. Three IAMs cover the Journey’s main inflection points.Day 1 — Onboarding flowUse a multi-card or carousel IAM to funnel new users into the two highest-leverage setup steps:
Profile / preferences completion
Push opt-in via a Push Permission Prompt click action
Users who finish both are dramatically more likely to stick. Profile investment creates sunk-cost attachment, and without push opt-in, the rest of this Journey can’t reach them outside the app.
A Push Permission Prompt IAM will not display if the user has already granted push permission, so it’s safe to leave the prompt in even for users who opted in elsewhere.
Day 3 — Feature spotlightA single-card IAM that highlights one secondary feature most users miss in their first week. Pick a feature with high adoption-to-retention correlation (e.g., the second tier of the core workflow, an integration, or a personalization setting).
A specific benefit (“Save 10 minutes a week with [feature]”)
A primary CTA that deep-links to the feature
A dismiss action that doesn’t re-show on the same session
Day 6 — Community and shareA soft-invite IAM that introduces the user to your broader community. Pick whichever touchpoint is most natural for your product:
Join a community channel (Discord, Slack, Reddit, customer forum).
Share a milestone or referral code with friends.
Follow your social accounts for tips and updates.
Keep the ask low-stakes — this is the inflection from “user” to “community member,” not a hard upsell.
Design your in-app message
Full reference for the IAM editor, blocks, and Carousel.
Prompt for push permission
Configure a Push Permission Prompt click action on a Day 1 IAM.
Time Window: A delivery window in the user’s local timezone (default: 6 PM – 10 PM). Each day’s push is held until the window opens.
Set the Wait to the Time Window duration + a 2-hour buffer. For a 4-hour evening window, the Wait is 6 hours — the buffer guarantees the Wait always expires after the window closes, so the next push is held for the following day rather than re-firing the same evening. See Welcome Journey: Mobile gaming for the full timing math.
Adjust the Time Window to your audience. B2B productivity apps may prefer a 9 AM – 12 PM weekday window; consumer wellness apps may prefer 7 AM – 9 AM. Evening is a strong default for general consumer apps but worth A/B testing against your usage data.
Case 1 – Basic
Case 2 – Advanced
The Basic flow uses time-based delays and the recent-activity Yes/No branch — a “set it and forget it” 7-day welcome that requires no Custom Events or Tags.
Day 1
1
Email: Day 1 — Welcome and push opt-in
Goal: Open the Journey with an appreciative, value-led email that also drives push opt-in.Because this is the first message step, the email lands 4 hours after the user’s first session ends (per the entry segment) — less needy, more deliberate. The email’s push opt-in CTA also catches users who declined the install-time permission prompt, deep-linking them to the in-app preference center.
2
In-App Message: Day 1 — Onboarding flow
Goal: Drive profile completion and push opt-in the next time the user opens the app.Queue the Day 1 onboarding IAM so it displays on the user’s next session. The flow funnels them into:
Profile / preferences completion
Push opt-in via a Push Permission Prompt click action
Make sure this IAM doesn’t overlap with other push permission prompt strategies outside the Journey. Two prompts firing back-to-back leads to one being silently skipped — better to remove it from this IAM than have both trigger.
3
Time Window: 6 PM – 10 PM
Goal: Hold the Day 1 push until the evening engagement window.The entry segment can trigger overnight or early morning. Without the Time Window, an inactivity threshold crossed at 2 AM would push at 6 AM. This holds the push until 6 PM in the user’s timezone.
4
Push Notification: Day 1 — First action
Goal: Drive a second session by deep-linking to the highest-leverage first action.Keep copy short and benefit-driven — “Here’s the one thing to try first” works as a starting point. Deep-link to the exact screen where the user can take that action, not the app home.
Day 2
1
Wait: 6 hours
Goal: Push the next Time Window evaluation past 10 PM so the window snaps to the next day rather than re-firing the same evening. See Daily timing for the math.
2
Time Window: 6 PM – 10 PM
Goal: Hold the next push until the evening engagement window.
3
Yes/No branch: Active in the last 12 hours
Goal: Skip the push if the user has already returned to the app.Setup: Segment membership: “Active in the last 12 hours.”This creates two branches:
Yes: User was active in the last 12 hours → skip the push and continue to the next day’s Wait.
No: User has not returned → send the Day 2 push on the No branch.
4
Push Notification: Day 2 — Quick win
Goal: Bring the user back with a 60-second action that reinforces value.Add this to the No branch of the Yes/No step.
Days 3–6
Each day repeats the Day 2 pattern — Wait 6 hours → Time Window 6 PM – 10 PM → Yes/No branch → push on the No branch. Drop in the per-day push template (Day 3 — Feature tip, Day 4 — Use case, Day 5 — Setup nudge, Day 6 — Community).Insert the Day 3 feature spotlight and Day 6 community/share IAM steps before their corresponding day’s 6-hour Wait, so the IAM is queued and ready to display the next time the user opens the app.
Day 7
Day 7 follows the same four-step pattern as Days 2–6, then adds the closing email after the branches converge:
1
Wait: 6 hours
Goal: Push the next Time Window evaluation past 10 PM so the window snaps to the next day.
2
Time Window: 6 PM – 10 PM
Goal: Hold the Day 7 push until the evening engagement window.
3
Yes/No branch: Active in the last 12 hours
Goal: Skip the push if the user has already returned to the app.Setup: Segment membership: “Active in the last 12 hours.”
Yes: User was active in the last 12 hours → skip the push and continue to the closing email.
No: User has not returned → send the Day 7 push on the No branch, then continue to the closing email.
4
Push Notification: Day 7 — Week 1 wrap (No branch)
Goal: Send a final value reminder before the closing email lands.Add this to the No branch of the Yes/No step.
5
Email: Day 7 — First week recap and what's next
Goal: Transition the user from “trying the product” to “part of the community.”Add this email step after the Yes/No branch’s two paths converge — not on either branch. Placing it after convergence means active and inactive users both receive the milestone email, regardless of whether they took the Day 7 push.
Case 2 is structurally identical to Case 1 — same Day 1 setup, same Day 3 and Day 6 IAMs, same Day 7 closing email. The only change is from Day 2 onward: replace Case 1’s Wait + Yes/No branch with a single Wait Until node that listens for core_feature_used (or another high-signal Custom Event). The Time Window stays.This swaps a time-based heuristic (“did the user open the app in the last 12 hours?”) for a behavioral fact (“did the user actually do the thing the Journey is nudging?”). Users who hit the event take the event branch and continue silently — no push lands on top of an active session, and active users still receive the closing Day 7 email.
Required data
Type
Name
Description
Custom Event
core_feature_used
Fires when the user takes the Aha-moment action. Dedupe to once per calendar day in the user’s timezone so same-day repeats don’t advance the Journey through subsequent days.
Tag (string)
first_name
Recommended. Used by the email and push templates for {{ first_name | default: 'there' }} personalization.
Tag (string)
acquisition_source
Optional. Lets you vary Day 1 push and email copy by acquisition channel.
Day 1
Identical to Case 1: Email → IAM → Time Window → Push. The only difference is the entry rule — Case 2 enters on the signup_completed Custom Event with a 4-hour Wait, instead of the inactivity-based segment. Switch to the Case 1 – Basic tab above to see the full Day 1 step list.
Days 2–6
Days 2 through 6 share a single pattern. Each day uses a Wait Until node in place of Case 1’s Wait + Yes/No combo. The Time Window and the day’s push move onto the expiration branch; the event branch stays silent.
1
Wait Until: core_feature_used
Goal: Branch on whether the user has hit their Aha moment in the last day.Condition:core_feature_used Custom Event fires.
Expiration:22 hours.
Event branch — user activated on their own. Continue silently; no push, no email.
Expiration branch — no activation in 22 hours. Continue to the Time Window and the day’s push.
Scope each Wait Until to a specific day with an event property. Fire core_feature_used with a property like day that increments per session day, and have each day’s Wait Until match the corresponding value. This prevents a late-arriving event from an earlier day from satisfying a later day’s Wait Until and gives you cleaner per-day funnel analytics. See Event Matching.
2
Time Window: 6 PM – 10 PM (expiration branch only)
Goal: Hold the day’s push until the evening engagement window.On the expiration branch only. Same Time Window pattern as Case 1, kept here so the push always lands in the evening regardless of when the Wait Until expired.
Goal: Send the day’s nudge — Day 2 — Quick win, Day 3 — Feature tip, etc.After this step, both branches converge and continue to the next day’s Wait Until.
IAM placement. Insert the Day 3 feature spotlight and Day 6 community/share IAM steps before their corresponding day’s Wait Until node, so the IAM is queued and ready to display the next time the user opens the app.
Day 7
Day 7 follows the same Wait Until pattern as Days 2–6 and adds the closing email after the branches converge:
1
Wait Until + Time Window + Push (expiration branch)
Same shape as Days 2–6: a Wait Until on core_feature_used with a 22-hour expiration, then the Time Window and Day 7 — Week 1 wrap push on the expiration branch. The event branch stays silent.
2
Email: Day 7 — First week recap and what's next
Goal: Transition the user from “trying the product” to “part of the community.”Add this email step after both branches converge — not on either branch. Active and inactive users both receive the milestone email, regardless of whether the push fired. Personalize the recap section using Tags you’ve collected during the week (core_feature_used, completed-setup signals, etc.).
Optional: route activated users to a separate post-activation Journey
If you want to do more than fall silent on activation, configure the Journey exit rule to fire on core_feature_used = "1" and use that Tag (or a welcome_completed = "true" Tag set in a Tag User step) as the entry filter for a follow-up Journey focused on adoption depth — second-tier features, integrations, or expansion offers.
Track time-to-Aha, not just open rate. The single best indicator of welcome Journey health is how quickly new users hit your core feature for the first time. Compare your control group to users who completed the welcome Journey to measure lift.
The trial-to-paid Journey converts trial users to paying subscribers in the days before their trial ends. Where the Welcome Journey teaches the product, this Journey closes the deal — value reminders, time pressure, and a clear upgrade ask calibrated to where the user is in the trial. Three principles drive the structure:
Time pressure beats discount. A trial-ending reminder converts higher than a blanket “20% off” email. Use trial_end_date for a real countdown; reserve discounts for the final day or the win-back Journey.
Activation status changes the message. A trial user who hit the core feature gets “Keep going — your data and progress carry over”; one who didn’t gets “Try {{ core_feature_name }} before your trial ends — it’s the part most subscribers love.” Same Journey, branched copy.
Exit on conversion, immediately. Add an exit on trial_converted (or account_type = "paid") so converted users stop receiving “trial ending” pushes. This is the single most damaging conversion-Journey mistake — see the mobile-first FAQ for the suppression pattern.
Case 1: account_type = "trial" AND trial_end_date within the next 7 days (the Trial Expiring segment from the strategy page, with the threshold widened from 3 days to 7).
Case 2: Custom Event entry on trial_started with a Wait until 7 days before trial_end_date using time operators. Cleaner attribution — entry timestamp matches the trial’s actual start, not the moment OneSignal evaluated the segment.
Exit rules:
Both cases: Exit when trial_converted Custom Event fires oraccount_type = "paid". Whichever your billing pipeline updates first triggers the exit.
Both cases: Also exit on subscription_cancelled so users who explicitly cancel their trial don’t get further reminders.
Re-entry rules: No — most trials are single-use. Apps that offer trial extensions should set re-entry per business policy.Future additions only:Checked — keep this on so users mid-trial when the Journey is created don’t get bulk-enrolled into a 7-day cadence partway through.
Soft heads-up. “Your trial ends {{ days_remaining }} days from now” framing.
5
Email
Feature recap + upgrade CTA. Personalize the recap with what the user already used.
3
Push + IAM
Activation-aware nudge. Deep-link to the upgrade screen, or the core feature for unactivated users.
1
Push
Last call — concrete time remaining. “Your trial ends tomorrow at {{ trial_end_time }}.”
0 (last day)
SMS (optional)
High-intent SMS-opted-in users only. Keep copy short and include the upgrade deep link.
Keep every push and email deep-linked to the upgrade screen — see Deep linking. The fewer taps between message and conversion, the higher the rate.
Case 1 – Basic
Case 2 – Advanced
The Basic flow uses the trial_end_date Tag with time operators to schedule each day’s message a fixed number of days before the trial ends.
1
Entry: Trial Expiring (widened to 7 days)
Goal: Catch every trial user 7 days before their trial ends.Setup: Build a segment account_type = "trial" AND trial_end_date within the next 7 days. Use this as the Journey entry audience.
2
Push: Day-7 heads-up
Goal: Open the Journey with a non-pushy reminder that the trial is ending.Lead with what the user has already done, not what they’ll lose. “You’ve logged 6 sessions — keep your streak going past {{ trial_end_date | date: '%b %-d' }}” outperforms “Your trial expires soon.”
3
Wait Until: 5 days before trial_end_date
Goal: Hold until the next milestone.Use a time operator Wait Until: trial_end_date - 5 days. This is more precise than a fixed 2-day Wait, because it anchors to the actual trial end date for users who entered partway through their trial.
4
Email: Day-5 feature recap and upgrade CTA
Goal: Surface a longer-form value reminder with a primary CTA to upgrade.Recap features used during the trial (where you have the data) and pair the recap with a single upgrade CTA. Email is where the longer-form value case lives — push and IAM carry the urgency.
5
Wait Until: 3 days before trial_end_date
Goal: Hold until the Day-3 push window.
6
Push: Day-3 nudge
Goal: Re-engage users who haven’t yet upgraded.Reference time concretely: “3 days left.” Deep-link to the upgrade screen.
7
Wait Until: 1 day before trial_end_date
Goal: Hold until the final-day push.
8
Push: Last call
Goal: A clear, concrete final ask.“Your trial ends tomorrow at {{ trial_end_date | date: '%-l %p' }}.” Keep the copy tight; this is the highest-intent moment in the Journey.
9
Exit on trial_converted or account_type = paid
Goal: Stop the Journey the moment the user converts.Configure as a Journey-level exit rule, not a step. Exit also on subscription_cancelled so cancelled users don’t continue to receive trial-ending reminders.
Case 2 is structurally identical to Case 1, with two additions: an entry rule on trial_started (cleaner attribution than segment entry), and an activation branch that varies copy based on whether the user has hit core_feature_used.
Required data
Type
Name
Description
Tag (timestamp)
trial_end_date
Unix timestamp set at trial start. Required for time-operator Waits.
Tag (string)
account_type
trial / paid / lapsed. Drives Journey entry and exit.
Tag (1)
core_feature_used
Drives the activation branch. Users with the Tag get “keep going” copy; users without get “try the core feature” copy.
Custom Event
trial_started
Journey entry event.
Custom Event
trial_converted
Exit event.
Activation branch
The key Case 2 enhancement is a Yes/No branch on core_feature_used before each push, so the same Journey delivers two parallel cadences:
Activated users (core_feature_used = "1"): “You’re on track — {{ core_feature_name }} is what most subscribers stay for. Keep going past {{ trial_end_date | date: '%b %-d' }}.”
Unactivated users (Tag does not exist): “Try {{ core_feature_name }} before {{ trial_end_date | date: '%b %-d' }}. It’s the part most subscribers love.”
Both branches deep-link to the upgrade screen; the activation branch additionally references the feature in a positive frame, while the unactivated branch deep-links to the core feature itself on the Day-3 push to give the user one last shot at activation before asking for the upgrade.
Day-by-day shape
Identical to Case 1’s step list, with the activation branch inserted before each push step (Day 7, Day 3, Day 1, and the optional Day 0 SMS). The Day-5 email gets the same activation-aware variation via Liquid conditionals — see Liquid syntax.
Measure trial-to-paid conversion rate by activation status. Activated users should convert at materially higher rates than unactivated users. If they don’t, the issue is upstream — your Welcome Journey isn’t hitting the right Aha moment, not your conversion copy.
Event-driven Journeys react to specific actions in real time. They’re entirely Case 2 territory — you need Custom Events flowing into OneSignal to use them.Common mobile-first event-driven patterns:
Pattern
Trigger event
What the Journey does
Purchase confirmation
purchase_completed
Thank-you push and email receipt with cross-sell items
A representative event-driven shape that almost every subscription app needs. Failed renewal payments are involuntary churn — most users want to keep paying but have an expired card or a temporary decline. A short dunning Journey recovers the majority of these.
1
Entry: payment_failed Custom Event
Goal: Catch failed renewal charges the moment your billing platform reports them.Fire payment_failed from your backend with failure_reason (e.g., card_expired, insufficient_funds) as a property. Filter the entry rule to account_type = "paid" so failed checkout attempts on free accounts don’t enter the dunning Journey.
2
Wait Until: payment_succeeded
Goal: Exit the Journey the moment the customer’s card processes successfully.Condition:payment_succeeded Custom Event fires.
Expiration:48 hours — most card retries succeed within 24–48 hours of the original failure.
Goal: Surface a one-tap deep link to the billing or payment-method screen.Use Liquid to vary copy by failure_reason — “Your card on file expired” lands much better than a generic “We couldn’t process your payment.” Deep-link straight to the card-update screen so the user doesn’t have to navigate.
Goal: Give the customer a longer-form explanation and a self-serve recovery path.Send 1–2 hours after the push so they aren’t simultaneous. Include the amount, the SKU or plan name, the failure reason, and a primary CTA to update payment. Email is also where the legal/billing detail lives that doesn’t fit in a push.
5
Exit: subscription_cancelled or 7-day timeout
Goal: Stop dunning if the customer cancels or never recovers.Add an explicit exit on subscription_cancelled so a cancellation routes the user into the Win-back Journey instead of continuing to receive payment-update reminders. After 7 days without success, the customer flips to account_type = "lapsed" via your billing webhook and exits naturally.
The full pattern guide — entry rules, Wait Until with Event Matching, threshold modeling, and Liquid personalization — lives on Event-driven Journeys. For mobile-specific welcome and retention shapes that include event-driven steps, see Case 2 in the Welcome and Retention sections on this page.
Event-driven Journeys
Three end-to-end patterns plus the design rules for events, properties, and Wait Until matching.
Retention catches active users who are slipping before they fully disengage. Two triggers matter for mobile-first apps:
Inactivity — the user hasn’t opened the app in N days
Core feature dormancy — the user is opening the app, but hasn’t engaged with the core feature in N days (Case 2 only — needs the core_feature_used Tag)
Retention catches users who are still active subscribers but slipping. Once a user explicitly cancels or expires, they belong in the Win-back Journey, not this one. The two share Tags and segments but have different goals — retention prevents churn, win-back recovers churned users.
Both cases share segment shape; the difference is granularity.Entry trigger:
Case 1: Built-in segment Last Session > 7 days.
Case 2: Combine Last Session > 7 days with account_type to split trial users (7 days) from paid users (14 days). Optionally add a parallel Core feature untouched segment for feature-dormant users.
Cadence (both cases):
Day
Channel
Purpose
7 / 14
Push
Reminder of value the user has already seen
10 / 17
Email
Tip or use case the user may not have discovered
14 / 21
Push
One clear action to bring them back
Exit conditions:
Both cases: Auto-exit when the user opens the app (segment membership ends).
Case 2: Also exit on subscription_cancelled event so the user moves to the win-back funnel without overlap.
Case 1 – Basic
Case 2 – Advanced
The Basic retention flow uses OneSignal’s built-in Last Session filter to target both trial and paying users with a single cadence.
1
Entry: Last Session > 7 days segment
Goal: Catch users the moment they cross the inactivity threshold.Built-in segment using OneSignal’s Last Session filter. Adjust the threshold based on your app’s expected usage cadence — daily-use apps may want 3–4 days, weekly-use apps may want 10–14.
2
Push Notification: Day 7 — Value reminder
Goal: Surface a short, benefit-led nudge that reminds the user what they’re missing.Lead with the benefit, not a feature list. “Your week-in-review is ready” outperforms “Don’t forget to use feature X” because it implies the user has earned something. Deep-link directly to the relevant screen — see Deep linking.
3
Email: Day 10 — Feature tip
Goal: Re-engage users who didn’t respond to the Day 7 push with a longer-form value message.Email lets you carry more context than push. Highlight a feature, walkthrough, or use case the user may not have discovered. Keep it scannable — most reads happen in under 30 seconds.
4
Push Notification: Day 14 — Final CTA
Goal: Send one last clear action before the user fully disengages.Lead with a concrete next step rather than a guilt trip. “Pick up where you left off” works better than “We miss you.”
5
Exit: on app open
Goal: Remove returning users from the Journey automatically.Because the entry segment depends on Last Session, the user falls out of segment membership when they open the app — no explicit exit rule needed. Make sure the Journey’s re-entry rules allow re-entry after exit so the next inactivity period catches them again.
Track 14-day return rate as the headline retention metric. A return rate above 8% on the Day-14 push is healthy for most subscription apps; below 4%, the inactivity threshold or message copy needs tuning before the cadence itself is the problem.
The Advanced retention flow uses account_type to split cadences between trial and paying users.
1
Entry: split by account_type
Goal: Apply different inactivity thresholds for trial users vs paying users.
Trial users:account_type = "trial" AND Last Session > 7 days. Trial users have a short window before churn — react fast.
Paid users:account_type = "paid" AND Last Session > 14 days. The longer window accounts for normal usage variation in users who have already converted.
Build these as two separate segments and run two parallel Journeys, or build one Journey with two entry rules — whichever your team can maintain more easily.
2
Push Notification: Day 7 / 14 — Personalized reminder
Goal: Bring the user back with a message that references something they already care about.If you have a most_used_feature Tag, mention it specifically: “It’s been a week since your last {{ most_used_feature }} session.” This lands meaningfully better than generic “We miss you” copy.
3
Email: Day 10 / 17 — Feature highlight
Goal: Email users who didn’t respond to push with a longer-form re-engagement message.Highlight a feature or use case they haven’t explored. Pull from the same most_used_feature Tag for personalization — “You’ve mastered {{ most_used_feature }}. Here’s what to try next.”
4
Push Notification: Day 14 / 21 — Final CTA
Goal: Make a clear final ask before the user fully disengages.If the user is still in trial, reference time remaining via trial_end_date — “Only 3 days left to set up your account.” Trial-aware copy materially outperforms generic re-engagement at the end of the funnel.
5
Exits: app open or subscription_cancelled
Goal: Remove returning users automatically and route churned users to the win-back funnel.
App open: segment membership ends naturally when the user opens the app.
subscription_cancelled event: explicit exit rule that moves the user out of retention and into win-back without overlap. See Mobile-first strategy for the win-back playbook.
Use SMS sparingly. SMS is most effective for high-intent moments — trial expiration, payment failures, account verification. Avoid using it for general re-engagement; the cost-per-message is high and the unsubscribe risk is real.
A user who’s actively opening the app but never touching the core feature is a different kind of risk than one who’s just inactive. They’ve passed the install hurdle but stalled before activation — re-engagement copy aimed at “we miss you” misses the actual problem.Use the Core feature untouched segment from Mobile-first strategy — core_feature_used does not exist — combined with Last Session < 7 days so you only message users who are opening the app.
1
In-App Message: Core feature pointer
Goal: When the user is in the app, redirect their attention to the core feature.The IAM should include:
A single, specific benefit tied to the core feature (“Set up your first goal in 60 seconds”).
A primary CTA that deep-links to the core feature screen.
A dismiss action that doesn’t re-show on the same session.
Target the IAM at Segment is “Core feature untouched” AND Last Session < 24 hours so it shows on the user’s next visit while the moment is still fresh.
2
Push Notification: Core feature CTA
Goal: Catch the user when they’re outside the app.Send a single push that deep-links to the core feature, no more than once per dormancy period. If they still haven’t engaged after 7 more days, they fall into the inactivity track above naturally — don’t double up.
Win-back targets users who have already churned — cancelled, lapsed, or expired — and aims to bring them back. The audience and goal are different from Retention: retention prevents churn for users still on a paid plan, while win-back recovers users who are no longer paying. Run them as separate Journeys with different exit conditions so a user can’t sit in both at once.Three principles drive the structure:
Lead with value, not discount. A “what you’ve been missing” message converts higher than a generic discount the first time. Reserve discounts for the second touch — discounting on day one trains users to cancel and wait for a coupon.
Cap the active window. Run win-back for 60 days post-cancellation, then exit users to a long-tail dormant list. Past 60 days, the unsubscribe risk outweighs the recovery upside.
Differentiate by past value. A high-LTV churned user (former VIP, long tenure, high spend) deserves a richer offer than a one-month trial that lapsed. Case 2 splits the cadence by total_spend_cents or tenure.
Case 1: Built-in segment account_type = "lapsed". Most billing pipelines flip the Tag from paid to lapsed on the cancellation date or at the end of the paid period.
Case 2: Custom Event entry on subscription_cancelled, with a 7-day Wait before the first message. The 7-day buffer lets the immediate-regret cancellations pass — those users either resubscribe on their own or were never going to come back.
Exit rules:
Both cases: Exit when account_type returns to paid, OR when trial_started or subscription_renewed Custom Event fires. Any of these mean the user is back; stop messaging.
Both cases: Hard exit at 60 days post-entry. Configure as a final step or a Journey-level timeout — depending on your dashboard, this might be a Wait: 60 days followed by a Tag User step that adds winback_completed = "1" so the user can be excluded from re-entry.
Re-entry rules: Allow re-entry — a user who churns, returns, then churns again should re-enter the Journey on the new cancellation.
”Here’s what you’ve been missing.” Value reminder, no discount, no urgency.
14
Push
One specific feature or content drop the user hasn’t seen. Deep-link to it.
30
Email
Return offer — first month at 50%, free trial extension, or feature unlock. First time discount appears.
45
Push
Final low-key reminder of the offer. Use {{ first_name | default: 'there' }} to personalize.
60
(none)
Hard exit. User flips to winback_completed.
Case 1 – Basic
Case 2 – Advanced
The Basic flow uses account_type = "lapsed" and a fixed 7 / 14 / 30 / 45 / 60-day cadence. Suitable for any app where your billing webhook updates account_type on cancellation.
1
Entry: account_type = lapsed
Goal: Catch every lapsed user automatically the moment your billing pipeline flips the Tag.Setup: Built-in segment using the account_type Tag. Confirm your billing webhook fires reliably on the cancellation date or at the end of the paid period — without that, the Journey won’t have an audience.
2
Wait: 7 days
Goal: Hold the first touch a week post-cancellation.Skipping the first week filters out immediate-regret cancellations and avoids the “we just got your cancellation” tone that reads as either tone-deaf or pushy.
3
Email: Day 7 — What you've been missing
Goal: A value reminder, no discount.Recap recent product updates, content drops, or feature releases since the user cancelled. Keep the tone neutral and informative — the user hasn’t asked to be back yet.
4
Wait: 7 days (to Day 14)
Goal: Hold until the Day 14 push.
5
Push: Day 14 — Specific feature
Goal: Surface one feature or content drop tailored to the user’s past usage.Deep-link directly to the relevant screen behind the auth wall — the user will hit a “log in or restart subscription” prompt, which is exactly the moment for an upgrade.
6
Wait: 16 days (to Day 30)
Goal: Hold until the offer touch.
7
Email: Day 30 — Return offer
Goal: First time the Journey introduces a discount or extension.Common offers: first month at 50%, two-week free trial extension, or a feature unlock. Whatever you choose, make the offer concrete, time-bound (e.g., expires in 14 days), and deep-link to a one-tap restart flow.
8
Wait: 15 days (to Day 45)
Goal: Hold until the final reminder.
9
Push: Day 45 — Final reminder
Goal: Low-key nudge that the offer is still available.“Your offer expires in {{ days_remaining }} days” works if your billing system supports a unique offer per user. Otherwise, a simple “We’re still saving your spot” is fine.
10
Exit: 60 days or account_type = paid
Goal: Stop the Journey.Configure two exits:
Conversion exit: account_type = "paid" OR subscription_renewed event fires. The user is back; stop messaging.
Timeout exit: 60 days from entry. Set a winback_completed = "1" Tag in a Tag User step before exit so re-entry rules can exclude these users from accidental re-entry.
Case 2 splits the cadence by past customer value. High-LTV churned users get a richer offer earlier; low-LTV users get the standard cadence. The structure is the same; the offer and channel mix differ.
Required data
Type
Name
Description
Tag (string)
account_type
Set to lapsed on cancellation by your billing webhook. Drives entry.
Tag (integer)
total_spend_cents
Lifetime value to date. Drives the high-LTV branch.
Tag (timestamp)
subscription_start_date
Used to compute tenure for tenure-based segmentation.
Custom Event
subscription_cancelled
Optional Journey entry event. Carry cancel_reason as a property if your billing platform captures it.
Custom Event
subscription_renewed / trial_started
Exit events for users who return on their own or via the Journey.
High-LTV vs standard branches
After the Day-7 entry Wait, branch on total_spend_cents (or your equivalent LTV threshold):
High-LTV branch (total_spend_cents > 5000 — adjust to your business): Day 7 personal email referencing tenure (“You were with us for {{ tenure_months }} months”). Day 14 push with a tier-specific concierge offer (priority support, free upgrade, account-manager outreach). Day 30 offer is more generous than the standard branch — e.g., 3 free months or a year-over-year price match.
Standard branch (total_spend_cents <= 5000): Identical to Case 1’s cadence — Day 7 value email, Day 14 feature push, Day 30 offer, Day 45 reminder, Day 60 exit.
cancel_reason-aware copy
If subscription_cancelled carries a cancel_reason property (e.g., too_expensive, not_using, missing_feature), branch the Day-7 email on that property:
too_expensive: Lead the Day-30 offer with the discount.
not_using: Day 7 leads with the most-valuable feature the user did use; Day 14 surfaces a feature drop.
missing_feature: Reference the feature directly. If it’s now shipped, lead with that. If it isn’t, route to a long-tail “we’ll let you know when this ships” list and exit the standard win-back Journey early.
Win-back rate is a lagging indicator. A churned user who returns within 60 days is what most teams measure, but a user who returns 9 months later via a separate channel (paid acquisition, organic search, referral) is also a win-back success even though no Journey claims credit. Track both — the Journey-attributed win-back rate and the overall churned-cohort return rate at 90 / 180 / 365 days.
How do I prevent a user from receiving overlapping Journeys?
Use exit conditions that map to Journey progression:
Welcome exits when core_feature_used = "1" or onboarding_completed.
Trial-to-paid exits when trial_converted or account_type = "paid". Also exits on subscription_cancelled so cancelled trials don’t keep getting reminders.
Retention only enters when Last Session > 7 days AND account_type is trial or paid. Exits on app open or subscription_cancelled.
Win-back only enters when account_type = "lapsed" (or on subscription_cancelled event). Exits on account_type = "paid", subscription_renewed, or 60-day timeout.
Re-entry rules on Journey settings prevent the same user from re-entering an active flow. See Re-entry rules.
Can I build these Journeys without Custom Events or Tags?
Yes — the Case 1 versions of Welcome, Retention, and Win-back use only built-in segments (First Session, Last Session, account_type) and require no Custom Events. Trial-to-paid requires the trial_end_date Tag in both cases. Event-driven Journeys (purchase confirmation, milestones, dunning) all require Custom Events.
Before sending any Welcome or Retention email at scale on a new sending domain. See Email warm-up. For double opt-in flows that confirm subscribers before adding them to your sending list, see Set up confirmed opt-in for email.
How frequently should I message users in onboarding?
A common starting point is one message per day for the first 3 days, then drop to every 2–3 days. Watch unsubscribe rate and push opt-out rate at each step — those tell you sooner than open rate whether you’re being too aggressive.
Do I need to use all three channels (push, email, SMS)?
No. Push and in-app are the foundation for mobile-first. Email layers in for consenting users when you have longer-form content (welcome, weekly digest, conversion). SMS is reserved for urgent, high-intent moments. Most apps run effectively on push + email.