之前看过一些 Hugo 显示文章阅读量的办法,主要归为两种,一种是用不蒜子,另一种是直接用网站使用的评论系统附带的统计功能,比如我试过的 Waline、Twikoo 等都有显示阅读量的功能。

在我看来,这两种办法都一些小缺点。不蒜子确实小巧简单,但毕竟需要多加载一个 js 文件;使用评论系统不需要另外的 js 文件,但是像这个网站,评论只有手动点击之后才会加载,这个功能实质上处于不可用的状态。

因此我把目光瞄向了 Umami,一个自托管的开源访问分析工具,这里面记载了每个页面的 UV、PV,而且查阅后发现也有 API,不如直接使用 Umami 的数据。

获取 Umami API Token

如果你是在直接在 Umami 网站注册帐号使用的,可以直接在网站后台获取 Api Token1

否则,如果是自托管,需要先进行身份验证。2(本文以下内容均以自托管为例)

使用 HoppscotchPOST https://your-umami-instance.com/api/auth/login

{
  "username": "your-username",
  "password": "your-password"
}

Send,返回 Token。

获取数据

获取网站统计信息是 GET https://umami-instance.com/api/websites/:websiteId/stats ,将其中的your-umami-instance.com替换为实例地址,:websiteId替换为 Website ID。

如果要显示单个页面的浏览量:GET https://umami-instance.com/api/websites/:websiteId/?startAt=1706745600000&endAt=1716866306859&url=:url

返回的数据串应该与下面的类似。

{
  "pageviews": {
    "value": 153,
    "change": 153
  },
  "uniques": {
    "value": 37,
    "change": 37
  },
  "bounces": {
    "value": 34,
    "change": 34
  },
  "totaltime": {
    "value": 7475,
    "change": 7475
  }
}
  • pageviews: 页面点击数
  • visitors:独立访客数量
  • bounces:仅访问单个页面的访问者数量
  • totaltime:在网站上花费的时间

在网页中嵌入

<script>
    document.addEventListener("DOMContentLoaded", function() {
        const fullUrl = window.location;
        const postPath = fullUrl.pathname;
        const websiteId = "website-id";  // 替换为你的 Umami 网站 ID
        const apiToken = "api-token";    // 替换为你的 Umami API 令牌

        const startAt = new Date('2024-01-01T00:00:00Z').getTime();  // 设置一个开始时间,例如开始使用 Umami 的时间
        const endAt = Date.now();

        fetch(`https://umami-instance.com/api/websites/${websiteId}/stats?startAt=${startAt}&endAt=${endAt}&url=${encodeURIComponent(postPath)}`, {
            headers: {
                'Authorization': `Bearer ${apiToken}`,
            }
        })
        .then(response => response.json())
        .then(data => {
        const viewsElement = document.getElementById("pageviews-count");
        viewsElement.textContent = `${data.uniques.value}`;
        });
    });
</script>
<div>
    <span id="pageviews-count">加载中...</span>
</div>

Tip

如果担心前端暴露 Api Token,可以使用 Cloudflare Worker 进行转发。


  1. 因为我没有使用 Umami Cloud,本文不涉及这种情况要如何展示阅读量,但是实现方法应该比较相似,只需要修改后面代码的地址部分即可。 ↩︎

  2. 更多 Umami Api 可以参考官网文档。 ↩︎