HugoとGoogle Analyticsで各記事のPV数のランキングをNode.jsで取得する方法を紹介します。
なお、Node.jsはDockerで動かす想定です。
まず、各記事のPV数を取得するためにGoogle Analytics Data APIを設定していきます。GCPにログインし、APIライブラリからAPIを有効にします。
次に、サービスアカウントを作成していきます。
「サービスアカウント名」と「サービスアカウントID」を入力し、完了ボタンをクリックします。
サービスアカウントを作成後、秘密鍵のJSONファイルのダウンロードを行います。サービスアカウントの画面から鍵を追加していきます。
ダウンロードしたファイルはデータ取得で使用するので、ブログフォルダ内の.gcp
内に配置します。
Gitで管理している場合は、間違って公開してしまわないよう.gitignore
に追記しておく必要があります。
1.gcp
ここから、Google Analyticsでサービスアカウントの権限設定を行います。管理画面の「プロパティのアクセス管理」をクリックします。
Google Analyticsの設定1
作成したサービスアカウントIDをメールアドレス欄に入力し、標準の役割は「閲覧者」に設定します。
ここからPVランキングを取得するスクリプトの作成していきます。今回はDockerを使用しますので、新たに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.js
をscripts
フォルダ内に配置します。
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}
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上では以下の様にしてPVデータを取得できます。参考として、当サイトのメニューバーに表示させているpartialファイルを紹介します。
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>
1週間に一度、自動でランキング取得処理とリポジトリへのプッシュを行えるよう、.github/workflows
ディレクトリに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.yml
でmainブランチ
に最新のランキングデータがプッシュされ、プッシュとトリガーとして、上の記事で設定した自動デプロイのフローが実行されるといった流れになります。以下の記事も参考にしてください。
続いて、GitHubのSecrets設定で、GOOGLE_ANALYTICS_CREDENTIALS
に先ほどダウンロードした鍵の内容を設定します。
また、自動デプロイ処理中でコミットとプッシュができるように、Actionsの設定の「Workflow permissions」を「Read and write permissions」に設定しておきましょう。
これで、GitHubへのプッシュ時にランキングを取得してからデプロイするようになります。
今回はHugoでPVランキングを取得する方法を紹介しました。やはり、人気記事の一覧はブログサイトとしてはあった方が見栄えが良い気がしますね。以上で記事を終わりにします。