Netlify Analytics reads your edge logs, not your visitors' browsers — no snippet, nothing for an ad blocker to catch, no cookies. That honesty comes with a ceiling: no custom events, no performance data, no campaign breakdown. Here's exactly where that ceiling sits, and what to add when you hit it.
Netlify Analytics is genuinely honest software. It's built from Netlify's own server logs, so there's no script to install, nothing for an ad blocker to strip, and no cookies. It also sees things a script never will, like 404s and bandwidth.
If you just want the how-to, skip to "add a script-based analytics tool to a Netlify site" below.
It's worth saying plainly: Netlify Analytics isn't a weak product, it's a different category of product. Because it's built from Netlify's own edge and server logs rather than a JavaScript snippet running in the visitor's browser, it has a few structural advantages that no script-based tool — ours included — can fully match.
There's nothing to install. No <script> tag, no tag manager, no build step, no code to touch on your site at all. It reads requests that already hit Netlify's infrastructure to serve your pages. That also means there's nothing for an ad blocker or privacy extension to catch — script-based analytics traffic is dropped by browser extensions before it ever fires, and that share is invisible to you by definition, and log-based analytics has no such gap because there's no script to block in the first place.
It's also cookieless by construction — there's no client-side storage to set because there's no client-side code running at all — and zero code to maintain. No dependency to update, no snippet that can break a Content Security Policy, no version to keep current.
And because it's reading the actual server logs, it sees things a browser-side script structurally cannot: top "not found" (404) pages and bandwidth, alongside pageviews, unique visitors, top pages, and top sources/referrers. A script only knows what happens after the page loads and the tracker fires; a log sees every request that hit the server, successful or not. For teams who've compared the broader field in our cookieless analytics roundup, Netlify Analytics is worth including specifically for this log-based angle — it's a genuinely different measurement model, not a lesser one.
The trade-off for that log-based honesty is that Netlify Analytics has zero visibility into anything that happens inside the browser. None of the following is a bug — it's the direct, unavoidable consequence of never running client-side code.
No custom events. There's no way to know that a visitor clicked "Start trial" or scrolled to your pricing table, because nothing is watching the page after it loads. If your team needs to track a signup click or a specific in-app action, server logs have no mechanism for that at all.
No Core Web Vitals, no performance data of any kind. Real-user FCP, LCP, CLS, TTFB — anything measured from an actual visitor's device — requires code running in that visitor's browser. A server log only knows a request happened and how long the server took to answer it, not how the page actually rendered for the person looking at it.
No scroll depth. Same root cause: scroll position is a browser-side signal, and there's no script present to observe it.
No UTM or campaign breakdown. You get top sources and referrers, but not a UTM Breakdown table split by source, medium and campaign. Query strings do reach a server log, so this is a product-scope decision rather than a hard limit of log-based analytics — but the reporting isn't there, and campaign-level attribution is where teams most often hit the ceiling.
Per-site billing that scales with client count. It's a paid add-on, billed per site per month — check Netlify's current pricing page for the actual figure, since we don't have a verified number to quote here. The relevant point for planning purposes: if you or your agency run several sites on Netlify, that cost multiplies per site, not per account.
Netlify-only. Because it's built directly from Netlify's own edge and server logs, it only exists for sites hosted on Netlify. Move a site to another host — or even just change how it's served — and Netlify Analytics, along with its history, doesn't come with you.
A limited data window. Historical retention isn't unlimited; check Netlify's current documentation for exactly how far back the data goes, since that window can change.
Every row below is a well-established fact about how each tool is built and sold, not a guess. Where a number varies by plan or changes over time, we say "check current pricing" or "check current docs" instead of inventing one.
| Tool | Install method | Cookieless | Custom events | Core Web Vitals | Raw export | Pricing model |
|---|---|---|---|---|---|---|
| Netlify Analytics | None — enabled per site in the Netlify dashboard, reads existing edge/server logs | Yes | No | No | No dashboard export — check current docs | Paid add-on, billed per site/month — check current pricing |
| GhostMetrics | One script tag in <head> | Yes | Yes | Yes (FCP, LCP, CLS, TTFB — not INP) | Yes, every plan (CSV or API) | Free (1 site); Pro $9.99/mo flat |
| Plausible | Script tag (self-host or hosted) | Yes | Yes | Not a core focus — check current docs | Check current plan details | Paid hosted plans; free if self-hosted (infra cost only) — check current pricing |
| Fathom | Script tag (hosted only) | Yes | Yes | Not a core focus — check current docs | Check current plan details | Paid, no free tier — check current pricing |
| Umami | Script tag (self-host or Umami Cloud) | Yes | Yes | Not a core focus — check current docs | Full DB access if self-hosted; check current Umami Cloud details | Free to self-host (infra cost only); Umami Cloud paid — check current pricing |
| Cloudflare Web Analytics | Script tag, or automatic if the site is proxied through Cloudflare | Yes | No | Yes | No CSV button — reachable via Cloudflare's GraphQL Analytics API | Free |
A few notes worth reading before you pick a row. Cloudflare Web Analytics is the closest philosophical match to Netlify Analytics in spirit — free, cookieless, minimal setup — but it's a script-based tool with Core Web Vitals baked in, which flips Netlify's own trade-off: it gets browser-side performance data at the cost of being blockable and missing non-browser hits. Plausible, Fathom, and Umami are all script-based, cookieless, and support custom events, but none of them replace the log-based guarantees Netlify Analytics offers — an ad blocker can still stop any of them. GhostMetrics — ours, full disclosure — sits in the same script-based category, built specifically for teams who want custom events and performance data with zero infrastructure and free raw export on every plan, including the free tier.
Netlify doesn't get in the way of this. There's no build plugin required. The one Netlify-specific thing to check is _headers: if you set a Content-Security-Policy there, add ghostmetrics.nullagency.io to script-src and connect-src, or the browser will block the tag. Otherwise you're just adding one line to whatever file renders your site's <head>, the same way you would on any host. Here's the pattern for the four most common Netlify setups, using GhostMetrics' one-line tag as the example (swap in whichever tool's script you've chosen).
<head> passes through. That's the only place you need to touch — not every page template.Add the tag to your base layout, inside <head>.
---
// src/layouts/BaseLayout.astro
---
<html lang="en">
<head>
<meta charset="utf-8">
<slot name="head" />
<script is:inline defer src="https://ghostmetrics.nullagency.io/gm.js" data-site="YOUR-SITE-ID"></script>
</head>
<body>
<slot />
</body>
</html>
The is:inline directive matters — without it Astro processes and bundles the tag at build time and the data-site attribute is lost.
If your theme already has layouts/partials/head.html, copy it to layouts/partials/head.html in your own project first (project files override theme files completely — creating a new one that holds only the script tag will wipe out your title, meta and CSS), then add the tag inside it.
<!-- layouts/partials/head.html — your copy of the theme's partial, plus one line -->
<script defer src="https://ghostmetrics.nullagency.io/gm.js" data-site="YOUR-SITE-ID"></script>
If your theme has no head partial at all, put the tag directly inside <head> in layouts/_default/baseof.html.
Add the tag to your base layout in _includes.
<!-- _includes/base.njk -->
<html lang="en">
<head>
<script defer src="https://ghostmetrics.nullagency.io/gm.js" data-site="YOUR-SITE-ID"></script>
<title>{{ title }}</title>
</head>
<body>
{{ content | safe }}
</body>
</html>
Add the tag to the root layout.
// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<script defer src="https://ghostmetrics.nullagency.io/gm.js" data-site="YOUR-SITE-ID"></script>
</head>
<body>{children}</body>
</html>
);
}
One honest note before you compare the two dashboards side by side: a script-based tool can be stopped by an ad blocker, and it can't see non-browser requests the way a server log can — so its pageview count will run lower than Netlify Analytics' log-based number. That gap is normal and expected for any script-based tool, not a sign either one is broken.
None of the above is an argument to rip Netlify Analytics out. It's still the right call for specific situations, and running it alongside a script-based tool rather than instead of one is a completely reasonable setup.
You want server-truth pageview counts. If the number you care about most is "how many requests actually hit my server," log-based data is the more complete answer — it includes hits a script-based tool structurally cannot see, from visitors running ad blockers to bots and prefetches that never execute JavaScript.
You never want to add a script, period. Some teams have a hard policy against third-party JavaScript on production pages, whether for security review, Content Security Policy simplicity, or just page-weight discipline. Netlify Analytics is one of the only ways to get any traffic visibility at all without adding a single line of client-side code.
404s and bandwidth matter to your job. If you're watching for broken links or tracking bandwidth usage, that's log-based territory a script-based tool doesn't cover — Netlify Analytics answers those questions directly.
GhostMetrics is cookieless web analytics that works on any host, Netlify included — install one script tag and you're live, no plugin, no tag manager, no build step. The free plan is free forever: one site, unlimited pageviews, real-time dashboard, every view, full history.
It picks up exactly where Netlify Analytics stops: Core Web Vitals (FCP, LCP, CLS, TTFB — INP is not captured) and Custom Events two ways — add data-gm-event="signup-click" to any element, or call window.ghostmetrics.track('name', { section: 'pricing' }) from code. Raw event export as CSV or JSON is on every plan, including free. Need more than one site, or a public shareable dashboard? Pro is $9.99/mo flat, unlimited pageviews, unlimited websites, with a 30-day free trial — a card starts the trial, nothing is charged for 30 days, cancel anytime.
Disclosure: GhostMetrics is built by Null Agency and we use it on this site, so we're not a neutral party about our own product — we've kept the claims to what the free and paid plans actually do, and pointed to Netlify Analytics and other tools where they genuinely fit better. Pricing for third-party products can change; always check the vendor's current pricing page before deciding.