The Engagement-Tier Engine That Keeps Your Shopify App Out of Spam
A detailed walkthrough of a Spreeflo journey that assigns Shopify app contacts to Hot, Warm, Cold, or Unknown engagement tiers on a monthly cycle, so your highest-value merchants keep seeing launches while disengaged subscribers stop dragging down deliverability.
Industry
Niche
Pattern
Loading sequence...
CartWizard had what every Shopify app founder wants: 40,000+ merchants on their list, a $90k MRR product, and a backlog of features worth talking about.
They also had a quiet problem.
Every time they emailed the full list about a new campaign playbook, Gmail’s "Promotions" tab swallowed it. Outlook started shunting launches into Junk for merchants who had actually paid them real money. Open rates slipped from 28% to 13% in six months. Support tickets started with lines like: "I didn’t even know this feature existed."
Their email volume hadn’t changed. Their engagement had.
The root cause was simple: they treated a merchant who hadn’t opened an email in a year the same as a power user who clicked everything within minutes.
The sequence at the top of this page is the whole journey, end to end. It’s a monthly "engagement-tier rotation" that keeps your list healthy by promoting and demoting contacts automatically based on what they actually do with your emails.
For a Shopify app or e‑commerce tool, that’s the difference between "Our launches disappear into filters" and "Our best customers always see what we ship."
Let’s pull it apart node by node.
Why cold merchants drag your sender reputation down
Mailbox providers don’t care how many installs you have or how proud you are of V4 of your reporting API.
They care about whether the last few thousand messages from your domain were opened, clicked, ignored, or marked as spam.
When you send every campaign to:
Merchants who installed during BFCM 2022 and never came back,
Stores that churned three quarters ago, and
Power users who reply to every second email,
the cold majority wins. Engagement rates fall. Gmail and Outlook adjust in the only way they can: by giving your future messages a slightly worse starting point in the inbox.
For an e‑commerce app, that’s particularly painful:
You rely on episodic communication (new features, best‑practice guides, seasonal playbooks).
You can’t afford to throttle volume manually every time your list grows.
You’re a small team. Nobody has time to do manual list‑cleaning every month.
The fix isn’t "send less." It’s "send smart":
Continuously classify every contact into an engagement tier.
Use those tiers to change how often (and how hard) you market to them.
Let promotions and demotions happen on autopilot as behavior changes.
That’s exactly what this journey does.
What this engagement-tier rotation actually does
At a high level, the journey built in Spreeflo:
Wakes up on a schedule using a Cyclic trigger.
Grabs every marketing contact who’s eligible for email.
Clears out any stale engagement-tier tags.
Routes each contact through a Multi-way Split based on their recent email activity.
Applies one clear tier: Hot, Warm, Cold, or Unknown.
Writes that tier into a contact attribute and timestamps when the decision happened.
From there, your other campaigns and journeys can:
Email Hot contacts weekly with deeper content and upsell prompts.
Email Warm contacts less frequently, keeping them engaged without fatigue.
Put Cold contacts on a gentle re‑permission / win‑back cadence instead of blasting them with every announcement.
You stop punishing your best merchants for the apathy of your worst. And because tiers are recalculated automatically, nobody lives forever in "Hot" just because they clicked once.
It also reinforces two things Spreeflo cares about:
You’re capturing an extra layer of detail on every contact so you can speak to each uniquely instead of treating "merchant@example.com" as just another row.
You’re plugging the very real lifetime‑value leak that happens when deliverability quietly decays and your product updates never reach the people who would deepen their spend.
If you’re new to the visual editor, this is all built with standard journeys and routing nodes; you can see how those work in more depth in the guide on how to build a journey.
Now, let’s walk the sequence.
Step 1: A Cyclic trigger that audits your list every month
At the very top of the journey is a Cyclic trigger.
Configuration:
Repeat interval: every 1 month.
Time of day: something quiet, like 03:00 in your main timezone.
Criteria: use the embedded Segment Builder to constrain who gets processed:
Email Subscription Status is "Subscribed".
Contact attribute "Marketing Status" is "Marketing".
Why Cyclic?
Because engagement is a sliding window problem. A merchant who was "Hot" in March might ignore everything in April. You want the system to re‑evaluate them automatically without tying it to a specific event like "opened X email."
This is also where Spreeflo’s journey‑scoped re‑enrollment matters. For this trigger you want:
Re‑enrollment: ON.
That tells Spreeflo: "On every monthly tick, process this contact again, even if they’ve been through this journey before, as long as they’re not currently mid‑journey." Since this flow is short and purely tagging, nobody will be mid‑journey for more than a second anyway.
Step 2: Clear out old tiers with a single Remove Tag
Next in the sequence is a Remove Tag action.
Configuration:
Tags to remove:
Force tag trigger: OFF.
tier-hottier-warmtier-coldtier-unknown
Why remove up front?
You want the tier set on each run to be authoritative. If you wait and only change tags in some branches, you’re at risk of a merchant accidentally keeping an old "tier-hot" tag while their behavior has cooled off.
Doing one Remove Tag before the split gives you this guarantee:
After the node runs, no contact has any tier tag.
Whatever tag they get downstream is their current engagement state.
With "Force tag trigger" off, you also avoid firing any Added Tag triggers elsewhere in your account when there’s nothing to actually remove.
If you’re not familiar with tags in Spreeflo, the help doc on getting started with tags is worth a skim; we’ll lean heavily on them in this pattern.
Step 3: Multi-way Split into Hot, Warm, Cold, and Unknown
Now comes the brain of the journey: a Multi-way Split process node with four branches.
Spreeflo evaluates Multi-way branches from top to bottom and sends the contact down the first branch whose condition matches. That ordering is important.
Here’s a pragmatic configuration that works well for apps like CartWizard or ShopMetrics:
1. Branch "Hot" (evaluated first)
Condition group:
Email Activity:
Any marketing email "opened" at least 3 times in the last 30 days
OR any marketing email "clicked" at least 1 time in the last 30 days.
In the Segment Builder, that’s one AND group containing a sub‑group with OR logic between the two rules.
Why these thresholds?
3 opens in 30 days or a click is a strong signal that the merchant is paying attention.
You’re intentionally being generous: better to slightly over‑include than under‑include your true fans.
2. Branch "Warm"
Condition group:
Email Activity:
Any marketing email "opened" at least 1 time in the last 90 days.
Because Hot is above Warm, anyone super‑engaged gets caught earlier. Warm becomes "has shown at least some recent interest, but doesn’t consistently act."
3. Branch "Cold"
Condition group:
Email Activity:
Any marketing email "did not open" in the last 90 days, with
Any marketing email "sent" at least 3 times in the last 90 days.
This ensures you’re not classifying people as Cold just because you never email them. They’ve had chances; they chose not to engage.
4. Else branch: "Unknown"
Else is implicit. Anyone who doesn’t match Hot, Warm, or Cold drops here.
Who ends up here?
Brand‑new subscribers who haven’t had time to receive 3 emails.
Contacts with patchy mailing history.
Edge cases like manually added contacts you only email occasionally.
You could leave this path unnamed, but giving it "Unknown" as a label makes it clearer what’s happening when you inspect the journey later.
All of these conditions are built with the same segment builder you use for saved segments. You’re just using it inline on a process node instead of saving each tier as a separate segment.
Step 4: Apply one clean tier tag per branch
Each branch now gets its own Add Tag node.
Hot branch: Add Tag with
tier-hot.Warm branch: Add Tag with
tier-warm.Cold branch: Add Tag with
tier-cold.Unknown branch: Add Tag with
tier-unknown.
For all of them:
Force tag trigger: OFF.
Why off? Because we already removed any existing tier tags at the top of the journey. When a contact gets a new tier tag here, it is by definition a fresh tag event. There’s no need to force it. That keeps any other journeys that listen to Added Tag events honest: they’ll only fire when a merchant genuinely changes tier, not on every monthly refresh where the tier happens to stay the same.
This is where the pattern earns its keep:
At any given moment, every marketing contact has exactly one tier tag or none at all.
Those tags track real behavior over rolling windows, not stale "last engaged" values in a spreadsheet.
Step 5: Store the tier in a contact attribute
Tags are great for routing and quick filtering. Attributes are better when you want to connect behavior to analytics, reports, or other tools via API.
So, after each Add Tag, the journey uses an Update Contact Attribute action:
Attribute: a custom TEXT attribute called
engagement_tier.Update type: Update (overwrite).
New value:
"hot" on the Hot branch,
"warm" on Warm,
"cold" on Cold,
"unknown" on Unknown.
Why bother, when the tags already exist?
Three reasons:
Analytics: you can build segments like "Power users on the Pro plan whose engagement_tier is cold" and treat them differently from hobby stores that go cold.
External tools: if you call the Spreeflo API to mirror contact data into your own admin or billing system, having a single attribute is easier to consume than four mutually exclusive tags.
Future‑proofing: if you ever change the tag naming (for branding or internal reasons), your analytics and integrations don’t break; you only update the journey.
Remember that Update Contact Attribute writes a static value you choose at design time. You’re not trying to mirror a dynamic event payload here; you’re setting a simple literal like "hot" or "cold" on each contact.
Step 6: Merge and timestamp the last tier update
All four tier branches then feed into a single Merge node to respect Spreeflo’s "one incoming edge per node" rule.
From the Merge, there’s one last Update Contact Attribute action:
Attribute: a custom TIMESTAMP attribute called
engagement_tier_updated_at.Update type: Set to now.
Every time the Cyclic trigger runs, this node stamps the exact moment the system last re‑tiered the contact.
Why it’s useful:
Diagnosing surprises later: "Why is this big merchant still marked cold?" → you can see precisely when that classification was made.
Building safety valves: you can create a segment like "Cold tier AND engagement_tier_updated_at before 6 months ago" and choose to purge or archive those contacts entirely.
After this node, the journey ends for that contact until the next monthly tick.
Turning tiers into different send cadences
Everything above is about classification, not sending. It’s the engine that keeps your tiers honest.
How do you actually change cadence?
There are two clean patterns app teams use.
1. Targeted campaigns by tier
For recurring broadcasts like "weekly product tips" or "monthly changelog," you run a Campaign instead of a Journey.
In the Campaign’s audience selection, you might:
Include: Segment where
engagement_tier is hot OR warm.Exclude: anyone with
engagement_tier is cold.
Cold contacts might get only:
Big, truly important updates (security, major pricing changes).
Occasional re‑engagement campaigns specifically designed to wake them up.
Because the tier tags and attributes are kept fresh by the journey, you don’t need to remember to rebuild the audience each time you schedule a send.
2. Dedicated journeys for Cold and Warm
You can also let tiers trigger their own nurture journeys using the Join Segment or Added Tag triggers.
Example: "Cold Re‑engagement" journey
Trigger: Join Segment "Engagement: Cold" where
engagement_tier is cold.First node: Send Email with a simple "Are we still helpful to you?" subject that:
Next node: Time Delay of 30 days.
Then an If/Else:
Re‑enrollment: ON, so a merchant who warms up and later cools down can re‑enter.
Offers a concise value recap.
Lets them adjust frequency or opt out.
Build it quickly with Spreeflo’s email builder.
Condition: Email Activity on that re‑engagement email "opened at least 1 time in the last 30 days."
If yes: Add Tag "reengaged-from-cold" and maybe Add Tag "tier-warm" or just let the monthly tier rotation update them naturally.
Else: optionally Update Email Subscription Status to "Unsubscribed" for contacts who have been cold for a long time and didn’t take the final chance.
Because of the "no back‑to‑back send" rule, the Time Delay ensures you’re not peppering them with multiple emails in a row.
You can mirror this idea for Warm contacts with a lighter touch. For example, a quarterly "what you might have missed" email triggered when someone first becomes Warm.
Measuring whether it’s working
Once the journey has been running for a month or two, you can start to look at:
Engagement‑rate‑by‑tier: pull open and click rates for any campaign and break them down by
engagement_tier. You should see a clear gradient: Hot highest, Warm in the middle, Cold lowest.Inbox placement: watch for fewer "why am I not getting your emails?" tickets and more replies from people who clearly read your stuff.
Sender reputation: if you’re using Postmaster Tools or other diagnostics, your domain’s spam complaint rate and "low engagement" flags should ease off as you stop hammering the truly disengaged.
The more detailed your contact picture, the easier this analysis gets. That’s why storing the tier as both a tag and an attribute matters: you’re not just cleaning your list, you’re enriching it.
The quiet upside: more lifetime value, not just cleaner logs
It’s easy to frame engagement-tier rotation as a defensive move to keep you out of spam.
For Shopify apps and e‑commerce tools, it’s more than that.
Your Hot segment becomes a testing ground for new upsells, feature betas, and case‑study asks.
Your Warm segment is where you prevent silent churn by reminding merchants what they’re getting from you.
Your Cold segment stops being a dead weight that slowly poisons deliverability and starts being a managed pipeline: some will re‑engage, others will be let go deliberately.
You built your app so a small team could serve a lot of merchants. Your marketing deserves the same kind of leverage: a system you set up once that keeps working quietly in the background, treating every store differently based on what they actually do.
This engagement-tier journey is that system. It turns a messy, flat email list into a living map of attention — and it gives your best customers the inbox experience they deserve.