Why “Time Spent Reading” Is Usually Wrong — and How to Measure It Honestly
“Read for 6 minutes” is the most persuasive number on any document analytics screen. It is also the easiest one to compute wrongly, and the way it is usually computed wrongly makes it look better than the truth rather than worse.
This is a piece about method. If you are buying a tool, it is a list of questions to ask. If you are building one, it is the set of mistakes that are cheap to avoid at the start and expensive to unpick later.
The wall-clock mistake
The obvious implementation is to record the moment the document opened, record the moment it closed, and subtract. It is one line of code and it is wrong in a specific, unbounded way.
Somebody opens your proposal at 10:00, reads for ninety seconds, and goes to lunch with the tab still open. They close the browser at 10:47. Wall clock says forty-seven minutes. You now believe your proposal held somebody’s attention for the better part of an hour, and you will make a different phone call because of it.
What makes this particular error so corrosive is that it only goes one way. Errors that scatter in both directions average out across enough sessions and you can still see a trend. This one only ever exaggerates, so the average is inflated too, and the longest, most flattering readings in your data are the ones most likely to be pure idle time.
The four moments the browser stops telling you anything
Any honest design starts from an inventory of the ways the signal disappears while the document is still, technically, open:
- The background tab. The document is loaded, the reader is in a spreadsheet, and nothing distinguishes this from reading unless you check.
- The suspended machine. A closed laptop lid or a phone in a pocket freezes everything, including any timer you started. When it wakes, the clock has moved and the reader has not.
- The departure with no goodbye. A crash, a killed tab, a lost network, a phone that ran out of battery. There is no event to hang an ending on, so a naive system leaves the session open forever.
- The reload. The reader presses refresh. Your code sees a departure immediately followed by an arrival, and unless you handle it, one eight-minute read becomes two four-minute ones.
The method: measure in slices, not in spans
The fix is to stop treating a reading session as a span with two ends, and start treating it as a sum of small confirmed slices.
While the document is visible on screen, the browser sends a periodic signal. Each signal adds the time since the previous one to a running total. Nothing is ever computed by subtracting a start time from an end time, so there is no single arithmetic operation anywhere in the system capable of crediting a lunch break.
Three details decide whether this works or merely looks like it works.
Rule 1 — a gap that is too long is credited as nothing
When a signal arrives after a suspiciously long silence, the tempting thing is to add the silence anyway, or to add some fraction of it. Both are guesses dressed as measurements.
The correct answer for a period you cannot account for is zero. Not “probably a bit”, not “half”. If you cannot show somebody was there, the number you have earned is nothing. This single decision is what makes a background tab cost you nothing instead of everything.
Rule 2 — the cutoff is a multiple of your sampling interval, not equal to it
If you sample every N seconds, the cutoff for “too long” cannot also be N. A single dropped signal on a slow connection already puts the next one at 2N, and if your cutoff is N you will shave real reading time off everybody with poor wifi — systematically, and only from the readers least able to notice.
Set it high enough to absorb two consecutive misses and no higher. Too tight and you undercount slow connections; too generous and a background tab starts earning credit again. The number itself is a consequence of your sampling rate, so derive it rather than picking it.
Rule 3 — round each slice, do not floor it
Every slice will have a sub-second remainder. Discard it and you lose a fraction on every single sample, in the same direction, for the entire length of the read — so a long session drifts measurably short while a short one is unaffected. Rounding leaves an error that averages to zero across samples instead of accumulating.
It is a small thing that becomes a large thing at exactly the length of read you most want to be accurate about.
Abandonment: end it where they left, not where you noticed
Sessions that end without a goodbye have to be closed by something that sweeps up after them. The question is what timestamp that sweep writes.
If it writes the moment the sweep ran, the recorded length of a read depends on how often your cleanup job happens to run — a number about your infrastructure wearing the costume of a number about your reader. Change the schedule and every historical figure means something different.
The right answer is to close the session at the last moment you had confirmation the reader was present, and to credit nothing for the silence afterwards. The reader gets the time you can prove and not a second more.
The reload, and the session window
A reload is a departure followed immediately by an arrival by the same reader on the same document. Treating it as two visits does two kinds of damage: it doubles your visit count and it halves your average reading time, which is the worst possible pair of errors to make together, because the second one hides the first.
The fix is to continue rather than restart when the same reader comes back within a session window. That raises the question of how long the window should be — and this is one of the rare cases where the right move is to take the convention rather than reason from first principles.
Thirty minutes has been the default session timeout in web analytics since the log-analysis work of the 1990s, and it is what Google Analytics, Adobe Analytics, Matomo and Snowplow all inherit. Your customer will eventually compare your “visits” to a visits number from one of those. If you invent your own window, the two figures are not comparable and nobody will be able to tell you why.
Say exactly what you measure
The last mistake is a copywriting one, and it is the most common. “Reading time stops when they look away” is a claim about attention. Almost nothing measures attention.
Be precise about which of these your number actually reflects:
- Visible — the document is on screen. A visible but unfocused window still counts. This is what most implementations measure, including ours.
- Focused — the window also has focus. Stricter, and a different number.
- Active — the reader has moved, scrolled or typed recently. Stricter again, requires idle detection, and if you have not built it you must not imply it.
Quixli measures the first and says so. Time counts while the document is on screen; hide the tab and the count pauses; come back and it resumes. A document left open in a background tab over lunch does not come back as a forty-seven-minute read. We do not claim idle detection, because we do not do idle detection.
Five questions for any tool that shows you a reading time
- Does the number come from a start-to-end subtraction, or from accumulated confirmed intervals?
- What happens to a document left open in a background tab for an hour?
- What happens when a session ends without a goodbye — is it closed at the reader’s last known moment, or at the moment your cleanup ran?
- Does a reload continue the visit or start a new one?
- Is the claim “on screen”, “focused” or “active” — and does the marketing copy match the implementation?
If a vendor cannot answer the second one, the number they are showing you is a wall clock with a nicer font.
Related: how accurate is IP-based location, really — the other number on the same screen that deserves more suspicion than it gets.