---
title: 网站埋点统计
tags: [网站, 埋点]
---

# 网站埋点统计

Tydora 的文档站与落地页是部署在 GitHub Pages 的纯静态站点（`zuorn.github.io/Tydora`），没有后端、没有数据库，无法通过服务器日志统计访问量。本文介绍如何通过「前端埋点 + 统计服务」的方式为网站接入访问统计，统计 PV（页面浏览量）与 UV（独立访客数）。

## 为什么需要埋点

- 了解文档的受欢迎程度，定位最热门的页面
- 观察访客来源与浏览路径，指导文档内容优化
- 评估发布活动的效果，例如新版本公告带来的访问量变化

## 统计服务选型

前端埋点需要在每个页面加载一小段统计脚本，脚本会向统计服务上报访问数据。常见的免费方案对比：

| 方案 | 成本 | PV/UV | 隐私合规 | 国内访问 | 维护量 |
|------|------|-------|---------|---------|--------|
| **Umami**（云免费版 / 自托管） | 免费额度起 | ✅ | 无 cookie，隐私友好 | 一般 | 中 |
| 百度统计 | 免费 | ✅ | 国内合规 | 好 | 低 |
| Cloudflare Web Analytics | 免费 | ✅ | 无 cookie | 一般 | 零 |
| Plausible | $9/月起 | ✅ | 无 cookie | 差 | 低 |
| Google Analytics 4 | 免费 | ✅ | 需要 cookie 弹窗 | 差 | 低 |

本项目选用 **Umami**（Umami Cloud 免费版）：开源无锁定、无 cookie 隐私友好、脚本极小不影响加载性能，数据归属于自己。

## 实施步骤

### 1. 注册 Umami 并创建网站

1. 访问 [umami.is](https://umami.is)，使用 GitHub 账号登录（Umami Cloud 免费版每月 10k 事件，足够个人文档站使用）
2. 点击 **Add website** 新建站点：
   - **Name**：随意填写，例如 `Tydora`
   - **Domain**：填 `zuorn.github.io`，**不要带 `/Tydora` 路径**（详见下方常见问题）
3. 保存后进入站点详情，复制 **Website ID**（形如 `56c781b4-...` 的 UUID）

### 2. 获取并保存埋点脚本

新建 `website/analytics/snippet.html`，填入 Umami 提供的脚本，并加上 `id="t-analytics"` 属性（用于注入脚本幂等去重）：

```html
<!-- Tydora Analytics · Umami Cloud（https://umami.is） -->
<script id="t-analytics" defer src="https://cloud.umami.is/script.js" data-website-id="你的Website ID"></script>
```

> 该文件是整个埋点功能的**唯一维护点**：将来想换统计服务（如百度统计），只需替换这一个文件的内容，其余代码无需改动。

### 3. 编写构建注入脚本

由于文档站由 `markdown-publish`（静态站点生成器）生成，不支持内置 analytics 注入，需要在构建完成后遍历所有 HTML，把埋点片段插入 `<head>` 中。

新建 `scripts/inject-analytics.mjs`：

```js
/**
 * 将埋点片段注入 website/site/** 下所有 HTML 的 </head> 前
 * 在 copy-landing 之后运行，因此落地页与文档页都会覆盖到
 * 片段内容统一维护在 website/analytics/snippet.html（换统计服务只改这一个文件）
 * 幂等：页面已含 id="t-analytics" 则跳过，重复构建不会重复注入
 */
import { readFileSync, writeFileSync, readdirSync, statSync } from "node:fs";
import { join, resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = dirname(fileURLToPath(import.meta.url));
const siteDir = resolve(__dirname, "../website/site");
const SNIPPET_FILE = resolve(__dirname, "../website/analytics/snippet.html");

let snippet = "";
try {
  snippet = readFileSync(SNIPPET_FILE, "utf-8").trim();
} catch {
  console.log("⚠️ website/analytics/snippet.html 不存在，跳过注入");
  process.exit(0);
}

function walk(dir) {
  for (const entry of readdirSync(dir)) {
    const full = join(dir, entry);
    if (statSync(full).isDirectory()) walk(full);
    else if (full.endsWith(".html")) inject(full);
  }
}

function inject(file) {
  const html = readFileSync(file, "utf-8");
  if (!html.includes("</head>") || html.includes('id="t-analytics"')) return;
  const out = html.replace("</head>", `  ${snippet}\n</head>`);
  writeFileSync(file, out, "utf-8");
  console.log(`✅ analytics injected → ${file.replace(siteDir, "site")}`);
}

walk(siteDir);
```

脚本的幂等逻辑：页面中已存在 `id="t-analytics"` 则跳过，因此本地重复构建不会出现重复注入。

### 4. 接入构建链路

修改 `package.json`，在 `postdocs:build` 中追加注入步骤：

```json
"postdocs:build": "node scripts/copy-landing.mjs && node scripts/inject-analytics.mjs"
```

`docs:build` 执行完成后 npm 会自动运行 `postdocs:build`，构建链变为：

```
docs:build（生成 site/）
  → copy-landing（落地页覆盖到 site 根目录）
  → inject-analytics（遍历全站 HTML 注入埋点）
```

### 5. 更新 CI 触发条件

修改 `.github/workflows/deploy-docs.yml`，把 `scripts/inject-analytics.mjs` 加入 push 触发路径，保证修改注入脚本时能触发重新部署：

```yaml
on:
  push:
    branches: [main]
    paths:
      - 'website/**'
      - 'scripts/copy-landing.mjs'
      - 'scripts/inject-analytics.mjs'
      - 'package.json'
      - '.github/workflows/deploy-docs.yml'
```

> `website/analytics/**` 已被 `website/**` 覆盖，无需单独列出。

## 验证

### 本地构建验证

```bash
npm run docs:build
```

看到类似输出即表示注入成功：

```
✅ analytics injected → site/index.html
✅ analytics injected → site/en/index.html
...
```

打开 `website/site/index.html`，确认 `</head>` 前有 `<script id="t-analytics" ...>`，且重新构建不会重复注入。

### 部署后验证

1. 推送代码，等待 GitHub Actions 完成（约 2-5 分钟），确认部署状态为 Active
2. 打开 `https://zuorn.github.io/Tydora/`，按 `F12` 打开开发者工具
3. 切到 **Network** 面板，刷新页面，搜索 `umami`，能看到发往 `cloud.umami.is` 的请求（如 `/api/send`）即表示埋点已生效
4. 访问几次后，在 Umami 后台即可看到 PV/UV、来源、页面排行等报表

## 常见问题

### Q: Umami 的 Domain 字段不能填 `zuorn.github.io/Tydora`？

Umami 的 Domain 字段只匹配 host（域名），不支持带路径。填 `zuorn.github.io` 即可，`/Tydora` 部分会被忽略，也不影响统计归属：

- Umami 只收到「安装了埋点脚本的页面」上报的数据，其他 GitHub Pages 项目没有装脚本，不会污染数据
- 报表中的页面 URL 仍带完整路径（如 `/Tydora/en/...`），按路径筛选即可区分

### Q: 埋点是从什么时候开始统计的？

从部署之后的新访问开始。部署前访问过、浏览器缓存着旧页面的访客，需要刷新加载新页面才会被记录，历史访问不会补录。

### Q: 为什么 Network 面板里看不到上报请求？

重点检查两处：

1. 部署后的页面源码 `</head>` 前是否有 `<script id="t-analytics" ...>`
2. Umami 后台该网站的 Domain 是否填的 `zuorn.github.io`（不带路径）

### Q: 如何更换统计服务？

只改 `website/analytics/snippet.html` 一个文件，替换为对应服务商的脚本即可，注入机制无需任何改动。

## 相关文档

- [[09-博客/自动更新配置]] — 自动更新配置
- [[09-博客/上架微软商店]] — 上架微软商店
