What is repeat purchase rate, and how do you measure it in Metabase?
Repeat purchase rate (RPR) is the share of customers who buy more than once. It's the clearest signal of retention and loyalty in a store, and the foundation of customer lifetime value: acquiring customers is expensive, so a healthy repeat rate is what makes the economics work. Measure it in Metabase from store data synced into a database (Shopify, WooCommerce, or Klaviyo).
How is repeat purchase rate calculated?
Over a chosen window, RPR = the number of customers with more than one order ÷ the total number of customers who ordered. Two refinements matter:
- Cohort it — group customers by their first-order month. A blended rate mixes seasoned customers with new ones who simply haven't returned yet.
- Fix the window — "repeat within 90 days" is more actionable than an all-time rate that only ever goes up.
What data does repeat purchase rate need?
- An orders table with a stable
customer_idandcreated_at. - A financial/payment status so unpaid or cancelled orders don't count.
- A reliable identity — dedupe guest checkouts by email so one person isn't counted as several first-time buyers.
SQL patterns
Share of paying customers with more than one order.
-- Repeat purchase rate: share of customers with more than one paid order.
WITH per_customer AS (
SELECT
o.customer_id,
COUNT(*) AS orders
FROM orders o
WHERE o.financial_status = 'paid'
GROUP BY o.customer_id
)
SELECT
COUNT(*) AS customers,
COUNT(*) FILTER (WHERE orders > 1) AS repeat_customers,
ROUND(100.0 * COUNT(*) FILTER (WHERE orders > 1)
/ NULLIF(COUNT(*), 0), 1) AS repeat_purchase_rate_pct
FROM per_customer;Group customers by first-order month so maturity is comparable.
-- Repeat rate by first-order month (acquisition cohort).
WITH first_order AS (
SELECT customer_id, MIN(created_at) AS first_at
FROM orders WHERE financial_status = 'paid'
GROUP BY customer_id
),
orders_per_customer AS (
SELECT customer_id, COUNT(*) AS orders
FROM orders WHERE financial_status = 'paid'
GROUP BY customer_id
)
SELECT
date_trunc('month', f.first_at) AS cohort_month,
COUNT(*) AS customers,
ROUND(100.0 * COUNT(*) FILTER (WHERE o.orders > 1)
/ NULLIF(COUNT(*), 0), 1) AS repeat_rate_pct
FROM first_order f
JOIN orders_per_customer o ON o.customer_id = f.customer_id
GROUP BY date_trunc('month', f.first_at)
ORDER BY cohort_month;Pitfalls
Where this metric applies
- Shopify + Metabase — orders keyed by customer, with financial status
- WooCommerce + Metabase — order history per customer in WordPress
- Klaviyo + Metabase — order events and customer profiles for retention flows