Your funnel's daily counts are not a conversion rate
A lead recorded today may come from a visit yesterday. How Tokenwise separates UTC event counts, missing data and operator checks—and what founders can learn from a small, real production sample.

A dashboard shows visits in one column and leads in another. Dividing the second by the first looks like an obvious way to measure conversion. It only works if the two columns describe the same group of visitors over a suitable period.
Tokenwise's landing counter records events by the day the server receives them. It does not follow a daily group of visitors from their first visit to a completed action. We made that distinction explicit in the storage and the founder dashboard. Here is the implementation, the production evidence and what a builder can reuse.
The problem: a lead can arrive on a different day
Consider an illustrative example, not a customer result. A browser opens your landing page on Monday, returns on Tuesday and submits a brief. Its exposure belongs to Monday's recorded events; its later action belongs to Tuesday's. Dividing Tuesday's actions by Tuesday's exposures mixes different groups.
Tokenwise's client remembers which funnel events it has already sent in browser storage, across reloads and UTC dates. A return visit therefore does not necessarily create another exposure. Clearing storage or using another browser can change that behaviour. These are recorded browser events, not authenticated unique people.
What we implemented
The counter has five stages: the landing rendered, a start-project button was pressed, the project chat received an answer, an idea and email were saved, and a brief was queued for a prototype build. The final stage means queued, not successfully built, adopted or paid for.
The server captures receipt time and chooses the UTC date. Clients cannot choose the date or arbitrary event names. One database transaction increments both the lifetime total and the matching daily bucket. If that transaction fails, neither increment commits.
The founder view keeps lifetime totals separate from daily rows. It reads seven completed UTC dates plus today. Today and the first recorded day are marked partial. A missing bucket stays unavailable; it is not filled with an invented zero. A stored bucket can contain an explicit zero for an event that was not recorded in it.
The daily view displays counts without calculating daily conversion percentages. Lifetime event-to-exposure ratios remain labelled as recorded-event ratios, not proof of a winning funnel or a conversion uplift.
A small production sample, with boundaries
We read the live aggregate documents on 12 October 2026 at 08:55 UTC. The current chat counter's first recorded day was 9 October. These are its stored receipt-day counts:
| UTC date | Exposure | CTA | Chat answer | Lead saved | Brief queued |
|---|---|---|---|---|---|
| 9 October — first day, partial | 1 | 1 | 1 | 1 | 1 |
| 10 October | 1 | 1 | 1 | 0 | 0 |
| 11 October | 6 | 0 | 0 | 0 | 0 |
| 12 October — partial at the read | 2 | 0 | 0 | 0 | 0 |
The 8 October bucket is absent for this counter and remains unavailable. The stored rows sum to the lifetime totals at that read: 10 exposure events, two CTA events, two answers, one saved lead and one queued brief.
That is evidence that these aggregate records exist and agree at the read time. It does not establish ten people, an external customer, a sale or a conversion rate. Historical operator checks remain included; the earlier wizard-versus-chat experiment is separate and frozen. This small sample cannot demonstrate that a design change improved growth.
Keep your own checks out of future measurements
On 11 October we added two controls. A browser where the founder signs in stores an exclusion flag and stops sending future funnel events. QA links with an ab query parameter and automated test browsers also skip counting. The exclusion flag applies to that origin and browser; it does not identify the founder on a new device before sign-in or remove historical events.
Exposure events can also carry a coarse source such as Facebook, Instagram or search. The client derives it from utm_source, when present, or the referrer host. Only an allowed bucket name reaches the counter, not the full URL. Source buckets describe exposures; they do not attribute subsequent leads to a channel. Missing referrers can appear as direct traffic, and older clients can send exposures without a source.
Lessons and limits worth carrying into your app
Write down what each event means before putting it on a dashboard. A queued build and a finished build answer different questions. A recorded exposure and a person are different measurements too.
Keep unknown, partial and zero separate. Store the date in one timezone, and explain which clock chooses it. Preserve old measurement periods when the product changes instead of joining incompatible totals.
If you need conversion for a group that first arrived in a particular period, you need a measurement design that follows that group through later actions, with an appropriate consent and data-handling policy. Daily aggregate counters alone cannot reconstruct it.
Our counter intentionally stores aggregate dates and counts, without per-hit identities, emails, ideas, IPs or full referrer URLs. The endpoint uses an IP only for an in-memory rate limiter. Delivery is best effort: blocked storage can weaken deduplication, requests can be dropped or throttled, and an HTTP 204 response alone does not prove a database write. These records are useful diagnostic signals with limits, not a complete analytics system.
Want an app where the dashboard's numbers have clear definitions? Describe your app on Tokenwise to start the project chat.
Implementation checked against factory-web revision 4741b240b47ccc1b2148ed5595b6bac2e7407fff, including the UTC aggregate writer, browser deduplication and source/exclusion changes. The public measurement revision identifies the deployed implementation. Production figures above are a dated snapshot, not live counters. Text prepared with AI from verified code and aggregate data. Illustration generated with AI.