Files

129 lines
7.2 KiB
Markdown
Raw Permalink Normal View History

# Cart/Checkout Recovery Strategies — Design Notes
**Status: open design discussion, not scoped or built.** This is a record of the
reasoning behind an eventual "Recovery Sequences" feature, kept so the discussion doesn't
have to be re-derived from scratch later. Nothing in this document is implemented.
See `docs/cart.md` for what's actually built today (the four-state cart classification,
`CartAbandoned`/`CheckoutAbandoned` events, `DetectAbandonedCarts`).
---
## Why Abandoned Cart and Abandoned Checkout need different strategies
Established in `docs/cart.md`: Abandoned Cart (no order ever started) is a weak purchase-intent
signal and often unreachable (no identity for a true guest). Abandoned Checkout (a draft order
exists, `placed_at IS NULL`) is a strong intent signal and usually reachable, since checkout
typically captures an email/address even for a guest.
That difference in intent and reachability drives genuinely different marketing strategy, not
just a different admin filter:
### Abandoned Cart strategy — re-engagement, not completion
- **On-site retargeting first** (exit-intent popups, "still thinking it over?" banners on
return visits) — often the only viable channel, since email may not exist yet.
- **Ad platform retargeting** (Meta/Google dynamic remarketing) is the dominant channel here
specifically because it works off a browser/device signal, not an email address — the one
thing reliably available for an anonymous cart.
- **Soft messaging** ("did you forget something?") rather than urgency-driven — intent is
weak, so aggressive discounting is often poor ROI: it trains browsers who were never close
to buying to expect a coupon.
- **Longer, gentler cadence** — a single reminder around 24h, maybe a second a few days out,
sometimes trigger-based (a price drop, back-in-stock) rather than a fixed schedule.
### Abandoned Checkout strategy — completion, not re-engagement
- **Speed matters most.** This is where the classic 1h/24h/72h recovery-email cadence lives —
conversion drops sharply with delay, since the shopper is often still in a "was about to
buy" mental state within the first hour.
- **Direct, urgency-framed messaging** ("complete your order"), sometimes showing cart
contents/total, occasionally a countdown or limited-time incentive on later touches.
- **Discount escalation pays off here** — a small incentive (free shipping, 10% off) on the
2nd/3rd touch is standard, because it's nudging someone who already decided to buy past
whatever blocked them (price shock, a broken payment step, indecision on shipping cost) —
not manufacturing demand from nothing.
- **SMS is more viable** — checkout often captures a phone number, and the higher intent
justifies a more direct channel than for cart-stage.
---
## The broader strategy space (beyond cadence + discount)
Raised as context for how far a "Recovery Sequence" feature might eventually need to flex,
without committing to building any of it yet:
**Message-content strategies**
- Social proof ("X people have this in their cart," reviews shown in the reminder)
- Scarcity/urgency framing (low-stock count, countdown timer on an offer)
- Personalized alternatives — a cheaper or complementary item instead of just re-showing the
abandoned one, useful when the likely blocker was price
**Channel strategies**
- Email (the baseline; nothing built yet — see `docs/cart.md`'s "Recovery Sequences" section)
- SMS — checkout-stage specifically, opt-in required
- Push notifications — not relevant yet given this project's storefront maturity, noted for
completeness
- On-site remarketing (banner/modal on the shopper's next visit) — doesn't require email at
all, arguably the highest-value channel for Abandoned Cart specifically
- Ad platform sync (pushing abandoned-cart product data to a custom audience for paid retargeting)
**Escalation/segmentation strategies**
- Value-based branching — a high-value abandoned checkout might skip straight to a bigger
incentive rather than waiting through a full ladder
- Repeat-abandoner suppression — a customer who's abandoned 3+ times without ever completing
either stops receiving emails (fatigue/spam risk) or gets a different tactic (e.g. a "what
stopped you?" survey) instead of another discount
- New vs. returning customer branching — a first-time visitor's abandoned cart might warrant
"welcome discount" framing instead of a generic recovery email, since the blocker was
likely trust/unfamiliarity rather than price
**Timing refinement**
- Time-of-day/timezone-aware sending (don't fire a touch at 3am local time even if the delay
technically elapsed)
- Cart-content-triggered timing — a fast-moving/low-stock item might warrant an earlier, more
urgent first touch than a cart of always-in-stock staples
---
## First-pass feature shape (discussed, not finalized)
An admin defines, independently per abandonment type (Abandoned Cart, Abandoned Checkout), an
ordered sequence of **touches**. Each touch is three ideas:
1. **How long to wait** since the abandonment began
2. **What offer to attach**, optional — reusing whatever `Discount` already exists in the
system rather than inventing a new pricing concept
3. **A label**, so staff can see what a touch represents in the admin UI
The system continuously re-evaluates every abandoned cart/checkout against its sequence, and
when a cart becomes due for the next touch it hasn't had yet, that becomes a signal — this
feature's responsibility ends there. Actually sending anything (email, SMS, on-site banner) is
explicitly out of scope for this feature; something else, not yet designed, would consume that
signal.
### What this requires that isn't built yet
- **A fixed "abandonment began at" timestamp**, captured once and never re-derived — a
sequence needs to schedule touches from a stable starting point, not from `Cart::updated_at`,
which keeps moving every time the cart (or its own bookkeeping) is written to. This is the
same underlying issue as the known bug in `docs/cart.md`'s "Abandonment detection" section —
fixing that bug properly (freezing the abandonment moment) is very likely a prerequisite for
this feature, not a separate concern.
- **Re-evaluation, not one-shot detection** — `DetectAbandonedCarts` today marks a cart
abandoned once and stops; a sequence needs a cart to be revisited on every scheduler run to
check "which touch, if any, is now due," for as long as it stays unrecovered.
### Still undecided
- **Which concern this belongs under.** Not `Cart` (it's not a cart-mechanics concern) —
candidates raised: a new `Recovery` concern, or `Marketing`. Not decided.
- **How far the touch model needs to flex.** The three-idea shape above (delay, discount,
label) covers cadence + discount escalation cleanly, but doesn't yet accommodate channel
choice, value-based branching, or segment targeting from the broader strategy list above.
Whether those get folded into the touch model, layered on top some other way, or deliberately
left out of v1 is unresolved.
- **Whether "recovery" is cart/checkout-specific at all**, or a more general "scheduled
customer touch based on a triggering condition" mechanism that cart/checkout abandonment
happens to be the first use case for.