入札およびオークション(B&A)サービスは、広告の購入者と販売者向けのサービス群で、高信頼実行環境(TEE)で実行され、Protected Audience(PA)オークションを促進します。このデベロッパー ガイドでは、販売者が B&A の Chrome PA オークションと統合する方法について説明します。
チュートリアル
手順の概要は次のとおりです。
getInterestGroupAdAuctionData()を呼び出して、ブラウザから暗号化されたペイロードを取得します。fetch('https://your-ad-server.example')を呼び出し、暗号化されたペイロードを含む統合オークション リクエストを SAS に送信します。- SAS から SFE の
SelectAd()オペレーションを呼び出して、B&A オークションを実行します。 - B&A オークションの結果とレスポンスのハッシュをページに返す
- ブラウザで
runAdAuction()を呼び出して、単一販売者、混合モード、複数販売者の PA オークションを実行し、サーバーサイドの B&A オークションの結果を呼び出しに渡します。
暗号化された広告オークション データを取得する
サーバーサイドの B&A オークションの実行に必要なデータを取得するため、パブリッシャー ページの販売者の JavaScript コードが navigator.getInterestGroupAdAuctionData() を呼び出します。
const adAuctionData = await navigator.getInterestGroupAdAuctionData({
seller: 'https://ssp.example', // Required
requestSize: 51200,
coordinatorOrigin: 'https://publickeyservice.pa.gcp.privacysandboxservices.com/',
perBuyerConfig: {
'https://dsp-x.example': { targetSize: 8192 },
'https://dsp-y.example': { targetSize: 8192 }
}
});
const { requestId, request } = adAuctionData;
| フィールド | 説明 |
|---|---|
seller |
必須。オークションを実施している販売者の所在地。この値は、後で runAdAuction() 呼び出しの seller 値と一致する必要があります。 |
requestSize |
(省略可)すべての購入者データの最大ペイロード サイズを設定します。詳しくは、説明のリクエスト サイズのセクションをご覧ください。 |
perBuyerConfig |
(省略可)購入者ごとに構成を設定し、B&A オークションに参加する購入者を制御します。 購入者のオリジンが |
targetSize |
requestSize が設定されている場合は省略可。perBuyerConfig で購入者の配信元が設定されているが、requestSize が設定されていない場合は必須です。購入者のデータの最大ペイロード サイズを設定します。詳しくは、説明のリクエスト サイズのセクションをご覧ください。 |
coordinatorOrigin |
省略可ですが、最終的には必須になります。設定しない場合、デフォルトは https://publickeyservice.pa.gcp.privacysandboxservices.com です。ペイロードの暗号化に使用する鍵を取得するために使用するコーディネーターを設定します。詳しくは、説明のコーディネーターのセクションをご覧ください。 |
呼び出しが行われると、ブラウザは perBuyerConfig に記載されている購入者のインタレスト グループを読み取り、購入者データを暗号化します。この購入者データには入札に使用されるクロスサイト情報が含まれており、TEE の外部で復号することはできません。ペイロードの最適化では、インタレスト グループ名、信頼できる入札シグナルのキー、ブラウザ シグナルのみがペイロードに含まれます。
getInterestGroupAdAuctionData() 呼び出しで返される広告オークション データ オブジェクトには、requestId 文字列と暗号化された request バイト配列が含まれています。
requestId 文字列は、ブラウザでオークションを終了するために runAdAuction() が呼び出されるときに使用されます。暗号化された request ペイロードは、統一オークション リクエストの一部として販売者広告サービスに送信されます。
この呼び出しの例については、ローカル テストアプリの販売者 JavaScript コードをご覧ください。
統合オークション リクエストを SAS に送信する
統合オークション リクエストは、プレーンテキストのコンテキスト オークション ペイロードと PA B&A オークション ペイロードを含むリクエストです。PA B&A オークション ペイロードは、ブラウザが getInterestGroupAdAuctionData() 呼び出しで生成した暗号化された request データです。このリクエストは SAS に送信され、コンテキスト オークションと PA B&A オークションが調整されます。
fetch('https://ssp.example/ad-auction', {
method: 'POST',
adAuctionHeaders: true,
body: JSON.stringify({
contextualAuctionPayload: { somePayload },
protectedAudienceAuctionPayload: encodeBinaryData(request)
}),
});
リクエストを SAS に送信するために、ページから fetch() 呼び出しが行われます。
- 呼び出しには
adAuctionHeaders: trueオプションを含める必要があります。このオプションは、ブラウザでオークションを終了するためにrunAdAuction()が呼び出されたときに、この呼び出しのレスポンスを後で検証するようブラウザに指示します。 - フェッチ リクエストのオリジンは、
getInterestGroupAdAuctionData()とrunAdAuction()の呼び出しに渡されたsellerオリジンと一致する必要があります。
呼び出しの本文には次の情報が含まれます。
- SAS がコンテキスト オークションを実行するために使用する、プレーン テキストのコンテキスト オークション ペイロード。
- サーバーサイドの B&A オークションを実行するために SAS が SFE に送信する、暗号化された Protected Audience オークション ペイロード。
この呼び出しの例については、ローカル テストアプリの販売者 JavaScript コードをご覧ください。
Base64 エンコーディングとデコーディング
getInterestGroupAdAuctionData() 呼び出しから返される暗号化された request ペイロードは、JSON で処理できないデータ型である Uint8Array のインスタンスです。JSON 形式でバイト配列を送信するには、バイナリデータに base64 エンコードを適用して文字列に変換します。
JavaScript ブラウザ API は、バイナリデータと base64 でエンコードされた ASCII 文字列の間で変換を行う window の atob() 関数と btoa() 関数を提供します。(atob は ASCII からバイナリへの変換、btoa はバイナリから ASCII への変換を意味します)。
バイナリデータを base64 でエンコードされた文字列にエンコードする btoa() の呼び出しは次のようになります。
function encodeBinaryData(data) {
return btoa(String.fromCharCode.apply(null, data));
}
この fetch 呼び出しから返される暗号化された B&A オークション結果も base64 エンコード形式であるため、バイナリデータにデコードする必要があります。atob() を呼び出して、base64 でエンコードされた ASCII 文字列をバイナリデータにデコードします。
function decodeBase64String(base64string) {
return new Uint8Array(
atob(base64string)
.split('')
.map((char) => char.charCodeAt(0))
);
}
ただし、base64 でエンコードされた文字列は、通常、元のデータよりも約 33% 大きくなります。レイテンシをさらに改善する場合は、JSON 以外の形式を使用してバイナリデータを送信します。
SFE の SelectAd を呼び出して B&A オークションを実行する
販売者の広告サービスがページから統合オークション リクエストを受け取ると、まずコンテキスト オークションが実行され、コンテキスト オークションの落札者が決定され、PA B&A オークションに渡される購入者のシグナルが収集されます。次に、リクエスト ペイロードを使用して SAS から SFE の SelectAd オペレーションを呼び出すことで、B&A オークションが開始されます。ステップ 2 で SAS へのページのリクエストから取得されたメタデータの一部は、SFE に転送されます。
SelectAdRequest ペイロードを作成する
SelectAd 呼び出しのリクエスト ペイロードは、次のように構築できます。
const selectAdRequest = {
auction_config: {
seller: 'https://ssp.example',
auction_signals: '{"testKey":"someValue"}',
seller_signals: '{"testKey":"someValue"}',
buyer_list: [
'https://dsp-x.example',
'https://dsp-y.example',
],
per_buyer_config: {
'https://dsp-x.example': { buyer_signals: '{"testKey": "someValue"}' },
'https://dsp-y.example': { buyer_signals: '{"testKey": "someValue"}' },
},
},
client_type: 'CLIENT_TYPE_BROWSER',
protected_auction_ciphertext: decodeBase64string(request)
};
ブラウザから送信された暗号化された広告オークション データが base64 でエンコードされている場合、gRPC を使用して SFE にリクエストを送信するときに、バイナリデータにデコードする必要があります。リクエストが HTTP を使用して送信される場合、暗号化された広告オークション データは base64 でエンコードされた形式のままにできます。
SelectAd リクエストで定義されている他のフィールドを確認するには、SelectAdRequest の proto 定義をご覧ください。
混合モードとコンポーネント オークションの最上位の販売者フィールドを設定する
販売者が混合モードのオークションを実施している場合、または複数販売者オークションにコンポーネント販売者として参加している場合は、リクエストで top_level_seller フィールドを定義する必要があります。
混合モードの販売者の場合、top_level_seller の値はオリジンです。
const selectAdRequest = {
auction_config: {
seller: 'https://ssp-mix.example',
top_level_seller: 'https://ssp-mix.example',
}
}
コンポーネント販売者の場合、top_level_seller の値はマルチ販売者オークションの最上位の販売者です。
const selectAdRequest = {
auction_config: {
seller: 'https://ssp-mix.example',
top_level_seller: 'https://ssp-top.example',
}
}
SFE の SelectAd に電話する
SAS から SFE への呼び出しは、gRPC または HTTP で行うことができます。
gRPC 呼び出し
gRPC クライアントを使用して Node で Express を使用した SFE への gRPC リクエストは次のようになります。
import grpc from '@grpc/grpc-js';
// Load proto definition
const packageDefinition = protoLoader.loadSync(protoPath, { keepCase: true, enums: String });
const {
privacy_sandbox: {
bidding_auction_servers: { SellerFrontEnd }
}
} = grpc.loadPackageDefinition(packageDefinition);
// Instantiate the gRPC client
const sfeGrpcClient = new SellerFrontEnd('192.168.84.104:50067', grpc.credentials.createInsecure());
// Send SelectAd request
sfeGrpcClient.selectAd(selectAdRequest,(error, response) => {
// Handle SFE response
});
SFE クライアントの proto 定義は、 ローカル テストアプリ リポジトリにあります。
Envoy プロキシへの HTTP 呼び出し
SFE への HTTP POST リクエストは /v1/selectAd パスに送信され、次のようになります。
fetch('https://ssp-ba.example/sfe/v1/selectAd', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(selectAdRequest),
});
転送メタデータ
ページの SAS 呼び出しからの次のメタデータを、SFE への SAS の SelectAd 呼び出しに追加する必要があります。
Accept-LanguageUser-Agent- IP アドレス
メタデータを SFE に送信するときは、次の非標準ヘッダーを使用する必要があります。これは、gRPC が User-Agent ヘッダーを変更する可能性があるためです。
X-Accept-LanguageX-User-AgentX-BnA-Client-IP
次の例は、gRPC クライアントを使用して Node の Express でメタデータを転送する方法を示しています。
sellerAdService.post('/ad-auction', (req, res) => {
// …
const metadata = new grpc.Metadata();
metadata.add('X-Accept-Language', req.header('Accept-Language'));
metadata.add('X-User-Agent', req.header('User-Agent'));
metadata.add('X-BnA-Client-IP', req.ip);
const sfeGrpcClient = createSfeGrpcClient();
sfeGrpcClient.selectAd(selectAdRequest, metadata, callbackFn);
})
HTTP 呼び出しを使用してメタデータを転送する方法の例を次に示します。
sellerAdService.post('/ad-auction', (req, res) => {
// …
fetch('https://ssp-ba.example/sfe/v1/selectAd', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Accept-Language': req.header('Accept-Language'),
'X-User-Agent': req.header('User-Agent'),
'X-BnA-Client-IP': req.ip
},
body: JSON.stringify(selectAdRequest)
});
})
サーバー オーケストレーションによるマルチセラー オークション
サーバー オーケストレーションによる複数販売者オークションを実施している最上位の販売者の場合、SelectAd 呼び出しが行われる前に GetComponentAuctionCiphertexts 呼び出しが SFE に対して行われます。レスポンスには、コンポーネント販売者の広告サービスに送信される、再暗号化されたコンポーネント オークション ペイロードが含まれます。返されたコンポーネント B&A 広告オークションの結果は、トップレベルの販売者の SFE の SelectAd 呼び出しに提供されます。
詳しくは、GitHub のマルチベンダーの説明をご覧ください。
B&A オークションの結果をページに返す
B&A オークションが終了すると、暗号化されたオークション結果が SAS に返され、SAS はステップ 2 のページからの統合オークション リクエストに対して、暗号化されたオークション結果で応答します。ページに対する SAS レスポンスでは、暗号化されたオークション結果の base64url エンコードされた SHA-256 ハッシュが Ad-Auction-Result レスポンス ヘッダーに設定されます。このハッシュは、クライアントでオークションが終了したときに、ブラウザがペイロードを検証するために使用されます。
Node で base64 エンコードを使用して SHA-256 ハッシュを作成すると、次のようになります。
import { createHash } from 'crypto';
createHash('sha256')
.update(binaryData, 'base64')
.digest('base64url');
レスポンス ヘッダーにハッシュを付加してオークション結果をページに返す処理は、次のようになります。
sellerAdService.post('/ad-auction', (req, res) => {
// …
sfeGrpcClient.selectAd(selectAdRequest, metadata, (error, response) => {
const { auction_result_ciphertext } = response;
const ciphertextShaHash = createHash('sha256')
.update(auction_result_ciphertext, 'base64')
.digest('base64url');
res.set('Ad-Auction-Result', ciphertextShaHash);
res.json({
protectedAudienceAuctionResult: encodeBinaryData(auction_result_ciphertext),
contextualAuctionResult: getContextualAuctionResult()
});
});
})
これは、ステップ 2 のページから行われた統合オークション リクエストに対するレスポンスであるため、コンテキストに基づくオークション結果もレスポンスに含まれます。
複数のハッシュを Ad-Auction-Result に含めるには、ヘッダーを繰り返すか、ハッシュを区切ります。次の 2 つのレスポンス ヘッダーは同等です。
Ad-Auction-Result: ungWv48Bz-pBQUDeXa4iI7ADYaOWF3qctBD_YfIAFa0=,9UTB-u-WshX66Xqz5DNCpEK9z-x5oCS5SXvgyeoRB1k=
Ad-Auction-Result: ungWv48Bz-pBQUDeXa4iI7ADYaOWF3qctBD_YfIAFa0=
Ad-Auction-Result: 9UTB-u-WshX66Xqz5DNCpEK9z-x5oCS5SXvgyeoRB1k=
この呼び出しの例については、ローカル テストアプリの販売者サーバーコードをご覧ください。
runAdAuction() を呼び出してオークションを完了します。
SAS から返される統合オークション レスポンスには、暗号化された B&A オークション結果が含まれます。このペイロードは runAdAuction() 呼び出しに渡され、ブラウザでオークションが終了します。ステップ 1 の getInterestGroupAdAuctionData() 呼び出しからの requestId 値もオークションに渡されます。
// Get the encrypted ad auction data (Step #1)
const { requestId, request } = navigator.getInterestGroupAdAuctionData(adAuctionDataConfig)
// Send unified auction request (Step #2)
const response = await fetch('https://ssp-ba.example/ad-auction', {
method: 'POST',
body: JSON.stringify({
adAuctionRequest: encodeBinaryData(request),
}),
});
const { protectedAudienceAuctionResult } = await response.json();
// Finish the auction in the browser
await navigator.runAdAuction({
// pass in "requestId" and "protectedAudienceAuctionResult"
// the config structure will differ based on the auction configuration
});
runAdAuction() 呼び出しに渡されるオークション構成の構造は、販売者が選択したオークション構成によって異なります。
単一販売者オークション
単一販売者の B&A オークションを実行する場合、runAdAuction() 呼び出しのオークション構成は次のようになります。
await navigator.runAdAuction({
seller: 'https://ssp-ba.example',
requestId,
serverResponse: protectedAudienceAuctionResult,
});
requestId フィールドには、getInterestGroupAdAuctionData() 呼び出しによって返された requestId を指定します。serverResponse フィールドには、ステップ 3 で実行された B&A オークションのバイト配列を指定します。
この呼び出しの例については、ローカル テストアプリの販売者 JavaScript コードをご覧ください。
混合モードのオークション
オンデバイス購入者と B&A 購入者の両方が参加できる混合モードの B&A オークションを実行する場合、runAdAuction() 呼び出しのオークション構成は次のようになります。
await navigator.runAdAuction({
seller: 'https://ssp-mix.example',
decisionLogicURL: 'https://ssp-mix.example/score-ad.js',
componentAuctions: [
// B&A auction result
{
seller: 'https://ssp-mix.example',
requestId,
serverResponse: protectedAudienceAuctionResult,
},
// On-device auction config
{
seller: 'https://ssp-mix.example',
decisionLogicURL: 'https://ssp-mix.example/on-device-score-ad.js',
interestGroupBuyers: [
'https://dsp-a.example', // On-device buyer
'https://dsp-a.example', // On-device buyer
],
},
]
});
混合モードのオークションを容易にするため、B&A オークションの結果とオンデバイス オークションの構成が componentAuctions フィールドに渡されます。混合モード オークションでは、最上位の構成とコンポーネント構成の両方で seller の値が同じになります。
この呼び出しの例については、ローカル テストアプリの販売者 JavaScript コードをご覧ください。
マルチセラー オークション
デバイス オーケストレーションによる複数販売者オークションを実施するトップレベルの販売者の場合、各コンポーネント販売者は B&A オークションの結果とオンデバイス オークションの設定を送信します。
await navigator.runAdAuction({
seller: 'https://ssp-top.example',
decisionLogicURL: 'https://ssp-top.example/score-ad.js',
componentAuctions: [
// SSP-BA's B&A-only auction result
{
seller: 'https://ssp-ba.example',
requestId: 'g8312cb2-da2d-4e9b-80e6-e13dec2a581c',
serverResponse: Uint8Array(560) [193, 120, 4, …] // Encrypted B&A auction result
},
// SSP-MIX's B&A auction result
{
seller: 'https://ssp-mix.example',
requestId: 'f5135cb2-da2d-4e9b-80e6-e13dec2a581c',
serverResponse: Uint8Array(560) [133, 20, 4, …] // Encrypted B&A auction result
}.
// SSP-MIX's on-device auction config
{
seller: 'https://ssp-mix.example',
interestGroupBuyers: ['https://dsp-a.example', 'https://dsp-b.example'],
decisionLogicURL: 'https://ssp-mix.example/score-ad.js',
}
// SSP-OD's on-device auction config
{
seller: 'https://ssp-od.example',
interestGroupBuyers: ['https://dsp-a.example', 'https://dsp-b.example'],
decisionLogicURL: 'https://ssp-od.example/score-ad.js',
}
]
})
この呼び出しの例については、ローカル テストアプリの販売者 JavaScript コードをご覧ください。
次のステップ
このガイドを読んだら、次の手順に進むことができます。
その他の情報
- 詳細については、GitHub の次の説明をご覧ください。
- ウェブ向けの B&A アーキテクチャの詳細
- エンドツーエンドのローカル テストの Codelab に沿って、B&A で Protected Audience をテストします。
ご不明な点がある場合
- 入札とオークション サービスについてご不明な点がある場合は、B&A サービス リポジトリで issue を作成してください。