ちょっとよろしくないGoogle AdSenseの遅延ロード用コードが蔓延している件

 こんにちは、その日暮らしです。

 今回は、Google AdSenseの遅延ロードのお話です。

 思いがけずGoogle AdSenseに合格したお話を先日したと思います。

 早速、Google AdSenseの広告を貼ったところまではよかったのですが、そのあと、Googleの監査ツールであるLighthouseで当ブログのページを測定してみたところ、測定値のうちPerformanceの結果が爆下がりしていることに気づきました。

 以前少しだけLighthouseにハマっていたことがあって、どのページの測定結果もほぼ満点になるまでチューニングしたはずなのですが(モバイルは除く)、Google AdSenseのおかげで(笑)ダメダメになってしまいました。

 その対策としてはGoogle AdSenseで使われているJavaScriptを遅延ロードさせるという手法が有名だそうで、今回は、その手法で使われているコードを使ってみて気づいた点をお話ししたいと思います。

目次

遅延ロード

 LighthouseのPerformanceの測定値がぼろぼろな件についての対策はすぐに見つけることができました。

 Google AdSenseで使われているJavaScriptを遅延ロードするよう変えればよいようです。

 早速ネットで見つけたコードを自分なりにリファクタリングし、使っているテーマのheader.phpに貼ります(当ブログのCMSはWordPress)。

 JavaScriptといえばなにかユーザーに警告するためにalert()を使うくらいだけだった時代の人間としては、最近のJavaScriptの記法にはついていけません。なにがどのようになっているのか知るためにコンソールにログを出力するコードを入れてみます。

 だんだんわかってきたところであることに気づきました。

 なにかというと・・・。

 下の画像はブラウザの開発ツールでコンソールを表示させたときのものです。広告を貼った画面をスクロールするたびに理解促進用に入れたログが鬼のように記録されていきます。遅延ロードの仕組みは、画面をスクロールしたときのイベントをキックとしてGoogle AdSenseのJavaScriptが起動されるというものです。

クライアント側のCPUを無駄に消費して電気を浪費

 改めて遅延ロードに使ったコードを見てみます。

<!-- AdSenseを遅延ロードする。 -->
<script>
    var lazyload = false;
    window.addEventListener('scroll', function() {
        console.log('Start Google AdSense');
        lazyload == false && (document.documentElement.scrollTop != 0 || document.body.scrollTop != 0) && (function() {
            let ads = document.createElement('script');
            ads.type = "text/javascript", ads.async = true, ads.crossorigin = "anonymous", ads.src = "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-xxxxxxxxxxxxxxxx";
            let ref = document.getElementsByTagName('script')[0];
            ref.parentNode.insertBefore(ads, ref);
        }(), lazyloadads = true)
    }, true);
</script>

 コードを見ると、スクロールでイベントが発生するたびにGoogle AdSenseのJavaScriptが起動されてしまわないようにlazyloadというフラグが使われています。

 これって駄目ですよね?

 1回だけ起動すればいいのなら最初の1回目でイベントハンドラーを削除するなりすればよいだけだと思います。

 ちなみに、驚いたことに私が参考にしたコードだけでなく、ネットで検索したときの上位3位までのサイト(検索キーワードは書きません)で紹介されているコードに同じ問題?がありました。

 もしかして、私の方が間違ってるのかな。

ちょっと改造したコード

<!-- AdSenseを遅延ロードする。 -->
<script>
    window.addEventListener('scroll', function() {
        console.log('Activate Google AdSense');
        (document.documentElement.scrollTop != 0 || document.body.scrollTop != 0) && (function() {
            let ads = document.createElement('script');
            ads.type = "text/javascript", ads.async = true, ads.crossorigin = "anonymous", ads.src = "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-xxxxxxxxxxxxxxxx";
            let ref = document.getElementsByTagName('script')[0];
            ref.parentNode.insertBefore(ads, ref);
        }(), true)
    }, {capture: true, once: true});
</script>

 この問題?に対処するには、イベントハンドラーを削除する代わりに、そのイベントハンドラーを登録するメソッドaddEventListenerの第3引数を「true」から「{capture: true, once: true}」に変えればよいことがわかりました。これはスクロールイベントが発火してイベントハンドラーが呼び出されたタイミングでイベントハンドラーを削除せよ、という指定です。この修正をすればlazyloadといったフラグが不要になります。もう少し言うと、「once: true」の部分で「イベントハンドラの起動は最初の1回だけ」と指定しています。

 これでスクロールするたびにイベントハンドラーが呼び出されることはなくなりました。

 ちなみに、5行目では、イベントハンドラーの本体が呼び出される条件として「(document.documentElement.scrollTop != 0 || document.body.scrollTop != 0)」が指定されているのですが、これの意図が読み取れませんでした。この条件がなくても問題なさそうな気がするのですが・・・。コードの意味は「スクロール位置がページ先頭でない場合にのみイベントハンドラー本体を実行する」です。もしかしたらLighthouse対策や古いブラウザ対策なのかもしれません(まったく自信なし)。

ちなみに私が使っているコード

 最後に私が現在使っているコードを紹介して終わりたいと思います。

 上のコードと違うところは、コード中のコメントにあるように非公開の記事やプレビューの場合には広告を表示しないようにしているところと、上で述べた意図がよくわからない部分をコメントアウトしているところです。

<!-- AdSenseを遅延ロードする。 -->
<!-- 公開ページかつ非プレビューなら広告を表示する。 -->
<?php if (get_post_status() === 'publish' && !is_preview()): ?>
    <script>
        window.addEventListener('scroll', function() {
            // (document.documentElement.scrollTop != 0 || document.body.scrollTop != 0) && (function() {
                console.log('Activate Google AdSense');
                let ads = document.createElement('script');
                ads.type = "text/javascript", ads.async = true, ads.crossorigin = "anonymous", ads.src = "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-xxxxxxxxxxxxxxxx";
                let ref = document.getElementsByTagName('script')[0];
                ref.parentNode.insertBefore(ads, ref);
            // }(), true)
        }, {capture: true, once: true});
    </script>
<?php endif; ?>

 デプロイ(完成したコードを実行環境の所定の場所に配置すること)は、WordPressなら上記のコードをテーマのheader.phpなどに貼ればそれだけで自動広告が動くようになります。自動広告以外の例えばディスプレイ広告やマルチプレクス広告などは、Google AdSenseのサイトからコピーしてきたコードをWordPressなら再利用ブロックなどを使って自身のサイトで広告を表示させたい場所に貼ればよいです。

 例えば、貼るコードはこんな感じ。

<!-- 再利用ブロックに貼るコード -->
<ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-xxxxxxxxxxxxxxxx" data-ad-slot="xxxxxxxxxx" data-ad-format="auto" data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>

 注意点としては、上のコードを見てわかる通り、Google AdSenseのサイトからコピーしてきたコードのうち1行目にある「<script ・・・>」から「</script>」までを削除したものを貼る、ということです。

2023/3/27追記

 遅延ロードに関する他所のブログを読んでいて予想はしていましたが、やはりGoogleから指摘されてしまいました。CLS(Cumulative Layout Shift)が悪いそうです。ようは、広告を遅れてロードしているのでその過程でレイアウトのずれが生じていてそれが許容範囲外とのこと。ページの読み込み中にレイアウトがずれるとユーザーが誤って意図しないリンクやボタンをクリックしてしまうからダメなのだそうです。

Googleからの指摘

 対策としては、以下のページに書いてあるように、再利用ブロックなどに貼ったコードを改めて「<div style="min-height:xxx;height: auto">」と「</div>」で囲むよう修正すればよいそうです。「xxx」の部分はあらかじめ確保する広告領域の高さで「280px」などと指定します。これにより、最初は小さかった広告の表示領域が広告がロードされるタイミングで急に拡大することがなくなりCLSが起こらなくなります。

 当ブログでは、ディスプレイ広告で280px、マルチプレクス広告で426pxと指定しました。例えばディスプレイ広告の場合なら以下のような感じです。

<!-- 再利用ブロックに貼るコード -->
<div style="min-height:280px;height:auto">
<ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-xxxxxxxxxxxxxxxx" data-ad-slot="xxxxxxxxxx" data-ad-format="auto" data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>

2023/4/2追記

 「2023/3/27追記」で述べた改善策がGoogleに合格と認められました。「不良」や「改善が必要」なURLが「0」となりすべて「良好」となりました。

効果確認OK


 以上、「ちょっとよろしくないGoogle AdSenseの遅延ロード用コードが蔓延している件」でした。

コメント

コメントする

コメントは日本語で入力してください(スパム対策)。

CAPTCHA

目次