Most beauty brands can tell you their ROAS by channel. Far fewer can tell you how many months a new customer takes to repay what you spent to acquire them. That number decides how fast you can grow on your own cash, and it is the one investors and lenders ask about first.
This guide builds CAC payback period for a physical product brand step by step. It uses the same $48 serum cohort as our LTV to CAC guide and the margin definitions from our contribution margin guide, so every number ties back to one model.
Month 3
Payback at a $40 CAC
Month 6
Payback at a $52 CAC
$74.30
12 month CM2 per customer
What is CAC payback period?
CAC payback period is the number of months it takes for a new customer cohort to return its acquisition cost in contribution margin. It is a time measure, not a ratio. Two brands can share an LTV to CAC ratio of 1.86 and have payback periods months apart, depending on when the repeat orders land.
Three definitions decide whether your payback number means anything:
- CAC is blended new customer acquisition cost: all paid spend aimed at acquisition divided by new customers, not one platform's reported cost per purchase. Our weighted CAC guide covers how to build it.
- Margin is CM2: price minus product cost, shipping, pick and pack and payment fees. Not revenue and not gross margin.
- Timing comes from a cohort table of real repeat orders by month, not an average monthly margin.
The CAC payback formula for a physical product
THE FORMULA
Payback = the first month where cumulative CM2 per customer ≥ CAC
Build it in three steps: compute CAC from blended new customer spend, compute CM2 per order, then add up CM2 month by month across the cohort until the running total covers CAC.
You will often see a simpler version: CAC divided by monthly margin per customer. That formula comes from subscription software, where revenue arrives in equal monthly amounts. Beauty margin is front loaded. The first order carries the most margin and reorders taper off, so the simple formula gets the answer wrong.
On the serum, 12 month CM2 is $74.30, or $6.19 a month on average. At a $40 CAC the simple formula says payback takes 6.5 months. The cohort says month 3. Using the shortcut would make a healthy acquisition program look twice as slow as it is.
One $48 serum cohort, month by month
The serum sells for $48. Product cost is $9.60, shipping and pick and pack $6.00 and payment fees $1.44, leaving $30.96 of CM2 per order (64.5%). For every 100 new customers, 60 reorder around month 3, 45 around month 6 and 35 around month 9, for 2.4 orders per customer in 12 months.
| Month | Orders per new customer | CM2 added | Cumulative CM2 | Cumulative gross margin |
|---|---|---|---|---|
| 0 (first order) | 1.00 | $30.96 | $30.96 | $38.40 |
| 3 | 0.60 | $18.58 | $49.54 | $61.44 |
| 6 | 0.45 | $13.93 | $63.47 | $78.72 |
| 9 | 0.35 | $10.84 | $74.30 | $92.16 |
Read across the cumulative CM2 column to find payback for any CAC:
- A CAC at or below $30.96 pays back on the first order.
- A $40 CAC leaves $9.04 open after the first order. The month 3 reorders clear it. Payback: month 3.
- A $52 CAC still has $2.46 open after month 3. Payback: month 6.
- A $70 CAC pays back in month 9.
- Above $74.30, the customer does not repay within 12 months.
A $12 increase in CAC, from $40 to $52, doubled the payback period. That step function is why payback deserves its own line in your reporting rather than living inside a ratio.
Gross margin payback hides months of cash
Build the same table on gross margin, which ignores shipping and fees, and payback looks faster. At a $52 CAC, gross margin shows payback in month 3 because $61.44 clears $52. CM2 shows month 6. At a $70 CAC, gross margin says month 6 and CM2 says month 9.
#block-yui_3_17_2_1_1793398986278_258048 { --opacity: 100%; --translate-x: 0px; --translate-y: 0px; --rotation: 0deg; --scale-x: 100%; --scale-y: 100%; --skew-x: 0deg; --skew-y: 0deg; --origin-x: 50%; --origin-y: 50%; --block-transform: none; opacity: var(--opacity, 1); transform: var(--block-transform); transform-origin: var(--origin-x) var(--origin-y); }