こなさんみんばんわ。

Google AdSense の自動広告のひとつに全画面広告というのがありますが、これを有効にしていると、記事目次(見出しが一覧になってて、リンクを押すと該当の箇所にジャンプするアレ)を置いてるサイトでちょっとした不具合が発生するのをご存知でしたか? 僕はつい数時間前まで全然気が付いてませんでした…

困ったことになってるなぁと思いながら調べてみたところ、AdSense 公式のヘルプにその対処方法が掲載されていましたので、少し時間を取ってその対処方法を導入し、とりあえずは無事解決に至りました。

本日はその不具合の詳細と対処方法、このサイトで実際にやった内容を書いておきます。が、ウチは最近では数少なくなった特殊な静的サイト生成環境なので、対策コード自体はあまり参考にはならないと思います。涙

アドセンスの全画面広告とは

全画面広告とは Google AdSense の自動広告フォーマットのひとつで、ユーザーが Web ページ内のリンクのどれかをクリック/タップしてページを遷移しようとした時に、そのリンク先ページの読み込み中に表示される広告のことです。

…だったのですが、最近はそれ以外の操作をした時(どころか、操作してない時)にもデフォルトで表示されるようになり、最初の頃よりそのウザさはおよそ256倍増しくらいになっているのではないかと思います。涙

全画面広告 + 記事目次で発生する罠(不具合)

そんな全画面広告、基本的にそれが表示されるのはリンクを押した時なのですが、実はその対象には記事目次のようなページ内リンクも含まれています。つまり、目次を置いているサイトで全画面広告を有効にした場合、目次のリンクを押すと該当の見出し位置までジャンプするより先に全画面広告が開くことがあるのですね。

しかもその場合、全画面広告を閉じたらちゃんと該当の見出しまで移動してくれるのか? というとそんなことはなく、ページの位置は目次のある場所に留まったままなのです。実際には背後で一度ジャンプした後また戻るといった感じで、一連の動作を観察してみたところ、次のような挙動でした:

  • ユーザーが記事目次内の項目のどれかをクリック/タップする
  • 該当の見出し要素までジャンプするのではなく、全画面広告が開く
  • ユーザーが全画面広告を閉じる操作をするが、広告はまだ完全には閉じられない
  • 消えない広告の背後で一瞬、先ほど押した目次リンクの対象となる見出しまでスクロール移動する
  • しかし広告が閉じられるとユーザーがクリック/タップした位置を記憶しているのか、スクロール位置が目次まで戻ってくる

と、こんな感じなので、結局ユーザーはもう一度、目的のリンクを押さないといけません。なんというトラップや…

この罠を放置しておくことは、ユーザー体験を悪くする

で、この全画面広告はその仕組み上、Google や Bing などの検索結果から飛んできたユーザーが最初にリンクを押したタイミングで表示されやすくなっていることが、さらにイメージを悪化させます。

だってこういったユーザーは、通常はその記事を読みたくて飛んできた訳じゃないですか。その内容に期待して飛んできたのに、目次をクリック/タップしたら広告を見せられ、それを閉じてもまだ何も起こらないので、結局もう1回目次を操作しないといけない…なんて、どう考えても印象悪いです

対処方法は、アドセンスの公式ヘルプに書いてある。けどな…

僕はこの罠をたまたま見たサイトで目次を操作して気が付いて、自分のサイトでも試してみたらやっぱり同じようになっていたので、あーこりゃあかん、すぐに何とかしなければ…と思って調べてみたところ、公式ヘルプに次の内容が掲載されておりました。

全画面広告を表示させたくないリンクには、その HTML タグに data-google-vignette="false" 属性を追加せよとのことです。なるほど、これで制作者側で自力で対処するのですね。了解了解。

しかしですね…この記事目次、おそらく多くのサイトが毎回手書きでせっせと書いてる訳ではなく、例えば WordPress ブログであればプラグインといったような、何らかのプログラムを使って生成していることかと思います。つまり、そのコードに手を加えられないと対策できないじゃないですか。涙
自力で解決できない人にはどうしろというんでしょうね…

対処のために、このサイトで実際にやった作業内容

まぁそんなことをボヤいてても仕方がないので、とにかくこちら側でその属性を追加して対処するしかありません。このサイトは Jekyll を使っていて、目次についてはそのデフォルト Markdown レンダラーである Kramdown の自動目次生成機能をそのまま利用しておりますので、そのコンバーター部分を探して上書きすればいけそうです。

Kramdown 本体のコードやリポジトリの Issue などを検索して参考になりそうな情報を当たってみた結果、Kramdown::Converter::Html クラスの generate_toc_tree メソッドが該当部分であることが分かりましたので、その部分を丸々コピーしたものを _plugins ディレクトリに保存して、少しだけコードを追加します。昨年はてブ砲に撃たれたあと、転送量削減のために <img> 要素に loading="lazy" を追加した時と同じ方法ですね。

module Kramdown
  module Converter
    class Html < Base
      def generate_toc_tree(toc, type, attr)
        sections = Element.new(type, nil, attr.dup)
        sections.attr['id'] ||= 'markdown-toc'
        stack = []
        toc.each do |level, id, children|
          li = Element.new(:li, nil, nil, level: level)
          li.children << Element.new(:p, nil, nil, transparent: true)
          a = Element.new(:a, nil)
          a.attr['href'] = "##{id}"
          a.attr['id'] = "#{sections.attr['id']}-#{id}"
          a.attr['data-google-vignette'] = "false"
          a.children.concat(fix_for_toc_entry(Marshal.load(Marshal.dump(children))))
          li.children.last.children << a
          li.children << Element.new(type)

          success = false
          until success
            if stack.empty?
              sections.children << li
              stack << li
              success = true
            elsif stack.last.options[:level] < li.options[:level]
              stack.last.children.last.children << li
              stack << li
              success = true
            else
              item = stack.pop
              item.children.pop if item.children.last.children.empty?
            end
          end
        end
        until stack.empty?
          item = stack.pop
          item.children.pop if item.children.last.children.empty?
        end
        sections
      end

    end
  end
end
今回作成したプラグインの全コード。ちなみにファイル名は add_data_google_vignette_to_toc.rb という、そのままの命名。涙

保存したプラグインのコードをそのまま掲載しておきます。追加したのは14行目の a.attr['data-google-vignette'] = "false" だけで、あとはすべてオリジナルのままです。僕と同じく Jekyll + Kramdown で記事書き & 目次自動生成している方にしか役に立たないコードではありますが、必要でしたらそのまま利用していただいて差し支えありません。

とにかく、これで動作確認をしましたところ、無事に属性がすべてのリンクに付与され、本番環境でも目次リンクのクリックで広告が開かないことが確認できましたので、これで対策は完了です。お疲れさまでした。

ちょっと待て、Jekyll + Kramdown じゃないところはどうすれば?

とにかく、対策の本体は目次リンクに data-google-vignette="false" 属性を追加することなので、何らかの手段でそれを達成することですね。

もし自由に目次生成機能のプログラムに手を加えられるようであれば、あとはリンクの出力部分を探し出して属性を書き加える処理を加えればいいのですが、その方法はツールによって違うはずなので、こちらではすべてを把握しきれません。なのでもう「がんばって!!」としか言いようがないです。涙

あと WordPress のプラグインなどを使って生成している方は、そのプラグインの作者さんに事情を話して、コードを付け加えてもらえるようにお願いするしかないでしょうね。あとは生成 AI に頼んで独自のプラグインを作ってもらうとか…それくらいしか思いつかないです。すみません。

そんな訳で

Google Adsense の全画面広告は記事目次のようなページ内リンクをクリック/タップした時の動作を妨げており、そのまま放置してるとユーザー体験を損ねるので対策した方がいいよ、その方法は基本的には data-google-vignette="false" をリンクの HTML タグに追加するだけだよ、というお話でした。参考になりましたら幸いです。

(以下余談)

まぁ全画面広告に限らず AdSense の自動広告って基本的にウザいものが多いです😭 最近はさらにそのウザさ加減が増してる気がするのですが、その収益に占める割合が高いために外すに外せなくて、結局オンのまま放置しているという方もけっこう多いのではないでしょうか。

Google もせっかくなら多くの広告収入を得てもらいたいと考えて色々やってるのだとは思うのですが、制作者が収入を得るのと引き換えに読みに来た人が不快な気分になっているようでは、一体我々は何のためにサイトを運営しているんだ…という話にもなってきますので、もう少し考えてくれないものかなぁと思います。今回の件だって、そもそも AdSense 側でデフォルトでやってくれれば、我々は何もする必要がない訳ですしね。

とりあえず、最近は「こちらをクリック」みたいなユーザーを混乱させるような広告もあるのに放置されてるようですし、もしも他に収入源が確保できるのであればもうアドセンスとかやめたいよな…とは、まじでちょっと思い始めているところです。

ということで、その手始めにと先日 Buy me a coffee のアカウントを作りましたので、もし記事を読んで役に立ったと思っていただけましたら、下のリンクから僕にコーヒー代というかビール代 ($3) をおごっていただけますと幸いです!! そのうち全ページに自動で出るようにしたいところですが、とりあえず今回は記事内に直接貼っております。ちなみに缶ビールはプレモル派。涙

つい最後の余談というかボヤきが長くなってしまいました。この辺でさようなら。あっ上のプロフィールはそのうち整えるから。涙