Aby pomóc deweloperom rozpocząć eksperymentowanie z interfejsem Protected App Signals API, w tym dokumencie opisaliśmy wszystkie interfejsy API w interfejsie API, podaliśmy szczegółowe informacje o konfigurowaniu środowiska testowego oraz podaliśmy przykłady konfiguracji i skryptów.
Historia zmian
Styczeń 2024 r.
Pierwsza wersja przewodnika dla deweloperów dotycząca wersji MVP PAS
Marzec 2024 r.
Zmiany w interfejsie API, które umożliwiają obsługę wersji M-2024-05 interfejsu API Androida i wersji komponentów po stronie serwera z kwietnia 2024 r. Najważniejsze zmiany:
- Dodano szczegóły dotyczące uprawnień wymaganych przez interfejs API na urządzeniu
- Dodaliśmy szczegóły na temat zarządzania limitem sygnałów na urządzeniu
- Zaktualizowany podpis
generateBid
z modyfikacjami związanymi z obsługą pobierania i wysyłania danych w kontekście - Zaktualizowana dokumentacja
reportWin
, w tym obsługa wychodzących połączeń - Zaktualizowana dokumentacja interfejsu AdRetrieval API, która usuwa obsługę pobierania reklam BYOS i dokumentuje UDF pobierania reklam
Przegląd interfejsów API
Interfejs Protected Signals API zawiera różne podzbiory interfejsu API w różnych systemach:
- Interfejsy API Androida:
- interfejs Signal Curation API, który składa się z:
- Update Signals API
- Signals Encoding API
- Interfejs Protected Auction Support API: służy do obsługi aukcji chronionych przez pakiety SDK na serwerach licytacji i aukcji (B&A) z wykorzystaniem sygnałów z chronionej aplikacji.
- Interfejsy API po stronie serwera:
- Protected Auction API: seria skryptów JS działających na serwerach określania stawek i aukcji. Ten interfejs API umożliwia sprzedawcom i kupującym tworzenie logiki implementacji aukcji chronionej.
- Interfejs API do pobierania reklam: odpowiada za udostępnianie listy reklam kandydujących na podstawie informacji kontekstowych i informacyjnych o użytkownikach udostępnionych serwerowi licytacyjnemu kupującego.
Klient na Androida
Po stronie klienta interfejs Protected App Signals składa się z 3 interfejsów API:
- Update Signals: interfejs API systemu Android umożliwiający selekcję sygnałów na urządzeniu.
- Kodowanie sygnałów: interfejs JavaScript API do przygotowywania sygnałów do wysłania do serwera podczas aukcji.
- Obsługa aukcji chronionych: interfejs API do obsługi aukcji chronionych na serwerach określania stawek i serwerach aukcji. Ten interfejs API nie jest przeznaczony tylko do sygnałów chronionych aplikacji, ale służy też do obsługi aukcji interfejsu Protected Audience API.
Update Signals API
Interfejs UpdateSignals API umożliwia dostawcom technologii reklamowych rejestrowanie sygnałów związanych z użytkownikiem i aplikacją w imieniu kupującego. Interfejs API działa na podstawie modelu delegowania. Wywołujący udostępnia identyfikator URI, z którego framework pobiera odpowiednie sygnały i logikę do ich kodowania na potrzeby aukcji.
Interfejs API wymaga uprawnienia android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS
.
Interfejs API updateSignals()
pobierze z identyfikatora URI obiekt JSON, który opisuje, które sygnały należy dodać lub usunąć, oraz jak przygotować te sygnały na potrzeby aukcji.
Executor executor = Executors.newCachedThreadPool();
ProtectedSignalsManager protectedSignalsManager
= ProtectedSignalsManager.get(context);
// Initialize a UpdateSignalsRequest
UpdateSignalsRequest updateSignalsRequest = new
UpdateSignalsRequest.Builder(Uri.parse("https://example-adtech1.com/signals"))
.build();
OutcomeReceiver<Object, Exception> outcomeReceiver = new OutcomeReceiver<Object, Exception>() {
@Override
public void onResult(Object o) {
//Post-success actions
}
@Override
public void onError(Exception error) {
//Post-failure actions
};
// Call updateSignals
protectedSignalsManager.updateSignals(updateSignalsRequest,
executor,
outcomeReceiver);
Aby pobrać aktualizacje sygnału, platforma wysyła żądanie https do identyfikatora URI podanego w żądaniu. Oprócz aktualizacji sygnałów odpowiedź może zawierać punkt końcowy, który hostuje logikę kodowania służącą do konwertowania nieprzetworzonych sygnałów na zakodowany ładunek. Aktualizacje sygnału powinny mieć postać JSON i można im przypisać te klucze:
Klucze najwyższego poziomu obiektu JSON muszą odpowiadać jednej z 5 komend:
klucz |
Opis |
|
Dodaje nowy sygnał, zastępując wszystkie istniejące sygnały tym samym kluczem. Wartość for this to obiekt JSON, w którym klucze to ciągi znaków w formacie base64 odpowiadające kluczowi, dla którego ma być zapisana wartość, a wartości to ciągi znaków w formacie base64 odpowiadające wartości, która ma zostać zapisana. |
|
Dodaje nowy sygnał lub nowe sygnały do serii czasowych sygnałów, usuwając najstarsze. sygnały, aby zrobić miejsce na nowe, jeśli rozmiar serii przekracza podany limit. Jego wartość to obiekt JSON, w którym klucze to ciągi znaków w standardzie Base64 odpowiadające kluczowi, do którego mają zostać dołączone, a wartości to obiekty z 2 polami: „values” i „maxSignals”. „values”: lista ciągów w formacie base64 odpowiadających wartościom sygnału, które mają zostać dołączone do ciągu czasowego. „maxSignals”: maksymalna liczba wartości dozwolonych w tym ciągu czasowym. Jeśli jeśli bieżąca liczba sygnałów powiązanych z kluczem przekroczy wartość maxSignals, najstarsze sygnały zostaną usunięte. Pamiętaj, że możesz dodać klucz za pomocą polecenia put. Pamiętaj, że dodanie większej liczby wartości niż maksymalna liczba spowoduje błąd. |
|
Dodaje nowy sygnał tylko wtedy, gdy nie ma żadnych istniejących sygnałów z tym samym kluczem. Jego wartością jest obiekt JSON, w którym klucze to ciągi znaków w formacie base64 odpowiadające kluczowi, dla którego ma być zapisywana wartość, a wartości to ciągi znaków w formacie base64 odpowiadające wartości, która ma być zapisywana. |
|
Usuwa sygnał dla klucza. Jego wartością jest lista ciągów w formacie Base64 odpowiadających kluczom sygnałów, które mają zostać usunięte. |
|
Udostępnia działanie służące do aktualizowania punktu końcowego oraz identyfikator URI, którego można użyć. aby pobrać logikę kodowania. Podklucz do podjęcia działania aktualizacji to „action”, a Obecnie obsługiwane wartości to tylko „REGISTER”, który zarejestruje punkt końcowy kodera, jeśli zostanie podany po raz pierwszy, lub zastąpi istniejący punkt końcowy nowo podanym punktem końcowym. Podanie punktu końcowego jest wymagane w przypadku działania „REGISTER”. Podrzędny klucz podający punkt końcowy kodera to „endpoint”, a wartością jest identyfikator URI. ciąg znaków w punkcie końcowym. |
Przykładowe żądanie w formacie JSON wygląda tak:
{
"put": {
"AAAAAQ==": "AAAAZQ==",
"AAAAAg==": "AAAAZg=="
},
"append": {
"AAAAAw==": {
"values": [
"AAAAZw=="
],
"max_signals": 3
}
},
"put_if_not_present": {
"AAAABA==": "AAAAaQ==",
"AAAABQ==": "AAAAag=="
},
"update_encoder": {
"action": "REGISTER",
"endpoint": "https://adtech1.com/Protected App Signals_encode_script.js"
}
}
Limit sygnałów na urządzeniu wynosi około 10–15 KB. Gdy przekroczysz limit, PPAPI usunie sygnały, korzystając ze strategii FIFO. Proces wyrzucania pozwoli na niewielkie przekroczenie limitu przez krótki czas, aby zmniejszyć częstotliwość wyrzucania.
Signals Encoding API
Kupujący muszą podać funkcję JavaScript, która służy do kodowania sygnałów zapisanych na urządzeniu i przesyłanych na serwer podczas licytacji chronionej. Kupujący mogą udostępnić ten skrypt, dodając adres URL, z którego można go pobrać, używając klucza „update_encoder” w dowolnej odpowiedzi na żądanie interfejsu UpdateSignal API. Skrypt będzie miał następującą sygnaturę:
function encodeSignals(signals, maxSize) {
let result = new Uint8Array(maxSize);
// first entry will contain the total size
let size = 1;
let keys = 0;
for (const [key, values] of signals.entries()) {
keys++;
// In this encoding we only care about the first byte
console.log("key " + keys + " is " + key)
result[size++] = key[0];
result[size++] = values.length;
for(const value of values) {
result[size++] = value.signal_value[0];
}
}
result[0] = keys;
return { 'status': 0, 'results': result.subarray(0, size)};
}
Parametr signals
to mapowanie kluczy w postaci tablic UInt8 o rozmiarach 4 na listy obiektów Protected App Signals. Każdy obiekt Protected App Signals ma 3 pola:
signal_value
: tablica UInt8 reprezentująca wartość sygnału.creation_time
: liczba reprezentująca czas utworzenia sygnałów w epoce sekund.package_name
: ciąg znaków reprezentujący nazwę pakietu, który utworzył sygnał.
Parametr maxSize
to liczba określająca największy dozwolony rozmiar tablicy danych wyjściowych.
Funkcja powinna zwracać obiekt z 2 polami:
status
: jeśli skrypt został wykonany pomyślnie, wartość powinna wynosić 0.results
: powinna być tablicą UInt8 o długości mniejszej lub równej maxSize. Ta tablica zostanie przesłana na serwer podczas aukcji i przygotowana przez skryptprepareDataForAdRetrieval
.
Kodowanie zapewnia specjalistom ds. technologii reklamowych początkowy etap tworzenia funkcji, na którym mogą przeprowadzać przekształcenia, np. kompresowanie surowych sygnałów w połączone wersje na podstawie własnej logiki niestandardowej. Pamiętaj, że podczas chronionej aukcji w zaufanym środowisku wykonawczym (TEE) logika niestandardowa technologii reklamowej będzie mieć dostęp tylko do odczytu danych sygnału wygenerowanych przez kodowanie. Logika niestandardowa, zwana funkcją zdefiniowaną przez użytkownika (UDF), działająca w ramach TEE B&A kupującego, będzie mieć dostęp do odczytu zakodowanych sygnałów i innych sygnałów kontekstowych dostarczanych przez aplikację wydawcy w celu wyboru reklamy (pobieranie reklam i licytowanie).
Kodowanie sygnałów
Co godzinę kupujący, którzy udostępnili logikę kodowania ze swoimi zarejestrowanymi sygnałami, będą mieli te sygnały zakodowane w danych aukcji.Tablica bajtów danych aukcji jest zapisywana na urządzeniu, a następnie szyfrowana i zbierana przez sprzedawców jako część danych doboru reklam, które są uwzględniane w ramach aukcji chronionej. Aby przetestować kodowanie, możesz je wywołać poza godzinnym rytmem, uruchamiając to polecenie:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
Wersje logiki kodera
Gdy otrzyma żądanie pobrania logiki niestandardowego kodera technologii reklamowych, może odpowiedzieć numerem wersji w nagłówkach odpowiedzi. Ta wersja jest przechowywana wraz z logiką kodowania na urządzeniu. Gdy sygnały nieprzetworzone zostaną zakodowane, zakodowany ładunek wraz z wersją użytą do zakodowania jest utrwalony. Ta wersja jest też wysyłana na serwer B&A podczas aukcji chronionej, aby firmy technologiczne zajmujące się reklamami mogły dostosować logikę ustalania stawek i kodowania na podstawie tej wersji.
Response header for providing encoder version : X_ENCODER_VERSION
Interfejs Protected Auction Support API
Na urządzeniu przeprowadzenie aukcji sygnałów chronionych aplikacji jest takie samo jak przeprowadzenie aukcji dla chronionych odbiorców.
Usługi określania stawek i aukcji
Interfejsy API po stronie serwera:
- Interfejs Protected Auction API: zbiór funkcji JS lub funkcji UDF, które kupujący i sprzedający mogą wdrażać w swoich komponentach B&A, aby określać stawki i logikę aukcji.
- Interfejs Ad Retrieval API: kupujący mogą go zaimplementować, korzystając z punktu końcowego REST, który będzie odpowiedzialny za dostarczanie zestawu reklam kandydujących do aukcji Protected App Signal.
Protected Auction API
Interfejs Protected Auction API składa się z interfejsu JS API lub UDF, które kupujący i sprzedający mogą wykorzystać do implementacji logiki aukcji i określania stawek.
UDF kupujących w technologiach reklamowych
Funkcja UDF prepareDataForAdRetrieval
Zanim chronione sygnały aplikacji będą mogły służyć do pobierania kandydatów reklam z usługi TEE „Pobieranie reklam”, kupujący muszą dekodować i przygotowywać chronione sygnały aplikacji oraz inne dane dostarczone przez sprzedawcę. Dane wyjściowe prepareDataForAdRetrieval
UDF kupujących są przekazywane do usługi pobierania reklam w celu pobrania najlepszych kandydatów na reklamy do ustalania stawek.
// Inputs
// ------
// encodedOnDeviceSignals: A Uint8Array of bytes from the device.
// encodedOnDeviceSignalsVersion: An integer representing the encoded
// version of the signals.
// sellerAuctionSignals: Information about auction (ad format, size) derived
// contextually.
// contextualSignals: Additional contextual signals that could help in
// generating bids.
//
// Outputs
// -------
// Returns a JSON structure to be used for retrieval.
// The structure of this object is left to the adtech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
return {};
}
Funkcja UDF generateBid
Po zwróceniu najlepszych k reklam kandydatów reklamy są przekazywane do logiki ustalania stawek niestandardowych kupującego: generateBid
UDF:
// Inputs
// ------
// ads: Data string returned by the ads retrieval service. This can include Protected App Signals
// ads and related ads metadata.
// sellerAuctionSignals: Information about the auction (ad format, size),
// derived contextually
// buyerSignals: Any additional contextual information provided by the buyer
// preprocessedDataForRetrieval: This is the output of this UDF.
function generateBid(ads, sellerAuctionSignals, buyerSignals,
preprocessedDataForRetrieval,
rawSignals, rawSignalsVersion) {
return { "ad": <ad Value Object>,
"bid": <float>,
"render": <render URL string>,
'adCost': <optional float ad cost>,
"egressPayload": <limitedEgressPayload>,
"temporaryUnlimitedEgressPayload": <temporaryUnlimitedEgressPayload>
};
}
Wynikiem tej funkcji jest pojedyncza stawka dla kandydata na reklamę, reprezentowana jako odpowiednik JSON elementu ProtectedAppSignalsAdWithBidMetadata
.
Funkcja może też zwracać 2 tablice, które zostaną przekazane do funkcji reportWin
w celu umożliwienia trenowania modelu (więcej informacji o wyjściu i trenowaniu modelu znajdziesz w sekcji dotyczącej raportowania w opisie usługi przetwarzania zapytań na żądanie).
reportWin UDF
Po zakończeniu aukcji usługa aukcji wygeneruje adresy URL raportowania dla kupujących i zarejestruje sygnały beacon za pomocą funkcji reportWin
UDF (jest to ta sama funkcja reportWin
, która jest używana w przypadku list odbiorców chronionych).
Urządzenie wyśle ping do serwera, gdy klient wyrenderuje reklamę.
Sygnatura tej metody jest prawie taka sama jak w wersji dotyczącej chronionych odbiorców, z tym że zawiera 2 dodatkowe parametry: egressPayload
i temporaryUnlimitedEgressPayload
, które służą do trenowania modelu i są wypełniane wynikami z funkcji generateBid
.
// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
buyerReportingSignals,
egressPayload, temporaryUnlimitedEgressPayload) {
// ...
}
UDF dostawcy technologii reklamowych dla sprzedawców
UDF scoreAd
Ten UDF jest używany przez sprzedawców do wyboru reklam od kupujących, które wygrają aukcję.
function scoreAd(adMetadata, bid, auctionConfig,
trustedScoringSignals, bid_metadata) {
// ...
return {desirability: desirabilityScoreForThisAd,
allowComponentAuction: true_or_false};
}
Funkcja UDF reportResult
Ten UDF umożliwia sprzedawcy raportowanie na poziomie zdarzenia z informacjami o zwycięskiej reklamie.
function reportResult(auctionConfig, reporting_metadata) {
// ...
registerAdBeacon({"click", clickUrl,"view", viewUrl});
sendReportTo(reportResultUrl);
return signalsForWinner;
}
Interfejs Ad Retrieval API
W wersji MVP usługa pobierania reklam będzie usługą zarządzaną i hostowaną przez kupującego , a usługa określania stawek będzie pobierać kandydatów do reklam z tej usługi. Od kwietnia 2024 r. serwer pobierania reklam musi działać w zaufanym środowisku wykonawczym (TEE) i musi udostępniać interfejs GRPC/proto. Firmy z branży technologii reklamowych muszą skonfigurować ten serwer i podać jego adres URL w ramach wdrożenia pakietu B&A. Implementacja tej usługi działająca w TEE jest dostępna na GitHubie Piaskownicy prywatności, a w pozostałej dokumentacji zakładamy, że jest to kod używany w wdrożeniu.
Od kwietnia 2024 r. wersje B&A obsługują pobieranie reklam na podstawie ścieżki kontekstowej. W takim przypadku serwer licytowania otrzyma listę identyfikatorów reklam przesłanych przez serwer RTB podczas części kontekstowej aukcji. Identyfikatory zostaną wysłane na serwer TEE KV, aby pobrać wszystkie informacje o reklamach, które mają być używane w fazie określania stawek (np. adres URL renderowania reklamy, metadane i wstawki reklamy, które mają być używane w ramach selekcji top-k). Ta druga ścieżka nie wymaga wdrażania żadnej konkretnej logiki, dlatego opiszemy tutaj tylko sposób konfigurowania przypadku użycia polegającego na wyodrębnianiu reklam na podstawie TEE.
UDF getCandidateAds
function getCandidateAds(requestMetadata, preparedDataForAdRetrieval,
deviceMetadata, contextualSignals, contextualAdIds,) {
return adsMetadataString;
}
Gdzie:
requestMetadata
: JSON. metadane serwera dotyczące poszczególnych żądań do UDF; Na razie pusty.preparedDataForAdRetrieval
: zawartość tego pola zależy od strategii wyszukiwania reklam. W przypadku pobierania reklam kontekstowych ten parametr będzie zawierać sygnały nieprzetworzone pochodzące z urządzenia i przekazywane przez usługę określania stawek. W przypadku pobierania reklam TEE za pomocą serwera pobierania reklam ten parametr będzie zawierać wynik funkcji definiowanej przez użytkownikaprepareDataForAdRetrieval
. Uwaga: na tym etapie sygnały z chronionych aplikacji zostaną odkodowane i odszyfrowane.deviceMetadata
: obiekt JSON zawierający metadane urządzenia przekazane przez usługę reklamową sprzedawcy. Więcej informacji znajdziesz w dokumentacji dotyczącej rozmów na czacie.X-Accept-Language
: język używany na urządzeniu.X-User-Agent
: klient użytkownika używany na urządzeniu.X-BnA-Client-IP
: adres IP urządzenia.
contextualSignals
: dowolny ciąg znaków pochodzący z serwera określania stawek kontekstowych obsługiwanego przez ten sam system DSP. Funkcja UDF powinna być w stanie zdekodować ciąg znaków i go wykorzystać. Sygnały kontekstowe mogą zawierać dowolne informacje, takie jak informacje o wersji modelu ML dla chronionego osadzenia przekazanego za pomocą chronionych sygnałów aplikacji.contextualAdIds
: obiekt JSON zawierający opcjonalną listę identyfikatorów reklam.
W przypadku powodzenia UDF powinien zwrócić ciąg znaków. Ciąg znaków jest zwracany do serwera określania stawek, który przekazuje go do UDF generateBid
. Chociaż ciąg znaków może być prostym ciągiem znaków, najprawdopodobniej powinien być on zakodowanym obiektem, którego schemat jest definiowany przez każdą firmę zajmującą się technologią reklamową.
Nie ma żadnych ograniczeń dotyczących schematu, o ile logika generateBid
technologii reklamowej może rozpoznać i wykorzystać ten ciąg znaków.
Konfigurowanie systemu na potrzeby programowania
Android
Aby skonfigurować środowisko programistyczne Androida, wykonaj te czynności:
- Utwórz emulator (preferowana opcja) lub urządzenie fizyczne z obrazum Android 10 w wersji deweloperskiej.
- Wykonaj zapytanie:
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity
Następnie wybierz wyświetloną opcję, aby wyrazić zgodę na wyświetlanie reklam sugerowanych przez aplikację.
- Aby włączyć odpowiednie interfejsy API, uruchom to polecenie: Może być konieczne okresowe uruchamianie tego polecenia, ponieważ domyślna konfiguracja wyłączonych urządzeń będzie okresowo synchronizowana.
adb shell device_config put adservices fledge_custom_audience_service_kill_switch false; adb shell device_config put adservices fledge_select_ads_kill_switch false; adb shell device_config put adservices fledge_on_device_auction_kill_switch false; adb shell device_config put adservices fledge_auction_server_kill_switch false; adb shell "device_config put adservices disable_fledge_enrollment_check true"; adb shell device_config put adservices ppapi_app_allow_list '\*'; adb shell device_config put adservices fledge_auction_server_overall_timeout_ms 60000;
- Uruchom urządzenie ponownie.
- Zastąpić klucze aukcji urządzenia, aby wskazywały na serwer kluczy aukcji. Ważne jest, aby wykonać ten krok przed uruchomieniem aukcji, aby zapobiec umieszczeniu w pamięci podręcznej nieprawidłowych kluczy.
Usługi określania stawek i aukcje
Aby skonfigurować serwery B&A, zapoznaj się z dokumentacją samodzielnej konfiguracji.
W tym dokumencie skupimy się na konfigurowaniu serwerów dla kupujących, ponieważ w przypadku sprzedawców nie trzeba wprowadzać żadnych zmian.
Wymagania wstępne
Przed wdrożeniem pakietu usług B&A technologia reklamowa kupującego musi:
- Upewnij się, że mają wdrożony własny interfejs usługi pobierania reklam TEE (patrz odpowiednia sekcja).
- Upewnij się, że technologia reklamowa ma zdefiniowane i hostowane wszystkie niezbędne UDF (
prepareDataForAdRetrieval
,generateBid
,reportWin
,getCandidateAds
).
Przydatna może być też znajomość działania aukcji chronionej z użyciem Protected Audience w połączeniu z modelem B&A, ale nie jest ona wymagana.
Konfiguracja Terraform
Aby korzystać z funkcji Protected App Signals, firmy technologiczne muszą:
- Włącz obsługę sygnałów z chronionych aplikacji w B&A.
- Podaj punkty końcowe adresów URL, z których można pobrać nowe UDF dla
prepareDataForAdRetrieval, generateBid
ireportWin
.
Ten przewodnik zakłada też, że firmy technologiczne, które chcą używać B&A do remarketingu, będą nadal ustawiać wszystkie istniejące flagi konfiguracji aukcji remarketingowej w zwykły sposób.
Konfiguracja technologii reklamowych kupującego
Na przykład w tym pliku demonstracyjnym kupujący muszą ustawić te flagi:
- Włącz Protected App Signals: włącza zbieranie danych Protected App Signals.
- Protected App Signals URLs: ustaw adresy URL serwerów Protected App Signals.
Specjaliści od technologii reklamowych muszą zastąpić prawidłowe adresy URL w polu zastępczym w przypadku tych pól:
module "buyer" {
# ... More config here.
runtime_flags = {
# ... More config here.
ENABLE_PROTECTED_APP_SIGNALS = "true"
PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS = "60000"
TEE_AD_RETRIEVAL_KV_SERVER_ADDR = "<service mesh address of the instance>"
AD_RETRIEVAL_TIMEOUT_MS = "60000"
BUYER_CODE_FETCH_CONFIG = <<EOF
{
"protectedAppSignalsBiddingJsUrl": "<URL to Protected App Signals generateBid UDF>",
"urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
"urlFetchPeriodMs": 13000000,
"prepareDataForAdsRetrievalJsUrl": "<URL to the UDF>"
}
EOF
} # runtime_flags
} # Module "buyer"
Konfiguracja technologii reklamowych sprzedawcy
Na przykład w pliku demo sprzedawcy muszą ustawić te flagi: (Uwaga: tutaj wyróżniono tylko konfigurację związaną z ochroną sygnałów aplikacji). Technologia reklamowa musi zastępować w miejscu zarezerwowanym dla substytutów prawidłowe adresy URL:
module "seller" {
# ... More config here.
runtime_flags = {
# ... More config here.
ENABLE_PROTECTED_APP_SIGNALS = "true"
SELLER_CODE_FETCH_CONFIG = <<EOF
{
"urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
"urlFetchPeriodMs": 13000000,
"protectedAppSignalsBuyerReportWinJsUrls": {"<Buyer Domain>": "URL to reportWin UDF"}
}
EOF
} # runtime_flags
} # Module "seller"
Usługi pobierania informacji o kliencie i reklam
W zależności od strategii wybranych na potrzeby pobierania reklam system będzie wymagać wdrożenia 1 lub 2 wystąpieni usługi KV. Nazwa Ad Retrieval Server
będzie odnosić się do instancji KV używanej do pobierania reklam na podstawie TEE, a nazwa KV Lookup Server
– do instancji obsługującej pobieranie na podstawie ścieżki kontekstowej.
W obu przypadkach wdrażanie serwerów odbywa się zgodnie z dokumentacją dostępną na stronie GitHub serwera KV. Różnica między tymi 2 przypadkami polega na tym, że wyszukiwanie działa od razu po wdrożeniu bez konieczności dodatkowej konfiguracji, a odzyskiwanie wymaga wdrożenia funkcji niestandardowej getCandidateAds
, aby zaimplementować logikę odzyskiwania. Więcej informacji znajdziesz w przewodniku wprowadzającym na temat serwera KV. Pamiętaj, że usługa B&A wymaga, aby obie usługi były wdrażane w tej samej sieci usług co usługa ustalania stawek.
Konfiguracja przykładowa
Rozważmy taki scenariusz: za pomocą interfejsu Protected App Signals API firma technologii reklamowej przechowuje odpowiednie sygnały na podstawie sposobu korzystania przez użytkownika z aplikacji. W naszym przykładzie przechowywane są sygnały, które reprezentują zakupy w aplikacji z kilku aplikacji. Podczas aukcji szyfrowane sygnały są zbierane i przekazywane do chronionej aukcji działającej w ramach B&A. UDF kupującego działające w ramach B&A korzystają z tych sygnałów, aby pobierać reklamy kandydujące i obliczać stawki.
[Buyer] Sygnały – przykłady
Dodaje sygnał z kluczem 0 i wartością 1.
{
"put": {
"AA==": "AQ=="
},
"update_encoder": {
"action": "REGISTER",
"endpoint": "https://example.com/example_script"
}
}
Dodaje sygnał z kluczem 1 i wartością 2.
{
"put": {
"AQ==": "Ag=="
},
"update_encoder": {
"action": "REGISTER",
"endpoint": "https://example.com/example_script"
}
}
[Buyer] encodeSignals example
Koduje każdy sygnał w 2 bajtach: pierwszy bajt to pierwszy bajt klucza sygnału, a drugi – pierwszy bajt wartości sygnału.
function encodeSignals(signals, maxSize) {
// if there are no signals don't write a payload
if (signals.size === 0) {
return {};
}
let result = new Uint8Array(signals.size * 2);
let index = 0;
for (const [key, values] of signals.entries()) {
result[index++] = key[0];
result[index++] = values[0].signal_value[0];
}
return { 'status': 0, 'results': result};
}
[Buyer] prepareDataForAdRetrieval – przykład
/**
* `encodedOnDeviceSignals` is a Uint8Array and would contain
* the app signals emanating from device. For purpose of the
* demo, in our sample example, we assume that device is sending
* the signals with pair of bytes formatted as following:
* "<id><In app spending>". Where id corresponds to an ad category
* that user uses on device, and the in app spending is a measure
* of how much money the user has spent in this app category
* previously. In our example, id of 0 will correspond to a
* fitness ad category and a non-zero id will correspond to
* food app category -- though this info will be useful
* later in the B&A pipeline.
*
* Returns a JSON object indicating what type of ad(s) may be
* most relevant to the user. In a real setup ad techs might
* want to decode the signals as part of this script.
*
* Note: This example script makes use of only encoded device signals
* but adtech can take other signals into account as well to prepare
* the data that will be useful down stream for ad retrieval and
* bid generation. The max length of the app signals used in this
* sample example is arbitrarily limited to 4 bytes.
*/
function prepareDataForAdRetrieval(encodedOnDeviceSignals,
encodedOnDeviceSignalsVersion,
sellerAuctionSignals,
contextualSignals) {
if (encodedOnDeviceSignals.length === 0 || encodedOnDeviceSignals.length > 4 ||
encodedOnDeviceSignals.length % 2 !== 0) {
throw "Expected encoded signals length to be an even number in (0, 4]";
}
var preparedDataForAdRetrieval = {};
for (var i = 0; i < encodedOnDeviceSignals.length; i += 2) {
preparedDataForAdRetrieval[encodedOnDeviceSignals[i]] = encodedOnDeviceSignals[i + 1];
}
return preparedDataForAdRetrieval;
}
[Buyers] Sample ad retrieval UDF
W naszym przykładzie serwer pobierania reklam wysyła metadane (np. identyfikator każdej reklamy w tym przykładzie, ale może też zawierać inne dane, które mogą być przydatne do generowania stawek w późniejszym czasie) dla wszystkich najlepszych kandydatów na reklamy.
function getCandidateAds(requestMetadata, protectedSignals, deviceMetadata,
contextualSignals, contextualAdIds,) {
return "[{\"adId\":\"0\"},{\"adId\":\"1\"}]"
[Buyers] Przykład generateBid
/**
* This script receives the data returned by the ad retrieval service
* in the `ads` argument. This argument is supposed to contain all
* the Protected App Signals related ads and the metadata obtained from the retrieval
* service.
*
* `preparedDataForAdRetrieval` argument contains the data returned
* from the `prepareDataForAdRetrieval` UDF.
*
* This script is responsible for generating bids for the ads
* collected from the retrieval service and ad techs can decide to
* run a small inference model as part of this script in order to
* decide the best bid given all the signals available to them.
*
* For the purpose of the demo, this sample script assumes
* that ad retrieval service has sent us most relevant ads for the
* user and this scripts decides on the ad render URL as well as
* what value to bid for each ad based on the previously decoded
* device signals. For simplicity sake, this script only considers
* 2 types of app categories i.e. fitness and food.
*
* Note: Only one bid is returned among all the
* input ad candidates.
*/
function generateBid(ads, sellerAuctionSignals, buyerSignals, preparedDataForAdRetrieval) {
if (ads === null) {
console.log("No ads obtained from the ad retrieval service")
return {};
}
const kFitnessAd = "0";
const kFoodAd = "1";
const kBuyerDomain = "https://buyer-domain.com";
let resultingBid = 0;
let resultingRender = kBuyerDomain + "/no-ad";
for (let i = 0 ; i < ads.length; ++i) {
let render = "";
let bid = 0;
switch (ads[i].adId) {
case kFitnessAd:
render = kBuyerDomain + "/get-fitness-app";
bid = preparedDataForAdRetrieval[kFitnessAd];
break;
case kFoodAd:
render = kBuyerDomain + "/get-fastfood-app";
bid = preparedDataForAdRetrieval[kFoodAd];
break;
default:
console.log("Unknown ad category");
render = kBuyerDomain + "/no-ad";
break;
}
console.log("Existing bid: " + resultingBid + ", incoming candidate bid: " + bid);
if (bid > resultingBid) {
resultingBid = bid;
resultingRender = render;
}
}
return {"render": resultingRender, "bid": resultingBid};
}
[Kupujący] Przykład raportu Win
reportWin
UDF informuje kupującego, że wygrał aukcję.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
buyerReportingSignals, directFromSellerSignals,
egressPayload,
temporaryUnlimitedEgressPayload) {
sendReportTo("https://buyer-controlled-domain.com/");
registerAdBeacon({"clickEvent":"https://buyer-controlled-domain.com/clickEvent"});
return;
}
[Seller] Konfiguracja serwera KV
Sprzedawcy muszą skonfigurować serwer KV sygnałów oceniania, aby można było mapować adresy URL renderowania reklamy na odpowiednie sygnały oceniania. Na przykład: jeśli kupujący zwróci wartości https:/buyer-domain.com/get-fitness-app
i https:/buyer-domain.com/get-fastfood-app
, sprzedawca może otrzymać od SFE zapytanie o sygnały oceniania przy użyciu GET
w https://key-value-server-endpoint.com?client_type=1&renderUrls=<render-url-returned-by-the-buyer>
.
{
"renderUrls" : {
"https:/buyer-domain.com/get-fitness-app" : [
"1",
"2"
],
"https:/buyer-domain.com/get-fastfood-app" : [
"3",
"4"
]
}
}
[Seller] przykład wyniku reklamy
/**
* This module generates a random desirability score for the Protected App
* Signals ad in this example. In a production deployment,
* however, the sellers would want to use all the available signals to generate
* a score for the ad.
*/
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
function scoreAd(adMetadata, bid, auctionConfig,
trustedScoringSignals, deviceSignals,
directFromSellerSignals) {
return {
"desirability": getRandomInt(10000),
"allowComponentAuction": false
};
}
[Seller] przykład wyniku raportu
function reportResult(auctionConfig, sellerReportingSignals, directFromSellerSignals){
let signalsForWinner = {};
sendReportTo("https://seller-controlled-domain.com");
registerAdBeacon({"clickEvent":
"https://seller-controlled-domain.com/clickEvent"});
return signalsForWinner;
}
Przykładowa aplikacja
Aby pokazać, jak można używać interfejsu API do tworzenia aplikacji, która korzysta z prostego procesu opisanego powyżej, utworzyliśmy aplikację sygnałów chronionych aplikacji, którą można znaleźć w tym repozytorium przykładowych aplikacji.