新しいAdSenseコードでアドセンス遅延読込
筆者は今まで、「GoogleAdSenseの遅延読込みでページ表示速度を改善」を参考に、AdSenseの遅延読み込みを行っていたのですが、「AdSenseの新しい広告コード」が登場し、それをどうやって遅延読み込みに適用させればいいかわからなかったので、調べてみました。
適用させる方法は見つかったのですが、その過程でAdSenseだけでなく他のHTMLやスクリプト、CSSなどを遅延読み込みできるライブラリを見つけたのでそちらの使い方も合わせて紹介しています。
遅延読み込み
従来型の遅延読み込みにAdSenseの新しいコードを適用する方法はStack overflowに紹介されていました。
ちなみに従来は、アドセンスのコード内のscriptタグを除去したうえで、次のようなコードをbodyを閉じる前に追加していました。
sample1.html
<script>
(function(window, document) {
//adsense用スクリプト読み込み
function main() {
let script = document.createElement('script');
script.src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js";
script.async=true;
script.dataset.adClient = 'ca-pub-xxxxx';
document.getElementsByTagName('head')[0].appendChild(script);
}
// 処理状態を記憶するフラグ
var lazyLoad = false;
// 重複呼出回避のためのイベント解除
function onLazyLoad() {
if (lazyLoad === false) {
lazyLoad = true;
window.removeEventListener('scroll', onLazyLoad);
window.removeEventListener('mousemove', onLazyLoad);
window.removeEventListener('mousedown', onLazyLoad);
window.removeEventListener('touchstart', onLazyLoad);
window.removeEventListener('keydown', onLazyLoad);
main();
}
}
// なにかアクションのあった際に読み込みを開始するようにイベント設定
window.addEventListener('scroll', onLazyLoad);
window.addEventListener('mousemove', onLazyLoad);
window.addEventListener('mousedown', onLazyLoad);
window.addEventListener('touchstart', onLazyLoad);
window.addEventListener('keydown', onLazyLoad);
window.addEventListener('load', function() {
// ドキュメント途中 or 更新時 or ページ内リンク;
if (window.pageYOffset) {
onLazyLoad();
}
});
})(window, document);
</script>
このmain関数を次のように変更することで、新しいAdSenseコードに対応します。
function main() {
let script = document.createElement('script');
script.src='https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client="ca-pub-xxxxx"';
script.async=true;
script.setAttribute('crossorigin', 'anonymous');
document.getElementsByTagName('head')[0].appendChild(script);
}
LazyHTML
Guest Blogに紹介されていた、「LayzyHTML」を利用すると、画像の遅延読み込み同様にビューポートにAdSense要素が近づいた時に読み込まれるようになります。またこれはAdSenseだけでなく画像などのHTML要素やスクリプト、CSS(styleタグ)の遅延読み込みにも利用できます。
先のGuest BlogではLazyHTMLの使い方として、headでAdSenseのスクリプトを読み込み、元のアドセンスのタグ部分からscriptタグを除去し、残ったコードをLazyHTML用のタグで囲む方法を紹介していました。これは後で述べるような問題がありますが、ほとんどの部分はこのまま利用できますので先にこのコードに沿ってソースを紹介します。
筆者の環境はBloggerですのでその際の注意点を記述しておきます。まずテンプレートを編集する場合は、値のない属性を記述できないため「async="true"」や「data-lazyhtml="true"」として仮の値を設定する必要があります。
また同じくテンプレートを編集する場合にですが、<!-- コメント -->で囲まれた範囲の内容はページ表示時には出力されないのですが、LazyHTMLはコメントアウトした内容が必要です。そのためタグをエスケープして、<!-- LazyHTML用コメント -->とする必要があります。
Bloggerのテンプレートの編集でない場合は、「="true"」という仮の値は不要です。またLazyHTML用のコメント部(下のコードの赤線の箇所)もそのまま<!--や-->として下さい。
sample2.html
...
<head>
...
<script async='true' crossorigin='anonymous' src='https://cdn.jsdelivr.net/npm/lazyhtml@1.0.0/dist/lazyhtml.min.js'/>
<script async='true' src='https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client="ca-pub-xxxxx"'/> crossorigin="anonymous"></script>
<div class="lazyhtml ad-wrapper-1" data-lazyhtml="true">
...
<body>
...
<script type="text/lazyhtml">
<!--
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-xxxxx"
data-ad-slot="yyyyy"
data-ad-format="auto"
data-full-width-responsive="false"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
-->
</script>
</div>
問題は、上記のコードのようにheadでAdSenseのスクリプトをasyncで読み込むと、従来型の遅延読み込みよりPageSpeed Insightsのスコアが落ちることです。
asyncで記述されたスクリプトの読み込み終了までブラウザがLoading状態になり、その遅延を計測されるのが原因だと思われます。それを切り離すには、AdSenseのスクリプト読み込みもlazyHTML用のコメントの中に含めてしまえばいいのですが、そうすると今度は別の問題が発生しました。
それは、ふたつ以上AdSenseを設置しているとふたつめの以降のLazyHTMLの処理の際に、「error: Only one AdSense head tag supported per page」というエラーがでることです。これに対処するには一番最初に表示される場所以外はそのAdSenseのスクリプトを読み込むコードを消してしまえばいいのですが、読み込まれる順番が常に一定とは限りません。レスポンシブデザインで入れ違うこともあれば、リロードでページ下部が先に表示されることもあると思います。
そこでコードにフラグを設けて読み込みされていない時だけ動的にスクリプトを読み込むようにしました。
sample3.html
...
<head>
...
<script async='true' crossorigin='anonymous' src='https://cdn.jsdelivr.net/npm/lazyhtml@1.0.0/dist/lazyhtml.min.js'/>
<script async='true' src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-xxxxx" crossorigin="anonymous"></script>
<div class="lazyhtml ad-wrapper-1" data-lazyhtml="true">
...
<script type="text/lazyhtml">
<!--
<script>lazyHtmlSub();</script>
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-xxxxx"
data-ad-slot="yyyyy"
data-ad-format="auto"
data-full-width-responsive="false"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
-->
</script>
</div>
...
<script>
//遅延読み込み補助
let adsLoad = false;
const lazyHtmlSub= async ()=> {
if (adsLoad == false) {
let script = document.createElement('script');
script.src='https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client="ca-pub-xxxxx"'
script.async=true;
script.setAttribute('crossorigin', 'anonymous');
document.getElementsByTagName('head')[0].appendChild(script);
adsLoad = true;
}
}</script>
【補足】Cross Origin
ちなみに最近CDNの記述でよく見るようになったcrossorigin属性ですが、これはCORS(オリジン間のソース共有)のリクエストを構成するものです。オリジンとはドメインとプロトコル(http/https)の組み合わせです。
これが「anonymous」になっている際は、異なったオリジンに対しクッキーやSSL証明書等のユーザー情報は送信されません。
「use-credentials」を設定すると異なったCORSのために資格情報を利用します。
エラーの解消
LazyHTMLを利用したら、今まで原因不明で放置してきた
the server responded with a status of 400
のエラーが消えました。