このブログには、Google Adsense の広告を組み込んでますが、2020年8月から、Google Adsense が表示されなくなっており、ログインしてみると以下のような警告が表示されていました。
Image from Gyazo

ポリシーセンターで、警告の詳細を確認すると、無効な<wbr>トラフィック問題で制限されている旨が表示されていました。
Image from Gyazo

無効な<wbr>トラフィックとは何かですが、無効なトラフィックの定義 - AdSense ヘルプみる限り以下のような行為が該当するようです。

  • サイト運営者様が、ご自身のライブ広告をクリックしてクリック数やインプレッション数を増やすこと
  • 1 人以上のユーザーが繰り返しクリックして、クリック数やインプレッション数を増やすこと
  • サイト運営者様がご自身の広告でのクリックを誘導すること(例: 広告をクリックするようユーザーを誘導するあらゆる言葉、大量の偶発的クリックを誘発する広告掲載など)
  • 自動クリックツールやトラフィック ソース、ロボット、その他の不正な行為を行うソフトウェア

Google Adsense で無効なトラフィックと判定されたアクセスを確認したところ、アメリカPCからのアクセスがほぼ無効なトラフィック扱いとなっていることが確認できました。
このため、対象のアクセスを広告表示対象外にすれば、ある程度無効なトラフィックの発生は防げると考えました。


特定地域からのアクセスを広告表示対象外にする方法

GeoIPというIPアドレスから、アクセスしている地域を特定する技術があります。
IPアドレスから地域特定するGeoIP系技術について調べてみた(追記あり)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社

IPアドレスは、クライアントJavaScriptでは取得できないため、以下のような方法で実装する必要があります。

  • 外部のGeoIP系のWeb APIを使って、IPアドレスから地域を特定する。
  • サーバー側でIPアドレスを取得し、地域を特定し、Google Adsense のコードを埋め込むか否か制御する。

また、このブログ特有の制約事項が以下2点あります。

  • HTMLをキャッシュしており、ユーザーごとのコンテンツをHTMLに埋め込むことが難しい。
  • Google Tag Manager を使っている。タグに関する制御なので、Google Tag Managerから制御を行いたい。

外部の<wbr>GeoIP系の<wbr>Web APIを<wbr>使って、<wbr>IPアドレスから<wbr>地域を<wbr>特定する。<wbr>APIの呼び出し回数制限が気になりましたので、制約事項を勘案して、以下のような実装にすることにしました。

  1. GeoIP で IPアドレスから地域を特定する Web APIを作る。
  2. 1.作成したAPIに Gooogle Tag Managerからアクセスし、その結果によって広告タグの配信を制御する。

Google Tag Manager から、外部のGeoIP系のWeb APIを呼び出す方法

Simo Ahava さんが、Free IP Geolocation API and Accurate IP Geolocation Database使って、IPアドレスから地域を特定する Custom Template を紹介する記事を書いていて、参考になりそうです。


作成したもの

以下、作ったものについて記載します。


Web API

Django で、GeoIP2 を使って、IPアドレスから地域を特定するWeb API を作成しました。
作成したWeb API については以下の記事でまとめています。


Google Tag Manager の カスタムHTMLタグ、トリガー、JavaScript変数

以下、カスタムHTMLタグ、トリガー、JavaScript変数を作成しました。

geoipタグ

Image from Gyazo

  • カスタムHTMLの内容
    カスタムHTMLの内容は以下の通りです。
    タグ内で、Ajax 通信を行い、戻り値取得後に、geoip.load イベントを発行します。
    <script>
      window.dataLayer = window.dataLayer || [];
      window.dataLayer.push({
        "event": "geoip.start",
        "geoip.startTime": (new Date()).getTime()
      });
    
      (function () {
        "use strict";
        // 正常終了時に呼び出す関数
        function onSuccess (data) {
          window.dataLayer.push({
            "event": "geoip.load",
            "geoip.countryCode": data.country_code,
            "geoip.endTime": (new Date()).getTime()
          });
        }
        // エラー時の処理
        function onError (err) {
          var data = { country_code : "UNKNOWN" };
          window.dataLayer.push({
            "event": "geoip.load",
            "geoip.countryCode": data.country_code,
            "geoip.endTime": (new Date()).getTime()
          });
          console.warn(err);
        }
        // fetch GeoIP data from Web API
        var request = new XMLHttpRequest();
        request.open("GET", "/api/geoip/", true);
        request.setRequestHeader('Accept', 'application/json');
        request.responseType = 'json'
        request.onreadystatechange = function () {
            if (this.readyState === 4) {
                if (this.status >= 200 && this.status < 400) {
                    onSuccess(this.response);
                } else {
                    onError(new Error("Unexpected HTTP Status Code " + this.status));
                }
            }
        }.bind(request);
        request.onerror = onError;
        request.send();
      }());
    </script>
    

ちなみに、Web API は以下のような、結果を返します。
カスタムタグで取得するのは、country_code のみです。

{
    "city": "Meguro-ku",
    "country_code": "JP",
    "country_name": "Japan",
    "dma_code": null,
    "latitude": 35.6418,
    "longitude": 139.7023,
    "postal_code": "153-0061",
    "region": "13"
}

geoip.countryCode 変数

geoipタグで設定しているデータレイヤー変数を受け取るために必要になります。
Image from Gyazo

geoip.load トリガー

geoipタグで設定している geoip.load イベントで発火するトリガーです。
geoip.countryCode追加で条件に指定し、geoip.countryCode JP の場合のみに発火するようにしています。
Image from Gyazo

Google Auto Adsense initタグ

geoip.loadトリガーに設定しています。
カスタムHTMLの内容は、AdSense コードについて - AdSense ヘルプ内容です。
Image from Gyazo

これで、Google Adsense のコードを国コードにより制御できるようになりました。
まだ、広告がブロック中のためか、表示の確認ができません。
自動広告の場合、Google Tag Manager で HTML描画後にタグを挿入できるか試している例があまりなかったので、ブロック解除後に再度表示を確認してみようかと思います。
以上です。

コメント