基于 Matomo 的 Ghost 博客埋点分析

为什么选择 Matomo?

需求

  1. 开源免费;
  2. 支持自部署;
  3. 可以和 ghost 博客轻松集成。

可选产品

由于需要和 ghost 集成,我们只能在 ghost 的集成服务中去选择,可能还有更好的方案,但是这里偷懒没有去调研其他的产品。由于需要自部署优先,最终选择以下两种方案:

Official Ghost + Plausible Integration
Plausible is a privacy-first analytics platform that you can integrate with your Ghost publication using a straightforward code injection 📊

Plausible 一个很不错的方案,可惜他提提供自部署版本,居然是一年两版,总是落后他们的付费服务,可以理解,也是一种稳定可行的开源软件商业化盈利方案。但是在内存占用和开箱即用上(定制化的一些数据分析需要自己查看文档去配置代码,相对麻烦一些),略输于 Matomo。

Official Ghost + Matomo Integration
Want powerful, privacy focussed analytics for your Ghost publication? Integrate with Matomo using a straightforward code injection 📊

Matomo 是一个很不错的方案,除了因为使用 PHP 来开发,导致部署的时候 Caddy 不方便直接代理 php_fastcgi 的配置,所以根据源码仓库里提供的 nginx 配置编写了一个简单的反代,这样的话,对外部就直接可以统一使用 Caddy 去反代了,由于只是监控面板,也不需要担心访问速度问题,而且实际使用下,并没有太大延迟。

两者在 docker stats 下的内存占用对比

提供的功能

  • 实时访问的情况,访客的趋势图;
  • 访客信息——大致地理位置、使用设备、匿名 IP;
  • 访客的浏览情况,包括打开的页面、停留的时间;
  • 设置收益转化,量化文章的质量;

安装 Matomo

架构模式

由于我为了易于迁移,采用了 Docker 来部署容器和数据卷,又希望端口不冲突,所以使用了个笨办法来代理不同的容器内部 IP,即都使用同一个网络来代理容器,网络都在 Docker 内部去处理。在这样的前提下,我不得不使用 Caddy 去代理 php_fastcgi,但是这个似乎不是很好理解,我只能曲线救国的使用 Nginx 辅助代理一层,由于 Nginx 的配置 Matomo 是提供了的,所以对外直接暴露的 80 端口可以直接让 Caddy 去监听反代。

最终确定的架构:Caddy 反代 Docker 的局部域名,Nginx 反代 Matomo 的 9000 到 80 端口,Docker compose 启动之后配置网络到 域名:80

基础文件

Matomo 提供了 Nginx 的默认配置,可以直接在 github 上找到源码。三个文件都很重要,可以全部复制到自己的项目中使用。

  • db.env:包含了一些默认的环境变量,记得修改密码,其他可以默认;
  • matomo.conf:Nginx 的配置文件,这里只需要修改 app:9000 为你的 matomo 的 容器名称:9000
  • docker-compose.yml:核心配置文件,包含三个容器,数据库、Mamoto、Nginx,这里基本不用改什么,如果自用的话默认就可以了。

docker compose 的常用修改

容器名

一般的,我会给每个容器一个固定的容器名,而不是交给 docker 生成的,这样可以在 Caddy 中指定容器名来访问不同的服务,比如给 matomo 一个容器名,在 matomo.conf 文件中就可以直接使用 容器名称:9000 ;给 Nginx 一个容器名,可以在外部的 Caddyfile 中直接使用 nginx:80 访问到这个反代。

services:
  matomo:
    image: matomo:5.0.3-fpm-alpine
    container_name: matomo

端口配置

一般的,由于有了 docker 容器名当作域名来访问不同的域名,所以端口一般不写具体的映射,只是象征性的写出需要的端口,其实不写也可以。

    ports:
      - 80

网络和镜像配置

配置外部的 Caddy 网络,可以让当前的容器加入到 Caddy 容器的网络环境中,并使用容器名访问。同时内部的几个容器通信,需要单独配置本地的一个网络,这样即使是相同的容器也可以隔离开,另一方面,有些默认 127.0.0.1 的配置项,不至于在外部网络中找不到目标。

配置外部数据卷,方便迁移的时候带上数据,这个不多解释。

volumes:
  matomo_data:
    external: true
  matomo_mariadb_data:
    external: true

networks:
  caddy_net:
    external: true
  matomo_net:

配好 Caddy

这边就更简单了,复杂的部分已经被 Nginx 消化掉了,直接反代到 Nginx 容器就好。

xx.xx.com {
	reverse_proxy matomo_nginx:80
}

记得运行重启命令,热更新服务上线,并在域名托管商那边处理好域名解析。

docker exec -it caddy caddy fmt --overwrite /etc/caddy/Caddyfile
docker exec -it caddy caddy reload --config /etc/caddy/Caddyfile

总结

就是这样,和常规的容器化配置方法差别不大,剩下的结合 ghost 的集成教程来做就可以了。