Skip to contact form
← BlogEngineeringAugust 17, 2026 · 4 min read

Our funnel was counting backwards

Nine boxes across the top of a dashboard, each showing the number of people who got that far and stopped — arranged to look like a funnel.

he engagement page opened with nine boxes: emailed, opened, mockup sent, mockup opened, replied, and so on down to won. Every box had a number in it. Arranged left to right and narrowing, it read as a funnel, and everybody who looked at it read it as one.

It was not a funnel. Each box counted the leads whose furthest progress was that step — in other words, the people who got that far and then stopped. “Opened: 17” did not mean seventeen people opened the email. It meant seventeen people opened it and never did anything else.

Thenumbereverybodywantedhowmanyeveropenedanythingwasnotonthepageatall.

On a seeded book of ninety-one leads the gap was not subtle. The box said six mockups sent when twenty had gone out. It said seventeen opened when thirty-nine had. Every figure was correct; every figure answered a question nobody was asking, in a layout that promised the other one.

The fix is to carry both numbers, which is easy. The part that needed care was the wording, because a stage needs two different sentences depending on which number you are showing. “Emailed, silent” is a fair description of a lead parked at that step, and a false one over everyone who was ever emailed — it sat above seventy-seven on a book where thirty-nine had opened something.

So each stage has a second label for its reach figure. No test would have caught that; it was caught by looking at a screenshot and reading the words out loud.

Drop-off is only shown between pairs where one set genuinely contains the other. A mockup can go to somebody who never opened the cold email, so “opened → mockup sent” is not a funnel step and printing a percentage there produces numbers above a hundred percent, or worse, numbers just under it that look plausible.

Those pairs stay blank. A blank space invites the question “why is there nothing here”, which has a good answer. A wrong percentage invites no question at all.

There is a script that renders the page against a real build, reads the figures back out of the rendered markup, and compares each one to a fresh call to the API behind it. It fails on any mismatch — and it also fails if reach ever equals stalled at every single step, because that is exactly what showing the old number twice would look like.

Want this kind of thinking on your project?

This is how we work through real decisions. If you're weighing a build of your own, tell us about it — we reply within one working day.