Stop Losing Renewals You Already Earned: A Renewal Reminder Journey for Shopify Apps
A detailed Spreeflo journey for Shopify apps to protect renewal revenue by segmenting auto- vs manual-renew customers, timing reminders at 30/7/1 days, catching billing issues early, and escalating only the right high-value accounts for human follow-up.
Industry
Niche
Pattern
Loading sequence...
Three times a year, Lina opens Stripe and winces.
She runs ChannelBoost, a Shopify reporting app doing about $95k MRR. Most of her bigger merchants are on annual plans. Every month, a small wave of contracts comes up for renewal. And every time, a familiar pattern shows up in the Stripe exports: a chunk of those “good fit” stores never renew.
Cards expired. Owners got busy. Someone meant to “review tools next week” after busy season and never came back.
None of that shows up as a rage-quit churn email. It’s quiet, unintentional decay.
The sequence at the top of this page is the whole journey, end to end. It’s built to catch that decay: a renewal reminder series that treats auto-renew and manual renewal customers differently, nudges billing updates before they fail, and flags at‑risk accounts for a human follow-up when it actually matters.
For a typical Shopify app with mixed monthly and annual plans, getting this right is often the easiest way to add low-double-digit percent to net revenue retention. Not from fancy feature launches, but from not dropping the ball on renewals you already earned.
Let’s walk through how the journey works and how you can adapt it to your own billing setup.
Where renewal revenue actually leaks
For e‑commerce apps, churn around renewal dates usually falls into three buckets:
Auto‑renew fails because billing details are stale.
Manual‑renew customers forget or postpone.
High‑value accounts wobble, but nobody notices in time to step in.
Each of these is preventable with simple, targeted communication. The problem isn’t strategy; it’s execution. Most teams either:
Blast a single generic “your plan renews soon” email to everyone, or
Rely entirely on in‑app banners that get ignored.
Spreeflo exists for exactly this kind of lifecycle leak. You don’t need more headcount to fix it. You need a journey that:
Knows who is coming up for renewal and when.
Knows whether they’re on auto‑renew or manual.
Paces touchpoints at 30, 7, and 1 day.
Escalates only the right customers to a human.
That’s what the journey at the top of this page does.
The data you need before you build
Before you drag a single node into the canvas, make sure your billing system is feeding Spreeflo three things for each subscriber:
A numeric custom attribute,
days_to_renewal
Updated daily via the billing backend. For an annual plan renewing in 30 days, this would be30, then29, and so on.A boolean or text attribute,
auto_renew_enabledtrue/false, or"auto"/"manual".(Optional but valuable) A numeric attribute,
mrrorplan_value
So you can prioritize internal alerts for bigger accounts.
You’d typically push these values in with the Spreeflo API on a nightly cron, along with whatever you already use to sync subscription_status.
Once those attributes exist, everything else in this playbook is point‑and‑click inside the journey editor.
Step 1: A Cyclic trigger that watches upcoming renewals
This is a date‑driven journey, so it starts with a Cyclic trigger.
Configuration:
Repeat interval: Every 1 day
Time of day: 09:00 in your main support timezone
Re‑enrollment: On (you want the same contact to re‑enter at 30, 7, and 1 day)
Criteria: contacts whose
days_to_renewalattribute is 30, 7, or 1 and whose subscription is currently active
You express the criteria using Spreeflo’s segment builder:
Outer group: OR
- Rule 1:days_to_renewalis30
- Rule 2:days_to_renewalis7
- Rule 3:days_to_renewalis1AND a second group: subscription_status is
"active"
Why this shape matters:
Using Cyclic instead of a one‑off trigger keeps the journey evergreen. You don’t hard‑code actual dates. As long as your backend updates
days_to_renewal, this single journey will handle every renewal, forever.Re‑enrollment is set to true because you explicitly want the same account to come back through on different days. The journey paths are short and don’t contain multi‑week waits, so contacts have exited by the time the next milestone comes around.
From this trigger, every matching contact flows directly into a Multi‑way Split.
Step 2: Split the journey into 30‑, 7‑, and 1‑day tracks
The Multi‑way Split node branches by days_to_renewal:
Branch “30_days”:
days_to_renewalis30Branch “7_days”:
days_to_renewalis7Branch “1_day”:
days_to_renewalis1Else branch: ends (safety net in case something unexpected slips through)
This keeps the logic for each touchpoint contained, so you can edit, test, and measure each milestone separately.
Every branch immediately flows into an If/Else that checks auto_renew_enabled. That gives you six distinct paths:
30‑day auto‑renew
30‑day manual
7‑day auto‑renew
7‑day manual
1‑day auto‑renew
1‑day manual
From there, the work is mostly about crafting the right emails and deciding where human intervention is worth it.
Step 3: What happens 30 days before renewal
At 30 days, you’re informing and pre‑framing, not selling hard.
30‑day auto‑renew path
Nodes:
If/Else:
auto_renew_enabledis true → this branch.Send Email: “Heads‑up: your ChannelBoost plan renews in 30 days”
Add Tag: apply something like
renewal_30d_notified
Use this as a value recap:
Remind them of key wins (you can pull usage stats from your app into the template if you sync those as attributes).
Clearly state renewal date and price.
Offer an easy way to change plan or turn off auto‑renew.
You design the email itself with Spreeflo’s email builder, and keep “Send only once” checked so the same contact never gets duplicate copies if something goes wrong upstream.
Tagging isn’t mandatory for the logic, but it helps you later if you want a segment of “received 30‑day reminder but still churned.” Tags are simple to manage in the UI, and you can learn more about them in the tags guide.
Why no waits here?
At 30 days, you aren’t gating later steps on action. That’s handled at 7 days. The contact exits the journey quickly, which keeps re‑enrollment available for the 7‑day milestone.
30‑day manual‑renew path
Nodes are identical structurally, but copy changes:
If/Else:
auto_renew_enabledis false → manual branch.Send Email: “Your ChannelBoost subscription is up for renewal in 30 days”
Add Tag:
renewal_manual_30d_notified
The call to action is different:
Explain that their plan will not renew automatically.
Spell out what they’ll lose if they let it lapse (historical reports, automations, etc.).
Offer an “add auto‑renew” link if your billing supports it.
Again, no waits here. The goal is awareness; you’ll push harder at 7 and 1 day.
Step 4: The 7‑day checkpoint (where you manage real risk)
Seven days out is where you start actively protecting against avoidable churn.
7‑day auto‑renew: catch billing problems early
Send Email: “7 days until your ChannelBoost renewal — quick billing check”
Wait Condition: up to 3 days for billing to be updated
If/Else: did they update billing?
Content:
Confirm renewal date and amount.
Show the last 4 digits and expiry of the current card.
Prompt them to update billing details if the card is expiring soon or belongs to a past employee.
The Wait Condition checks a condition like:
Custom event
payment_method_updatedtriggered at least 1 time in the last 3 days
ORTimestamp attribute
billing_updated_atis not blank and is_after [today minus 3 days]
If that condition becomes true, the contact moves on immediately. If not, they move on after 3 days anyway. Either way, this wait creates the pacing gap you need before any further email.
The If/Else re‑uses the same condition as the wait:
Yes branch (billing updated):
- Add Tag:billing_ok_pre_renewal
- Exit.Else branch:
- Send Internal Email: “High‑value renewal with stale billing”
In the Send Internal Email node, you can:
Route to a shared “success@” inbox or a renewal‑owner’s address.
Include the contact’s email, plan, current MRR, and renewal date in the body.
Keep “Send only once” on to avoid spamming your team if the contact ever re‑enters this branch.
Optionally, you can guard this internal alert with another If/Else on mrr or plan_value so you only ping humans for accounts above a threshold (say, $200 MRR).
Why this structure:
You’re still only sending one external email on this path.
The Wait Condition enforces a time gap before any internal alert.
You focus human attention where it changes the outcome instead of letting failed renewals surprise you.
7‑day manual‑renew: push action, then escalate
Send Email: “Renew your ChannelBoost account in the next 7 days”
Time Delay: 2 days
If/Else: did they manually renew?
This is your main conversion email for manual renewals:
Restate value and key features they’re using.
Include a big “Renew now” button.
If you offer an incentive (e.g., lock in current pricing), this is the place.
A simple Time Delay node (2 days) gives enough space to avoid feeling spammy and satisfies the rule that you never send back‑to‑back emails without a wait.
There are several ways to express this condition in the segment builder:
Custom event
subscription_renewedtriggered at least 1 time in the last 7 days, orAttribute
subscription_statusis"active"ANDdays_to_renewalis greater than300(for annual), depending on how you encode it.
If yes:
- Add Tag:manual_renewed_post_7d
- Exit.If no:
- Send Internal Email: “Manual renewal at risk: 5 days left”
- Optionally, Add Tag:manual_renewal_at_risk
This gives your team the chance to message them personally, especially for stores you’d hate to lose. Often a short, founder‑sent note wins back accounts that would otherwise quietly disappear.
Step 5: The 1‑day “no surprises” reminder
By the time days_to_renewal hits 1, your job is clarity.
1‑day auto‑renew path
Send Email: “Your ChannelBoost plan renews tomorrow”
Add Tag:
renewal_1d_notified
Keep it short:
Confirm amount and billing date.
Remind them it’s automatic.
Provide a one‑click link to manage their plan if needed.
That tag is useful later when you analyse churn: if someone cancels right after this email, you know they were at least consciously opting out rather than silently failing.
1‑day manual‑renew path
Send Email: “Last day to renew your ChannelBoost account”
Add Tag:
manual_renew_last_call
This is your last clear nudge:
Spell out what happens tomorrow if they don’t act (reports disappear, automations pause, etc.).
Make the renew button impossible to miss.
Again, no waits or follow‑ups here. If they don’t renew after this, let the churn stand. The 7‑day flow (plus any human outreach) is where you put the effort.
How this journey speaks to each customer, not “the list”
Under the hood, this playbook is really about using data you already have to talk to each merchant as a specific account instead of a row in a CSV.
Spreeflo’s combination of contact attributes, tags, and branching nodes makes this natural:
The Cyclic trigger and numeric
days_to_renewalattribute ensure every subscriber hits the right milestones without manual exports.The If/Else branches on
auto_renew_enabledlet you change tone and calls to action for each billing model.Tags like
billing_risk,manual_renewal_at_risk, and the various*_notifiedvariants give you slices to analyse or retarget later.
You never have to rebuild the flow. Once it’s live, it just runs. That’s leverage.
If you’re building this from scratch, it helps to outline the structure visually in the campaigns and journeys builder, then fill in email content and conditions node by node.
What to measure and how to iterate
This journey is aimed squarely at Brand Message #3: most businesses leak lifetime value because they don’t nurture engagement around critical lifecycle moments. Renewals are one of those moments.
Once it’s running, watch:
Renewal rate, segmented by auto vs manual
If manual renewals improve more than auto, your messaging is doing real work, not just being a formality.Billing‑update completion
Compare the number of accounts tagged withbilling_riskvsbilling_ok_pre_renewal. Over time, tweak the 7‑day email copy and subject line to reduce the risk pool.Manual‑renewal opt‑in to auto‑renew
If your billing system lets customers switch to auto‑renew, track aauto_renew_enabledflip after the 30‑day manual email. Even a small uptick here compounds over time.Human‑touch outcomes
For accounts that triggered internal emails, record whether the store renewed after a personal outreach. If the hit rate is high, you’re justified spending those cycles. If not, rethink thresholds so your team isn’t distracted.
Because Spreeflo charges only for marketing contacts, you can afford to keep plenty of non‑marketing attributes and historical tags around to support this analysis. You don’t have to delete context just to control costs.
Renewals are where LTV is defended, not created
New installs feel exciting. Feature launches are glamorous. But for Shopify app developers, so much of the actual profit comes from the quiet, steady act of getting already‑happy customers to stay that way year after year.
This renewal reminder journey doesn’t rely on heroics or big launches. It codifies a simple discipline:
Watch every upcoming renewal.
Talk to each customer based on how they pay you.
Create space for them to fix problems before they bite.
Pull humans in only when it’s worth it.
Once you’ve wired this into Spreeflo, it works while you sleep. That’s what founder‑led teams need: systems that guard lifetime value without constant attention.
If your Stripe dashboard has those same ugly renewal cliffs Lina saw, this is one of the highest‑leverage flows you can build next.