TEASEDocs
ProductsLinkSmart links & ads

Record ad spend and see ROI

Turn a link's revenue into profit, ROI, ROAS, and CPA by giving it a cost model.

A link's revenue is tracked automatically. Its cost is not — you tell the system what you're spending, and the Performance card pairs the two into a bottom line.

Set the cost

POST /api/admin/links/cost:

FieldNotes
link_keyThe cost_key the list row carried.
cost_modelflat, cpc, cpa, or cpm.
amount_centsUsed by flat — a lump sum for the window, not prorated.
rate_centsUsed by cpc / cpa / cpm.
platform, period_start, period_end, noteBookkeeping fields.

This upserts one spend row per (link, platform, period_start) — posting again for the same slot updates it rather than adding a duplicate.

How each model prices the window

ModelCost
flatamount_cents, clamped ≥ 0.
cpcrate_cents × clicks
cparate_cents × subscribers (acquisition = a new subscriber)
cpmround(rate_cents × impressions / 1000)

An unrecognized model contributes 0 cost.

What comes out

MetricFormulaNone when
profit_centsrevenue − costnever — see below
roi_pct(revenue − cost) / cost × 100cost == 0
roas_bpsrevenue / cost × 10000 (basis points; divide by 100 for a "×" figure)cost == 0
cpc_centscost / clicksclicks == 0
cpa_centscost / subscribers (the realised CAC — not the cpa input rate)subscribers == 0
epc_centsrevenue / clicksclicks == 0
margin_pctprofit / revenue × 100revenue == 0

profit_cents is deliberately not clamped at zero. When ad spend exceeds revenue, profit is negative — the system shows you the real loss instead of hiding it at "$0".

has_cost is true only once cost_cents > 0 — that's the flag the panel uses to light up ROI at all, instead of showing "0%" for a link nobody has priced yet.

What's next

If ROI stays stuck on "needs a price" after setting a cost, see Troubleshooting.

On this page