Open source · MIT · Self-hostable · No cookies

Know who visits your apps, without tracking anyone

metrics counts page views and visitors for every project you register: top pages, referrers, countries and cities, devices, browsers and custom events — from one script tag, a pixel or an API call. No cookies, no stored IP addresses, nothing to put in a consent banner.

Early access: every account gets full access, free. Plans come later, with notice.

Three ways to count

Pick the one that fits each app. They all land in the same dashboard.

One script tag

Under 3 KB, no dependencies. Counts every page view, follows single-page-app route changes, and exposes metrics.track() for custom events. Works in Qwik, Astro, React, jQuery pages and Phaser games alike.

<script defer src="https://metrics.3m4.net/m.js"
        data-key="metrics_pub_…"></script>

Tracking pixel

A 1×1 image for places where JavaScript can't run: emails, READMEs, documentation hosted elsewhere. The URL says which page or event it stands for.

<img src="https://metrics.3m4.net/api/collect/pixel.gif?k=metrics_pub_…&u=/newsletter"
     alt="" width="1" height="1">

Collect API

A single POST with the project's public key, from your backend, a CLI, a game server or a cron job. Perfect for apps without a DOM.

curl -X POST https://metrics.3m4.net/api/collect \
  -H "X-Project-Key: metrics_pub_…" \
  -H "Content-Type: application/json" \
  -d '{"n": "purchase", "u": "https://myapp.example.com/checkout",
       "p": {"amount": 42}}'

How it works

1. Create a project

One project per site or app. You get a public key for the script, the pixel and the API, and you pick its time zone.

2. Paste the snippet

Copy it from the project settings into your layout. The first page views show up within seconds.

3. Read the dashboard

Pick a range, click any page, country or device to filter everything by it, watch the live counter, or let an AI agent read the numbers through MCP.

Everything you want to know, nothing you don't

The dashboard answers the questions people actually ask about a site, and stops there.

  • Where from. Referrers, UTM source / medium / campaign, countries, regions and cities.
  • On what. Desktop, mobile or tablet; browser and operating system; screen size and language.
  • Doing what. Top pages, entry paths, and the custom events you send (signups, purchases, clicks) with their properties.
  • Right now. Visitors in the last five minutes and the pages they are on.
PagesVisitors
  • /1,284
  • /docs612
  • /blog/launch391
  • /pricing207
7 visitors right now

Privacy-friendly by construction

The tracker sets no cookie and writes nothing to the browser. The server hashes each visitor's IP address with a salt that changes every day, keeps only the derived country, region and city, and throws the user agent away once device, browser and OS are known.

  • ✓ No cookies, no localStorage, no fingerprinting across sites or days
  • ✓ Raw IP addresses are not stored by default — only a daily salted hash (a per-project switch keeps them if you need to)
  • ✓ Query strings are dropped from page URLs (except UTM tags), so tokens and emails never reach the dashboard
  • ✓ Optional Do Not Track support, and bots are filtered out
Read the docs
Request
curl -X POST https://metrics.3m4.net/api/collect \
  -H "X-Project-Key: metrics_pub_…" \
  -H "Content-Type: application/json" \
  -d '{"n": "purchase", "u": "https://myapp.example.com/checkout",
       "p": {"amount": 42}}'
Response
HTTP/1.1 202 Accepted
{ "ok": true }

Public keys can only send hits. They can never read anything.

Model Context Protocol

Ask your AI agent how the site is doing

metrics ships an MCP server. Connect it to Claude Code, Claude Desktop, Cursor or any MCP host and ask things like “how did traffic to the docs change this week?” or “which countries visit the pricing page most?”

  • Role-scoped keys. A viewer key never even sees the delete tools; editor and admin unlock more. Enforced by the API too.
  • Human in the loop. Destructive actions (delete a project, purge its events) ask you to confirm before anything happens.
  • Audit trail. Every change and every refused call is logged, server-side and agent-side.
  • Local or remote. Run it over stdio with npx metrics-mcp (npm) or point your host at https://metrics.3m4.net/mcp with your key.
Claude Code · local (npm)
claude mcp add metrics --scope user --env METRICS_API_KEY=metrics_live_… -- npx -y metrics-mcp
Claude Code · remote (nothing to install)
claude mcp add --transport http metrics https://metrics.3m4.net/mcp --header "Authorization: Bearer metrics_live_…"
Any MCP host (JSON)
{
  "mcpServers": {
    "metrics": {
      "command": "npx",
      "args": ["-y", "metrics-mcp"],
      "env": { "METRICS_API_KEY": "metrics_live_…" }
    }
  }
}

Create a key with the role you want under Dashboard → API keys.

See your first visitor in a minute

Create a project, paste one script tag and watch the live counter move.

Early access. Every account has full access at no cost right now. Plans and limits will be introduced later, with notice before anything changes.

Self-host it (MIT, open source)

The entire stack — Flask API, tracker, MCP server and this Qwik app — is MIT-licensed. Run it on your own VPS with onedocker compose up. No billing code, no limits beyond what you configure.

View on GitHub