Why push-first, email-second works for app developers
This playbook shows how CartWizard and similar Shopify or SaaS apps can wire a push-first, email-second journey in Spreeflo, using behavioral triggers, wait conditions, and branching to rescue ignored notifications and drive measurable feature adoption and revenue.
Industry
Niche
Pattern
Loading sequence...
When your push goes ignored: a simple fallback that quietly prints money
CartWizard thought push was going to be their secret weapon.
They’re a four-person team behind a Shopify abandoned-cart app doing just over $100k MRR. They’d added browser notifications inside their merchant dashboard: “Your BFCM cart flows are one click away” sent as a web push to every high-volume store that hadn’t set up Black Friday campaigns.
The alert looked great. Delivery rates were fine. But the click numbers were… underwhelming. Plenty of merchants just swiped the notification away while juggling a dozen other things.
What moved the needle was a tiny change: every time that push went ignored for an hour, CartWizard automatically sent an email version of the same nudge. Cross-channel reach jumped, and so did feature adoption.
The sequence at the top of this page is the whole journey, end to end. This article walks through how it works in Spreeflo, why each node is there, and how you can adapt it for your own Shopify app or e‑commerce tool.
We’ll use CartWizard as our running example: a behavioral trigger inside their app kicks off a web push. If the merchant clicks, great. If they don’t, Spreeflo waits, checks who stayed silent, and then sends a deeper email to everyone who didn’t respond.
That’s the entire pattern. The magic is in the timing and the conditions.
For SaaS apps serving merchants, web push and email are good at different things.
Web push is fast and interruptive. It’s perfect for “tiny next steps”:
“Turn on A/B testing before Black Friday traffic ramps up.”
“You’ve just crossed $10k recovered. Want to double down with our advanced flows?”
Email is slower but richer. It’s where you explain, show screenshots, and make the business case.
The problem: most teams treat these channels separately. They either spam email and ignore push, or dabble in push without a safety net when it doesn’t get clicked.
A push-fallback-to-email journey fixes that:
Start with web push for immediacy.
Give it a small window to earn a click.
If the merchant stays quiet, follow up with an email that does the heavier lifting.
You don’t guess which channel a specific person prefers. You let their behavior in that moment decide.
To make this work, you need two things:
Detailed behavioral data per merchant.
A journey that reacts to that data in real time.
That’s exactly what Spreeflo’s campaign and journey builder plus web push and segmentation are built for.
The scenario we’re designing for
Let’s get concrete.
CartWizard has a new “Flow Experiments” feature that automatically A/B tests subject lines inside recovery flows. They only want to push it to merchants who are:
Actively recovering carts with the app.
At a high enough volume to benefit.
Not already using Flow Experiments.
Inside their app, they already track events like:
cart_recoveredflow_createdflow_experiment_enabled
Using the Spreeflo API, they add a server-side call whenever a store crosses 50 recovered carts on a single flow without experiments enabled:
Spreeflo.track('feature_eligible', { feature_name: 'flow_experiments' }, { shop_id: '...', plan: 'pro' })
That custom event is the entry point to the journey you see at the top of this page.
Now let’s go node by node.
Node 1: Custom Event trigger – catching real intent
We start with a Custom Event trigger watching for feature_eligible with a specific property:
Event name:
feature_eligibleProperty conditions:
feature_name is "flow_experiments"Re-enrollment: off (CartWizard only wants to nudge each store once for this feature)
Why this choice:
It’s purely behavioral. You’re talking to merchants at the moment they’re most likely to care: when their flows are performing and they’re ready for incremental gains.
Using event properties instead of separate events (
feature_eligible_flow_experiments) keeps your tracking tidy while still giving you precise control in the trigger.Turning re-enrollment off protects merchants from getting hit again if your app fires the event twice.
You could swap this trigger for Join Segment or Criteria Match built using the segment builder (e.g., “Recovered carts ≥ 50 AND not using experiments”). The behavior is the same: a high-intent merchant enters the journey once when they become eligible.
Node 2: Send Web Push – the quick nudge
The first action after the trigger is a Send Web Push node.
CartWizard has already followed the web push setup guide: added the Spreeflo SDK, hosted the service worker, and configured an opt-in prompt inside their dashboard. So many of their merchants are already subscribed to push from the app’s UI.
In this node they:
Choose or create a notification template with:
Title: “You’re ready for Flow Experiments”
Body: “You recovered 50+ carts on a single flow. Turn on experiments to test your subject lines in 2 clicks.”
Click URL: deep link into the app’s experiments setup screen.
Leave “Send only once” on, so the same merchant never gets this notification twice even if you later rewire the journey.
Why web push first:
It fits the ask. You’re not trying to teach a concept, you’re nudging a small configuration change.
It respects time. The merchant can act instantly from their browser without digging into email.
It captures behavior at a fine-grained level: Spreeflo records sent, delivered, clicked, and dismissed per contact.
If a merchant isn’t subscribed to push, that’s fine. This node will simply do nothing for them, and the fallback email will handle it.
Node 3: Wait Condition – give the click a fair chance
Next is a Wait Condition node that pauses the journey while you watch for a click.
Configuration:
Condition: Web Push Activity “clicked at least 1 time” for this specific template, in the last 1 hour.
Timeout: 1 hour.
In terms of web tracking and analytics, you’re essentially saying: “Hold this merchant here until one of two things happens: they click this notification, or an hour passes without a click.”
Why Wait Condition instead of a simple Time Delay:
Time Delay can’t see behavior. It would always wait an hour, even if the merchant clicked after 10 seconds.
Wait Condition releases early for merchants who engage immediately, so you can move them down a “clicked” path in near real time.
The timeout gives you a clean, configurable window for your fallback. One hour is common for immediacy plays; for lower-urgency nudges, you might pick 4 or 24 hours.
At the end of this node, every merchant has either clicked or not. The journey continues either way; the next node decides which path they follow.
Node 4: If/Else – clicked vs didn’t click
After the wait, we drop in an If/Else process node with the same condition as the Wait Condition:
Condition: Web Push Activity “clicked at least 1 time” on this template in the last 1 hour.
Then branch: “clicked.”
Else branch: “didn’t click.”
Why mirror the condition:
When a merchant clicks the push, that “clicked” activity will stay true for the full hour window.
When the timeout expires without a click, the condition will be false, so the merchant falls into the else branch.
This pairing (Wait Condition + If/Else using the same criteria) is the core trick in the pattern. It’s what lets you route based on whether the condition was met vs whether the timer simply ran out.
Node 5: Clicked branch – tag, don’t nag
On the “clicked” side, we keep things light.
Typical steps:
Add Tag:
(Optional) Send Internal Email to your team or success inbox with context on the merchant, so someone can follow up manually if you run high-touch onboarding for top accounts.
Tag name:
clicked-flow-experiments-pushForce tag trigger: off (you don’t need to fire other journeys here)
You do not send them the email version of the message. They’ve already shown intent by clicking; they’re likely on the feature setup page or in your docs.
The tag is mainly for:
Analytics: filter cohorts later to see how push-clickers convert vs fallback-email-clickers.
Suppression: excluding anyone with this tag from bulk campaigns about the same feature.
This is where Spreeflo’s philosophy shows through: you’re capturing detail on this specific merchant’s behavior, so every downstream message can speak to what they’ve already done.
Node 6: Didn’t-click branch – the email version
On the else branch, the first action is a Send Email node.
Because the merchant has either ignored or never seen the push, this email needs to do more work:
Subject: outcome-focused, not feature-focused.
“How CartWizard merchants get 18% more recovered revenue”
Body:
Lead with their situation: “You’re already recovering carts with CartWizard. You’ve crossed 50 recovered carts on Flow X.”
Show why experiments matter: quick explanation of how A/B testing subject lines lifts recovery rates.
Include a single primary CTA linked to the feature setup screen.
Inside Spreeflo’s email builder, you can fold in dynamic variables and, if you want, the AI personalization helpers from the docs to tune subject lines and copy based on plan, geography, or usage.
Message pacing is baked in here:
The Wait Condition guaranteed at least one hour between the notification and this email.
This prevents “back-to-back” channel hits that feel spammy (“push now, email 2 minutes later”).
If you want to go further, you can:
Follow this Send Email with a Time Delay of 2–3 days.
Then add a Check Email Activity node to branch on who opened or clicked the email.
On the “clicked email” branch, add a tag like
clicked-flow-experiments-email.On the “no engagement” branch, simply exit or move them to a lower-intensity nurture.
Just remember to keep at least a 1-hour Time Delay between any two Send Email nodes on the same path.
Making the journey aware of web push subscription
One useful adaptation for Shopify apps: gate the push step based on whether a merchant is actually subscribed to web push.
You can do this in a couple of ways:
Move an If/Else process node right after the trigger:
Condition: Web Push Activity “sent at least 1 time over all time.”
Then: treat as “push-capable.”
Else: skip straight to the email version (no Send Web Push node).
Or build a saved segment like “Dashboard visitors with web push subscription” using a combination of Page Visited and Web Push Activity conditions, and use a Join Segment trigger for that audience.
Either way, you’re still running the same push-fallback pattern. You’re just being smart about who even sees the push.
What to measure from this sequence
The pattern is simple, but the metrics unlock real insight about your merchants.
At minimum, track:
Cross-channel reach
Fallback conversion rate
Feature activation and downstream revenue
What percentage of eligible merchants engaged through either the click on the web push or the click on the fallback email?
Numerator: unique merchants who clicked the push OR clicked the email.
Denominator: total merchants who triggered the journey.
Among merchants who did not click the push, what percentage clicked the email?
This tells you how much value the email is adding on top of push. If this number is low, your email may be weak or redundant. If it’s high, you’ve probably been underusing email for this kind of feature nudge.
Of those who engaged in either channel, how many actually enabled the feature, and how did their recovered revenue change afterwards?
You can track feature_used and revenue-related events via the Spreeflo API and match them back to tags like clicked-flow-experiments-push or clicked-flow-experiments-email.
Because Spreeflo keeps all this activity on one contact record, you’re building a granular behavior trail for each merchant: what they were eligible for, which channels reached them, what they actually did next.
Adapting this pattern to other high-impact moments
The example above is feature upsell, but the same push-fallback-to-email structure works across your app:
Trial nearing end\nTrigger: Criteria Match on “plan is trial AND days since signup = 10.”\nPush: “Your trial ends in 2 days.”\nFallback email: walkthrough of what they’ll lose, with case studies and pricing.
Recovering at-risk stores\nTrigger: Custom event
usage_droppedwhen daily active users fall below a threshold.\nPush: “Your automations haven’t run this week. Want to see what’s paused?”\nEmail: a personalized report of missed opportunities and steps to re-activate.“We fixed the problem you cared about”\nTrigger: Added Tag
requested-feature-Xset by support.\nPush: “That feature you asked for is live.”\nEmail: changelog entry and implementation guide.
Once you understand the building blocks:
Behavioral trigger that’s specific and meaningful.
Push for speed.
Wait Condition watching for a click with a sane timeout.
If/Else to branch based on engagement.
Email to everyone who stayed silent.
…you can redeploy this across dozens of journeys without starting from scratch every time.
Why this pattern is tailor-made for small app teams
Founder-led app businesses don’t have lifecycle teams and channel specialists. You have a handful of people and an install base that grows faster than your headcount.
This is where marketing automation earns its retainer line:
You wire up a few key events from your app into Spreeflo.
You define exactly who should hear about which feature, in which order of channels.
You let the system watch behavior and do the follow-up for you.
Most Shopify apps already collect plenty of usage data. The gap is turning that into conversations that feel specific to each store:
“You crossed 50 recovered carts on this flow.”
“You haven’t run a campaign in 14 days.”
“You asked us about this feature three months ago, and it’s finally ready.”
A push-fallback-to-email journey is a compact way to put that data to work. It respects merchants’ attention, it learns from their behavior in the moment, and it nudges them toward actions that grow both their revenue and yours.
The sequence at the top of this page is small on purpose. You can build it quickly, test it on one feature, and then decide where else this pattern belongs. Once it’s running, it doesn’t ask for your time again, but it keeps speaking to each customer based on what they actually do.