DEV Community

Elder Fernandes
Elder Fernandes

Posted on Originally published at selfhoststack-8z4.pages.dev

Self-Hosted Analytics in 2026: Ditch GA4 for Umami, Plausible, or PostHog

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.com and googletagmanager.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
Enter fullscreen mode Exit fullscreen mode

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}
    }
}
Enter fullscreen mode Exit fullscreen mode

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!
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Or trigger programmatically in TypeScript/JavaScript:

if (window.umami) {
  window.umami.track('Purchase Completed', { 
    revenue: 29.00, 
    currency: 'USD', 
    item: 'Self-Hosted Stack Pack' 
  });
}
Enter fullscreen mode Exit fullscreen mode

4. Why First-Party Proxying Beats Cloud SaaS

  1. Ad-Blocker Resilience: When tracking scripts load from stats.yourdomain.com directly, standard ad-blocking rules don't intercept first-party analytics requests.
  2. GDPR Exemption: Cookieless aggregate metrics do not store personal identifiable information (PII) or cross-site tracking profiles, eliminating compliance liability.
  3. 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)