出價和競價 (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,由 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 會將加密的 Protected Audience 競價酬載傳送至 SFE,以執行伺服器端 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 的通訊協定定義。
為混合模式和元件競價設定頂層賣家欄位
如果賣家執行混合模式競價,或以元件賣家身分參與多賣家競價,則需要在要求中定義 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 呼叫
使用 Node 中的 Express 和 gRPC 用戶端,向 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 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-LanguageUser-Agent- IP 位址
將中繼資料傳送至 SFE 時,必須使用下列非標準標頭,因為 gRPC 可能會變更 User-Agent 標頭:
X-Accept-LanguageX-User-AgentX-BnA-Client-IP
以下範例說明如何使用 Node 中的 Express,透過 gRPC 用戶端轉送中繼資料:
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 呼叫前,先對 SFE 發出 GetComponentAuctionCiphertexts 呼叫。回應包含重新加密的元件競價酬載,這些酬載會傳送至元件賣方廣告服務。系統會將傳回的元件 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 架構
- 請按照端對端本機測試程式碼研究室的說明,透過 B&A 實驗 Protected Audience。
有任何問題嗎?
- 如果您對出價與競價服務有疑問,請在出價與競價服務存放區中開啟問題。