How to Self-Host Umami: Simple Google Analytics Alternative 2026
TL;DR
Umami is the simplest self-hosted analytics alternative to Google Analytics — no cookies, no personal data, GDPR compliant out of the box. MIT license, ~22K GitHub stars, built with Next.js and PostgreSQL. The tracking script is ~2KB. Deploy in 10 minutes with Docker Compose. If Plausible feels too complex (it needs ClickHouse), Umami is the right choice — just Postgres and a Node.js app.
Key Takeaways
- Umami: MIT license, ~22K stars, Next.js + Postgres, no cookies needed
- vs Plausible: Simpler to self-host (Postgres only, no ClickHouse), but fewer analytics features
- Script size: ~2KB vs Google Analytics' 45KB
- GDPR: No personal data collected, no cookie consent banner required
- Setup time: 10 minutes with Docker Compose
- Multi-site: One Umami instance tracks unlimited websites
Umami vs Plausible vs Google Analytics
| Feature | Umami | Plausible | Google Analytics 4 |
|---|---|---|---|
| License | MIT | AGPL 3.0 | Proprietary |
| Database | PostgreSQL | PG + ClickHouse | Cloud |
| Tracking script | ~2KB | <1KB | ~45KB |
| Cookies | None | None | Yes (consent required) |
| GDPR | ✅ Compliant | ✅ Compliant | Requires consent |
| Setup complexity | Low | Medium (ClickHouse) | N/A |
| Funnels | ❌ | ✅ | ✅ |
| Custom events | ✅ | ✅ | ✅ |
| GitHub Stars | ~22K | ~21K | — |
| Monthly cost | ~$3–6 VPS | ~$5–10 VPS | Free (data to Google) |
Choose Umami when: You want the simplest possible privacy-respecting analytics with minimal ops overhead. Choose Plausible when: You need funnels, better retention charts, and a more polished dashboard and are okay managing ClickHouse.
Part 1: Docker Compose Setup
Umami requires only two services: the app and PostgreSQL.
# docker-compose.yml
version: '3.8'
services:
umami:
image: ghcr.io/umami-software/umami:postgresql-latest
container_name: umami
restart: unless-stopped
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://umami:${POSTGRES_PASSWORD}@db:5432/umami
DATABASE_TYPE: postgresql
APP_SECRET: "${APP_SECRET}" # Generate: openssl rand -hex 32
DISABLE_TELEMETRY: 1
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: umami
POSTGRES_USER: umami
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
volumes:
- umami_db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U umami"]
interval: 10s
timeout: 5s
retries: 5
volumes:
umami_db:
# .env
POSTGRES_PASSWORD=strong-database-password
APP_SECRET=$(openssl rand -hex 32)
docker compose up -d
Visit http://your-server:3000 → log in with default credentials:
- Username:
admin - Password:
umami
Change the password immediately in Settings → Profile.
Part 2: HTTPS with Caddy
analytics.yourdomain.com {
reverse_proxy localhost:3000
}
Part 3: Add Your First Website
- Settings → Websites → Add website
- Enter domain:
yourdomain.com - Name:
My Website - Copy the tracking snippet
<!-- Add to your website's <head>: -->
<script
async
defer
data-website-id="your-website-id-here"
src="https://analytics.yourdomain.com/script.js">
</script>
Since the script is served from your own domain (not umami.is), it bypasses ad blockers that target the umami.is CDN.
Next.js Integration
// app/layout.tsx
import Script from 'next/script';
export default function RootLayout({ children }) {
return (
<html>
<head>
<Script
async
defer
data-website-id={process.env.NEXT_PUBLIC_UMAMI_ID}
src="https://analytics.yourdomain.com/script.js"
strategy="afterInteractive"
/>
</head>
<body>{children}</body>
</html>
);
}
WordPress Integration
Install the Umami Analytics plugin:
- Plugins → Add New → search "Umami Analytics"
- Settings → Umami Analytics → enter your Website ID and script URL
Part 4: Custom Events
Track button clicks, signups, and custom interactions:
<!-- HTML attribute-based tracking (no JS required): -->
<button
data-umami-event="signup-click"
data-umami-event-plan="pro">
Sign Up for Pro
</button>
<!-- Or via JavaScript: -->
<script>
document.getElementById('cta').addEventListener('click', function() {
umami.track('cta-click', { location: 'hero', variant: 'blue' });
});
</script>
Track Page Views in SPAs
Umami auto-tracks page views on navigation. For custom SPA route changes:
// Manually trigger page view:
umami.track('/dashboard');
// With custom data:
umami.track(props => ({
...props,
url: '/checkout',
title: 'Checkout Page',
}));
Part 5: Multiple Sites and Team Access
Add Multiple Websites
One Umami instance handles unlimited sites:
- Settings → Websites → Add website for each domain
- Each site gets a unique
data-website-id - All visible from one dashboard
User Management
Create team members with specific access:
- Settings → Users → Create user
- Assign websites each user can view
- Viewer role: read-only access to assigned sites
- Admin: full access
Share Dashboard Publicly
Create a shareable link for clients or stakeholders:
- Website → Edit → Enable share URL
- Get a public read-only link:
https://analytics.yourdomain.com/share/abc123 - No login required for viewers
Part 6: Umami API
Umami exposes a stats API for embedding data in dashboards:
# Get API token:
curl -X POST https://analytics.yourdomain.com/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"username": "admin", "password": "your-password"}'
# Returns: {"token": "your-jwt-token"}
# Get page views (last 24 hours):
curl "https://analytics.yourdomain.com/api/websites/{websiteId}/stats?startAt=0&endAt=86400000" \
-H "Authorization: Bearer your-jwt-token"
# Get top pages:
curl "https://analytics.yourdomain.com/api/websites/{websiteId}/metrics?type=url&startAt=0&endAt=86400000" \
-H "Authorization: Bearer your-jwt-token"
# Get active visitors (real-time):
curl "https://analytics.yourdomain.com/api/websites/{websiteId}/active" \
-H "Authorization: Bearer your-jwt-token"
Part 7: Self-Hosted vs Umami Cloud
| Self-Hosted | Umami Cloud | |
|---|---|---|
| Cost | VPS cost (~$3–6/month) | $9–$29/month |
| Setup time | 10 minutes | Instant |
| Data ownership | 100% yours | Umami's servers |
| Scaling | Manual | Automatic |
| Updates | Manual docker pull | Automatic |
| Websites | Unlimited | 3–20 |
For developers comfortable with Docker: self-host. For non-technical users or teams who don't want to maintain infrastructure: Umami Cloud at $9/month is reasonable.
Maintenance
# Update Umami:
docker compose pull
docker compose up -d
# Backup:
docker exec umami-db pg_dump -U umami umami | \
gzip > umami-backup-$(date +%Y%m%d).sql.gz
# Restore:
gunzip -c umami-backup-YYYYMMDD.sql.gz | \
docker exec -i umami-db psql -U umami -d umami
See all open source Google Analytics alternatives at OSSAlt.com/alternatives/google-analytics.