Every website needs analytics, but almost every mainstream analytics solution is frustrating in its own distinct way.
Google Analytics 4 is a bloated maze that slows down your Core Web Vitals and forces you to slap cookie consent banners on your website. Modern product analytics suites like PostHog are incredible, but self-hosting them means maintaining a heavy cluster of ClickHouse, Kafka, Redis, and Postgres for what should be simple event counts.
When we set up analytics for Zyntopia, we had four non-negotiable requirements:
- Zero Cookie Banners: 100% privacy-compliant, lightweight (
<5KB), and non-blocking for lightning-fast page loads. - Effortless Self-Hosting: A single binary with persistent storage on our existing VPS, no distributed database zoo.
- AI & Crawler Intelligence: Visibility into how AI search engines (ChatGPT, Claude, Perplexity) cite our practice and which AI bots crawl our pages.
- Editor-Native MCP Integration: The ability to query live conversion funnels and traffic directly inside our AI code editors (Cursor, Claude Code, Antigravity) without having to open a dashboard.
We chose Smol Analytics, an open-source (MIT) Go binary built for modern developers and AI agents.
Here is why it works so well, along with a complete, human-readable guide to setting it up from scratch.
Why Smol Analytics?
Smol Analytics boils down to three things:
- One Universal Ingestion Endpoint:
POST /v1/eventshandles everything: browser clicks, server-side Stripe webhooks, and background jobs. - Deterministic Answers, Zero AI Hallucinations: When you query metrics through your coding assistant, the MCP server calls the exact same deterministic calculation engine that powers the dashboard.
- Self-Host Free Forever: It compiles down to a single lightweight Go executable that runs on a basic VPS or a $4/mo container.
Step-by-step: the complete setup guide
Setting up Smol Analytics across your server, your Next.js application, and your AI editor takes less than 10 minutes.
1. Deploy the engine on your VPS (Docker Compose)
Create a docker-compose.yml file on your server (or VPS):
services:
smolanalytics:
image: ghcr.io/arjun0606/smolanalytics:latest
container_name: smolanalytics
restart: unless-stopped
ports:
- "127.0.0.1:8090:8080"
volumes:
- ./data:/data
environment:
- PORT=8080
- DATA_DIR=/data
Start the container and expose it behind your reverse proxy (Caddy, Nginx, or a Cloudflare Tunnel) with HTTPS:
docker compose up -d
Once running, inspect docker logs smolanalytics to get your three keys:
- Public Host URL:
https://analytics.yourdomain.com - Write Key (Public): Safe to include in frontend HTML; it can only ingest events.
- Read Key (Secret): Grants access to reports, dashboard admin, and MCP tools.
2. Add the client tracking to Next.js (App Router)
In your Next.js project, add your public keys to .env.local:
NEXT_PUBLIC_SMOLANALYTICS_HOST="https://analytics.yourdomain.com"
NEXT_PUBLIC_SMOLANALYTICS_WRITE_KEY="your_public_write_key"
Next, open your root layout (app/layout.tsx) and inject the script using Next.js next/script with strategy="afterInteractive":
// components/SmolAnalytics.tsx
"use client";
import Script from "next/script";
export function SmolAnalytics() {
const host = process.env.NEXT_PUBLIC_SMOLANALYTICS_HOST;
const writeKey = process.env.NEXT_PUBLIC_SMOLANALYTICS_WRITE_KEY;
const env = process.env.NEXT_PUBLIC_VERCEL_ENV || process.env.NODE_ENV || "production";
if (!host || !writeKey) return null;
return (
<Script
src={`${host}/sdk.js`}
strategy="afterInteractive"
onLoad={() => {
if (typeof window !== "undefined" && window.smolanalytics) {
window.smolanalytics.init(writeKey, {
host,
env,
});
}
}}
/>
);
}
Then drop <SmolAnalytics /> inside your root app/layout.tsx:
import { SmolAnalytics } from "@/components/SmolAnalytics";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<SmolAnalytics />
</body>
</html>
);
}
Why
onLoadmatters: Next.js script loading is asynchronous. Initializing the tracker inonLoadensures the SDK has finished downloading beforeinit()is called. Passingenvensures local dev and preview deployments are automatically separated from production metrics.
3. Track high-intent moments (beyond basic pageviews)
Pageviews are good, but for consulting and SaaS, high-intent conversion moments are what actually move the needle.
We created a tiny helper (lib/analytics.ts):
export function trackEvent(name: string, properties?: Record<string, unknown>) {
if (typeof window !== "undefined" && window.smolanalytics?.track) {
window.smolanalytics.track(name, properties);
}
}
export function identifyUser(distinctId: string) {
if (typeof window !== "undefined" && window.smolanalytics?.identify) {
window.smolanalytics.identify(distinctId);
}
}
When a visitor submits a contact or lead form:
// Inside your form submission handler
identifyUser(leadEmail);
trackEvent("lead_submitted", { company: leadCompany });
This immediately stitches the visitor's past anonymous browsing history into their verified identity, giving you a full timeline of what they read before reaching out.
4. Catching invisible AI crawlers (middleware.ts)
AI search bots like GPTBot, ClaudeBot, and PerplexityBot never run client-side JavaScript. If you rely only on a browser script tag, your analytics will report zero AI crawlers.
The fix is simple: report them from your server in Next.js middleware.ts:
import { NextResponse, type NextRequest } from "next/server";
const AI_CRAWLERS = [
{ pattern: /GPTBot/i, crawler: "GPTBot", operator: "OpenAI", purpose: "training" },
{ pattern: /OAI-SearchBot/i, crawler: "OAI-SearchBot", operator: "OpenAI", purpose: "search" },
{ pattern: /ClaudeBot/i, crawler: "ClaudeBot", operator: "Anthropic", purpose: "training" },
{ pattern: /PerplexityBot/i, crawler: "PerplexityBot", operator: "Perplexity", purpose: "search" },
];
export async function middleware(request: NextRequest) {
const userAgent = request.headers.get("user-agent") || "";
const matched = AI_CRAWLERS.find((bot) => bot.pattern.test(userAgent));
if (matched && process.env.NEXT_PUBLIC_SMOLANALYTICS_HOST) {
// Fire-and-forget server event
fetch(`${process.env.NEXT_PUBLIC_SMOLANALYTICS_HOST}/v1/events`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.NEXT_PUBLIC_SMOLANALYTICS_WRITE_KEY}`,
},
body: JSON.stringify({
name: "$ai_crawl",
distinct_id: "$crawler",
properties: {
crawler: matched.crawler,
operator: matched.operator,
purpose: matched.purpose,
path: request.nextUrl.pathname,
status: 200,
site: "zyntopia.com",
},
}),
}).catch(() => {});
}
return NextResponse.next();
}
Now, your dashboard's AI Crawlers report will show exactly which AI labs are scraping your documentation or citing your pages in real time.
5. Connecting your AI code editor (the superpower)
The most transformative feature of Smol Analytics is its native Model Context Protocol (MCP) server.
Instead of opening a browser tab to check a dashboard, you can connect your analytics directly to Cursor, Claude Code, Windsurf, or Antigravity:
{
"mcpServers": {
"smolanalytics": {
"url": "https://analytics.yourdomain.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_SECRET_READ_KEY"
}
}
}
}
Now you can highlight a component or open your terminal and ask your AI assistant:
"What was our conversion rate from the blog to the booking form this week?"
"Which AI assistant (ChatGPT vs Claude vs Perplexity) generated the most referral traffic?"
"Did our latest release improve the signup drop-off rate?"
Because answers are computed directly from deterministic backend reports rather than guessed, the numbers are guaranteed to match your dashboard 1-to-1.
Conclusion
Analytics shouldn't require complex infrastructure or intrusive tracking cookies. By running a single self-hosted Go binary with native MCP connectivity, you get:
- Complete data sovereignty.
- Zero Core Web Vitals penalty.
- Deep visibility into human visitors, conversion funnels, and AI search engines alike.
- Instant conversational metrics inside the tools you already use to write code.
If you're building modern web apps or deploying AI automation systems, an AI-native analytics engine is one of the most useful upgrades you can make to your stack.


