Back to Playbooks

Stop Blanket Upsells: Build a Next‑Best‑Offer Engine for Your Shopify App

Free

This playbook shows Shopify app teams how to build a next‑best‑offer journey in Spreeflo that uses purchase and usage data to target upsell emails, increase add‑on attachment rates, and drive predictable expansion revenue without adding headcount.

Industry

Niche

Pattern

Loading sequence...

CartWizard had a “good problem.”

Their Shopify app recovered abandoned carts for 2,000+ merchants at $49/month. Installs were steady. Churn was acceptable. But expansion revenue? Flat.

Every merchant, from side-hustle boutiques to eight‑figure brands, got the same post‑purchase upsell email: “Upgrade to Pro for more revenue.”

Click rates tanked. Attachment rate on add‑ons stayed stuck under 5%. Worse, the bigger stores that should have been buying more from CartWizard were ignoring them entirely.

The team knew the answer wasn’t “send more emails.” It was “send different emails to different customers based on what they’ve actually done.”

The sequence at the top of this page is the whole journey, end to end. It’s a next‑best‑offer engine built in Spreeflo that reacts to your customers’ purchase and usage history, then recommends the specific next thing they’re likely to buy: an add‑on, a higher tier, or a power‑feature bundle.

In this playbook, we’ll walk through that journey node by node, and show how a small Shopify app team can turn it into predictable AOV lift and expansion revenue without adding headcount.

The moment your upsell emails start hitting a wall

If you’ve been live in the Shopify App Store for a while, you’ve probably seen the pattern:

  • Generic “Upgrade to Pro” nurture that works for a while, then stalls.

  • Feature launches sent as one‑size‑fits‑all announcements.

  • Occasional “50% off annual” blast when MRR feels flat.

Everything goes to everyone who’s “Active” and “Subscribed.”

This is exactly where most SaaS for e‑commerce leaks lifetime value. The installs are there. The logos are there. But there’s no system translating purchase and usage data into targeted, timely offers.

Two things tend to be true in this stage:

  1. You already capture rich data in your app (plan, GMV, features used).

  2. Your marketing tool knows almost none of it.

The journey you see above is what happens when those two worlds meet. It uses Spreeflo’s event tracking plus the segment builder to capture detail on every store, then uses that detail to speak to each merchant uniquely.

Next-best-offer for apps, not just products

“Next‑best‑offer” is usually explained with ecommerce products:

  • Bought a cleanser? Offer moisturizer.

  • Bought a phone? Offer a case.

For a Shopify app or headless stack, your “products” are different:

  • Core subscription tiers (Starter, Pro, Advanced).

  • Add‑ons (analytics, priority support, additional stores).

  • Usage‑based upgrades (higher order volume brackets, more seats).

  • Adjacent modules (reviews, email flows, UGC widgets, etc.).

A good next‑best‑offer system answers one question:

“Given what this merchant has already bought and used, what’s the single most logical next step that increases their value and my revenue?”

That means:

  • Power users of your abandoned cart flows might be ready for browse‑abandon flows.

  • High‑GMV stores on mid‑tier pricing might be under‑monetized.

  • Merchants hammering your reporting feature might be primed for an analytics add‑on.

Blanket cross‑sell ignores this. Next‑best‑offer automation bakes it into every email.

Let’s map how to do that in Spreeflo.

Step 1: Capture the data that makes “next best” possible

Before touching the journey, you need reliable signals coming into Spreeflo.

For most Shopify apps, that means:

  • A purchase or subscription_updated event from your billing system.

  • Usage events like feature_used, order_synced, report_generated.

  • A few key contact attributes for each merchant: current plan, monthly GMV bucket, vertical, store size.

You send these from your backend or app server using the Spreeflo API or the JavaScript SDK:

  • Each merchant is a contact.

  • You identify them with their email and attributes (plan, GMV bucket, etc.).

  • You track events for purchases and feature usage.

Those attributes and events become first‑class filters inside Spreeflo’s segment builder and inside triggers. That’s what lets the journey decide which offer is truly “next best” for this merchant instead of guessing.

Once that’s wired, you’re ready to build a journey.

Step 2: Map the journey in Spreeflo node by node

Here’s how the sequence at the top of the page is structured, from left to right.

Trigger: Custom Event (purchase) with re‑enrollment on

We start with a Custom Event trigger listening for your purchase event:

  • Event name: something like subscription_purchased or addon_purchased.

  • Property conditions: filtered to the purchases where a cross‑sell actually makes sense (e.g. exclude refunds, trials, or one‑off support charges).

  • Re-enrollment: set to on.

Why re‑enrollment on? Because you want this journey to run every time a merchant makes a qualifying purchase, not just the first time they ever buy from you. Spreeflo’s mid‑journey lock keeps them from being in two copies at once, so they’ll re‑enter only after they exit the previous run.

If you also want to catch existing customers who’ve never made that purchase, you can add a second trigger using Criteria Match:

  • Criteria: plan is Pro, has not purchased analytics add‑on, email subscription status is Subscribed.

  • Re-enrollment: can stay off, because we’ll tag these contacts once pitched so the criteria can never be true twice.

Each trigger anchors its own path in the same journey. That’s fine — Spreeflo happily runs multiple entry points in parallel.

First delay: don’t upsell on the receipt

The next node is a Time Delay:

  • Value: 1.

  • Unit: Day(s).

You probably already send a transactional receipt with your billing system or via Spreeflo’s transactional email. This delay keeps the marketing cross‑sell from landing on top of the receipt.

It also gives the merchant a day to feel the win from their purchase before you suggest the next one.

Filter: only market to subscribers

After the delay, we gate on consent with an If/Else process node:

  • Condition: Email Subscription Status is “Subscribed”.

Yes‑branch: contacts who can receive marketing email.\nElse‑branch: everyone else flows to the end of the journey or a simple Add Tag (“crosssell_suppressed”) so you can report on how many are excluded.

Multi-way Split: choose the right cohort and offer

Now the heart of the system: a Multi-way Split node that turns raw customer data into concrete offers.

Each branch is a named condition built with the segment builder. For CartWizard, you might define:

  • Branch “Starter stores ready for more”:\n- Plan attribute is Starter.\n- Total recovered revenue > $1,000 in the last 30 days.\n- Has not purchased the “Advanced Flows” add‑on.

  • Branch “Pro power users missing analytics”:\n- Plan attribute is Pro.\n- Custom event report_generated triggered at least 5 times in the last 14 days.\n- Has not purchased the analytics add‑on.

  • Branch “Enterprise candidates on mid‑tier”:\n- Plan attribute is Pro.\n- Custom attribute gmv_bucket is “$250k+”.\n- Tag is not “enterprise_customer”.

The Else branch catches everyone who doesn’t match any of these cohorts. You can either send them a soft, generic upgrade suggestion later or exit them from the journey.

This is where the brand belief “capture detail on every customer so you can speak to each uniquely” becomes operational. Each branch literally encodes what “next best” means for that cohort.

Branch example: Starter stores → Advanced Flows add‑on

Let’s walk through one branch fully; the others follow the same pattern with different conditions and content.

  1. Time Delay — 1 day\nEven inside a branch, we avoid back‑to‑back selling. This extra day means the cross‑sell email doesn’t land immediately after the cohort decision, and it also lines up nicely with “you’ve had a couple days to see value, here’s how to multiply it.”

  2. Send Email — cross‑sell Advanced Flows\n- Template: “Advanced Flows for stores like yours.”\n- From: your usual marketing identity.\n- “Send only once”: on.\n\nThis is where you speak directly to the cohort:\n\n- Reference their recovered revenue.\n- Highlight how Advanced Flows unlock browse‑abandon and winback.\n- Include a simple “Enable in one click” CTA.\n\nYou build this with Spreeflo’s email builder, and you can pull in AI‑generated copy that adapts to each merchant’s vertical or size.\n\nIf you want to A/B test subject lines or framing, insert a Random Split before this Send Email:\n\n- Percentage weight: 0.5 (50% to each path).\n- Each path has its own Send Email with a different subject or hero.\n\nBoth variants still respect the same pacing, and you can read performance later.

  3. Wait Condition — give the offer time to work\n- Condition: Custom event addon_purchased with property addon_name is “Advanced Flows”, at least 1 time in the last 7 days.\n- Timeout: 7 days (unit: Day(s)).\n\nThis node pauses the journey until either:\n\n- The merchant buys the add‑on, or\n- A week passes with no purchase.\n\nAs soon as either happens, the contact moves forward.

  4. If/Else — did they buy?\nWe reuse the same condition as the Wait Condition:\n\n- Yes branch: they purchased Advanced Flows in the last 7 days.\n- Else branch: they didn’t.\n\nThis pairing is intentional. The Wait Condition ensures we only evaluate this fork when there’s something to decide; the If/Else makes the decision explicit.

  5. Yes branch: reinforce the win, prep for the next next‑best‑offer\n\na. Add Tag — “addon_advanced_flows_customer”\nThis gives you a clean way to exclude them from future “buy this add‑on” pitches.\n\nb. Update Contact Attributelast_crosssell_success_at\n- Attribute: a Timestamp custom attribute.\n- Update type: Set to now.\n\nThis helps you report on how often cross‑sells convert and prevents you from stacking big asks too close together.\n\nFrom here, the branch typically flows to a Merge node that recombines all “success” paths from other cohorts before exiting the journey.

  6. Else branch: gentle reminder, then exit\n\na. Time Delay — 3 days\nWe still respect pacing. Three extra days keeps us far away from the first pitch.\n\nb. Send Email — alternate angle\nThis follow‑up email might:\n\n- Show a short case study from a similar store.\n- Emphasize ROI (“Most stores recoup this add‑on in 5 days”).\n- Offer a small bonus (extended trial, onboarding help).\n\nAgain, “Send only once” stays on.\n\nc. Add Tag — “advanced_flows_offered”\nThat tag becomes part of future Criteria Match triggers so you don’t keep nagging the same owners with the same offer.\n\nThen this path also flows into a Merge node and exits.

Each cohort branch uses the same skeleton with different conditions, emails, and add‑on names.

Step 3: Design cohorts that actually predict the next purchase

The journey pattern is reusable, but the cohorts are where your results live.

Good next‑best‑offer cohorts usually combine three dimensions:

  1. What they’ve already bought\n- Current plan.\n- Add‑ons enabled.\n- Billing cycle (monthly vs annual).

  2. How they’re using the product\n- Feature usage events (feature_used).\n- Volume indicators (orders processed, emails sent).\n- Engagement (logins, reports run).

  3. What they haven’t done yet\n- Custom events that have not triggered.\n- Tags that are missing (“has not purchased analytics add‑on”).\n- Segments they’re not in (“not member of segment Enterprise customers”).

Spreeflo’s web tracking and analytics can also feed in page‑level intent: repeated visits to your pricing page for a higher plan, or to a feature‑specific landing page, are classic signals.

Use the segment builder to express this logic cleanly:

  • Group rules with AND/OR.

  • Nest groups so you can say things like:

“Plan is Pro AND (visited /pricing/advanced in the last 7 days OR opened the ‘New Advanced Plan’ email).”

Those saved segments are reusable far beyond this one journey. They become your building blocks for launch campaigns, re‑engagement, and reporting.

Step 4: Tune cadence and measure lift

You’re building this to move three numbers:

  • Average order value (AOV) per customer.

  • Attachment rate on add‑ons or higher tiers.

  • Overall expansion revenue.

A few practical tips while you tune:

  • Start with conservative cadence\nOne cross‑sell sequence per purchase, with 1–2 emails spaced days apart, is plenty. You can always add more branches later.

  • Use tags and attributes for reporting\n- Tag when an offer was shown (“advanced_flows_offered”).\n- Tag when it was bought (“addon_advanced_flows_customer”).\n- Store timestamps for both.\n\nThat lets you quantify, per cohort, “attach rate when we showed this offer” versus “baseline attach.”

  • Use Random Split sparingly, but intentionally\nGreat use cases: subject lines, framing (ROI vs feature), social proof variants. Keep the underlying offer and cadence the same so you can isolate the effect.

  • Watch unsubscribe and complaint rates\nIf those spike for a specific branch, your “next best” might feel more like “hard sell.” Adjust copy, delay, or even the offer itself.

Because this journey runs every time a qualifying event fires, you don’t need a huge win on day one. A small, measured AOV uplift that repeats quietly for months is the goal.

Why this kind of automation compounds for founder-led teams

For teams like CartWizard or ShopMetrics, the constraint isn’t ideas. It’s time.

You already know that:

  • Trial nurture needs love.

  • Onboarding needs cleanup.

  • Expansion offers are leaving money on the table.

Building a next‑best‑offer journey like the one above is the classic “set it up once and let it compound” project. You invest a focused afternoon wiring up events, defining two or three meaningful cohorts, and writing a handful of emails. Then:

  • Every new purchase routes through the logic automatically.

  • Every merchant sees an offer that makes sense given what they’ve done.

  • Every accepted offer turns into higher AOV and richer customer data for the next round.

That’s the core of how founder‑led businesses win with automation: capture detail on every customer so you can speak to each one uniquely, and stop leaking lifetime value by ignoring the moments when they’re most ready to buy more.

When you’re ready, use the sequence at the top of this page as your template. Plug in your own events, attributes, and offers, and let your app start making smarter suggestions than “Upgrade to Pro” ever could.