Let Merchants Choose Their Own Adventure: A Preference-Center Journey That Actually Routes Traffic
Walk through a complete Spreeflo journey that turns a Shopify app’s preference center into real routing logic, updating contact attributes and tags, reshaping onboarding and campaigns in near real time, and lifting engagement while protecting “billing only” merchants.
Industry
Niche
Pattern
Loading sequence...
CartWizard had a classic Shopify app problem.
They were doing “the right things”: welcome series, feature updates, best-practice playbooks, occasional promo pushes. All through a single broadcast list in their email tool.
Then high-value merchants started replying with some version of: “I only want critical updates and billing notices. Please stop the rest.”
The team added a basic in-app preference center. But under the hood it was just toggling booleans in their database. Their email tool still had one marketing list. Once a week, someone exported CSVs, filtered by columns like billing_only = true, and tried not to mess it up.
That manual layer is exactly where most teams leak trust and engagement. A merchant updates “billing only” on Monday, and still gets the Tuesday promo blast. They unsubscribe. Or worse, they churn.
The sequence at the top of this page is the whole journey, end to end, that fixes this: a preference-center-driven path selection journey that reroutes each contact’s marketing path within hours of any change.
In this article, we’ll walk through how a Shopify app like CartWizard wires their preference center into Spreeflo so that:
Every preference change fires a Custom Event.
The journey reacts within an hour.
Other automations and campaigns immediately respect the new intent.
And because you’re running a lean SaaS team, you build this once and let it run. No more weekly CSV surgery.
Why preference centers matter more for Shopify apps
If you sell a Shopify app, your audience is not generic “subscribers.” They’re operators running six or seven-figure stores, often on thin margins. Their inbox is full of:
Shopify announcements
Theme, plugin, and app updates
Vendor pitches
If your onboarding and marketing streams ignore their preferences, they do not patiently wait for you to get better. They mute, filter, or uninstall.
A preference center is your promise that you’ll only send what’s relevant. But that promise only holds if your marketing automation respects it quickly and consistently.
That’s the job of this journey:
Treat every preference as first-class customer data.
Route each contact into the right stream based on those preferences.
Keep that routing up to date whenever they change their mind.
Spreeflo gives you the pieces to do this properly: Custom Event triggers, the segment builder, branching nodes like Multi-way Split, and actions like Update Email Subscription Status and Add Tag. The flow you see in the sequence at the top of this page is one concrete way to assemble them.
Step 1: Turn preferences into structured contact data
Before you even touch the journey canvas, decide how you’ll store preferences on the contact.
For a typical e-commerce app, a clean pattern is:
A TEXT attribute
email_pref_modewith values likebilling_only,low_touch,standard.A TEXT attribute
email_frequency(weekly,monthly,never_marketing).Topic-level tags such as
topic-product-updates,topic-best-practices,topic-partner-offers.
Your preference center UI (inside the app or on a standalone page) should do two things whenever a user hits “Save”:
Fire
Spreeflo.track('email_preferences_updated', { ... })so the event can trigger journeys.Call
Spreeflo.identify(email, { email_pref_mode: 'billing_only', ... })(or the equivalent via the Spreeflo API) to update those attributes and tags on the contact record.
That second step is important. The Update Contact Attribute node in Spreeflo cannot copy values from event payloads at runtime. It only writes static literals you set during design. So the system of record for “what did they choose?” must be your app or backend pushing attributes into Spreeflo, not the journey itself trying to infer it.
Once that’s in place, every contact has a durable, queryable picture of their preferences. Now the journey can react to it.
Step 2: Listen for changes with a Custom Event trigger
At the far left of the sequence is a Custom Event trigger:
Event name:
email_preferences_updatedRe-enrollment: enabled (
isReEnrollment=true)
You don’t filter by properties here. Any time a merchant changes their mind, they should re-enter the journey, even if they did it last week. That’s the whole point: the journey is the enforcement layer for “what they want right now.”
Spreeflo’s journey-level re-enrollment model means:
If re-enrollment is on for this trigger, the contact can go through the journey again after they’ve exited it.
While they’re mid-journey, duplicate enrollments are blocked so they don’t get interleaved actions.
That’s fine here because this journey is intentionally short. We want it to fire, make the necessary adjustments, and end. If a merchant toggles preferences twice in one afternoon, the most recent change will trigger the next pass through the journey as soon as they’ve exited the prior one.
At this point, every change is flowing into the journey in real time. Now we need to avoid overreacting to every click.
Step 3: Add a short Time Delay to absorb “flailing”
Immediately after the trigger, the sequence uses a Time Delay:
Duration: 1 hour
Unit: Hour(s)
Two reasons:
Humans flail. They land on the preference screen, tick a few boxes, untick others, change their mind. A one-hour buffer lets that micro-session settle before you reshape their entire messaging experience.
You still keep the promise of “within hours.” The minimum delay unit in Spreeflo is one hour, and for preferences, that’s a solid default.
If you know your customers rarely tweak settings more than once, you can shorten to the minimum. If you see a lot of back-and-forth during onboarding, bump to a few hours. Either way, this node ensures you don’t fire a cascade of Add Tag / Remove Tag / Update Email Subscription Status actions for every intermediate state.
Step 4: Branch on preference mode with a Multi-way Split
Next, the journey hits a Multi-way Split process node, which is where the real routing happens.
Each branch condition is defined with the segment builder, but instead of creating saved segments, you embed the criteria right in the node.
A typical setup for a Shopify app might be:
Branch
billing_only
- Condition: Contact Attributeemail_pref_modeisbilling_only.Branch
low_touch
- Condition: Contact Attributeemail_pref_modeislow_touch.Branch
standard
- Condition: Contact Attributeemail_pref_modeisstandard.Else branch
- No condition. Catches anyone whose preferences are missing or unexpected.
Order matters in a Multi-way Split. Branches are evaluated top to bottom, so put the most specific conditions first. In this example, the three explicit modes are mutually exclusive, so any order is fine, but in more complex setups (for example, modes combined with plan type) you’ll want to pay attention.
Why Multi-way Split instead of a chain of If/Else nodes? Because preference modes are exactly the kind of thing that tends to grow over time. Maybe you add product_updates_only or partner_offers_only later. A Multi-way Split keeps that logic in one place instead of scattering it.
From here, each branch implements a different policy.
Step 5: Enforce “billing only” properly
When a merchant asks for “billing only,” they’re asking you to stop marketing to them, not to get a slightly different newsletter.
On the billing_only branch, the journey typically does three things:
Use Update Email Subscription Status
- Status: Email unsubscribedNormalize tags
- Remove Tag: any marketing-topic tags such astopic-product-updates,topic-best-practices.
- Add Tag:pref-billing-only.Do not send a marketing confirmation email
For this branch, the contact has literally asked you to reduce noise. You can show a confirmation message in-app, but resist the urge to send “You’re unsubscribed” by email. The Update Email Subscription Status node already ensures they’re out.
After these branch-specific actions, the path connects into a Merge node that recombines all the branches, which we’ll come back to in Step 7.
Step 6: Tune “low touch” and “standard” streams
For merchants who still want marketing, just less of it, you use the other branches to tune their future path.
Low-touch branch
Here’s a common pattern for a low_touch branch:
Update Contact Attribute
- Attribute:email_frequency
- Update type: Update
- Value:monthlyAdd Tag
- Tags:pref-low-touch
- Optionally remove a previouspref-standardtag if you use one.Send Email
- A single, clear confirmation: “We’ll only email you our best monthly highlights.”
- The Send Email node’s “send only once” toggle is a judgment call. If you think merchants will bounce between modes occasionally, leaving it on prevents duplicate confirmations. If you prefer them to get a fresh summary every time they come back frombilling_only, turn it off.
That confirmation email can be built quickly with Spreeflo’s email builder, and it doubles as a chance to set expectations: “No promos, just one roundup with key metrics and product improvements.”
The key is what you do elsewhere. Your monthly digest campaign should be a Cyclic journey or campaign that targets only contacts with:
Email subscription status is Subscribed.
Tag contains
pref-low-touch.Tag does not contain
pref-billing-only.
Because this preference journey keeps those tags and attributes accurate, your digest campaign stays honest.
Standard branch
For standard mode, the actions are similar but tuned for higher engagement:
Update Contact Attribute
email_frequencytoweekly.Add Tag
pref-standard, removepref-low-touchif present.Optionally Send Email summarizing the types of emails they’ll get.
You might also add topic tags here based on what they selected in the preference center (for example, topic-product-updates and topic-best-practices), though the actual assignment of those is usually done by your app via the API, not this journey.
Again, after branch-specific updates and the optional Send Email, the path flows into the same Merge node as the other branches.
Else branch: handle weird states
The else branch is your safety net for:
Contacts whose
email_pref_modeattribute is blank.Legacy data where values don’t match your current options.
Edge cases from partial migrations.
On this branch, a sensible pattern is:
Send Internal Email to your team with the contact’s details so someone can check what went wrong.
Optionally Add Tag
pref-reviewso you can build a segment of “preference records that need cleanup.”
Then send this branch to the Merge node as well. The less time you have contacts sitting in ambiguous states, the better.
Step 7: Tag everyone who has ever set preferences
All the branches converge into a Merge node, which then leads into a simple Add Tag action:
Add Tag:
has-updated-preferences
This tag serves two important roles:
Targeting
You can build one-off campaigns or journeys specifically for contacts who have not set preferences, nudging them to the preference center. For example, a Cyclic trigger that, once a month, emails active users without thehas-updated-preferencestag and invites them to fine-tune what they receive.Analytics
It’s the denominator for your “preference-update rate” metric. The higher this climbs among active subscribers, the more confident you can be that your list is self-optimizing instead of stuck in one-size-fits-all mode.
After this Add Tag, the journey ends. The heavy lifting happens not in this flow, but in how other automations and campaigns use the data it keeps clean.
How this journey reshapes every other email you send
A preference journey doesn’t live in a vacuum. It feeds everything else.
Some practical ways to wire that in:
For your onboarding journey (often triggered by Add to Audience), add an If/Else node right after the trigger:
- Condition: Contact is not tagged withpref-billing-onlyAND Email subscription status is Subscribed.
- “Yes” branch: send the normal onboarding series.
- “Else” branch: skip marketing onboarding entirely or send a minimal “setup checklist” email.For promos and launches, build your audience using the segment builder so it always excludes:
-pref-billing-only
-pref-low-touchif the campaign is high-frequencyFor education content, create separate campaigns:
- One forpref-standardwith weekly tips.
- One forpref-low-touchwith a curated monthly digest.
All of that is possible only because you’re treating preferences as structured data tied to each contact record. Spreeflo’s campaign and journey automation then lets you consistently apply that same logic everywhere without reinventing it per send.
Measuring success: preference-update rate and CTR uplift
Two numbers tell you whether this pattern is doing its job.
1. Preference-update rate
Define three simple saved segments:
“All active contacts” (however you define active: recent logins, recent installs, etc.).
“Has updated preferences” (tag contains
has-updated-preferences).“Active with preferences” (intersection of the two).
The size of “Active with preferences” divided by “All active contacts” is your preference-update rate. CartWizard saw this climb to about 55% of paying accounts within a quarter once they started nudging non-preference users toward the center.
The closer this gets to 100% among your best-fit customers, the less guesswork you’re doing.
2. Downstream CTR uplift
To see whether this translates into engagement, compare:
Click-through rate on a few key campaigns for contacts with
has-updated-preferences.The same campaigns for contacts without that tag.
You can either:
Create two saved segments and send the same campaign to each.
Or use a Random Split node inside a journey to keep a 10% holdout that ignores preference topics temporarily (for example, it still respects
billing_onlybut not content topics), then compare behavior via Check Email Activity.
When CartWizard wired their promos to respect both frequency and topics, CTR among “has-updated-preferences” contacts was about 30% higher than the rest. Unsubscribes also dropped noticeably, but the real win was more clicks from people who actually cared.
That’s the compounding effect you’re after.
Why this pattern quietly grows LTV for Shopify apps
Preference centers are easy to treat as a compliance checkbox. “We have a page, we’re good.” For a Shopify app business, they’re more than that. They’re how you prove to busy merchants that you see them as individuals with different tolerances and interests.
Spreeflo’s model is to capture detail on every customer so you can speak to each uniquely. A preference-center journey like the one in the sequence at the top of this page is a very literal expression of that idea:
Your app records what they want.
Spreeflo listens, updates their profile, and routes them.
Every future message “remembers” that choice without extra work from your team.
You keep your promise at scale, and you do it with one small, well-structured journey instead of constant manual list surgery. For a lean, founder-led SaaS team, that kind of automation is exactly what helps you punch above your headcount.