E-commerce
Abandoned-cart chat agent: €38k recovered in one quarter
A Maastricht specialty brand ditched a four-email Klaviyo recovery flow for a chat agent texting from a real Dutch 06 number. One quarter later: €38,400 back.

It was 21:47 on a Tuesday in February. A customer in Utrecht had a Shopify cart open: a €92 specialty bottle, two accessories, free shipping unlocked. She read a notification, closed the tab, and went to bed. Forty-three minutes later, the Klaviyo abandoned-cart flow fired its first email. It landed in a Gmail Promotions tab between seventeen other things, and there it stayed for four more emails over five days. The cart never came back.
This is roughly what 78% of carts looked like at a 26-person specialty e-commerce brand in Maastricht. They were doing about €4.2M a year, growing 30% YoY, and losing somewhere between €140k and €160k a quarter to abandoned checkouts. The Klaviyo flow they had built two years earlier was recovering maybe 3% of that, and the marketing lead could tell you in advance which emails would be opened (the one with the 10% code) and which would not (the rest).
In Q1 2026 we replaced that four-email flow with a chat agent that texts customers from a real Dutch 06 number. Three months later, recovered revenue from abandoned carts had gone up by €38,400 against the previous quarter. Here is what we built, what nearly broke it, and the parts you can copy without hiring anyone.
What the Klaviyo flow was actually doing
Before the rebuild, the abandoned-cart sequence was a textbook setup: Klaviyo's recommended four-step flow, with 43-minute, 24-hour, 72-hour, and 120-hour delays. Subject lines were A/B tested. The third email carried a 10% code. The fourth was a soft-urgency "last chance" framing. None of this was wrong. It was just bumping the channel ceiling.
The measured numbers, across Q4 2025:
- Open rate: 24.1% on email 1, falling to 11.3% by email 4.
- Click rate: 2.9% on email 1, falling to 0.6%.
- Attributed recovered revenue: roughly €15,200 per quarter.
- Carts triggered: about 280 per week, average abandoned value €148.
The flow was not broken. It was just hitting the ceiling any Dutch consumer-email channel hits, which is that almost nobody reads marketing email anymore. Especially nobody who put €184 worth of niche goods into a cart at 21:47 on a Tuesday and went to bed without paying. The brand had spent two months optimising subject lines for what was, fundamentally, the wrong channel.
The 06 number as the actual unlock
SMS open rates in the Netherlands sit around 95% within three minutes. That is not a benchmark worth arguing with. It is the messaging-channel reality every Dutch consumer brand bumps into the moment they actually try. The constraint is not deliverability. The constraint is that most "SMS marketing" looks like noise from a shortcode, and Dutch consumers screen those the same way they screen junk mail.
The thing that changes the response is the number. Not a 1456 shortcode. Not a long alphanumeric sender ID like "BRANDNAME". A real, dialable, repliable Dutch 06 number. The kind a friend would have. The brand procured one through Bird (formerly MessageBird) with both SMS and WhatsApp Business API attached to the same MSISDN, so a conversation could flow from one channel to the other without the customer noticing.
The first message went out 35 minutes after abandonment, just before the Klaviyo flow would have fired. The copy was short, lowercase, and pointedly un-marketed:
hoi marieke, zag dat de tualet bottle in je mandje stond. iets waar je nog over twijfelt?
First message, agent-drafted, sent from a +316 number
About 31% of recipients replied within four hours. That is the number that broke the project open. An email flow does not produce 31% reply rates because email is not a conversation. A real 06 with a human-shaped sentence is.
The agent decision logic
The core handler runs on a Bird inbound webhook for Shopify's checkouts/update event, debounced to fire once per cart 35 minutes after the last activity. The interesting decisions happen before any message is sent:
// abandoned-cart-agent/src/handlers/cart-abandoned.ts
import { sendSMS } from "../channels/bird";
import { draftOpener } from "../agent";
import { Cart } from "../types";
import { withinQuietHours, alreadyMessaged, orderHistory } from "../guards";
const MIN_VALUE_EUR = 60;
const QUIET = { from: 21, to: 9, tz: "Europe/Amsterdam" };
export async function onCartAbandoned(cart: Cart) {
if (cart.totalEur < MIN_VALUE_EUR) return "skip:low-value";
if (!cart.customer.smsConsent) return "skip:no-consent";
if (!cart.customer.phoneE164?.startsWith("+316")) return "skip:non-nl-mobile";
if (await alreadyMessaged(cart.customer.id, { days: 7 })) return "skip:cooldown";
if (withinQuietHours(QUIET)) return "defer:quiet-hours";
const opener = await draftOpener({
cart,
history: await orderHistory(cart.customer.id),
tone: "dutch, casual, lowercase, one short sentence, no emoji, no exclamation",
});
await sendSMS({
from: process.env.BIRD_06_NUMBER!,
to: cart.customer.phoneE164,
body: opener,
tags: { cartId: cart.id, kind: "abandoned-cart-opener" },
});
return "sent";
}
The gates are doing more work than the agent itself. The €60 floor strips out impulse abandons that would never have converted. The seven-day cooldown stops a customer who abandons three times in a week from feeling stalked. The 06-only filter avoids sending to international numbers where SMS economics fall apart. The quiet-hours check is non-negotiable. A brand text at 22:30 reads as harassment, regardless of what it says.
When the customer replies, the conversation switches into a different mode. The agent has read-only Shopify access (product copy, stock, shipping ETAs, the customer's prior orders) and a tightly scoped action set: it can email a discount code, reserve stock for 24 hours, or hand off to a human inbox during office hours. It cannot apply discounts directly, change addresses, or process refunds. The reasoning for that boundary is in the next section.
The quarter in numbers
Q1 2026, measured against Q4 2025 as the baseline:
- Carts triggered for messaging: 3,114 (vs. 3,640 emails sent. The drop is the consent + value + cooldown filters doing their job).
- Reply rate to opener: 31.4%.
- Recovered revenue attributable to the SMS channel: €53,600.
- Recovered revenue from the comparable Klaviyo flow in the prior quarter: €15,200.
- Delta: +€38,400.
- Channel cost (Bird SMS + WhatsApp + 06 rental + LLM tokens): €1,840.
- Human handoffs to the support inbox: 84, of which 51 converted.
Two effects we did not predict. First: a non-trivial fraction of recovered carts came back at a higher AOV than they abandoned at, because the agent could answer a question ("does this fit a 750ml bottle?") that the product page had not addressed. Second: the support inbox got quieter, not louder. The agent absorbed about 60 questions a week that would otherwise have arrived as tickets at 09:00 the next morning. The marketing lead's first reaction was that the customer-service lead was going to thank her, which is not a sentence those two people normally exchange.
AVG, opt-in, and the parts that almost killed the project
Three things nearly broke this before it shipped.
The first was consent. Under the AVG and the Dutch Autoriteit Persoonsgegevens guidance, SMS marketing requires explicit, unbundled, granular opt-in. The brand's existing newsletter checkbox at checkout did not cover SMS, and we could not retroactively assume consent because a customer had previously given an email address. We added a separate, unticked checkbox at checkout: "ja, ik wil updates via SMS van [brand]". Roughly 38% of new customers opt in. Existing customers without opt-in are excluded from the flow entirely. There is no shortcut here. The €38k recovery only counts if the customers messaged actually consented.
The second was tone. The first version of the agent wrote in clean, capitalised, slightly enthusiastic Dutch. It tested terribly. Reply rate was 11%. We rewrote the system prompt to enforce lowercase, one short sentence, no exclamation marks, no emoji, no rep names, and the reply rate tripled. The lesson is that a 06 number signals a person, and people do not write like marketing emails. If the copy is off, the channel is wasted.
A real Dutch 06 signals a real person. If your agent's copy reads like a Mailchimp template, you have built the worst of both channels: SMS pricing with email response rates.
The third was the action boundary. The first prototype let the agent issue discount codes on its own authority. Within two days, a customer figured out that mentioning a competitor's price reliably produced a 15% code. We pulled discount authority back to a deterministic rule: codes only for carts over €120, only after a second reply, max once per customer per 30 days. The agent recommends. The rule engine authorises. This is how every consumer-facing agent should be wired. The model is not the policy. Treat it as the conversation layer and keep money decisions in code you can read on a Friday afternoon.
What you can copy this week
If you are running a Klaviyo abandoned-cart flow today and want to test the SMS angle without rebuilding everything: procure a real 06 number through Bird, CM.com, or a similar Dutch gateway. Add an unticked SMS opt-in at checkout. Send a single, plain, lowercase opener 35 minutes after abandonment. Read the replies yourself for the first two weeks before automating anything. The signal is in the texts that come back, and you will not see it from a dashboard.
When we built this agent for the Maastricht brand, the part that nearly killed it was not the model or the SMS gateway. It was discovering, three weeks in, that Shopify's checkouts/update webhook fires on every cart edit, not just abandonment, so the agent kept re-triggering against the same cart. We ended up debouncing on the cart token and only firing once the cart had been idle for 35 minutes with no further updates. That debounce is the difference between a chat agent and a stalker. We do this kind of work as AI agents for ABN clients, and the playbook above is the one we use.
One five-minute audit you can run before any of this: pull your last 90 days of abandoned-cart triggers, filter to carts above €60, and count how many came from Dutch mobile numbers. That number, times a plausible 38% opt-in rate, times a 3% recovery delta, is roughly the quarterly revenue you are currently leaving in Klaviyo's queue.
Key takeaway
A real Dutch 06 number with two-way reply is a different category of message in the customer's brain. That is the lift, not the model.
FAQ
Why did SMS work better than email for abandoned carts?
It was not SMS that worked. It was a real Dutch 06 number with a one-sentence, lowercase opener. Customers read it as a person, not a brand, and 31% of them replied within four hours.
Is it legal to text customers under the AVG?
Yes, if you have explicit, unbundled opt-in for SMS specifically. A newsletter checkbox does not cover it. We added a separate unticked SMS checkbox at checkout. About 38% opt in.
Do I need a real 06 number, or will a shortcode work?
A shortcode reads as marketing and screens out. The whole lift in this case study came from using a real, repliable Dutch mobile number procured through Bird. Shortcodes do not produce conversations.
How much does the SMS and WhatsApp channel cost?
For this brand, about €1,840 in Q1 across SMS, WhatsApp Business, the 06 number rental, and LLM tokens, against €53,600 in recovered revenue. The economics only work if you gate by cart value.
What stops the agent from giving away discounts?
The model never authorises money. It can recommend a code, but a deterministic rule engine decides: cart over €120, only after a second reply, max once per customer per 30 days. The agent is the conversation layer, not the policy.