Back to Playbooks

Send It Fast, Then Make It Stick: Coordinating Web Push and Email for Shopify Apps

Free

Playbook for Shopify and e‑commerce apps to route time-sensitive alerts through a push-first, email-second journey in Spreeflo, tagging behaviour along the way so each merchant’s profile and channel preferences become richer for future automation.

Industry

Niche

Pattern

Loading sequence...

CartWizard’s monitoring system spots something ugly at 3:12pm.

A chunk of their Shopify merchants have recovery flows paused after a theme update. Every minute the app is offline is lost revenue for those stores, and a few hours of downtime will show up as churn risk in CartWizard’s own metrics.

They can’t wait for merchants to “eventually check their email.” They need an interruption now. Browser push is perfect for that. But not every merchant has allowed notifications, and some will be away from their laptop until tonight.

So CartWizard does both, without spamming anyone: a real-time web push first, then a tightly scoped fallback email only for the people who didn’t engage with the notification.

The sequence at the top of this page is the whole journey, end to end.

In this article, we’ll walk through that journey in Spreeflo: why each node exists, how it’s configured, and how you can adapt it for your own Shopify or e‑commerce app.

Our example company is CartWizard: a four‑person team doing ~$90k MRR with a cart recovery app on the Shopify App Store. Their stack looks like a lot of e‑commerce apps: Stripe for billing, Shopify for install data, a basic email tool they’ve outgrown, and a tangle of custom scripts to send “urgent” alerts. You probably recognise some of that.

Why push-first, email-second is worth the setup

For SaaS apps that sell to merchants, a lot of your highest-value communication is time-sensitive:

  • “Your payment method just failed.”

  • “We’ve detected a sudden drop in conversion.”

  • “BFCM traffic is spiking and one of your flows is paused.”

  • “Webinar starts in 30 minutes.”

Web push is perfect for these moments. It’s fast, it surfaces outside the inbox, and it feels closer to “real-time app alert” than “marketing.”

Email is the safety net. Almost every customer has an email on file, and even if they don’t see it instantly, they will see it.

The mistake most teams make is one of two extremes:

  • Blast only email, and accept that many merchants will see it too late.

  • Blast both channels at once, so the same person gets a browser ping and an email seconds apart, which feels noisy and lazy.

The flow in this playbook avoids both problems. It:

  1. Listens for a real alert coming from your app.

  2. Sends a web push notification immediately.

  3. Waits a few hours.

  4. Checks who actually interacted with that push.

  5. Tags the people who clicked.

  6. Sends a single fallback email only to those who didn’t click and are actually subscribed.

You wire it once in the campaigns and journeys builder, and it quietly coordinates push + email every time your app emits the right signal.

Let’s go node by node.

Step 1: Trigger the alert from real product behavior

Node: Custom Event trigger (time_sensitive_alert), re-enrollment ON

This is a behavioural journey. The entry point isn’t a list you pulled from a segment; it’s your app saying “this merchant needs to hear from us now.”

In Spreeflo, that means a Custom Event trigger. On your backend (or via the JS SDK in your app UI), you fire something like time_sensitive_alert whenever an urgent condition is met.

The trigger is configured roughly as:

  • Event name: time_sensitive_alert

  • Property conditions: optional (you might later use these to distinguish “severity” or “alert type”)

  • Re-enrollment: ON

Re-enrollment matters. The same store might hit this alert several times over its lifetime (multiple payment failures, multiple broken flows). With re-enrollment on, they can run through this journey every time the event fires, as long as they’re not already mid-journey.

You send the event into Spreeflo using the Spreeflo API or the web SDK (Spreeflo.track('time_sensitive_alert', {...})). Either way, once this trigger sees it, the merchant drops straight onto the next node.

Why not use a Criteria Match trigger instead? You could, by building a segment like “Payment failed at least 1 time in last 1 day.” But Custom Event keeps the logic in your app, where you already know exactly when something is urgent.

Step 2: Fire the web push notification immediately

Node: Send Web Push (“Time-sensitive alert”)

The first action is a Send Web Push node. This is your real-time alert.

You pick or create a web push template that might look like:

  • Title: “We just paused your CartWizard flows”

  • Body: “Your store ‘Acme Apparel’ stopped recovering carts at 3:12pm. Fix this now to avoid lost revenue.”

  • Click URL: deep link into the exact settings page inside your app.

Behind the scenes, this relies on having web push enabled for your site (service worker hosted, opt‑in prompt configured, etc.). The setup is a one‑time task guided by the web push help guide. After that, any contact who’s subscribed can receive browser notifications, even if they’re not currently on your site.

Why push first?

  • It reaches merchants who are actively working in a browser right now.

  • It feels like an app alert, not marketing.

  • It creates a clean behavioural signal: clicked vs not clicked.

That last point is what powers the rest of the flow.

Step 3: Give the push time to work

Node: Time Delay (4 hours)

Next, we insert a Time Delay node:

  • Delay: 4 hours (you can tune this per use case)

This pause does two things:

  1. It gives the notification time to be delivered, displayed, and acted on.

  2. It prevents the fallback email from feeling like it arrived at the same moment as the push.

Could you make this 1 hour? For hyper‑urgent “site is down” alerts, maybe. For most commercial alerts (“payment failed”, “flows paused”), 3–6 hours is a good starting point. You want the email to feel like a backup, not a duplicate.

Without this delay, you’d violate basic message pacing and you’d lose the behavioural separation that makes the Check Web Push Activity node valuable.

Step 4: Check who engaged with the push

Node: Check Web Push Activity (branch: Clicked vs everyone else)

After the delay, we drop into a Check Web Push Activity process node.

Configuration:

  • Web push template: the exact template you used in Step 2.

  • Activities to branch on: Clicked

  • Else branch: everyone who did anything else (delivered but not clicked, not delivered, not sent)

Effectively, this creates two paths:

  • “Clicked the notification”

  • “Did not click (or never saw it)”

Why only branch on Clicked?

Because for this pattern, that’s the action that matters. If they clicked, they saw the alert and at least opened your app. You probably don’t need to also email them about the same thing.

The else branch intentionally groups together a bunch of less‑engaged states:

  • Notifications that were delivered but ignored.

  • Notifications that could not be delivered (no subscription, permission denied).

  • Any “we tried to send but failed” scenarios.

All of those justify a backup email.

Step 5a: For clickers, tag and stop

Node: Add Tag (“alert-via-push-clicked”)

On the “Clicked” branch, we keep it simple: an Add Tag action, then the path ends.

Example tag: alert-via-push-clicked.

Why bother tagging?

  1. Two reasons that matter a lot for a small SaaS team:

  2. You’re building up a picture of who responds well to real-time notifications. That can influence future targeting, pricing tiers, even product decisions about which merchants to invite into beta programs.

  3. It gives you an easy way to analyse channel performance later. Filter by this tag vs contacts who never click push and you can compare revenue or churn.

This is where Brand Message 1 comes in: capture detail on every customer so you can speak to each uniquely. With one extra node, you’ve created a durable data point on the contact record, not just a one‑off click.

You could also send an internal email on this branch for especially high‑value alerts (“Enterprise customer just clicked critical downtime alert”), but for most Shopify apps, tagging is enough.

The “no click” branch needs a bit more care. Some of these merchants are ideal candidates for a fallback email. Some are not allowed to get marketing email at all.

So we add two nodes.

5b(i): Check email subscription status

Node: If/Else (Email Subscription Status is Subscribed)

First is an If/Else node with a simple condition built in Spreeflo’s segment builder:

  • Condition: Email subscription status is Subscribed

This splits the path:

  • Yes: we’re allowed to send marketing email. Continue to the fallback email node.

  • Else: we’re not. Do not email. Optionally tag for reporting.

On the Else branch, you might add a tag like alert-missed-no-email. Later, you can pull a list of these and consider other channels (support outreach, in‑app banners, etc.).

This step is what keeps the pattern respectful. You only fall back to email when the contact has actually given consent for marketing messages.

5b(ii): Send the fallback email

Node: Send Email (“Time-sensitive alert – backup email”)

On the “Subscribed” side of the If/Else, we finally send the Send Email action.

This message is the safety net for everyone who didn’t engage with push but can receive email. It should:

  • Repeat the core alert, clearly.

  • Carry a subject that signals urgency without sounding like clickbait (“CartWizard flows paused for Acme Apparel”).

  • Deep link to the same place the notification did.

Inside Spreeflo’s email builder, you can draw on contact attributes (store name, plan, current MRR range) and AI variables to personalise the subject and body so it reads like it was written for that specific merchant, not a blast.

The “Send only once” toggle on this node should stay ON. Even if your app mistakenly fires duplicate time_sensitive_alert events, the same merchant won’t receive this exact email multiple times from the same journey.

At this point, both branches end. Either they clicked the push and got tagged, or they didn’t and, if allowed, got a single backup email.

How this pattern builds a richer profile on every merchant

Even though the flow is simple, it quietly enriches your data in ways most tools ignore.

You now know, per contact:

  • Do they subscribe to web push at all? (inferred by whether push ever shows as “sent” or “delivered” in analytics)

  • Do they tend to click time‑sensitive notifications?

  • Do they prefer email as a catch‑up channel?

  • Are they actually subscribed to email marketing, or relying on transactional communications only?

Combined with the rest of your tracking — page views, custom events like feature_used, subscription_upgraded, total visits from the web tracking and analytics SDK — you have a multi-dimensional view of each store:

  • Behaviour in your app

  • Response to alerts

  • Channel preferences

That’s the raw material for smarter segments:

  • “High‑value stores who always click push” → invite them into more real-time workflows or mobile notifications when you ship them.

  • “At‑risk stores who ignore both push and email” → treat them as a churn‑risk segment, maybe escalate to support intervention.

  • “Stores with no marketing consent but frequent visits” → prioritise in‑app messaging and transactional nudges.

This is how you stop treating “all merchants” as one blob and start talking to each one based on how they actually behave.

Adapting the same journey to your Shopify app

The skeleton of this journey stays the same across a lot of use cases. You mainly swap out the trigger event and the content.

Some patterns that work well:

  1. Billing and subscription alerts

    - Trigger: payment_failed, subscription_about_to_cancel.
    - Push: “Your payment for CartWizard failed. Update card to keep flows running.”
    - Fallback email: detailed explanation, screenshots of where to update billing.

  2. Usage spikes and limits

    - Trigger: usage_quota_80_percent, with properties like plan and current_usage.
    - Push: “Your analytics events are at 80% of plan. Upgrade before BFCM to avoid throttling.”
    - Email: a clearer walkthrough of options with plan comparison.

  3. Feature adoption nudges tied to calendar events

    - Trigger: bfcf_feature_missing a week before Black Friday for stores that haven’t turned on unique BFCM features.
    - Push: “Turn on multi-step recovery before Black Friday starts.”
    - Email: case study style overview of how much uplift they could see.

  4. Live events and webinars

    - Trigger: webinar_reminder an hour before go‑live.
    - Push: “CartWizard live training starts in 60 minutes.”
    - Email: “Join us live in 60 minutes” with calendar links and agenda.

In all of these, you’re doing the same thing: real-time nudge via push, respectful backup via email where allowed, and tagging along the way so you can tell who responds to what.

Why this earns a permanent spot in your automation library

For a small e‑commerce app team, the temptation is to focus all your automation effort on onboarding and upgrade flows. Those are important. But time‑sensitive alerts are where a lot of hidden value lives:

  • They prevent avoidable churn (a broken flow or failed payment that lingers too long).

  • They generate high‑intent sessions (merchants who click alerts are usually ready to take action).

  • They reveal channel preferences you can use everywhere else.

The cross‑channel pattern in the sequence at the top of this page is one of those flows you set up once and keep forever. It takes advantage of everything Spreeflo is built for: listening to granular product events, coordinating email and push from one place, and building a richer profile on every contact with tags and attributes.

Most Shopify apps already send some version of these alerts as ad‑hoc emails or “someone manually pings the customer.” Turning them into a journey means you stop relying on memory and Slack threads, and start relying on a system.

And once you’ve seen what happens when a single Custom Event can trigger the right message, in the right channel, at the right time, it becomes hard to go back to one‑channel bursts.

You’ve already done the hard part: you built an app merchants depend on. This pattern is how you match that product quality with communication that’s just as smart — treating every merchant as a detailed record you can act on, not a line in a generic mailing list.