Star Whale Analytics Lab — Visitor Statistics with Umami

Written by

in

Star Whale Analytics Lab — Visitor Statistics with Umami

Self-hosting build series part 5. Taking data sovereignty to the mini-PC.


TL;DR

  • Google Analytics free = I give visitor data to Google servers + forced cookie consent pop-ups
  • Umami self-hosted = own analysis on mini-PC. No cookies, data owned by me, automatic exemption from GDPR
  • Docker Compose in 5 minutes. Automatic injection of one line tracker into WP = done
  • Display: visitor count, popular posts, traffic sources, devices, countries, dwell time

1. The Hidden Costs of Google Analytics

Item Google Analytics 4 Umami self-hosted
Cost Free (personal use) Free (open source)
Data Ownership Google Own mini-PC
Cookie Consent Popup Required (GDPR/CCPA) Unnecessary (0 cookies)
Page Load Load ~50KB JS ~2KB JS
User Tracking Cross-site (linked to Google ads) Same site only
South Korea PIPA Compliance Complicated Automatic exemption
Setup Complexity 1 hour+ 5 minutes

Google Analytics externalizes the real costs to the user (the visitor). Is it normal for Google to take all that data just because a visitor entered my site? For a personal blog, it is right to operate it ourselves.


2. Structure



When the visitor browser receives the Star Whale page, the script in the head <script defer src="https://analytics.sticknstone.org/script.js" data-website-id="..."> executes → asynchronous request to Umami → Umami logs to Postgres. The page display is not interrupted.


3. Docker Compose

/home/user/umami/docker-compose.yml:

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

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

volumes:
  umami_db:

.env:

APP_SECRET=$(openssl rand -hex 32)
DB_PASSWORD=$(openssl rand -hex 24)

Run:

cd /home/user/umami
docker compose up -d
curl -I http://localhost:3001  # HTTP/1.1 200

Default login: admin / umami. Change the password immediately.


4. Registering Star Whale + Receiving Tracker

Umami dashboard → Websites → Add Website:

Field Value
Name Star Whale Logbook
Domain sticknstone.org

Save → Click site → Edit → Tracking Code:

<script defer src="https://analytics.sticknstone.org/script.js" data-website-id="1892c870-dd4d-4ce7-9fd6-2635f8ef6220"></script>

5. Automatic Injection into WP — mu-plugin

The code is automatically placed, not manually by me for every post.

/var/www/html/wp-content/mu-plugins/umami-tracker.php:

<?php
/**
 * Plugin Name: Umami Analytics Tracker
 * Description: Injects Umami tracker into front-end pages. Excludes logged-in users.
 */
if (!defined('ABSPATH')) exit;

add_action('wp_head', function () {
    if (is_admin()) return;
    if (is_user_logged_in()) return;  // Exclude my own visits
    ?>
    <script defer src="https://analytics.sticknstone.org/script.js" data-website-id="1892c870-dd4d-4ce7-9fd6-2635f8ef6220"></script>
    <?php
}, 100);

Checking is_user_logged_in() = the number of times I’ve previewed my own posts will not be counted in the statistics. Surprisingly important.


6. What is Visible on the Dashboard

Screen Data
Overview Daily, weekly, monthly visitors, page views, sessions, dwell time
Pages Ranking of popular posts
Referrers Traffic sources (Google, Twitter, other sites)
Browsers Chrome, Safari, Firefox ratio
OS Windows, Mac, iOS, Android
Devices Desktop, mobile, tablet
Countries Visitors by country
Languages Browser languages
Events Clicks and downloads defined by me

Automatically updates every 5 seconds. Realtime menu = see who is currently viewing which page.


7. Reason to Handle Domain Linking Together

When the tracker is first received, the URL is http://192.168.0.x:3001/script.js (LAN IP). This causes:
– HTTP → Browser Mixed Content block
– LAN IP → Uninterpretable from external visitor PCs

Umami must be activated after connecting the domain (part 9). It needs to be exposed externally as analytics.sticknstone.org to function.


FAQ

Q. Is there a free cloud plan for Umami?
Umami Cloud starts at $9 per month. Self-hosted is unlimited and free. If you have a mini-PC, self-hosted is the answer.

Q. Can I migrate from Google Analytics?
No past data import. It’s a fresh start. However, both tools can be operational concurrently (both trackers can be placed).

Q. Do I need to worry about South Korea’s PIPA (Personal Information Protection Act)?
Umami does not store IP addresses (only hashes), and there are no cookies. It qualifies for PIPA exemption.

Q. Is there a mobile app?
No official app. The mobile web is responsive, so it displays well on phones.

Q. Can I export data as CSV?
CSV and JSON export are available on the dashboard. API is also provided.


Next Part Preview

Part 6 — Domain Fraud: Cloudflare Registrar. Reasons for purchasing from Cloudflare with Gabia and WhoIs (price, management integration, future Tunnel connection).


Summary in One Line

The real cost of Google Analytics is the externalization of user data. Umami self-hosted = 5 minutes of Docker on the mini-PC + automatic WP mu-plugin injection = data sovereignty + no cookies + the same information.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *