All Newbie, Semua Tentang Ilmu

Recent

Umami: Analytics Web Self-Hosted Tanpa Cookie dan Tanpa Google

Kalau yang Anda butuhkan hanya jumlah kunjungan, halaman yang paling dibaca, dan dari mana pengunjung datang, Google Analytics 4 terasa seperti memakai truk untuk membeli sayur. GA4 memasang cookie, sering memaksa consent banner, dan mengirim data kunjungan ke server Google. Untuk blog pribadi, dokumentasi internal, atau situs UMKM, itu pertukaran yang tidak sepadan. Umami menawarkan jalan lain: satu script kecil, tanpa cookie, dan seluruh data tersimpan di database Anda sendiri.

Tangkapan layar dasbor analytics dengan grafik kunjungan
Foto: Visitor analytics, CC BY-SA 4.0, via Wikimedia Commons

Ringkasan singkat

  • Umami adalah analytics web open source yang tidak memakai cookie dan menyimpan data di database sendiri.
  • Instalasinya hanya dua container: aplikasi Umami dan PostgreSQL, dijalankan lewat Docker Compose.
  • Script pelacak dipasang satu baris sebelum </head>, dan event khusus bisa ditambahkan lewat atribut HTML.
  • Backup cukup satu perintah pg_dump, upgrade cukup docker compose pull.

Masalah dengan GA4 untuk kebutuhan sederhana

Google Analytics 4 adalah produk yang dirancang untuk tim marketing dengan analis data. Struktur event-nya, laporan eksplorasi, dan istilah seperti "engagement rate" atau "model atribusi" masuk akal bagi orang yang memakainya setiap hari. Bagi pemilik blog yang hanya ingin tahu artikel mana yang dibaca dan dari mesin pencari mana asalnya, antarmuka itu justru menambah pekerjaan.

Ada tiga masalah lain yang lebih substantif. Pertama, GA4 bergantung pada cookie dan identifier, sehingga di banyak yurisdiksi Anda perlu menampilkan consent banner sebelum pelacakan boleh berjalan. Kedua, data mentah kunjungan dikirim ke infrastruktur Google, dan Anda tidak punya kendali penuh atas retensi maupun pemrosesannya. Ketiga, script GA4 cukup besar untuk situs yang isinya teks; itu berat yang dibayar setiap pengunjung.

Bukan berarti GA4 buruk. Kalau Anda butuh funnel, audiens, integrasi iklan, dan atribusi lintas kanal, GA4 memang alat yang tepat. Persoalannya adalah memilih alat sesuai pertanyaan yang ingin dijawab.

Apa itu Umami

Umami adalah aplikasi analytics web open source dengan lisensi MIT. Aplikasi ini ditulis dengan Next.js dan menyimpan data kunjungan di database relasional milik Anda sendiri. Karena tidak memakai cookie dan tidak menyimpan identifier pribadi, umumnya Anda tidak perlu consent banner hanya untuk analytics. Script pelacaknya kecil, jauh lebih ringan daripada tag analytics pada umumnya.

Yang dicatat Umami adalah hal-hal dasar: pageview, referrer, browser, sistem operasi, perangkat, negara, dan event kustom. Tidak ada heatmap, tidak ada session recording, tidak ada laporan lintas perangkat. Justru pembatasan itu yang membuatnya cepat dan mudah dibaca.

Tabel berikut membandingkan tiga pilihan yang paling sering dipertimbangkan untuk blog atau situs kecil.

KriteriaUmami (self-host)GA4Plausible (self-host)
CookieTidak adaAda, butuh consentTidak ada
Lokasi dataServer AndaServer GoogleServer Anda
Resource serverAplikasi + PostgreSQLTidak ada (SaaS)Aplikasi + PostgreSQL + ClickHouse
Biaya lisensiGratis (MIT)Gratis, data ditukarGratis (AGPL-3.0)
KemudahanSatu file composeDaftar akun, pasang tagButuh dua database

Arsitektur: aplikasi dan database

Umami tidak memerlukan Redis, message queue, atau worker terpisah. Ada dua komponen: aplikasi Umami yang melayani API, script pelacak, dan dashboard; lalu PostgreSQL tempat semua data kunjungan disimpan. Script yang Anda tempel di situs hanya mengirim POST kecil ke endpoint aplikasi, dan aplikasi menuliskannya ke database.

Browser pengunjung script.js (async) Umami app (Next.js) PostgreSQL port 5432 Admin (browser) Dashboard Umami
Diagram: alur pageview dan akses dashboard Umami (dibuat sendiri)

Konsekuensi praktisnya: kalau aplikasi mati, script di situs Anda tetap termuat tetapi kunjungan tidak tercatat. Tidak ada data yang "tertahan" di pihak ketiga, dan tidak ada cara memulihkannya. Karena itu monitoring uptime dan backup database perlu dipikirkan sejak awal, bukan setelah data setahun hilang.

Menjalankan Umami dengan Docker Compose

Buat direktori kerja, misalnya /opt/umami, lalu siapkan file compose. Image yang dipakai adalah varian PostgreSQL resmi dari proyek Umami di GitHub Container Registry. Jangan tertukar dengan image lama ghcr.io/umami-software/umami:latest yang ditujukan untuk database lain.

Buat APP_SECRET lebih dulu:

openssl rand -hex 32

Salin hasilnya ke docker-compose.yml di bawah ini.

services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    container_name: umami
    ports:
      - "3000:3000"
    environment:
      DATABASE_TYPE: postgresql
      DATABASE_URL: postgresql://umami:umami@db:5432/umami
      APP_SECRET: hasil_openssl_rand_hex_32
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    container_name: umami-db
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: umami
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U umami -d umami"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

volumes:
  db-data:

Beberapa hal yang perlu diperhatikan. DATABASE_URL memakai hostname db karena kedua container berada di network Compose yang sama, bukan localhost. depends_on dengan condition: service_healthy memastikan Umami baru start setelah PostgreSQL benar-benar menerima koneksi, bukan sekadar setelah container hidup. Volume db-data wajib ada; tanpa itu semua data hilang saat container dibuat ulang. Kalau port 3000 sudah terpakai, ubah sisi kiri menjadi "3100:3000".

Nyalakan dan lihat log:

docker compose up -d
docker compose ps
docker compose logs -f umami

Kalau berjalan normal, http://IP-SERVER:3000 akan menampilkan halaman login Umami. Pada tahap ini jangan langsung dipakai publik; akses lewat IP dan HTTP polos berarti password admin Anda lewat jaringan tanpa enkripsi.

Reverse proxy dan HTTPS

Umami sebaiknya tidak diekspos langsung. Letakkan di belakang reverse proxy yang menangani TLS, sehingga script pelacak bisa dimuat lewat https://. Ini penting karena situs yang memakai HTTPS tidak akan menjalankan script HTTP (mixed content).

Nginx

Tambahkan blok server berikut, lalu pasang sertifikat dengan Certbot seperti pada panduan Let's Encrypt untuk Nginx.

server {
    listen 80;
    server_name stats.contoh.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Empat header di atas bukan formalitas. Tanpa X-Forwarded-For, semua pengunjung akan terlihat berasal dari IP reverse proxy, dan statistik negara Anda akan menunjuk ke satu titik. X-Forwarded-Proto memastikan Umami tahu koneksi aslinya HTTPS, sehingga cookie sesi dashboard ditandai dengan benar.

Kalau Anda mengelola banyak domain, pola blok server seperti ini bisa dirapikan dengan include agar tidak berulang.

Caddy

Dengan Caddy, konfigurasi dan sertifikat TLS otomatis cukup ditulis dua baris:

stats.contoh.com {
    reverse_proxy 127.0.0.1:3000
}

Caddy meneruskan header X-Forwarded-For dan X-Forwarded-Proto secara default, jadi tidak ada tambahan yang perlu ditulis. Ini alasan banyak homelab beralih ke Caddy untuk layanan internal.

Mengaktifkan dashboard dan memasang script

Buka https://stats.contoh.com. Login pertama memakai kredensial default admin / umami. Segera ganti password dari menu pengaturan; jangan biarkan default itu hidup lebih dari lima menit, apalagi jika port 3000 terbuka ke internet.

Setelah itu, tambahkan website baru: isi nama dan domain, misalnya blog.contoh.com. Umami akan membuat website ID berupa UUID dan menampilkan potongan script yang harus dipasang. Letakkan tepat sebelum </head> di template situs Anda:

<script async src="https://stats.contoh.com/script.js" data-website-id="UUID"></script>

Atribut async membuat script tidak menahan render halaman. Ganti UUID dengan ID dari dashboard. Buka situs di tab lain, lalu kembali ke dashboard: pageview pertama biasanya muncul dalam beberapa detik.

Event tracking

Selain pageview, Umami bisa mencatat aksi tertentu, misalnya klik tombol unduh atau submit form. Cara paling sederhana adalah atribut pada elemen HTML, tanpa JavaScript tambahan:

<a href="/panduan.pdf" data-umami-event="unduh-panduan">Unduh panduan</a>

Untuk kasus yang butuh logika, gunakan API global. Perlu diingat: objek umami baru tersedia setelah script selesai dimuat, jadi panggilan yang berjalan terlalu awal akan gagal dengan umami is not defined. Bungkus dalam event yang terjadi setelah halaman siap, atau periksa keberadaannya lebih dulu.

if (typeof umami !== "undefined") {
  umami.track("selesai-baca");
}

Nama event sebaiknya pendek, huruf kecil, dan konsisten. Dashboard akan mengelompokkan event berdasarkan nama tersebut, jadi unduh-panduan dan Unduh Panduan akan dihitung sebagai dua event berbeda.

Backup dan upgrade

Seluruh nilai instalasi ini ada di database. Backup rutin cukup satu perintah, dijalankan dari direktori compose:

docker compose exec db pg_dump -U umami umami > backup.sql

Simpan hasilnya di luar server, misalnya ke object storage, dan jadwalkan lewat systemd timer atau cron. Untuk restore, salurkan file kembali ke psql:

cat backup.sql | docker compose exec -T db psql -U umami umami

Upgrade mengikuti pola container biasa. Image postgresql-latest diperbarui lebih sering, jadi baca catatan rilis sebelum melompati banyak versi.

docker compose pull
docker compose up -d

Setelah upgrade, cek log dan pastikan dashboard masih memuat data lama. Kalau migrasi skema gagal, container akan restart berulang; di titik itu backup adalah satu-satunya jalan kembali.

Troubleshooting

Container Umami restart terus dengan "connection refused"

Hampir selalu berarti aplikasi tidak bisa menghubungi PostgreSQL. Periksa docker compose logs db dan pastikan healthcheck lulus. Penyebab umum: DATABASE_URL memakai localhost alih-alih db, password di URL tidak sama dengan POSTGRES_PASSWORD, atau volume berisi data lama dari percobaan sebelumnya dengan kredensial berbeda. Kalau volume memang berasal dari uji coba, hapus volume tersebut dan mulai ulang; kalau berisi data nyata, perbaiki kredensialnya, jangan dihapus.

Dashboard kosong, tidak ada kunjungan sama sekali

Urutan pemeriksaan yang paling cepat: buka situs di jendela incognito dengan adblock dimatikan, lalu lihat tab Network di developer tools dan cari request ke /api/send. Kalau request tidak ada, script belum terpasang atau diblokir. Kalau request ada tetapi dashboard tetap kosong, data-website-id kemungkinan salah atau menunjuk ke website lain. Perhatikan juga bahwa sebagian pemblokir iklan memblokir domain analytics secara default, termasuk domain dengan kata "stats" atau "analytics" di dalamnya; itu bagian dari alasan angka di dashboard selalu lebih rendah daripada hit di log web server.

Semua kunjungan tercatat sebagai satu IP yang sama

Itu IP reverse proxy Anda. Umami membaca IP asli dari header X-Forwarded-For atau X-Real-IP, dan header itu hanya ada kalau proxy meneruskannya. Periksa blok server Nginx dan pastikan kedua header tersebut di-set. Kalau Anda memakai Cloudflare Tunnel atau CDN lain sehingga jumlah proxy lebih dari satu, set variabel TRUSTED_PROXIES berisi rentang IP proxy Anda; tanpa itu Umami bisa berhenti pada alamat internal seperti 10.0.0.8 alih-alih IP pengunjung.

Script tidak jalan di situs HTTPS

Browser memblokir permintaan campuran: halaman HTTPS tidak boleh memuat script dari http://. Pastikan URL di tag src memakai https://, sertifikat di domain analytics valid, dan tidak ada redirect yang berakhir di HTTP. Gejala khasnya adalah error mixed content di console dan tidak ada request sama sekali di tab Network.

Kesimpulan

Umami cocok kalau pertanyaan Anda tentang traffic bersifat dasar dan Anda ingin data itu tetap di server sendiri. Biaya operasionalnya rendah: dua container, satu database, satu perintah backup. Yang perlu Anda terima adalah daftar fitur yang sengaja dibatasi; tidak ada atribusi lintas perangkat atau integrasi iklan, dan itu memang bukan tujuannya. Sebelum memutuskan, hitung dulu pertanyaan apa yang benar-benar akan Anda ajukan ke data tersebut. Kalau jawabannya hanya "halaman mana yang dibaca dan dari mana asalnya", Umami sudah lebih dari cukup, dan Anda tidak perlu membayar dengan cookie serta consent banner.

Baca juga: Cara Install Docker di Ubuntu 24.04 + Container Pertama · Docker Compose yang Tidak Berantakan Setelah 20 Container · Cara Setting Nginx Reverse Proxy untuk Banyak Domain · Cara Pasang SSL Let's Encrypt di Nginx (Ubuntu 24.04) · How to Use Caddy as a Reverse Proxy with Automatic HTTPS · Cara Self-Host Vaultwarden: Password Manager Pribadi · Cara Memakai Cloudflare Tunnel: Akses Server Tanpa Buka Port

Sumber: umami.is/docs · github.com/umami-software/umami · hub.docker.com/r/umami-software/umami





0 comments:

Post a Comment