RACCOON TECH BLOG

株式会社ラクーンホールディングスのエンジニア/デザイナーから技術情報をはじめ、世の中のためになることや社内のことなどを発信してます。

広告タグを整理してWebサイトのパフォーマンスを改善した話

こんにちは、羽山です。

今回は私自身が半年にわたって弊社の運営する仕入れのECサイトスーパーデリバリーで利用している各種Web広告サービスの仕組みを調査・理解して、手段を考えて、そして改善を行った成果とそのノウハウを共有します。

まず何が問題だったかというと、Web広告サービスにはGoogle広告・Facebook広告・Yahoo広告など広告サービスは多数ありますが、それらを有効に活用するには各サービスが提供している専用タグをサイトの全ページに埋め込む必要があります。
察しの良い方はすでに感づいているかと思いますが、サイト全体に埋め込んだそれらのタグがスーパーデリバリーの表示パフォーマンスを大きく低下させていたのでした。

エンジニアにとって広告に利用する外部タグは不可侵領域みたいな扱いで言われるがまま入れたり、もしくはタグマネージャをマーケティング担当部門が管轄していて知らぬ間に広告タグが増えているけど実体も把握できないし口も出せないという状況はよくあるのではないでしょうか?実際に半年前の私自身がその状態でした。

しかし今回の対応をしていて「それではダメだ」と痛切に気付かされました。いまやWebパフォーマンスを適切に保ち改善するには外部タグも含めたコントロールが必要であり、それらの領域にもエンジニアが理解して踏み入れる勇気が必要だと感じます。
外部から提供されたタグは結局プログラムであり、何らかの仕組みが動作しています。その動作の仕組みを非エンジニアが理解することは難しいため、結果として無駄の多いタグの埋め方をしているケースは少なくないと考えられます。

そこで当記事ではエンジニア目線で理解する広告サービス、そして得られる効果を維持しながらWebパフォーマンスも両立するバランスの良い使い方を紹介します。
具体的には「広告タグが与えるWebパフォーマンスへの影響」「Webパフォーマンスとは何か」「広告タグの仕組みと役割」「安全に広告タグを削減する方法」というあたりの内容になっています。

まずは成果のアピール

ここ5ヶ月のパフォーマス速度改善

これは最近5ヶ月で各種広告タグを徐々に削除してパフォーマンスを改善したことを示すグラフです。
縦軸はスーパーデリバリーの各ページに利用者がアクセスした際の、ナビゲーションの開始から load イベントの発火までの経過時間を蓄積して日ごとに中央値を取ったもので単位は秒です。

グラフの左端が今年の2月で、その頃は1.5秒程度かかっていたのが5ヶ月後には1.0秒程度まで改善して、3分の2の時間でページを表示できるようになりました。

ちなみにこのデータは GA4 とタグマネージャの設定で、サイト速度のRUM(Real User Monitoring)を行っています。
詳しくはGoogle Analytics 4 でサイト速度を計測する方法で解説しているので是非ご参照ください。

広告タグはなぜ重いのか?

広告タグがWebサイトのパフォーマンスにおよぼす悪影響を見てみましょう。
広告タグとは要するに外部の JavaScript ファイルを読み込むタグやコード片です。それらの JavaScript コードは広告の提供に必要な情報を収集した上で各広告サービスのサーバへ情報を送信します。

例えば Google広告は以下のタグをサイトの全ページに埋め込みます。処理内容は外部の JavaScript ファイルをダウンロードして実行するものです。

<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=AW-70******1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'AW-70******1');
</script>

広告タグはうまく管理しないとサービスを運営とともに徐々に種類や数が増える傾向にあり、今だから恥を忍んで書きますが改善を始めるまでは1ページ中に Google広告のタグだけで6個も入っていました。
同じ広告サービスのタグでも例えば運営する複数サイト間でお互いの広告タグを入れあったり、運用上の利便性のために用途ごとにタグを分離するなどで増殖します。

次の図はそのツライ状況をメンバーに訴えるために Slack に投稿した画像です。手書き感があるのはご容赦ください。
読み込みパフォーマンスの分析

Chromeでパフォーマンス分析したこの図ですが、①は Googleのサーバから各広告タグの動作に必要な JavaScript コードをダウンロードするフェーズです。HTTP通信は非同期IOで並列ダウンロードされるので数が増えてもパフォーマンス劣化は最低限です。注目は②で、これは JavaScript コード実行を表しています。

さて、みなさまご存じの通り JavaScript は原則としてシングルスレッドで実行されます。そして昨今はフロントエンドがリッチになり以前まではサーバーサイドで行っていた処理をクライアントサイドの JavaScript が担当するケースが増加しています。

現在のWebパフォーマンスは JavaScript の実行を担当する1スレッドがクリティカルパスとなるケースが大半で、JavaScript の実行にかかる時間がそのままイコールでページ表示時間の遅延に繋がります。

そこで改めて②を見ると「スクリプトの評価」と書かれた(※表記が一部省略されてます)オレンジのバーが5つ並んでいます。これは①でダウンロードされた5つのGoogle広告タグが順番に実行さる様子を表しています。①は縦に並んで並列処理されていますが、②は横に並んでシリアルに実行されています。

時系列を確認すると②の部分は2400ミリ秒付近から開始して2700ミリ秒付近で完了していて約300ミリ秒かかっています。3000ミリ秒付近に登場する load イベント (※ L という表記)はそれらの完了を待ってから発火するので、Google広告タグの JavaScript コード実行によって約300ミリ秒遅延しています。

様々な広告タグのパフォーマンスをプロファイリングしてみましたが、Core i7 のノートPC環境では1つの広告タグあたり、おおよそ 50ミリ秒ほどのCPU計算量が必要なものが大半でした。
今回はGoogle広告タグだけでも6個も入っていたため、それだけであらゆるページが0.3秒遅くるのでパフォーマンスに与える影響は甚大です。

DOM構築、CSSOM構築、JavaScript実行

昨今のWebパフォーマンスは JavaScript の実行時間の分だけ悪化する事実が分かったので、Webサイトのレンダリングの仕組みを交えて少しだけ掘り下げます。とはいえ全体像をゼロから解説すると1記事では収まらないので、重要なエッセンスであるDOM構築・CSSOM構築・JavaScript実行の3点に焦点を当ててさわり部分を解説します。

DOM構築とは

CSSOM構築とは

JavaScript実行

DOM構築とCSSOM構築は並列実行されますが、JavaScript実行はDOM構築とCSSOM構築を停止させます。仕組みを考えれば自明ですが、JavaScriptはDOM及びCSSOMを読み書きできるので並列実行するとスレッドセーフの問題が出てくるので排他的に実行する仕様となっています。GUIアプリを作ったことがある方にはUIスレッドで全ての処理を行う様子を想像すれば理解しやすいかもしれません。

つまり DOM/CSSOM構築とJavaScript実行は互いにシリアルに実行されるので、load イベントが発火するまでにかかる時間はそれらの合計実行時間です。

これらの動作をさらに詳しくは知りたい方はこちらの記事が参考になります。

loadイベントをWebパフォーマンスの指標とする理由

10数年前まではバックエンドの応答速度がそのままイコールでWebパフォーマンスと言っても支障はありませんでしたが、昨今はWebパフォーマンスの評価基準が曖昧になっています。

loadイベント、DOMContentLoaded イベント、バックエンドの応答速度、Core Web Vitalsなど指標となり得る値は様々あります。
用途によって向き不向きもあるので、例えばサーバーサイドレンダリング、CSS/JavaScript などのリソース読み込みが少なめ、利用者が日本国内だけならば、バックエンドの応答速度を指標としても問題ないと考えられます。

一方で私個人としてはナビゲーションの開始から load イベント発火までの経過時間を利用することを好んでいます。

なぜならば昨今のウェブサイトは JavaScript に頼る比重が大きくなり、その結果 load イベント発火までの間に多数の JavaScript の実行キューが積まれがちです。結果として DOMContentLoaded が発火してほぼ画面表示されていても、JavaScript の反応が悪いので快適には使えません。そこでWebサイトが問題なく利用可能になるタイミングが load のタイミングであると考えています。
また load はサーバーサイドレンダリングでもクライアントサイドレンダリングでも有効に利用でき、異なる成り立ちのサイト間でも比較可能な点が指標として優れています。

そこで当記事では広告タグを削減することで load イベント発火までの時間を短縮することを目的とします。

広告タグの仕組み

Webサイトのパフォーマンスの考え方が分かったので、次は広告タグの仕組みと役割を解説します。
一般にサイトに埋め込まれる広告タグは次の二つの役割を持っていて、これらを実現するためにはサイトの全ページに広告タグを入れることが推奨されています。

広告タグを埋め込みたい人のニーズを理解して、やりたいことをなるべく損なわずに埋め込むページ数を削減するためには広告の動作原理を理解する必要があります。

コンバージョンの記録とは

各サービスが広告を使う理由は様々ですが、「会員登録数の増加」「購入の促進」のように何らかの目的があり、それをコンバージョンと呼びます。
コンバージョンの記録とは、広告を経由して達成したい目的が実行されたことを広告サービスにデータとして送信する行動です。

一般的には会員登録などの完了ページにコンバージョンを報告する専用のタグを埋め込みます。
ではそれだけで良いかというとそういうわけではありません。
実はコンバージョンの報告のためにはサイト全体にもその広告サービスが提供する広告タグを埋め込む必要があるのですが、何故かというとサードパーティCookieの規制問題が関わってきます。

コンバージョン記録とサードパーティCookie

広告サービスは、ユーザーがどの広告をクリックしてコンバージョンに至ったのか、もしくは広告以外の経路でコンバージョンに至ったのかをできるだけ正確に把握する必要があり、そのために以前まではサードパーティCookieが主に利用されていました。

次の図はサードパーティCookieを利用したGoogle広告のコンバージョン記録の流れです。

サードパーティCookieと広告

まずは www.google.co.jp で検索したユーザーにCookie (CookieABC とします) がセットされます。そのユーザーが広告をクリックしたら Google はクリックされた広告の情報を CookieABC に紐付けて保持します。
次に遷移先のサイト(www.superdelivery.com)でコンバージョン(=会員登録)が発生すると、コンバージョンタグによって www.google.co.jp にその情報が送信されます。その際にサードパーティCookieに制限がなければ CookieABC も付与されるため、Google は誰がどの広告をクリックしてコンバージョンしたのかを把握できます。

コンバージョン記録はなぜ必要?

なぜコンバージョン記録が必要かというと、広告の運営担当者が成果を分析する以外にも「自動入札」という仕組みが関連しています。

Googleで検索ワードに連動して表示される検索広告(いわゆるリスティング広告)を例に解説します。ユーザーが広告をクリックするごとにクリック単価分の広告費用が発生する仕組みで、そのクリック単価の設定を手動でやると非常に労力がかかりますが、実際の広告運用では自動入札を利用するケースが大半です。

前述のように広告を利用する人は広告によって達成したい目標(=コンバージョン)を設定します。例えばスーパーデリバリーは会員登録をコンバージョンとしています。

コンバージョンを設定してしばらく広告運用をすると、ユーザーの様々な属性ごとにコンバージョンへ至る確率を統計的に推測できるデータがGoogle広告内に蓄積されます。
その情報を使うと「パソコンを利用」「検索ワード: スーパーデリバリー」「平日、午前9時~午後5時に検索」の条件に合致するユーザーが広告をクリックしたら約4%の確率でコンバージョンに至る、などのようにコンバージョン率を推測できます。

次にコンバージョン1件あたりいくらで獲得したいかを設定します。例えば5000円に設定すると前述のコンバージョン率4%のユーザーにはクリック単価を 5000円 x 4% = 200円 に設定すれば良いと分かります。
一方で「スマホを利用」「検索ワード: 問屋」「週末、午後4時以降に検索」ではコンバージョン率が 1% ならば 5000円 x 1% = 50円 とすれば、どちらのケースでも机上の計算では1コンバージョンにかかる費用は5000円になります。こういう計算を広告表示のたびに自動実行してくれるのが自動入札です。

自動入札の仕組み

クリック単価を高く設定する必要性に疑問を持つ方もいらっしゃると思います。しかしそこが広告サービスのうまいところで広告を出したい人々は互いにクリック単価で競い合います。オークションになっていてクリック単価を高く付けた順に上から広告表示をするのでクリック単価を抑えると広告自体が表示されなくなってしまいます。

サードパーティCookieを利用せずにコンバージョンを記録する方法

さて昨今の流れではサードパーティCookieが徐々に使えなくなりつつあり、現時点では Safari, Firefox で実質的に利用できません。
そこで広告サービスはサードパーティCookieがなくてもユーザーを識別してコンバージョン記録をできるようにアップデートしています。

サードパーティCookieを利用しないコンバージョン記録

上図はGoogle広告がサードパーティCookieを利用せずにコンバージョン記録をする流れです。
先ほどとの違いは広告経由でランディングしたページに「Google広告タグ」が埋め込まれている点です。

Googleは各広告を表示するごとにユニークの gclid 値を生成して、広告でランディングするURLパラメータに https://www.superdelivery.com/?gclid=abcdef... という形式で gclid パラメータを付与します。

www.superdeliveryy.com 側は広告経由でランディングする全てのページに Google広告タグの埋め込んでおきます。すると Google広告タグの JavaScript は gclid パラメータをURL中に見つけたら www.superdelivery.com のファーストパーティCookieとして保存します。
そして会員登録などのコンバージョンが発生したら、コンバージョンタグは www.superdelivery.com のファーストパーティCookieから gclid の値を取得して Google広告のサーバに送信するコンバージョンデータに付与します。
ユニークに生成された gclid 値によってどの広告がどんな属性のユーザーにクリックされたのかがGoogle広告のデータベースに蓄積される仕組みです。

ファーストパーティCookieで動作するので、サードパーティCookieが必要ない点が特徴ですが、そのためには広告から流入するページに広告タグを埋め込む必要があり、一般的にはサイト全体に埋め込むケースが大半です。

オーディエンスの構築

広告タグの二つ目の役割は「オーディエンスの構築」で、オーディエンスとはユーザーリストのことです。
いわゆるリマーケティング・リターゲティングと言われる手法に利用され、一度サイトに訪れたユーザーに重点的に広告を表示することで再訪を促します。

このオーディエンス機能を有効に活用するために同一運営会社の別サービスで相互に広告タグを入れあったりすることが広告タグ増殖の一因となっていました。

しかしこのオーディエンスにもサードパーティCookieの制限が影響してきています。
制限がなかった時代はユーザーが www.superdelivery.com へアクセスするだけで、そのページに埋め込まれた Google広告タグが www.google.co.jp ドメインに保存されたユーザー識別子(下図のCookieABC)と共にアクセスログを送信していました。すると Google側は自社の認識するユーザーと www.superdelivery.com にアクセスしたユーザーを紐付けることができるので、CookieABC さんを www.superdelivery.com のオーディエンスに入れることができます。

サードパーティCookieが有効なオーディエンス構築

サードパーティCookieが利用できないと、www.superdelivery.com のアクセスログは収集できますが、そのユーザーが www.google.co.jp 側で認識する誰なのかを識別するすべがなく、オーディエンスを構築することができません。
次の図のように今まで送られていた CookieABCwww.google.co.jp に送信されなくなります。

サードパーティCookieが無効なオーディエンス構築

サードパーティCookieが規制されたブラウザでもオーディエンスに入れるには下図のように広告をクリックして gclid によって双方ドメインのユーザーを紐付ける必要があります。

gclidでオーディエンス構築

つまり現在はオーディエンスの構築という役割が徐々に縮小しつつあります。

Google広告タグの削除

次はいよいよ本題の広告タグの削減手段を解説ですが、Google広告を他の広告サービスとは分けて考えます。
なぜなら Google広告には Google Analytics プロパティ4(以下GA4)と連携する機能があり、すでにGA4タグを埋め込んでいるサイトならば Google広告タグを利用する必要なくGoogle広告タグと同等に利用できるからです。

【GA4】コンバージョンイベントの定義

Google広告で利用するコンバージョンを定義するには、まずGA4側でコンバージョンイベントを生成します。

そのためにはまずGA4側で以下のような方法で任意のイベントを発生させます。

下図はGA4の「イベントを作成」機能を利用してコンバージョンとみなす特定のURLにアクセスが発生すると sign_up イベントが生成されるように設定しています。
図のように valuecurrency パラメータにコンバージョン値と JPY などの通貨を設定すると、Google広告にコンバージョン値として取り込むことができます。

GA4の設定でイベントを生成

イベント名は任意で付けることができますが分かりやすい名前にしましょう。参考資料としてGA4の公式ドキュメントに推奨イベントの一覧があり、例えば会員登録完了のイベント名は sign_up が推奨されています。

GA4でイベントを発生させたらコンバージョンとしてマークします。方法は2つあり、1つ目は設定画面の「イベント」から該当イベントを探して「コンバージョンとしてマークを付ける」のトグルをONにします。しかしイベント一覧にはすでに発生しているイベントしか表示されないので、新規イベントをコンバージョンイベントとする場合は設定画面の「コンバージョン」を開いて「新しいコンバージョンイベント」にイベント名を手動で入力します。

一通り設定できたら実際にイベントを発生させて、「イベント名」ディメンションと「イベントの値」指標(※コンバージョン値)に正しい値が入ることを確認しましょう。

【Google広告】リンクアカウントの設定

次は Google広告の管理画面での設定です。
「リンクアカウント」画面を開いて「Google Analytics (GA4) & Firebase」や「Firebase 向け Google アナリティクス(GA4)」の項目でGA4プロパティへリンクします。
現時点では画面によって名称が表記揺れしていますが両方とも同じ意味です。

【Google広告】コンバージョンアクションのインポート

「新しいコンバージョン アクション」ページを開き「インポート」から「Google アナリティクス 4 プロパティ」を選択して次の画面へ遷移すると、GA4側で定義したコンバージョンイベントが表示されるのでインポートします。
コンバージョンアクションの設定はGoogle広告タグを元にした場合とさほど変わらないので、設定画面の説明を参照しながら適切に設定しましょう。

コンバージョンアクションのインポート

1つ注意点として、すでにGoogle広告タグを元に運用している場合は、GA4へ切り替える前に「サブアクション」として定義してコンバージョンが正しく溜まることを確認しましょう。

【GA4】オーディエンスについて

GA4で定義したオーディエンスは Google広告に自動的にインポートされます。Google広告の「オーディエンスマネージャー」ではソース列が「Firebase 向け Google アナリティクス(GA4)」と表示されます。(※ソース列を表示していない場合は「表示項目」から追加してください)
うまく連携されていれば「サイズ:検索」などの数値が徐々に増加するはずです。
ただし前述のとおり現在はオーディエンスの役割が徐々に縮小しています。そのためオーディエンス運用が今後も必要かの検討を行う余地はあります。

※Google広告からGA4のオーディエンスを利用するにはGA4設定面の「データ収集」オプションを適切に設定する必要がある点に注意しましょう

その他の広告タグの削減

次は Google広告以外の広告タグの削減方法を解説します。この設定は Googleタグマネージャの利用を前提としています。

今回ご紹介する方法は、先ほど解説した広告タグの仕組みを元に、広告サービスの機能性をなるべく損なわずに必要性の低い埋め込みページを削減することを目的としています。
具体的には広告タグを埋め込むページを以下に制限します。

広告タグは外部から流入した最初のページに埋める必要があります。なぜならば「サードパーティCookieを利用せずにコンバージョンを記録する方法」項で解説したように gclid などの識別用パラメータをファーストパーティCookieとして保存する必要があり、そのパラメータが付与されるのは広告経由で流入した最初のページのみだからです。
そこでユーザーが一連の閲覧行動を開始する最初の1ページ目を識別して広告タグを動的に埋め込みます。

ちなみに gclid に当たるパラメータを Yahoo広告は yclid 、Facebook広告は fbclid という名称で付与します。いずれのサービスも命名の足並みがそろっていて面白いですよね。

また現時点でもサードパーティCookieが利用可能な Chrome などのブラウザでは広告経由の流入でなくてもオーディエンスを構築できるので、ユーザーの一連の閲覧行動のうち少なくとも1度は広告タグを埋め込むとメリットがあります。

あとはコンバージョンページと、オーディエンスを構築した特定のページがある場合はそのページには固定で広告タグを埋め込みます。

では具体的な設定を見ていきましょう。

セッション開始ページビューとなる任意のページ

一連の閲覧行動の最初の1ページ目を識別するためにタグマネージャを設定します。

新規変数の作成で変数のタイプ「カスタム JavaScript」を選択して、以下のJavaScriptコードを入力します。

function() {
  return !document.referrer.startsWith(location.protocol + "//" + location.host + "/") ? 1 : 0;
}

変数名は任意ですが is_session_start_pageview としています。

is_session_start_pageview変数

この変数はリファラのドメインが現在のドメインと一致するかを確認して、異なる場合に 1 を返すので、一連の閲覧行動の最初のアクセスを識別できます。

次はページビューの is_session_start_pageview = 1 で発火する「セッション開始ページビュー」トリガーを作成します。

セッション開始ページビュートリガー

そして対象となる広告タグを作成して、そのトリガーとして「セッション開始ページビュー」トリガーを設定します。
オーディエンスを構築したい特定のページがある場合はそのページに対応するトリガーも作成して、同様に広告タグのトリガーとして設定します。
また、コンバージョンタグも必要なページに設置します。

必要な設定は以上です。これで複数ページを閲覧するユーザーは2ページ目以降、広告タグが埋め込まれなくなるため表示のパフォーマンスが改善します。
ただし広告サービスには2ページ目以降の閲覧情報が送信されなくなるため、広告サービスの最適化レベルが若干低下する可能性はあります。とはいえ最も重要な1ページ目の情報を送信できているため大きな影響はないと考え、Webパフォーマンス改善を優先しています。

まとめ

ここまで読まれた方は是非、自社の運営するサービスにどれほどの外部タグが入っているかを確認してみてください。
真剣に成長を目指して真面目に取り組んでいるサービスほど様々な試行錯誤と共に多くの外部タグが埋め込まれる傾向にありそうです。

その結果たくさんの外部タグや広告タグを見つけたら、まずは現在の使用状況を確認しましょう。記事本文では触れませんでしたが実は「以前利用していたけど現在は使ってません」というパターンも多かったりします。
サイト全体に埋め込まれている現役の広告タグが見つかったなら、そしてそのタグを元に広告サービスが現在進行形で便利に利用しているならば、そこには既得権益が発生していて簡単には削除できません。その時こそ当記事が役に立つことを祈っています。

世の中のWebサイトが今よりもさらに速くなることを願っています。

さて、ラクーンホールディングスではエンジニアデザイナーHTMLコーダーを大募集中です!
興味を持っていただいた方は是非、お話ししましょう!

一緒にラクーンのサービスを作りませんか? 採用情報を詳しく見る

関連記事

運営会社:株式会社ラクーンホールディングス(c)2000 RACCOON HOLDINGS, Inc