Self Hosted Analytics with Matomo

It’s easy enough to host your own blog. Once you have a website running and the visitors start arriving, you’ll be left with the question how can I track and analyze my traffic?

The most popular choice is to use Google Analytics, and for good reason. Google makes it very easy to include analytic functionality. For the unfamiliar, analytics is a broad term that describes measuring user behavior across your webiste. You will be able to learn where your visitors are coming from, how long they spend on each page, track page rendering speed performance, compile stats on clicks, etc. Really useful stuff for any serious web property.

However Google Analytics has a downside. Big Tech is profiting off your data, and it’s common for adblock and browser plugins to obfuscate or disable their tracking techniques.

Now many users to your webiste won’t care, so you’re fine either way. But if you’re interesting in a self-hosted solution that lets you control and manage every bit of the tracking data, read on.

I use Matomo on this site. Read about it, decide if you’re interested, then head back here to get it installed.

Docker Setup

No surprise, we’re going to use Docker!

I have a special directory created in /docker/matomo, and the following docker-compose.yml:

version: "2"

services:
  matomo:
    image: matomo:4
    restart: unless-stopped
    volumes:
      - matomo:/var/www/html
    environment:
      - MYSQL_DATABASE=matomoDB
      - MYSQL_USER=matomoUser
      - MYSQL_PASSWORD=matomoPass
      - MYSQL_RANDOM_ROOT_PASSWORD=yes
    depends_on:
      - matomo-db
    labels:
      - traefik.enable=true
      - traefik.http.routers.bowtieddevil-matomo.entrypoints=websecure
      - traefik.http.routers.bowtieddevil-matomo.rule=Host(`stats.bowtieddevil.com`)
      - traefik.http.services.bowtieddevil-matomo.loadbalancer.server.port=80

  matomo-db:
    image: mariadb:10
    command: --max-allowed-packet=64MB
    restart: unless-stopped
    volumes:
      - matomo-db:/var/lib/mysql
    environment:
      - MATOMO_DATABASE_HOST=matomo-db
      - MATOMO_DATABASE_ADAPTER=mysql
      - MATOMO_DATABASE_TABLES_PREFIX=matomo_
      - MATOMO_DATABASE_USERNAME=matomoUser
      - MATOMO_DATABASE_PASSWORD=matomoPass
      - MATOMO_DATABASE_DBNAME=matomoDB


volumes:
  matomo:
  matomo-db:

networks:
  default:
    name: matomo

Note that this interacts with the Traefik reverse proxy via the labels section above. I have set up my analytics using the subdomain stats.bowtieddevil.com.

Be sure to add the traefik container (defined elsewhere) to the matomo network using docker network connect matomo traefik. After that, Traefik will be able to relay between the user and the Matomo container.

Start and Setup

Bring the stack up with docker-compose up -d and head to your special URL. From there, you will complete the Matomo installer and configure your user. It will also give you a special code block with Javascript tracking code for inclusion on all of your pages. The specifics of your particular blogging software are beyond the scope of this tutorial, so please ask on Twitter, read the documentation, or search Google for the exact way to inject this tracking code into your pages.

In my case, here is the tracking code:

<!-- Matomo -->
<script type="text/javascript">
  var _paq = window._paq = window._paq || [];
  /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
  _paq.push(['trackPageView']);
  _paq.push(['enableLinkTracking']);
  (function() {
    var u="https://stats.bowtieddevil.com/";
    _paq.push(['setTrackerUrl', u+'matomo.php']);
    _paq.push(['setSiteId', '1']);
    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
    g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
  })();
</script>
<noscript><p><img src="https://stats.bowtieddevil.com/matomo.php?idsite=1&amp;rec=1" style="border:0;" alt="" /></p></noscript>
<!-- End Matomo Code -->

You’ll notice it includes a tracking pixel for any noscript users, so all visits will be tracked.

If you view the source for any page here, you’ll see this code appearing in the HTML footer.

Post-Setup Configuration

Once you’ve installed this,I recommend visiting the Administration > Privacy > Users opt-out section. By default, “Do Not Track” support is enabled. Any visitors to your site that have the option checked will not be recorded. It’s your choice here, since “Do Not Track” is an optional preference with no enforcement.

You can also choose the level of anonymization of user visits. Personally, I have this set to anonymize user data to 2 bytes (192.168.xxx.xxx), but pass the full IP to plugins like Geolocation so I can accurately determine country of origin and ISP.

Newsletter

Tip Jar

If you're getting value from my writing, please support my efforts with a donation. You can donate directly using my public Ethereum address bowtieddevil.eth. Or you can use the donation button below, which works through my self-hosted BTCPay Server.

See also