LaravelでGoogleAnalyticsAPIを利用してPVを取得する

メディアなどのシステムを構築する場合、PVを計測するというのはよくある要件だと思います。しかし、同一セッションを省いたり、ランキングを計測するためのデータベースを設計したりというのは少々大変です。
そんな時に、GoogleAnalyticsのAPIを使ってPVを計測すれば、上記のようなことを簡単に実現することができます。
本記事では、LaravelでGoogleAnalyticsのAPIを利用して、あるページのPVを取得する方法をご紹介します。

APIの設定

まず最初にAPIの設定を行います。手順は大きく以下の流れとなります。

  1. GoogleAnalyticsのAPIを有効にする。
  2. 認証情報を作成する。(今回はサーバーのバッチ処理などを想定しているため、サービスアカウントで作成)
  3. サービスアカウントをAnalyticsのアカウントに追加する。

詳細な手順は、過去に紹介しましたので、こちらの記事をご参照ください。

実装

APIの設定が終わりましたら実装に入ります。

ここで、実装する要件について、ざっくりと以下のようにすることにします。

  • 朔日の記事ページのPVを取得する
  • 記事のURLは、「/posts/:postId」とする

ライブラリをインストール

GoogleAnalyticsのAPIを利用するためライブラリをインストールしましょう。

composer require google/apiclient

APIをリクエストする処理を実装

まず、APIをリクエストするクラスを作成します。

APP_NAMEは、作成したプロジェクトの名前。
VIEW_IDは、参照するAnalyticsのビューのIDを設定します。

# app/Utils/Analytics.php

<?php

namespace App\Utils;

class Analytics
{
    const APP_NAME = '*****';
    const VIEW_ID = '*****';
    const SCOPES = ['https://www.googleapis.com/auth/analytics.readonly'];
    const KEY_FILE_LOCATION = __DIR__ . '/google-service-account-credentials.json';

    private $analytics;

    /**
     * API設定の初期化
     */
    public function __construct()
    {
        $client = new \Google_Client();
        $client->setApplicationName(self::APP_NAME);
        $client->setAuthConfig(self::KEY_FILE_LOCATION);
        $client->setScopes(self::SCOPES);
        $this->analytics = new \Google_Service_AnalyticsReporting($client);
    }

    /**
     * APIリクエスト
     */
    public function getReports(
        \Google_Service_AnalyticsReporting_DateRange $dateRange,
        Array $metrics,
        Array $dimensions,
        Array $dimensionFilterClauses,
        Int $pageSize,
        String $nextPageToken = null
    )
    {
        $request = new \Google_Service_AnalyticsReporting_ReportRequest();
        $request->setViewId(self::VIEW_ID);
        $request->setDateRanges($dateRange);
        $request->setMetrics($metrics);
        $request->setDimensions($dimensions);
        $request->setDimensionFilterClauses($dimensionFilterClauses);
        $request->setPageSize($pageSize);

        if ($nextPageToken) {
            $request->setPageToken($nextPageToken);
        }

        $body = new \Google_Service_AnalyticsReporting_GetReportsRequest();
        $body->setReportRequests(array($request));
        return $this->analytics->reports->batchGet($body);
    }
}

記事のPVを取得する処理

それでは、記事のPVを取得する処理を実装します。
定期的に取得することを前提に、Laravelのコマンドで実装することにします。

下記を実行してコマンドを作成します。

php artisan make:command DailyPostViews

作成されたコマンドを下記のように変更します。

実装のポイントになる点は、

  • PVをページパス単位で取得する。(「Metrics」と「Dimension」の箇所に設定)
  • 1リクエストで全件取れないため、再起処理を行う。

ことです。

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

use Log;
use App\Utils\Analytics;

class DailyPostViews extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'dailyPostViews';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '昨日の記事のPVを取得する。';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $analytics = new Analytics();

        $pageSize = 1000;

        // - リクエストパラメータの設定

        // 日付の範囲
        $dateRange = new \Google_Service_AnalyticsReporting_DateRange();
        $dateRange->setStartDate("1daysAgo");
        $dateRange->setEndDate("1daysAgo");

        // Metrics
        $pageviewsMetric = new \Google_Service_AnalyticsReporting_Metric();
        $pageviewsMetric->setExpression("ga:pageviews");
        $pageviewsMetric->setAlias("pageviews");
        $metrics = [$pageviewsMetric];

        // Dimension
        $pagePathDimension = new \Google_Service_AnalyticsReporting_Dimension();
        $pagePathDimension->setName('ga:pagePath');
        $dimensions = [$pagePathDimension];

        // Filter
        $pagePathFilter = new \Google_Service_AnalyticsReporting_DimensionFilter();
        $pagePathFilter->setDimensionName('ga:pagePath');
        $pagePathFilter->setOperator('REGEXP');
        $pagePathFilter->setExpressions(['^/posts/(\d+)$']);

        $dimensionFilterClauses = array_map(function($filter) {
            $filterClause = new \Google_Service_AnalyticsReporting_DimensionFilterClause();
            $filterClause->setFilters([$filter]);
            return $filterClause;
        }, [$pagePathFilter);


        // 結果を取得
        try {
            $reports = [];
            do {
                $nextPageToken = count($reports) ? $reports[count($reports) - 1]->getNextPageToken() : null;

                $response = $analytics->getReports(
                    $dateRange,
                    $metrics,
                    $dimensions,
                    $dimensionFilterClauses,
                    $pageSize,
                    $nextPageToken
                );
                $reports[] = $response[0];

            } while ($response[0]->getNextPageToken() != '');

            // PVのデータを処理
            foreach ($reports as $report) {
                $rows = $report->getData()->getRows();
                $header = $report->getColumnHeader();

                foreach ($rows as $row) {
                    $dimensions = $row->getDimensions() ?: [];
                    $metrics = $row->getMetrics();

                    $path = $dimensions[0];
                    $views = $metrics[0]->getValues()[0];

                    Log::info("{$path} : {$views}");
                }
            }

        } catch (\Exception $e) {
            Log::error($e->getMessage());
            return;
        }
    }
}

最後に、コマンドを実行してログファイルにPVが表示されればOKです。

php artisan dailyPostViews

この記事と関連している記事