Google AdSense を本文にのみ適切に自動挿入する機能を自作した

Google AdSense を本文にのみ適切に自動挿入する機能を自作した
みるみ

この記事は2020年の3月に大幅にリライトしています。AdSenseの自動広告を取り巻く環境が変わったこと、掲示していたアルゴリズムを大きく改善させたこと、PHPで書いていたプログラムをJavaScriptに書き換えたことなどが理由です。

Google AdSenseには「自動広告」という機能がありますが、アイツはやべぇので使わない方がいいでしょう。

どのくらいヤバいかというと、

auto-ad-example-2

ヘッダーにそんなドでかく出す?普通…。自動広告のアホ代表例。

auto-ad-example-1

かと思ったらそれを2つも!?
PCでファーストビュー全部隠れてますけど!?!??!?

しかも期待の本文中の広告はというと、

auto-ad-example-3

そこ話の途中なんだけど…?しかもその広告ユニット微妙じゃない…?

という有り様。

「本文中にはAdSenseは出したいんだよなあ」という方は多いと思いますが、現状の自動広告設定では局所的に自動のON/OFFを制御することはできないので泣く泣く使わないようにしているというパターンがほとんどでしょう。

auto-ad-settings

設定でいじれるのはせいぜいこのくらい。「最適化」してもバンバン出やがるし、「ページ内広告」でもメインコンテンツ以外の部分に出力されやがります…。

そこで、記事内の本文中にのみ、適切な場所・適切な個数で好きな広告ユニットを挿入できるようなプログラムを自作しました。

それを今回公開してみますので、ぜひみなさんにもお使いいただければと!

元々自分用なので、それぞれのユーザーさんごとに調整可能な部分がまだ不十分だったりはするかと思います。その際はお気軽にTwitterやコメントなどでご連絡ください~

事前に色々説明

自動挿入プログラムの話の前に、色々説明しておくべきことがあるので先にそれを。

規約/ポリシー関係について

今回一番注意を払ったのはGoogleが提示する規約関連です。

特にAdSenseまわりは規約が厳しく、少しでも違反すると永久BANなんてことになりかねないので慎重に調べました。

関係がありそうなところは以下のような感じだと思っています。冗長だとは思いつつも、念の為全て引用して掲載しておきます。引用元はAdSense プログラム ポリシーAdSense 広告コードの修正より。

無効なクリックとインプレッション
サイト運営者様がご自身の広告をクリックしたり、手動または他の方法で表示回数やクリック数を作為的に増やしたりすることは禁止されています。

「表示回数」とあるので一瞬ヒヤッとしますが、不当な目的で表示回数を増やしているわけではないし、サイト運営者のために表示/クリックを推奨するものではありません。そもそもWordPressテーマなどPHPによるAdSenseコード出力と差異はないので問題ないと判断します。

広告の配置
Google では、サイト運営者様に広告のさまざまな配置や形式を検証するようおすすめしています。ただし、AdSense コードをポップアップ上、メール内、ソフトウェアの内部など、不適切な場所で使用することはできません。

問題なし。むしろお前達よりまともな場所に表示している

適切な広告配置
以下は許可されないページの一例であり、これらに限定されません。
(中略)
・サイト運営者様が提供したコンテンツよりも、広告の方が多いページ

今回作ったプログラムでは、コンテンツより広告の方が感覚的に多くなることは絶対にありません。この辺については次の項で説明しています。

禁止されているコードの改変方法
(一部抜粋)
・display:none などを使用して広告ユニットを隠す(ただし、レスポンシブ広告ユニットを実装している場合を除く)
・コンテンツが隠れてしまうような方法、またはコンテンツが広告を覆い隠すような方法で AdSense 広告コードを設定する
・モバイルサイトやレスポンシブ デザインのサイトでコンテンツと広告が重なるような方法で広告ユニットを配置する

一切抵触してません。
CSSでdisplay:none;を当ててしまうケースはありがちなので、今回に限らずみなさん注意しましょう。

最後、ちょっと趣旨が変わりますが「ラベル」について。

auto-ad-example-4

こういうやつですね。これ、よく勘違いされていますが記載は必須ではありません。

広告のラベル表示
AdSense の広告ユニットには、「広告」と「スポンサーリンク」のいずれかのラベルを表示できます。他の種類のラベルは、現時点では許可されません。詳細については、広告のプレースメントに関するポリシーをご覧ください。

「表示"してください"」ではなく「表示"できます"」なので、ラベルの記載は義務化されていないと取れます。屁理屈ではなく、規約にこうある以上それが絶対です。僕も何年もラベルは表示していませんが問題なくAdSenseのパートナーシップが続いています。

というわけで、今回のプログラムにはラベルの表示は含まれていません。

とは言ってもデフォルトでそうなっているだけで、表示したい場合はもちろん簡単に付け足せるのでご安心を。

考えられるデメリット

ほぼ思いつかないんですが、考えられるデメリットも一応(無理矢理に)上げてみます。

ページ表示速度が微妙に遅くなるかも たかが100行程度のコードで、しかもJSなので人間が体感できる速度は全く変わらないレベルと思います。PageSpeed Insightsの点数は保証できません(下がりにくい実装は後ろでお伝えします)。
本当に必要なタイミングでAdSenseを挿入する使い方はやりにくくなる AdSenseも広告なので、当然クリック後にユーザー行動が大きいほうが収益は上がります。その意味では「毎回挿入場所を手動で考えている人」には合わないかも。
挿入場所1つずつで広告ユニットを分けたい もちろん可能なんですが、僕自身が必要と思っていないためそのような実装はしていません。ご了承ください。

これくらいでしょうか…。適宜ご検討ください。

PHPからJavaScriptに変えた理由

PHPで書いていたコードをJavaScriptに変えた一番の理由は「サイトの表示速度」です。

単純にプログラミング言語としてJavaScriptの方が処理速度が圧倒的に速いというのはもちろん、

  • アルゴリズムの内容的にJavaScript(jQuery)の方が相性が良く、コードが短くなる
  • PHPはサーバー上で実行されるのに対してJavaScriptはユーザーのブラウザ上で実行されるので色んなメリットがある

などが大きな理由でした。

特に2つめは、「記事コンテンツの表示自体をまず邪魔しないこと」を思うと良い選択になったのではと思っています。詳しい説明は省きます。

このプログラムで得られるメリットは?

今回作ったこの機能を利用するとどういうメリットがあるのかまとめてみました。標準の自動広告を使っている状態なら、たぶんほとんどの方に当てはまるはず。

  • 文中(話の途中)での表示はなくなるので読者を阻害しない
  • 文中での表示だと「文を読み進めたい」ので視線は広告をスルーしがちだが、大きな見出し(h2)の前で一息ついたときなら広告に目が留まりやすくなる(かも)
  • 表示できる広告ユニットが上述の微妙なものではなく、自分の好きな広告ユニットに置き換えられる(2020年3月現在は新規のディスプレイ広告はほぼ一択なので、「スクエア」で「レスポンシブ」にするのが安定)
  • 自動広告は広告過多の印象があるけど、これを抑制できる。広告掲載率をこのためにいじってしまうとAdSense全体に影響があるのもまた悩ましいところ

結果、クリック率とクリック単価どちらも増加が見込めるのでは、と思ってます。

ちなみに4つめに関連して、「自動広告が出すぎてしまうのを広告掲載率で制御しよう」と思いがちですが、あそこでいじる数値は自動広告だけではなくAdSenseの広告ユニット全体に影響します。

むしろ「表示確率」とは違うイメージだと思うので注意しておきましょう(ソース)。

設計思想・プログラムの仕様

前置きが長くて申し訳ありませんでした。
ここからプログラム自体のお話です。

まず基本的な方針なんですが、「とにかくユーザーのことを第一に考える」以外にはなにもありません。

広告数や表示パターンを迷ったりした時も「まずは読者がコンテンツを読みやすいように、なるべく広告は出さない方向に」という指針にしてます(しきい値などはお好きなように設定できます)。

で、仕様は以下です。

  • 個別投稿ページでのみ動作
  • 好きな広告ユニットを使用可能
  • 1ページ内で表示する広告数は本文中のプレーンテキストの文字数と見出し(h2のみ)の数によって決まります(決定された広告表示数とh2タグのバランスが悪い場合は自動で少なめ方向に調整されます)
  • 広告数のパターンは0個~3個
  • なるべく本文を等分するような場所(に最も近いh2見出しの前)に広告が入る
  • 最初のh2の前には表示されない(既に個別で広告ユニットを置いていたり目次があることがほとんどなため)
  • 決定された挿入場所が最後のh2前だった場合は表示されない( 最後の見出しは「まとめ」など文章量も少ない上、記事下に別の広告があることが多いため)
    ※広告数が1のときは見出し1つ分手前にズレるだけで非表示にはしません

実際の掲載例を図に示すと、以下のような感じ。

position-auto-insert-my-create-function

「体感的に広告の存在を意識しにくくする」という感じになっているかと思います。

ソースコードと実装方法

おまたせしました。実際のコードと使い方です。

1.JavaScriptファイルとしてサーバーにアップロードする

functions.phpにコピペだけ、というわけにはいかないのでテーマディレクトリにアップロードする作業が必要です。

コードも掲載しますが、.jsのファイルごとダウンロードできるようにもしておきました。下記のボタンからどうぞ。

Download

$(document).ready(function () {
  const adCode = ''; //←の''の間に広告ユニットのコードを記入(改行とスペースの削除必須です)
  const entryContent = $(''); //←の''の間にコンテンツ本文を囲うclass名を記入([.]も!)
  let entryContentHTML = entryContent.html();
  entryContentText = entryContentHTML.replace(/(<(script|style)[^>]*?>(.*?|\n*?.*?\n*?)<\/(script|style)>)|<.*?>|\(adsbygoogle = window.adsbygoogle \|\| \[\]\).push\({}\);/gim,"");
  entryContentText = entryContentText.replace(/(\s+?)|(\n+?)|(\r+?)|(\t+?)/gim,"");
  entryContentText = entryContentText.replace(/\[.+?\]/gim,"");
  let charLength = entryContentText.length;
  let htmlLength = entryContentHTML.length;
  let h2Tags = entryContent.find("h2");
  let h2Size = h2Tags.length;
  let h2Array = [];
  for (let i = 0; i < h2Tags.length; i++) {
    h2Array.push(h2Tags[i]);
  }
  let adSize = 0;
  if (charLength <= 2500) { //この文字数(2500)以下のときは広告を表示しない
    return;
  } else if ((charLength > 11800) && (h2Size >= 5)) { //11800文字より多いときは広告数3
    adSize = 3;
  } else if ((charLength > 7200) && (h2Size >= 4)) { //7200文字より多いときは広告数2
    adSize = 2;
  } else if ((charLength > 2500) && (h2Size >= 3)) { //2500文字より多いときは広告数1
    adSize = 1;
  } else {
    return;
  }
  let h2CharNumber = [];
  let indexOffset = 0;
  for (let i = 0; i < h2Size; i++){
    h2CharNumber[i] = entryContentHTML.indexOf("<h2",indexOffset);
    indexOffset = h2CharNumber[i] + 3
  }
  let resultInsertPosition_1 = 0;
  let resultInsertPosition_2 = 0;
  let resultInsertPosition_3 = 0;
  let slicePoint = 0;
  switch (adSize) {
    case 1:
      slicePoint = htmlLength / 2;
      for (let i = 0; i < h2CharNumber.length; i++){
        if (slicePoint < h2CharNumber[i]) {
          resultInsertPosition_1 = i + 1;
          break;
        }
      }
      break;
    case 2:
      slicePoint = htmlLength / 3;
      for (let i = 0; i < h2CharNumber.length; i++){
        if (slicePoint < h2CharNumber[i]) {
          resultInsertPosition_1 = i + 1; 
          break;
        }
      }
      slicePoint *= 2;
      for (let i = 0; i < h2CharNumber.length; i++){
        if (slicePoint < h2CharNumber[i]) {
          resultInsertPosition_2 = i + 1; 
          break;
        }
      }
      if(resultInsertPosition_1 == resultInsertPosition_2) {
        resultInsertPosition_2++;
      }
      break;
    case 3:
      slicePoint = htmlLength / 4;
      for (let i = 0; i < h2CharNumber.length; i++){
        if (slicePoint < h2CharNumber[i]) {
          resultInsertPosition_1 = i + 1; 
          break;
        }
      }
      slicePoint *= 2;
      for (let i = 0; i < h2CharNumber.length; i++){
        if (slicePoint < h2CharNumber[i]) {
          resultInsertPosition_2 = i + 1; 
          break;
        }
      }
      if(resultInsertPosition_1 == resultInsertPosition_2) {
        resultInsertPosition_2++;
      }
      slicePoint *= 1.5;
      for (let i = 0; i < h2CharNumber.length; i++){
        if (slicePoint < h2CharNumber[i]) {
          resultInsertPosition_3 = i + 1;
          break;
        }
      }
      if(resultInsertPosition_2 == resultInsertPosition_3) {
        resultInsertPosition_3++;
      }
      break;
  }
  resultInsertPosition_1--;
  resultInsertPosition_2--;
  resultInsertPosition_3--;
  switch (adSize) {
    case 1:
      if (resultInsertPosition_1 >= h2Size-1) {
        ($("h2").eq(resultInsertPosition_1 - 1).before(adCode));
      } else {
        ($("h2").eq(resultInsertPosition_1).before(adCode)); 
      }
      break;
    case 2:
      ($("h2").eq(resultInsertPosition_1).before(adCode));
      if (resultInsertPosition_2 != h2Size-1) {
        ($("h2").eq(resultInsertPosition_2).before(adCode));
      }
      break;
    case 3:
      ($("h2").eq(resultInsertPosition_1).before(adCode));
      ($("h2").eq(resultInsertPosition_2).before(adCode));
      if (resultInsertPosition_3 != h2Size-1) {
        ($("h2").eq(resultInsertPosition_3).before(adCode));
      }
      break;
  }
});

次で各種値の設定などをするので、アップロードはちょっと待ってくださいね。

2.ユーザー設定を行う

コードが手元に来たら、適宜必要な部分を編集します。
みなさん側で編集する必要があるのは以下です。

  • 挿入したい広告コードを書き込む
  • お使いのWordPressテーマで動作するようにclass名を書き込む
  • 広告数を0~3個に決めるための文字数のしきい値を決める(変更しなくても可)

1つずつ説明します。

挿入したい広告コードを書き込む

2行目にあるconst adCode = ' ここ! ';に、表示させたいAdSenseの広告コードを記入してください。

貼り付ける際に改行と半角スペースは全て削除してください。

例えばこういう感じになります↓

const adCode = '<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-0000000000000000" data-ad-slot="0000000000" data-ad-format="auto" data-full-width-responsive="true"></ins><script>(adsbygoogle = window.adsbygoogle || []).push({});</script>'; //←の''の間に広告ユニットのコードを記入(改行とスペースの削除必須です)

お使いのWordPressテーマで動作するようにclass名を書き込む

本文を取得するためにclass名を記入する必要があります。

ブラウザの「デベロッパーツール」を使って本文を囲んでいるdiv要素のclass名を調べてください。

get-class-name-entry-content

取得するclass名は「enrty」や「content」など、メインコンテンツの本文を囲む用のclass名かどうかに注意してください。

慣れない方にはちょっと敷居の高い作業かもしれないため、様子を見て解説をより詳しくするか検討させていただければと思います。

みるみ
みるみ

サイトのURLをご提示いただければコードの編集はお手伝いします!

それを3行目にあるconst entryContent = $(' ここ! ');[.](ピリオド)を付けて記入してください。

例えばCocoonだと下記のようにすればOKです。

const entryContent = $('.entry-content'); //←の''の間にコンテンツ本文を囲うclass名を記入([.]も!)

広告数を0~3個に決めるための文字数のしきい値を決める(変更しなくても可)

17行目~23行目で文字数のしきい値を変更できます。

Threshold-char-length

デフォルトでは

  • 2500文字以下は広告数が0
  • 2500文字~7200文字だと広告数が1
  • 7200文字~11800文字だと広告数が2
  • 11800文字以上は広告数が3

という風になっています。

自分のブログの文字数やAdSenseのレポートなどをそれなりに見つつ決めた数字なので、特にこだわりがなければ変更しなくても良いと思います。

なお「最初と最後のh2見出し前には表示しない」という仕様上、

  • 広告数がのときはh2見出しが最低つ必要
  • 広告数がのときはh2見出しが最低つ必要
  • 広告数がのときはh2見出しが最低つ必要

という風になっています。見出しの数が上記より足りないときは広告は出力しません。

3.アップロードする

編集が終わったらアップロード。

できあがったJavaScriptファイルを子テーマ直下などに配置しましょう。FTPソフトでもサーバーのFTPクライアントでもOKです。

4.テンプレートファイルから読み込むようにする

最後に、アップロードしたJavaScriptファイルがWordPressから読み込まれるようにします。

これにはテンプレートファイルを直接編集する必要があるので、footer.phpなどをダウンロードして用意してください(テーマで好きなJavaScriptファイルを読み込めるような機能がある場合はそれを使っても構いません)。

今回はfooter.phpを例にします。

下記コードを貼り付けます。

<script defer src="/wp-content/themes/[自分のテーマフォルダ名]/auto-adsense.js"></script>

例えば僕なら

<script defer src="/wp-content/themes/cocoon-child-master/auto-adsense.js"></script>

となります。

[自分のテーマフォルダ名]はさっきJavaScriptファイルをアップロードしたフォルダ名と同じものです。

貼り付け場所はどこでもいいですが、テーマによってはjQueryの読み込みが後ろの方で行われていることも多いので、できるだけ</body>の閉じタグに近いところがいいでしょう。

5.動作確認

作業が完了したら動作確認をお願いします。

新しい広告ユニットを設置したわけではない限り、即座にAdSenseが各h2見出しの前に表示されていると思います。反映の確認の際はキャッシュ削除を忘れずに(特にキャッシュ系プラグイン!)

おわりに

以上です。お疲れさまでした。

この際に言っておきたいんですけど、G○○gleさんは「ユーザー目線を忘れずに」とか「ファーストビューには広告を置くな」とか色々言うわりには、その自動広告の仕様はどうなってんだよぉ!!

…あんまり言って垢BANってのだけは勘弁してほしいのでこのくらいにしておきます。

ちなみに、このプログラムで挿入している広告ユニットはめちゃめちゃ収益を上げてくれています。まあ純粋な本文中のみの自動広告と比較はできないのでなんとも言えないデータではありますけど…。

ではおわりでーす!

お役に立てましたらぜひシェアをお願い致します~

みるみ
みるみ

ブロガー、ソフトウェアエンジニア。

文章を書くのが好きです。サイトは全部自分でつくっています。

この記事へのコメント
コメントはまだひとつもありません :)

新しいコメントを書く

  • 必須項目はコメント本文のみですが、お名前はぜひご記入いただけると嬉しいです。
    ※メールアドレスを書いた場合も公開されることはないのでご安心ください。
  • 特定のコメントに返信したい場合は各コメントにある「返信する」ボタンからどうぞ。
  • コメントはこちらで承認の作業を行うまでは表示されません。ご了承ください。
    ※ここ数年スパムが激化しており、誤って削除されてしまうケースが増えてきました。スパムボックスも毎日自分の目で確認するようにはしているのですが、どうしても限界があります。確実に僕に連絡を取りたい方は メールTwitter からお願いします。