以賣家身分整合 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,在該處協調內容相關競價和 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 傳送至 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 競價

同一個逐步操作說明圖表,其中第三個步驟已醒目顯示,這是當 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 的 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 呼叫:

傳送至 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 競價結果傳回至網頁

同一個逐步操作說明圖表,其中第四步驟已加以醒目標示,這是 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 程式碼

後續步驟

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

瞭解詳情

有任何問題嗎?