What we found when we tried to build an honest ROI model
Every vendor selling into post-purchase has an ROI number. Almost none will show you the arithmetic. We built ours, published every formula, and found out how little of the data you need actually exists.
Ask a platform vendor what you’ll save by buying their product, and you’ll get a number. It will be large, flattering, and probably wrong — not because they’re lying, but because the incentives of a sales conversation push every number in one direction. Nobody wins a deal by telling the buyer their case is softer than they thought.
We took the opposite approach. We built a public ROI model for Hantera_ — one you can change, argue with, and forward to your CFO — and made the arithmetic the product. Every formula is on the page. Every default is sourced, with a confidence chip that says whether it’s yours, ours, or published. And when we went looking for the data to back it all up, we found something we didn’t expect: almost none of it exists in a form you can cite.
This is the story of building it — the modelling decisions, the data we could and couldn’t find, and the things we got wrong along the way.
The problem with a single ROI number
A single figure is a decision about how much softness to hide. If your retention estimate is generous and your cost estimate is conservative, the number flatters you. If you reverse both, it buries you. Neither is honest — and nobody reading it knows which one you did.
So we built the model as a three-point span instead. Each point is the one before it plus a term you should trust less:
- Conservative — operations only. The failures you prevent, and the money you genuinely stop spending on putting them right. Invoice-adjacent. The end we’d defend in a board meeting.
- Balanced — plus the contribution margin on customers you keep who would otherwise have left. What we’d actually plan on.
- Full — plus the replacement cost you avoid by not having to acquire a new customer for every one you lose. Striped, and never the headline.
Because each model is strictly the one above it plus one new term, the span is monotonic by construction — it can’t be gamed by reordering. And where the left end sits tells the reader how much of the case is money they can see on an invoice, versus an estimate they’ll need to defend.
At defaults, that’s €105k on the left, €295k on the right. The share of the Full figure that is hard operational money? 36%. That number — the fraction of your own case that doesn’t depend on a retention guess — is probably the single most useful thing the model prints.
Six choices that made the number smaller
If we wanted a bigger headline, we could have done any of these differently. We wrote down why we didn’t, because the alternatives are what most vendor ROI models actually do.
Margin, not revenue. A lost €80 order is not €80 of lost profit. Everything on the retention side runs through contribution margin — the money an order contributes after cost of goods and shipping. That roughly halves the number we could otherwise have printed, and it’s the number a CFO will ask for.
Forward-looking lifetime only. The order a departing customer had already placed is revenue you’ve already had. We count only the orders they would have placed from here on. The CLV in the model isn’t the one you’ve banked — it’s the one you’re about to lose.
The churn figure, halved. More on this below. It’s the single most important number in the entire model, and every published version of it disagrees.
CAC excluded from the headline. Acquiring a replacement customer costs five to twenty-five times what keeping one costs, per published research. That’s a real number — but only if you’d genuinely have gone out and bought the replacement. Plenty of teams simply run smaller instead. So the replacement cost lives in the Full point only, where it’s visibly striped and never moves the floor.
Two zeroable effectiveness sliders. The share of failures we prevent, and the share of angry customers we keep through recovery, are our estimates — the softest things on the page. Both can be set to zero, at which point the model shows you the cost of doing nothing — and admits it. A model that can be made to say it doesn’t work is a model worth reading.
One rule for every cost. An earlier draft asked whether your support capacity was variable — fixed teams would see prevented status enquiries as freed hours rather than money. That looked like honesty. But the cost of putting a failure right already includes agent time, and we had never zeroed that. The toggle was an exception applied to the smaller pool, not a principle. So we dropped it: every cost figure on the page is a fully-loaded number you give us, and we count it. No second-guessing your labour rate.
What we found when we went looking for data
The model needs inputs. Your order volume, your margin, your failure rate — those are yours to type. But the defaults are ours, and the defaults are where the credibility lives or dies.
A single example. The share of customers who stop buying after one bad experience is probably the most important input in the entire model, because it determines how much of the case is retention rather than operations. Here are three published figures, side by side:
~32% — consumer research, brands people say they love. Survey of stated intent. 84% — a delivery vendor’s blog, European shoppers, “would stop buying completely.” No methodology or sample published. 15% — what we use. Less than half the lower published figure.
A spread that wide isn’t a rounding difference. It’s the evidence. Every one of those numbers is an answer to a survey question, and people abandon brands far less often than they say they will — particularly when the alternative is inconvenient. So we start below the bottom of the published range, say plainly that it’s a practitioner estimate, and leave the field where you can overwrite it.
If we’d used the 84% figure, the retention half of the model would be roughly five times larger. It would also be the easiest claim on the page to demolish, and we’d deserve it.
This pattern repeated everywhere we looked. Every compelling data point had the same problem: it was published by a vendor, quoted another vendor, or measured stated intent rather than observed behaviour. “Where is my order?” queries account for up to 50% of support calls — but that’s the peak-season spike in the source, not the average. The $5–$12 cost to handle one comes from a blog post that cites MetricNet service-desk benchmarking — traced through three vendor pages, none of them the original study. “Nearly 40% of UK retailers fail to meet their delivery times” turned out to mean 40% of retailers, not 40% of orders — a different denominator that makes it useless as a failure rate.
We shipped with what we could verify, labelled everything that isn’t audited, and wrote down in the method section exactly which sources are primary research and which are a chain of citations. The page itself tells you where it’s weak.
Three numbers we were offered, and left out
A vendor in this space is expected to produce a Forrester-style “167% ROI, payback under six months” figure. Those come from analyst studies commissioned by other vendors about their own products. On our page it would read as though it were ours, which it isn’t. We left it out.
Along with it: “up to 95% less manual data entry” (no method published, nothing to check), “repeat buyers spend 67% more” (blogs citing blogs, and the model doesn’t need it — your own repeat rate already carries that weight), and the 84% figure mentioned above (vendor-published intent with no methodology — we showed it in the churn spread as evidence that intent figures can’t be used raw).
These aren’t wrong. Some of them are probably true. But if we can’t show you the arithmetic, we’re not going to print the figure — and every one of those would have made our number bigger.
Making it printable
The model is a form, and a form is useless on paper. So printing /roi doesn’t print the widget — it prints a two-page A4 summary: the answer, your own inputs, and where every number came from. The ink bands turn white, the nav disappears, URLs are spelled out after every link, and nothing splits across a page break. Browser-native “Save as PDF” produces better typography than any JS library would, and keeps the text selectable.
The sheet carries the live model’s URL and hash, so the recipient can open the exact configuration and change it. A board member who wasn’t at the meeting can arrive at the same page with the same numbers. That turned out to matter more than we thought — the people who need to see the model are rarely the people standing at the whiteboard.
What we’d do differently
If we started again, we’d do three things in the opposite order. Source-first: find the data, publish what’s verifiable, throw out what isn’t, and then build the model that fits the evidence. Model-second: the arithmetic is the last thing to write, not the first. Implementation-third: the page gets built once the first two are solid. We did implementation first, model second, and source-hunting last — which meant we built a model for inputs we couldn’t find, and then had to unwind assumptions that didn’t survive. The result is honest, but the path was backwards.
The invitation
The model is live at /roi. Change anything. Set our effectiveness sliders to zero and watch the answer become “doesn’t pay for itself.” The page is willing to tell you no — we’d rather you had that answer here than three months into a project.
If you have better data than we do — your own failure rate, your own cost to put one right, an audited study — bring it. If you catch us counting something twice or missing something entirely, tell us. The number on the page changes when the evidence does, and we’ll say so.
Nothing you type leaves your browser. There’s no form, no gate, and no lead capture. The model itself is the whole point.
Hantera_ connects everything after the buy button — orders, fulfillment, returns, and service — in one platform. See pricing →