Google AnalyticsでWordPressのタグとカテゴリのランキングを実装する方法

[一休コンシェルジュ](https://www.ikyu.com/concierge/)の開発を担当している @hayatoise です。

# 概要
## 何が分かるの？
- Google Analytics APIを叩いて、タグ（ `example.com/tag/example` ）及びカテゴリ（ `example.com/category/example` ）のPV数を取得し、それを独自テーブルにインサートする方法です。
- とりわけ、本記事はWordPressに導入することを想定しています。

## どうやってやるの？
1. 独自テーブル（ e.g. `term_pageviews` ）を作成
2. APIを叩き、データを取得し、タグとカテゴリのデータだけ独自テーブルにインサートするためのバッチファイルを作成
3. CRONで定期的にバッチファイルを実行

## 前提条件
- PHP 5.4.0 以上

## 本記事が想定しているURLの例
Tag      : https://www.example.com/tag/example
Category : https://www.example.com/category/example

## 確認済みのバージョン
- WordPress 4.9.1
- PHP 5.6.X（確認してないが、PHP7でも動くはず）
- さくらのVPS

# 準備
## Google Analytics Reporting APIの有効化
1. [API Manager](https://console.developers.google.com/?hl=JA) にアクセス
2. `APIとサービスの有効化` をクリック
3. Google Analytics Reporting APIを検索し、`有効にする` をクリック

## 認証情報を作成
1. [API Manager](https://console.developers.google.com/?hl=JA) に戻る
2. 左のメニューから `認証情報` を選択
3. `認証情報を作成` をクリックし、ドロップダウンメニューから `サービスアカウントキー` を選択

![google_setsumei_1.png](https://qiita-image-store.s3.amazonaws.com/0/88460/61b495cb-bb6c-ef3e-e805-bf02d5c03645.png)

4 上記のようにフォームを埋めた上で、作成をクリック
5. 秘密鍵のJSONファイルがダウンロードされる

## Google Analyticsの設定
1. ダウンロードしたJSONファイルを開き、`client_email` に記載されているメールアドレスをコピー
2. Google Analyticsにログインし、左のメニューの `管理` をクリック
3. 任意の `ユーザー管理` をクリックし、右上の `＋` ボタンもクリック
4. 先程コピーしたメールアドレスを貼り、`表示と分析` にチェックを追加し、`ADD` する

### これで準備は完了です。

# 実装
## バッチファイルのコード
```php:google-analytics.php
<?php

require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/../../../wp-load.php';

// 認証情報のJSONファイルを定義
define( 'KEY_LOCATION', __DIR__ . '/example.json' );
// ビューIDを定義
define( 'VIEW_ID', '123456789' );

$report = getGoogleAnalyticsReport();

global $wpdb;

db_query( 'START TRANSACTION' );
try {
	db_query( 'DELETE FROM term_pageviews;' );
	save_term_pageviews( $report );

	db_query( 'COMMIT' );

} catch ( Exception $e ) {
	echo $e->getMessage() . PHP_EOL;
	db_query( 'ROLLBACK' );
	exit( 1 );
}

/**
 * @return array
 */
function getGoogleAnalyticsReport() {
	// Class及びAPIの初期化
	$client = new Google_Client();
	$client->setApplicationName( 'Analytics Reporting' );
	$client->setAuthConfig( KEY_LOCATION );
	$client->setScopes( [ 'https://www.googleapis.com/auth/analytics.readonly' ] );
	$analytics = new Google_Service_AnalyticsReporting( $client );

	// データ取得範囲の指定（過去1日分）
	$date_range = new Google_Service_AnalyticsReporting_DateRange();
	$date_range->setStartDate( 'yesterday' );
	$date_range->setEndDate( 'yesterday' );

	// メトリクスの指定
	$metrics          = [];
	$configureMetrics = [ 'ga:pageviews' ];
	foreach ( $configureMetrics as $metric ) {
		$rMetric = new Google_Service_AnalyticsReporting_Metric();
		$rMetric->setExpression( $metric );

		$metrics[] = $rMetric;
	}

	// ディメンションの指定
	$dimension = new Google_Service_AnalyticsReporting_Dimension();
	$dimension->setName( 'ga:pagePath' );

	// ソート順の指定
	$orderBy = new Google_Service_AnalyticsReporting_OrderBy();
	$orderBy->setFieldName( 'ga:pageviews' );
	$orderBy->setSortOrder( 'DESCENDING' );

	// リクエストの構築
	$request = new Google_Service_AnalyticsReporting_ReportRequest();
	$request->setViewId( VIEW_ID );
	$request->setDateRanges( $date_range );
	$request->setMetrics( $metrics );
	$request->setDimensions( $dimension );
	$request->setOrderBys( $orderBy );

	// Google Analyticsにレポートをリクエスト
	$body = new Google_Service_AnalyticsReporting_GetReportsRequest();
	$body->setReportRequests( [ $request ] );

	$result = $analytics->reports->batchGet( $body );

	$reports = $result->getReports();

	if ( ! isset( $reports[0] ) ) {
		return [];
	}

	// データを取得
	return $reports[0]->getData()->getRows();
}

/**
 * @param $sql
 *
 * @return int 取得/変更した件数
 * @throws Exception
 */
function db_query( $sql ) {
	global $wpdb;
	$result = $wpdb->query( $sql );
	if ( $result === false ) {
		throw new Exception( 'Failed to execute SQL:' . $sql );
	}

	return $result;
}

/**
 * @param $report
 *
 * @return array
 * @throws Exception
 */
function save_term_pageviews( $report ) {
	global $wpdb;
	// データからTermを絞る
	foreach ( $report as $r ) {
		$uri        = $r->getDimensions()[0];
		$page_views = $r->metrics[0]->values[0];
		$slug       = get_slug( $uri );

		if ( empty( $slug ) ) {
			continue;
		}

		$term_id = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT term_id FROM $wpdb->terms WHERE slug = %s", rawurlencode( $slug )
			)
		);

		if ( is_null( $term_id ) ) {
			printf( "Term not found for slug: %s(%s)\n", $slug, $uri );
			continue;
		}

		$term_id    = intval( $term_id );
		$page_views = intval( $page_views );

		db_query(
			$wpdb->prepare(
				"
        INSERT INTO term_pageviews
        (
          term_id,
          pageviews
        )
        VALUES
        (
          %d,
          %d
        )
        ON DUPLICATE KEY UPDATE
          pageviews = pageviews + VALUES(pageviews)
      ",
				array(
					$term_id,
					$page_views
				)
			)
		);
	}
}

/**
 * @param $uri
 *
 * @return string
 */
function get_slug( $uri ) {
	$parts = parse_url( $uri );
	if ( ! isset( $parts['path'] ) ) {
		return '';
	}

	$path = $parts['path'];

	$parts = array_filter( explode( '/', $path ) );

	if ( ! isset( $parts[0] ) || ( $parts[0] !== 'tag' & $parts[0] !== 'category' ) ) {
		return '';
	}

	$slug        = '';
	$page_counts = 0;
	foreach ( $parts as $part ) {
		if ( $part === 'page' ) {
			$page_counts ++;
		} else {
			continue;
		}
	}

	if ( $page_counts === 0 ) {
		$slug = array_pop( $parts );
	} elseif ( $page_counts === 1 ) {
		array_pop( $parts ); // page numberを取り除く
		array_pop( $parts ); // pageを取り除く
		$slug = array_pop( $parts ); // 変数にslugを代入する
	} else {
		echo 'Unexpected Error';
	}

	return $slug ?: '';
}
```
## ディレクトリの構造
```
├── auth
│   └── example.json
├── google-analytics.php
├── batch.php
├── composer.json
├── composer.lock
├── composer.phar
└── vendor
```

- `example.json` は準備のフェーズでダウンロードしたファイルです。

```php:google-analytics.php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/../../../wp-load.php';
```
- 僕の場合、これらのファイルを `wp-content/plugins/batch` というディレクトリにまとめています。

```php:batch.php
<?php
/*
Plugin Name: batch
Plugin URI: https://example.com
Description: 独自のバッチファイルを格納するためのプラグイン
Version: 1.0
Author: hayatoise
Author URI: https://example.com/author/hayatoise
*/
```
- batch.phpの中身は上記の通りです。WordPressにプラグインとして認識してもらうための説明文です。

## テーブルの構造
```sql:example.sql
CREATE TABLE `term_pageviews` (
  `term_id` bigint(20) unsigned NOT NULL,
  `pageviews` int(11) unsigned NOT NULL,
  PRIMARY KEY (`term_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
- `term_id` と `pageviews` だけのシンプルなテーブル構造です。

## データの取得期間を変更する方法
```php:example.php
// データ取得範囲の指定（過去1日分）
$date_range = new Google_Service_AnalyticsReporting_DateRange();
$date_range->setStartDate( 'yesterday' );
$date_range->setEndDate( 'yesterday' );
```
1週間分のデータを取得したい場合 `yesterday` から `8daysAgo` にしましょう。

```php:example.php
$date_range->setStartDate( '2017-12-18' );
$date_range->setEndDate( '2017-12-19' );
```
また、日付形式で書くことも可能です。

# おまけ
## ランキングデータを取得するSQL文

```sql:example.sql
SELECT t.*, v.*
FROM wp_terms t
INNER JOIN term_pageviews v ON t.term_id = v.term_id
ORDER BY v.pageviews DESC;
```

# 最後に
明日は @zimathon さんの「[データ分析基盤、その後](http://user-first.ikyu.co.jp/entry/2017/12/21/011132)」です。

### [一休.com Developers Blog](http://user-first.ikyu.co.jp/)

# 参考URL
- [Google アナリティクス Reporting API v4](https://developers.google.com/analytics/devguides/reporting/core/v4/?hl=ja)
- [Googleアナリティクスからアクセス数の多い記事を取得するWordPressプラグインを作ってみた](https://www.sria.co.jp/blog/2017/04/ranking-by-analytics/)