以賣家身分整合 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 中的 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 呼叫:

將中繼資料傳送至 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 回應中,加密競價結果的 SHA-256 雜湊會以 base64url 編碼,並設定在 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() 呼叫,以在瀏覽器中完成競價。步驟 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 程式碼。

後續步驟

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

瞭解詳情

有任何問題嗎?