4 kBgzipped browser SDK · one script tag, no wiring

Your users have already measured your last release

Every page they load is a measurement you already own. Ritim collects it, ties it to the build it came from — and to the pull request that has not merged yet — and tells you which one made things worse. Cookieless, and 4 kB on the wire.

No cookies · no persistent identifiers · no surprise invoices

From the CDN, or from npm

Either one is the whole install. The key is public — it names a project, it authorises nothing.

CDNone tag in your head, no build step

index.htmlauto-init
<script
  async
  src="https://cdn.ritim.io/v1/browser.min.js"
  data-project-key="P-ABC123"
></script>

npmbundled with your app

terminal
$ npm install @ritim/browser-sdk
app.tsESM
import { init }from '@ritim/browser-sdk';

init({ projectKey: 'P-ABC123' });

No router plugin, nothing to call per navigation, and nothing to configure for an SPA. The tag is async, and buffered performance entries mean loading late costs almost nothing.

Awareness

Know what your website feels like from the outside

Synthetic tests measure one machine on one connection. Ritim measures the ones you have — every device, every network, every route — and keeps the reading honest: sampled rows are weighted back up, and a metric nobody recorded stays empty rather than being scored as perfect.

live
0

Performance score

Weighted from the vitals your visitors actually recorded — not a lab run on a machine nobody uses.

1.24M views3 sitesp75 · 24h
LCP

0s

INP

0ms

CLS

0

Page viewslast 24 hours

The score your users gave you

Core Web Vitals at p75 from real sessions — LCP, INP, CLS, TTFB — weighted into one score that is computed server-side, versioned, and never influenced by the client.

Every page, ranked

Each (domain, route) pair with its own vitals, page weight and score. Find the one template that is dragging the whole site down instead of guessing from an average.

A list of what to fix next

Needs work is the triage view: the pages failing a metric, worst first, with the reading that failed and the traffic behind it. The answer to "where do I start on Monday".

Device and network reality

Desktop and mobile split apart, because they are two different products. A p75 that mixes them tells you about neither.

Many sites, one project

Staging, preview and production hosts under one project, each with its own history — grouped where it helps, never averaged where it lies.

A lab audit when you want one

Run a PageSpeed Insights audit on a domain, mobile and desktop, and read it beside the real-user numbers — clearly labelled as Google's hardware, never mixed into your p75.

Release awareness

Watch your releases, and what they did to real users

Every measurement carries the build it came from — identified for you on Next.js and Nuxt, or set to a name you chose. Ritim then tells you when each release first appeared in the wild, how much traffic it has seen, and whether the numbers moved — so "the site feels slower this week" becomes "v2.4.0, two days ago, LCP p75 1.9s → 3.5s".

  • Next.js and Nuxt need no setup — Ritim identifies each deployment on its own. Declare a release yourself only when you want the dashboard to read the name you chose.
  • Releases are keyed by site as well as by name — the same build on two hosts is one release and two deployments.
  • Cadence is the median gap between first sightings, computed per site and never averaged across a project.
  • Statistics count hard navigations only, so a soft navigation cannot make a release look lighter than it is.

shop.acme.com

Ships every 2.4 days

last 30 days
  1. v2.3.89 days ago91—
    312k views
  2. v2.3.96 days ago93+2
    408k views
  3. v2.4.02 days ago72-21
    287k views
  4. v2.4.14 hours ago95+23
    96k views
v2.4.0 regressed LCP by 1.6s. Caught 4 hours after the first real page view carrying it, not at the end of the sprint.

From deploy to verdict

  1. You ship

    A build goes out. On Next.js and Nuxt, Ritim identifies the deployment on its own.

    release: identified

  2. Someone loads it

    A real visitor, on their own device and their own network.

    4 kB · no wiring

  3. It reports itself

    The SDK waits for the view to settle, then sends — it does not wait for the tab to close.

    ~2s quiet period

  4. You know

    The release exists in Ritim because that measurement arrived, and it is scored against what was live before it.

    score −21 vs v2.3.9

Footprint

4 kB on the wire. That is the whole agent.

A performance tool that costs performance is a contradiction. The browser SDK ships as a single minified file of about 10 kB — roughly 4 kB gzipped, 3.7 kB brotli — and that is everything: vitals collection, INP tracking, sampling, navigation detection and transport.

Minified10.3 kB
Gzipped4.2 kB
Brotli3.7 kB

Measured from the build that is on the CDN right now — not a target, and not the number before tree-shaking.

One dependency

Its only import is the shared event schema. No framework, no polyfill bundle, nothing to keep in step with your build.

It cannot break your page

Loaded async, failure-isolated, and it never blocks rendering. The page it measures is the page it must not affect.

No wiring, ever

It detects same-document navigations itself — synchronously, before your router's hooks run — so SPA routes are measured without a plugin or a per-route call.

Pull requests

Review the regression before you merge it

Your trunk, the branches forking off it, and what each preview build did to the numbers — so a slow page is something you catch in review, not in production on Monday.

  • Grouped by pull request

    Every candidate a branch produced, in order, with the traffic it saw.

  • Scored against production

    Merging replaces what is live, so that is the comparison it makes.

  • Nothing extra to install

    Your preview host already serves the SDK. The branch build is its release.

Dashboard view shipping next
Release candidates
main · v2.4.1
v2.4.1production95
#482Lazy-load the hero carouselopen
96+4 vs live

3 candidate builds · last 7 days

#479Add third-party review widgetopen
81-11 vs live

5 candidate builds · last 7 days

#476Preconnect to the font hostdraft
93+1 vs live

1 candidate build · last 7 days

GitHub Action

One step in the workflow you already have

Point it at the preview you just deployed. Everything else — the branch, the commit, the author — comes from the pull request event GitHub already handed the job.

.github/workflows/preview.ymlthe whole change
permissions:
  pull-requests: write

steps:
  - uses: ritim-io/pr-review-action@v1
    with:
      project-secret: ${{ secrets.RITIM_PROJECT_SECRET }}
      preview-url: ${{ steps.deploy.outputs.url }}
  • Only a missing secret or preview URL fails the step
  • Mobile by default, desktop on request
  • One comment, edited on every push

⚡ Ritim performance report

Mobile · preview · 9f2a1c4

Performance
94
LCP
2.1 s
CLS
0.04
TBT
210 ms

Lighthouse, on Google's hardware — labelled as such, because it is not the real-visitor stream the rest of Ritim reports.

Pricing

No surprise invoices. Ever.

A monitoring bill should be the least interesting thing about monitoring. Ritim has no usage meter running behind your back: every limit is a stop, you can watch it approach, and the number you agreed to is the number you pay.

A ceiling, never a meter

Every allowance is a hard stop. Spend a project’s month and the collector stops accepting, the SDK stops sending for the life of the page — and nothing keeps running up a total on your behalf.

The counter is on your dashboard

Usage is a page, not a line item you meet at the end of the month. What has been used, per project, is visible while you can still do something about it.

No overage, no true-up, no add-ons

There is no per-seat maths and no module to unlock. Overview, pages, releases, triage, pull request audits and synthetic runs are the product, not the upsell.

You are told before it stops

An allowance running out is a thing you see coming, not a service that goes quiet. The dashboard shows the month against the limit that applies to it.

Beta

Plans and prices are published before the beta ends. Start now without a card, and nothing turns itself into a paid plan while you are not looking.

What you are choosing between

Two reasonable purchases. Not the same purchase.

A full observability suite

Everything, instrumented

  • Tens of thousands a year — committed up front, and a call with sales to get there
  • Logs, traces and metrics across every service
  • Session replay, error tracking, on-call alerting
  • Priced per seat, so the bill grows with the team

Built for a platform team standardising a whole estate. That is a real job, and the price is the price of doing all of it.

Ritim

One question, answered well

  • Under $100 a month — at the very top of the range, and month to month
  • Core Web Vitals from the visitors you already have
  • Which release moved them, and which pull request will
  • A ceiling on what it can cost, visible before you reach it

Built for the team shipping the site, and priced like the one tool it is — the same whether you check it once a quarter or every morning. Exact plans are published before the beta ends.

If you need the whole estate instrumented, buy the suite — it is the right tool and Ritim is not trying to replace it. If the question is whether your site is fast for the people using it, that is a smaller thing to buy, and it should be priced like one.

Install

Two ways in. Either one is the whole install.

CDN

One tag in your <head>

No build step and no bundler. The SDK reads data-project-key off the tag that loaded it and starts itself.

  • Works on any stack, including the ones you did not choose
  • The key is public — it names a project, it authorises nothing
  • The dashboard renders this snippet with your key already in it
npm

Or one import in your app

Bundled with everything else you ship, typed, and versioned in your lockfile instead of on a CDN path.

  • One call at startup — nothing per route, nothing per navigation
  • Its only dependency is the shared event schema
  • Same 4 kB on the wire as the tag

Cookieless and without persistent user identification by default — the honest version of the claim, rather than promising you out of every regulation.

CDN · index.html
<script
  async
  src="https://cdn.ritim.io/v1/browser.min.js"
  data-project-key="P-ABC123"
></script>
npm · app.ts
npm install @ritim/browser-sdk
import { init } from '@ritim/browser-sdk';

init({ projectKey: 'P-ABC123' });

Stop guessing which release made it slow

Add one script tag and watch the next deploy land in real user data — usually within minutes of the first page view that carries it. No cookies, no consent banner, and no invoice you did not see coming.