9
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Google AnalyticsAdvent Calendar 2015

Day 16

広告ブロックアプリ「Crystal」で動作しないアナリティクスを動かす方法

Last updated at Posted at 2015-10-15

iPhoneの人気有料広告ブロックアプリ「Crystal」が、Googleアナリティクスまで無効化するらしい。

【検証2】iOS 9の広告ブロックがGAを無効化!の件を、広告屋として調べてみた(+Optmizely)【150923更新】 - でぶててのWEB録

#実際に検証してみる

Crystal 1Blocker AdBlock Plus
動作しない 問題なく動作 問題なく動作

実際にiOS 9にアップデートし、人気どころの3つのアプリで検証。Googleアナリティクスのリアルタイムレポートを用いて調べると、「Crystal」では確かにGoogleアナリティクスが動作しないことが分かる。アクセス解析に不都合が生じるので、今回はこれを動くように試みる。

#アナリティクスがブロックされている場合のみ「Measurement Protocol」を叩く

「Measurement Protocol」はユニバーサルアナリティクスより追加された新機能で、画像ビーコンにより直接情報が送信できる仕組みです。手順としては、

  1. アナリティクスが効いているか調べる
  2. 効いていない場合にのみ「Measurement Protocol」発動
    と言った感じでできそうです。

アナリティクスが効くかどうかは、下記の記事を読むに、結構簡単に調べることが可能なようです。

[iOS9] コンテンツブロックされているかどうかチェックする方法 | SEM Technology

サンプルを示します。通常のユニバーサルアナリティクスが<body>直後に設置されているものとします。そして、</body>直前にcheck.jsを読み込ませます。

test.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Test page</title>
<meta charset="utf-8">
</head>
<body>
<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-XXXXXXXX-X', 'auto');
  ga('send', 'pageview');

</script>
<!-- Contents -->
<script src="check.js"></script>
</body>
</html>

「check.js」は
・アナリティクスが効いていない時に
・JavaScriptで取れるユーザー情報を「ga.php」にパラメータ付加して画像として設置
させており、内容は下記の通りです。

check.js
if (typeof(window[window['GoogleAnalyticsObject']].getByName) === 'undefined') {
	(function(d, s) {
		var f = d.getElementsByTagName(s)[0],
			i = d.createElement('img'),
			dl = document.location.origin + document.location.pathname + document.location.search,
			dt = d.title,
			sr = screen.width + 'x' + screen.height,
			vp = screen.availWidth + 'x' + screen.availHeight,
			sd = screen.colorDepth;
		i.src = "ga.php?dl=" + encodeURIComponent(dl) + "&dt=" + encodeURIComponent(dt) + "&sr=" + sr + "&vp=" + vp + "&sd=" + sd;
		f.parentNode.insertBefore(i, f);
	})(document, 'script');
}
```
次に実際に「Measurement Protocol」を作成している「ga.php」です。
JavaScriptで取れる(取りやすい)情報は「check.js」内で取得しておいて、「ga.php」にGETで送っておき、PHPで取得できる情報を足した上で「Measurement Protocol」を作成しています。
出来たURLをfile_get_contentsにて叩いたのち、1px×1pxの透過GIF画像を出力しています。

````php:ga.php
<?php
	$cid = "";

	// クライアントIDのCookieがある場合利用
	if(isset($_COOKIE["measurementprotocol"]) && strlen($_COOKIE["measurementprotocol"]) == 36) $cid = $_COOKIE["measurementprotocol"];

	// 無い場合生成
	else $cid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));

	// プロトコルのバージョン(必須)
	$param = "?v=1";

	// トラッキングID(必須)
	$param .= "&tid=UA-XXXXXXXX-X";

	// クライアントID(必須)
	$param .= "&cid=".$cid;

	// IP オーバーライド(任意)
	$param .= "&uip=".$_SERVER['REMOTE_ADDR'];

	// ユーザー エージェント オーバーライド(任意)
	$param .= "&ua=".rawurlencode($_SERVER['HTTP_USER_AGENT']);

	// 画面の解像度(任意)
	$param .= isset($_GET['sr']) && is_string($_GET['sr']) ? "&sr=".$_GET['sr'] : '';

	// 表示領域のサイズ(任意)
	$param .= isset($_GET['vp']) && is_string($_GET['vp']) ? "&vp=".$_GET['vp'] : '';

	// ドキュメントのエンコード(任意)
	$param .= "&de=UTF-8";

	// 画面の色(任意)
	$param .= isset($_GET['sd']) && is_string($_GET['sd']) ? "&sd=".$_GET['sd']."-bit" : '';

	// ユーザーの言語(任意)
	$param .= "&ul=ja";

	// ヒットタイプ(必須)
	$param .= "&t=pageview";

	// ドキュメントの場所のURL(任意)
	$param .= isset($_GET['dl']) && is_string($_GET['dl']) ? "&dl=".$_GET['dl']."[Blocked]" : '';

	// ドキュメント タイトル(任意)
	$param .= isset($_GET['dt']) && is_string($_GET['dt']) ? "&dt=[Blocked]".$_GET['dt'] : '';

	// キャッシュの無効化(任意)
	$param .= "&z=".mt_rand(100000000000, 199999999999);

	// Measurement Protocol叩く
	file_get_contents("https://ssl.google-analytics.com/collect".$param);

	// 画像ヘッダ出力
	header("Content-type: image/gif");

	// Cookieの保存(アナリティクス同様、とりあえず2年とする)
	setcookie("measurementprotocol", $cid, time() + (3600 * 24 * 365 * 2));

	// 1px×1pxの透過GIF画像を表示
	echo base64_decode("R0lGODlhAQABAID/AP///wAAACwAAAAAAQABAAACAkQBADs=");
?>
```
cidクライアントID)」の生成箇所は下記参考リンクより頂戴しています
[Google Analytics Measurement Protocol for PHP - Campaign Tracking - Mudd Advertising]
(http://mudd.com/blog/google-analytics-measurement-protocol-for-php-campaign-tracking/)

今回の例ではブロックされていることを分かりやすくするため下記のように[Blocked]を足した状態でデータを取れるようにしております必要なければ削除しても構いません

|ページタイトル|仮想ページビュー|
|:-----------:|:------------:|
|Blockedページのタイトル|/test/Blocked|

ちなみに

````html
<img src="ga.php?dl=%2Ftest%2F&dt=TEST" alt="">
```
などとすることで、ガラケーなどでもユニバーサルアナリティクスにデータ送信することが可能です。パラメータ「dl」は「ドキュメントの場所のURL」、「dt」は「ドキュメント タイトル」を示しますが、UTF-8にてURLエンコードした上で付加して下さい。

なお、「Measurement Protocol」のパラメータについては公式ページにて詳しく説明されています。

[Measurement Protocol のパラメータ リファレンス  |  アナリティクス Measurement Protocol  |  Google Developers]
(https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters?hl=ja)
9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?