Matomo (formerly Piwik) is the most complete open-source web analytics platform: visitors, pages, referrers, campaigns, goals, e-commerce, funnels and real-time dashboards, comparable to Google Analytics, but with the data stored on your server. Many organisations choose it for privacy compliance, data ownership, and avoiding sampling.

Want something much simpler? See Plausible and Umami.

Requirements

Traffic VPS
< 100k page views/month 2 vCPU, 2–4 GB RAM
~1M page views/month 4 vCPU, 8 GB RAM, separate DB tuning
More Dedicated DB server, queued tracking, Redis

Matomo uses PHP (8.1+) and MySQL/MariaDB, and the database grows with traffic.

Install on a LEMP server

sudo apt install nginx mariadb-server php-fpm php-mysql php-xml php-mbstring php-curl php-gd php-intl php-zip unzip
cd /var/www
sudo wget https://builds.matomo.org/matomo-latest.zip
sudo unzip matomo-latest.zip && sudo rm matomo-latest.zip
sudo chown -R www-data:www-data /var/www/matomo

Create the database:

CREATE DATABASE matomo CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'matomo'@'localhost' IDENTIFIED BY 'a-strong-password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON matomo.* TO 'matomo'@'localhost';

Nginx essentials (Matomo provides a full recommended config):

server {
    server_name analytics.example.com;
    root /var/www/matomo;
    index index.php;

    location ~ ^/(index|matomo|piwik|js/index|plugins/HeatmapSessionRecording/configs)\.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
    location ~* ^.+\.php$ { deny all; return 403; }      # only allow the PHP entry points above
    location ~ ^/(config|tmp|core|lang) { deny all; return 403; }
    location ~ /\.ht { deny all; }
    location ~ js/container_.*_preview\.js$ { expires off; add_header Cache-Control 'private, no-cache, no-store'; }
    location ~ \.(gif|ico|jpg|png|svg|js|css|htm|html|mp3|mp4|wav|ogg|avi|ttf|eot|woff|woff2)$ {
        allow all; expires 1h; add_header Pragma public; add_header Cache-Control "public";
    }
}

Add HTTPS (certbot --nginx), open the site, and complete the installer: system check, database, super user, first website. See Nginx with PHP-FPM and Let’s Encrypt.

A Docker image (matomo, with MariaDB) is also available.

Add the tracking code

Matomo shows a JavaScript snippet for each site. Add it to your site’s <head>, or use plugins for WordPress and other CMSs. For better resistance to ad blockers, serve the tracker from your own domain. Matomo also supports server-side tracking via its HTTP API, and log import (misc/log-analytics/import_logs.py) from Nginx access logs.

Archiving via cron (important for performance)

By default, reports are processed when someone views them in the browser, which is slow and heavy on busy sites. Switch to cron archiving:

  1. Administration → System → General settings: set “Archive reports when viewed from the browser” to No.
  2. Add a cron job:
5 * * * * www-data /usr/bin/php /var/www/matomo/console core:archive --url=https://analytics.example.com/ > /var/log/matomo-archive.log 2>&1

See crontab.

Privacy and GDPR

Matomo can be configured for privacy-friendly analytics:

  • Anonymise IPs (2 bytes), and respect Do Not Track;
  • cookieless tracking (disableCookies) and shorter data retention (Privacy → Anonymise data, Delete old raw data);
  • a consent integration, if you keep cookies or user IDs;
  • opt-out iframe or JavaScript for your privacy policy.

Requirements vary by jurisdiction. Some EU regulators accept specially configured Matomo without consent banners. Check what applies to you.

GeoIP

Install the DBIP or MaxMind GeoLite2 database (Administration → System → Geolocation) for country and city reports. It updates automatically when configured.

Maintenance

  • Database growth: enable deletion of old raw logs (keep aggregated reports). Tune MySQL. See MySQL performance tuning.
  • Backups: mysqldump the database plus config/config.ini.php. See mysqldump.
  • Updates: a one-click updater, or ./console core:update. Keep plugins compatible. See updating self-hosted apps.
  • Security: a strong super-user password, 2FA (a core plugin), and HTTPS.

Quick reference

Task Command / setting
Archive reports ./console core:archive --url=… (cron)
Disable browser archiving General settings → No
Update ./console core:update
Config file config/config.ini.php
Import logs misc/log-analytics/import_logs.py

Related: Plausible vs Umami and PHP-FPM tuning.

  • Self-Hosting
  • Analytics
  • Privacy