コンテンツブロックはどのように動いているのか?

まずは、Appleの開発者向けドキュメントをチェックしたいと思います。公式ドキュメントは、

iOS Developer Library - Content Blocking Safari Extensions

という形で提供されています。英語のドキュメントではあるものの、Safari拡張に対して下記のようなJavaScriptを指定することで、コンテンツブロックを実現しているものと思われます。

[
    {
        "action": {
            "type": "block"
        },
        "trigger": {
            "url-filter": "webkit.org/images/icon-gold.png"
        }
    },
    {
        "action": {
            "selector": "a[href^=\"http://nightly.webkit.org/\"]",
            "type": "css-display-none"
        },
        "trigger": {
            "url-filter": ".*"
        }
    }
]

1つ目の例では、URLベースでリソースの読み込みをブロックしているようです。また2つ目の例では、CSSセレクタベースでCSSスタイルにdisplay: noneを設定し、画面表示を行わないようにしているようです。

もともと、コンテンツブロックは、読み込むデータ量を削減すること、も目的の1つかと思いますので、多くはURLベースで読み込みのブロックを行っているのではないでしょうか。その上で、読み込まれていない広告表示枠を非表示にするために、2つ目の形式の枠非表示も併用しているものと思われます。

url-filterとしてブロック対象のURLを指定しているため、GoogleアナリティクスやGoogleタグマネージャについては、それぞれのライブラリJavaScriptを自分のサーバー上にダウンロードしてきて、そこから読み込むようにしてしまえば、ブロック対象のURLに掲載されていないURLからリソースを読み込むことになり、ブロックを回避できそうです。

ブロックされているか否かをチェックする方法

上記のように、コンテンツブロックされている場合、GoogleアナリティクスやGoogleタグマネージャのJavaScriptライブラリが読み込めない、ということから、GoogleタグマネージャやGoogleアナリティクスがブロックされているか否かをチェックするには、ライブラリ内部で定義しているJavaScript関数が存在するか否かでチェックできそうです。Qiitaや一部の記事の中には、DOM上のクラス名で判断している、といった記事もあります。実際コンテンツブロックの方法には、URLベースのものとCSSセレクタベースの2種類あるようなので、DOM上のクラス名での判断でも可能だと思いますが、ブロックをチェックする対象をGoogleタグマネージャとGoogleアナリティクスだけに絞るのであれば、このやり方が単純かと思います。

具体的には、

;(function (window) {
  var ContentsBlockChecker = function () {};
  ContentsBlockChecker.prototype.isBlockGoogleTagManager = function () {
    return typeof(window.google_tag_manager) === 'undefined';
  };
  ContentsBlockChecker.prototype.isBlockUniversalAnalytics = function () {
    return typeof(window[window['GoogleAnalyticsObject']].getByName) === 'undefined';
  };
  ContentsBlockChecker.prototype.isBlockGoogleAnalyticsAsync = function () {
    return Object.prototype.toString.call(_gaq) == "[object Array]";
  };
  ContentsBlockChecker.prototype.isBlockGoogleAnalyticsSync = function () {
    return Object.prototype.toString.call(_gat) == '[object Undefined]';
  };

  ContentsBlockChecker.prototype.isBlock = function () {
    return {
      'GoogleTagManager': this.isBlockGoogleTagManager(),
      'UniversalAnalytics': this.isBlockUniversalAnalytics(),
      'GoogleAnalyticsAsync': this.isBlockGoogleAnalyticsAsync(),
      'GoogleAnalyticsSync': this.isBlockGoogleAnalyticsSync()
    };
  };
  window.ContentsBlockChecker = ContentsBlockChecker;
})(window);

のようなJavaScriptを読み込み、

var checker = new ContentsBlockChecker();
if (checker.isBlockUniversalAnalytics()) {
  // ユニバーサルアナリティクスがブロックされています
} else {
  // ユニバーサルアナリティクスはブロックされていません
}

といった形で判断することができます。

上記では、旧Googleアナリティクス(同期版、非同期版)についてもチェック関数を作成していますが、こちらの動作テストは不十分ですので、利用の際には注意してご利用ください。

さっそく、コンテンツブロックの利用状況をテスト

ということで、このブログにおいて、上記のJavaScriptコードを実装しています。
ある程度アクセスが貯まったら、このブログのデータでどのくらいのユーザーがコンテンツブロックを利用しているか、公開できればと思います(アクセスが少ない、かつPCからのアクセスが多いので、いつになるかは分かりませんが)。

もし、アクセスの多いサイト(特にモバイルからのアクセスが多いと参考にしやすいです)をお持ちの方で、このサイトと同様の調査に協力していただける方がいれば、お問合せフォームよりご連絡いただけますと、幸いです。