AdSenseのレスポンシブ広告ユニットを使わずにレスポンシブに対応させる:メモ

悩み
悩み

以前作ったiframeのレスポンシブ対応を少し改造してAdSenseでもうまく動くようにしたコードを作りました。

ただ、AdSenseが現在の構造のままならという条件付きですので、完全なものではありません。

反面単純な作りではありますので、構造が変わっても対応しやすいとは思います。

構築環境
JavaScriptjQuery

実現したいこと

実現したいことは以下の通りです。

  • AdSenseでコンテンツ幅を越える広告を使用(レクタングル大など)
  • AdSenseのレスポンシブ広告ユニットは使わない
  • iPhone4や5のサイズではみ出ないようにする

AdSenseで用意されているレスポンシブの広告を使えば済む話ではあります。しかし、実験サイトではレスポンシブにするとクリック数も単価も落ちる傾向があったため、可能ならレクタングル大を使いたいと考えた次第です。

余談ですが、きれいにレイアウトされているブログさんでも、iPhone4のサイズで見るとスマホ表示が崩れている(横幅が収まっていない)場面がわりと見受けられます。
そういう場合、「AdSenseがはみ出ている」という原因がそれなりの割合を締めるように思います。もちろん、iPhohe4サイズを切り捨てているのであれば余計なお世話ですが。

前提

以下の構造であることを前提としています。


<div class='contents'>
 <p>※文章や画像なのどのコンテンツ</p>
 <p>※文末にAdSense</p>
 <script type='text/javascript'>※AdSenseのIDなど</script>
 <script type='text/javascript' src='http://pagead2.googlesyndication.com/pagead/show_ads.js'></script>
 <ins>
  <ins>
   <iframe>※Adsenseの広告</iframe>
  </ins>
 <ins>
</div>

上記は概ねの略図みたいなものですが、現在のAdSenseはscriptタグ2つの次にinsが並ぶ配置でした。

今回はこのinsが曲者で、2つや3つだったり、insにclassかidのいずれかがあったりするようで…。
このinsに横幅が設定されていたために、その一番外側のinsの上からラッピングしなければならないのですが、それを特定する手段がなかなか見つかりませんでした。

コード

いろいろ悩んで、以下のコードに落ち着きました。基本的には以前の「[改]画像一枚だけの別ドメインページをiframeで読み込みレスポンシブに対応:メモ」を利用しています。


<script type='text/javascript'>
jQuery(function($){
 $('ins:has(iframe)').not('ins > ins').wrap('<span class='adsense-wrap'></span>');
 function divide(num){
  var num1 = num * 10000;
  num1 = Math.round(num1) / 10000;
  return num1;
 }
 $(window).on('load resize orientationchange', function(){
  $('.adsense-wrap').each(function(){
   var adsenseWidth = parseInt($(this).children('ins').css('width'));
   var adsenseHeight = parseInt($(this).children('ins').css('height'));
   var baseWidth = $(this).parent().width();
   var thisWidth = baseWidth / adsenseWidth;
   var ratio = divide(thisWidth);
   if (ratio > 1){
    var ratio = 1;
   }
   var setAdsenseHeight = adsenseHeight * ratio;
   $(this).children('ins').css({'transform':'scale('+ ratio +')','-webkit-transform':'scale('+ ratio +')','-moz-transform':'scale('+ ratio +')','-ms-transform':'scale('+ ratio +')+','transform-origin':'0 0'});
   $(this).css({'height': setAdsenseHeight +'px','width': baseWidth +'px','overflow':'hidden','display':'block'});
  });
 });
});
</script>

前述の一番外側の親要素であるinsを指定するためには以下のコードを用いました。
iframeを子孫要素に持ち、かつ、insの子要素ではないins」という指定方法です。


$('ins:has(iframe)').not('ins > ins').wrap('<span class='adsense-wrap'></span>');

この指定法も完璧ではなく、AdSense以外でinsの中にiframeが存在するパーツがあれば反応してしまいます。
そのため上記コードを利用する際は、そういった問題が起きないことを確認してからになります。

仮に構造が変わる場合は、この部分を変更して「AdSenseでwidthを指定しているもっとも外側の要素」を特定する内容に書き換えることで対応可能です。

なお、現時点では大外のins.adsbygoogleというクラスが設定されるようですから、下記のコードでも対応可能かもしれません。


$('ins.adsbygoogle').wrap('<span class='adsense-wrap'></span>');

css.(‘width’)は文字列

css.('width')で取得できる値が数値ではなく文字列である点に気づかず悩んでしまいました。consoleで変数の中身を表示させた際にはしっかりとダブルクォーテーションに囲まれて知らせてくれていましたのに…。

以下のコードのparseIntで数値に変えて変数に放り込むことで解決です。


var adsenseWidth = parseInt($(this).children('ins').css('width'));

別の指定方法

上記のコードのinsを特定する指定では、以下のコードも一応動きます。


$('script[src*='googlesyndication'] + ins').wrap('<span class='adsense-wrap'></span>');

AdSenseからコードをそのままコピペする場合はinsの直前にscriptタグが存在する構造のため、一番外側のinsを指定するためにそのscriptタグを利用する指定方法です。

とはいえ、これも今後もそうかといえばそうだと言い切れず。また、insのように入れ子でそれ自体の構造を加味した指定ではなく、隣接する要素との関係性で指定していますから、脆い指定法かもしれません。

以前のiframeのコードと併用する場合

以前のiframeのコードと併用する場合は以下のように以前のコードにnotで除外指定を行えば大丈夫なはずです。

単純に、insの中にあるiframeを除外すれば良いだけですから。


$('.contents iframe').not('ins iframe')

結び

ともかく一番外側の要素さえ特定できれば解決は早かったのですが、その特定が困難だと遅々として進みません。
仮に今確定的な指定法があったとしても、今後もそうだとは限りませんし。

とはいえ冒頭で述べたように、構造が変わっても変更自体はそれほど難しくありません。今回のように(悩んでしまいましたが)指定方法をその時々で作ればよいのですから、現時点で判明している範囲での汎用的な指定をするしかないのかなと。

0人がこの記事を評価

役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。

連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。

コメント欄