---
title: "The True Cost of Analytics Scripts: Performance Benchmarks for 2026"
description: "We benchmarked 10 analytics providers by transfer size, decoded size, execution time, and memory impact. The results show Google Analytics costs 156x more decoded bytes than Plausible - and why that matters for INP."
canonical_url: "https://scripts.nuxt.com/learn/analytics-script-performance"
last_updated: "2026-03-18"
---

Most performance audits focus on your own code: image optimization, component lazy-loading, bundle splitting. The analytics script gets a free pass because it's "just tracking."

It shouldn't. We measured 10 providers across three metrics that determine real-world impact on your users. The spread is an order of magnitude.

## The 2026 Analytics Performance Matrix

Six metrics tell the full story: **Transfer Size** (bytes over the wire), **Decoded Size** (what the browser parses and executes), **Script Duration** (pure V8 execution time), **Task Duration** (total main-thread blocking), **Heap Impact** (memory allocated), and **Request Count** (network overhead).

<benchmark-table>



</benchmark-table>

<chart-analytics-sizes>



</chart-analytics-sizes>

Rybbit's 1,135ms load time and GA4's 585ms stand out immediately-but the decoded size column is where the real damage happens.

## Why Decoded Size is the New Bottleneck

Developers fixate on gzipped transfer size. The browser doesn't execute gzip-it executes the decoded JavaScript. Those numbers are different.

Chrome's V8 engine does roughly [90% of parsing on background threads](https://v8.dev/blog/compile-hints), so parse time alone isn't the culprit. **Execution stays on the main thread.** Every byte of decoded JS that contains function calls, closures, and event listeners runs on the same thread that handles user interactions.

The gap between providers is stark. GA4 at 452.9 KB decoded is **156x heavier** than Plausible at 2.9 KB, and our benchmarks show it: GA4 burns 20ms of pure script execution and 33ms of total task time, vs 1ms script / 6ms task for Plausible. On mid-range mobile hardware, 400 KB of decoded JavaScript translates to roughly **150-250ms of main-thread contention** ([Addy Osmani, "Cost of JavaScript" 2024](https://medium.com/p/the-cost-of-javascript-in-2023-7eb669046f2)). GA4 also allocates +2.6 MB of heap memory compared to Plausible's +698 KB.

That contention directly degrades [Interaction to Next Paint (INP)](https://web.dev/articles/inp)-Chrome's primary responsiveness metric since March 2024. If your analytics script fires during the first few seconds of a visit, you're burning INP budget on tracking code rather than user interactions.

### Core Web Vitals Impact

The benchmark table above includes measured CWV estimates for every script: LCP impact (how much script execution delays rendering), INP risk (based on script weight and DOM observation), and CLS elements (injected visible elements that shift layout).

The heaviest scripts show consistent LCP delays. On a local page with no network variance, scripts like GA4 and Matomo add measurable rendering delays from pure execution time. Field numbers on real mobile connections will be worse - a script that costs 5-20ms of LCP on desktop can easily cost 30-50ms on mid-range mobile, which is the difference between passing and failing the 2.5s LCP threshold.

Scripts that combine heavy execution with `MutationObserver` usage (like GA4) carry a "high" INP risk - they not only block during initialization but continue to compete for the main thread on every DOM change.

Here's the full audit for GA4 - note the privacy footprint, network activity, and cookie surface:

<script-stats script-key="googleAnalytics">



</script-stats>

<chart-analytics-load-time>



</chart-analytics-load-time>

<note>

Every 100 KB of gzipped JS that decodes to ~400 KB adds roughly [100-150ms of main-thread work](https://devclass.com/2024/05/15/google-chrome-engineers-propose-explicit-compile-hints-to-speed-up-javascript-heavy-sites/) on average mobile hardware. GA4 at 154.3 KB compressed sits right at that threshold.

</note>

## The 2025 Fingerprinting Pivot

In February 2025, Google officially reversed its stance on digital fingerprinting, permitting canvas and WebGL fingerprinting in Google Ads provided advertisers disclose it in privacy policies. The UK's ICO called it ["irresponsible"](https://www.forbes.com/sites/zakdoffman/2024/12/19/google-chrome-privacy-u-turn-as-ico-slams-irresponsible-fingerprinting-change/).

GA4 is currently the only provider in our benchmark set using these techniques. The privacy implications have extensive coverage elsewhere. The performance cost gets less attention: canvas fingerprinting requires **synchronous GPU readbacks**, which add [10-30ms of latency](https://coveryourtracks.eff.org/) directly to the main thread during script evaluation ([Brave Privacy Blog](https://brave.com/privacy-updates/7-fingerprinting-protections/)). It's synchronous and blocks the main thread.

For a script already carrying 585ms of load time, an additional 10-30ms of synchronous GPU work is a rounding error in isolation. Combined with everything else GA4 does on initialization, it's one more reason the script consistently underperforms in field data.

## Compression Wars: zstd vs the World

The compression story changed in 2025. Zstandard (`zstd`) reached baseline support across all major browsers with iOS 18 and macOS Sequoia joining Chrome 123+ and Firefox 126+. That means you can serve `zstd`-compressed assets to your entire user base.

The numbers: `zstd` decompresses at [600-800+ MB/s, roughly **3x faster** than Brotli or Gzip](https://blog.cloudflare.com/zstd-compression-rules/) (Cloudflare, 2024). Lower CPU overhead on mobile means faster decoding with less battery drain.

<link-script slug="cloudflareWebAnalytics">



</link-script>

 and <link-script slug="vercelAnalytics">



</link-script>

 have already shifted their analytics delivery to `zstd`. This is part of why Cloudflare Web Analytics (10.8 KB transfer, 30.4 KB decoded, 86ms load) punches above its weight in load time despite having a relatively large decoded footprint. The decompression cost is lower, and they've optimized the delivery pipeline.

If your self-hosted Matomo or custom analytics endpoint is still serving Brotli or Gzip, switching to `zstd` is a free win.

## How Nuxt Scripts Loads Analytics

The standard analytics integration pattern-copy a snippet, paste it into a script tag-has predictable performance problems.

**Dynamic injection hides from the preload scanner.** Scripts created with `document.createElement('script')` are invisible to Chrome's preload scanner, which runs ahead of the parser to discover resources early. Dynamic injection means the browser can't queue the network request until the script that creates the element executes. That delay is typically [**200-500ms**](https://www.debugbear.com/blog/script-async-vs-defer) ([DebugBear, 2024](https://www.debugbear.com/blog/script-async-vs-defer)).

Nuxt Scripts uses declarative loading, emitting the script as a standard script tag that the preload scanner can discover immediately-without blocking the initial render.

**Initialization timing matters as much as load timing.** Even a fast-loading script can hurt performance if it executes during the critical rendering window. Nuxt Scripts initializes analytics via `requestIdleCallback` by default, which defers execution until the browser's main thread has finished painting and handling any pending user input.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  scripts: {
    registry: {
      plausibleAnalytics: { domain: 'your-domain.com' }
    }
  }
})
```

That single config line handles declarative injection, idle-time initialization, and SPA navigation tracking automatically. The manual alternative requires a plugin, `process.client` guards, a router watcher, and still probably gets the timing wrong.

<tip>

Nuxt Scripts also supports first-party proxying, routing analytics requests through your own domain to bypass ad blockers. At [25-45% blocker adoption](https://blockthrough.com) in many audiences ([Blockthrough Ad-Block Report 2026](https://blockthrough.com)), this restores significant data accuracy.

</tip>

## The 19-Second Death March

In emerging markets, average load time over 3G sits around [**19 seconds**](https://hpbn.co/) ([Google/HPBN](https://hpbn.co/)). For users on that connection, a 154.3 KB GA4 script becomes a failure point. Unstable mobile connections drop requests. Expensive data plans mean users disable images and scripts. A script that takes 585ms to become interactive on a fast connection might simply never load.

A [0.1-second improvement in mobile load time increases retail conversion by **8.4%**](https://www.siteqwality.com/post/page-speed-vs-conversion-rate) (Google/Deloitte, 2024). Swapping GA4 for Plausible-1.9 KB vs 154.3 KB on the wire-can recover [10-15 PageSpeed points and reduce Total Blocking Time by 100-200ms on mobile](https://www.debugbear.com/blog/third-party-scripts).

Sub-5 KB providers (<link-script slug="vercelAnalytics">



</link-script>

, <link-script slug="plausibleAnalytics">



</link-script>

, <link-script slug="umamiAnalytics">



</link-script>

, <link-script slug="fathomAnalytics">



</link-script>

) make sites accessible to users who would otherwise abandon them before the first interaction. For those users, this determines whether your site loads at all.

## Making the Call

Compare that GA4 audit to the lightweight alternative:

<script-stats script-key="plausibleAnalytics">



</script-stats>

The benchmark data makes the performance winner clear: <link-script slug="vercelAnalytics">



</link-script>

, <link-script slug="plausibleAnalytics">



</link-script>

, and <link-script slug="umamiAnalytics">



</link-script>

 are in a different category from everyone else. If you don't need <link-script slug="segment">



</link-script>

's data routing, <link-script slug="googleAnalytics">



</link-script>

's Google Ads integration, or <link-script slug="matomoAnalytics">



</link-script>

's on-premise compliance features, there's no performance justification for using them.

If you do need those features, Nuxt Scripts' idle-time initialization and declarative loading reduce the damage. You can't make 452.9 KB of decoded JavaScript free, but you can stop it from running at the worst possible moment.

For the full breakdown of which provider fits which use case, see [Choosing the Right Analytics for Nuxt](/learn/choosing-analytics-nuxt). For privacy-specific comparisons including cookie policies and GDPR compliance, see [Privacy-First Analytics Compared](/learn/privacy-first-analytics-compared).
