部署了博客之后,我就想为博客添加访问流量统计的功能。fluid中提供了三种统计方式,分别是不蒜子LeanCloudUmami。而不蒜子是将数据存放在其自己的平台,似乎不太稳定,并且隐私性可能得不到保证,同时统计脚本会被广告拦截器拦截,因此没有考虑;LeanCloud的国内版还需要实名验证且通过支付宝授权[1],并且也不想注册多余的账号;Umami支持自部署,且自称是「Google Analytics的简单、快速、注重隐私的替代方案」。因此我决定使用Umami实现统计流量功能。

部署

Umami的部署比较简单。根据官方仓库的说明,Umami支持直接通过yarn运行,以及使用Docker部署。而我的服务器上没有数据库,并且希望实现数据的分离,因此选择使用Docker部署。

首先获取源代码并定位到此目录下:

1
2
git clone https://github.com/umami-software/umami.git
cd umami

然后构建相应的容器:

1
sudo docker compose up -d

构建完毕后,其默认会在3000端口上运行。随后反代即可。本人使用的是nginx,示例配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 80;
server_name your.umami.domain;

add_header Access-Control-Allow-Origin 'https://your.blog.domain' always;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT, X-Mx-ReqToken, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}

location / {
proxy_pass http://127.0.0.1:3000;
proxy_hide_header 'Access-Control-Allow-Origin';
}
}

提示:请将配置文件中的your.umami.domain以及your.blog.domain替换成真实的地址。

注意:由于同源策略,若Umami与博客不在同一域名下,则需要添加对应的响应头以允许脚本跨域读取数据。上述的示例配置中已经包含了这些内容。强烈建议允许所有网站的跨域读取请求,这可能会带来安全问题。

配置

Umami

首先需要打开Umami后端管理界面。默认的账户名为admin,密码为umami。登录后请立即修改管理员的密码。为了让博客能够获取统计数据并显示,同时不暴露管理员的token,我们需要创建一个仅能查看浏览量的账号。但该账号并没有添加网站的权限。为此,我们仅需要使用管理员账号创建团队,并保存访问代码,然后在团队中添加博客网站,并记录下网站 ID,以及跟踪代码js文件的地址,接着登录仅能查看浏览量的账号,并使用访问代码加入团队。这样就能够利用该账号查看浏览量信息了。

随后,我们还需要获取该账号的token。根据官方文档,我们需要构造相应的请求。最初我在使用curl时出现了转义相关问题,随后转而使用Node.js完成这一操作。首先需创建一个.js文件,并向其中写入内容。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const axios = require('axios');

async function getToken() {
try {
const response = await axios.post('https://your.umami.domain/api/auth/login', {
username: 'your-username',
password: 'your-password'
}, {
headers: {
'Content-Type': 'application/json'
}
});
console.log(response.data);
} catch (error) {
console.error('Error during API request:', error.response ? error.response.data : error.message);
}
}

getToken();

提示:请将配置文件中的your.umami.domainyour-usernameyour-password替换成真实的信息。

然后,我们需要在当前目录下打开终端,并执行node your-js-name.js(请将your-js-name替换成真实的文件名)。不出意外的话,能够正常返回token。然后你需要记录token信息。

提示:若尚未安装axios包,则需要执行npm install axios

博客

通过上一节的操作,我们已经获取到了js文件地址网站 ID仅浏览量账户token,同时还需要Umami服务器地址。本人使用的是fluid主题,因此在_config.fluid.yml配置文件中依次填入这些数据即可。如果使用的是其他主题或是其他博客框架,可以参考其自身的文档来配置。若没有提供,则可以参考Umami官方的API文档以及fluid主题中的对应js(可能有滞后性),自行构建请求头以调用API获取数据。

出于对访问者隐私的尊重,个人建议遵循浏览器「请勿追踪」的设置,若其开启则不统计其信息。

截至fluid主题的1.9.8版本,其umami-view.js脚本是存在问题的,需要做出以下三处更改(参见此PR):

1
2
3
4
@@ -3,4 +3,4 @@
// 拼接请求地址
- const request_url = `${CONFIG.web_analytics.umami.api_server}/websites/${website_id}/stats`;
+ const request_url = `${CONFIG.web_analytics.umami.api_server}/api/websites/${website_id}/stats`;

此处请求的链接存在问题,应添加/api

1
2
3
4
5
6
7
8
9
10
@@ -29,36 +29,36 @@
// 构造请求头
const request_header = {
method: "GET",
headers: {
"Content-Type": "application/json",
- "x-umami-api-key": "oZKCH3msvqt10VlXKwoJvHclmaS4bVx0",
+ "Authorization": "Bearer " + token,
},
};

此处构造的请求头存在问题,应为Authorization而非x-umami-api-key。可以参考Umami官方文档

1
2
3
4
5
6
7
8
9
@@ -38,44 +38,44 @@
// 获取站点统计数据
async function siteStats() {
try {
const response = await fetch(`${request_url}?${params}`, request_header);
const data = await response.json();
- const uniqueVisitors = data.uniques.value; // 获取独立访客数
+ const uniqueVisitors = data.visitors.value; // 获取独立访客数
const pageViews = data.pageviews.value; // 获取页面浏览量

此处请求的数据存在问题,应为visitors而非uniques。可以参考Umami官方文档

修改完成后,可以将该js文件放入/source/js/目录中,以便持久化保存,避免在执行hexo clean后丢失修改。

效果

Umami后端的统计数据

问题

我在部署时遇到了一些问题:

  1. 由于同源策略而导致无法获取相应的信息,参见GitHub上plugin-umami中的issue
  2. 由于fluid主题umami-view.js的错误配置,导致无法正常跟踪以及获取数据。

如果你遵循了上述过程,那么应该就能避免上述问题。


  1. 参见Jekyll博客统计访问量,阅读量工具总结–LeanCloud,不蒜子,Valine,Google Analytics - 浮云的博客↩︎