Skip to content

Powered by Grav CMS + Helios Theme

Cart recovery

Help customers return to an abandoned cart. This page covers setting recovery up, reading the recovery rate, and sharing a cart with a customer over the phone.

Cart recovery is one email plus one reminder; there is no campaign builder. The email carries a signed link that puts the whole cart back in one press, at today's prices, with anything that changed called out.

Before you begin

  • The Email plugin installed and configured. Every message here is queued and sent by the worker. See Emails.
  • bin/plugin kahunacart work running on a schedule. Nothing sends without it. See CLI.
  • A cart only qualifies if it has an email address on it, so a customer who reached the checkout form and did not pay.
  • A cart a shopping agent built is never mailed, whatever address is on it. The buyer gave that address to the platform to finish a purchase, not to your store to be reminded. See Agentic commerce.

How it works

  1. A cart sits untouched for cart.abandoned_hours.
  2. The worker's sweep mails the customer once and stamps the cart. A cart is never mailed twice.
  3. With recovery.enabled on, that message carries a restore link. The link is good for recovery.link_days and may be opened more than once.
  4. recovery.reminder_hours later, if the cart still has not come back and recovery.reminder_enabled is on, the worker sends one reminder. That is the last message about the cart.
  5. The customer opens the link, sees what would come back at today's prices, and presses a button. The lines go into their own cart and the abandoned cart is marked recovered once, however many times the link is opened.

Turn cart recovery on

  1. Open KahunaCart → Settings, the Commerce tab, and scroll to Carts.
  2. Set Abandoned Cart Reminders to enabled. This is the message itself.
  3. Set Restore links to enabled. This puts the signed link in the message and makes the restore page answer.
  4. Leave Restore link lifetime at 7 days, or shorten it.
  5. Optionally set One reminder to enabled and choose Reminder after (hours).
  6. Open Notifications in the admin's Operations group and check that Abandoned cart and Abandoned cart reminder are switched on. A message switched off there queues no job, whatever the config keys say.

The next worker tick starts mailing carts that qualify.

Important

Both switches are off in a fresh install and stay off through an upgrade.

The link opens a restore page, not the cart. The page lists the lines, what each costs today, and anything that cannot come back. Nothing is written until the customer presses the button, so mail scanners that fetch the link restore nothing.

Prices are today's prices

Every line goes back through the same path the buy button uses, at today's price.

What happened to the line What the customer sees
Unit price is unchanged The line, at its price
Unit price has moved Today's price, with the old one beside it, and a notice against the line
Product deleted or unpublished Named under "these cannot come back"
Product has sold out Named under "these cannot come back"

Those notices are order notices on the cart the customer is about to check out with, so the moved price is still named at checkout, on the receipt and in the confirmation email. Restoring the same cart twice does not stack two notices about one line. Every dropped line is its own notice.

An expired link, a tampered one, one whose cart has since been bought, and a token that never existed all land on the same expired-link page with the same sentence.

That page offers a fresh link, sent to the address already on the cart and never to one typed into the form. The form is rate-limited per address and per link, and answers the same whether or not the cart exists.

Share a cart with a customer

A merchant who builds a cart on the phone can hand it over as a link.

  1. Open Recovery in the admin's Store group.
  2. Find the cart and choose Share link from its row menu.
  3. Copy the link, or give an email address to send it as well.

A share link differs from a recovery link in three ways:

Recovery link Share link
Lifetime recovery.link_days, 7 days by default share.link_hours, 24 hours by default
Uses Repeatable Single-use
Anonymous load Opens Challenged for the address on the cart, when share.challenge_required is on

With share.challenge_required on, somebody who is not signed in as the cart's own customer has to type the email address on the cart before the link opens it. The page never prints that address; it compares hashes, so a wrong answer gives nothing away.

Note

A cart with no email address on it produces a link with no challenge.

Read the recovery rate

The dashboard carries a Cart recovery tile, and Recovery in the admin's Store group carries the same figures over a chosen window.

Figure What it counts
Mailed Carts that got a recovery message inside the window
Reminded Of those, how many also got the reminder
Recovered Of those, how many had their link redeemed
Rate Recovered divided by mailed, as a percentage
Revenue recovered The total of the restored carts that went on to become orders
Still in a cart The total of the restored carts that have not been bought yet

A recovered cart is counted once, however many times its link is opened. The window applies to when a cart was mailed. Revenue is counted only once a restored cart becomes an order, so a link clicked this morning is a recovery but not yet revenue.

The two money figures are one currency's: the base currency, unless the request to GET /kahunacart/reports/recovery carries ?currency=EUR. The answer's currency says which. On a store with recovered carts in other currencies the answer also carries other_currencies, a count of those carts as { "currency": "EUR", "orders": 2 }, and the screen says "2 recovered carts in other currencies are not included." under the tiles. The counts (mailed, reminded, recovered) are of carts and stay whole, so the rate is the same whatever the currency. A store with one currency sees no difference. See Reports and totals.

When the abandoned-cart email or restore links are switched off, the Recovery screen says so.

Delete the cart's links from the Recovery row menu. The link stops working immediately, and no other link is affected.

Configuration

Key Default Effect
cart.abandoned_enabled false The abandoned-cart message itself
cart.abandoned_hours 24 Idle time before a cart earns that message
recovery.enabled false Put a signed restore link in it, and answer the restore route
recovery.link_days 7 How long a recovery link works for
recovery.reminder_enabled false Send the one reminder
recovery.reminder_hours 48 Hours after the first message before the reminder is due
share.link_hours 24 How long a share link works for
share.challenge_required true Challenge an anonymous load of a share link
email_log.retain_days 180 How long an email-log row is kept. 0 keeps them forever
emails.abandoned_reminder_subject '' Blank uses the translated default

API reference

Storefront routes

Route Method What it does
{base}/cart/restore GET Lists what a signed link would restore. Writes nothing
{base}/cart/restore POST Restores the cart, answers the challenge, or asks for a fresh link

Both answer Cache-Control: private, no-store, max-age=0, like every hash-addressed page on the storefront.

Admin routes

Route Permission MCP tool
GET /kahunacart/carts/abandoned kahunacart.orders.view abandoned_carts_list
POST /kahunacart/carts/{id}/recovery-email kahunacart.orders.manage abandoned_cart_send_recovery
POST /kahunacart/carts/{id}/link kahunacart.orders.manage cart_link_create
GET /kahunacart/reports/recovery kahunacart.orders.view report_recovery

There is no admin route that restores a cart. Restoring is the customer's own action behind their own link.

Templates

Template What it renders
kahunacart-restore.html.twig The restore confirmation page
emails/abandoned-cart.html.twig, .txt.twig The first message
emails/abandoned-cart-reminder.html.twig, .txt.twig The one reminder
emails/cart-share.html.twig, .txt.twig A shared cart

All four are theme-overridable in the usual way. See Theming.

  • Emails - every message the store sends, and the email log
  • Orders and the admin - the Recovery screen, the notice queue and the email log
  • Storefront - the restore page and the expired-link page
  • Configuration - every config key
  • CLI - the worker tick that does the sending
  • Events - the onKahunaCartCartRecovered event