I sent you this chapter. Reply on LinkedIn or by email.
The fields an offer needs, and five pulls that build every table in this book.
Every pull below runs on an orders table, an order-lines table and a customers table. Resolve identity first: customer ID, then normalized email, then phone. A customer who checked out as a guest and later made an account is one customer, and counting them twice turns a repeat buyer into two one-timers.
| Field | On | Written when | Rule |
|---|---|---|---|
first_order_at | Customer | First paid order | Set once, never overwritten |
first_offer | Customer | First paid order | The offer that won them: code, landing page or campaign, mapped to your offer list |
first_products | Customer | First paid order | Product IDs in the first order |
first_discount_pct | Customer | First paid order | Discount as a share of the full-price subtotal |
holdout_digit | Customer or visitor | Profile creation | Random 0 to 9, set once, never recomputed |
existing_customer_at_order | Order | Every order | True if the customer had a prior paid order; used to count cannibalized codes |
-- first products and what their buyers did next
WITH firsts AS (
SELECT customer_id, MIN(ordered_at) AS first_at
FROM orders WHERE status = 'paid'
GROUP BY customer_id
HAVING MIN(ordered_at) <= CURRENT_DATE - 180
),
first_lines AS (
SELECT f.customer_id, l.product_id
FROM firsts f
JOIN orders o ON o.customer_id = f.customer_id AND o.ordered_at = f.first_at
JOIN order_lines l ON l.order_id = o.order_id
),
after AS (
SELECT f.customer_id,
COUNT(o.order_id) FILTER (WHERE o.ordered_at > f.first_at
AND o.ordered_at <= f.first_at + 180) AS reorders,
SUM(o.net_revenue) FILTER (WHERE o.ordered_at <= f.first_at + 180) AS rev_180
FROM firsts f JOIN orders o ON o.customer_id = f.customer_id
WHERE o.status = 'paid'
GROUP BY f.customer_id
)
SELECT fl.product_id,
COUNT(DISTINCT fl.customer_id) AS first_orders,
AVG((a.reorders > 0)::int) AS reorder_rate_180,
AVG(a.rev_180) AS revenue_180
FROM first_lines fl JOIN after a USING (customer_id)
GROUP BY fl.product_id
ORDER BY first_orders DESC;
A customer whose first order contains two products counts toward both. That’s intended: you want to know what each door leads to. For a clean split, rerun it on single-product first orders only and compare.
Want to answer the note that sent you here? Reply on LinkedIn or by email.
If this is your store
The free Klaviyo audit reads your own account and scores it. Start with your store’s address. A read-only key gets the full report.
Written by Andrew Lauchner, a growth and retention operator for consumer brands. The paid work is one ninety-day Sprint.
This is one chapter of The First Offer, which is free and readable in full on a single page with no form in front of it.