שילוב עם B&A בתור מוכרים

שירותי בידינג ומכרזים (B&A) הם קבוצה של שירותים לקונים ולבעלי תוכן דיגיטלי שמפעילים בסביבת מחשוב אמינה (TEE) כדי להקל על מכרז של קהל מוגן (PA). במדריך למפתחים הזה מוסבר איך מוכרים יכולים לשלב את המודעות שלהם במכרזים של מודעות לרשת החיפוש ב-Chrome ל-B&A.

הדרכה מפורטת

תהליך השילוב של המוכר, שבו קוד ה-JavaScript מקבל את עומס העבודה של מכרז B&A שנשלח ל-SAS, ו-SAS מעביר את הבקשה לקצה הקדמי של המוכר (SFE). SFE מחזיר את התוצאה ש-SAS צריך להעביר לדפדפן, וקוד ה-JavaScript של המוכר קורא ל-runAdAuction.

אפשר לסכם את השלבים כך:

  1. קריאה ל-getInterestGroupAdAuctionData() כדי לקבל את עומס העבודה המוצפן מהדפדפן
  2. קוראים ל-fetch('https://your-ad-server.example') ושולחים את הבקשה למכרז המאוחד עם עומס העבודה המוצפן ל-SAS
  3. קוראים לפעולה SelectAd() של ה-SFE מה-SAS כדי להפעיל את המכרז של B&A
  4. החזרת תוצאת המכרז של B&A לדף יחד עם גיבוב התגובה
  5. קריאה ל-runAdAuction() בדפדפן כדי להפעיל מכרז PA של מוכר יחיד, מכרז PA במצב מעורב או מכרז 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 נדרש. המקור של המוכר שמפעיל את המכרז. הערך הזה צריך להתאים לערך seller בקריאה ל-runAdAuction() בהמשך.
requestSize אופציונלי. הגדרת הגודל המקסימלי של עומס העבודה של כל נתוני הקונים. מידע נוסף זמין בקטע גודל הבקשה במאמר ההסבר.
perBuyerConfig אופציונלי. מגדיר את ההגדרות לכל קונה, וגם קובע אילו קונים ישתתפו במכרז B&A.

אם מקורות של קונים מפורטים ב-perBuyerConfig, רק נתוני קבוצות האינטרסים של הקונים האלה נכללים בעומס העבודה. אם לא רשומים קונים ב-perBuyerConfig, כל קבוצות העניין של המשתמש נכללות בעומס העבודה.

targetSize אופציונלי אם הערך של requestSize מוגדר. חובה אם מוגדר מקור של קונה ב-perBuyerConfig אבל requestSize לא מוגדר.

הגדרת גודל המטען המרבי של נתוני הקונה. מידע נוסף זמין בקטע גודל הבקשה במאמר ההסבר.

coordinatorOrigin אופציונלי, אבל בסופו של דבר יהיה חובה. אם הפרמטר לא מוגדר, ברירת המחדל שלו היא https://publickeyservice.pa.gcp.privacysandboxservices.com.

מגדיר את התיאום לצורך אחזור המפתח להצפנת עומס העבודה. מידע נוסף זמין בקטע רכז במאמר ההסבר.

כשמתבצעת הקריאה, הדפדפן קורא את קבוצות תחומי העניין של הקונים שמפורטים ב-perBuyerConfig ומצפין את נתוני הקונים. נתוני הקונים האלה מכילים מידע מאתרים שונים שמשמש לבידינג, ואי אפשר לפענח אותם מחוץ ל-TEE. לאופטימיזציה של עומס העבודה, רק השם של קבוצת האינטרסים, מפתחות של אותות בידינג מהימנים ואותות הדפדפן נכללים בעומס העבודה.

באובייקט הנתונים של מכרז המודעות שמוחזר על ידי הקריאה getInterestGroupAdAuctionData(), זמינים המחרוזת requestId ומערך הבייטים המוצפן request.

צילום מסך של כלי הפיתוח ל-Chrome שבו מוצגים הבקשה ומזהה הבקשה שזמינים בנתוני המכרז של המודעות

המחרוזת requestId משמשת מאוחר יותר כשמתבצעת קריאה ל-runAdAuction() כדי לסיים את המכרז בדפדפן. המטען הייעודי (payload) המוצפן של request נשלח לשירות המודעות של המוכר כחלק מהבקשה למכרז המאוחד.

דוגמה לקריאה הזו מופיעה בקוד JavaScript של המוכר באפליקציית הבדיקה המקומית.

שליחת הבקשה למכרז המאוחד ל-SAS

אותו תרשים של הדרכה עם הדגשה של השלב השני, שבו קוד ה-JavaScript של המוכר שולח בקשה למכרז מאוחד ל-SAS

בקשה מאוחדת למכרז היא בקשה שמכילה את המטען הייעודי (payload) של מכרז לפי הקשר בטקסט ללא הצפנה ואת המטען הייעודי של מכרז B&A של מודעות לרשת החיפוש. נתוני העומס של מכרז B&A ב-PA הם נתוני request מוצפנים שהדפדפן יצר בקריאה getInterestGroupAdAuctionData(). הבקשה הזו נשלחת ל-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() כדי לסיים את המכרז בדפדפן.
  • המקור של בקשת האחזור חייב להתאים למקור seller שסופק בקריאות getInterestGroupAdAuctionData() ו-runAdAuction().

גוף הקריאה מכיל את הפרטים הבאים:

  1. תוכן טעינה (payload) של מכרז לפי הקשר בטקסט ללא הצפנה, ש-SAS ישתמש בו כדי להפעיל את המכרז לפי הקשר.
  2. נתוני העומס המוצפנים של מכרז Protected Audience, שיישלחו ל-SFE על ידי SAS כדי להפעיל את מכרז הבידינג והביצועים (B&A) מצד השרת.

דוגמה לקריאה הזו מופיעה בקוד JavaScript של המוכר באפליקציית הבדיקה המקומית.

קידוד Base64 ופענוח

המטען הייעודי (payload) המוצפן של request שמוחזר מהקריאה ל-getInterestGroupAdAuctionData() הוא מופע של Uint8Array, שהוא סוג נתונים ש-JSON לא יכול לטפל בו. כדי לשלוח את מערך הבייטים בפורמט JSON, אפשר להחיל קידוד base64 על הנתונים הבינאריים כדי להמיר אותם למחרוזת.

ממשק ה-API של דפדפן JavaScript מספק את הפונקציות atob() ו-btoa() ב-window שממירות בין נתונים בינאריים למחרוזת ASCII בקידוד Base64. (atob מציין המרה מ-ASCII לבינארי, ו-btoa מציין המרה מבינארי ל-ASCII).

קריאה ל-btoa() כדי לקודד נתונים בינאריים למחרוזת בקידוד base64 נראית כך:

function encodeBinaryData(data) {
  return btoa(String.fromCharCode.apply(null, data));
}

תוצאת המכרז המוצפן של B&A שמוחזרת מהקריאה fetch הזו גם היא בקידוד base64, כך שצריך לפענח אותה חזרה לנתונים בינאריים. קוראים לפונקציה atob() כדי לפענח את המחרוזת ASCII בקידוד Base64 לנתונים בינאריים:

function decodeBase64String(base64string) {
  return new Uint8Array(
    atob(base64string)
      .split('')
      .map((char) => char.charCodeAt(0))
  );
}

עם זאת, מחרוזת בקידוד base64 בדרך כלל גדולה ב-33% מהנתונים המקוריים. כדי לשפר עוד יותר את זמן האחזור, אפשר להשתמש בפורמט אחר מלבד JSON כדי לשלוח את הנתונים הבינאריים.

קוראים ל-SelectAd של SFE כדי להפעיל את המכרז של B&A

אותו תרשים של הדרכה, שבו השלב השלישי מודגש. בשלב הזה, ה-SAS שולח בקשה ל-SelectAd ל-SFE, ו-SFE מפעיל מכרז B&A

אחרי ששירות המודעות של מוכרים מקבל מהדף את הבקשה למכרז המאוחד, המכרז לפי הקשר פועל קודם כדי לקבוע את המנצח במכרז לפי הקשר ולאסוף את אותות הקונים שיועברו למכרז ה-B&A של PA. לאחר מכן, מפעילים את המכרז של B&A על ידי קריאה לפעולה SelectAd של SFE מ-SAS עם עומס הבקשה. שימו לב שחלק מהמטא-נתונים מהבקשה של הדף ל-SAS בשלב 2 מועברים ל-SFE.

יצירה של המטען הייעודי (payload) של 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, צריך לפענח אותם חזרה לנתונים בינאריים אם הבקשה ל-SFE נשלחת באמצעות gRPC. אם הבקשה נשלחת באמצעות HTTP, נתוני המכרזים של המודעות המוצפנים יכולים להישאר בפורמט שלהם עם קידוד base64.

כדי לראות שדות אחרים שמוגדרים בבקשה SelectAd, אפשר לעיין בהגדרת ה-proto של 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',
  }
}

התקשרות למספר SelectAd של SFE

אפשר לבצע את הקריאה ל-SFE מ-SAS באמצעות gRPC או HTTP.

קריאה ל-gRPC

בקשת ה-gRPC ל-SFE נראית כך באמצעות 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
});

הגדרת ה-proto של לקוח SFE נמצאת ב מאגר האפליקציות המקומי לבדיקה.

קריאה ל-HTTP לשרת ה-proxy של Envoy

בקשת ה-HTTP POST ל-SFE נשלחת אל הנתיב /v1/selectAd, והיא נראית כך:

fetch('https://ssp-ba.example/sfe/v1/selectAd', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(selectAdRequest),
});

העברת מטא-נתונים

צריך להוסיף את המטא-נתונים הבאים מהקריאה של הדף ל-SAS לקריאה SelectAd של SAS ל-SFE:

כשהמטא-נתונים נשלחים ל-SFE, צריך להשתמש בכותרות הלא סטנדרטיות הבאות כי gRPC עשוי לשנות את הכותרת User-Agent:

  • X-Accept-Language
  • X-User-Agent
  • X-BnA-Client-IP

בדוגמה הבאה מוסבר איך אפשר להעביר את המטא-נתונים באמצעות Express ב-Node עם לקוח 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)
  });
})

מכרז עם כמה מוכרים שמנוהל על ידי שרת

אם אתם מוכרים ברמה העליונה שמפעילים מכרז עם מספר מוכרים שמנוהל על ידי שרת, הקריאה GetComponentAuctionCiphertexts מתבצעת ל-SFE לפני הקריאה SelectAd. התשובה מכילה את עומסי הנתונים (payloads) של מכרז הרכיבים שעבר הצפנה מחדש, ונשלח לשירותי המודעות של מוכר הרכיבים. תוצאות המכרז של מודעות ה-B&A של הרכיב שמוחזרות יסופקו לקריאה SelectAd של ה-SFE של המוכר ברמה העליונה.

מידע נוסף זמין במאמר ההסבר על חשבונות עם כמה אתרי מכירה ב-GitHub.

החזרת תוצאת המכרז של B&A לדף

תרשים זהה של הדרכה עם הדגשה של השלב הרביעי, שבו המערכת של SAS שולחת את תוצאת המכרז של SelectAd בחזרה לדפדפן

בסיום המכרז המשולב, תוצאת המכרז המוצפנת מוחזרת ל-SAS, ו-SAS משיבה לבקשת המכרז המאוחד מהדף שמופיע בשלב 2 עם תוצאת המכרז המוצפנת. בתגובת ה-SAS לדף, הגיבוב מסוג SHA-256 של תוצאת המכרז המוצפן בקידוד base64url מוגדר בכותרת התגובה Ad-Auction-Result. הדפדפן משתמש בגיבוב הזה כדי לאמת את עומס העבודה כשמסיימים את המכרז בלקוח.

יצירת גיבוב SHA-256 עם קידוד base64 נראית כך ב-Node:

import { createHash } from 'crypto';

createHash('sha256')
  .update(binaryData, 'base64')
  .digest('base64url');

הצמדת ה-hash לכותרת התגובה והחזרת תוצאת המכרז לדף נראית כך:

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() כדי לסיים את המכרז בדפדפן. הערך requestId מהקריאה getInterestGroupAdAuctionData() בשלב 1 מועבר גם למכרז.

// 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 מקבל את הערך requestId שהוחזר על ידי הקריאה getInterestGroupAdAuctionData(). השדה serverResponse מקבל מערך בייטים של מכרז ה-B&A שפעל בשלב 3.

דוגמה לקריאה הזו מופיעה בקוד 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 של המוכר באפליקציית הבדיקה המקומית.

מכרז עם כמה מוכרים

אם אתם מוכרים ברמה העליונה שמפעילים מכרז מרובה-מוכרים שמנוהל במכשיר, כל מוכר רכיב שולח את תוצאת המכרז של בדיקת הביצועים וההתאמה ואת הגדרות המכרז במכשיר.

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 של המוכר באפליקציית הבדיקה המקומית.

השלבים הבאים

אחרי שתסיימו לקרוא את המדריך הזה, תוכלו לבצע את השלבים הבאים:

מידע נוסף

יש לך שאלות?