Dịch vụ Đặt giá thầu và Phiên đấu giá (B&A) là một bộ dịch vụ dành cho người mua và người bán quảng cáo, chạy trong Môi trường thực thi đáng tin cậy (TEE) để hỗ trợ phiên đấu giá Protected Audience (PA). Hướng dẫn dành cho nhà phát triển này giải thích cách người bán có thể tích hợp với phiên đấu giá PA của Chrome cho B&A.
Hướng dẫn từng bước
Các bước có thể được tóm tắt như sau:
- Gọi
getInterestGroupAdAuctionData()
để lấy tải trọng đã mã hoá từ trình duyệt - Gọi
fetch('https://your-ad-server.example')
và gửi yêu cầu đấu giá hợp nhất cùng với tải trọng đã mã hoá đến SAS - Gọi toán tử
SelectAd()
của SFE từ SAS để chạy phiên đấu giá B&A - Trả về kết quả phiên đấu giá B&A cho trang cùng với hàm băm của phản hồi
- Gọi
runAdAuction()
trong trình duyệt để chạy phiên đấu giá PA một người bán, chế độ kết hợp hoặc nhiều người bán, đồng thời truyền kết quả phiên đấu giá B&A phía máy chủ vào lệnh gọi
Nhận dữ liệu phiên đấu giá quảng cáo đã mã hoá
Để lấy dữ liệu cần thiết cho việc chạy phiên đấu giá B&A phía máy chủ, mã JavaScript của người bán trên trang nhà xuất bản sẽ gọi 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;
Trường | Mô tả |
---|---|
seller |
Bắt buộc. Nguồn gốc của người bán đang chạy phiên đấu giá. Giá trị này phải khớp với giá trị seller trong lệnh gọi runAdAuction() sau này.
|
requestSize |
Không bắt buộc. Đặt kích thước tải trọng tối đa của tất cả dữ liệu người mua. Hãy xem phần kích thước yêu cầu trong nội dung giải thích để tìm hiểu thêm. |
perBuyerConfig |
Không bắt buộc. Đặt cấu hình cho từng người mua, đồng thời kiểm soát những người mua tham gia phiên đấu giá B&A.
Nếu nguồn gốc của người mua được liệt kê trong |
targetSize |
Không bắt buộc nếu bạn đặt requestSize . Bắt buộc nếu bạn đặt nguồn gốc của người mua trong perBuyerConfig nhưng không đặt requestSize . Đặt kích thước tải trọng tối đa của dữ liệu của người mua đó. Hãy xem phần kích thước yêu cầu trong nội dung giải thích để tìm hiểu thêm. |
coordinatorOrigin |
Không bắt buộc, nhưng cuối cùng sẽ bắt buộc. Mặc định là https://publickeyservice.pa.gcp.privacysandboxservices.com khi không được đặt.Đặt trình điều phối để sử dụng cho việc tìm nạp khoá nhằm mã hoá tải trọng. Hãy xem phần trình điều phối trong nội dung giải thích để tìm hiểu thêm. |
Khi lệnh gọi được thực hiện, trình duyệt sẽ đọc các nhóm mối quan tâm của người mua được liệt kê trong perBuyerConfig
và mã hoá dữ liệu của người mua. Dữ liệu người mua này chứa thông tin trên nhiều trang web để dùng cho tính năng đặt giá thầu và không thể giải mã bên ngoài TEE. Để tối ưu hoá tải trọng, tải trọng chỉ bao gồm tên nhóm mối quan tâm, khoá tín hiệu đặt giá thầu đáng tin cậy và tín hiệu trình duyệt.
Trong đối tượng dữ liệu phiên đấu giá quảng cáo do lệnh gọi getInterestGroupAdAuctionData()
trả về, bạn có thể sử dụng chuỗi requestId
và mảng byte request
đã mã hoá.
Chuỗi requestId
được sử dụng sau này khi runAdAuction()
được gọi để kết thúc phiên đấu giá trong trình duyệt. Tải trọng request
đã mã hoá được gửi đến Dịch vụ quảng cáo của người bán trong yêu cầu phiên đấu giá hợp nhất.
Để xem ví dụ về lệnh gọi này, hãy xem mã JavaScript của người bán trong ứng dụng kiểm thử cục bộ.
Gửi yêu cầu phiên đấu giá hợp nhất đến SAS
Yêu cầu đấu giá hợp nhất là yêu cầu chứa tải trọng đấu giá theo bối cảnh ở dạng văn bản thuần tuý và tải trọng đấu giá B&A của Protected Audience. Tải trọng phiên đấu giá B&A PA là dữ liệu request
đã mã hoá mà trình duyệt tạo ra trong lệnh gọi getInterestGroupAdAuctionData()
. Yêu cầu này được gửi đến SAS, nơi phiên đấu giá theo bối cảnh và phiên đấu giá B&A PA được điều phối.
fetch('https://ssp.example/ad-auction', {
method: 'POST',
adAuctionHeaders: true,
body: JSON.stringify({
contextualAuctionPayload: { somePayload },
protectedAudienceAuctionPayload: encodeBinaryData(request)
}),
});
Để gửi yêu cầu đến SAS, một lệnh gọi fetch()
sẽ được thực hiện từ trang:
- Lệnh gọi phải bao gồm tuỳ chọn
adAuctionHeaders: true
. Tuỳ chọn này sẽ báo hiệu cho trình duyệt xác minh phản hồi của lệnh gọi này vào lúc khác khirunAdAuction()
được gọi để kết thúc phiên đấu giá trong trình duyệt. - Nguồn gốc của yêu cầu tìm nạp phải khớp với nguồn gốc
seller
được cung cấp cho các lệnh gọigetInterestGroupAdAuctionData()
vàrunAdAuction()
.
Nội dung của lệnh gọi chứa:
- Trọng tải phiên đấu giá theo bối cảnh ở dạng văn bản thuần tuý mà SAS sẽ sử dụng để chạy phiên đấu giá theo bối cảnh.
- Tải trọng phiên đấu giá Protected Audience đã mã hoá sẽ được SAS gửi đến SFE để chạy phiên đấu giá B&A phía máy chủ.
Để xem ví dụ về lệnh gọi này, hãy xem mã JavaScript của người bán trong ứng dụng kiểm thử cục bộ.
Mã hoá và giải mã Base64
Tải trọng request
đã mã hoá được trả về từ lệnh gọi getInterestGroupAdAuctionData()
là một thực thể của Uint8Array
, đây là một loại dữ liệu mà JSON không thể xử lý. Để gửi mảng byte ở định dạng JSON, bạn có thể áp dụng phương thức mã hoá base64 cho dữ liệu nhị phân để chuyển đổi dữ liệu đó thành một chuỗi.
API trình duyệt JavaScript cung cấp các hàm atob()
và btoa()
trên window
để chuyển đổi giữa dữ liệu nhị phân và chuỗi ASCII được mã hoá base64. (atob
có nghĩa là ASCII sang nhị phân và btoa
có nghĩa là nhị phân sang ASCII).
Gọi btoa()
để mã hoá dữ liệu nhị phân thành một chuỗi được mã hoá base64 như sau:
function encodeBinaryData(data) {
return btoa(String.fromCharCode.apply(null, data));
}
Kết quả phiên đấu giá B&A được mã hoá được trả về từ lệnh gọi fetch
này cũng ở dạng mã hoá base64, vì vậy, bạn cần giải mã kết quả đó trở lại thành dữ liệu nhị phân. Gọi atob()
để giải mã chuỗi ASCII được mã hoá base64 thành dữ liệu nhị phân:
function decodeBase64String(base64string) {
return new Uint8Array(
atob(base64string)
.split('')
.map((char) => char.charCodeAt(0))
);
}
Tuy nhiên, một chuỗi được mã hoá base64 thường lớn hơn dữ liệu ban đầu khoảng 33%. Nếu bạn muốn cải thiện thêm độ trễ, hãy sử dụng một định dạng khác ngoài JSON để gửi dữ liệu nhị phân.
Gọi SelectAd
của SFE để chạy phiên đấu giá B&A
Sau khi Dịch vụ quảng cáo của người bán nhận được yêu cầu phiên đấu giá hợp nhất từ trang, phiên đấu giá theo bối cảnh sẽ chạy trước để xác định người chiến thắng phiên đấu giá theo bối cảnh và thu thập các tín hiệu của người mua để chuyển vào phiên đấu giá B&A PA. Sau đó, phiên đấu giá B&A được bắt đầu bằng cách gọi thao tác SelectAd
của SFE từ SAS với tải trọng yêu cầu. Lưu ý rằng một số siêu dữ liệu từ yêu cầu của trang đến SAS ở bước 2 sẽ được chuyển tiếp đến SFE.
Tạo tải trọng SelectAdRequest
Bạn có thể tạo tải trọng yêu cầu của lệnh gọi SelectAd
như sau:
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)
};
Xin lưu ý rằng nếu dữ liệu phiên đấu giá quảng cáo đã mã hoá từ trình duyệt được mã hoá base64, thì dữ liệu đó cần được giải mã trở lại thành dữ liệu nhị phân nếu yêu cầu gửi đến SFE được gửi bằng gRPC. Nếu yêu cầu được gửi bằng HTTP, thì dữ liệu phiên đấu giá quảng cáo đã mã hoá có thể vẫn ở dạng được mã hoá base64.
Để xem các trường khác được xác định trong yêu cầu SelectAd
, hãy xem định nghĩa proto của SelectAdRequest
.
Đặt trường người bán cấp cao nhất cho phiên đấu giá ở chế độ kết hợp và phiên đấu giá thành phần
Nếu người bán đang chạy phiên đấu giá ở chế độ kết hợp hoặc tham gia với tư cách là người bán thành phần trong phiên đấu giá nhiều người bán, thì bạn cần xác định trường top_level_seller
trong yêu cầu.
Nếu bạn là người bán ở chế độ kết hợp, thì giá trị top_level_seller
là nguồn gốc của bạn:
const selectAdRequest = {
auction_config: {
seller: 'https://ssp-mix.example',
top_level_seller: 'https://ssp-mix.example',
}
}
Nếu bạn là người bán thành phần, thì giá trị top_level_seller
là người bán cấp cao nhất của phiên đấu giá nhiều người bán:
const selectAdRequest = {
auction_config: {
seller: 'https://ssp-mix.example',
top_level_seller: 'https://ssp-top.example',
}
}
Gọi SelectAd
của SFE
Bạn có thể thực hiện lệnh gọi đến SFE từ SAS bằng gRPC hoặc HTTP.
Lệnh gọi gRPC
Yêu cầu gRPC đến SFE có dạng như sau khi sử dụng Express trong Node với ứng dụng 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
});
Bạn có thể tìm thấy định nghĩa proto cho ứng dụng SFE trong kho lưu trữ ứng dụng kiểm thử cục bộ.
Lệnh gọi HTTP đến proxy Envoy
Yêu cầu POST HTTP đến SFE được gửi đến đường dẫn /v1/selectAd
và có dạng như sau:
fetch('https://ssp-ba.example/sfe/v1/selectAd', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(selectAdRequest),
});
Chuyển tiếp siêu dữ liệu
Bạn nên thêm siêu dữ liệu sau đây từ lệnh gọi của trang đến SAS vào lệnh gọi SelectAd
của SAS đến SFE:
Accept-Language
User-Agent
- Địa chỉ IP
Khi siêu dữ liệu được gửi đến SFE, siêu dữ liệu phải sử dụng các tiêu đề không chuẩn sau đây vì gRPC có thể thay đổi tiêu đề User-Agent
:
X-Accept-Language
X-User-Agent
X-BnA-Client-IP
Sau đây là ví dụ về cách chuyển tiếp siêu dữ liệu bằng Express trong Node bằng ứng dụng 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);
})
Sau đây là ví dụ về cách chuyển tiếp siêu dữ liệu bằng lệnh gọi 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)
});
})
Phiên đấu giá nhiều người bán do máy chủ điều phối
Nếu bạn là người bán cấp cao nhất đang chạy phiên đấu giá nhiều người bán do máy chủ điều phối, thì lệnh gọi GetComponentAuctionCiphertexts
sẽ được thực hiện đến SFE trước khi lệnh gọi SelectAd
được thực hiện. Phản hồi chứa tải trọng phiên đấu giá thành phần được mã hoá lại được gửi đến dịch vụ quảng cáo của người bán thành phần. Kết quả phiên đấu giá quảng cáo B&A của thành phần được trả về được cung cấp cho lệnh gọi SelectAd
của SFE của người bán cấp cao nhất.
Hãy xem nội dung giải thích về nhiều người bán trên GitHub để tìm hiểu thêm.
Trả về kết quả phiên đấu giá B&A cho trang
Sau khi phiên đấu giá B&A kết thúc, kết quả phiên đấu giá đã mã hoá sẽ được trả về SAS và SAS sẽ phản hồi yêu cầu phiên đấu giá hợp nhất từ trang trong bước 2 bằng kết quả phiên đấu giá đã mã hoá. Trong phản hồi SAS cho trang, hàm băm SHA-256 được mã hoá base64url của kết quả phiên đấu giá đã mã hoá được đặt trong tiêu đề phản hồi Ad-Auction-Result
. Hàm băm này được trình duyệt sử dụng để xác minh tải trọng khi kết thúc phiên đấu giá trong ứng dụng.
Cách tạo hàm băm SHA-256 bằng cách mã hoá base64 trong Node như sau:
import { createHash } from 'crypto';
createHash('sha256')
.update(binaryData, 'base64')
.digest('base64url');
Việc đính kèm hàm băm trong tiêu đề phản hồi và trả về kết quả phiên đấu giá cho trang sẽ có dạng như sau:
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()
});
});
})
Vì đây là phản hồi cho yêu cầu phiên đấu giá hợp nhất được thực hiện từ trang ở bước 2, nên kết quả phiên đấu giá theo bối cảnh cũng có trong phản hồi.
Bạn có thể đưa nhiều hàm băm vào Ad-Auction-Result
bằng cách lặp lại tiêu đề hoặc tách các hàm băm. Hai tiêu đề phản hồi sau đây tương đương nhau:
Ad-Auction-Result: ungWv48Bz-pBQUDeXa4iI7ADYaOWF3qctBD_YfIAFa0=,9UTB-u-WshX66Xqz5DNCpEK9z-x5oCS5SXvgyeoRB1k=
Ad-Auction-Result: ungWv48Bz-pBQUDeXa4iI7ADYaOWF3qctBD_YfIAFa0=
Ad-Auction-Result: 9UTB-u-WshX66Xqz5DNCpEK9z-x5oCS5SXvgyeoRB1k=
Để xem ví dụ về lệnh gọi này, hãy xem mã máy chủ của người bán trong ứng dụng kiểm thử cục bộ.
Gọi runAdAuction()
để hoàn tất phiên đấu giá
Phản hồi phiên đấu giá hợp nhất được trả về từ SAS bao gồm kết quả phiên đấu giá B&A đã mã hoá. Trọng tải này được truyền vào lệnh gọi runAdAuction()
để hoàn tất phiên đấu giá trong trình duyệt. Giá trị requestId
từ lệnh gọi getInterestGroupAdAuctionData()
ở bước 1 cũng được truyền vào phiên đấu giá.
// 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
});
Cấu trúc của cấu hình phiên đấu giá được truyền vào lệnh gọi runAdAuction()
sẽ khác nhau tuỳ thuộc vào cấu hình phiên đấu giá mà người bán chọn.
Phiên đấu giá của một người bán
Để chạy phiên đấu giá B&A của một người bán, cấu hình phiên đấu giá của lệnh gọi runAdAuction()
được tạo như sau:
await navigator.runAdAuction({
seller: 'https://ssp-ba.example',
requestId,
serverResponse: protectedAudienceAuctionResult,
});
Trường requestId
chấp nhận requestId
do lệnh gọi getInterestGroupAdAuctionData()
trả về. Trường serverResponse
chấp nhận một mảng byte của phiên đấu giá B&A đã chạy trong bước 3.
Để xem ví dụ về lệnh gọi này, hãy xem mã JavaScript của người bán trong ứng dụng kiểm thử cục bộ.
Phiên đấu giá ở chế độ kết hợp
Để chạy phiên đấu giá B&A ở chế độ kết hợp, trong đó cả người mua trên thiết bị và người mua B&A đều có thể tham gia, cấu hình phiên đấu giá của lệnh gọi runAdAuction()
được tạo như sau:
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
],
},
]
});
Để tạo điều kiện cho phiên đấu giá ở chế độ kết hợp, kết quả phiên đấu giá B&A và cấu hình phiên đấu giá trên thiết bị sẽ được truyền vào trường componentAuctions
. Trong phiên đấu giá ở chế độ kết hợp, giá trị seller
giống nhau cho cả cấu hình cấp cao nhất và cấu hình thành phần.
Để xem ví dụ về lệnh gọi này, hãy xem mã JavaScript của người bán trong ứng dụng kiểm thử cục bộ.
Phiên đấu giá nhiều người bán
Nếu bạn là người bán cấp cao nhất đang chạy phiên đấu giá nhiều người bán do thiết bị điều phối, thì mỗi người bán thành phần sẽ gửi kết quả phiên đấu giá B&A và cấu hình phiên đấu giá trên thiết bị.
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',
}
]
})
Để xem ví dụ về lệnh gọi này, hãy xem mã JavaScript của người bán trong ứng dụng kiểm thử cục bộ.
Các bước tiếp theo
Sau khi đọc hướng dẫn này, bạn có thể thực hiện các bước tiếp theo:
Tìm hiểu thêm
- Để hiểu rõ hơn, hãy xem các nội dung giải thích sau trên GitHub:
- Tìm hiểu thêm về cấu trúc B&A cho web
- Thử nghiệm Protected Audience với B&A bằng cách tham gia Lớp học lập trình về kiểm thử cục bộ toàn diện.
Bạn có câu hỏi?
- Nếu bạn có câu hỏi về Dịch vụ đặt giá thầu và Phiên đấu giá, hãy mở một vấn đề trong kho lưu trữ Dịch vụ B&A.
- Nếu bạn có câu hỏi chung về Hộp cát về quyền riêng tư, hãy mở một vấn đề trong kho lưu trữ hỗ trợ nhà phát triển privacy-sandbox-dev-support.