The Zero-Overhead Send-Time Experiment Your Shopify App Should Be Running
Step-by-step walkthrough of a zero-overhead send-time experiment for your Shopify or e‑commerce app, using Spreeflo journeys to A/B test onboarding email timing, tag outcomes, and turn behavioural triggers into always-on experiments that quietly grow MRR.
Industry
Niche
Pattern
Loading sequence...
When CartWizard hit $80k MRR, their onboarding email looked "fine" on paper.
Same welcome template for every new install. Solid copy. Clean design. Sent whenever the founder remembered to hit send in their legacy tool.
Some days it pulled a 42% open rate. Other days, 19%. Trial-to-paid conversion wobbled in step, and the team had no idea why.
They were obsessing over copy tweaks and CTA buttons while ignoring the quiet variable driving most of the swing: send time.
The sequence at the top of this page is the whole journey, end to end. It’s a send-time experiment you can wire once in Spreeflo, then forget about while it quietly collects evidence on what actually works for your app.
This article walks through that journey node by node, why it’s built the way it is, and how to adapt it for your own Shopify or e‑commerce app.
Why send time is worth an experiment (and not another guess)
For a Shopify app, "onboarding email" is doing a lot of heavy lifting:
Turning an install into an activated user.
Preventing the first-week churn that kills LTV.
Seeding future upsells.
But your install base isn’t homogeneous. Some merchants install from Europe after dinner. Others from the US mid-morning. Some click through setup immediately; others plan to "come back to it tonight" and never do.
If you always send that first email on a fixed schedule or "whenever," you’re baking a guess into one of your most important messages. And most teams never test that guess because:
Their tools make A/B testing feel like a separate project.
They’re busy shipping features.
They assume they don’t have “enough volume” to justify it.
A send-time experiment done the right way is almost zero extra work:
Same trigger.
Same email.
Same copy.
The only variable: how long after the behavior you send.
That’s exactly what the journey at the top of this page does using Spreeflo’s Random Split, Time Delay, and Send Email nodes.
The experiment in plain language
Let’s ground this in a specific example.
Our fictional app: CartWizard, a cart recovery and upsell app for Shopify. Four-person team. $80k MRR. Tech stack: Stripe, a custom Rails backend, Shopify API, and a basic email tool they’re about to replace.
They want to test whether sending the "Activate CartWizard in 3 steps" email 1 hour after install beats sending it 24 hours later.
Here’s the core idea of the journey:
When a merchant installs the app, CartWizard fires an
app_installedevent into Spreeflo.That event triggers a journey.
A Random Split sends half of new installs down the "send after 1 hour" path and half down the "send after 24 hours" path.
Both paths send the same email template, just at different delays.
Each path tags its contacts so you can later see:
- Open rate by variant.
- Trial-to-paid conversion by variant.
You build this once and let it run. After a few hundred installs, you have hard data on which timing actually moves revenue.
Now let’s walk through each node and why it’s there.
Step 1: Behavioural trigger on `app_installed`
This is a behaviour-driven journey, so we start with a Custom Event trigger.
In Spreeflo, you’d:
Track
app_installedfrom your backend or client app via the Spreeflo API or JavaScript SDK.Configure a Custom Event trigger with:
Event name:
app_installed(Optional) Property filters if you only want certain installs, like
plan = "trial".Re-enrollment: off, because you probably don’t want to re-run the onboarding sequence if someone uninstalls and reinstalls later.
Why this trigger?
It aligns with your real lifecycle: you care about send time relative to install, not relative to when you remember to hit send.
It’s easy to implement if you’re already using web tracking and analytics or server-side events.
From here on, every merchant that fires app_installed enters this journey automatically. No manual batching. No cron jobs.
Step 2: Random Split to create two comparable groups
Right after the trigger, the sequence uses a Random Split process node.
Configuration:
Branch A: label it
early_send.Branch B: label it
late_send.Percentage: 0.5 (50% to each branch).
Why Random Split here?
You want the groups to be statistically comparable. That means no manual targeting like "US-only" vs "Rest of World" on different branches.
Randomization ensures that any difference in open or conversion rates is very likely due to send-time, not some hidden factor.
You could tweak the percentages if you like (for example, 70% early, 30% late if you’re nervous about underperforming), but 50/50 keeps the math and the comparison clean.
Step 3: Tag each variant for later analysis
On each branch, the first Action node is an Add Tag.
Early branch adds a tag like
sendtime_onboarding_1h.Late branch adds a tag like
sendtime_onboarding_24h.Keep "Force tag trigger" off; we’re not trying to trigger other journeys here.
Why tag immediately?
Tags give you a permanent "this contact was in variant X" stamp.
Later, you can use the segment builder to build:
You could try to infer variant from which nodes they passed through, but tags make it explicit and much easier to work with everywhere else in Spreeflo.
A segment of "Early send variant" contacts.
A segment of "Late send variant" contacts.
Sub-segments of "Early send + opened" or "Late send + upgraded".
You could try to infer variant from which nodes they passed through, but tags make it explicit and much easier to work with everywhere else in Spreeflo.
Step 4: Time Delay — defining your send-time variants
Now comes the key experimental variable: Time Delay.
On the early branch:
Add a Time Delay node:
Duration:1
Unit:Hour(s)
On the late branch:
Add another Time Delay node:
Duration:1
Unit:Day(s)
Spreeflo’s Time Delay works in hours or days, with a minimum of 1 hour. That’s plenty for meaningful send-time testing in B2B SaaS, where you’re usually comparing "soon after the behavior" vs "next day" or similar.
Why 1 hour vs 24 hours?
1 hour keeps you close to the moment of intent. The merchant still remembers why they installed you.
24 hours lets you test "next workday morning" behavior for people who install late in their day.
The difference is big enough that you’re likely to see a clear signal, even at modest volume.
You can absolutely tune these later — 2 hours vs 8 hours, 4 hours vs 3 days — using the same pattern.
Step 5: Send the same email template on both paths
After each Time Delay, you place a Send Email action.
Critical rule for this experiment: both branches use the exact same email content.
In Spreeflo, that looks like:
Create one welcome email template in the email builder (or bring your own HTML).
In both Send Email nodes, pick the same template.
Configure:
- From account: your usual sender.
- "Send only once": on, so a contact never gets duplicate copies if they somehow re-enter this step.
Why use the exact same template?
You want to isolate send-time as the variable. If copy, subject line, or CTA differ, you’re running a multi-variable test without enough traffic to interpret it.
It keeps maintenance simple. You improve the onboarding email once and both variants improve.
At this point, the only difference between paths is: how long you waited before sending the identical email.
Step 6: Give the email time to work, then look for conversions
Open rate is nice, but CartWizard ultimately cares about trial-to-paid conversion.
To measure that without turning your journey into a tangle, you do two things on each branch:
On each branch:
Add a Time Delay node of, say,
7 Day(s)after the Send Email.
This gives everyone a fair 7-day window to upgrade after receiving the email.After that delay, add an If/Else process node with a condition like:
- "Custom eventsubscription_upgradedtriggered at least 1 time in the last 7 days."
- That event is something you already track via your backend or app using the Spreeflo API.
"Yes" branch: they converted.
"Else" branch: they didn’t.
You could use a slightly different conversion signal — "created first campaign," "enabled key feature," etc. The pattern is the same.
Step 7: Tag outcomes so you can compare variants
On each of the four outcome paths (early-converted, early-not, late-converted, late-not), add an Add Tag action:
Early + converted:
sendtime_onboarding_1h_convertedEarly + not converted:
sendtime_onboarding_1h_not_convertedLate + converted:
sendtime_onboarding_24h_convertedLate + not converted:
sendtime_onboarding_24h_not_converted
Again, "Force tag trigger" off.
Now you have everything you need to answer two questions:
1. Open rate by send time.
2. Conversion lift by send time.
How you read it:
Use the segment builder to create:
- Segment A: tagged withsendtime_onboarding_1h.
- Segment B: tagged withsendtime_onboarding_24h.Within each segment, count:
- How many have "Email activity: opened this onboarding email at least once."
- How many have the appropriate_convertedtag.
The ratios give you:
% opened for each send-time.
% converted within 7 days for each send-time.
Not perfect randomized-trial statistics, but more than enough to make a confident product decision.
Why this works so well for founder-led Shopify app teams
Spreeflo’s brand thesis is simple: founder-led businesses win on leverage, not headcount. You feel that day to day. There are always more experiments you could run than you have hours.
This pattern earns its slot because:
You reuse an email you already have.
You wire the experiment once in a visual journey.
Every new install automatically becomes another datapoint.
No manual CSV exports. No temporary hacks in your code. No "we’ll remember to send half tomorrow."
Instead, you’ve programmatically embedded a meaningful experiment into your onboarding flow.
And because this is a journey, not a one-off campaign, it keeps working next month and next quarter. When you log back into the campaigns and journeys view, you’re looking at a living experiment that’s still adding signal.
Adapting the pattern to other touchpoints
You don’t have to stop at app_installed. E‑commerce apps have plenty of behaviours where send-time is probably doing more work than you think.
Some examples:
Feature activation nudges
Trigger: custom eventfeature_usedfor a related feature, or lack of a critical event after trial start.
Test: "nudges sent 4 hours after install" vs "nudges sent 2 days after install."Upsell emails for higher tiers
Trigger:feature_usedfor something that hints at higher-tier fit.
Test: send immediately after feature discovery vs batching a day later so they’re not overwhelmed.Payment failure recovery
Trigger:payment_failed.
Test: "retry email at 1 hour" vs "retry email next morning in their workday."
The skeleton is identical:
Behavioural trigger.
Random Split to two variants.
Add Tag for variant.
Different Time Delay per branch.
Same Send Email template per branch.
Fixed observation window.
Outcome tags for conversion/non-conversion.
You can run several of these in parallel across your lifecycle without adding meaningful operational overhead.
A quick word on re-enrollment and guardrails
A couple of configuration details matter if you’re going to roll this out in production:
For one-off lifecycle events like
app_installed, keeping re-enrollment off on the Custom Event trigger is usually right. You don’t want the same store getting onboarding sequences twice because they reinstalled during troubleshooting.For recurring events (like
feature_used), you might want a different journey where the trigger’s re-enrollment is on, but with internal guards (tags or attributes) so a contact doesn’t endlessly re-enter the same experiment.Respect pacing. The journey here has exactly one Send Email per path with Time Delays around it, so you’re safe. If you extend the flow, keep at least one Time Delay or Wait Condition between every email contact can receive.
The sequence at the top of this page already respects those guardrails. If you adapt it, keep them in mind so your experiment stays clean and your messaging stays sane.
The real win: an experimentation habit that runs itself
Most e‑commerce app teams know they should be testing more. Send-time. Subject lines. Onboarding sequences. They’re just too busy building the product and handling support to turn that into a habit.
Automations like this are how you change that reality.
You don’t need a growth team. You need an hour with a journey builder, a couple of clear hypotheses, and the discipline to keep copy constant while you vary one thing at a time.
Spreeflo’s visual journeys, email builder, and behavioural triggers give you the building blocks to bake experiments into the flows you already run. Pricing that’s friendly to small teams (see Spreeflo’s pricing) means you can keep those experiments running as your install base grows without worrying about tool bloat.
Start with this send-time experiment on your onboarding email. Let it run for a few hundred installs. See which timing actually creates more activated, paying stores.
Once you’ve seen that a one-hour setup can move MRR in the background, it becomes much easier to treat experimentation as something your system does for you, not another task on your to‑do list.