Small Plates
Replacing Google Analytics
by Alex Lance
2026-05-18
5 minutes
tech
Let's ditch Google Analytics and self-host Matomo with Cloudflare Tunnels.
item
No offence Google, but you're a lot. I recently saw<br>this article<br>that mentions moving away from certain US based web services and then decided to<br>try and migrate my Google Analytics sites (eg Dibs) onto something else.
The why
I'm tired of the Google Analytics interface. It's slow. It needs to be<br>refreshed every time I go to the tab. The calendar picker is always behind.<br>It's annoying to track individual webpages. And swapping between different<br>accounts and properties one by one is ponderously clumsy.
Also maybe it's not such a great idea to pour money into Adwords,<br>and then use another Google product to measure the effectiveness of that spend.<br>Independently measuring that impact might be more prudent.
Momma's tomatoes
Enter Matomo*.<br>I know nothing about it. But, it does website traffic stats. It's open<br>source. It can be self-hosted. And I don't need to have cookie consent<br>popups for web visitors. It also takes measures on the backend to maintain<br>GDPR compliance.
*I'm still having trouble remembering the name. Momoto? Momatomato? It's a Benadryl Cabbagepatch for the brain.
Now, I didn't want to pay for a dedicated server to host Matomo. Nor for their<br>hosted solution. I briefly wondered about running Matomo in a serverless<br>fashion. Some sort of AWS Lambda situation with a shared storage/data backend?<br>Nope. Matomo needs a MariaDB/MySQL database. Normally I'd reach for an EC2<br>server or possibly an RDS... but I wanted to do this on the cheap.
The how
Maybe I could put one of the idle Raspberry Pi's in my cupboard to use?
I could run matomo on the Pi locally, and publish its endpoint to the world via a Cloudflare Tunnel.
So, Cloudflare has this Tunnels<br>product that allows you to expose private network services as though they were public. For free. As long<br>as you're using their DNS.
On the flipside, if any of my sites were to experience an absolutely hallucinogenic<br>level of web-traffic, there'd be a flood of analytics data headed for my home<br>network. It might suck. Ya know, let's burn that bridge when we get to it.
The point of no return
Installing Momatomato
Matomo provides a Docker Compose configuration file, so installing it is fairly simple provided<br>you've got a bit of docker up your sleeve. I grabbed their<br>docker compose configuration,<br>set the passwords, changed the volumes to bind-mounts and created the local directories (db-data, app-data).
docker-compose.yml
services:<br>db:<br>image: mariadb:latest<br>container_name: matomo-db<br>restart: unless-stopped<br>environment:<br>MYSQL_ROOT_PASSWORD: choose-a-password<br>MYSQL_DATABASE: matomo<br>MYSQL_USER: matomo<br>MYSQL_PASSWORD: choose-a-password<br>volumes:<br>- ./db-data:/var/lib/mysql
matomo:<br>image: matomo:latest<br>container_name: matomo-app<br>restart: unless-stopped<br>ports:<br># choose a local port that's available
- "9000:80"<br>environment:<br>MATOMO_DATABASE_HOST: db<br>MATOMO_DATABASE_USERNAME: matomo<br>MATOMO_DATABASE_PASSWORD: gumtr33<br>MATOMO_DATABASE_DBNAME: matomo<br>volumes:<br>- ./app-data:/var/www/html<br># I'll explain this down below
# - ./.htaccess:/var/www/html/.htaccess
depends_on:<br>- db
cron:<br>image: matomo:latest<br>container_name: matomo-cron<br>restart: unless-stopped<br>volumes:<br>- ./app-data:/var/www/html<br>entrypoint: ><br>/bin/sh -c "while true; do<br>php /var/www/html/console core:archive;<br>sleep 3000;<br>done"<br>depends_on:<br>- db
Then I ran docker compose up -d and navigated to http://localhost:9000 to complete the<br>Matomo installation process. If you're doing this too: immediately enable 2FA on the administrator account.
Cloudflare Tunnels
A Cloudflare Tunnel will give you a globally routable hostname, that can redirect people to resources that<br>you're hosting in your own private network, or in your own private cupboard.
Note: This is the pathway I chose because traffic statistics aren't<br>mission-critical for me. Collecting them on a Raspberry Pi is definitely<br>tempting the universe, but if it falls over, it falls over.
This approach also requires you to have the domain name hosted with Cloudflare. I.e. if you're<br>setting up the CNAME record stats.mydomain.com then you'll need to have the DNS for mydomain.com managed by<br>Cloudflare.
In the Cloudflare configuration you'll note that I've created separate<br>routes (redacted) pointing to my private Matomo server, one hostname for each<br>major web-property that I'm running. You don't have to do this of course,<br>perhaps you'd prefer one host to collect all stats for all your properties eg<br>bigstats.com.*
*Well, that's how I thought things were going to go, (spoilers) but<br>then uBlock Origin had something to say about it...
Anyway, you'll essentially be setting up new hostnames that redirect to<br>your private instance of Matomo (http://localhost:9000). This will require you<br>to install the Cloudflare daemon on your private endpoint, CF provides<br>you with the exact commands to run. This sort...