Using Matomo on Angular
Published: 2022-05-03 10:41:49

If you haven’t heard about [Matomo](https://matomo.org/), yet, then you should check this out.

Matomo is a 
> “Google Analytics alternative that protects your data and your customers' privacy” and that “gives you 100% data ownership”.

This is great news for those of you who are GDPR aware and unfortunately (for some) aren’t able to use cloud services like Google Analytics.

## OK, so where can we start?

On this guide, I’ll help you configure an “on-premise” installation of Matomo using Docker with nginx, and running it on Angular.

## Reference material

All the info I’m sharing can be found at [matomo-org/docker](https://github.com/matomo-org/docker) and [EmmanuelRoux/ngx-matomo](https://github.com/EmmanuelRoux/ngx-matomo).

Some tweaks can be found in my git [matomo-angular-docker](https://github.com/fborges42/matomo-angular-docker)

I’m also assuming you already installed docker on your machine.

## Setting up your docker

This setup is for Matomo version 3 and includes a database with MySQL image (you could use MariaDB as well), the Matomo app and the web using nginx. 

First thing is first, let’s get the `docker-compose.yaml` file. 

```yaml
version: "3"

services:
  db:
    image: mysql
    command: --max-allowed-packet=64MB
    restart: always
    volumes:
      - db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=matomo
    env_file:
      - ./db.env

  app:
    image: matomo:fpm-alpine
    restart: always
    links:
      - db
    volumes:
      - matomo:/var/www/html
    environment:
      - MATOMO_DATABASE_HOST=db
      - PHP_MEMORY_LIMIT=2048M
    env_file:
      - ./db.env

  web:
    image: nginx:alpine
    restart: always
    volumes:
      - matomo:/var/www/html:ro
      - ./matomo.conf:/etc/nginx/conf.d/default.conf:ro
    ports:
      - 8080:80

volumes:
  db:
  matomo:
```

Nothing fancy here, Matomo will be running on port 8080, and you can of course change the values like `MYSQL_ROOT_PASSWORD` or the restart option (which if you don’t know, keeps restarting the container in case of failure).

In case you didn’t notice, we’re referencing two other files in this compose.

The `db.env` where we will set some variables for MySQL image

```yaml
MYSQL_PASSWORD=matomo
MYSQL_DATABASE=matomo
MYSQL_USER=matomo
MATOMO_DATABASE_ADAPTER=mysql
MATOMO_DATABASE_TABLES_PREFIX=matomo_
MATOMO_DATABASE_USERNAME=matomo
MATOMO_DATABASE_PASSWORD=matomo
MATOMO_DATABASE_DBNAME=matomo
```

And `matomo.conf` file where we’re defining some behaviour for Matomo nginx.

```yaml
upstream php-handler {
	server app:9000;
}

server {
	listen 80;

	add_header Referrer-Policy origin; # make sure outgoing links don't show the URL to the Matomo instance
	root /var/www/html; # replace with path to your matomo instance
	index index.php;
	try_files $uri $uri/ =404;

	## only allow accessing the following php files
	location ~ ^/(index|matomo|piwik|js/index|plugins/HeatmapSessionRecording/configs).php {
		# regex to split $uri to $fastcgi_script_name and $fastcgi_path
		fastcgi_split_path_info ^(.+\.php)(/.+)$;

		# Check that the PHP script exists before passing it
		try_files $fastcgi_script_name =404;

		include fastcgi_params;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		fastcgi_param PATH_INFO $fastcgi_path_info;
		fastcgi_param HTTP_PROXY ""; # prohibit httpoxy: https://httpoxy.org/
		fastcgi_pass php-handler;
	}

	## deny access to all other .php files
	location ~* ^.+\.php$ {
		deny all;
		return 403;
	}

	## disable all access to the following directories
	location ~ /(config|tmp|core|lang) {
		deny all;
		return 403; # replace with 404 to not show these directories exist
	}
	location ~ /\.ht {
		deny all;
		return 403;
	}

	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|json)$ {
		allow all;
		## Cache images,CSS,JS and webfonts for an hour
		## Increasing the duration may improve the load-time, but may cause old files to show after an Matomo upgrade
		expires 1h;
		add_header Pragma public;
		add_header Cache-Control "public";
	}

	location ~ /(libs|vendor|plugins|misc/user) {
		deny all;
		return 403;
	}

	## properly display textfiles in root directory
	location ~/(.*\.md|LEGALNOTICE|LICENSE) {
		default_type text/plain;
	}
}

# vim: filetype=nginx
```

## Up up we go!
![Hot air balloon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q5sqgc9k9xu5mc5oez20.png)
 
Time to run the docker-compose file. For this, just open your favourite terminal (I like ZSH!) on the root of the folder where you have the file in and execute the command `docker-compose up`. This will create the needed volumes and images for the new docker containers.

If you now head to your [http://localhost:8080/](http://localhost:8080/), and you did exactly as I said, you’ll see that Matomo is ready to be configured.

## Setting up Matomo

On the Database Setup, make sure you enter the inputs for the values defined on the `docker-compose.yaml` file.

On the `Superuser` step just set up your credentials as you want them and then on `Set up a Website` make sure to define your target, in this example it will be [https://localhost:4200](https://localhost:4200/) which is where we will be running our angular application.

## Problems ahead?
![developer thinking](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sj71gm0u4aihcehny0zi.png)
 
On ending the setup, you might be faced with a warning stating that Matomo has not been configured to run on your [localhost](http://localhost) 8080 port.
![matomo error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nitpr5codez5csxrb07m.png)
 
 
## The problem is not the problem, savvy?

To get around this, we need to change Matomo `config.ini.php` file inside the app container that was created by our compose file.

The deal is that we basically need to tell Matomo that the port we’re using is a trusted host.

To do this, run the following command from same folder where docker-compose.yaml is: `docker exec -u 0 -it matomo_app /bin/sh` take in consideration that `matomo_app` is your container name (in some scenarios you might end up with and suffix like matomo_app_1, just check the name using `docker ps`)

If the command ran successfully, then we should be inside the container.

Now we'll use `vi` to edit the Matomo configuration file by running the command `vi config/config.ini.php` (make sure your path is `/var/www/html`).
Press the key `I` to insert data, navigate to the `[General]` section and then append the following: 

```jsx
[General]
trusted_hosts[] = "localhost:8080"
cors_domains[] = *
```

Once finished the editing, press the `ESC` key, write `:wq` and press enter. This will write and quite the editing of the file.

Trusted hosts will allow you to run Matomo in your defined port (in this scenario it’s 8080) and the CORS will allow your local project to call Matomo on the same port (look at me, doing magic and stuff)


## Are we there yet?

Almost there, kids. So we got everything up and running, and the only missing link is adding the Matomo package to your angular project and set it up.

On the angular project, install the package `npm install --save @ngx-matomo/tracker` followed by `npm install --save @ngx-matomo/router` and then import the modules `NgxMatomoTrackerModule` and `NgxMatomoRouterModule` into your app.module, so it looks like this

```tsx
import { NgModule } from '@angular/core';
import { NgxMatomoTrackerModule } from '@ngx-matomo/tracker';
import { NgxMatomoRouterModule } from '@ngx-matomo/router';

@NgModule({
  imports: [
    // ...
    NgxMatomoTrackerModule.forRoot({
      siteId: 'YOUR_MATOMO_SITE_ID', // your Matomo's site ID (find it in your Matomo's settings)
      trackerUrl: 'http://localhost:8080/', // your matomo server root url
    }),
    NgxMatomoRouterModule,
  ],
  // ...
})
export class AppModule {}
```

## Are we done yet?

![Matomo real time dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bvbjwi6jookre7033cfr.png)
 
Oh, yes, we are! The configuration above is the bare minimum, so you'll have a report for every routing navigation you do. Try navigating back and forward on your angular app and then check the Matomo dashboard, you should see some data appearing.
 
This was a very fun and educational exercise for me, and I hope I’ve helped you set up your machine as well.
As always, please feel free to advise, share ideas and, comment! See you soon!

![people bump fist](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8yafy58ns9hgv2zc3rgd.png)

Special thanks to [Ashkan Forouzani](https://unsplash.com/@ashkfor121), [Tim Gouw](https://unsplash.com/@punttim) and [Ricardo Rocha](https://unsplash.com/@rcrazy) for the photos.