Jul 16, 2005
ページレンダリングを妨げない広告挿入手法に関する覚書
多分わかる人にはわかると思うんだけど、わかんない人にはわかんないと思うので、誰かわかりやすく書き直してくれると助かるんだけどとりあえず書いておく。例えば、GoogleAdsenseなんかで広告を挿入するには、外部ドメインに置いたJavaScriptを読み込んで使う。セキュリティ上の問題があるにもかかわらず外部ドメインのJavaScriptをそのドメインにあるかのように取り込めるのは、多分、そういう需要があるからだろう。
んで、そういうスクリプトの構成というのは大抵、scriptタグを挿入した位置に広告がdocument.writeを使って書き出される、というものだ。
しかしこの方法には問題があって、それはscriptがロードされて実行が完了するまでページのレンダリングが止まる、ということだ。jsファイルを受信するまでにかかる時間と、解釈と実行、document.writeでブラウザに出力する、この間ブラウザはscriptタグを挿入した位置でHTMLをぶった切って表示できる範囲まで表示する、という動作をする。
例えば
-ヘッダ
-広告
-本文
というような順番でページを構成した場合、広告JavaScriptがロードされて、実行完了するまで5秒かかったら、本文が表示されないまま5秒間ユーザーは待たされることになる。
もし、
-ヘッダ
-本文
-サイドバー
というような後置型サイドバーの構成で、サイドバーに広告を入れる場合は、本文が先に表示されるので、ユーザーを待たせずに本文を読むことが出来る。広告JavaScriptのロードに5秒かかっても、とりあえず本文を先に読むことが出来る。
という違いがある。
GoogleAdsenseなんかをページに挟んでいる場合、その場所で若干レンダリングがもたつくのを体感したことのある人は多いはず、多いと思う。これはブラウザの正常な挙動である。scriptの実行が完了するまでページ全体がどういう構成になるのかわからないのだから仕方ない。
GoogleAdsenseの広告挿入スクリプトは、これだ。
http://pagead2.googlesyndication.com/pagead/show_ads.js
Googleの取っている手法は
-jsファイルは動的に生成しないで、共通のコードを使う。
-本体HTML側で指定したパラメータに応じてIFRAMEを生成する
つまり固定のJavaScriptで、動的に生成されたIFRAMEを埋め込んでいるわけだ。jsファイルに対してはブラウザのキャッシュが最大限利くようになる。とりあえず最速でjsファイルは渡しておいて、動的に生成されたIFRAMEが表示される。IFRAMEの中の表示が多少遅れても、ページのレンダリングには影響を与えずにすむ。
これはJavaScript自体を動的に生成するよりも、若干スマートである。JavaScript自体を動的に生成してしまうとブラウザのキャッシュが利かないのでページ毎に毎回ダウンロードする必要がある。
しかし、いずれにせよshow_ads.jsがキャッシュされていなかった場合は、jsファイルをダウンロードするまでに若干の時間がかかることになる。またIFRAMEを挿入するためにページのレンダリングはそこでいったん止まる。Googleのサーバーはレスポンスが速いので、気にしている人は少ないと思うけれど、もしこれが0.1秒でなくて1秒~2秒程度の遅延があるなら、明確に広告挿入はユーザーのストレスと結びつく。
これはテーブルレイアウトだとレンダリングが遅いとか、そういうのと同系統の問題なんだけど、あんまり触れられていないような気がする。外部サーバーに置いてある画像を直リンクで表示する場合は、サーバーのレスポンスが遅くてもとりあえずページ全体のレンダリングは出来るようになっている。しかし、外部サーバーに置いてあるスクリプトを取り込む場合、一番レスポンスが遅いサーバーにページの描画全体が引きずられることになる。
しかし、このページのレンダリングが遅れるという現象は、コードの書き方を少し工夫すれば解消することが出来る。
----
どうすればいいのか、というと。
広告表示用の領域を、あらかじめ固定の幅と高さで作っておいてやり、scriptのロードが完了したらその領域をスワップする、という方法であればjsファイルのロードが遅れたとしてもページのレンダリングを妨げることは無い。
例えば俺だったら
本体HTMLの側で
ADS_TARGET_ID = "任意のID"
広告JavaScriptの側で
document.getElementById(ADS_TARGET_ID).innerHTML = 広告HTML
というような作りにするだろう。
innerHTMLじゃなくてappendChildでもいいけど。
id=ADS_TARGET_IDの領域はスタイルシートを使ってあらかじめ表示される広告のサイズに合わせておけば、不要な再描画を避けることが出来るはずだ。
script要素にはdefer属性を指定しておく。defer属性が付いていれば、スクリプトのロードを待たずにページをレンダリングすることが出来る。
document.writeは確かにscriptの挿入位置が広告挿入位置でわかりやすいけれど、サーバーのレスポンスが遅ければ広告が挿入されているページの表示全てに支障をきたすので、そろそろやめにしてもいいんじゃないの、っていう。
これは広告だけの話ではなくて、例えばJavaScriptを使ってRSSのヘッドラインを貼り付けるようなサービスなんかでも同じことが言える。
まあ、そういう提案なんだけども、
具体的になんか作らないと説得力無いので、続く。
Edit this entry...
wikieditish message: Ready to edit this entry.
A quick preview will be rendered here when you click "Preview" button.