訪問別ページ数を改善させるA/Bテストを実施する方法

Google アナリティクスには、ページのコンバージョンを改善するためのA/Bテストを実施することができる「[ウェブテスト](https://support.google.com/analytics/answer/1745147?hl=ja)」という機能が用意されています。この機能を使えば、あるページに2つのパターンのデザインを用意し、いずれのパターンでコンバージョン率が高かったのかを分析することができます。

一方でたとえば、検索エンジンを経由し、トップページではなく、商品カテゴリページや商品詳細ページへ流入したユーザに対して、サイトの説明文を追加表示するという施策が、[訪問別ページ数](https://support.google.com/analytics/answer/1006251?hl=ja)（サイトへの 1 回の訪問あたりにユーザーが閲覧した平均ページ数）にどの程度の影響を与えるのか測定するようなテストを実施することはできません。

Google アナリティクスの「ウェブテスト」は、あくまである特定ページのデザインを複数パターン提示する機能であり、ある要素を露出したユーザに、その後どんな行動の変化が現れたかを分析することができないからです。

そこで、Google アナリティクスの新しい測定方法である「[ユニバーサルアナリティクス](https://support.google.com/analytics/answer/2790010?hl=ja)」に、新たに導入された「[カスタムディメンション](https://support.google.com/analytics/answer/2709828?hl=ja)」と、さらに「[Google Tag Manager（GMT）](https://www.google.com/tagmanager/web/)」を使い、この課題を解決する方法を実装してみました。

## 前提条件

1. Google アナリティクス（ユニバーサルアナリティクス）を使用している。
2. Google Tag Managerを使用している
3. 商品カテゴリページ、商品詳細ページに流入してきたユーザのうち、20%のユーザに「このサイトについて」というPRコンテンツを表示する。（＝トップページなど、ほかのページに流入したユーザはテストの対象外）

## カスタムディメンションを追加する

### Google アナリティクス側の設定

ユニバーサルアナリティクスでは、[カスタムディメンションはプロパティ単位で管理画面から設定します](https://support.google.com/analytics/answer/2709829?hl=ja)。

* **[名前]** には、レポート内の別のカスタム ディメンションや指標と区別が付くよう、他と重複しない名前を指定します。たとえば、「Experiment Pattern」などです。名前はあとから変更できます。
* **[範囲]** を選択します。今回は、訪問別ページ数を比較するため、セッションを選択します。
* **[アクティブ]** ボックスは、オンに設定します。

### Google Tag Manager 側の設定

ユニバーサルアナリティクスのタグをGoogle Tag Managerで配信する場合、[カスタムディメンションの送信は
マクロを使用して行います]( https://developers.google.com/analytics/devguides/collection/upgrade/reference/gtm?hl=ja#customvars)。

**カスタムディメンションの値を格納するデータ レイヤー変数マクロを作成。**
![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/644/a5854bac-dff7-8673-4778-f1c69b7db679.jpeg "カスタムディメンションの値を格納するデータ レイヤー変数マクロを作成。")

**Google タグマネージャで ユニバーサルアナリティクス のタグを編集。**
![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/644/1bdb1a52-237b-aef0-9ba8-913ff22ce297.jpeg "")


## JavaScriptで実装する

次は、JavaScriptで以下の処理を実装します。

1. テストごとに異なるID（今回のテストでは、 **14022001** を利用）を発行し、
2. 訪問者のCookieを確認して、過去30日間、テスト 14022001 の被験者に一度もなったことがないことを確認し、
3. 表示されたページがテスト対象のページかどうかを確認し、
4. 表示させるパターンを決定し、
5. 決定されたパターンに基づいて表示をだしわけ、
6. Google アナリティクスに、カスタムディメンションを使用して、表示したパターンを送信する

この機能を実装するには、以下のライブラリが必要です。

* [jQuery](http://jquery.com/)
* [jQuery Cookie](https://github.com/carhartl/jquery-cookie/tree/v1.4.0)

```experiments.js
/*!
 * A/B testing script
 */

// EXPERIMENT CLASS DEFINITION
// ======================

var Experiment = function(experimentId, options) {
	this.experimentId = experimentId;
	this.options      = $.extend({}, Experiment.DEFAULTS, options);
};

Experiment.DEFAULTS = {
	cookie : {
		expires : 30,
		path    : '/'
	}
};

Experiment.prototype.getPattern = function() {
	var that    = this;

	return $.cookie('experiments.' + that.experimentId);
};

Experiment.prototype.setPattern = function(pattern) {
	var that = this;

	pattern = pattern || '';

	$.cookie('experiments.' + that.experimentId, pattern, that.options.cookie);
};

Experiment.prototype.push = function() {
	var that    = this;
	var pattern = that.getPattern();

	var data = {
			'event' : 'sendPageView'
		};

	pattern && (data.experimentPattern = pattern);

	dataLayer.push(data);
};

Experiment.prototype.getPassname = function() {
	return location.pathname;
};

Experiment.prototype.getRandomKey = function() {
	var key    = 0;
	var total  = 0;
	var random = Math.floor(Math.random() * 100) + 1;

	for ( var i = 0; i < arguments.length; i++) {
		key = i;
		total += arguments[i];

		if (total >= random) {
			break;
		}
	}

	return key;
};

// EXPERIMENT ID : 14021901
// ======================

$(function() {
	// 1. テストごとに異なるID（今回のテストでは、 **14022001** を利用）を発行し、
	var experiment = new Experiment('14021901');

	// 2. 訪問者のCookieを確認して、過去30日間、テスト 14022001 の被験者に一度もなったことがないことを確認し、
	if (experiment.getPattern() === undefined) {
		// 3. 表示されたページがテスト対象のページかどうかを確認し、
		// ここでは、Pathnameが /category か /product からはじまっていれば対象ページ
		if (experiment.getPassname().match(/^\/(category|product)/g)) {
			// 4. 表示させるパターンを決定し、
			// このケースでは、noneを通常パターン（80%）、p1を別パターン（20%）で表示
			var patterns = new Array('none', 'p1');
			var pattern  = patterns[experiment.getRandomKey(80, 20)];

			experiment.setPattern(pattern);

			// 5. 決定されたパターンに基づいて表示をだしわけ、
			if (pattern === 'p1') {
				console.log('Pattern P1 is fired');
			}

		} else {
			experiment.setPattern();
		}
	}

	// 6. Google アナリティクスに、カスタムディメンションを使用して、表示したパターンを送信する
	experiment.push();
});
```

## GMTでGoogle アナリティクスのタグ配信ルールを変更する

これだけだと、カスタムディメンションの値は送信されません（！）。
なぜなら、dataLayer変数名によるpush ```dataLayer.push(data);``` を待たずに、Google アナリティクスのタグ配信が行われ、ページビューを記録してしまうためです。

これを防ぐために、 ```dataLayer.push()``` の処理をも待って、Google アナリティクスのページビュー記録が行われるよう、[タグの配信ルール](https://support.google.com/tagmanager/answer/2644396?hl=ja)を変更します。

Experiment.push() 関数では、カスタムディメンションを格納するデータレイヤー変数名（experimentPattern）に加え、イベント名（sendPageView）を合わせて送信しています。

ここでは、以下のようなタグの配信ルールを指定します。

* すべてのURLで
* イベントが sendPageView と等しい

![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/644/a3be5cca-1e56-ec50-83c3-8216e8760739.jpeg)

これで、カスタムディメンションの値が設定されたあと、Google アナリティクスのタグが配信され、ページビューが記録されます。

## 注意

* ここでは、20%のユーザに対して異なるパターンのページを表示することを目指していますが、実際には、ある程度の誤差がでます。
* Google アナリティクスの配信ルールにイベントの条件を追加することで、PV数が減ってしまうことも考えられます。[自社サイト](http://dohosha.com/jp/)に試験的に導入したところ、前日、および前週同曜日と比較して大きく変化はありませんでしたが、十分に注意して検証されることをおすすめします。