Gatsbyで作ったサイトに人気記事のランキングを実装する【前編】

スタッフブログ

こんにちは、マークアップエンジニアの松本です。

ブログを読んでいると人気記事やよく読まれている記事のランキングが目に入ると思います。
そんな人気記事のランキングをGatsbyで作ったサイトに実装することになりました。

今回は単純にページビュー数(以降、PV数と称します)が多い記事を人気記事と定義してランキングを作ります。
PV数はGoogle Analytics 4(以降、GA4と称します)で計測できている状態だったので、GA4のデータを使えると良さそうです。
どうすればGA4のデータを使えるのかと調べたところ Google Analytics Data API というAPIを見つけました。

ということで今回はGoogle Analytics Data APIを使って、Gatsbyで作ったサイトに人気記事のリストを実装していきたいと思います。

実装までの流れ

実装までの大まかな流れは以下のようになります。

  1. Google Analytics Data APIを使用できる状態にする
  2. GatsbyでGoogle Analytics Data APIを使用してGA4のデータを取得する
  3. 取得したデータをGatsbyノードとして保存する
  4. GraphQLでデータを取得してページ上に表示させる

今回は「2. GatsbyでGoogle Analytics Data APIを使用してGA4のデータを取得する」までを書きます。

前提条件

Gatsbyで作ったサイトにGA4が導入されており、各ページのPV数が取得できているという前提のもと進めます。
※ユニバーサルアナリティクス(UA)には対応しておりませんのでご注意ください。

Google Analytics Data APIを使用できる状態にする

Google Analytics Data APIを使用するためには、

  • Google Analytics Data APIの有効化
  • GA4プロパティへのアクセス権限を付与
  • 認証情報の取得

の3つの工程が必要になります。

Google Analytics Data APIの有効化

まず有効化から行います。
今回使用するGoogle Analytics Data APIはGoogle Cloudサービスの一つなので、Google Cloud Platformで有効化の作業を行います。

Googleアカウントにログインした状態でGoogle Cloud Platformにアクセスします。
初回利用時は規約への同意が求められるので、利用規約欄にチェックを入れて「同意して続行」を押してください。

プロジェクトを作成する

Google Cloudサービスを使用するためには、プロジェクトを作成する必要があります。

  • プロジェクトとは?
    すべてのGoogle Cloudサービスの作成、有効化、使用の基礎となるものです。プロジェクトがないとGoogle Cloudサービスを使うことができません。
    ここでは作業フォルダのようなものだと捉えておいてください。
    詳しくはドキュメントをご覧ください。

ヘッダーのタイトル「Google Cloud」の横にあるドロップダウンメニューをクリックし「新しいプロジェクト」からプロジェクトを作成します。

プロジェクトの作成時にログインしているアカウントが一般ユーザー向けのアカウントの場合と、Google WorkspaceアカウントまたはCloud Identityアカウントの場合とで設定項目が異なるため、それぞれ説明します。

● 一般ユーザー向けアカウントでログインしている場合


プロジェクト名を入力します。プロジェクト名は後で自由に変更できます。
プロジェクトIDは自動で生成されますが、「編集」から自分で設定することもできます。IDは後から変更できません。
場所は特に設定する必要はないので「組織なし」のまま進めます。

  • 場所とは?
    組織またはフォルダがある場合、それらを参照しプロジェクトがどの組織またはフォルダに属するかを設定できます。
    詳しくはドキュメントをご覧ください。

「作成」を押したらプロジェクトが作成されます。

● Google WorkspaceアカウントまたはCloud Identityアカウントでログインしている場合


プロジェクト名を入力します。プロジェクト名は後で自由に変更できます。
プロジェクトIDは自動で生成されますが、「編集」から自分で設定することもできます。IDは後から変更できません。
組織を設定します。デフォルトで組織が選択されている状態なので、問題なければそのまま進みます。

  • 組織とは?
    複数のGoogle Cloudプロジェクトをまとめて管理するための親フォルダのようなものだと捉えておいてください。
    Google WorkspaceアカウントまたはCloud Identityアカウントを持っている場合、プロジェクト作成時に組織が自動的に作成されます。
    詳しくはドキュメントをご覧ください。

場所を設定します。デフォルトで組織が選択されている状態なので、問題なければそのまま進みます。
※組織や場所の設定について、会社等でGoogle Cloudプロジェクト管理の決まりがある場合はそちらに従ってください。

「作成」を押したらプロジェクトが作成されます。

Google Analytics Data APIを有効にする

ハンバーガーメニューの「APIとサービス」の項目から「ライブラリ」を選択してAPIライブラリページに行きます。
検索バーが出てくるので「Google Analytics Data API」と検索します。


「Google Analytics Data API」を選択し「有効にする」を押します。

これでGoogle Analytics Data APIが有効化されました。

GA4プロパティへのアクセス権限を付与

次に、アクセス権の付与を行います。

サービスアカウントの作成

GA4プロパティへのアクセス権限を付与するためには、サービスアカウントが必要になります。

  • サービスアカウントとは?
    仮想ユーザーのようなものです。このサービスアカウントに権限を付与し、データを閲覧できるようにします。
    詳しくはドキュメントをご覧ください。

ハンバーガーメニューの「IAMと管理」の項目から「サービスアカウント」を選択してサービスアカウントページに行きます。

「サービスアカウントを作成」を選択し、サービスアカウントの作成に進みます。


サービスアカウント名を入力します。名前は後から自由に変更できます。
サービスアカウントIDは自動で生成されますが、自分で設定することもできます。IDは後から変更できません。
アクセスの制御について今回は特に必要ないので省略します。アクセスの制御は後から設定できます。
「完了」を押したらサービスアカウントが作成されます。


Google Analyticsとの連携で必要になるので、サービスアカウントのメールアドレスを控えておいてください。

権限を付与する

Google Analyticsにアクセスし、サービスアカウントにアクセス権限を付与する作業を行います。

左下の歯車マークからプロパティの「設定アシスタント」を開き、「ユーザーを管理」を選択します。
※ユーザーを管理するには管理者権限が必要です。

プラスマークを押し「ユーザーを追加」を選択します。

メールアドレス欄に先ほど控えておいたサービスアカウントのメールアドレスを入力します。
権限はデフォルト(閲覧者)のままでOKです。データの制限は特に設定する必要はありません。
「追加」を押したらユーザの追加は完了です。

これでサービスアカウントにGoogle Analyticsへのアクセス権限が付与されました。
次は認証情報の取得をしていきます。

認証情報の取得

Google Cloud Platformに戻り、ハンバーガーメニューの「IAMと管理」の項目から「サービスアカウント」を選択してサービスアカウントページに行きます。
先ほど作成したサービスアカウントのメールアドレスをクリックします。

「キー」タブを選択し、「鍵を追加」から「新しい鍵を作成」を選択します。

JSONを選択した状態で「作成」を押すと、認証情報のJSONファイルがパソコンにダウンロードされます。

ダウンロードしたJSONファイルはプロジェクトフォルダ内に移動させておきます。
認証情報が書かれているので、外部からアクセスされない安全な場所に置いてください。
ファイル名が長いので使いやすいファイル名に変更することをお勧めします。

GatsbyでGoogle Analytics Data APIを使用してGA4のデータを取得する

Google Analytics Data APIを使用できる状態になったので、Gatsbyでデータを取得してみたいと思います。

まずライブラリをインストールします。

npm install @google-analytics/data

APIのリファレンスを参考にデータの取得をしていきます。
gatsby-node.jsに以下のコードを書き、データをログに出力して取得できているか確認します。
gatsby-node.jsがない場合はプロジェクトフォルダ直下にgatsby-node.jsを作成してください。

// ライブラリをインポート
const {BetaAnalyticsDataClient} = require('@google-analytics/data');

// オプションを指定して、BetaAnalyticsDataClientのインスタンスを作成
const credentialsFilePath = "./src/files/apikey.json"; /* 認証情報(JSONファイル)の相対パス */
const analyticsDataClient = new BetaAnalyticsDataClient({ keyFilename: credentialsFilePath });

const propertyId = 'GA4-PROPERTY-ID'; /* GA4のプロパティID */

async function runReportFunc() {
    // 取得したレポートデータを response に格納
    const [response] = await analyticsDataClient.runReport({
        property: `properties/${propertyId}`,
        dateRanges: [
            {
                startDate: "30daysAgo",
                endDate: "today",
            },
        ],
        dimensions: [
            {
                name: "pagePath",
            },
        ],
        dimensionFilter: {
            filter: {
                fieldName: "pagePath",
                stringFilter: {
                    matchType: "BEGINS_WITH",
                    value: "/Blog/", /* ブログページに共通するパス */
                },
            },
        },
        metrics: [
            {
                name: "screenPageViews",
            },
        ],
        orderBys: [
            {
                desc: true,
                metric: {
                    metricName: "screenPageViews",
                },
            },
        ],
    });

    console.log(response);

    console.log("Report result:");
    response.rows.forEach(row => {
        console.log(row.dimensionValues[0], row.metricValues[0]);
    });
}

runReportFunc();

コードを上から順に説明していきます。

const {BetaAnalyticsDataClient} = require('@google-analytics/data');

const credentialsFilePath = "./src/files/apikey.json"; /* 認証情報(JSONファイル)の相対パス */
const analyticsDataClient = new BetaAnalyticsDataClient({ keyFilename: credentialsFilePath });

ライブラリをインポートし、BetaAnalyticsDataClientを読み込みます。
オプションkeyFilenameに認証情報のJSONファイルパスを指定して、BetaAnalyticsDataClientのインスタンスanalyticsDataClientを作成します。

const propertyId = 'GA4-PROPERTY-ID'; /* GA4のプロパティID */

GA4のプロパティIDを変数propertyIdに格納しています。プロパティIDは数字のみで構成されているものです。

  • プロパティIDを確認・コピーする方法

    Google Analyticsにアクセスし、左下の歯車マークからプロパティの「プロパティ設定」を開くとプロパティIDが書いてあります。プロパティIDの右にあるマークを押すとプロパティIDがコピーできます。
const [response] = await analyticsDataClient.runReport({
    property: `properties/${propertyId}`,
    dateRanges: [
        {
            startDate: "30daysAgo",
            endDate: "today",
        },
    ],
    dimensions: [
        {
            name: "pagePath",
        },
    ],
    dimensionFilter: {
        filter: {
            fieldName: "pagePath",
            stringFilter: {
                matchType: "BEGINS_WITH",
                value: "/Blog/", /* ブログページに共通するパス */
            },
        },
    },
    metrics: [
        {
            name: "screenPageViews",
        },
    ],
    orderBys: [
        {
            desc: true,
            metric: {
                metricName: "screenPageViews",
            },
        },
    ],
});

analyticsDataClientのrunReportメソッドでAPIにリクエストを飛ばし、帰ってきたデータをresponseに格納しています。
runReportメソッドの引数にリクエストボディを渡して、カスタマイズされたレポートデータを取得します。
リクエストボディの中身についてはドキュメントをご覧ください。

今回リクエストボディに指定した内容を簡単に説明すると、以下のようになります。

  • dateRangesstartDate: "30daysAgo"endDate: "today"を指定して、直近の30日間のデータを取得する
  • dimensionspagePathを、metricsscreenPageViewsを指定して、ページパスとそのページのPV数を取得する
  • stringFilterpagePath/Blog/で始まるものだけにフィルタリングし、ブログページのデータのみを取得する
  • orderBysscreenPageViews(PV数)の多い順に並び替える

この指定に基づいてカスタマイズされたレポートデータを取得します。

  console.log(response);

responseをログに出力して確認します。

結果:

{
  dimensionHeaders: [ { name: 'pagePath' } ],
  metricHeaders: [ { name: 'screenPageViews', type: 'TYPE_INTEGER' } ],
  rows: [
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] },
    { dimensionValues: [Array], metricValues: [Array] }
  ],
  totals: [],
  maximums: [],
  minimums: [],
  rowCount: 14,
  metadata: {
    dataLossFromOtherRow: false,
    currencyCode: 'JPY',
    _currencyCode: 'currencyCode',
    timeZone: 'Asia/Tokyo',
    _timeZone: 'timeZone'
  },
  propertyQuota: null,
  kind: 'analyticsData#runReport'
}

responserowsに欲しいデータが入っているので、rowsの中身を1行ずつログに出力していきます。

console.log("Report result:");
response.rows.forEach(row => {
    console.log(row.dimensionValues[0], row.metricValues[0]);
});

結果:

Report result:
{ value: '/blog/', oneValue: 'value' } { value: '123', oneValue: 'value' }
{ value: '/blog/995/', oneValue: 'value' } { value: '34', oneValue: 'value' }
{ value: '/blog/949/', oneValue: 'value' } { value: '32', oneValue: 'value' }
{ value: '/blog/1050/', oneValue: 'value' } { value: '27', oneValue: 'value' }
{ value: '/blog/510/', oneValue: 'value' } { value: '23', oneValue: 'value' }
{ value: '/blog/471/', oneValue: 'value' } { value: '17', oneValue: 'value' }
{ value: '/blog/445/', oneValue: 'value' } { value: '11', oneValue: 'value' }
{ value: '/blog/520/', oneValue: 'value' } { value: '10', oneValue: 'value' }
{ value: '/blog/541/', oneValue: 'value' } { value: '10', oneValue: 'value' }
{ value: '/blog/1986/', oneValue: 'value' } { value: '7', oneValue: 'value' }
{ value: '/blog/479/', oneValue: 'value' } { value: '7', oneValue: 'value' }
{ value: '/blog/498/', oneValue: 'value' } { value: '7', oneValue: 'value' }
{ value: '/blog/970/', oneValue: 'value' } { value: '6', oneValue: 'value' }

オブジェクトのvalueにページパスとPV数が表示されていることが確認できます。
これでGA4のデータをGatsbyで取得できるようになりました。

今回はここまでです。
次回はこれらのデータをGatsbyノードとして保存するところから、ランキングをページ上に表示させるまでを書いていきます。