以賣家身分整合 B&A

出價和競價 (B&A) 服務是一組廣告買方和賣方適用的服務,可在受信任的執行環境 (TEE) 中運作,協助進行 Protected Audience (PA) 競價。本開發人員指南說明賣家如何整合 Chrome PA 競價,以進行 B&A。

逐步操作說明

賣方整合流程:JavaScript 程式碼會取得傳送至 SAS 的 B&A 競價酬載,而 SAS 會將要求轉送至賣方前端 (SFE)。SFE 會傳回 SAS 應轉送至瀏覽器的結果,而賣方 JavaScript 程式碼會呼叫 runAdAuction

步驟如下:

  1. 呼叫 getInterestGroupAdAuctionData(),從瀏覽器取得加密酬載
  2. 呼叫 fetch('https://your-ad-server.example'),並將含有加密酬載的統一競價要求傳送至 SAS
  3. 從 SAS 呼叫 SFE 的 SelectAd() 作業,執行 B&A 競價
  4. 將 B&A 競價結果連同回應的雜湊值傳回網頁
  5. 在瀏覽器中呼叫 runAdAuction(),執行單一賣家、混合模式或多重賣家 PA 競價,並將伺服器端 B&A 競價結果傳遞至呼叫

取得加密的廣告競價資料

這張圖與上圖相同,但第一個步驟已醒目顯示,也就是賣家 JavaScript 程式碼呼叫 getInterestGroupAdAuctionData 時

如要取得執行伺服器端 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 競價。

如果 perBuyerConfig 中列出買家來源,酬載中只會包含這些買家興趣群組資料。如果 perBuyerConfig 中未列出任何買方,則酬載會包含使用者的所有興趣群組。

targetSize 如果已設定 requestSize,則為選用屬性。如果買家來源是在 perBuyerConfig 中設定,但 requestSize 未設定,則為必填

設定該買家資料的酬載大小上限。詳情請參閱說明文章的「要求大小」一節。

coordinatorOrigin 選填,但日後會成為必填欄位。如未設定,則預設為 https://publickeyservice.pa.gcp.privacysandboxservices.com

設定用於擷取酬載加密金鑰的協調器。詳情請參閱說明文章的「協調員」一節。

發出呼叫時,瀏覽器會讀取 perBuyerConfig 中列出的買家興趣群組,並加密買家資料。這項買家資料包含用於出價的跨網站資訊,且無法在 TEE 以外解密。為最佳化酬載,酬載中只會納入興趣群組名稱、受信任的出價信號鍵和瀏覽器信號。

getInterestGroupAdAuctionData() 呼叫傳回的廣告競價資料物件中,會提供 requestId 字串和加密的 request 位元組陣列。

Chrome 開發人員工具的螢幕截圖,顯示廣告競價資料中提供的要求和要求 ID。

稍後呼叫 runAdAuction() 以在瀏覽器中完成競價時,會用到 requestId 字串。加密的 request 酬載會做為統一競價要求的一部分,傳送至賣方廣告服務。

如要查看這項呼叫的範例,請參閱本機測試應用程式的賣家 JavaScript 程式碼

將統一競價要求傳送至 SAS

這張圖與上一個相同,但第二個步驟已醒目顯示,也就是賣方 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 來源相符。

呼叫內容包含:

  1. SAS 用於執行內容比對競價的純文字內容比對競價酬載。
  2. 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 競價

同一張逐步解說圖,但第三個步驟已醒目顯示。這個步驟是 SAS 將 SelectAd 要求傳送至 SFE,而 SFE 執行 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 中的 ExpressgRPC 用戶端,向 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 呼叫:

將中繼資料傳送至 SFE 時,必須使用下列非標準標頭,因為 gRPC 可能會變更 User-Agent 標頭:

  • X-Accept-Language
  • X-User-Agent
  • X-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 競價結果傳回網頁

與先前相同的逐步說明圖表,但這次醒目顯示第四個步驟,也就是 SAS 將 SelectAd 的競價結果傳回瀏覽器

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() 以完成競價

與先前相同的逐步解說流程圖,但第五個步驟已醒目顯示,也就是用戶端 JavaScript 程式碼執行競價並提供伺服器回應的步驟。

SAS 傳回的統一競價回應包含加密的 B&A 競價結果。這個酬載會傳遞至 runAdAuction() 呼叫,以在瀏覽器中完成競價。步驟 1getInterestGroupAdAuctionData() 呼叫的 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() 呼叫傳回的 requestIdserverResponse 欄位接受在步驟 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 程式碼

後續步驟

閱讀本指南後,您可以採取下列後續步驟:

瞭解詳情

有任何問題嗎?