Each pull below runs on a Shopify order export. Each lists the columns, the steps, the output, and the bad reading: the result, or the misread, that should stop you. The export has one row per line item, so build one row per order first, with its date, customer and revenue. Export the full history; three years or more gives the day-365 reads enough customers.
Resolve identity first
One customer is one customer ID where you have one, then a normalized email (lowercase, trimmed), then a phone number in E.164 format. A split identity turns one returning customer into two one-time buyers, so every rate below comes out worse than the truth. Drop cancelled and fully refunded orders before you count anything.
An afternoon if your customer IDs are clean; a few days if they aren't. Resolve identity first either way.
Keep the result as a lookup from every raw email and phone to one resolved customer, and run all six pulls off it. Pick one revenue definition, such as Subtotal less refunds, and use it everywhere, so the pulls agree with each other. Label every table you hand back with the file, the date range and the n, because a table without them gets quoted as if it covered everything.
The customer file
- Orders per customerColumns: Email, Created at, Subtotal, Financial Status, Cancelled at, the refunded amount, and the customer's phone where you have it.
Steps: Group orders by resolved customer. For each, record order count, lifetime revenue and first order date. Bucket by order count, not by dollars: 1, 2, 3 to 5, 6 to 10, 11 and up. Frequency is where the two groups split; spend follows it.
Output: One order against two or more: customers, share of customers, revenue, share of revenue, and revenue per customer. Add a histogram of order counts.
Bad reading: A one-order bucket three or more times the size of the two-order bucket, reported as one blended average. That average describes almost nobody in the file.
- The step-upColumns: The customer table from the first pull.
Steps: Take customers with one order and customers with two orders and no more. Average lifetime revenue for each group. The step-up is the two-order average minus the one-order average. Multiply it by your count of one-time buyers and label the result a ceiling, since no program converts all of them.
Output: One dollar figure per converted customer, and the ceiling beside it.
Bad reading: A step-up taken against customers with two or more orders. Heavy buyers inflate it, and the prize looks bigger than one more order can deliver.
Value over time, and by entry product
- The cohort triangle and value curveColumns: Email, Created at, Subtotal, Financial Status.
Steps: Key each customer to the month of their first paid order and never move them. Use the order date, never an import or signup date, or a migrated file lands in one cohort. Count days from each customer's own first order. Bucket forward in 30-day windows. Fix each row's denominator at the cohort's starting size. Leave cells blank where the cohort is too young; a blank isn't a zero. Say whether cells show repeat inside the window or cumulative repeat. Compare down columns only.
Output: A triangle with an empty lower-right corner, plus cumulative revenue per acquired customer at day 30, 90 and 365 for the last full-year cohort, with the halfway day marked.
Bad reading: A full rectangle, or customer counts that grow as the window lengthens. That report is stacked calendar windows.
- Repeat rate by first productColumns: Email, Created at, Lineitem name, Lineitem sku, Subtotal.
Steps: Find each customer's first order. If it holds several items, name it by the highest-priced line and treat a kit as its own product. Collapse SKUs into classes, shades together and sizes apart, because size can be the whole finding. Count customers per class; that count is n. Mark who ordered again within 365 days, using only customers whose first order is that old. Add the Wilson interval. Day-365 value is revenue per customer across the first year, first order included.
Output: One row per first product: n, repeat rate, interval and day-365 value, sorted by n.
Bad reading: A high-volume entry product returning a fraction of the rows beside it, with intervals that don't overlap.
Reorder gaps and the top of the file
- First-to-second gap by first productColumns: Email, Created at, Lineitem name, Lineitem sku.
Steps: Keep customers whose first order is at least a year old and who placed a second. Take the days between order one and order two, and ignore later orders, which run on a different clock. Group by first product. Take the median, never the mean, and the 25th and 75th percentiles. Under about 50 repeaters, use the product class.
Output: Per product: repeaters, median, and the 25th and 75th percentiles. The median times the reorder touches; the 75th sets the earliest winback.
Bad reading: One median for the whole catalog, or a median well past the label while the reminder still fires on the label.
- Top-customer thresholdsColumns: The customer table from the first pull.
Steps: Sort customers by lifetime revenue, descending. Add a row number, a percentile (row number over total customers) and a running share of revenue. Read the lifetime revenue at the top 1%, 10% and 20%. Add trailing-twelve-month revenue beside it, since a lifetime floor never drops a customer who stopped buying.
Output: Three dollar floors and the revenue share above each. Build each as a segment on lifetime revenue at or above the floor, and recompute monthly.
Bad reading: A top tier with fewer names than expected. Split identities have turned top customers into pairs of mid-tier ones.
The Wilson cell
Put conversions in B2 and n in C2, then paste these two cells beside the rate. The Wilson interval stays between zero and one hundred percent and holds up at low rates and small samples, where the textbook plus-or-minus interval breaks.
| Bound | Formula |
| Lower | =((B2/C2)+1.96^2/(2*C2)-1.96*SQRT((B2/C2)*(1-B2/C2)/C2+1.96^2/(4*C2^2)))/(1+1.96^2/C2) |
| Upper | =((B2/C2)+1.96^2/(2*C2)+1.96*SQRT((B2/C2)*(1-B2/C2)/C2+1.96^2/(4*C2^2)))/(1+1.96^2/C2) |
Format both cells as percentages. Check: 9 of 476 gives about 1.0% to 3.6%. If yours doesn't, look for a missing bracket before you trust any interval it prints.
Read the width as the resolution of the file. Two rows whose intervals overlap haven't been told apart, whatever their rates say. Two rows whose intervals sit well apart have, even at a few hundred customers each, because a large gap shows through a small sample.
Small-file rules
These are rules of thumb. Each one guards against reading noise as a result. A small file still shows large gaps, so a thin read has value, but it can't carry a fine distinction. When a read fails its rule, report it as a lead with its n beside it, then widen the window or roll up the class until it passes.
| Read | Rule of thumb |
| A product's reorder-gap median | About 50 repeaters. Below that, use the product class. |
| A test or holdout cell | 10 or more expected conversions, per the Single-Digit Stop. |
| A weekly cohort line | A few hundred first orders a week. Otherwise, read monthly. |
| A low-volume SKU's reorder gap | Roll it up to its product class. |
| A rate | Print its n. Under 300, print its interval too. |
Re-run the first-product and gap pulls every quarter, and date each run. Pack sizes change, a subscription option shifts the mix, and a customer who switches products starts a new clock. A median measured in January is a hypothesis by June. Recompute the top-customer floors monthly, because they drift as the base grows, and a stale floor changes who's in the tier without anyone deciding it.