My website ran on Google Analytics for a long time — consent banner and cookie management included. After switching to Umami Analytics, all of that is gone. No banner, no cookies, no data in the US. Here's why I switched and what the migration actually looked like.
The Problem with Google Analytics
Google Analytics is powerful. But for a straightforward business website, it comes with a lot of overhead:
- ~50 KB tracking script that affects load times
- Cookie banner required under GDPR — every visitor must actively consent
- Data transfer to the US — legally problematic, especially for Austrian and German businesses
- Consent rate below 50% — half of all visitors are invisible in GA because they declined
That last point bothered me most. I could only see a fraction of my actual visitors because the other half dismissed the banner.
Why Umami
Umami is an open-source web analytics alternative with a clear focus:
- Cookie-free — no cookies, no consent banner required
- ~2 KB script — 25× smaller than GA4
- Privacy-compliant by default — no personal data, no plain-text IP addresses stored
- Self-hosted — full control, data stays on my servers
- MIT license — free, no hidden costs
- Multi-site — one instance for multiple projects
The key point: Umami can be operated without consent under GDPR and Austrian TKG 2021 because no personal data is processed. No banner, no consent management, no added complexity.
My Architecture
I run Umami on the same Hetzner VPS as my other tools:
analytics.example.com
↓ nginx (reverse proxy, Let's Encrypt SSL)
Docker Container (Umami Node.js app)
↓ SSL connection
Hetzner Managed PostgreSQL
└── Schema: umami (isolated from everything else)
Deliberate decisions:
- No dedicated Postgres — I reuse the existing Hetzner Managed DB with a dedicated
umamischema, fully isolated from the rest of the database
The Migration in Detail
1. Prepare Infrastructure
Create the schema in the existing Postgres database:
CREATE SCHEMA IF NOT EXISTS umami;
GRANT USAGE, CREATE ON SCHEMA umami TO youruser;
Docker Compose for Umami (/opt/umami/docker-compose.yml):
services:
umami:
image: docker.umami.is/umami-software/umami:postgresql-latest
container_name: umami
restart: unless-stopped
ports:
- '127.0.0.1:3002:3000'
environment:
DATABASE_URL: ${DATABASE_URL}
DATABASE_TYPE: postgresql
APP_SECRET: ${APP_SECRET}
DISABLE_TELEMETRY: '1'
NODE_EXTRA_CA_CERTS: /etc/ssl/certs/hetzner-ca.crt
volumes:
- /opt/umami/ca.crt:/etc/ssl/certs/hetzner-ca.crt:ro
I extracted the Hetzner Managed DB server certificate directly from the TLS handshake and trusted it via NODE_EXTRA_CA_CERTS:
openssl s_client -connect db-host:5432 -starttls postgres 2>/dev/null </dev/null \
| sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' \
| tee /opt/umami/ca.crt
2. nginx vhost + SSL
server {
listen 443 ssl http2;
server_name analytics.example.com;
location / {
proxy_pass http://127.0.0.1:3002;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
SSL via Certbot, as usual.
3. Nuxt Integration
In nuxt.config.ts — the script is only injected when the env var is set:
script: process.env.NUXT_PUBLIC_UMAMI_ID ? [
{
src: 'https://analytics.example.com/script.js',
'data-website-id': process.env.NUXT_PUBLIC_UMAMI_ID,
defer: true,
},
] : [],
Plus a small composable for custom events:
// composables/useUmami.ts
export function trackEvent(
event: string,
data?: Record<string, unknown>,
): void {
if (import.meta.client && window.umami) {
window.umami.track(event, data)
}
}
4. Remove the Cookie Banner
Since Umami sets no cookies, the banner is simply no longer needed. Two lines removed from the layouts — done.
What I Gained
| Google Analytics | Umami | |
|---|---|---|
| Script size | ~50 KB | ~2 KB |
| Cookies | Yes (consent required) | No |
| Consent banner | Yes | No |
| Data location | Google (US) | Own server (DE) |
| Visible visitors | ~50% | 100% |
| Cost | Free (data = price) | Self-hosted |
| Setup effort | Low | Medium (one-time) |
The biggest practical win: complete visitor visibility. No visitors disappearing through the consent banner.
When Umami Is Not Enough
Umami is not a GA replacement for every use case. If you need any of the following, stick with GA or choose a different solution:
- Deep conversion funnels with attribution (e.g. Google Ads integration)
- Remarketing audiences for Google/Meta Ads
- E-commerce tracking with revenue data
For a business website, a blog, or a SaaS dashboard, Umami is more than sufficient.
Conclusion
The migration took a few hours and was worth it. I now see more data than before — no banner, no cookies, no data at Google. For projects that take GDPR compliance seriously, Umami is a clear recommendation.