23 June 2026, 20:00 (CST)
2026年06月23日(东八区)
功能调试:Umami 流量统计未生效
概述
站点启用 Ametrine 主题内置的 Umami 统计后,Umami 控制台 长期无访客数据。本次排查确认根因为 zola.toml 中 self_hosted_url 误填为博客域名,导致追踪脚本指向不存在的 /script.js,且 CSP 未放行 Umami Cloud 域名。修复后仅改动站点根目录 zola.toml,未修改 themes/。
1. Umami 在源代码中的设计逻辑与调用链
Ametrine 主题(参考 daudix.one)将统计能力拆为 配置 → CSP 白名单 → 脚本注入 三层,全部在 themes/ametrine/templates/partials/ 中实现。
1.1 配置入口:zola.toml
[extra.analytics]
service = "umami" # 统计服务:goatcounter | umami | plausible
id = "cdf54193-b449-4454-884b-029e82434c32" # Umami Cloud 的 website ID
# self_hosted_url = "https://stats.example.com" # 仅自托管 Umami 时填写
exclude_hash = true # 可选:不采集 URL hash
# exclude_search = false # 可选:不采集 URL 查询参数
# do_not_track = false # 可选:尊重浏览器 DNT| 字段 | 作用 |
|---|---|
service | 选择统计后端,决定加载哪段 partial |
id | Umami 的 data-website-id |
self_hosted_url | 自托管实例根 URL;留空则走 Umami Cloud(cloud.umami.is) |
exclude_hash / exclude_search / do_not_track | 映射为 <script> 上的 data-* 属性 |
主题默认示例见 themes/ametrine/config.toml 的 [extra.analytics] 段(daudix 使用自托管 https://stats.daudix.one)。
1.2 CSP 白名单:partials/csp.html
页面 <head> 内生成 Content-Security-Policy,决定是否允许加载外部脚本与上报数据:
config.extra.csp(zola.toml 自定义域)
↓
csp.html 合并 analytics 域
↓
<meta http-equiv="Content-Security-Policy" …>Umami 相关逻辑(themes/ametrine/templates/partials/csp.html):
| 条件 | script-src 追加 | connect-src 追加 |
|---|---|---|
设置了 self_hosted_url | 该 URL | 该 URL |
未设置 + service == "umami" | cloud.umami.is | *.umami.dev cloud.umami.is |
若误填 self_hosted_url 为博客地址,CSP 不会自动加入 cloud.umami.is,脚本即使写对也会被策略拦截。
1.3 脚本注入:partials/head.html → partials/analytics.html
触发条件(themes/ametrine/templates/partials/head.html):
{%- if config.mode != "serve" and config.extra.analytics.service -%}
{%- include "partials/analytics.html" -%}
{%- endif -%}要点:
zola serve开发模式不注入 — 本地热重载页面无统计脚本,属预期行为。zola build产物才包含 — 部署到 GitHub Pages 后访客才会被追踪。
Umami 脚本生成(themes/ametrine/templates/partials/analytics.html):
| 条件 | 输出 |
|---|---|
self_hosted_url 有值 | <script … src="{{ self_hosted_url }}/script.js" data-website-id="{{ id }}"> |
self_hosted_url 为空 | <script … src="https://cloud.umami.is/script.js" data-website-id="{{ id }}"> |
等价于官方嵌入代码:
<script defer src="https://cloud.umami.is/script.js"
data-website-id="cdf54193-b449-4454-884b-029e82434c32"></script>1.4 完整调用链(生产环境)
zola build
→ head.html 读取 config.extra.analytics
→ csp.html 写入 script-src / connect-src 白名单
→ analytics.html 输出 <script defer src="cloud.umami.is/script.js">
→ 浏览器加载 script.js
→ script.js 向 *.umami.dev / cloud.umami.is 上报 pageview
→ Umami 控制台展示数据2. 本次错误原因与修复方案
2.1 现象
| 检查项 | 修复前(线上) |
|---|---|
页面 <script> | src="https://suchaharcan.github.io/script.js" |
| 脚本 HTTP 状态 | 404(GitHub Pages 无此文件) |
CSP script-src | 'self' https://suchaharcan.github.io …(无 cloud.umami.is) |
CSP connect-src | 无 *.umami.dev |
| Umami 控制台 | 无访客记录 |
2.2 根因
复制 daudix.one 配置时,将 self_hosted_url 设成了博客域名 https://suchaharcan.github.io。
daudix 的 self_hosted_url = "https://stats.daudix.one" 指向独立的 Umami 自托管实例;本站点使用的是 Umami Cloud,不应填写 self_hosted_url。
连锁影响:
- 脚本 URL 错误 — 主题从
博客域名/script.js加载,文件不存在。 - CSP 错误 — 白名单指向博客域名,未放行
cloud.umami.is与*.umami.dev。 - 即使手动改 script 地址,上报请求仍会被 CSP 拦截。
2.3 修复
文件:zola.toml(仅此一处,未改 themes/)
[extra.analytics]
service = "umami"
id = "cdf54193-b449-4454-884b-029e82434c32"
-self_hosted_url = "https://suchaharcan.github.io"
exclude_hash = true修复后 zola build 产物对比:
| 检查项 | 修复后 |
|---|---|
| 脚本 | src="https://cloud.umami.is/script.js" → 200 |
| CSP | script-src … cloud.umami.is;connect-src … *.umami.dev cloud.umami.is |
| website ID | cdf54193-b449-4454-884b-029e82434c32 ✓ |
部署提醒:本地 build 已正确,需 push 触发 GitHub Pages 重建后线上才生效。
3. 验证方式与使用注意点
3.1 部署后验证(推荐)
浏览器 Network
- 打开 https://suchaharcan.github.io/
- DevTools → Network,筛选
script.js - 确认来源为
cloud.umami.is,状态 200
查看页面源码
- 搜索
data-website-id,应出现cdf54193-b449-4454-884b-029e82434c32 - 搜索
Content-Security-Policy,应含cloud.umami.is
- 搜索
Umami 控制台
- 登录 Analytics 面板
- 刷新博客首页,Realtime / 今日访客应在数秒内更新
命令行快速检查(可选)
curl -sL "https://suchaharcan.github.io/" | grep -o 'cloud.umami.is/script.js' # 应输出:cloud.umami.is/script.js curl -sI "https://cloud.umami.is/script.js" | head -1 # 应输出:HTTP/2 200
3.2 使用注意点
| 场景 | 说明 |
|---|---|
zola serve 本地开发 | 不注入 analytics,Network 中看不到 Umami 脚本 — 正常 |
| Umami Cloud vs 自托管 | Cloud 用户不要填 self_hosted_url;自托管才填实例根 URL(如 https://stats.example.com) |
| CSP 自定义域 | zola.toml 的 [extra.csp] 与主题自动合并;Umami Cloud 域由主题在 self_hosted_url 为空时自动追加 |
| 参考 daudix.one | 可借鉴导航、CSP 结构等;self_hosted_url 不能直接照搬(daudix 为自托管) |
| 不修改 themes/ | 统计逻辑已在主题内;站点级只需正确配置 zola.toml 并 build 部署 |
| 隐私 / 分享 | 数据分享页:https://cloud.umami.is/share/2hWVbYvlPUkk98Yz |
| AdBlock / 隐私扩展 | 访客若安装拦截器,可能不上报 — 控制台数据为「可统计访客」子集 |
3.3 配置对照速查
| 部署方式 | service | id | self_hosted_url |
|---|---|---|---|
| Umami Cloud(本站) | umami | Cloud 控制台 website ID | 留空 |
| 自托管 Umami | umami | 实例中的 website ID | https://你的-umami-域名 |
| GoatCounter / Plausible | 对应 service 名 | 各服务文档 | 自托管时填实例 URL |
修改文件
| 文件 | 变更 |
|---|---|
zola.toml | 删除错误的 self_hosted_url = "https://suchaharcan.github.io" |
相关链接:Umami 控制台 · 数据分享页 · daudix.one 参考仓库 · 热力图 + 统计启用记录
22 June 2026, 20:00 (CST)