Google Adsenseの検索ユニットには検索結果の表示方法が3つあり、iframe を使用して自分のウェブサイトに表示する方法を選択して実装した時に検索結果が表示されないという症状に陥いる場合がある。その時の解決方法を備忘録として残しておこう。

Googleカスタム検索の結果がiframeに表示されない時

まず、検索ユニットを設置したウェブサイトがSSL対応しているかどうかが重要だ。特に、ローカルや開発環境がSSL対応してないけど、本番環境はSSL対応だったりすると、試験してた時は動いていたのに、いざ本番にアップしたら動かない…という事態にもなり易い。

──というわけで、一番最初に行ってほしいのは、実際にサイト内に設置したGoogle Adsenseの広告コードがSSL対応されているかどうかを確認することだ。もしSSL非対応のサイトでこの症状が起きている場合、おそらくは広告コードの記述ミスが原因だろうと思われる。

Adsenseの管理画面で発行される検索ユニットの初期コードは下記のようになっている。

1. 検索ボックス(BEFORE)

<form action="https://www.example.com/search-results/" id="cse-search-box">
  <div>
    <input type="hidden" name="cx" value="partner-pub-xxxxxxxxxxxxxx:yyyyyyyyyyy" />
    <input type="hidden" name="cof" value="FORID:zz" />
    <input type="hidden" name="ie" value="UTF-8" />
    <input type="text" name="q" size="55" />
    <input type="submit" name="sa" value="検索" />
  </div>
</form>

<script type="text/javascript" src="http://www.google.co.jp/coop/cse/brand?form=cse-search-box&lang=ja"></script>

2. 検索結果(BEFORE)

<div id="cse-search-results"></div>
<script type="text/javascript">
  var googleSearchIframeName = "cse-search-results";
  var googleSearchFormName = "cse-search-box";
  var googleSearchFrameWidth = 800;
  var googleSearchDomain = "www.google.co.jp";
  var googleSearchPath = "/cse";
</script>
<script type="text/javascript" src="http://www.google.com/afsonline/show_afs_search.js"></script>

私のサイトのようにSSL対応のサイト(上記の検索ボックスコード中でformタグのaction属性がhttps://~となるようなサイト)にこの初期コードを埋め込んでしまうと、Mixed Contentsのスクリプトエラーが発生して検索結果が表示されなくなる。

つまり、検索結果ページとして指定したhttps://~(上記の例だとhttps://www.example.com/search-results/)にhttp://www.google.co.jp/~からスクリプトを読み込もうとして「1つのページ内にHTTPとHTTPSのコンテンツが混在しているよ」と怒られるわけだ。

そこで、Googleの公式ヘルプ「SSL 対応の AdSense 用広告コード」の通りに、広告コードのSSL対応を行ってあげる。上記のBEFOREの例をSSL対応コードに直すと下記のようになる。

1. 検索ボックス(AFTER)

<form action="https://www.example.com/search-results/" id="cse-search-box">
  <div>
    <input type="hidden" name="cx" value="partner-pub-xxxxxxxxxxxxxx:yyyyyyyyyyy" />
    <input type="hidden" name="cof" value="FORID:zz" />
    <input type="hidden" name="ie" value="UTF-8" />
    <input type="text" name="q" size="55" />
    <input type="submit" name="sa" value="検索" />
  </div>
</form>

<script type="text/javascript" src="//www.google.co.jp/coop/cse/brand?form=cse-search-box&lang=ja"></script>

2. 検索結果(AFTER)

<div id="cse-search-results"></div>
<script type="text/javascript">
  var googleSearchIframeName = "cse-search-results";
  var googleSearchFormName = "cse-search-box";
  var googleSearchFrameWidth = 800;
  var googleSearchDomain = "www.google.co.jp";
  var googleSearchPath = "/cse";
</script>
<script type="text/javascript" src="//www.google.com/afsonline/show_afs_search.js"></script>

それぞれのスクリプトタグのsrc属性のURLからhttp:の部分を取り除くだけだ。
これで、ソースのインクルードを行う際にブラウザが最適なプロトコルを自動で補完してくれるようになる。

しかし、これだけだと検索結果ページに自動でレンダリングされるiframeタグのsrc属性のURLまでは変更されない(最初はブラウザのキャッシュかと思ったが、何度やってもダメだったので、Google Adsenseのバグではないかと思われる)。つまり、検索結果ページには下記のようなHTMLが生成されてしまい、Mixed Contentsエラーで検索結果が表示されないのだ。

<div id="cse-search-results">
<iframe name="googleSearchFrame" src="http://www.google.co.jp/cse?cx=partner-pub-xxxxxxxxxxxxxx%3Ayyyyyyyyyyy&cof=FORID%3Azz&ie=UTF-8&q=keyword&sa=%E6%A4%9C%E7%B4%A2&siteurl=www.example.com%2F&ref=www.example.com%2Fsearch-unit%2F&ss=527j94689j4&ad=n9&num=10&rurl=https%3A%2F%2Fwww.example.com%2Fsearch-results%2F%3Fcx%3Dpartner-pub-xxxxxxxxxxxxxx%253Ayyyyyyyyyyy%26cof%3DFORID%253Azz%26ie%3DUTF-8%26q%3Dkeyword%26sa%3D%25E6%25A4%259C%25E7%25B4%25A2%26siteurl%3Dwww.example.com%252F%26ref%3Dwww.example.com%252Fsearch-unit%252F%26ss%3D527j94689j4" frameborder="0" width="800" height="1860" marginwidth="0" marginheight="0" hspace="0" vspace="0" allowtransparency="true" scrolling="no"></iframe>
(以下略)

──であれば、自動でレンダリングされるiframesrc属性をウェブ側から修正してあげれば良い。サイト側のJavaScriptに下記のスクリプトを追加してみた(下記の例ではjQuery使っている)。

if ( $('#cse-search-results').size() > 0 ) {
  if ( $('iframe[name="googleSearchFrame"]').size() > 0 ) {
    var ifsr = $('iframe[name="googleSearchFrame"]');
    var loadSrc = ifsr.attr('src');
    ifsr.attr('src', loadSrc.replace( 'http:', '' ));
  }
}

Google Adsenseが自動生成するiframesrc属性のURLにhttp:の記述があったら削除するという処理だ。SSL非対応のHTTPプロトコルではHTTPSコンテンツが混在していてもMixed Contentsエラーは起きないのでhttp:固定処理で構わない。

これで、SSL対応サイト内にもGoogle Adsenseの検索ユニットで検索結果が表示されるようになった(少々強引だが…)。

この強引な対応だけだと、ページの初回読み込み時にはMixed Contentsエラーが起きてしまうのは防げない。まぁ、大元のGoogle Adsenseでそのうち対応されると思うのでそれまでの暫定的な対処だ。ただ、もしGoogle Adsense側で対応された後でもこの暫定対処スクリプトはそのまま残しておけるので、一度対応しておけば放置していても構わない(ハズだ)。

おまけ

ついでに、Google Adsenseの検索ユニットの検索結果の表示領域(横幅)をレスポンシブ対応させるやり方を紹介しておこう。Google Adsenseで検索結果を「iframe を使用して自分のウェブサイトに表示」にすると横幅が指定できるのだが、固定値での指定になってしまい扱いづらい。
そこで、サイト側のJavaScript(jQuery)で表示域をレスポンシブ化するのだ。

まず、検索結果表示用の検索コードを下記のように変更する。

<div id="cse-search-results"></div>
<script type="text/javascript">
  var googleSearchIframeName = "cse-search-results";
  var googleSearchFormName = "cse-search-box";
  var googleSearchFrameWidth = $('#cse-search-results').width();
  var googleSearchDomain = "www.google.co.jp";
  var googleSearchPath = "/cse";
</script>
<script type="text/javascript" src="//www.google.com/afsonline/show_afs_search.js"></script>

次に、サイト側のJavaScript(jQuery)に下記を追加する。

var adjustAdsenseSearchResults = function(){
  if ( $('#cse-search-results').size() > 0 ) {
    if ( $('iframe[name="googleSearchFrame"]').size() > 0 ) {
      var ifsr = $('iframe[name="googleSearchFrame"]');
      ifsr.attr('src', loadSrc.replace( 'http:', '' )).attr( 'width', $('#cse-search-results').width() ).css({ width: $('#cse-search-results').width() + 'px' });
    }
  }
};
$(window).on('load resize', function(){
  adjustAdsenseSearchResults();
});

これで、ページが読み込まれたりリサイズされた時に検索結果のiframeの横幅が調整されるようになる。

一般的にサイト内検索は、パフォーマンス的にもマネタイズ的にもGoogle Adsenseの検索ユニットを利用した方がメリットが多い。もしあなたのサイトのサイト内検索が自前のスクリプトに依存しているのであれば、Google Adsenseの検索ユニットへの変更を検討してみてはどうだろうか。