Skip to content

What is Ritim?

Ritim measures how fast your site is for the people actually using it, and tells you when that changes.

A synthetic test — a lab run from one machine on one connection — tells you what your site can do. Real user monitoring tells you what it does do: on a four-year-old Android phone, on hotel wifi, on the one route that renders a thousand rows.

Every page view produces one measurement. Every measurement carries the Core Web Vitals plus the context needed to slice them:

Group Fields
Vitals LCP, INP, CLS, TTFB, FCP
Loading Long task count and duration, resource count, transferred bytes
Context Route, release, device type, connection type, country, browser

Interactions are their own event, so an interaction that turns out to be the worst one on the page can be reported after the page view has already been sent. It also records which element was slow — #add-to-cart, or the tag name when the element has no id.

The full field-by-field list is in Metrics.

your page Ritim
───────── ─────
the SDK
├─ watches for navigations (history API, popstate, bfcache)
├─ collects vitals as the browser reports them
└─ ~2s after the page settles ──POST──▶ collector ──▶ analytics store
dashboard reads p75

Two details are worth knowing, because they explain most of the SDK’s behaviour:

It sends when the page settles, not when the visitor leaves. Waiting for visibilitychange is the traditional approach and it loses measurements — a closed tab does not always get to run anything. Page hide is a backstop here, not the plan.

It recovers what happened before it loaded. The tag is async, so it frequently starts after the largest paint has already happened. The SDK reads buffered performance entries to fill that in, which is why loading late costs very little.

No cookies. No localStorage. No fingerprint. No identifier that survives a page view — the measurementId that ties a page view to its own interaction events is regenerated per view and means nothing outside it.

Because there is no persistent identifier and nothing personal is stored, there is nothing to ask consent for. That is the point of the design, not a side effect of it. What the SDK never sends is the exact list, including the one field that can carry your data if you put it there.

The bundle is small and loaded async, so it never blocks rendering. If it fails to load, fails to parse, or throws, the page it is measuring is unaffected — failure isolation is a hard requirement, since this code runs on sites that are not ours.

An npm package and one init() call, or one script tag — the two paths ship the same code and collect the same things. Install covers both and explains which to pick.