ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

自托管网站分析:用Hindsight替代Google Analytics的完整实践

自托管网站分析:用Hindsight替代Google Analytics的完整实践 如果让我用一个词解释网站分析我会选 hindsight。字面意思是“事后才看明白”中文里最贴近的说法是“事后洞察、复盘”放到网站场景里它就是一面后视镜——用户来过、看过、离开这些事只有事后才留下数据。Hindsight 恰好也是一套开源的、可自托管的网站分析平台的名字目标就是把这面“后视镜”装回你自己的服务器上。这趟迁移里我把个人博客的统计从 Google Analytics 换成了 Hindsight去掉了 Cookie 弹窗去掉了第三方脚本数据全在自己机器里查询速度还快得离谱。这篇文章不打算复述官方文档只记录我实际部署、接入、看数、排错的全过程以及它和 Plausible、Umami 这类工具之间的取舍。想彻底掌控访问数据的人、被 Cookie 弹窗烦到不行的站长以及刚开始接触自托管分析产品的开发者都适合接着往下看。1. Hindsight 的整体设计与思路拆解1.1 为什么我会倾向自建分析平台先说动机。我一直觉得 Google Analytics 功能确实强但放在今天这个小网站上有点“杀鸡用牛刀”。它默认会种 Cookie访客第一次进来就得面对一串授权弹窗数据虽然免费但采样、延迟、数据出口这些事让我心里没底。最要命的是我导出原始事件数据时发现很多分析需求在免费额度下根本绕不过“抽样”这两个字。自建分析平台解决的就是这件事数据进你的服务器出你的数据库规则你自己定。Hindsight、Plausible、Umami、Matomo 都是这条路。它们通常不依赖 Cookie不给访客加跟踪指纹法律合规压力小很多而且部署完以后代码和数据库都捏在自己手里。我的博客访问量不算大一天几千 PV一台 2C2G 的云服务器完全跑得动。换下来之后最直观的感受是页面不再额外加载一堆第三方域名资源隐私弹窗消失分析面板打开速度比 GA 快一个量级。如果说在给别人做产品时还得考虑团队协作和功能完整性那自己的小网站、小工具箱自托管是性价比最高的方案。1.2 技术栈为什么是 Go ClickHouseHindsight 后端用 Go 写前端是 React数据层放在 ClickHouse 里。这个组合第一眼有点重但拆开看非常合理。Go 的好处是部署简单编译完就是一个二进制跑起来没有 JVM 那一大套依赖。就算用 Docker镜像也小内存占用比 Java 系的产品友好太多。React 负责看板层图表交互和筛选器体验做得很顺。真正的重点是 ClickHouse。它是个列式数据库和 MySQL、PostgreSQL 这种行式数据库的思路完全不一样。行式库适合频繁增删改一行数据而分析场景的查询往往是“扫描几百万行但只取其中两列做聚合”。列式库把每列单独存储查询时只需要读相关列所以“今天有多少访客”“哪个页面最受欢迎”这类统计能秒级出结果。用生活化的类比解释行式数据库像一本按日期写满的日记你想统计这个月提到“爬山”的次数得把每一页从头翻一遍列式数据库像一沓按主题整理的卡片你只需要抽出“活动”那一沓数一遍。事件分析天生适合这种结构。1.3 事件模型是这套工具的精髓Hindsight 没有把“页面浏览量”当成唯一的数据类型而是把所有行为都抽象成事件。一条事件记录通常包含这些字段站点标识、事件名、时间戳、当前 URL、来源 URL、会话 ID、用户代理以及可选的业务属性。{ site_id: blog, event: pageview, ts: 1735689600, url: https://example.com/posts/hindsight-deploy, referrer: https://duckduckgo.com/, session_id: 8f4a91c2e6, meta: { title: Hindsight 自托管部署 } }这个设计的妙处在于先存原始事件展示层再按需求聚合。今天想看 PV就把事件按 URL 分组明天想算转化率就把“注册按钮点击”和“注册成功”两个事件串起来。它不像传统统计工具那样预先把几十个报表字段算好而是把灵活性留到了查询阶段。我是做产品出身特别吃这一套。因为埋点需求永远会变今天要追踪下载按钮明天要追踪搜索框如果底层模型不支持自定义事件后面每个新指标都要改数据库结构太痛了。事件模型等于提前把口子开好你只需要往里塞数据。1.4 和 Plausible、Umami 等同类工具的横向对比自托管分析工具已经不少选 Hindsight 之前我也对比过几个工具技术栈存储隐私特点部署难度核心优势PlausibleElixir ClickHouseClickHouse 或 Postgres无 CookieIP 匿名中成熟稳定功能打磨细UmamiNext.js PrismaPostgres无 Cookie轻量低界面简洁资源占用小MatomoPHP MySQLMySQL/MariaDB可配置 Cookie中高功能最全类 GAHindsightGo React ClickHouseClickHouse无 Cookie事件模型中高查询快自定义事件强如果你只需要“今天多少人、哪个页面火”Umami 上手最快如果你需要一整套完整报表并愿意维护 PHPMatomo 更合适Hindsight 则更像“事件分析平台”而不是“网站计数器”适合愿意稍微多花点部署成本、但换来灵活查询的人。我当时选它核心原因是看中了事件模型和 ClickHouse 的查询能力因为后面我想给自己的工具站做几个自定义转化漏斗。2. 部署前要准备好的几件事2.1 服务器、域名和基础环境先列一下我这次部署的底线配置系统Ubuntu 22.04 LTS配置2 核 CPU4G 内存2G 也能跑但 ClickHouse 偶尔会吃紧磁盘20G SSD日志增长不快但建议预留一半余量域名单独用analytics.example.com作为统计入口别和主站混在一起我推荐把统计服务放到一个独立子域名原因有两个第一主站服务器和统计服务分开后将来换主机不用牵连业务第二广告拦截器通常只屏蔽常见统计域名自建域名很少会被误杀但也别把统计脚本和业务脚本混到一个域名下否则以后想拆就难了。基础环境只需要 Docker 和 Compose 插件sudo apt update sudo apt install -y docker.io docker-compose-v2 sudo systemctl enable --now docker装完以后确认一下版本Compose 插件和旧版docker-compose的命令格式略有差别后面统一用docker compose。然后去 DNS 控制台加一条 A 记录把analytics.example.com指向服务器 IP。这一步可以提前做因为 DNS 生效需要时间而 Docker 启动很快。2.2 用 Docker Compose 一次拉起全家桶Hindsight 官方文档一直推荐用 Docker 部署我也建议直接用 Compose。我的docker-compose.yml大概是下面这个样子基于我当时部署的版本整理出来的镜像名称和 tag 会随版本变化以官方 README 为准services: clickhouse: image: clickhouse/clickhouse-server:23.8 container_name: hs-clickhouse restart: unless-stopped environment: CLICKHOUSE_DB: hindsight CLICKHOUSE_USER: hindsight CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD} ulimits: nofile: soft: 262144 hard: 262144 volumes: - ./ch_data:/var/lib/clickhouse hindsight: image: ghcr.io/hindsight/hindsight:latest container_name: hs-web restart: unless-stopped environment: CLICKHOUSE_DSN: clickhouse://hindsight:${CLICKHOUSE_PASSWORD}clickhouse:9000/hindsight APP_BASE_URL: https://analytics.example.com DISABLE_REGISTRATION: true ports: - 127.0.0.1:8080:8080 depends_on: - clickhouse这里有几个细节要解释。第一ClickHouse 的ulimits是必填项默认文件句柄限制不够启动时容易报 “Too many open files”。如果不加大概率会在日志里看到一个和nofile相关的错误。第二我把 Hindsight 的 Web 端口绑定在了127.0.0.1:8080而不是直接暴露到公网。因为 HTTPS 和外部访问交给反向代理这样做可以减少一层攻击面。如果你不会配置反向代理也可以直接映射8080:8080但强烈不建议裸奔。第三密码不要写在 compose 文件里用.env文件存放CLICKHOUSE_PASSWORD$(openssl rand -hex 24)然后把生成的随机字符串写进.env启动时 Compose 会自动读取。之后依次执行docker compose up -d docker compose ps docker compose logs -f hindsight看到 Web 服务日志正常输出监听端口后用curl http://127.0.0.1:8080测试一下。这一步能通说明应用本身没问题剩下的就是把它暴露出去。2.3 上 HTTPSCaddy 与 Nginx 两种方式我第一个用的是 Caddy因为它的 HTTPS 配置真的省心。在服务器上安装 Caddy 后Caddyfile 里写三行analytics.example.com { reverse_proxy 127.0.0.1:8080 }Caddy 会自动申请和续期证书第一次访问就能带上小绿锁。如果你已经有一套 Nginx也可以把下面这段塞进对应的 server 块里server { server_name analytics.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }用 Nginx 的话记得配合 certbot 发证书不然浏览器会拦得不舒服。无论哪种方式配置完打开https://analytics.example.com能看到登录页就算成功了。2.4 前端接入和分析脚本接下来是让网站把数据送进来。Hindsight 的接入方式通常是往页面里插入一段脚本类似这样script async srchttps://analytics.example.com/hs.js>script-src self https://analytics.example.com; connect-src self https://analytics.example.com;这个坑我踩过一次脚本加载了但事件请求被 CSP 拦下看板里整整三天是零数据。所以接入后第一件事不是看面板而是看浏览器控制台有没有报 CSP 错误。3. 上线后核心指标与事件怎么用3.1 熟悉默认看板别被虚荣指标绑架打开 Hindsight 看板默认能看到 PV、独立访客、会话数、跳出率、访问时长、热门页面、来源渠道、设备分布这些常见指标。我的建议是看数据前先问自己一个问题我今天要看的是“动作”还是“结果”。以博客为例PV 涨了 50% 听起来开心但如果来源全是某个社交平台的批量点击停留时间极短那这波流量对“读者真正读完文章”这个目标毫无帮助。我更愿意关注“热门页面”和“来源渠道”这两个模块前者告诉我选题方向后者告诉我该去哪宣传。跳出率则用来发现页面体验问题——如果一个落地页跳出率长期超过 85%大概率是首屏没说明白或者加载太慢。有基础之后可以进一步用 Hindsight 的自定义筛选功能把“来自搜索引擎且访问时长超过 60 秒”的会话单独拉出来看。这一步就能把泛流量和“有效流量”区分开。3.2 埋点一个自定义事件Hindsight 的事件模型让我最舒服的是埋点不用改后端。以“下载按钮”为例在前端代码里加一个监听document.getElementById(btn-download).addEventListener(click, function () { window.hs window.hs.track(download_click, { file: setup.zip, from: landing }); });用户在页面上的每次点击都会带着事件名和属性发到收集端之后在后台里选择download_click事件就能看到这个按钮的点击次数和转化来源。做落地页 A/B 测试时这个功能比单纯看 PV 有用得多你可以把方案 A 的按钮埋成cta_a_click方案 B 埋成cta_b_click跑一周看数据说话。再进阶一点把多个事件串成漏斗。流程是“访问落地页 - 点击下载按钮 - 打开注册页 - 完成注册”每一步命名成独立事件Hindsight 的漏斗分析会告诉你每一步流失了多少人。这一步往往能发现真正的产品问题比如点击很多但注册很少那问题大概率出在注册表单而不是流量入口。3.3 会话和留存怎么看会话是理解用户行为的关键单位。Hindsight 通过会话 ID 把一组相关事件聚合在一起这样你能看到的不只是“有多少次页面浏览”而是“访客一次进来做了哪些事”。我一般会关注两类会话一类是“单页会话”进来只看了一个页面就走这类会话占比高说明内容相关性或站内导航有问题另一类是“多页会话”这类用户才是真正在消费内容的人。把这两个比例拉出来对比比单独看跳出率更明确。留存分析则更适合产品型站点。比如注册后第 1 天、第 7 天、第 30 天还有多少用户回来形成队列对比。内容型网站不用太执着于这个指标因为很多人是搜到某篇文章才来不订阅不注册也正常。但你如果做的是工具站留存数据会直接告诉你产品是“一次性工具”还是“日常工具”。如果你想更暴力一点可以直接连 ClickHouse 写查询。下面这个是一个示意 SQL具体表名以你部署的版本为准SELECT toDate(timestamp) AS day, uniqExact(session_id) AS sessions FROM events WHERE site_id blog AND event pageview GROUP BY day ORDER BY day DESC LIMIT 30;ClickHouse 对这种按天聚合的查询非常擅长30 天的数据量对个人站点来说基本是毫秒级返回。3.4 隐私、留存与数据导出Hindsight 默认不种 Cookie、不做浏览器指纹这对访客来说确实是更友好的方案。但“没有 Cookie”不代表你可以什么都不写我的习惯是在网站隐私政策里加一句“本站使用自托管分析服务不设置跨站 Cookie仅记录必要的访问事件”。别小看这句话真遇到较真的用户它能帮你省很多解释成本。数据留存方面个人站点默认配置已经够用但如果你在意磁盘占用建议定期清理三个月前的原始事件。ClickHouse 支持按时间删除分区数据也可以用一条简单的 DELETE 按时间范围清理。自托管的好处就是这种事没人拦你想留多久留多久想删立刻删。导出数据也很重要。Hindsight 后台一般提供事件导出或查询接口我每月会把原始事件导出一次存到本地备份因为再可信的数据库也有误删的可能自己的备份才是最后的保险。4. 常见问题与排查技巧实录4.1 接入后数据为零这是最让人焦虑的问题但九成都是配置问题。我的排查顺序固定三步第一步打开浏览器控制台看 Network 里面有没有指向analytics.example.com的请求。如果没有说明脚本根本没加载检查一下模板路径和 CSP。第二步看请求状态码如果是 404说明hs.js路径不对或者反向代理没生效如果是 204/200说明请求已经进入服务端。第三步去服务器上看容器日志docker compose logs collector找不到 collector 容器的话就统一看 hindsight 主服务的日志。大多数情况下日志里会直接写出site_id 不存在或referrer 不允许这类明确错误照着修就行。另外广告拦截插件也可能把自建统计请求拦截掉尤其是插件规则里包含了较新的分析域名。不过自建域名的命中率远低于 GA我自己测试下来影响很小真遇到了临时关掉插件排除即可。4.2 ClickHouse 起不来或总被 OOM如果你看到 ClickHouse 容器反复重启先看日志是不是 “Memory limit exceeded”。2G 内存的机器确实容易触发这个问题因为 ClickHouse 启动默认会预留较大内存作为查询缓存。应对办法是显式限制内存使用在配置目录里加一个内存上限文件yandex max_server_memory_usage2147483648/max_server_memory_usage /yandex注意不同版本 ClickHouse 的根标签可能叫yandex或clickhouse以你镜像版本为准。配置完重启容器后内存占用会稳定在 2G 左右4G 内存的机器跑起来就非常宽裕了。如果nofile报错回到 compose 里的ulimits确认数值不小于 262144。这个限制不是可选项而是 ClickHouse 官方文档明确要求的。4.3 时区不对导致日报数据漂移现象是看板里的“今日”数据在早晨八点前显示为零或者日期分组“少一天”。原因很简单容器默认用 UTC而你在东八区。解决办法是在 compose 环境变量里统一加environment: TZ: Asia/Shanghai前端看板时区也要同步设置。这事看起来小但如果不处理所有日报、周报的日期口径都会错位后面复盘数据时非常麻烦。我在第一次部署时忽略了这一步导致第一周的“周一峰值”其实混进了周日的半夜流量数据比例完全失真。4.4 数据备份、升级与回滚自托管就要承担运维责任备份不能不做。最简单的思路是直接对 ClickHouse 数据目录做快照容器停止状态下打包docker compose stop tar czf hs-backup-$(date %F).tar.gz ./ch_data docker compose up -d数据量小的话这个方案完全够用。升级前重复一遍把备份文件下载到本地然后再拉新镜像。如果新版本出现兼容性问题直接把 compose 里的镜像 tag 改回旧版本从备份恢复数据目录后重新启动基本就能回到升级前状态。我现在的习惯是每次升级前都看一眼官方 changelog确认没有破坏性的 SQL 表结构变更。数据这种东西平时备份了用不上等真出事就知道救命。4.5 referrer 刷量与内网流量干扰网站上线一段时间后看板里可能出现一堆“来源是奇怪域名”的流量这些大概率是来探测或刷量的。别指望它彻底消失也别被它影响判断。处理方法是先把这类 referrer 加到过滤规则里再重新看数据。真实用户流量通常集中在搜索引擎、直接访问和少数几个社交平台突然暴涨的“未知来源”优先怀疑刷量。内网 IP 的干扰也值得一提。如果你在开发环境里也嵌入了统计脚本测试人员的访问会污染数据。解决办法是给统计服务配置 IP 过滤或者建立一个单独的测试站点 ID把开发测试流量和线上流量彻底分家。5. 这套方案的影响范围和适用边界5.1 哪些场景收益最大跑了几个月之后我越来越清楚 Hindsight 适合谁。个人博客是收益最明显的场景一天几千 PV数据量不大ClickHouse 的查询能力完全溢出换来的是绝对的数据主权和几乎没有的隐私负担。独立开发者的产品站也合适因为自定义事件让你能低成本追踪注册、激活、付费这些关键动作不需要给第三方 SaaS 按月交钱。内部工具和私有系统更推荐。公司内部系统不适合把数据发到外部第三方自托管分析服务能把所有访问事件留在内网既满足审计需求又不用引入外部 Cookie。甚至可以说只要是你自己能控制服务器的场景Hindsight 都值得试一次。5.2 哪些情况不建议用反过来也说说边界。如果你需要的是会话录屏、热力图、漏斗之外的自动化营销Hindsight 这类事件分析工具不是正确答案Matomo 或者商业分析平台会更合适。如果你的团队没人愿意维护 ClickHouse或者网站访问量已经大到需要集群那就别为了“自托管”而自托管分摊运维成本也是成本。技术上Hindsight 的部署确实比 Umami 多了一个 ClickHouse门槛高了一截。这也意味着你选择它的前提是愿意承担一点点运维成本来换取查询能力和事件模型上的灵活性。我自己跑下来的体会是切换后第一个感觉是首页加载分数上去了第三个脚本消失了Cookie 弹窗也没了第二个感觉是查数据终于不用等转圈。当然代价是每个月要花点时间看容器状态、做一次备份。对我来说这笔账非常划算。如果你正好也在纠结统计方案不妨挑个周末部署一套让数据告诉你答案。
返回列表