Build Your Own Analytics Script in Under 2KB
Every analytics tool I’ve used ships the same script to every customer. It doesn’t matter if you only care about pageviews — you’re loading code for event tracking, session replay hooks, A/B testing integrations, and a dozen other things you never asked for. It’s the buffet model: pay for everything, eat three items, feel vaguely bad about it.
We built INSG differently. You pick the modules you need. The server assembles a script with just those pieces. Nothing extra ships to your visitors.
The bloat problem is worse than you think
Google Analytics 4 weighs in at 45KB+ gzipped. That’s not a one-time download — it loads on every page, for every visitor, on every session. And because it’s JavaScript (not an image or a stylesheet), the browser has to parse, compile, and execute all of it. That blocks the main thread. That delays interactivity. That tanks your Core Web Vitals. That hurts your SEO rankings.
Even the privacy-first alternatives — tools I genuinely respect — tend to land in the 1.5-2KB range. That’s dramatically better than GA, but it’s still a fixed payload. If you only need pageview tracking, you’re still loading outbound link tracking, custom event APIs, and hash-based SPA routing whether you use them or not.
Every byte matters. Not in a theoretical “well actually” way, but in a measurable, show-up-in-Lighthouse way. A 2KB script on a fast connection is invisible. That same script on a budget phone over a spotty mobile connection in Lagos or Dhaka? It adds up. Multiply it by every page load and you’re imposing a tax on your visitors for features you never enabled.
A modular approach to analytics
INSG builds your tracker script on-demand. There’s a core module that’s always included — it handles pageviews, attention time (how long someone actually has your tab focused), and SPA navigation detection. That core weighs about 900 bytes gzipped.
From there, you toggle on exactly what you need:
Web Vitals (+380B) — Measures Largest Contentful Paint, Cumulative Layout Shift, and Interaction to Next Paint. These are the three Core Web Vitals that Google uses as ranking signals. Instead of running a separate Web Vitals library or relying on field data from Chrome UX Report, you get the numbers directly in your INSG dashboard, from your actual visitors.
Outbound Links (+180B) — Tracks clicks on links that leave your site. You’ll see which external sites your visitors click through to, which is useful for affiliate tracking, partnership measurement, or just understanding where your audience goes next.
File Downloads (+120B) — Detects clicks on links to common file types (PDF, ZIP, DOCX, etc.) and logs them as events. If you host whitepapers, software downloads, or media files, this tells you what’s actually getting downloaded versus just viewed.
Scroll Depth (+250B) — Fires events at 25%, 50%, 75%, and 100% scroll milestones. Essential for content sites. If you write 2,000-word articles and 80% of readers bail before the halfway point, you need to know that. This module tells you exactly where the drop-off happens.
Rage Clicks (+350B) — Detects rapid, repeated clicking on the same element. This is what frustrated users do when a button doesn’t respond, a link appears broken, or an interactive element isn’t behaving as expected. If you run a SaaS product or an e-commerce site, rage click data is gold for your UX team. It points directly at the parts of your interface that are confusing or broken.
Dead Clicks (+320B) — Catches clicks on elements that don’t do anything. A visitor clicks on a piece of text that looks like a link but isn’t. Or clicks on an image expecting it to enlarge. Dead clicks reveal mismatches between what your design implies and what your code actually does.
Scroll Hesitation (+300B) — Detects when a visitor scrolls to a section and then stops for a notable period before continuing or leaving. This signals confusion or decision-making — places where your content or layout is giving someone pause. Particularly useful for landing pages and pricing pages.
Copy Tracking (+150B) — Logs when visitors select and copy text from your site. Tells you which sentences, code snippets, or data points people are grabbing. Developers building documentation sites find this one surprisingly revealing.
404 Detection (+80B) — Fires an event when a visitor lands on a page that returns a 404. You’ll see the broken URL and the referrer, so you can fix dead links before they hurt your SEO. At 80 bytes, this is nearly free to include.
Reading Speed (+160B) — Combines scroll depth with time-on-page to estimate how fast visitors are actually reading your content. Are they skimming or reading every word? This helps content teams understand engagement beyond simple pageview counts.
How it works under the hood
Each site you add to INSG gets a unique script URL: /t/{siteId}.js. When a browser requests that URL, the server looks up your module configuration and assembles the script with only the modules you’ve enabled. The response is served with aggressive cache headers: 1 hour in the browser cache, 24 hours on the CDN edge.
This means the script isn’t being rebuilt on every request. The first visitor after a config change triggers the build; everyone after that gets the cached version from whichever edge node is closest to them. When you change your module selection in the dashboard, the new script propagates globally in under an hour.
The assembly itself is straightforward. Each module is a self-contained function that registers its own event listeners and sends data using the same lightweight beacon the core module uses. No shared state between modules, no complex dependency graph. They’re concatenated, minified, and served. The simplicity is the point — fewer moving parts means fewer bytes and fewer bugs.
The size comparison
Here’s what the numbers look like in practice.
A full INSG script with every single module enabled — all ten of them — comes in under 4KB gzipped. That’s less than one-tenth the size of Google Analytics. And it’s tracking significantly more useful things than GA’s default setup.
But most sites don’t need everything. The most common configuration we see is core + web vitals + outbound links. That combination covers pageviews, attention time, SPA navigation, all three Core Web Vitals, and outbound link tracking. Total size: roughly 1.5KB. That’s comparable to the fixed-size privacy tools, except you’re getting web vitals measurement included.
A content-focused site might run core + scroll depth + reading speed + 404 detection. That’s about 1.4KB and gives you a detailed picture of how people consume your articles.
A SaaS product might want core + web vitals + rage clicks + dead clicks. That’s around 1.9KB and surfaces exactly the UX friction points that matter for reducing churn.
The point isn’t that every site needs to be as small as possible. The point is that your analytics script should contain exactly the code that serves you and nothing more. Your visitors shouldn’t download rage click detection if you’ve never once looked at a rage click report.
Build yours
The Script Builder lives in your dashboard under site settings. Toggle modules on and off, and the estimated script size updates in real time. When you save, your script URL stays the same — the content just changes at the edge. No code changes on your site, no redeployment, no waiting for a build pipeline. Flip a switch, wait for the cache to roll over, and your visitors get the new script on their next page load.
Your analytics should work for you without working against your visitors. Pick what you need, skip what you don’t, and ship something you can feel good about.