The Sentiment Score is Witnes's per-visit grade: every page load your users experience is automatically classified as Good, Needs Improvement, or Bad. It gives you a single answer per session — not an aggregate — so no bad experience gets hidden inside a green dashboard.
The three grades
Good
No detected issues. The page loaded smoothly and the user's history shows similar or better performance.
Needs Improvement
One to three experience symptoms detected. The visit was imperfect but not critically broken.
Bad
Four or more symptoms, or at least one severe symptom (Rage Quit or Infinite Waterfall).
How it's calculated
Rather than applying fixed thresholds to a single metric (e.g. "LCP > 4 s = bad"), Witnes accumulates experience symptoms — specific signals that something went wrong during the visit. The final grade depends on how many symptoms were detected and whether any of them are severe.
Experience symptoms
There are six possible symptoms. Each one is either present or absent for a given visit.
Slow Visual Load
The main content took too long to appear on screen.
- Full page loads: Largest Contentful Paint (LCP) exceeded 4 000 ms.
- SPA navigations: The request-till-idle time exceeded 4 000 ms.
Unstable Layout
Content visibly shifted after it was rendered. Cumulative Layout Shift (CLS) exceeded
0.5. At this level the shift is noticeable and disruptive — buttons move,
text jumps, users click the wrong thing.
Stuttering UI
The browser's main thread was repeatedly blocked, causing visible jank. Witnes counts individual long tasks (> 50 ms) that occurred during the visit; more than 7 jank events triggers this symptom.
Delayed Functional Ready
Full page loads only. The page looked loaded but remained non-interactive for an unusually long time. When the interaction dead zone — the gap between visual readiness and actual interactivity — exceeds 3 000 ms, users click buttons that do nothing.
Infinite Waterfall
The page never finished loading during the session. Witnes waits for the browser's network activity to settle; if it times out before settling, and the page wasn't even usable at that point, the visit is marked with this symptom. It usually indicates a stuck request, an infinite polling loop, or a broken lazy-load chain.
Rage Quit
The user left the page before it finished loading, and the page wasn't usable yet when they
left. Detected via pagehide, beforeunload, or
visibilitychange events firing before the page settled. This is the most direct
signal that a user gave up.
Grading rules
| Condition | Grade |
|---|---|
| Contains Rage Quit or Infinite Waterfall | Bad |
| 4 or more symptoms (any combination) | Bad |
| 0 symptoms and historical comparison is similar or better | Good |
| Everything else (1–3 symptoms) | Needs Improvement |
Historical comparison
Even a symptom-free visit isn't automatically Good. Witnes looks at the same user's last several visits to the same route and checks whether the current session was significantly slower. If the user is used to a 200 ms load time and today got 1 800 ms — still below any raw threshold — that context matters.
The comparison categories are:
- Better — noticeably faster than the user's recent baseline.
- Similar — within normal variation.
- Worse — noticeably slower than baseline. Prevents a Good grade even with zero symptoms.
- Insufficient data — first visit or not enough history. Treated as Similar for grading purposes.
vs. Web Vitals
Google's Core Web Vitals (LCP, CLS, INP) are a useful starting point but have well-known limitations for per-session grading:
- They use fixed global thresholds that don't account for what a specific user normally experiences.
- They don't capture whether the user actually gave up or waited.
- CLS thresholds in Web Vitals are strict by design; Witnes uses a higher threshold (
0.5) because the Sentiment Score already captures multiple dimensions — layout shift alone at0.2won't make a session bad if everything else was fast. - They don't detect long task accumulation (jank count) or interaction dead zones directly.
Witnes captures all standard Web Vitals and displays them on the page-load detail view. The Sentiment Score is a separate, higher-level signal built on top of them — plus additional signals not covered by Web Vitals.