Dịch vụ Đặt giá thầu và Phiên đấu giá (B&A) là một nhóm 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
Bạn có thể tóm tắt các bước 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ó tải trọng đã mã hoá đến SAS của bạn - Gọi thao tác
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ả đấu giá B&A phía máy chủ vào lệnh gọi
Nhận dữ liệu đã mã hoá về phiên đấu giá quảng cáo
Để lấy dữ liệu cần thiết để chạy phiên đấu giá B&A phía máy chủ, mã JavaScript của người bán trên trang của 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. Quốc gia 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 đó.
|
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 phần 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 nguồn gốc của người mua được đặt trong perBuyerConfig nhưng requestSize không được đặt. Đặt kích thước tải trọng tối đa cho dữ liệu của người mua đó. Hãy xem phần kích thước yêu cầu trong phần giải thích để tìm hiểu thêm. |
coordinatorOrigin |
Không bắt buộc, nhưng cuối cùng sẽ là thông tin 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 để dùng cho việc tìm nạp khoá nhằm mã hoá tải trọng. Hãy xem phần điều phối viên trong phần 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ó 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 hoạt độ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, chỉ tên nhóm mối quan tâm, các khoá tín hiệu đặt giá thầu đáng tin cậy và tín hiệu của trình duyệt được đưa vào tải trọng.
Trong đối tượng dữ liệu phiên đấu giá quảng cáo do lệnh gọi getInterestGroupAdAuctionData() trả về, chuỗi requestId và mảng byte request đã mã hoá sẽ có sẵn.
Chuỗi requestId sẽ được dùng sau đó khi runAdAuction() được gọi để hoàn tất 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 đấu giá thống 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 đấu giá thống 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 PA. Tải trọng phiên đấu giá B&A của PA là dữ liệu request được mã hoá mà trình duyệt đã tạo 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 củ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 lựa chọn
adAuctionHeaders: true, lựa chọn này 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 thời điểm sau đó khirunAdAuction()được gọi để hoàn tất 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:
- Tải trọng đấu giá theo bối cảnh ở dạng văn bản thuần tuý mà SAS sẽ dùng để chạy phiên đấu giá theo bối cảnh.
- Tải trọng phiên đấu giá Protected Audience được mã hoá mà SAS sẽ 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 được mã hoá do lệnh gọi getInterestGroupAdAuctionData() trả về là một phiên bản của Uint8Array, đây là một kiểu 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á do lệnh gọi fetch này trả về cũng ở dạng mã hoá base64, vì vậy, bạn cần giải mã kết quả đó về 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 khoảng 33% so với dữ liệu ban đầu. Nếu 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 đấu giá thống 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 trong 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 củ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 bằng tải trọng yêu cầu. Xin lưu ý rằng một số siêu dữ liệu từ yêu cầu của trang đối với SAS trong 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 đấ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 đến SFE được gửi bằng gRPC. Nếu yêu cầu được gửi bằng HTTP, thì dữ liệu đấ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 một 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 một 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, 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 linh kiện, 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 cho SelectAd của SFE
Bạn có thể thực hiện cuộc gọi đến SFE từ SAS bằng gRPC hoặc HTTP.
Cuộc gọi gRPC
Yêu cầu gRPC đến SFE có dạng như sau khi sử dụng Express trong Node với một gRPC client:
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 HTTP POST đế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-LanguageUser-Agent- Địa chỉ IP
Khi gửi siêu dữ liệu đế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-LanguageX-User-AgentX-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 máy khách 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á có 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 một 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 này chứa các tải trọng phiên đấu giá thành phần được mã hoá lại và gửi đến các dịch vụ quảng cáo của người bán thành phần. Kết quả đấu giá quảng cáo B&A của thành phần được trả về sẽ được cung cấp cho lệnh gọi SelectAd của SFE người bán cấp cao nhất.
Hãy xem tài liệu giải thích về nhiều người bán trên GitHub để tìm hiểu thêm.
Trả kết quả phiên đấu giá B&A về trang
Sau khi phiên đấu giá B&A kết thúc, kết quả phiên đấu giá được mã hoá sẽ được trả về SAS và SAS sẽ phản hồi yêu cầu phiên đấu giá thống nhất từ trang ở bước 2 bằng kết quả phiên đấu giá được mã hoá. Trong phản hồi SAS đối với trang, hàm băm SHA-256 được mã hoá base64url của kết quả phiên đấu giá được mã hoá sẽ được đặt trong tiêu đề phản hồi Ad-Auction-Result. Trình duyệt dùng hàm băm này để xác minh tải trọng khi hoàn tất phiên đấu giá trong ứng dụng.
Việc tạo hàm băm SHA-256 bằng phương thức mã hoá base64 sẽ có dạng như sau trong Node:
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 đưa vào phản hồi.
Bạn có thể thêm nhiều hàm băm vào Ad-Auction-Result bằng cách lặp lại tiêu đề hoặc phân 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 do SAS trả về bao gồm kết quả phiên đấu giá B&A đã mã hoá. Tải trọng 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() trong 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 đấ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 đấu giá mà người bán chọn.
Phiên đấu giá của một người bán
Để chạy một phiên đấu giá B&A của một người bán, cấu hình đấ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 đấ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ả đấu giá B&A và cấu hình đấ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 sẽ 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ả đấu giá B&A và cấu hình đấ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 sau đây:
Tìm hiểu thêm
- Để hiểu rõ hơn, hãy xem các bản 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 bằng B&A bằng cách làm theo Lớp học lập trình Kiểm thử cục bộ toàn diện.
Bạn có thắc mắc?
- 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ụ đặt giá thầu và phiên đấu giá.