Self-Hosted Analytics in 2026: Ditch GA4 for Umami, Plausible, or PostHog
Google Analytics 4 (GA4) has become a nightmare for developers and privacy-conscious founders:
- Intrusive Cookie Banners: GA4 sets tracking cookies that trigger mandatory GDPR / ePrivacy consent banners across the EU and UK.
- Heavy Frontend Overhead: Google Tag Manager + GA4 JS payloads exceed 45KB–80KB of client overhead, harming Core Web Vitals and PageSpeed scores.
-
Severe Data Loss (30–50%): Brave, Firefox Enhanced Tracking Protection, Safari ITP, uBlock Origin, and DNS blockers routinely block
google-analytics.comandgoogletagmanager.com. - Complex, Cluttered UI: Generating basic funnel or pageview reports requires navigating confusing menus and sampled data models.
By self-hosting modern open-source web analytics, you serve the script from your own first-party subdomain (e.g. stats.yourdomain.com), load a tiny < 2KB script, respect user privacy without cookie popups, and recover 100% of your visitor metrics.
Which Tool Should You Choose?
| Feature | Umami | Plausible CE | PostHog Open-Source |
|---|---|---|---|
| Primary Use-Case | Lightweight web analytics & custom events | Clean SaaS/Blog visitor analytics | Full product analytics, feature flags & session recording |
| Script Weight | < 2 KB | < 1 KB | ~40 KB (full SDK) |
| Cookies Needed | ❌ No (Cookieless) | ❌ No (Cookieless) | Optional / Configurable |
| Database | PostgreSQL | PostgreSQL + ClickHouse | ClickHouse + PostgreSQL + Redis + Kafka |
| Minimum RAM | 512 MB | 2 GB | 4 GB - 8 GB |
| Best For | Indie hackers, blogs, fast SaaS, client sites | Modern SaaS dashboards & marketing sites | Product teams needing deep event funnels & replays |
Option 1: Umami — Ultra-Lightweight & Zero Hassle (< 2KB Script)
Umami is the easiest and lightest analytics platform to self-host. It runs effortlessly on a $4/mo Hetzner or DigitalOcean VPS alongside your other apps.
Production docker-compose.yml
version: "3.8"
networks:
analytics-net:
driver: bridge
volumes:
umami-db-data:
caddy-data:
caddy-config:
services:
# --- Reverse Proxy with Auto HTTPS ---
caddy:
image: caddy:2-alpine
container_name: analytics-caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
networks:
- analytics-net
depends_on:
- umami
# --- Umami App ---
umami:
image: ghcr.io/umami-software/umami:postgresql-latest
container_name: umami-app
restart: unless-stopped
environment:
DATABASE_URL: postgresql://umami_user:SuperSecretPassword123!@umami-db:5432/umami_db
DATABASE_TYPE: postgresql
APP_SECRET: generate-a-random-32-char-string-here-12345
CLIENT_IP_HEADER: X-Forwarded-For
networks:
- analytics-net
depends_on:
umami-db:
condition: service_healthy
# --- PostgreSQL Database ---
umami-db:
image: postgres:16-alpine
container_name: umami-db
restart: unless-stopped
environment:
POSTGRES_DB: umami_db
POSTGRES_USER: umami_user
POSTGRES_PASSWORD: SuperSecretPassword123!
volumes:
- umami-db-data:/var/lib/postgresql/data
networks:
- analytics-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U umami_user -d umami_db"]
interval: 5s
timeout: 5s
retries: 5
Caddyfile Configuration
stats.yourdomain.com {
encode gzip zstd
reverse_proxy umami:3000 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
2. Deploying in 60 Seconds
# 1. Clone or create folder
mkdir -p /opt/analytics && cd /opt/analytics
# 2. Generate random APP_SECRET
sed -i "s/generate-a-random-32-char-string-here-12345/$(openssl rand -hex 16)/g" docker-compose.yml
# 3. Start containers
docker compose up -d
# 4. Access dashboard
# Open https://stats.yourdomain.com
# Default login: username 'admin', password 'umami'
# IMMEDIATELY change your password in Settings -> Profile!
3. Integrating the Script on Your Website
Add this single tag to your website's <head>:
<script
defer
src="https://stats.yourdomain.com/script.js"
data-website-id="YOUR-UMAMI-WEBSITE-UUID"
></script>
Custom Event Tracking (e.g. Button Clicks & Form Submissions)
<!-- Track a sign-up button click -->
<button
class="btn-primary"
data-umami-event="Signup Button Click"
data-umami-event-plan="Pro Monthly"
>
Start Free Trial
</button>
Or trigger programmatically in TypeScript/JavaScript:
if (window.umami) {
window.umami.track('Purchase Completed', {
revenue: 29.00,
currency: 'USD',
item: 'Self-Hosted Stack Pack'
});
}
4. Why First-Party Proxying Beats Cloud SaaS
-
Ad-Blocker Resilience: When tracking scripts load from
stats.yourdomain.comdirectly, standard ad-blocking rules don't intercept first-party analytics requests. - GDPR Exemption: Cookieless aggregate metrics do not store personal identifiable information (PII) or cross-site tracking profiles, eliminating compliance liability.
- Zero Variable Invoices: Enterprise SaaS tools charge tiered fees as your traffic scales ($50-$500/mo). A $4/mo VPS can easily serve 5,000,000+ pageviews/month on PostgreSQL.
Need Production-Ready Templates for Your Whole Stack?
Looking for tested Docker Compose stacks with automated SSL, daily encrypted backups, and security hardening for 30+ open-source tools?
👉 Explore our interactive directory and guides at SelfHostStack, or grab the Self-Hosted Starter Stack Pack ($29) for turnkey production templates, Caddy configs, and one-line backup scripts.
Top comments (0)