Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.

添加第一方匿名访问 UV/PV 统计 - #90

Merged
jiangmuran merged 1 commit into
mainfrom
feat/real-visit-uv
May 4, 2026
Merged

jiangmuran merged 1 commit into
mainfrom
feat/real-visit-uv

Conversation

@FlashingChen

Copy link
Copy Markdown
Collaborator

背景与为什么要改

当前后台 /admin 里已有“请求数 / IP”等统计,但这些指标来自 usage_log,本质上统计的是用户发起诊断、生成、解析等业务请求,不是用户访问页面的真实 PV/UV。

这会带来几个问题:

  • 只打开首页、隐私页、条款页、白皮书页、React /app 页面但没有发起诊断的用户不会被统计到。
  • 后台里类似“UV”的数字容易被误解为真实访问 UV,实际上更接近“发生过业务请求的 IP 数”。
  • 如果接入 Microsoft Clarity 之类第三方脚本,虽然能看访问数据,但会引入第三方追踪、隐私披露和用户信任成本。
  • 项目部署在 CDN / 多页面入口下,仅靠 CDN 面板不一定能稳定区分 NoteRx 自己的访问行为,也不方便和现有 /admin 放在一起看。

所以这次改为第一方、服务端、自有数据库里的匿名访问统计:保留原有业务请求统计,同时新增真正的页面 PV/UV。

这次改了什么

1. 新增第一方访问打点接口

新增 POST /api/visit,用于记录页面访问。

实现点:

  • 新增 backend/app/api/visit_api.py
  • 使用 IP + User-Agent + VISITOR_HASH_SALT 生成不可逆 visitor_hash
  • 只存 visitor_hashuser_agent_hash、访问路径和时间。
  • 不把原始 IP 写入 visit_log
  • 不把原始 referrer 写入 visit_log,避免 URL 中可能携带敏感参数。
  • 同时兼容普通 JSON 请求和 navigator.sendBeacon 常见的 text/plain;charset=UTF-8 JSON body。

2. 数据库启动时自动补表

在后端启动初始化逻辑里新增 visit_log 表和索引:

  • visit_log
  • idx_visit_created
  • idx_visit_visitor
  • idx_visit_path

这样线上旧库升级时不需要跑 make data,只要后端正常启动,就会自动补齐新表结构。

3. 后台 /admin 改成真实访问 PV/UV

/admin/api/stats 新增这些字段:

  • total_pv
  • total_uv
  • today_pv
  • today_uv
  • visits_by_path
  • visit_hourly_24h

后台页面展示也调整为:

  • 今日访问 UV
  • 今日访问 PV
  • 总访问 UV
  • 总访问 PV
  • 今日诊断
  • 诊断 IP
  • 总诊断

也就是说:访问统计和诊断请求统计分开,不再把业务请求 IP 当作真实访问 UV。

4. React /app 页面打点

前端新增 trackVisit(),并在 BrowserRouter basename="/app" 内根据路由变化打点。

这样用户访问:

  • /app/
  • /app/report
  • /app/history
  • /app/diagnosing

这类 SPA 页面时,后台都能看到真实路径访问分布。

5. 静态页面也加入打点

以下静态页 <head> 中加入同样的第一方访问打点脚本:

  • docs/research_whitepaper.html
  • docs/privacy.html
  • docs/terms.html

这样非 React 页面也会进入统一 PV/UV 统计。

6. 隐私政策文案同步更新

docs/privacy.html 原文写的是“不追踪您的浏览行为”,但新增第一方访问统计后,这句话不再准确。

本次更新为明确披露:

  • 不使用 Cookie。
  • 不接入第三方追踪工具。
  • 仅记录匿名访问统计。
  • 使用 IP 和浏览器信息生成不可逆哈希。
  • 用途是计算 PV/UV 和排查服务质量问题。
  • 不记录点击轨迹、输入内容、截图或诊断报告。

能解决什么问题

  • 后台终于能看到真实访问 UV/PV,而不是只能看到发起诊断请求的人。
  • 可以区分“有人访问了页面”和“有人真的发起了诊断”。
  • 可以看到不同入口路径的访问分布,例如 /app//privacy/terms 等。
  • 不需要接入 Clarity 这类第三方分析脚本,降低隐私和合规成本。
  • 保留原有 usage_log 统计,不影响现有诊断请求、token、耗时、分类等业务分析。
  • 对旧数据库是增量补表,不要求重建 baseline 数据。

可能带来的好处

  • 统计口径更准确:PV/UV 来自页面访问,诊断请求仍来自业务日志,两套口径不会混在一起。
  • 隐私风险更低:不存 raw IP,不存 raw referrer,不使用 Cookie,不使用第三方行为分析脚本。
  • 部署更简单:仍然沿用现有 SQLite 和 /admin,不需要额外接入分析平台。
  • 对 CDN 更友好:即使 CDN 面板不稳定,应用自己的后台也能看核心访问数据。
  • 后续可扩展visit_log 后续可以继续支持路径趋势、来源概览、页面转化等,但本 PR 没做过度扩展。

可能的坏处 / 风险 / 注意事项

  • 不是跨设备用户 ID:UV 基于 IP + User-Agent 哈希,同一个人换网络、换浏览器会被算成不同 UV;多人共用出口 IP 且 UA 相同也可能被合并。这是匿名统计的取舍。
  • 首次上线后访问 UV 从 0 开始累积:旧数据库没有 visit_log,因此不会凭空拥有历史 PV/UV;历史诊断数据仍保留在 usage_log
  • 数据库会增加写入量:每次页面访问会写一行 visit_log。目前写入很轻量,但高流量下 SQLite 仍需要关注磁盘和写锁情况。
  • 需要保护线上数据库backend/data/baseline.db 是运行时数据,里面包含业务历史和访问日志,不能随代码发布覆盖,也不应该提交到 GitHub。
  • 不要在线上跑 make datamake data 是本地初始化/演示数据生成流程,会重建 baseline 数据,不适合线上保留业务数据的环境。
  • 隐私政策必须同步发布:因为新增了匿名访问统计,隐私页更新需要随代码一起上线,避免页面声明和实际行为不一致。

上线 / 运维注意事项

上线前建议:

  1. 备份线上数据库:

    cp backend/data/baseline.db backend/data/baseline.db.bak.$(date +%Y%m%d%H%M%S)
  2. 更新代码。

  3. 重启后端服务,让启动逻辑自动创建 visit_log 表和索引。

  4. 不要执行 make data

  5. 打开 /admin 检查:

    • 原有诊断请求统计仍存在。
    • total_pv / total_uv 正常显示。
    • 访问 /app/ 后 PV 有增长。

本地验证

已在本地执行:

  • make -C /Users/flashingchen/Coding/VibeCoding/noterx test
    • 结果:14 passed, 1 warning
  • npm --prefix /Users/flashingchen/Coding/VibeCoding/noterx/frontend exec tsc -- --noEmit
    • 结果:通过,无输出错误
  • npx --prefix /Users/flashingchen/Coding/VibeCoding/noterx/frontend vite build
    • 结果:构建成功
  • 手动验证 /admin/api/stats?password=pageone
    • 能返回业务请求统计
    • 能返回 total_pv / total_uv / today_pv / today_uv / visits_by_path
  • 手动验证 /api/visit
    • sendBeacon 风格的 text/plain;charset=UTF-8 payload 可正常写入

不包含什么

  • 不接入 Microsoft Clarity。
  • 不做热力图、录屏、点击轨迹。
  • 不引入 Cookie 或本地持久用户 ID。
  • 不提交 backend/data/baseline.db
  • 不修改线上数据库内容,只新增兼容旧库的表结构。

Track anonymous page visits separately from diagnosis usage so admin stats can report real PV/UV without third-party analytics.
@jiangmuran
jiangmuran merged commit 200e6b2 into main May 4, 2026
6 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants