Programming / Travel / Liquor

Nuxtで構築したブログでGoogle Analytics APIを使って「人気の記事一覧」を実装する

Nuxt ブログ構築 Google APIs

ブログサービス等でよくある「人気の記事一覧」をJAMStack構成のブログで、Google AnalyticsのAPIを使って実装する方法を紹介します。

人気の記事一覧

人気の記事の定義

まず、人気の記事一覧について。

例えば、WordPressやはてなブログなどでサイドバー等で人気の記事Top5ぐらいまでのリンクが並んでいるものがありますよね。そのようなものを今回実装したいと思います。

通常のブログサービスであれば、基本的には設定で有効にするだけでブログ画面に表示できると思いますが、本ブログのようなJAMStack構成で構築したブログは、本質的にはブログサービスではないので、当然設定で有効にするとかは出来ません。

ということで、自前で実装が必要になります。

人気の記事の定義については色々考えられるかと思いますが、今回はシンプルに記事のPVにしたいと思います。つまり、PV上位の記事ページを「人気の記事」としてブログ画面にその記事のリンクを表示することを考えます。

記事のPVを取得する方法

ということで「記事ページのPVを取得して上位順で抽出すれば良い」ということなのですが、残念ながらJAMStack構成で構築した本ブログ(繰り返しになりますが)はPVを取得していません。。

取得していないというよりも、そもそもDBを使用しておらず、Nuxtで生成した静的ページを表示しているだけなので、そういったデータを保持する方法もありません。

そこでどうするかというと、Google Analyticsの統計データを利用します。

本ブログではGoogle Analyticsを利用しており、ページごとのPVもデータとして存在します。Google AnalyticsはAPIが用意されており、APIで統計データを取得することが出来ます。

このAPIを使用して記事ページのうち、PV上位のページを取得して人気の記事一覧に利用したいと思います。

NuxtでGoogle Analytics API

GCPアカウント・プロジェクト作成

Google AnalyticsのAPIに限らず、Googleが提供しているサービスの各種APIを利用するためにはGoogle Cloud Platform(GCP)でアカウントを作成した上で、プロジェクトを作成する必要があります。この部分についてはこの記事では説明しませんが、以下のリンクが参考になります。

Google Analytics APIの追加

GCPで作成したプロジェクトに、実際に使用するGoogle Analytics Reporting API(正式名)を追加します。

1. プロジェクトダッシュボード ⇒ ナビゲーションメニュー ⇒ APIとサービス ⇒ ライブラリとリンクをたどります。

2. 検索ボックスでanalytics reporting apiを入力します

3. Google Analytics Reporting APIを選択します

3. APIを有効化します

これでプロジェクトにAPIを追加できました。

ちなみに、上記に似たAPIにGoogle Analytics APIというAPIもライブラリにありますが、こちらは古いものなので注意してください。

サービスアカウント・認証情報の作成

APIを利用するためにはさらにサービスアカウントと認証情報を作成する必要があるため作成します。

アプリケーションはサービス アカウントを使用して、ユーザーの関与を必要とせずにGoogle のサービス API を呼び出すことができます。

1. 認証情報画面から「ウィザードで選択」を選びます

2. 追加する認証情報の設定。使用するAPIは「Analytics Reporting API」

3. 「必要な認証情報」からサービスアカウントを作成します

これで、サービスアカウントが作成されて認証情報が記載されたjsonファイルがダウンロードされます。アプリ側でAPIを利用する際にこの認証情報が必要なります。

次に、Google AnalyticsとNuxtでの設定を行います。

Google Analyticsでユーザ追加

上記で追加したサービスアカウントをGoogle Analyticsの管理画面で追加します。

「管理画面」⇒「ビュー」⇒「ユーザー管理」からユーザを追加可能です。

GCPで作成したサービスアカウントのメールアドレスを入力します

次に「管理画面」⇒「ビュー」⇒「ビューの設定」からビューIDを取得しておきます。ビューIDはアプリ側(Nuxt)で使用します。

これでGoogle Analytics側の設定はおわりです。

ピンクの塗りつぶし箇所です

NuxtでGoogle Analytics APIの設定

ようやく、Nuxt側の設定です。これをやればNuxtアプリケーションでAPIを実行することが出来るようになります。

クライアントライブラリの追加

GoogleからAPI操作用のライブラリが提供されているので、プロジェクトに追加します。

yarn add googleapis

Analytics Reporting APIの実装

Google AnalyticsからPVデータを取得するために、API実行処理を実装します。ただし、このAPIは1日あたりのリクエスト可能回数に制限があるので、例えばブログにアクセスがあるたびにAPIが実行されるといったことはあまりよろしくありません。

また、今回の利用用途が人気の記事一覧であるため、リアルタイムな更新等は不要で適当なタイミングでAPIを実行してそのデータを作成しておけば良いものです。

そのため、本ブログではnuxt generate時にAPIを実行して、PV上位の記事ページを取得しjsonファイルに書き出しておく方法をとりました。書き出したjsonファイルをVuexで読み込んでおき、コンポーネントで利用しています。

具体的には↓のような流れです。

  1. nuxt generateにbeforeフックを追加
  2. analytics reporting apiを実行(PV上位5記事を取得)
  3. 記事のURLからUIDを取得する
  4. prismic apiでUIDをもとに記事データ取得
  5. タイトルや日付等と一緒にJSON書き出し

以上のことを行う処理をnuxt.config.jsに実装しました。

import fs from "fs";
import Prismic from "prismic-javascript";
import { initGenerateApi } from "./plugins/prismic-config";
const { google } = require("googleapis");

export default {
  hooks: {
    // 人気の記事PV取得
    generate: {
      async before() {
        const client = await google.auth.getClient({
          keyFile: "./keys.json", // ルートフォルダの認証情報ファイル利用
          scopes: "https://www.googleapis.com/auth/analytics.readonly"
        });
        const analyticsReport = google.analyticsreporting({
          version: "v4",
          auth: client
        });
        const res = await analyticsReport.reports.batchGet({
          requestBody: {
            reportRequests: [
              {
                viewId: "XXXXXXXXXX", // ビューID
                dateRanges: [
                  {
                    startDate: "2019-11-01", // データ取得開始日
                    endDate: "today" // データ取得終了日
                  }
                ],
                dimensions: [{ name: "ga:pagePath" }],
                dimensionFilterClauses: [
                  {
                    filters: [
                      {
                        // 記事ページのみ取得対象とする
                        dimensionName: "ga:pagePath",
                        expressions: "^/entry/.*/"
                      }
                    ]
                  }
                ],
                // ページビューを指標として利用
                metrics: [{ expression: "ga:pageviews" }],
                orderBys: {
                  fieldName: "ga:pageviews", // ページビューでソート
                  sortOrder: "DESCENDING" // 降順
                },
                pageSize: 5
              }
            ]
          }
        });
        const api = await initGenerateApi();
        const popularEntrys = { data: [] }; // json格納データ
        for (const data of res.data.reports[0].data.rows) {
          // gapiで取得した記事urlからuidを抜き出して記事データを取得する
          const uidStr = data.dimensions[0].slice(7, -1);
          const entry = await api.getByUID("entry", uidStr);
          popularEntrys.data.push({
            uid: uidStr,
            title: entry.data.entry_title[0].text,
            created_at: entry.data.created_at,
            eyecatch_image_url: entry.data.eyecatch_image.url,
            pv: data.metrics[0].values[0]
          });
        }
        // jsonファイルを生成する
        fs.writeFile(
          "assets/json/popular-entrys.json",
          JSON.stringify(popularEntrys),
          err => {
            if (err) {
              process.exit();
            }
          }
        );
      }
    }
  }
};

認証情報ファイルというのはGCPで作成されたJSONファイルのことです。環境変数化していないのは、Nuxtで環境変数にするとクライアントと共有されてしまい、クライアントサイドで見れてしまうためファイル読み込みとしています。

この認証情報ファイルはこの時にのみ使い、generateした資産にも含まれません。認証情報ファイルをGit管理下におくのは不本意ですが、、何か良い方法があれば教えてください。。(publicリポジトリではやらないでください

ちなみに、認証情報ファイルの中で必要な情報は「private_key」と「client_email」のみなので、念のためそれ以外の設定値は削除しています。ファイル読み込みではなくて、環境変数で指定する場合もこの2つの設定情報だけでOKです。

vuex storeで読み込み

storeでは以下のような感じでJSONファイルを読み込め、stateにセットできます。

あとは利用したいコンポーネントで利用するだけです。

import popularData from "~/assets/json/popular-entrys.json";

export const state = () => ({
  /** 人気の記事 */
  popularEntrys: popularData.data
});

おわりに

JAMStack構成のブログで「人気の記事一覧」を実装する方法について書きました。表示する部分の実装は省略しましたが、このブログのサイドバーにある人気の記事リンクがそれです。

更新のタイミングとしてはgenerate時なので、記事を投稿した時か、Nuxtソースを修正してGitにpushした時になるので、リアルタイムではないですが特に大きい乖離は発生しないかなと思います。

普通のブログサービスであればこんな苦労必要ないのですが、、こういうところはJAMStackブログの大変なところですね~

About
K

旅行とお酒、そしてプログラミングが大好きなエンジニアです。

バックエンド、言語としてはJava(Spring FW)・Cが専門ですが、最近はVue/Nuxtをはじめとするフロントエンドまわりも勉強中。

旅行は国内・海外問わず、海外旅行は現在12か国、国内は色々。東南アジアの旅行ならカンボジアが大好き(3回ほど渡航)

お酒はビール・ウイスキー・日本酒があればOK。

Portfolio

QT Visualizer

Portfolio Site

プライバシーポリシー

Frontend by Nuxt & Vuetify / Contents by Prismic.io

© 2019 K note.life