時間のかかる広告介入への対応

Rowan Merewood 氏
Rowan Merewood

デバイス上で過度にリソースを消費する広告は、パフォーマンスの低下による明白な影響から、バッテリーの消耗や帯域幅の容量の消費といった目に見えない影響まで、ユーザー エクスペリエンスに悪影響を及ぼします。これらの広告には、暗号通貨マイナーなどの積極的に悪意のあるものから、意図しないバグやパフォーマンスの問題を含む正規のコンテンツまで、多岐にわたります。

Chrome では、広告で使用できるリソースに上限が設定され、その上限を超えると、その広告がアンロードされます。詳しくは、Chromium ブログのお知らせをご覧ください。広告をアンロードするメカニズムは、負荷のかかる広告介入です。

厳しい広告条件

広告が重いとみなすのは、ユーザーが操作しておらず(例: タップもクリックもしていない場合)、次のいずれかの条件を満たす場合です。

  • メインスレッドを合計 60 秒以上使用している
  • メインスレッドを 30 秒間のウィンドウで 15 秒以上使用している
  • 4 メガバイトを超えるネットワーク帯域幅を使用する

広告フレームの子孫 iframe が使用するリソースはすべて、その広告の介入の上限にカウントされます。メインスレッドの制限時間は、広告の読み込みからの経過時間と同じではないことにご注意ください。この上限は、CPU が広告のコードの実行に要する時間です。

介入のテスト

この介入は Chrome 85 でリリースされましたが、ユーザーのプライバシーを保護するために、デフォルトでしきい値にノイズとばらつきが追加されています。

chrome://flags/#heavy-ad-privacy-mitigations無効に設定すると、このような保護設定が解除されます。つまり、制限は純粋に上限に従って決定論的に適用されます。これにより、デバッグとテストが容易になります。

介入がトリガーされると、サイズの大きい広告のコンテンツが iframe 内の「Ad removed」メッセージに置き換えられます。表示された [詳細] リンクをクリックすると、「この広告はデバイスのリソースが多すぎるため、Chrome によって削除されました」というメッセージが表示されます。

weight-ads.glitch.me のサンプル コンテンツに適用される介入は、このテストサイトを使用して任意の URL を読み込むことでも、独自のコンテンツを簡単にテストできます。

テストでは、さまざまな理由によって介入が行われない可能性があることに留意してください。

  • 同じページ内で同じ広告を再読み込みすると、その組み合わせは介入から除外されます。このような場合は、閲覧履歴を消去し、新しいタグでページを開く方法が有効です。
  • ページがフォーカスされたままであることを確認します。ページをバックグラウンドに移動する(別のウィンドウに切り替える)と、ページのタスクキューが一時停止するため、CPU による介入はトリガーされません。
  • テスト中に広告コンテンツをタップまたはクリックしないでください。介入は、ユーザーの操作を受けるコンテンツには適用されません。

必要なご対応について

サイトにサードパーティ プロバイダの広告を表示している

特に対応は必要ありません。サイトで設定された制限を超える広告がユーザーに表示される可能性があることにご注意ください。

自社サイトに自社広告を掲載している、または第三者のディスプレイ広告を掲載している

ヘビー広告介入のための Reporting API を介して必要なモニタリングを実装する際は、このまま読み進めてください。

お客様が広告コンテンツを作成する、または広告コンテンツを作成するためのツールを管理している場合

引き続き読み進めて、コンテンツのパフォーマンスとリソース使用量の問題をテストする方法を理解してください。その他の技術的なアドバイスや制限が適用される場合もあるため、使用する広告プラットフォームのガイダンスも参照してください。たとえば、Google のディスプレイ クリエイティブのガイドラインをご覧ください。パフォーマンスの低い広告の漏えいを防ぐために、構成可能なしきい値を作成ツールに直接組み込むことを検討してください。

広告を削除するとどうなりますか?

Chrome への介入は、Reporting APIintervention のレポートタイプで報告されます。Reporting API を使用すると、レポート エンドポイントへの POST リクエスト、または JavaScript 内で、介入の通知を受け取ることができます。

このレポートは、広告タグが設定されたルートの iframe に対して、その子孫(介入によって取り込まれたすべてのフレーム)とともにトリガーされます。つまり、広告がサードパーティ ソース(クロスサイト iframe など)から配信される場合、そのサードパーティ(広告プロバイダなど)がレポートを処理します。

HTTP レポートにページを設定するには、レスポンスに Report-To ヘッダーを含める必要があります。

Report-To: { "url": "https://example.com/reports", "max_age": 86400 }

トリガーされた POST リクエストには、次のようなレポートが含まれます。

POST /reports HTTP/1.1
Host: example.com
…
Content-Type: application/report

[{
 "type": "intervention",
 "age": 60,
 "url": "https://example.com/url/of/ad.html",
 "body": {
   "sourceFile": null,
   "lineNumber": null,
   "columnNumber": null,
   "id": "HeavyAdIntervention",
   "message": "Ad was removed because its CPU usage exceeded the limit. See https://www.chromestatus.com/feature/4800491902992384"
 }
}]

JavaScript API は、介入時に提供されたコールバックをトリガーするために使用できる observe() メソッドを ReportingObserver に提供します。これは、デバッグに役立つ追加情報をレポートに添付する場合に役立ちます。

// callback that will handle intervention reports
function sendReports(reports) {
  for (let report of reports) {
    // Log the `report` json via your own reporting process
    navigator.sendBeacon('https://report.example/your-endpoint', report);
  }
}

// create the observer with the callback
const observer = new ReportingObserver(
  (reports, observer) => {
    sendReports(reports);
  },
  { buffered: true }
);

// start watching for interventions
observer.observe();

ただし、この介入では文字どおり iframe からページが削除されるため、たとえば iframe 内の広告など、ページが完全に消える前にレポートを確実にキャプチャできるように、フェイルセーフを追加する必要があります。そのためには、同じコールバックを pagehide イベントにフックします。

window.addEventListener('pagehide', (event) => {
  // pull all pending reports from the queue
  let reports = observer.takeRecords();
  sendReports(reports);
});

なお、pagehide イベントは、ユーザー エクスペリエンスを保護するため、そのイベント内で発生する可能性のある作業の量を制限します。たとえば、レポートと一緒に fetch() リクエストを送信しようとすると、そのリクエストはキャンセルされます。そのレポートを送信するには navigator.sendBeacon() を使用する必要があります。それでも、これはブラウザによるベスト エフォートでしかなく、保証されるものではありません。

JavaScript から生成される JSON は、POST リクエストで送信される JSON と似ています。

[
  {
    type: 'intervention',
    url: 'https://example.com/url/of/ad.html',
    body: {
      sourceFile: null,
      lineNumber: null,
      columnNumber: null,
      id: 'HeavyAdIntervention',
      message:
        'Ad was removed because its network usage exceeded the limit. See https://www.chromestatus.com/feature/4800491902992384',
    },
  },
];

介入の原因の診断

広告コンテンツはウェブ コンテンツにすぎないため、Lighthouse などのツールを使用してコンテンツの全体的なパフォーマンスを監査してください。監査の結果は、改善点に関するインライン ガイダンスとなります。また、web.dev/fast コレクションを参照することもできます。

より隔離された環境で広告をテストすることをおすすめします。https://weight-ads.glitch.me のカスタム URL オプションを使用すると、広告のタグが付いた既製の iframe を使ってテストできます。Chrome DevTools を使用して コンテンツが広告としてタグ付けされていることを確認できます[レンダリング] パネル(その他アイコン メニューから [その他のツール] > [レンダリング] からアクセス可能)で、[Highlight Ad Frames] を選択します。トップレベルのウィンドウでコンテンツをテストする場合、または広告としてタグ付けされていないその他のコンテキストでコンテンツをテストする場合、介入はトリガーされませんが、しきい値に対して手動でチェックすることはできます。

フレームの広告ステータスも [Elements] ペインに表示され、<iframe> 開始タグの後に ad アノテーションが追加されます。これは [アプリケーション] パネルの [フレーム] セクションにも表示されます。この広告のタグ付きフレームには「広告ステータス」属性が含まれます。

ネットワーク使用量

Chrome DevTools で [Network] パネルを表示して、広告の全体的なネットワーク アクティビティを確認します。繰り返しの読み込みで一貫した結果を得るには、[Disable cache] チェックボックスをオンにする必要があります。

DevTools の [Network] パネル。
DevTools の [ネットワーク] パネル

ページの下部にある転送値には、ページ全体で転送された金額が表示されます。上部にある [フィルタ] 入力を使用して、リクエストを広告に関連するもののみに限定することを検討してください。

広告に対する最初のリクエスト(iframe のソースなど)が見つかった場合は、リクエスト内の [イニシエータ] タブを使用して、トリガーされたすべてのリクエストを確認することもできます。

リクエストの [Initiator] タブ。
リクエストの [イニシエータ] タブ。

リクエストのリストをサイズ別に並べ替えると、過度に大きいリソースを特定できます。主な原因としては、最適化されていない画像や動画があります。

レスポンスのサイズでリクエストを並べ替えます。
レスポンスのサイズでリクエストを並べ替える。

また、名前で並べ替えると、繰り返しリクエストを見つけるのに適しています。介入をトリガーする大規模なリソースが 1 つでなくても、多数の反復リクエストが段階的に上限を超える場合があります。

CPU 使用状況

DevTools の [パフォーマンス] パネルでは、CPU 使用率の問題を診断できます。まず、キャプチャ設定メニューを開きます。[CPU] プルダウンを使用して、CPU の速度を可能な限り下げます。CPU の介入は、ハイエンドの開発マシンよりも低性能のデバイスでトリガーされる可能性が高くなります。

[パフォーマンス] パネルでネットワークと CPU のスロットリングを有効にします。
[パフォーマンス] パネルでネットワークと CPU のスロットリングを有効にします。

次に、[Record] ボタンをクリックしてアクティビティの記録を開始します。長いトレースの読み込みにはかなりの時間がかかるため、記録するタイミングと時間をテストすることをおすすめします。録画が読み込まれたら、一番上のタイムラインを使用して録画の一部を選択できます。グラフ上のスクリプト、レンダリング、ペイントを表す黄色、紫色、または緑色で点灯している領域に焦点を当てます。

[Performance] パネルでのトレースの概要。
[パフォーマンス] パネルでのトレースの概要

下部の [Bottom-Up]、[Call Tree]、および [Event Log] タブを確認します。これらの列を [Self Time] と [Total Time] で並べ替えると、コード内のボトルネックを特定しやすくなります。

[ボトムアップ] タブでセルフ時間で並べ替えます。
[Bottom-Up] タブで [Self Time] で並べ替える。

関連するソースファイルもここにリンクされているため、それに従って [ソース] パネルまで行ごとにコストを調べることができます。

[ソース] パネルに表示された実行時間。
[ソース] パネルに表示された実行時間

ここで注意すべき一般的な問題としては、付属のライブラリ内に隠されている、継続的なレイアウトとペイントまたはコストのかかるオペレーションをトリガーする、最適化が不十分なアニメーションが挙げられます。

誤った介入を報告する方法

Chrome では、リソース リクエストをフィルタリストと照合して、コンテンツに広告としてタグ付けします。広告以外のコンテンツがタグ付けされている場合は、フィルタリング ルールと一致しないように、そのコードを変更することを検討してください。介入が誤って適用されたと思われる場合は、このテンプレートから問題を報告できます。介入レポートのサンプルをキャプチャし、問題を再現するためのサンプル URL があることを確認してください。