Next.jsサイトをCloudflare Pagesにデプロイ!独自ドメイン設定までの完全ガイド

この記事では、人気フレームワーク「Next.js」で作成したWebサイトを、高機能なホスティングサービス「Cloudflare Pages」へデプロイし、さらにオリジナルの独自ドメイン(例: your-domain.com)を設定するまでの全手順を、初心者の方にも分かりやすく、ステップバイステップで解説する完全ガイドです。

Next.jsのデプロイ先としては開発元のVercelが有名ですが、Cloudflare Pagesも非常に有力な選択肢です。Cloudflareが提供する高速なCDN、強力なセキュリティ機能、そして余裕のある無料枠といったメリットがあり、個人開発から小~中規模のWebサイトまで幅広く活用できます。今回は、筆者がよく利用するCloudflare Pagesへのデプロイ方法をご紹介します。

※この手順は、作成したNext.jsプロジェクトのコードが、GitHub(またはGitLab)のリポジトリ(プライベートでも可)にプッシュ(保存)されていることを前提としています。


この記事で解説する手順

  1. Cloudflare PagesにNext.jsプロジェクトを追加する
  2. GitHubプライベートリポジトリへのアクセス許可を設定する
  3. Next.js用のビルド設定と注意点 (Node.jsバージョン, 互換フラグ)
  4. Cloudflare Pagesに独自ドメインを設定する (ネームサーバー変更)
  5. まとめ:Next.js + Cloudflare Pages + 独自ドメイン設定の流れ

Cloudflare PagesにNext.jsプロジェクトを追加する

まず最初のステップとして、Cloudflareの管理画面(ダッシュボード)で新しいPagesプロジェクトを作成し、デプロイしたいNext.jsプロジェクトのGitHubリポジトリと連携させます。

1. Cloudflareダッシュボードにログインし、左側のメニューから「Workers & Pages」セクションを選択します。(※CloudflareのUIは頻繁に更新されるため、メニュー名が若干異なる場合があります。類似の項目を探してください。)

CloudflareダッシュボードのWorkers & Pagesメニュー

2. 表示された画面の「概要」タブなどで、「アプリケーションを作成」ボタンを見つけてクリックします。

アプリケーションを作成ボタン

3. 「アプリケーションを作成」画面が開いたら、「Pages」タブが選択されていることを確認し、「Gitに接続」ボタンをクリックします。Cloudflare PagesはGitリポジトリと連携して自動デプロイを行うのが基本です。

Pagesタブを選択し、Gitに接続ボタンをクリック

4. GitHubまたはGitLabアカウントとの連携画面に進みます。初めて連携する場合は、「アカウントを追加」ボタンをクリックし、画面の指示に従ってGitHubアカウントを認証し、Cloudflareからのアクセスを許可します。

5. アカウント連携が完了すると、「リポジトリを選択」セクションに、連携したアカウントのGitリポジトリ一覧が表示されます。この中から、デプロイしたいNext.jsプロジェクトのリポジトリを選択してください。

GitHubリポジトリの選択画面

GitHubプライベートリポジトリへのアクセス許可を設定する

【ポイント】 もしデプロイしたいリポジトリがプライベート(非公開)設定の場合、上記のリポジトリリストに表示されないことがあります。これは、Cloudflare Pagesアプリケーションがそのプライベートリポジトリにアクセスする権限を持っていないためです。その場合は、以下の手順でGitHub側でアクセス許可を与える必要があります。

1. GitHubにログインし、右上のアイコンから「Settings」(設定)を開き、左側メニューの「Applications」(アプリケーション)を選択します。

GitHub設定画面のApplicationsメニュー

2. 「Installed GitHub Apps」タブを選択し、リストの中から「Cloudflare Pages」(または類似の名前)を見つけてクリックします。

Installed GitHub Apps内のCloudflare Pages

3. 「Repository access」(リポジトリへのアクセス)セクションまでスクロールします。ここで、「Only select repositories」(選択したリポジトリのみ)オプションを選択し、表示されるリポジトリリストの中から、Cloudflare PagesにデプロイしたいNext.jsプロジェクトのリポジトリにチェックを入れます。最後に「Save」ボタンを押して変更を保存します。

【セキュリティ推奨】もしここが「All repositories」(すべてのリポジトリ)になっていた場合でも、セキュリティの観点から、必要なリポジトリのみにアクセスを限定する「Only select repositories」に変更することをお勧めします。

Repository access設定でリポジトリを選択

4. このGitHub側の設定が完了したら、Cloudflare Pagesの画面に戻り、リポジトリ選択のリストを更新(またはページを再読み込み)すると、先ほどアクセスを許可したプライベートリポジトリが表示されるはずです。目的のリポジトリを選択し、「セットアップを開始」ボタンをクリックして次のステップに進みます。

リポジトリを選択してセットアップを開始

Next.js用のビルド設定と注意点 (Node.jsバージョン, 互換フラグ)

リポジトリを選択すると、次にビルド設定とデプロイに関する設定画面が表示されます。Cloudflare PagesがGitHubリポジトリからコードを取得し、どのようにビルドしてデプロイするかをここで指定します。

1. 「ビルド設定」セクションにある「フレームワーク プリセット」のドロップダウンメニューを開き、「Next.js」を選択します。Cloudflare Pagesは多くのフレームワークに対応しており、プリセットを選択すると、そのフレームワークに最適なビルドコマンドや設定が自動的に入力されるため便利です。

フレームワークプリセットでNext.jsを選択

2. プリセットを選択すると、「ビルドコマンド」(例: `npm run build` や `next build`)や「ビルド出力ディレクトリ」(例: `.next` や `.vercel/output/static`。Next.jsのバージョンや設定により異なる場合があります)が自動的に入力されます。通常はこのままで問題ありません。

自動設定されたビルドコマンドと出力ディレクトリ

【注意点1】Node.jsバージョンの指定が必要な場合

基本的な設定は以上ですが、このまま「保存してデプロイする」をクリックすると、ビルド時にエラーが発生することがあります。よくある原因の一つが、Cloudflare Pagesのビルド環境で使用されるNode.jsのバージョンが、あなたのNext.jsプロジェクトが必要とするバージョンよりも古い場合です。

ビルドログを確認し、以下のようなエラーメッセージが表示されていたら、Node.jsのバージョン指定が必要です。

Initializing build environment. Failed: error finding node version '>=18.0.0'
You are using Node.js 18.17.1.
For Next.js, Node.js version "^18.18.0 || ^19.8.0 || >= 20.0.0" is required.

(上記はエラーメッセージの例です。バージョン番号は異なる場合があります)

このエラーを解決するには、Cloudflare Pagesのプロジェクト設定で、使用するNode.jsのバージョンを明示的に指定します。

プロジェクトの「設定」>「環境変数」を開き、「ビルド環境変数」セクション(または「実稼働/プレビュー環境変数」の両方)で「変数を追加」をクリックし、以下のように設定します。

  • 変数名: NODE_VERSION
  • 値: あなたのNext.jsプロジェクトが必要とするNode.jsのバージョン番号を指定します(例: 18.18.020.0.0 など。エラーメッセージやNext.jsのドキュメント、ローカル開発環境に合わせてください)。package.json の `engines` フィールドで指定している場合は、それに合わせるのが良いでしょう。

環境変数でNODE_VERSIONを指定

環境変数を設定した後、再度デプロイ(ビルドログ画面などから「デプロイを再試行」)を行うと、指定したNode.jsバージョンが使用され、ビルドが正常に完了するはずです。

【注意点2】Node.js互換フラグの設定が必要な場合

ビルドは成功したものの、デプロイされたサイト(xxx.pages.dev)にアクセスすると、以下のようなエラー画面が表示される場合があります。

Node.JS Compatibility Errorの画面

これは「Node.JS Compatibility Error」と呼ばれるもので、Cloudflare Pagesの実行環境(Cloudflare Workers)でNext.jsアプリケーション(特にサーバーサイドの機能やAPIルートなど)を正しく動作させるために、Node.jsのAPI互換モードを有効にする必要があることを示しています。

このエラーを解決するには、以下の設定を行います。

プロジェクトの「設定」>「関数」>「互換性フラグ」セクション(または「互換性設定」など類似の項目)を見つけます。「フラグを設定」(または「追加」)ボタンをクリックし、「nodejs_compat」というフラグを追加して保存します。(通常、実稼働環境とプレビュー環境の両方に設定します)

互換性フラグにnodejs_compatを設定

このフラグを設定し、再度デプロイが完了した後、サイトにアクセスすると、Next.jsアプリケーションが正常に表示されるはずです。

Cloudflare Pagesに独自ドメインを設定する (ネームサーバー変更)

ビルドとデプロイが成功し、プロジェクト名.pages.dev のようなURLでサイトが表示されるようになったら、最後のステップとして、あなたが所有する独自ドメイン(例: your-cool-site.com)をこのCloudflare Pagesプロジェクトに割り当てます。

独自ドメインを設定する大まかな流れは以下の通りです。

  1. Cloudflare Pages側での設定: プロジェクトの設定画面で、使用したい独自ドメイン名を追加します。
  2. ネームサーバー情報の確認: Cloudflareから、あなたのドメインに設定すべきネームサーバーのアドレスが指示されます。
  3. ドメインレジストラ側での設定: あなたがドメインを取得したサービス(例: お名前ドットコム, Google Domains, Route 53など)の管理画面で、ドメインのネームサーバー設定を、Cloudflareから指示されたものに変更します。
  4. DNS反映待ち: ネームサーバー変更の情報がインターネット全体に行き渡る(DNSが伝播する)のを待ちます。通常は数分から数時間ですが、最大で48時間程度かかることもあります。
  5. Cloudflare Pages側での有効化: Cloudflareがネームサーバーの変更を確認できたら、ドメインが「アクティブ」状態になり、Pagesプロジェクトと独自ドメインが接続されます。

以下では、ドメインレジストラとして「お名前ドットコム」を使用した場合の具体的な手順例を示します。(基本的な流れは他のレジストラでも同様です)

ステップ1:Cloudflare Pagesにカスタムドメインを追加

1. Cloudflare Pagesのプロジェクト画面に戻り、「カスタムドメイン」タブを選択し、「カスタムドメインを設定」ボタンをクリックします。

カスタムドメインを設定ボタン

2. テキストボックスに、設定したいあなたの独自ドメイン名(例: your-cool-site.com)を入力し、「続行」をクリックします。

設定したいドメイン名を入力

3. もしまだそのドメインがCloudflareで管理されていない場合は、CloudflareにドメインのDNS管理を移管(または部分的に委任)するプロセスが開始されます。画面の指示に従い、「DNS転送を開始」や「サイトを追加」のようなボタンをクリックします。(※これはドメイン自体をCloudflareに移管するのではなく、あくまでDNSの管理権限をCloudflareに向ける設定です)

DNS転送を開始ボタン

4. ドメイン名を入力し、Cloudflareが既存のDNSレコードをスキャンするプロセスに進みます。「Continue」をクリックします。

DNSレコードのスキャン開始画面

5. Cloudflareのプラン選択画面が表示されます。独自ドメインの利用だけであれば、通常は画面下部にある「Freeプラン」(無料プラン)を選択して「Continue」をクリックすれば十分です。

Freeプランを選択

6. Cloudflareがスキャンした現在のDNSレコードが表示されます(もしあれば)。内容を確認し(分からなければそのままでもOK)、「Continue」をクリックします。

DNSレコードのスキャン結果画面

7. 確認のポップアップが出たら「Confirm」をクリックします。

確認ポップアップ

8. 【重要】 この画面で、あなたのドメインに設定すべきCloudflareのネームサーバーアドレス(通常は2つ)が表示されます。これらのアドレス(例: `ada.ns.cloudflare.com`, `ben.ns.cloudflare.com` など)を正確にコピーまたはメモしておきます。これが次のステップで必要になります。

表示されたCloudflareのネームサーバーアドレス

ステップ2:ドメインレジストラでネームサーバーを変更

次に、あなたのドメインを取得・管理しているサービス(ドメインレジストラ)の管理画面にログインし、ネームサーバーの設定を変更します。

1. ドメインレジストラ(この例では「お名前ドットコム」)のウェブサイトにアクセスし、ログインします。

2. ドメイン管理メニューの中から、対象ドメインの「ネームサーバー設定」や「DNS設定」といった項目を探し、編集画面を開きます。

3. レジストラの現在のネームサーバー設定(通常はレジストラ自身のネームサーバーが設定されています)を削除または変更し、先ほどCloudflareから指示された2つのネームサーバーアドレスを入力・保存します。(入力欄が複数ある場合は、指示された2つを入力し、残りは空欄にするか、レジストラの指示に従います)

お名前ドットコムでのネームサーバー変更画面例

【注意】DNSの伝播には時間がかかります!

ネームサーバーの変更設定がインターネット全体に行き渡る(DNSが伝播する)までには、時間がかかります。早ければ数分で反映されることもありますが、通常は数時間、場合によっては最大で48時間程度かかることもあります。この間は、独自ドメインでサイトにアクセスできなかったり、古い情報が表示されたりすることがありますので、焦らず気長に待ちましょう。Cloudflareのダッシュボードで定期的にステータスを確認するか、Cloudflareから届く確認メールを待ちます。

Cloudflareからのネームサーバー更新完了通知メール例

ステップ3:Cloudflare Pagesでドメインを有効化

ネームサーバーの変更がCloudflare側で無事に認識されると、Cloudflareダッシュボードのドメイン管理画面で、該当ドメインのステータスが「保留中」から「アクティブ」に変わります。(今回は比較的早く、5分程度で反映されました)。

Cloudflareでドメインがアクティブになった状態

ドメインがアクティブになったら、いよいよCloudflare Pagesプロジェクトと独自ドメインを正式に接続します。

1. 再度、Cloudflare Pagesのプロジェクト設定画面に戻り、「カスタムドメイン」タブを開きます。

2. 「カスタムドメインを設定」ボタンをクリックし、もう一度あなたの独自ドメイン名を入力して「続行」します。

3. 今度はCloudflareがドメインを認識しているため、「ドメインをアクティベート」や「DNSレコードを確認」といった画面が表示されるはずです。Cloudflare Pagesが必要とするDNSレコード(通常はCNAMEレコード)が自動で設定(または提案)されます。内容を確認し、「ドメインをアクティベート」ボタンをクリックします。

カスタムドメインのアクティベート画面

4. ステータスが「初期化中」や「認証中」などと表示され、しばらく待つと最終的に「アクティブ」に変わります。これで設定は完了です!

設定が完了すると、あなたの独自ドメイン(例: https://your-cool-site.com)にアクセスすると、Cloudflare PagesにデプロイされたNext.jsサイトが表示されるようになります。(SSL証明書もCloudflareが自動で発行・管理してくれます)

カスタムドメインがアクティブになった状態

まとめ:Next.js + Cloudflare Pages + 独自ドメイン設定の流れ

以上が、Next.jsサイトをCloudflare Pagesにデプロイし、独自ドメインを設定するまでの一連の手順でした。全体の流れをもう一度おさらいしましょう。

  1. GitHub準備: Next.jsプロジェクトをGitHubリポジトリにプッシュする。
  2. Cloudflare Pages連携: Cloudflare Pagesでプロジェクトを作成し、GitHubリポジトリと連携する。(プライベートリポジトリの場合はGitHub側でアクセス許可設定を行う)
  3. ビルド設定とエラー対応:
    • フレームワークプリセットで「Next.js」を選択。
    • 必要に応じて、環境変数 `NODE_VERSION` でNode.jsバージョンを指定する。
    • 必要に応じて、互換性フラグ `nodejs_compat` を設定する。
  4. 独自ドメイン設定:
    • Cloudflare Pagesにカスタムドメインを追加し、指示されたCloudflareのネームサーバーを確認する。
    • ドメインレジストラの管理画面で、ネームサーバーをCloudflareのものに変更する。
    • DNSの伝播を待ち、Cloudflareでドメインがアクティブになったら、Pagesプロジェクトでドメインを有効化する。

ビルド時のNode.js関連のエラーや、DNS設定の反映待ち時間など、いくつか注意すべき点はありますが、手順自体は比較的シンプルに進められます。Cloudflare Pagesは、高速な配信、強力なセキュリティ、そして手厚い無料枠を提供しており、Next.jsアプリケーションのホスティング先として非常に魅力的な選択肢です。ぜひこのガイドを参考に、デプロイに挑戦してみてください。

(※この記事では基本的なデプロイ手順を解説しました。実際のアプリケーションの要件によっては、環境変数の設定、カスタムビルドコマンド、リダイレクトルールなど、さらに詳細な設定が必要になる場合があります。その際はCloudflare Pagesの公式ドキュメント等も合わせて参照してください。)

Google Analytics Data APIで静的ブログサイトに『人気記事一覧』を実装する方法【Next.js / Gatsby.js】

JAMstack構成(例: Next.jsGatsby.js + ヘッドレスCMS)は、フロントエンドとバックエンドを分離することで、使用する技術選択の自由度が高く、パフォーマンスやセキュリティ面でのメリットも大きいモダンなWebサイト構築のアプローチです。

しかし、その一方で、従来のWordPressサイトなどではプラグインで簡単に実現できた機能、例えば「人気記事一覧(ランキング)」などを実装しようとすると、少し工夫が必要になります。

WordPressで人気記事一覧が容易なのは、記事データとページ閲覧数(PV数)が同じデータベース内に記録されており、動的にデータを取得・集計してランキング表示できるためです。しかし、JAMstack構成の多くは、ビルド時に静的なHTMLファイルを生成するため、リアルタイムで変動する閲覧数を基にした動的なランキング表示は得意ではありません。また、フロントエンドとバックエンドが分離しているため、アクセス数を記録・参照する共通の仕組みが標準では備わっていません。

そこで活用したいのが、多くのWebサイトで導入されているアクセス解析ツール「Google Analytics」です。Google Analyticsに蓄積されたページごとの閲覧数データを、そのAPI(Google Analytics Data API (GA4 Data API))経由で取得し、ビルドプロセスに組み込むことで、静的サイトでありながら「人気記事一覧」を表示することが可能になります。

この記事では、Google Analytics Data API (GA4) を利用して人気記事データを取得し、Next.jsGatsby.jsといった静的サイトジェネレーター環境で「人気記事一覧」を実装するための具体的な手順と考え方を紹介します。


この記事の内容

  1. 静的サイト(ヘッドレスCMS)で人気記事一覧を実装する難しさ
  2. Google Analytics Data API (GA4) の有効化と基本準備
  3. サービスアカウントの利用とセキュリティ上の注意点
  4. Node.jsによる人気記事データ取得スクリプトの実装例
  5. ビルド時にJSONデータを活用し、静的サイトに組み込む方法
  6. まとめ:静的サイトでもAPI連携で人気記事一覧は実現できる!

静的サイト(ヘッドレスCMS)で人気記事一覧を実装する難しさ

JAMstack構成とGoogle Analytics連携のイメージ図

前述の通り、従来の動的なCMS(WordPressなど)では、データベースへのアクセスを通じてリアルタイムにPV数を集計し、人気記事ランキングを表示することが一般的でした。

しかし、JAMstack構成の静的サイトでは、サイトのコンテンツはビルド時に生成され、サーバー側での動的なデータ処理は基本的には行いません。そのため、サイトが表示されるたびにPV数をリアルタイムで集計してランキングを変動させる、といった実装は困難です。

そこで、外部サービスであるGoogle Analyticsのデータを活用するアプローチが有効になります。基本的な流れは以下のようになります。

  1. ビルド前にデータを取得: スクリプトを実行し、Google Analytics Data APIを通じて、指定期間のページ別閲覧数を取得します。(例: 直近30日間のPV数トップ10記事)
  2. データを整形・保存: 取得したランキングデータを扱いやすい形式(例: JSONファイル)に整形して、プロジェクト内に保存します。
  3. ビルド時にデータを参照: Next.jsやGatsby.jsなどの静的サイトジェネレーターがサイトをビルドする際に、保存されたJSONファイルを読み込みます。
  4. 静的ページに埋め込み: 読み込んだランキングデータ(記事タイトル、URL、PV数など)を使って、「人気記事一覧」のコンポーネントやリストを生成し、静的なHTMLページ内に埋め込みます。

この方法であれば、サイトをデプロイ(ビルド)するたびに最新のランキング情報が反映され、かつサイト自体は高速な静的ファイルとして提供できるため、パフォーマンスを損なうこともありません。


Google Analytics Data API (GA4) の有効化と基本準備

まず、Google Analyticsのデータをプログラムから取得するために、APIの有効化と必要な情報を準備します。

Google Cloud PlatformでGoogle Analytics Data APIを有効化する画面

  1. Google Cloud Platform (GCP) でAPIを有効化:
    • Google Cloud Console (https://console.cloud.google.com/) にアクセスし、プロジェクトを選択または新規作成します。
    • 「APIとサービス」>「ライブラリ」で「Google Analytics Data API」を検索し、有効にします。
  2. サービスアカウントを作成し、キーをダウンロード:
    • GCPの「APIとサービス」>「認証情報」で、「認証情報を作成」>「サービスアカウント」を選択し、新しいサービスアカウントを作成します。(名前は任意、ロールは不要な場合が多い)
    • 作成したサービスアカウントを選択し、「キー」タブ>「鍵を追加」>「新しい鍵を作成」で「JSON」形式のキーを作成・ダウンロードします。このJSONファイルは後でスクリプトから使用します。大切に保管してください。
  3. サービスアカウントにGA4プロパティへのアクセス権を付与:
    • Google Analytics (https://analytics.google.com/) にアクセスし、対象のGA4プロパティの「管理」(歯車アイコン)を開きます。
    • 「プロパティ設定」>「プロパティのアクセス管理」で、「+」ボタン >「ユーザーを追加」を選択します。
    • 先ほど作成したサービスアカウントのメールアドレス(GCPの認証情報画面で確認できます)を入力し、「役割」として少なくとも「閲覧者」の権限を付与して追加します。
  4. GA4プロパティIDを控える:
    • Google Analyticsの「管理」>「プロパティ設定」で、「プロパティ ID」(数字のみのID)を確認し、控えておきます。これもスクリプトで使用します。

    Google Analytics 4のプロパティID確認画面

これらの準備(特にGCPやGA4の操作)については、Googleの公式ドキュメントや他の解説記事も参考に、ご自身の環境に合わせて進めてください。


サービスアカウントの利用とセキュリティ上の注意点

Google Cloud Platformでのサービスアカウントキー管理画面

Google Analytics Data APIのように、Googleのサービスにプログラムからアクセスする際には、通常「サービスアカウント」という特殊なアカウントを使用します。これは、個人のGoogleアカウントではなく、アプリケーションやスクリプトが自身を認証するためのものです。

前述のステップで作成しダウンロードしたサービスアカウントキー(JSONファイル)には、そのサービスアカウントとしてAPIにアクセスするための秘密の情報が含まれています。そのため、このキーファイルの取り扱いには細心の注意が必要です。

  • 絶対に公開しない: JSONキーファイルは、Gitリポジトリ(特にPublicリポジトリ)に絶対にコミットしないでください。誤って公開してしまうと、第三者に不正利用される危険性があります。.gitignoreファイルにキーファイル名を追加し、Gitの管理対象から除外しましょう。
  • 安全な場所に保管: ローカル開発環境ではプロジェクトルートなどに置くこともありますが、本番環境(デプロイ先)では、環境変数やシークレット管理機能を使って安全にキー情報を渡すのが一般的です。(後述のスクリプト例参照)
  • 権限は最小限に: GA4プロパティでサービスアカウントに付与する権限は、データ取得に必要な最低限の「閲覧者」権限にしておきましょう。

Node.jsによる人気記事データ取得スクリプトの実装例

ここでは、準備したサービスアカウントキーとGA4プロパティIDを使って、実際に人気記事データを取得し、JSONファイルとして保存するNode.jsスクリプトの例を示します。

【準備】

  1. プロジェクトのルートディレクトリにscriptsフォルダを作成し、その中に以下のスクリプトをfetch-popular-posts.jsなどの名前で保存します。
  2. プロジェクトのルートディレクトリに、GCPからダウンロードしたサービスアカウントキーのJSONファイルをservice-account.json(または任意の名前)として配置します。
  3. プロジェクトのルートディレクトリに.envファイルを作成し、以下の形式でGA4プロパティIDを記述します(?????????の部分は実際のIDに置き換えてください)。
    GA4_PROPERTY_ID=?????????
  4. 【重要】service-account.json.envファイルは機密情報を含むため、必ず.gitignoreファイルに追加して、Gitリポジトリに含まれないようにします。
    # .gitignore ファイルの例
    service-account.json
    .env
        
  5. 必要なnpmパッケージをインストールします。ターミナルで以下のコマンドを実行してください。
    npm install @google-analytics/data dotenv

    (または yarn add @google-analytics/data dotenv

【スクリプト例: scripts/fetch-popular-posts.js

// .envファイルから環境変数を読み込む
require("dotenv").config();
// Google Analytics Data APIクライアントライブラリ
const { BetaAnalyticsDataClient } = require("@google-analytics/data");
// Node.jsのファイルシステムとパス操作モジュール
const fs = require("fs");
const path = require("path");

// 非同期関数として人気記事取得処理を定義
async function fetchPopularPosts() {
  let credentials;

  // --- 認証情報の設定 ---
  // 本番環境用に環境変数 GA_CREDENTIALS_JSON があればそれを使う (推奨)
  if (process.env.GA_CREDENTIALS_JSON) {
    try {
      credentials = JSON.parse(process.env.GA_CREDENTIALS_JSON);
    } catch (e) {
      console.error("Failed to parse GA_CREDENTIALS_JSON environment variable.", e);
      process.exit(1);
    }
  }
  // 環境変数がなければ、ローカルの service-account.json を読み込む
  else {
    const keyFilePath = path.resolve(__dirname, "../service-account.json");
    if (fs.existsSync(keyFilePath)) {
      credentials = JSON.parse(fs.readFileSync(keyFilePath, "utf8"));
    } else {
      console.error(`Service account key file not found at ${keyFilePath}. Or set GA_CREDENTIALS_JSON env var.`);
      process.exit(1);
    }
  }

  // --- GA4 Data API クライアントの初期化 ---
  const analyticsDataClient = new BetaAnalyticsDataClient({
    credentials: {
      client_email: credentials.client_email,
      private_key: credentials.private_key,
    },
  });

  // --- GA4 プロパティIDの取得 ---
  const propertyId = process.env.GA4_PROPERTY_ID;
  if (!propertyId) {
    throw new Error("GA4_PROPERTY_ID is not set in environment variables.");
  }

  // --- APIリクエストの実行 ---
  try {
    const [response] = await analyticsDataClient.runReport({
      // プロパティIDを指定
      property: `properties/${propertyId}`,
      // データ取得期間 (過去30日間)
      dateRanges: [{ startDate: "30daysAgo", endDate: "today" }],
      // 取得するディメンション (ページのパス, ページのタイトル)
      dimensions: [{ name: "pagePath" }, { name: "pageTitle" }],
      // 取得するメトリクス (表示回数)
      metrics: [{ name: "screenPageViews" }], // GA4では "ga:pageviews" ではなく "screenPageViews"
      // 並び順 (表示回数の降順 = 多い順)
      orderBys: [{ metric: { metricName: "screenPageViews" }, desc: true }],
      // 取得件数 (上位10件)
      limit: 10,
      // ディメンションフィルタ (ブログ記事パス '/blog/' で始まるページのみ対象とする例)
      dimensionFilter: {
        filter: {
          fieldName: "pagePath",
          stringFilter: {
            matchType: "PARTIAL_REGEXP", // 正規表現に部分一致
            value: "^/blog/", // /blog/ で始まるパス
          },
        },
      },
    });

    // --- 結果の整形 ---
    const popularPosts = response.rows.map((row) => ({
      pagePath: row.dimensionValues[0].value,
      pageTitle: row.dimensionValues[1].value,
      pageViews: parseInt(row.metricValues[0].value, 10), // 閲覧数を整数に変換
    }));

    // --- JSONファイルへの書き出し ---
    // プロジェクトルートに data フォルダがなければ作成
    const dataDir = path.resolve(__dirname, "../data");
    if (!fs.existsSync(dataDir)) {
      fs.mkdirSync(dataDir);
    }
    // dataフォルダ内に popular-posts.json として保存
    fs.writeFileSync(
      path.join(dataDir, "popular-posts.json"),
      JSON.stringify(popularPosts, null, 2) // 読みやすいように整形して出力
    );
    console.log("Successfully fetched popular posts and saved to data/popular-posts.json");

  } catch (error) {
      console.error("Error fetching Google Analytics data:", error);
      process.exit(1); // エラー発生時はプロセスを終了
  }
}

// 関数を実行
fetchPopularPosts();

スクリプトのポイント:

  • 認証情報: 環境変数 `GA_CREDENTIALS_JSON` があればそれを優先的に使用し、なければローカルの `service-account.json` を読み込みます。これにより、ローカル開発と本番環境(Cloudflare Pagesなど)で認証情報を安全に扱うことができます。(本番環境では、環境変数にJSONキーの内容全体を設定するのが一般的です)
  • APIリクエスト: `runReport` メソッドでGA4にリクエストを送ります。
    • dateRanges: データ取得期間を指定します(例: “30daysAgo”~”today”)。
    • dimensions: 取得したい情報の種類(ページのパス、タイトルなど)を指定します。
    • metrics: 集計したい指標(表示回数 `screenPageViews` など)を指定します。
    • orderBys: 並び順を指定します(例: 表示回数の多い順)。
    • limit: 取得する最大件数を指定します。
    • dimensionFilter: 【重要】 取得するページを絞り込むためのフィルターです。この例では「ページのパス (`pagePath`) が正規表現 ^/blog/ に一致するもの」だけを取得しています。これにより、ブログ記事以外のページ(トップページ `/` など)がランキングに含まれるのを防ぎます。この `value` は、あなたのブログ記事のURL構造に合わせて必ず変更してください。
  • 結果の整形と保存: APIからの応答データを扱いやすいJSON形式(パス、タイトル、閲覧数のオブジェクト配列)に変換し、data/popular-posts.json ファイルに書き出します。

このスクリプトをターミナルで node scripts/fetch-popular-posts.js と実行すると、`data` フォルダ(なければ作成される)に人気記事のデータがJSONファイルとして保存されます。


ビルド時にJSONデータを活用し、静的サイトに組み込む方法

人気記事データを含むJSONファイルが用意できたら、あとは静的サイトジェネレーター(Next.jsやGatsby.js)のビルドプロセスでこのJSONファイルを読み込み、ページやコンポーネントにデータを渡して表示するだけです。

しかし、ここで重要なのは「サイトをビルド(デプロイ)するたびに、このJSONファイルが最新の情報に更新されるようにする」ことです。そうしないと、ランキングが古いままになってしまいます。

これを実現するには、通常、プロジェクトの package.json ファイル内の scripts セクションを編集し、ビルドコマンドの実行前にデータ取得スクリプトが実行されるように設定します。

package.json の設定例 (Gatsby.jsの場合)】

{
  "scripts": {
    // データ取得スクリプトを実行するコマンドを定義
    "fetch-data": "node scripts/fetch-popular-posts.js",
    // 開発サーバー起動時にもデータを取得する場合 (任意)
    "develop": "npm run fetch-data && gatsby develop",
    // 本番ビルド時に必ずデータ取得を実行するように設定
    "build": "npm run fetch-data && gatsby build",
    // startコマンドも同様に(開発用サーバー起動など)
    "start": "npm run develop",
    // 他にも test や serve など...
  }
}

この例では、

  1. fetch-data という名前でデータ取得スクリプトを実行するコマンドを定義しています。
  2. build コマンド(本番用ビルド)の実行時に、まず npm run fetch-data を実行し、その後に gatsby build が実行されるように設定しています。(&& はコマンドを順番に実行する指定子)
  3. 同様に、開発サーバー起動時 (develop, start) にもデータを取得するようにしています(開発中も最新データで確認したい場合)。Next.jsの場合は next devnext build の前に npm run fetch-data && を追加します。

このように設定しておくことで、npm run build コマンドを実行(またはVercelやCloudflare Pagesなどのホスティングサービスで自動ビルドが実行される際)に、

  1. まず fetch-popular-posts.js が実行され、最新の人気記事データが data/popular-posts.json に保存されます。
  2. 次に、Gatsby (またはNext.js) のビルドプロセスが開始され、その中で data/popular-posts.json ファイルを読み込み、人気記事一覧を含む静的HTMLページが生成されます。

この「ビルド時データフェッチ」のアプローチにより、サイト訪問者は常に(ビルド時点での)最新の人気記事一覧を高速な静的ページとして閲覧でき、サーバーへの負荷やAPIの実行時呼び出しを気にする必要がなくなります。これはパフォーマンスとセキュリティの観点からもJAMstack構成の大きなメリットです。

あとは、各フレームワークの方法に従って、ビルド時にJSONデータを読み込み、Reactコンポーネントなどに渡して表示する部分を実装してください。(例: Gatsbyではgatsby-node.jsでJSONを読み込みGraphQLデータレイヤーに追加、Next.jsではgetStaticProps内でfs.readFileを使ってJSONを読み込むなど)


まとめ:静的サイトでもAPI連携で人気記事一覧は実現できる!

JAMstackヘッドレスCMSを採用した静的サイト環境では、WordPressのような従来の動的CMSとは異なり、「人気記事一覧」をリアルタイムで表示することは困難です。

しかし、この記事で解説したように、Google Analytics Data API (GA4) を活用し、サイトのビルドプロセス前にアクセスデータを取得・整形してJSONファイルなどの形で保存し、それをビルド時に静的ページに埋め込むというアプローチを取ることで、静的サイトのメリット(高速表示、高セキュリティ、スケーラビリティ)を維持しつつ、最新の人気記事ランキングを表示することが可能になります。

この方法は、特定のCMSやフロントエンドフレームワークに強く依存しないため、Next.jsGatsby.jsだけでなく、様々なJAMstack構成に応用できます。サービスアカウントキーの安全な管理や、APIリクエストのフィルター設定など、いくつか注意点はありますが、一度仕組みを構築すれば、自動でランキングが更新される便利な機能を実現できます。

ぜひ、ご自身の静的ブログサイトやWebサイトの構成に合わせて、この手法を参考に「人気記事一覧」の実装に挑戦してみてください。