A Klaviyo abandoned cart flow only works if it is built on the right trigger, filtered to stop messaging shoppers who already bought, and paced so the discount isn’t doing all the work. Most of the flows that underperform were never broken in an obvious way — they were built once, off one trigger, with no filter checking for a purchase that happened five minutes into the sequence. This guide covers the setup decisions that actually determine whether a Klaviyo abandoned cart flow recovers revenue or quietly annoys people who have already paid: which event starts the flow, why two similar-sounding triggers need two separate flows, the filter that keeps a converted shopper out of the rest of the sequence, how many emails to send and roughly when, how to show a shopper their own cart contents rather than a generic product grid, and a discount approach that doesn’t train your list to wait for one.
This assumes the underlying event is already firing — that a Shopify checkout genuinely creates a record Klaviyo can see. What an abandoned cart is on Shopify, and the identity gap that keeps some sessions invisible to any flow at all, is covered separately in what an abandoned cart actually is and why the trigger event matters. This piece assumes that trigger exists and focuses on the flow built on top of it.
What Do You Need Connected Before You Build a Klaviyo Abandoned Cart Flow?
Confirm three things before opening the flow builder. First, that the Shopify-Klaviyo integration is installed and active, not just authorised once and forgotten — an integration can silently stop syncing after a checkout extensibility change or a theme migration without throwing an obvious error. Second, that Added to Cart, Started Checkout and Placed Order events are actually appearing in Klaviyo’s metrics list with recent timestamps; open the metric and check the most recent event rather than trusting that the integration page says “connected.” Third, that you know which checkout your store actually uses at the moment a shopper reaches it — Shopify’s default checkout, a headless or Hydrogen storefront calling the Storefront API directly, or a subscription widget from a platform like Recharge that can redirect into its own native checkout before Shopify’s identity capture happens. Any of the last two can mean the events this flow depends on never fire for a slice of your traffic, and no flow filter fixes an event that never arrives.
Should the Flow Trigger on Added to Cart or Started Checkout?
Trigger the recovery flow on Started Checkout, not Added to Cart. Added to Cart fires the moment a product is added to the cart object, which in many storefronts can happen before Shopify has any identifying detail about the shopper — no email, no phone number, sometimes not even a stable anonymous profile Klaviyo can reliably message later. Started Checkout fires later, once the shopper has begun the checkout process, which in practice means Shopify has created a checkout record with at least a partial identity attached, usually an email address entered manually or captured through an express-pay button.
That later firing point is what makes Started Checkout the more useful trigger for a flow whose whole purpose is sending a message to a specific person. A flow built on Added to Cart either restricts itself to profiles Klaviyo has already identified through some other means — a previous purchase, a newsletter signup — which throws away most of its potential reach, or it accepts sending to a wide anonymous pool and hopes identity resolves later, which is a weaker foundation for a flow meant to close a sale. Started Checkout gives up some volume — a shopper who adds to cart and leaves without ever reaching checkout never enters this flow at all — in exchange for a trigger that reliably has somewhere to send.
Why Do Added to Cart and Started Checkout Need Two Separate Flows?
Because the two metrics carry different identity guarantees and a different position in the funnel, and a single flow trying to branch off both cannot cleanly manage a shopper who progresses from one to the other mid-sequence. If a shopper adds an item, gets caught in a shared flow’s Added to Cart branch, and then starts checkout three minutes later, a combined flow needs to detect that transition and reroute them out of the cart branch and into the checkout branch without sending a duplicate message from each — logic Klaviyo’s flow builder does not give you for free across two different trigger metrics inside one flow.
Two separate flows sidestep the problem entirely. An Added to Cart flow, if you build one at all, exists as an earlier, lighter-touch nudge aimed at the identified subset of cart-adders and exits anyone who reaches Started Checkout before an email sends. The Started Checkout flow is the primary recovery flow and does not need to know anything happened before its own trigger fired. Each flow gets its own entry condition, its own exit filter, and its own analytics, which also makes it possible to tell later which trigger is actually producing recovered revenue — a distinction that disappears the moment both are folded into one flow’s mixed reporting.
How Do You Filter Out Shoppers Who Already Converted?
Add a flow filter set to Placed Order zero times since starting this flow, applied to every email in the sequence, not just the first. This is the setting most abandoned cart flows are missing, and it is different from an entry condition. An entry condition — the rule that decides whether a shopper enters the flow at all — is checked once, at the moment Started Checkout fires. A flow filter attached to each individual email is checked again, immediately before that specific email would send, against the shopper’s behaviour at that later moment.
The distinction matters because a shopper’s status changes constantly during the hours or days a sequence runs. Someone who starts checkout, abandons, and then completes the purchase from a different device an hour later has already converted by the time the flow’s second email is due. Without the “since starting this flow” filter checked at each step, that email still sends, because the entry condition — Started Checkout occurred — was true once and stays true; Klaviyo does not automatically revisit it. With the filter in place, the flow checks Placed Order again right before each send and removes anyone who has bought, so the shopper who already checked out does not get a message thanking them for a sale that was theirs to make, followed by a second message pushing a discount on a cart they no longer have.
Set the same filter, Placed Order zero times since starting this flow, on every email in the sequence rather than only the first. A shopper who converts between email two and email three needs to be caught at that later checkpoint too — a filter placed only at entry or only on the first message leaves every message after it unprotected.
How Many Emails Should the Sequence Contain, and How Should They Be Timed?
A short sequence — commonly three emails — covers most of what an abandoned cart flow needs to do without becoming a fatigue complaint. Each email in that sequence should earn its place with a different job: the first re-anchors the shopper to what they left in the cart and answers the most likely objection for that segment, the second widens the case for coming back with something the first didn’t say, and the third closes the window, often with more urgency than the earlier two.
Timing is a variable to test against your own data rather than a fixed number to copy from a benchmark, since purchase consideration time genuinely differs by category and price point. As an illustrative starting point only — not a setting to copy — a first email while the cart is still fresh, a second spaced a bit further out, and a third closing the sequence a few days after the first is a common shape teams start from and then adjust once they have their own send-to-conversion data. What matters more than any specific delay is that the three emails are spaced far enough apart that each can be read as its own message, not stacked so closely that the second and third arrive before the shopper has even opened the first.
How Do You Add a Dynamic Cart Block to Each Email?
Klaviyo’s Abandoned Checkout dynamic block, added from the flow email’s content panel, pulls the actual line-item data from the Started Checkout event that triggered the flow — product image, name, price, and a link back to the checkout with those items still in it. Drop the block into the template, connect it to the Started Checkout trigger data already available in that flow, and confirm in a test send that it renders the real cart contents rather than a placeholder.
The reason this matters more than it sounds: a generic template showing catalogue bestsellers instead of the shopper’s own cart forces them to re-find and re-add whatever they were actually considering, which reintroduces the exact friction the flow exists to remove. A dynamic block that shows their own items, at the price they saw them, with a direct link back into checkout, keeps the path from email to completed order as short as the flow can make it. Confirm the block renders correctly at send time, not only in the flow builder’s preview, since preview data and live checkout data can diverge if the integration’s line-item sync has any gap.
What Discount Strategy Actually Recovers Revenue Without Training Shoppers to Wait?
Hold the discount out of the first email and let the sequence’s own value carry it instead — proof, specifics about the product, a real reply address, urgency framed honestly rather than a countdown timer with no real deadline behind it. A discount offered on email one treats every abandonment as price-driven, when a meaningful share of cart abandonment on a $3M–$30M brand’s storefront is trust, a shipping question, or a shopper who genuinely got distracted, not price resistance.
The cost of leading with a discount compounds past the first send: a shopper who learns that abandoning reliably produces a code starts abandoning on purpose, and a discount stacked into a sequence sent by default to everyone erodes margin on a share of sales that would have completed anyway, whether or not the flow sent a code. A defensible structure reserves an incentive, if your margin supports offering one at all, for a later email in the sequence, framed as closing a genuine window rather than repeated on every message. Whether to offer one at all is a margin decision only you can make with your own numbers — this guide’s job is the mechanics of where it sits in the sequence, not what depth to set it at.
What’s the Step Most Teams Get Wrong?
Check whether the Placed Order filter on your flow is set to run once, at entry, or continuously, on every email. This is the single setting most responsible for an abandoned cart flow that looks fine on its send-count dashboard while quietly emailing people who already bought. A flow built with the filter only at entry — or with no filter at all beyond the trigger itself — will keep firing every scheduled message to a shopper who converts partway through, because nothing in that configuration ever checks their status again after the first moment.
The fix is not a new flow; it is opening the existing one, adding or correcting the Placed Order zero times since starting this flow filter on every email node individually, and confirming in the flow’s own filter settings that it is evaluated per-send rather than once. Teams that skip this rarely notice the cost directly — no error appears, no alert fires — they just see a flow with a send count that looks healthy and a support inbox with an occasional complaint from a customer who received a discount pitch for an order they had already placed.
How Do You Verify the Flow Fired and Filtered Correctly?
Open the flow’s own analytics tab and look at the filtered-out count for each email, not just the total sends. That number should track with your Placed Order volume over the same window — if checkout completions are steady but the filtered-out count on your abandoned cart flow’s second and third emails is near zero, the filter is very likely not catching converters the way it should, even though the flow itself is technically running.
Placing a real test order is the second check worth running before calling the build finished. Use the exact checkout path your real shoppers use — including any subscription widget or headless frontend, not just Shopify’s default checkout in a private browser tab — start the flow, and then complete the order before the second email is due. If the second email still arrives, the filter is not attached correctly to that email node, and it needs fixing before the flow goes live for real traffic. Confirming this once at build time is faster than tracing it back from a customer complaint weeks later.
Getting the trigger, the filters and the timing right for every checkout path your store actually has — Shopify’s default checkout, a subscription widget’s redirect, a headless frontend — is not a one-time build you finish and forget; it is what we do as ongoing lifecycle flows work, and it is exactly the kind of setup a $3M–$30M brand on scaling infrastructure needs someone actually maintaining as checkout paths change under it.
Sources
- Klaviyo, benchmark data across more than 183,000 brands: 41% of email revenue attributed to automated flows (vendor-reported).
No independent, third-party study beyond the figure above is quoted in this piece; the flow-building steps are written from how Klaviyo flows are configured and operated on Shopify.