שירותי בידינג ומכרזים (B&A) הם קבוצה של שירותים לקונים ולבעלי תוכן דיגיטלי שמפעילים בסביבת מחשוב אמינה (TEE) כדי להקל על מכרז של קהל מוגן (PA). במדריך למפתחים הזה מוסבר איך מוכרים יכולים לשלב את המודעות שלהם במכרזים של מודעות לרשת החיפוש ב-Chrome ל-B&A.
הדרכה מפורטת
אפשר לסכם את השלבים כך:
- קריאה ל-
getInterestGroupAdAuctionData()
כדי לקבל את עומס העבודה המוצפן מהדפדפן - קוראים ל-
fetch('https://your-ad-server.example')
ושולחים את הבקשה למכרז המאוחד עם עומס העבודה המוצפן ל-SAS - קוראים לפעולה
SelectAd()
של ה-SFE מה-SAS כדי להפעיל את המכרז של B&A - החזרת תוצאת המכרז של B&A לדף יחד עם גיבוב התגובה
- קריאה ל-
runAdAuction()
בדפדפן כדי להפעיל מכרז PA של מוכר יחיד, מכרז PA במצב מעורב או מכרז 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 |
נדרש. המקור של המוכר שמפעיל את המכרז. הערך הזה צריך להתאים לערך seller בקריאה ל-runAdAuction() בהמשך.
|
requestSize |
אופציונלי. הגדרת הגודל המקסימלי של עומס העבודה של כל נתוני הקונים. מידע נוסף זמין בקטע גודל הבקשה במאמר ההסבר. |
perBuyerConfig |
אופציונלי. מגדיר את ההגדרות לכל קונה, וגם קובע אילו קונים ישתתפו במכרז B&A.
אם מקורות של קונים מפורטים ב- |
targetSize |
אופציונלי אם הערך של requestSize מוגדר. חובה אם מוגדר מקור של קונה ב-perBuyerConfig אבל requestSize לא מוגדר. הגדרת גודל המטען המרבי של נתוני הקונה. מידע נוסף זמין בקטע גודל הבקשה במאמר ההסבר. |
coordinatorOrigin |
אופציונלי, אבל בסופו של דבר יהיה חובה. אם הפרמטר לא מוגדר, ברירת המחדל שלו היא https://publickeyservice.pa.gcp.privacysandboxservices.com .מגדיר את התיאום לצורך אחזור המפתח להצפנת עומס העבודה. מידע נוסף זמין בקטע רכז במאמר ההסבר. |
כשמתבצעת הקריאה, הדפדפן קורא את קבוצות תחומי העניין של הקונים שמפורטים ב-perBuyerConfig
ומצפין את נתוני הקונים. נתוני הקונים האלה מכילים מידע מאתרים שונים שמשמש לבידינג, ואי אפשר לפענח אותם מחוץ ל-TEE. לאופטימיזציה של עומס העבודה, רק השם של קבוצת האינטרסים, מפתחות של אותות בידינג מהימנים ואותות הדפדפן נכללים בעומס העבודה.
באובייקט הנתונים של מכרז המודעות שמוחזר על ידי הקריאה getInterestGroupAdAuctionData()
, זמינים המחרוזת requestId
ומערך הבייטים המוצפן request
.
המחרוזת requestId
משמשת מאוחר יותר כשמתבצעת קריאה ל-runAdAuction()
כדי לסיים את המכרז בדפדפן. המטען הייעודי (payload) המוצפן של request
נשלח לשירות המודעות של המוכר כחלק מהבקשה למכרז המאוחד.
דוגמה לקריאה הזו מופיעה בקוד 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()
.
גוף הקריאה מכיל את הפרטים הבאים:
- תוכן טעינה (payload) של מכרז לפי הקשר בטקסט ללא הצפנה, ש-SAS ישתמש בו כדי להפעיל את המכרז לפי הקשר.
- נתוני העומס המוצפנים של מכרז 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
אחרי ששירות המודעות של מוכרים מקבל מהדף את הבקשה למכרז המאוחד, המכרז לפי הקשר פועל קודם כדי לקבוע את המנצח במכרז לפי הקשר ולאסוף את אותות הקונים שיועברו למכרז ה-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:
Accept-Language
User-Agent
- כתובת IP
כשהמטא-נתונים נשלחים ל-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, ו-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()
כדי להשלים את המכרז
תגובת המכרז המאוחד שמוחזרת מ-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 של המוכר באפליקציית הבדיקה המקומית.
השלבים הבאים
אחרי שתסיימו לקרוא את המדריך הזה, תוכלו לבצע את השלבים הבאים:
מידע נוסף
- להבנה מעמיקה יותר, אפשר לעיין במאמרים הבאים ב-GitHub:
- מידע נוסף על ארכיטקטורת B&A לאינטרנט
- כדי לערוך ניסויים עם Protected Audience באמצעות בדיקות A/B, אפשר לפעול לפי ההוראות במדריך Codelab לבדיקות מקומיות מקצה לקצה.
יש לך שאלות?
- אם יש לכם שאלה לגבי שירותי בידינג ומכרזים, אתם יכולים לפתוח פנייה במאגר של שירותי בידינג ומכרזים.
- אם יש לכם שאלה כללית לגבי ארגז החול לפרטיות, אתם יכולים לפתוח פנייה במאגר privacy-sandbox-dev-support.