Skip to content

← Atlas

Migrate from Google Analytics 4 to Umami: Self-Hosted Guide

Umami is open-source self-host on Postgres/MySQL. Docker compose deployment + event mapping + proxy setup. Engineer-led teams.

When Umami is the right destination

Engineering-led teams who want a Plausible-style UI but on their own infrastructure. Privacy-strict environments where even EU-hosted SaaS isn’t acceptable. Cost-sensitive setups at high traffic volumes (own VPS = predictable cost).

Wrong if: you don’t have Postgres + Docker ops experience, or your real questions are e-commerce / product analytics shaped (use Matomo / PostHog instead).

Pre-migration checklist

  1. Provision infra. 1GB VPS minimum (Hetzner €4/mo works). Postgres or MySQL. Docker recommended.
  2. Decide hosting topology. Same domain (proxy /umami) or separate subdomain (umami.example.com).
  3. Plan data retention. Umami stores all events indefinitely by default. Configure retention before launch.
  4. Backup strategy. Postgres dumps daily. Umami’s tables grow ~1MB per 100k events.

Step-by-step

1. Deploy Umami (Day 1)

bash Docker compose deployment
<br />
cat > docker-compose.yml <<'YAML'
version: '3'
services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://umami:umami@db:5432/umami
      DATABASE_TYPE: postgresql
      APP_SECRET: 'change-this-to-random-string'
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: umami
    volumes:
      - umami-db:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  umami-db:
YAML

docker compose up -d
[/ma_code]



<h3>2. Add your site (Day 1)</h3>
<p>Login to Umami (default admin/umami — change immediately). Settings → Websites → Add. Copy the tracking code:</p>
[ma_code lang="html" title="Umami tracking script"]<br />
<script defer src="https://umami.example.com/script.js" data-website-id="abc123-uuid"></script><br />

3. Map GA4 events (Days 1-2)

js Umami event tracking
<br />
// GA4<br />
gtag(‘event’, ‘purchase’, { transaction_id: ‘T_123’, value: 99 });</p>
<p>// Umami equivalent<br />
umami.track(‘purchase’, { transaction_id: ‘T_123’, value: 99 });<br />

Umami accepts arbitrary event names + properties (up to 500 chars per property). No reserved-event constraints like GA4.

4. Configure proxy (Day 2)

Block ad-blockers by proxying through your domain:

nginx Nginx proxy config
<br />
location /stats/ {<br />
  proxy_pass https://umami.example.com/;<br />
  proxy_set_header Host umami.example.com;<br />
  proxy_set_header X-Real-IP $remote_addr;<br />
}<br />

Then update tracking script: data-host-url="https://yoursite.com/stats".

5. Dual-tag + cutover (Days 3-14)

Standard 10-day parallel run. Compare via Parallel-Run Validator. Cut GA4 once deltas are within tolerance.

Common gotchas

  • Database growth — Without retention, Umami’s events table grows linearly. Configure cleanup cron: DELETE FROM website_event WHERE created_at < NOW() - INTERVAL '13 months'.
  • Backup before upgrade — Umami v2 changed schema. Always pg_dump before docker compose pull.
  • Login security — Default admin/umami credentials are public. Change on first login or expose only via VPN.
  • Real-time view perf — Real-time dashboard queries `website_event` aggressively. Index on created_at + website_id if >1M events.

Frequently asked

Umami vs Plausible self-host?

Plausible self-host is heavier (Elixir, ClickHouse). Umami is lighter (Node, Postgres). Plausible has richer UI; Umami is simpler.

Can Umami handle 5M events/month?

Yes on a 4GB VPS with proper indexing. At 50M+ events/mo, ClickHouse-backed alternatives (Plausible, PostHog) scale better.

Is Umami GDPR-compliant out of the box?

Yes — no cookies, no fingerprinting, no PII collected by default. Configure retention to match your DPA.

Migration timeline for 100k pageviews/mo site?

1 day infra setup + 2 days mapping + 10 days dual-tag + 1 day cutover = 2 weeks elapsed, ~15 hours work.

What about reports / dashboards?

Umami has built-in dashboards. For Looker Studio / Metabase, use the Umami API.