---
title: "Observability Sampling"
description: "Wire up Web Analytics and Speed Insights on Saturday with sensible sampling rates and a beforeSend filter so observability data is useful without being exhaustive."
canonical_url: "https://vercel.com/academy/optimize-your-vercel-account/observability-sampling"
md_url: "https://vercel.com/academy/optimize-your-vercel-account/observability-sampling.md"
docset_id: "vercel-academy"
doc_version: "1.0"
last_updated: "2026-07-22T04:29:13.826Z"
content_type: "lesson"
course: "optimize-your-vercel-account"
course_title: "Optimize Your Vercel Account"
prerequisites:  []
---

<agent-instructions>
Vercel Academy — structured learning, not reference docs.
Lessons are sequenced.
Adapt commands to the human's actual environment (OS, package manager, shell, editor) — detect from project context or ask, don't assume.
The lesson shows one path; if the human's project diverges, adapt concepts to their setup.
Preserve the learning goal over literal steps.
Quizzes are pedagogical — engage, don't spoil.
Quiz answers are included for your reference.
</agent-instructions>

# Observability Sampling

# Observability Sampling

Speed Insights captures performance data from every page view. Web Analytics counts every visit. Drains forward every log line. The defaults are 100% sampling because the tools want to be useful out of the box. The defaults are also the most expensive way to run them.

You don't need a full sample to know if your Largest Contentful Paint is regressing. A 25% sample is enough to spot the trend, and it costs you a quarter as much. If you do have specific routes that don't deserve any tracking, the `beforeSend` callback in Web Analytics is the place to drop them.

For Saturday, we'll wire up both tools with sensible defaults. The shop doesn't have an admin section yet, but the filter pattern is what you'll keep coming back to as the app grows.

\*\*Note: What are Web Analytics and Speed Insights?\*\*

Two opt-in measurement products. Web Analytics counts visitors and page
views. Speed Insights collects Core Web Vitals from real sessions. Both are
billed by volume, events for one and data points for the other, which is why
sampling is the cost lever.

## Outcome

`<Analytics>` and `<SpeedInsights>` are mounted in the root layout. Speed Insights uses a 25% sample rate. Analytics filters out any future `/admin` routes before sending events.

## Hands-on exercise 4.4

One file. The dependencies already exist; you're wiring the components.

**Requirements:**

1. Open `app/layout.tsx`
2. Import `Analytics` from `@vercel/analytics/next`
3. Import `SpeedInsights` from `@vercel/speed-insights/next`
4. Mount both at the end of `<body>`, after the footer
5. On `<SpeedInsights>`, set `sampleRate={0.25}`
6. On `<Analytics>`, pass a `beforeSend` function that returns `null` for any event whose `url` includes `/admin` (we don't have admin routes yet; this is preventive)
7. Commit, push, redeploy

**Implementation hints:**

- The components are inert during local development. They only send data when running on a Vercel-hosted deployment. So you won't see the integration "work" until after deploy.
- `sampleRate` is a number between 0 and 1. 0.25 means roughly one in four sessions get measured. That's enough granularity to surface real regressions but small enough to keep observability costs predictable.
- `beforeSend` runs per event, client-side. Returning `null` drops the event entirely. Returning the event lets it through. You can also mutate the event and return a modified version, but for filtering, `null` is the answer.
- The `url` field on the event is the page URL. If your filter is path-based, you can check `event.url.includes('/admin')` or use `new URL(event.url).pathname.startsWith('/admin')` for stricter matching.

## Try It

After the redeploy, open Saturday in a browser and navigate around. Then check the two dashboards.

For Speed Insights, open Saturday > Speed Insights. Within a few minutes you should see data appear. The sample rate means it'll take more total traffic to fill out the graphs than at 100% sampling, but the metrics shown will be representative.

```
Real Experience Score   84
Sampled visits today    12 (sampled from ~48 total)
LCP                     1.8s
FID                     12ms
CLS                     0.04
```

For Web Analytics, open Saturday > Analytics. You should see your visits counted in real time. The pages list should show `/`, `/drops`, `/products/foundry`, etc., but no `/admin` paths, even if you visit one in a browser. (Try `https://YOUR_DOMAIN/admin/test`. Next.js will 404, but more importantly, Analytics won't record the visit.)

To verify the filter is actually firing, open DevTools > Network and look for requests to `va.vercel-scripts.com`. On regular pages you'll see the analytics beacons going out. On `/admin/*` paths, no beacons.

## Done-When

- [ ] `app/layout.tsx` imports and renders `<Analytics>` and `<SpeedInsights>`
- [ ] `<SpeedInsights>` has `sampleRate={0.25}`
- [ ] `<Analytics>` has a `beforeSend` that drops `/admin` events
- [ ] Speed Insights dashboard shows sampled data within a few minutes of deployment
- [ ] Analytics dashboard shows visits but excludes any `/admin` paths

## Troubleshooting

**Speed Insights shows zero visits.**

A few options. Sampling at 25% means low-traffic sites can take time to register their first sampled session, keep refreshing. Also confirm the SpeedInsights component is actually rendering: view the page source on production and look for the SpeedInsights script tag. If it's missing, the import path is wrong or the deploy didn't pick up the change.

**Analytics is counting `/admin` pages even though I set the filter.**

Two common issues. The `beforeSend` function must return the event (or a modified copy) for it to pass through; if you forget the return statement, all events get dropped silently. Also check that you're testing against a real Vercel deployment, not local dev, the integration is a no-op locally.

**Why not sample Analytics too?**

You could, but Web Analytics is typically priced per event with a free tier per project, so for most teams the volume isn't the cost driver, keeping the data clean is. Speed Insights, on the other hand, is priced per data point and tends to fill faster, so sampling is the higher-leverage knob.

## Solution

The finished `app/layout.tsx` is on the [`complete` branch](https://github.com/vercel-labs/academy-optimize-vercel-account/blob/complete/app/layout.tsx) if you want to check your version against it.

```tsx title="app/layout.tsx"
import type { Metadata } from "next";
import Link from "next/link";
import { Analytics } from "@vercel/analytics/next";
import { SpeedInsights } from "@vercel/speed-insights/next";
import "./globals.css";

// ...metadata unchanged

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className="min-h-screen flex flex-col">
        {/* ...header, main, footer unchanged */}

        <Analytics
          beforeSend={(event) => {
            if (event.url.includes("/admin")) return null;
            return event;
          }}
        />
        <SpeedInsights sampleRate={0.25} />
      </body>
    </html>
  );
}
```

A note on Vercel Drains for log shipping: if you're forwarding production logs to Datadog, Splunk, S3, or a custom HTTP endpoint, the Drains UI has a sampling field too. The default is 100%. The same logic applies, sample at 25-50% for general visibility, sample at 100% for specific log levels you must not lose (errors, security events). Saturday doesn't ship logs externally yet, so we'll leave that for the day it does.

That's the last hands-on cost setting in the course. One more lesson in this section ties the whole cost arc together: instead of hunting these levers by hand, you'll point an agent skill at a real project and let it find them from production metrics.


---

[Full course index](/academy/llms.txt) · [Sitemap](/academy/sitemap.md)
