Blog

Abandoned checkouts: reminders that stop the moment a basket becomes an order

A shopper who typed their email and then left is the order closest to happening. GoCommerce’s new cart-recovery module notices that basket within minutes, emails the shopper a few times, and stops the moment the basket becomes an order. Then it shows you which orders it actually brought back.

What counts as abandoned

A basket with something in it that sits untouched long enough gets a record of its own, with the items and prices as they were.

TypeWhat it meansIdle time before it counts (default)
CheckoutThe shopper typed an email, which a guest does at checkout’s first step10 minutes
CartNo email was typed30 minutes

A cart can be emailed only when it carries a verified address, such as a signed-in shopper’s confirmed email. It is listed either way.

Baskets that went idle before you installed the module are shown, but the reminders never go to them — nobody wants a backlog mailed on day one.

A shopper who comes back and leaves again resumes the same record, and the next reminder waits for that visit to go quiet.

The reminder sequence

Checkouts and carts each get a sequence: an on/off switch, the idle time, and up to five “wait, then send” steps. Each wait counts from the step before; the first from when the basket was marked abandoned.

StepCheckout (default)Cart (default)Email it sends
11 hour2 hourscart.recovery.1 — “You left something in your basket”
220 hours24 hourscart.recovery.2 — “Still thinking it over?”
348 hours—cart.recovery.3 — “Last chance for the items in your basket”

The idle time can be 1 minute to 7 days, and each wait 1 minute to 30 days. Both sequences live on Marketing › Automations; the emails’ wording is edited on Notifications › Setup Email, with the store’s other emails.

Nothing is decided early. Before every send, the module checks the basket as it is now:

CheckIf it fails
The basket still existsThe record is marked expired
It has not become an orderNothing more is sent
Reminders are not suppressed for itNothing is sent
The shopper has not been in it within the idle timeThe step moves to when the visit counts as over
It has an email addressHeld until the shopper comes back with one
At least one item can still be boughtHeld until the shopper comes back to it
The automation is onHeld until it is switched on and saved
An email provider is set upHeld until one is, and the automation is saved

A held reminder shows its reason. If the provider refuses a message, the module retries after 10 minutes, then 20. After three failed tries it stops with “sending kept failing”; saving the automation tries again.

Where a reminder’s link goes depends on two addresses you set.

You setThe linkClick counted?
A storefront address and GOCOMMERCE_PANEL_URL<panel URL>/x/cart-recovery/r/<token>, which counts the click, then <storefront>/cart/<cart token>Yes
A storefront address onlyStraight to <storefront>/cart/<cart token>No
No storefront addressNo link; the default email gives a basket reference instead—

If the basket was already bought or has gone, a counted link opens the storefront’s home page instead.

How an order is credited

The engine’s order.created event now carries cart_id, the basket the order came from. The module marks that record recovered, with the order number and total, and notes whether any reminder — automatic or by hand — went out first. So the figures keep “recovered after a reminder” apart from “came back on their own”.

StatusMeaning
AbandonedRecorded; nothing scheduled, and the reason shown
ScheduledA reminder is planned
ContactedAt least one reminder has gone out
RecoveredIt became an order — final
SuppressedStaff stopped the reminders, with a reason
ExpiredThe basket was deleted by the store’s retention clean-up

What staff can do

Orders › Abandoned checkouts lists every record. A record’s page shows the basket then and now — a price that moved, a line that sold out — the address’s past orders, and a timeline of what happened and who did it.

ActionRightGiven by default to
See the list, records and figuresabandonment.readOwner, Manager, Staff
Send a reminder now, copy the linkabandonment.contactOwner, Manager, Staff
Suppress, with a reasonabandonment.suppressOwner, Manager, Staff
Change the automationabandonment.automateOwner, Manager

Send now picks one of the three emails and does not move the sequence on. Copy link is for pasting into a chat; it goes on the timeline, because the link opens the basket for whoever holds it. Suppress asks why: contacted manually, asked for no more contact, invalid customer, fraud or test, or other, with a note.

If an action cannot happen — the basket was just bought, say — the screen says why.

The figures

Six cards sit above the list and filter with it: abandoned, potential revenue, recovery emails sent, recovered orders, recovered revenue, and the recovery rate (recovered ÷ abandoned).

Marketing › Recovery analytics adds three views:

How to turn it on

WhatHow
The moduleThe -recovery flag — already on in both Docker Compose files
Where the basket livesSTOREFRONT_URL, or the automation screen, which wins
Counted clicksGOCOMMERCE_PANEL_URL, where the store’s panel is reached (a multi-store platform uses each store’s domain)
An email provider-resend or -sendgrid with its key; without one, reminders are held

One store with recovery on

# Where the shopper's basket lives
export STOREFRONT_URL=https://shop.example.com
# The engine's public address, so clicks are counted
export GOCOMMERCE_PANEL_URL=https://admin.example.com
# An email provider; without one, nothing is sent
export RESEND_API_KEY=your-resend-api-key

./gocommerce -recovery -resend serve

Flags and variables from cmd/gocommerce/main.go. As for any store, the database comes from DATABASE_URL and the admin token from GOCOMMERCE_ADMIN_TOKEN.

For developers: the module adds no third-party dependency and sends through the store’s installed email notifier. Its admin routes are under /api/admin/x/cart-recovery/. The one engine change is cart_id on order.created, explained in decision D82 of PLAN.md.

What it does not do yet

Further reading

Chat on WhatsApp