博客访问统计

我是如何在不追踪用户的情况下计算「热门文章」的

很多博客都会有一个模块:
热门文章 / Trending / Most Read

问题是,这个“热门”通常是怎么来的?

答案往往并不让人舒服:
第三方统计脚本、跨站追踪、用户画像、行为分析。

而我的博客选择了另一条路。

我希望知道哪些文章更受欢迎,但我不希望知道“谁”在读。

这篇文章,我想完整讲清楚:
在不追踪用户的前提下,我是如何计算“热门文章”的。


一、我不想用的那套东西

我明确排除了以下方案:

  • Google Analytics / GA4

  • 任何需要加载第三方 JS 的统计服务

  • 基于用户身份、登录态、跨页面行为的分析

  • 以 Cookie / Fingerprint 为核心的用户追踪

原因很简单:

  1. 对博客来说,这些信息并不必要

  2. 引入的复杂度远高于实际价值

  3. 与我对隐私与数据最小化的理解相冲突

我真正想要的,只有一件事:

哪些文章,在最近一段时间内,被更多人读过。


二、先明确一个事实:博客不需要“精确统计”

很多人一提统计,就会追求“绝对准确”。

但对博客而言,这是一个伪命题。

我不需要知道:

  • 某个用户读了多久

  • 是否滚动到第几行

  • 是否二次回访

  • 是否来自哪个广告渠道

我只需要一个稳定、可比较的信号

热门文章不是“精确数字”,而是“相对趋势”。


三、我的核心原则

在设计统计方案前,我给自己定了四个原则:

  1. 不识别用户

  2. 不跨页面追踪

  3. 不依赖第三方

  4. 不被缓存/CDN 干扰

只要违反其中任何一条,这套方案就不成立。


四、阅读统计的最小实现

1️⃣ 不在页面渲染时计数

页面可能被:

  • CDN 缓存

  • 静态化

  • 预渲染

所以我不会在 PHP 渲染阶段统计阅读数

取而代之的是:

页面加载完成后,通过一次 AJAX 请求,单独记录一次“阅读事件”。

这样:

  • 页面是否缓存无关紧要

  • 统计逻辑与内容完全解耦


2️⃣ 只做“文章级别”的计数

我不关心用户是谁,只关心:

  • 这篇文章是否被“读过一次”

因此我只在文章维度存两类数据:

  • 总阅读数

  • 按天聚合的阅读数

不记录:

  • 用户 ID

  • IP 原文

  • 访问路径

  • 行为序列


3️⃣ 非侵入式去重

为了避免刷新刷量,我只做了两件事:

  • 24 小时 Cookie 去重(只作用于当前文章)

  • 分钟级 IP Hash 限速(防脚本刷)

注意几点:

  • IP 不落库,只做 Hash

  • Cookie 不跨文章、不跨站

  • 没有任何“用户画像”的可能性


五、为什么我要引入「7 天热度」

如果只用“总阅读数”,会发生一件事:

老文章会永久霸榜。

这对博客并不健康。

所以我引入了一个非常简单的概念:

只看最近 7 天,这篇文章被读了多少次。

实现方式也很朴素:

  • 每天一个计数

  • 只保留最近 7 天

  • 自动清理旧数据

这带来一个重要结果:

  • 新文章有机会被看见

  • 老文章如果重新被讨论,也能再次上榜


六、我的「热门文章」算法

我没有使用复杂模型,只用了一个可解释、可写进博客的公式

热度分数 =(7 天阅读数 × 1.0)+(总阅读数 × 0.05)

它有几个特点:

  • 近期行为权重大

  • 历史内容仍有价值

  • 不会被一次流量峰值长期污染

更重要的是:

任何读者都可以理解这个规则。


七、这套方案我“刻意没有做”的事

为了保持克制,我主动放弃了很多看似“高级”的功能:

  • 不做实时榜单

  • 不做用户停留分析

  • 不做转化路径

  • 不做内容 A/B Test

因为这些都意味着:

  • 更多数据

  • 更复杂系统

  • 更强的追踪动机

而这已经偏离了“博客”这个媒介的本质。


八、这套方案对我来说意味着什么

对我而言,这不仅是一个统计方案,更是一种态度:

  • 内容比用户重要

  • 趋势比画像重要

  • 最小数据原则是工程美德

我依然可以知道哪些文章更受欢迎,
但我不需要知道是谁在读。


九、如果你也在写博客

如果你也在写博客,我的建议是:

在引入统计之前,先问自己一句话:
“我真的需要知道这么多吗?”

很多时候,一个简单、干净、可解释的方案,
反而更适合长期写作。

👁 2 views

Leave a Comment

Your email address will not be published. Required fields are marked *