Plausible Analytics を使って人気エントリーのランキングを生成する

Posted on

このブログのトラッキングには Plausible Analytics を使っています。オープンソースでシンプル、軽量、プライバシーに配慮し、Google Analytics の代替を謳うツールです。 Plausible Analytics には API も用意されており、JSON 形式でデータを取り出すことができます。

このデータを使って人気エントリーのランキングを出すようにしてみました(このページの下に表示されています)。

Plausible Analytics からデータを取得する

過去 30 日の中で訪問者数の多い順でトップ 5 のページを取得します。 GET リクエストを送るだけの簡単なシェルスクリプトを書きます。

#!/bin/bash

set -eu

base_dir=$(cd "$(dirname $0)/.."; pwd)
env_file="${base_dir}/.env"

if [ -f "${env_file}" ]; then
  . "${env_file}"
fi

res=$(curl -sS -H "Authorization: Bearer ${PLAUSIBLE_TOKEN}" \
  "https://plausible.io/api/v1/stats/breakdown?site_id=${PLAUSIBLE_SITE_ID}&property=event:page&limit=5")

echo "${res}" | jq -r ".results"

このスクリプトを実行すると次のような JSON が取得できます(数字はダミー)。

[
  {
    "page": "/2023/03/replace-onu-of-nuro/",
    "visitors": 999
  },
  {
    "page": "/2023/06/config-driven-import-via-terraform-1-5/",
    "visitors": 888
  },
  {
    "page": "/2020/03/elasticache-for-redis-with-terraform/",
    "visitors": 777
  },
  {
    "page": "/2012/05/jquery-ajax-status-code/",
    "visitors": 666
  },
  {
    "page": "/2021/08/review-the-kms-key-policy/",
    "visitors": 555
  }
]

Jekyll の Data Files で JSON を読み込む

Jekyll には _data ディレクトリにある YAML や JSON を自動的にロードする Data Files という機能があります。先ほどの JSON ファイルを _data/popular.json に置くと site.data.popular でアクセスすることができます。

あとはテンプレート側で出力するだけですが、Plausible Analytics の JSON にはタイトルが含まれていないのでひと工夫が必要です。全エントリーの情報は site.posts に入っているので、JSON の page の値をもとに site.posts から URL が一致するオブジェクトを取り出しています。

具体的には次のようなテンプレートを書いています。

<section>
  <h2>Popular Entries</h2>
  <ul>
{%- assign popular_pages = site.data.popular | map: 'page' %}
{%- for page in popular_pages %}
{%- assign post = site.posts | find_exp: 'post', 'post.url contains page' %}
    <li>
      <a href="{{ post.url | replace: 'index.html', '' }}">{{ post.title }}</a>
      <time datetime="{{ post.date | date: '%Y-%m-%d %H:%M' }}">{{ post.date | date: '%Y-%m-%d' }}</time>
    </li>
{%- endfor %}
  </ul>
</section>

ブログ更新時に人気エントリーのランキングを自動更新する

このブログの更新頻度は月に数回なので、人気エントリーのランキングもそんなに入れ替わりません。そのためブログを更新するときにランキングも更新すれば十分です。

ブログの更新は GitHub Actions でビルドして S3 にアップロードしているだけなので、ビルドの前に先ほどのスクリプトを実行して _data/popular.json を上書きします。

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: ruby/setup-ruby@v1
        with:
          bundler-cache: true

      - name: Get Popular Entries
        run: ./scripts/get-popular-entries.sh | tee ./_data/popular.json
        env:
          PLAUSIBLE_TOKEN: ${{ secrets.PLAUSIBLE_TOKEN }}
          PLAUSIBLE_SITE_ID: ${{ vars.PLAUSIBLE_SITE_ID }}
        continue-on-error: true

      - name: Build
        run: bundle exec jekyll build
        env:
          JEKYLL_ENV: production

      # このあとに S3 にアップロードする step が続く

Plausible Analytics に依存してブログの更新ができないのは避けたいので、失敗してもジョブを進めるために continue-on-error: true を指定しています。 API リクエストに失敗したとしても、コミットしてある JSON が使われて古いランキングが表示されるだけです。

もともとは「Hugo で人気記事ランキング機能を AWS のノーコードなサービスで作ったで」のような仕組みを考えていましたが、既存のパイプラインの延長でシンプルに実装できました。

Popular Entries

Recent Entries