Cookieless · No consent banner

Privacy-first analytics
for every site you build.

Self-host Zenith once. Track unlimited client sites with a tiny cookieless script, run on-demand SEO audits, and give each client a dashboard that lives on their own domain.

$ npm install zenith-analytics
acme.com/analytics-dashboardlive

Visitors

12,847

+18%

Pageviews

48.1K

+12%

Sessions

15.3K

+9%

Traffic

last 30 days

Top pages

/5,210
/pricing3,102
/blog2,011

Referrers

news.ycombinator.com1,204
google.com890
x.com410

Zenith in action

One console. Every site you build.

Deploy Zenith once on your own server. Every client site reports into it, and any of them can serve its owner a dashboard on their own domain — password-gated, same-origin, reading through your site rather than ours.

Your Zenith console
ridgeline.io
northwind.co
acme.com
atlas.dev
vela.studio
acme.com/analytics

1

KB, cookieless · Tracking script

Sites per deploy

0

Consent banners

320

Tests, end to end

Everything you need

One deploy. Every site. Zero cookies.

The things the product exists to do — analytics, domain-native dashboards, SEO auditing, and privacy — with nothing you have to bolt on.

Multi-site console

Deploy once and every site you manage reports into one place. Overview, events, SEO and setup — for each client, behind one login.

acme.com

Visitors

12,847

Pageviews

48.1K

Bounce

38%

Cookieless tracking

A daily-rotating visitor hash — no cookies, no fingerprinting, no persistent identifier. GDPR-clean, so no consent banner.

sha256(ip + ua + saltᴰᵃʸ)

a3f9c1e0…7b42

Rotates 00:00 UTCcookie

Domain-native dashboards

Your client reads their analytics at theirsite.com/analytics-dashboard — password-gated, same-origin, native to their brand.

acme.com/analytics-dashboard

SEO audits

On-demand, headless-Chromium audits: titles, meta, links, structured data, and Core Web Vitals from the real render.

Missing alt text3 images
LCP1.2s
Canonical tagpresent

Monthly email reports

Each client is emailed last month's numbers automatically on the 1st. No cron to run — the scheduler is built in.

Your October reportNov 1

Visitors

+18%

Views

+12%

Audits

4

Self-hosted, open-core

Two Go services, DuckDB for events, SQLite for app data. One command brings the whole thing up, and your data never leaves your box.

$ docker compose up -d
GoDuckDBSQLiteReactNext.jsDockeryour box

Honestly, how it compares

Zenith isn’t the right answer for everyone.

Here is where it actually sits — including the two rows where it loses. If you need funnels and session replay, or you want nothing to deploy, one of the others is the better tool and this table should tell you so.

CapabilityGoogle AnalyticsPlausible / FathomUmami (self-hosted)Zenith
Cookie banner neededYesNoNoNo
Cost per extra siteFreePer site or pageviewFreeFree
You own the dataNoNoYesYes
Client reads it on their domainNoNoNoYes
SEO audits built inNoNoNoYes
Monthly client emailsNoSome plansNoYes
Setup effortPaste a tagPaste a tagDeploy a serverDeploy a server
Funnels, cohorts, replayExtensiveGrowingBasicBasic

Choose something else if

you want zero infrastructure — Plausible and Fathom cloud are excellent — or you need deep product analytics: funnels, cohorts, session replay, attribution modelling. Zenith deliberately doesn’t do those.

Choose Zenith if

you look after several sites for other people, you’re tired of consent banners and per-site pricing, and you’d rather hand a client a page on their own domain than another login.

How it works

Three steps. About fifteen minutes.

This is the whole setup — not an excerpt. One deploy on your server, one package in your client’s app, and a dashboard they open on their own domain.

01

Deploy once

Clone the repo, fill in three environment variables, and bring it up. That server is now the only Zenith you will ever need to run — every client site reports into it.

your server
git clone https://github.com/MUKE-coder/zenith.git
cd zenith/deploy
docker compose --env-file ../.env up -d --build
02

Install the package

In your client's Next.js app, install and scaffold. zenith init detects the router and writes the config plus the dashboard route; after that the tracker is one component in the root layout.

npm install zenith-analytics
npx zenith init      # config/zenith.ts + the dashboard route
npx zenith hash      # the client's dashboard password
app/layout.tsx
import { Analytics } from "zenith-analytics/next";
import { ZENITH_PUBLIC } from "@/config/zenith";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        {/* Only the public half: the site key and the service URL. */}
        <Analytics config={ZENITH_PUBLIC} />
      </body>
    </html>
  );
}
03

Hand off the dashboard

Your client opens theirsite.com/analytics-dashboard, enters their password, and reads their own analytics — same-origin, on their own domain, with no third-party subdomain in sight.

acme.com/analytics-dashboard

Analytics

Enter the password to continue

••••••••
View analytics

Under the hood

Two Go services and two embedded databases.

Events land on /api/collect and go straight into DuckDB, which is built for exactly this kind of counting. App data — your sites, keys and users — lives in SQLite, which doubles as the queue the SEO worker pulls audits off. No message broker, no managed database, nothing to bolt on.

Your sites
Client dashboard
/api/collect
core (Go)
DuckDB · events
SQLite · app data
SEO worker
Muke Johnbaptist

Muke Johnbaptist

Creator of Zenith — JB

A word from the creator

I build websites for clients, and the analytics part was always the ugly bit. Every site meant another third-party account, another cookie banner nobody wanted, and a dashboard on somebody else’s subdomain that my client had to be walked through every single time.

So Zenith is the thing I wanted instead: deploy it once, and it covers every site you build. The tracker is cookieless, so there is no banner to argue about. The dashboard lives on your client’s own domain, so it just looks like part of their site. And because you host it, the numbers stay yours — not rented back to you.

It is open-core and it runs on one box. If that is the kind of thing you have been looking for, I would genuinely like to hear how it goes.

Own your clients’ analytics.

No third-party subdomain, no cookie banner, no per-site setup. Deploy once and every site you build reports into it.