Metric · E-commerce

What is cart abandonment rate, and how do you measure it in Metabase?

Cart abandonment rate is the share of shopping journeys that start — a cart created, a checkout begun — but never end in an order. It's the inverse of conversion rate viewed up close: instead of one blended number, it tells you at which step, on which device, buyers give up. Measure it in Metabase from checkout event data synced into a database alongside orders from Shopify, WooCommerce, or Medusa.

TL;DR — abandonment = journeys started without an order ÷ journeys started. Define the stage first: cart abandonment starts at cart_created, checkout abandonment at checkout_started. Around 70% is normal for carts — trend and segments beat the level.

How is cart abandonment rate calculated?

Abandoned journeys ÷ journeys started, per period. The definition work is in picking the funnel stage:

  • Cart abandonment — carts created that never reach checkout. Wide funnel, noisy: includes window-shoppers and shipping-cost checkers.
  • Checkout abandonment — checkouts started that never complete. Narrow funnel, high intent: this is where payment friction, surprise costs, and forced account creation show up.
  • Session rollup — group events by session or cart ID and flag whether an order_completed event ever arrived, within a cutoff window so yesterday's sessions aren't counted as abandoned prematurely.

What data does cart abandonment rate need?

  • Event data, not just orders: cart_created, checkout_started, order_completed with timestamps.
  • A shared session_id or cart_id tying a journey's events together.
  • Device, checkout step, and channel attributes for segmentation — the level is rarely actionable, the breakdown usually is.
  • Bot filtering upstream, or crawler traffic will inflate the rate.

SQL patterns

Monthly checkout abandonmentPostgreSQL

Sessions rolled up from a checkout_events model, abandoned share by month.

-- Monthly checkout abandonment: sessions that started checkout
-- but never produced a completed order.
WITH checkout_sessions AS (
  SELECT
    session_id,
    MIN(occurred_at)                                AS started_at,
    BOOL_OR(event_name = 'order_completed')         AS completed
  FROM checkout_events
  GROUP BY session_id
  HAVING BOOL_OR(event_name = 'checkout_started')
)
SELECT
  date_trunc('month', started_at)                   AS month,
  COUNT(*)                                          AS checkouts_started,
  COUNT(*) FILTER (WHERE NOT completed)             AS abandoned,
  ROUND(100.0 * COUNT(*) FILTER (WHERE NOT completed)
        / NULLIF(COUNT(*), 0), 1)                   AS abandonment_rate_pct
FROM checkout_sessions
-- Only judge a session once it has had time to convert. A checkout that
-- started 10 minutes ago isn't abandoned -- it's still in progress. The
-- maturity window (tune to your funnel) keeps the current month honest.
WHERE completed OR started_at < NOW() - INTERVAL '3 hours'
GROUP BY date_trunc('month', started_at)
ORDER BY month;
Abandonment by device and stepPostgreSQL

Find the step where each device's checkouts actually die.

-- Where checkouts die: abandonment by device and the furthest
-- step each session reached, over the last 30 days.
WITH checkout_sessions AS (
  SELECT
    session_id,
    MAX(device_type)                                AS device_type,
    MAX(step_number)                                AS furthest_step,
    BOOL_OR(event_name = 'order_completed')         AS completed
  FROM checkout_events
  WHERE occurred_at >= CURRENT_DATE - INTERVAL '30 days'
  GROUP BY session_id
  HAVING BOOL_OR(event_name = 'checkout_started')
)
SELECT
  device_type,
  furthest_step,
  COUNT(*)                                          AS sessions,
  ROUND(100.0 * COUNT(*) FILTER (WHERE NOT completed)
        / NULLIF(COUNT(*), 0), 1)                   AS abandonment_rate_pct
FROM checkout_sessions
GROUP BY device_type, furthest_step
ORDER BY device_type, furthest_step;

Pitfalls

Mixing cart and checkout abandonment in one number.→ They are different funnel stages with different fixes — merchandising for carts, friction for checkout. Define the stage in the card title and keep the two rates separate.
Deriving abandonment from order data alone.→ Orders can't see the people who left. Without checkout_startedevents you have no denominator, only completions.
Treating the ~70% benchmark as an emergency.→ High absolute abandonment is the industry norm. Chase the trend, the post-release delta, and the device gap instead of the headline level.
Folding recovered carts back into the base rate.→ Recovery emails are a separate funnel. Netting them out hides checkout friction behind email performance and makes the metric impossible to interpret.

Where this metric applies

Analytics

Metrics

FAQ

Cart abandonment or checkout abandonment — which should I track?
Both, as separate numbers. Cart abandonment (carts created that never reach checkout) measures merchandising intent — people parking items, comparing, or checking shipping costs. Checkout abandonment (checkouts started that never complete) measures friction in your payment flow, which is where fixes pay back fastest. Blending them into one rate makes both undiagnosable; a conversion funnel dashboard shows each stage with its own drop-off.
What's a normal cart abandonment rate?
Around 70% of carts are abandoned across the industry, so a high absolute number is not by itself a crisis. What matters is your trend and your segments: a rate that jumps after a checkout change, or a mobile rate far above desktop, is actionable in a way the level never is. Watch it next to conversion rate so you can tell a funnel problem from a traffic-mix shift.
Can I calculate abandonment from my orders table?
No — orders only record the people who finished. Abandonment needs the denominator of attempts, which means event data: cart_created, checkout_started, and order_completed with a shared session or cart ID. That comes from your platform's event exports or a tracking pipeline landing in your warehouse, synced alongside order data from Shopify or WooCommerce.
How should I measure cart recovery emails?
As their own funnel, separate from the base abandonment rate: recovered carts ÷ recovery messages sent. If you subtract recovered orders from the abandonment numerator, the metric stops describing checkout friction and starts describing your email program, and you can no longer tell whether an improvement came from a better checkout or a better discount code. Keep the base rate pure and report recovery revenue alongside it.
How do you track cart abandonment in Metabase?
Land checkout events in a SQL database — via your platform's event export or a pipeline like Airbyte or Fivetran — with one row per event carrying a session ID, event name, and timestamp. Roll sessions up with BOOL_OR flags for started and completed, chart the monthly rate, and add device and step breakdowns next to your sales dashboard so revenue and funnel health travel together.