INP Punishes Heavy Analytics: Why Your Tracker Is on the Main Thread
Interaction to Next Paint is the Core Web Vital most sites fail, and field data shows behavior-tracking scripts are a leading cause. The fix is sending less work to the main thread.
Interaction to Next Paint (INP) is the Core Web Vital developers most often fail, and the reason is sitting in your <head>. INP became a stable Core Web Vital in 2024, replacing First Input Delay, and it measures something FID never could: how responsive a page stays across every click, tap, and keypress for its entire lifetime.
The metric is unforgiving toward the kind of JavaScript that surveillance analytics ships. If your tracker does meaningful work on the main thread, every interaction your users make inherits that cost.
What INP Actually Measures
INP reports the latency of interactions at the 75th percentile of all clicks, taps, and key presses on a page. A score of 200 ms or less is "good"; 200–500 ms "needs improvement"; above 500 ms is "poor".
Each interaction breaks into three phases:
- Input delay — time before your event handlers can even start, because the main thread is busy.
- Processing duration — time your event handler callbacks take to run.
- Presentation delay — time from the callback finishing until the browser paints the next frame.
Heavy analytics damages all three. A tracker that parses a large bundle, evaluates consent logic, batches a tag-manager queue, or reads layout to build a fingerprint occupies the main thread exactly when a user is trying to interact.
Long Tasks Are the Mechanism
The browser cannot process an interaction while a task is running. Any task that runs longer than 50 ms is a long task, and the portion over 50 ms is dead time during which clicks queue up.
A tag manager that synchronously loads and executes a dozen vendor scripts produces a cascade of long tasks. The user clicks, nothing happens, they click again — and when the main thread finally clears, the queued inputs fire at once.
This is not theoretical. The HTTP Archive's 2024 Web Almanac found that pages carrying user-behavior scripts — session replay, heatmaps, behavioral analytics — reached good INP only 37% of the time on mobile, against 60% on desktop. Consent-management scripts, the banners those tools require, passed INP on just 53% of mobile pages. The instrumentation meant to "understand users" is actively degrading their experience.
The Architecture That Avoids It
The fix is structural, not a flag you toggle. Send less code, and keep it off the critical path.
A privacy-first tracker can be small enough that parsing and execution never register as a long task. Monoid's tracker is roughly 2 KB, has no dependencies, sets no cookies, and reads no layout — so there is nothing to fingerprint and nothing heavy to run. It records a pageview with a single keepalive request and otherwise stays idle:
fetch('/collect', {
method: 'POST',
keepalive: true,
body: JSON.stringify({ site_id, path: location.pathname })
})
keepalive: true lets the request outlive the page without holding the main thread, so navigation and unload are never blocked waiting on a beacon.
When you do run your own scripts, yield to the main thread between chunks of work so queued interactions can run:
async function processQueue(items) {
for (const item of items) {
handle(item)
if (navigator.scheduling?.isInputPending?.()) {
await scheduler.yield()
}
}
}
scheduler.yield() breaks a long task into pieces and resumes with priority, so a third-party script cannot jump the queue ahead of your continuation.
Measure It in the Field, Not the Lab
Lighthouse cannot report INP, because INP only exists once a real person interacts. Lab tools estimate; they do not measure responsiveness.
Use field data. The Chrome User Experience Report (CrUX) aggregates real interactions from opted-in Chrome users, and the Search Console Core Web Vitals report surfaces the same data per URL group. If your CrUX INP is fine but your lab Total Blocking Time is high, you have headroom; if CrUX INP is poor, your users are already feeling it.
The privacy argument and the performance argument converge here. A tracker that reads no storage, builds no fingerprint, and ships no vendor cascade has almost nothing to do on the main thread — which is exactly why it never shows up in your INP. Surveillance is expensive in milliseconds, not just in trust.
Comments
Loading comments…