入札とオークション(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 オークションの結果を呼び出しに渡します。
暗号化された広告オークション データを取得する
パブリッシャー ページの販売者の JavaScript コードは、サーバーサイドの B&A オークションの実行に必要なデータを取得するために 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
ペイロードは Uint8Array
のインスタンスであり、JSON で処理できないデータ型です。バイト配列を JSON 形式で送信するには、バイナリデータに base64 エンコードを適用して文字列に変換します。
JavaScript ブラウザ API には、バイナリデータと base64 でエンコードされた ASCII 文字列を変換する window
の atob()
関数と btoa()
関数があります。(atob
は ASCII からバイナリへの変換、btoa
はバイナリから ASCII への変換を意味します)。
btoa()
を呼び出してバイナリデータを base64 エンコード文字列にエンコードするコードは次のようになります。
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 でエンコードされている場合、SFE へのリクエストを gRPC を使用して送信する場合は、バイナリデータにデコードし直す必要があります。リクエストが HTTP を使用して送信される場合、暗号化された広告オークション データは Base64 エンコードされた形式のままにできます。
SelectAd
リクエストで定義されている他のフィールドについては、SelectAdRequest
のプロト定義をご覧ください。
混合モードとコンポーネント オークションの最上位の販売者フィールドを設定する
販売者が混合モード オークションを実施している場合、または複数販売者オークションにコンポーネント販売者として参加している場合は、リクエストで 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 呼び出し
SFE への gRPC リクエストは、gRPC クライアントを使用して Node の Express を使用すると次のようになります。
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 クライアントのプロト定義は、 ローカル テストアプリ リポジトリにあります。
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 呼び出しからの次のメタデータを、SAS の SFE への SelectAd
呼び出しに追加する必要があります。
Accept-Language
User-Agent
- IP アドレス
gRPC が User-Agent
ヘッダーを変更する可能性があるため、メタデータを SFE に送信する場合は、次の標準以外のヘッダーを使用する必要があります。
X-Accept-Language
X-User-Agent
X-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 に沿って、Protected Audience と B&A をテストします。
ご不明な点がある場合
- 入札とオークション サービスについてご不明な点がある場合は、B&A Services リポジトリで issue を作成してください。
- プライバシー サンドボックス全般に関する質問がある場合は、privacy-sandbox-dev-support リポジトリでイシューを作成してください。