出價和競價 (B&A) 服務是一組服務,適用於在可信執行環境 (TEE) 中執行的廣告買方和賣方,可協助進行 Protected Audience (PA) 競價。本開發人員指南說明賣家如何整合 Chrome PA 競價,以便進行 B&A。
逐步操作說明
步驟可歸納為以下幾點:
- 呼叫
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
位元組陣列。
稍後在呼叫 runAdAuction()
以在瀏覽器中完成競價時,會使用 requestId
字串。系統會將已加密的 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 用於執行內容相關競價的純文字內容相關競價酬載。
- 由 SAS 傳送至 SFE 的加密 Protected Audience 競價酬載,用於執行伺服器端 B&A 競價。
如需此呼叫的範例,請參閱本機測試應用程式的賣方 JavaScript 程式碼。
Base64 編碼和解碼
從 getInterestGroupAdAuctionData()
呼叫傳回的加密 request
酬載是 Uint8Array
的例項,這是 JSON 無法處理的資料類型。如要以 JSON 格式傳送位元組陣列,您可以將 base64 編碼套用至二進位資料,將其轉換為字串。
JavaScript 瀏覽器 API 在 window
上提供 atob()
和 btoa()
函式,可在二進位資料和 Base64 編碼 ASCII 字串之間轉換。(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 編碼,則在使用 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
您可以使用 gRPC 或 HTTP 從 SAS 呼叫 SFE。
gRPC 呼叫
傳送至 SFE 的 gRPC 要求如下所示,使用 Express 搭配 Node 中的 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 Proxy 的 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 位址
傳送至 SFE 的中繼資料必須使用下列非標準標頭,因為 gRPC 可能會變更 User-Agent
標頭:
X-Accept-Language
X-User-Agent
X-BnA-Client-IP
以下範例說明如何在 Node 中使用 gRPC 用戶端,透過 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)
});
})
由伺服器協調的多個賣方競價
如果您是執行伺服器協調多賣家競價的頂層賣家,系統會先向 SFE 發出 GetComponentAuctionCiphertexts
呼叫,再發出 SelectAd
呼叫。回應包含傳送至元件賣家廣告服務的重新加密元件競價酬載。系統會將傳回的 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
中加入多個雜湊。以下兩個回應標頭的效果相同:
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 實驗 Protected Audience。
有任何問題嗎?
- 如果您對出價與競價服務有任何疑問,請在 B&A Services 存放區中提出問題。
- 如果您對 Privacy Sandbox 有任何疑問,請在 privacy-sandbox-dev-support 存放區中提出問題。