【Hugo】PV数の人気記事のランキングを取得する【Node.js】

【Hugo】PV数の人気記事のランキングを取得する【Node.js】

HugoGoogle Analyticsで各記事のPV数のランキングをNode.jsで取得する方法を紹介します。

なお、Node.jsはDockerで動かす想定です。

Google Analytics Data APIの設定

まず、各記事のPV数を取得するためにGoogle Analytics Data APIを設定していきます。GCPにログインし、APIライブラリからAPIを有効にします。

Google Analytics Data APIの設定1

Google Analytics Data APIの設定1

Google Analytics Data APIの設定2

Google Analytics Data APIの設定2

次に、サービスアカウントを作成していきます。

Google Analytics Data APIの設定3

Google Analytics Data APIの設定3

Google Analytics Data APIの設定4

Google Analytics Data APIの設定4

「サービスアカウント名」と「サービスアカウントID」を入力し、完了ボタンをクリックします。

Google Analytics Data APIの設定5

Google Analytics Data APIの設定5

Google Analytics Data APIの設定6

Google Analytics Data APIの設定6

サービスアカウントを作成後、秘密鍵のJSONファイルのダウンロードを行います。サービスアカウントの画面から鍵を追加していきます。

Google Analytics Data APIの設定7

Google Analytics Data APIの設定7

Google Analytics Data APIの設定8

Google Analytics Data APIの設定8

ダウンロードしたファイルはデータ取得で使用するので、ブログフォルダ内の.gcp内に配置します。

Gitで管理している場合は、間違って公開してしまわないよう.gitignoreに追記しておく必要があります。

.gitignore
1.gcp

Google Analyticsの設定

ここから、Google Analyticsでサービスアカウントの権限設定を行います。管理画面の「プロパティのアクセス管理」をクリックします。

Google Analyticsの設定1

Google Analyticsの設定1

右上の「+」ボタンからユーザーを追加をクリックします。

Google Analyticsの設定2

Google Analyticsの設定2

作成したサービスアカウントIDをメールアドレス欄に入力し、標準の役割は「閲覧者」に設定します。

Google Analyticsの設定3

Google Analyticsの設定3

PVランキングを取得するスクリプトの作成

ここからPVランキングを取得するスクリプトの作成していきます。今回はDockerを使用しますので、新たにcompose.create-ranking.ymlを作成します。

compose.create-ranking.yml
 1volumes:
 2  node-modules:
 3
 4services:
 5  node:
 6    image: node:latest
 7    working_dir: /node
 8    tty: true
 9    ports: 
10    - '3000:3000'
11    volumes:
12      - .:/node
13      - node-modules:/node/node_modules
14    command: >
15      bash -c "npm install &&
16      npm install @google-analytics/data &&
17      node scripts/create-ranking.js"

実際にPVデータを取得するanalytics-api.jsと、表示用にjsonファイルを作成するcreate-ranking.jsscriptsフォルダ内に配置します。

scripts/analytics-api.js
 1// Google Analytics 4 property ID
 2propertyId = 'XXXXXXXXX'; //プロパティID
 3
 4// Imports the Google Analytics Data API client library.
 5const { BetaAnalyticsDataClient } = require('@google-analytics/data');
 6process.env.GOOGLE_APPLICATION_CREDENTIALS = `.gcp/google-analytics_credentials.json`;
 7
 8// Using a default constructor instructs the client to use the credentials
 9// specified in GOOGLE_APPLICATION_CREDENTIALS environment variable.
10const analyticsDataClient = new BetaAnalyticsDataClient();
11
12exports.runReport = async function () {
13  const [response] = await analyticsDataClient.runReport({
14    property: `properties/${propertyId}`,
15    dateRanges: [
16      {
17        startDate: '8daysAgo',
18        endDate: '1daysAgo',
19      },
20    ],
21    dimensions: [
22      {
23        name: 'pagePath',
24      },
25    ],
26    metrics: [
27      {
28        name: 'screenPageViews',
29      },
30    ],
31  });
32  return response;
33}
scripts/create-ranking.js
 1const { runReport } = require('./analytics-api.js');
 2
 3const fs = require('fs');
 4const currentDate = new Date().toISOString();
 5
 6async function main() {
 7  try {
 8    const response = await runReport();
 9
10    let rankings = []
11    response.rows.forEach((row) => {
12      rankings.push({
13        pagePath: row.dimensionValues[0].value,
14        pv: row.metricValues[0].value,
15      })
16    })
17    fs.writeFileSync(
18      'data/ranking.json',
19      JSON.stringify(
20        {
21          items: rankings,
22          createdAt: currentDate
23        },
24        null,
25        4
26      )
27    )
28  } catch (error) {
29    console.error('Error running report:', error);
30  }
31}
32
33main();

PVデータの取得は以下のコマンドで実行できます。

ターミナル
1$ docker compose -f compose.create-ranking.yml run --rm node # PVランキング取得

Hugoでランキングを表示

Hugo上では以下の様にしてPVデータを取得できます。参考として、当サイトのメニューバーに表示させているpartialファイルを紹介します。

ranking.html
 1{{ $ranking := slice }}
 2{{ range $item := sort .Site.Data.ranking.items "pv" "desc" }}
 3  {{ $ranking = $ranking | append (dict "page" $item.pagePath) }}
 4{{ end }}
 5
 6<div class="widget-recent widget">
 7  <h4 class="widget__title">人気記事</h4>
 8  <div class="widget__content">
 9    <ul class="widget__list">
10      {{ range first 5 $ranking }}
11        {{ $url := replace .page "/" ""}}
12        {{ $page := $.Site.GetPage $url }}
13        <li class="widget__item"><a class="widget__link" href="{{ $page.Permalink  }}" target="_blank">{{ $page.Title }}</a></li>
14      {{ end }}
15    </ul>
16  </div>
17</div>

Github Actionsの設定

1週間に一度、自動でランキング取得処理とリポジトリへのプッシュを行えるよう、.github/workflowsディレクトリにupdate-ranking.ymlを配置します。ついでに手動実行もできるようにしていおきます。

update-ranking.yml
 1name: update-ranking
 2
 3on:
 4  schedule:
 5    - cron: '0 0 * * 0'
 6  workflow_dispatch:
 7
 8jobs:
 9  update-ranking:
10    runs-on: ubuntu-latest
11    timeout-minutes: 5
12    permissions:
13      id-token: write
14      contents: write
15    steps:
16      - name: Checkout
17        uses: actions/checkout@v4
18        with:
19          submodules: true
20          fetch-depth: 0 # enableGitInfoでの取得用
21      - name: Setup npm
22        uses: actions/setup-node@v4
23        with:
24          node-version: 20
25      - name: Cache npm dependencies    
26        uses: actions/cache@v4
27        with:
28          path: ~/.npm
29          key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
30          restore-keys: ${{ runner.os }}-node-
31      - name: npm Install
32        run: npm ci
33      - name: Create Ranking
34        env:
35          GOOGLE_ANALYTICS_CREDENTIALS: ${{ secrets.GOOGLE_ANALYTICS_CREDENTIALS }}
36        run: |
37          mkdir .gcp
38          echo "$GOOGLE_ANALYTICS_CREDENTIALS" > .gcp/google-analytics_credentials.json
39          node scripts/create-ranking.js          
40      - name: Commit and Push
41        run: |
42          git branch
43          git config user.name "github-actions[bot]"
44          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
45          git commit -am "Create Ranking"
46          git push origin HEAD

フローとしては、update-ranking.ymlmainブランチに最新のランキングデータがプッシュされ、プッシュとトリガーとして、上の記事で設定した自動デプロイのフローが実行されるといった流れになります。以下の記事も参考にしてください。

続いて、GitHubのSecrets設定で、GOOGLE_ANALYTICS_CREDENTIALSに先ほどダウンロードした鍵の内容を設定します。

GitHub ActionsのSecrets設定

GitHub ActionsのSecrets設定

また、自動デプロイ処理中でコミットとプッシュができるように、Actionsの設定の「Workflow permissions」を「Read and write permissions」に設定しておきましょう。

GitHub Actionsの書き込み設定

GitHub Actionsの書き込み設定

これで、GitHubへのプッシュ時にランキングを取得してからデプロイするようになります。


今回はHugoでPVランキングを取得する方法を紹介しました。やはり、人気記事の一覧はブログサイトとしてはあった方が見栄えが良い気がしますね。以上で記事を終わりにします。

参考文献