FLEDGEにおけるWebAssemblyの利用

この記事は MicroAd Advent Calendar 2022 の22日目の記事です。

qiita.com

これまでリターゲティング*1は、3rd Party Cookie*2を利用し、サイトアクセス情報をアドテクのサーバで保存することで実現していました。
しかしChromeで2024年に3rd Party Cookieの廃止が予定されているため、今の仕組みは使えなくなります。 そこでFLEDGEの登場です。

FLEDGEとは

FLEDGEはPrivacy Sandbox*3で提案される、クロスサイトトラッキング技術に依存せずにリターゲティングを実現する仕組みです。
K匿名性やブラウザ上でのオークションなどの技術を利用することにより、ユーザのプライバシーは保護された上で広告配信が行われます。
FLEDGEではざっくりと以下のような流れで処理が行われます。

  1. ユーザが広告主サイトにアクセスした時、buyer(広告主またはDSP)が設置したタグがインタレストグループの情報をブラウザに保存する。
  2. 同じユーザ(ブラウザ)がパブリッシャーサイトにアクセスした時、seller(パブリッシャーまたはSSP)の設置したタグがブラウザ上のオークションを実行し表示する広告を選ぶ。この時、ブラウザに保存されたインタレストグループの情報を利用する。
  3. 広告がFenced Frame(特殊なiframeのようなもの)の中で表示される。

ブラウザ上のオークション処理は入札ワークレットと呼ばれる特別な環境で実行され、通信ができないなどの制限があるため注意が必要です。

FLEDGEの仕組み

もう少し詳しくFLEDGEの仕組みを説明します。
以下で示すコードの例を動かすには、現時点(2022年12月22日)ではChromeで以下のフラグを有効化する必要があります。

  • chrome://flags/#privacy-sandbox-ads-apis
  • chrome://flags/#enable-fenced-frames

インタレストグループ登録

インタレストグループは共通の興味を持つユーザのグループを表し、広告や入札処理に関連する情報が含まれます。
以下はインタレストグループのデータをブラウザに保存するコードの例です。
navigator.joinAdInterestGroupはFLEDGE特有のAPIなのでフラグを有効化している必要があります。

const interestGroup = {
  "owner": "https://example-buyer.com",  // インタレストグループのオーナー
  "name": "item1", // インタレストグループの名前。ownerとペアでインタレストグループは一意になる。
  "biddingLogicUrl": "https://example-buyer/biddingLogic.js", // 入札額計算を行う時に使用する関数を定義したファイルのURL
  "ads": [, // 表示する広告のURLとメタデータ
    {"renderUrl": "https://ads.advertiser-a.com/ads/item1-ad1.html", "metadata": "item1-ad1"},
    {"renderUrl": "https://ads.advertiser-a.com/ads/item1-ad2.html", "metadata": "item1-ad2"}
  ]
}

const kSecPerDay = 30 * 24 * 60 * 60; // インタレストグループの有効期間

navigator.joinAdInterestGroup(interestGroup, kSecPerday)

※ 上記の interestGroupには最低限の値しか設定していません。他にも入札時に使用可能なシグナルなどを設定可能です。

ブラウザ上でのオークション

FLEDGEでは広告のオークション処理がブラウザ上で実行されます。
以下はブラウザ上のオークションを実行するコードの例です。
navigator.runAdAuctionはFLEDGE特有のAPIなのでフラグを有効化している必要があります。

const auctionConfig = {
  "seller": "https://example-seller.com",
  "decisionLogicUrl": "https://example-seller.com/decisionLogic.js",
  "interestGroupBuyers": ["https://example-buyer.com", ...]
};

const opaqeuAds = await navigator.runAdAuction(auctionConfig);

※ 上記のauctionConfigには他にもさまざまな値が設定可能です。

navigator.runAdAuctionが実行されると、ブラウザ内部ではbuyerの定義したgenerateBidとsellerの定義したscoreAdが実行されます。

generateBid

インタレストグループごとに実行され、入札する広告を選択します。
入札処理を行う場合には広告のメタデータや、その他シグナルと呼ばれる情報を用いることが可能です。

generateBid(interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals, browserSignals, directFromSellerSignals) {
  ...
  return {'ad': adObject,
          'bid': bidValue,
          'render': renderUrl,
          'adComponents': [adComponent1, adComponent2, ...],
          'allowComponentAuction': false};
}

scoreAd

generateBidで入札された広告ごとに、入札額を調整するような処理をseller側で定義したコードで実行します。

scoreAd(adMetadata, bid, auctionConfig, trustedScoringSignals, browserSignals, directFromSellerSignals) {
  ...
  return {desirability: desirabilityScoreForThisAd,
          allowComponentAuction: componentAuctionsAllowed};
}

WebAssembly

WebAssemblyを利用することで実行速度の問題を解決可能な場合があります(WebAssemblyではJavaScriptエンジンによる呼び出しではなく、機械語レベルでの呼び出しを用いる)。
WebAssemblyのユースケースとしては以下が参考になります。
Use Cases - WebAssembly

C/C++やRustなどのコードをWebAssemblyバイナリにコンパイルし、ブラウザがWebAssemblyバイナリを機械語のコードにコンパイルします。
C/C++ではEmscripten、Rustではwasm-bindgenを利用することでWebAssemblyバイナリを生成できます。

Main — Emscripten 3.1.26-git (dev) documentation

Introduction - The `wasm-bindgen` Guide

FLEDGEにおけるWebAssemblyの利用

WebAssemblyがFLEDGEにどう関わってくるのでしょうか。
入札額計算が実行される入札ワークレットで複雑な計算を行うと、パフォーマンスが大幅に低下しタイムアウト制限を超えてしまう問題がありました。
詳細は以下のissueで議論されています。

Bidding worklet performance limitations · Issue #215 · WICG/turtledove · GitHub

generateBidでのタイムアウトを回避するためにWebAssemblyを使用することが可能です。
インタレストグループに登録するデータとして biddingWasmHelperUrl という項目が指定可能で、ブラウザでの入札額計算実行前に指定したURLからWebAssemblyバイナリを取得し、入札関数に引数としてWebAssemblyモジュールを渡してくれます。

インタレストグループでのbiddingWasmHelperUrl登録例

const interestGroup = {
  "owner": "https://example-buyer.com", 
  "name": "item1", 
  "biddingLogicUrl": "https://example-buyer/biddingLogic.js",
  "biddingWasmHelperUrl": "https://example-buyer.com/wasm",  // WebAssemblyバイナリを取得するURL
  "ads": [,
    {"renderUrl": "https://ads.advertiser-a.com/ads/item1-ad1.html", "metadata": "item1-ad1"},
    {"renderUrl": "https://ads.advertiser-a.com/ads/item1-ad2.html", "metadata": "item1-ad2"}
  ]
}

入札額計算実行前に指定したURLからWebAssemblyモジュールを取得し、generateBid関数のbrowserSignalsから取得可能です。

function generateBid(interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals, browserSignals, directFromSellerSignals) {
  ...
  const wasmInstance = (new WebAssembly.Instance(browserSignals.wasmHelper)).exports;
  const bid = wasmInstance.bid(interestGroup.ads); // bidは入札額計算を行う関数とする
  ...
}

これを利用することで複雑な計算処理を高速化することが可能になり、ブラウザ上でのオークションでも精度の高い入札が行えることが期待できます。

さいごに

FLEDGEの仕組みとWebAssemblyがどう利用されているのかを簡単に紹介しました。
まだまだ仕様変更が入ることが考えられるため、今後も動向を追っていきたいです。

参考

turtledove/FLEDGE.md at main · WICG/turtledove · GitHub

FLEDGE API - Chrome Developers

FLEDGE RTB origin trial  |  Real-time Bidding  |  Google Developers

*1:サイトにアクセスしたユーザに対してそのサイトの広告を配信するターゲティング

*2:アクセスしたサイトのドメインとは別のドメインが発行するCookieのこと。

*3:3rd Party Cookieやその他のトラッキング技術を用いずにクロスサイトのユースケースを満たす一連の提案。