GA4のPV上位記事をトップページへ自動表示する方法
GA4 Data APIの直近30日PVをContent Collectionsの記事と照合し、上位3件をゆまラボのTOPページへ自動表示した。既存ArticleCardを再利用し、PV数や順位は表示しない構成にした。

トップページに人気記事を自動表示したくても、 「GA4からPVは取れたけど記事データとどう結び付けるのか」 「期間は何日にするのか」 「PV数や順位まで画面に出すべきなのか」 と迷っていないでしょうか。データ取得より、その数字を読者向けの導線へ変換するところが実装の本体です。
ゆまラボではGA4 Data APIから直近30日のpagePathとscreenPageViewsを取得し、/blog/の記事と照合してPV上位3件を「注目コンテンツ」としてTOPへ表示しました。順位やPV数そのものは出さず、既存の記事カードだけを人気順に並べています。
この記事では、既に作ったGA4取得処理をAstro側へ接続し、APIの集計結果から実在する記事だけを選ぶ流れを紹介します。実データを使った読者向けの導線を作りたい場合の実装例で、アクセス数そのものは表示しません。
GA4 Data APIをCloudflareビルドで使う方法|OAuth認証へ切り替えた手順
今回は、その認証とGA4 Data APIで記事別PVを取得する方法|Node.jsで実データを取得をTOPページへ接続する。
修正前はカテゴリの次に新着・更新記事#
修正前のTOPページは、上から次の順になっている。
hero
↓
連載
↓
カテゴリ
↓
新着・更新記事
「人気記事」のような枠はまだ存在しない。

以前から、アクセスデータが蓄積したら「カテゴリ」と「新着・更新記事」の間へ注目コンテンツを追加する予定にしていた。
今回、その部分を実装する。
GA4取得処理をサイト側でも再利用する#
既存の scripts/ga-pageviews.mjs には、GA4 Data APIから次のデータを取得する処理がある。
- Property:
553074385 - 期間:
30daysAgoからyesterday - dimension:
pagePath - metric:
screenPageViews /blog/前方一致- PV降順
今回、共通処理を src/utils/ga4-pageviews.mjs へ切り出し、TOPページからも利用する形にした。
変更したファイルは3つ。
src/utils/ga4-pageviews.mjs
scripts/ga-pageviews.mjs
src/pages/index.astro
node scripts/ga-pageviews.mjs から実行できる既存CLIも残したまま、Astro側から同じ取得処理を利用する構成にした。
新しいnpmパッケージは追加していない。
ローカルADCとCloudflare Secretを切り替える#
認証は実行環境によって2経路にした。
ローカル
↓
gcloud Application Default Credentials
Cloudflare
↓
GA4_ADC_JSON
GA4_ADC_JSON が存在する場合はJSONを解析し、authorized_user 形式の認証情報としてGA4クライアントへ渡す。
Secretが存在しないローカル環境では、従来どおりADCへフォールバックする。
これにより、開発時は毎回Cloudflare用のSecretを手元へコピーする必要がなく、ローカルで使ってきたADCと同じ方法で確認できる。
一方、Cloudflare側ではgcloud CLIを前提にせず、Secretに登録した認証情報を使用する。
認証情報は生成HTMLや画面へ出力しない。
GA4のURLをそのまま人気記事にはしない#
GA4から返る pagePath には、Content Collectionsの記事ではないURLも含まれる。
実際、Cloudflare連携前までの確認では次のような結果があった。
/blog/
/blog/codex-luna-astra-astro-comparison/
/blog/sns-publishing-candidates/
/blog/27-astro-image-optimization-lazy-loading/
...
/blog/ は記事一覧ページなので、人気記事の候補には入れない。
また、GA4にURLが残っていても、現在のContent Collectionsに対応する公開記事が存在しなければカードを作れない。
そこで今回の処理では、GA4の結果を現在のContent Collectionsの記事URLと照合してから候補を決めるようにした。
GA4
pagePath + screenPageViews
↓
/blog/ を除外
↓
Content Collectionsの記事URLと照合
↓
一致した記事だけ残す
↓
人気順に並べる
↓
上位3件
タイトル、description、heroImage、公開日などの表示情報はGA4から作らず、Astroの記事データを使う。
GA4は「どの記事がよく読まれたか」を決めるためだけに使用する。
同じPVならpagePathの昇順にする#
実データでは、3位付近に同じPVの記事が複数あった。
今回確認した時点では、次の2記事がどちらも30PVで並んだ。
/blog/27-astro-image-optimization-lazy-loading/
/blog/technical-blog-monetization/
同率時の順番が毎回曖昧にならないよう、ソート条件を固定した。
1. screenPageViews DESC
2. pagePath ASC
まずPVの多い順。
PVが同じなら pagePath の昇順。
この順序で並べた後、Content Collectionsと一致する記事の先頭3件を採用する。
実際に選ばれた3記事#
実装後に選ばれた記事は次の3件。
| 記事 | pagePath | screenPageViews |
|---|---|---|
| CodexでAstro改修をLunaとAstraに任せて比較―小さな改修に高性能モデルは必要なのか? | /blog/codex-luna-astra-astro-comparison/ | 66 |
| 記事をSNSへ流す運用を始める―X連携の前に投稿方法と候補を確認する | /blog/sns-publishing-candidates/ | 38 |
| Astroで画像を最適化する方法|WebP・srcset・遅延読み込みを実装 | /blog/27-astro-image-optimization-lazy-loading/ | 30 |
このPV数は確認用のデータで、TOPページには表示しない。
「1位」「2位」「3位」の順位表示も付けていない。
読者から見ると、通常の記事カードが3件並ぶだけになる。
既存のArticleCardをそのまま使う#
注目コンテンツ専用の新しい記事カードは作らなかった。
既存の ArticleCard.astro を再利用した。
これにより、TOPページの新着記事や他の一覧と同じ形式で、次の情報を表示できる。
- カテゴリ・サブカテゴリ
- 公開日
- アイキャッチ
- 記事タイトル
人気記事用だけ別のカードデザインを持たせると、同じ記事を表示するためのUIが増えてしまう。
今回は「人気順で3件選ぶ」というデータ側だけを追加し、カード側は既存のものを使う形にした。
カテゴリと新着・更新記事の間へ追加#
src/pages/index.astro へ「注目コンテンツ」を追加した。
変更後は、この順番になった。
hero
↓
連載
↓
カテゴリ
↓
注目コンテンツ
↓
新着・更新記事
見出しの横には「アクセスの多い記事」と補足を入れている。
3件のカードにはPV数や順位を出していないため、既存TOPの見た目から大きく外れない。

実際の画面では、カテゴリの直後に3枚のカードが並び、その下にこれまでどおり「新着・更新記事」が続く。
CLIでも82記事を取得できた#
実装後も既存CLIを実行した。
node scripts/ga-pageviews.mjs
結果は成功し、今回の条件では82記事が対象になった。
前段階では /blog/ を含む83件が取得されていたが、今回の人気記事処理では記事一覧ページを対象外にしている。
GA4_ADC_JSON を使う認証経路でもGA4取得に成功した。
ローカルADCとCloudflare用Secretの両方を同じGA4取得処理へ接続できた。
npm run buildも成功#
続けてAstroのビルドを実行した。
npm run build
結果は成功。
確認できた内容は以下。
- 237ページ生成
- 内部リンク9649件
- リンクエラー0件
- TOPページに注目コンテンツ3件を生成
- PV数をHTMLへ出力していない
- Secret情報をHTMLへ出力していない
既存の新着・更新記事もそのまま残っている。
今回の変更では、API取得に失敗した場合は既存CLIと同じくビルドを失敗させる仕様にした。取得失敗時だけ古いランキングを残すキャッシュ処理などは追加していない。
人気記事はビルド時に更新される#
今回の構成では、GA4 Data APIをAstroのビルド時に呼び出す。
そのため、TOPページの「注目コンテンツ」はブラウザを開くたびにGA4へ問い合わせるわけではない。
Cloudflareでビルド
↓
GA4 Data APIから直近30日を取得
↓
人気記事3件を決定
↓
AstroがTOPページを生成
↓
静的HTMLとして配信
次のビルドが実行されるまで、表示される3件はそのままになる。
デプロイ時点の直近30日データを使い、「注目コンテンツ」として扱う。リアルタイム更新は行わない。
変更したファイルと役割#
今回の変更は、TOPページの人気記事表示に必要な範囲だけに絞った。
src/utils/ga4-pageviews.mjs
GA4取得と認証の共通処理
scripts/ga-pageviews.mjs
既存CLIから共通処理を利用
src/pages/index.astro
Content Collectionsとの照合
人気記事3件の決定
注目コンテンツの表示
新規npmパッケージは追加していない。
既存URL、カテゴリ、連載、タグ、RSS、sitemap、robots.txt、GA4計測タグも変更していない。
これで、「将来はGA4のデータから人気記事を自動表示する」と決め、GA4を導入し、Data APIから記事別PVを取得してきた流れが、TOPページの表示までつながった。


