The AI-Native Analytics Stack: Why We Switched to Smol Analytics (and How to Set It Up)

Hashan Wickramasinghe6 min read
The AI-Native Analytics Stack with Smol Analytics and MCP integration

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:

  1. Zero Cookie Banners: 100% privacy-compliant, lightweight (<5KB), and non-blocking for lightning-fast page loads.
  2. Effortless Self-Hosting: A single binary with persistent storage on our existing VPS — no distributed database zoo.
  3. AI & Crawler Intelligence: Visibility into how AI search engines (ChatGPT, Claude, Perplexity) cite our practice and which AI bots crawl our pages.
  4. 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 designed from the ground up 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?

At its core, Smol Analytics strips analytics down to its simplest, most powerful primitives:

  • One Universal Ingestion Endpoint: POST /v1/events handles 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 smoothly 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:

  1. Public Host URL: https://analytics.yourdomain.com
  2. Write Key (Public): Safe to include in frontend HTML; it can only ingest events.
  3. 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":

import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}

        {process.env.NEXT_PUBLIC_SMOLANALYTICS_HOST &&
          process.env.NEXT_PUBLIC_SMOLANALYTICS_WRITE_KEY && (
            <>
              <Script
                src={`${process.env.NEXT_PUBLIC_SMOLANALYTICS_HOST}/sdk.js`}
                strategy="afterInteractive"
              />
              <Script id="smolanalytics-init" strategy="afterInteractive">
                {`
                  if (window.smolanalytics) {
                    window.smolanalytics.init("${process.env.NEXT_PUBLIC_SMOLANALYTICS_WRITE_KEY}", {
                      host: "${process.env.NEXT_PUBLIC_SMOLANALYTICS_HOST}",
                      env: "${process.env.NEXT_PUBLIC_VERCEL_ENV || process.env.NODE_ENV || 'production'}"
                    });
                  }
                `}
              </Script>
            </>
          )}
      </body>
    </html>
  );
}

Why the env tag matters: Smol Analytics automatically detects staging and preview subdomains. By passing NEXT_PUBLIC_VERCEL_ENV, local dev runs and Vercel preview pull requests are automatically hidden from your live production dashboard.


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, giving your stack an AI-native analytics engine is one of the highest-leverage upgrades you can make.

Filed under: Build LogAnalyticsAI AgentsNext.jsSelf-HostingOpen Source

Work with me

Got a process that's eating your week?

Fixed-scope, fixed-price automation work. We agree what's being built and what it costs — then I build it.

Book a call →