Entwicklerleitfaden für Protected App-Signale

ad techproject_path: /_project.yaml book_path: /_book.yaml keywords: api:ProtectedAppSignals, docType:Guide, skill:Beginner, audienceAdBuyer, audienceAdSeller, topicAdAuction, contentTypeFundamental, category:Mobile, apiGroupAds

Damit Entwickler die Protected App Signals API ausprobieren können, werden in diesem Dokument alle APIs in der API-Oberfläche beschrieben. Außerdem wird erläutert, wie eine Testumgebung eingerichtet wird, und es werden Beispiele für die Konfiguration und die Skripts bereitgestellt.

Versionsverlauf

Januar 2024

Erste Version des Entwicklerhandbuchs zur Unterstützung der PAS MVP-Version

März 2024

Änderungen an der API zur Unterstützung der M-2024-05-Version der Android API und der im April 2024 veröffentlichten serverseitigen Komponenten. Wichtigste Änderungen:

  • Details zu den für die On-Device-API erforderlichen Berechtigungen wurden hinzugefügt.
  • Details zur Kontingentverwaltung für On-Device-Signale hinzugefügt
  • Aktualisierte generateBid-Signatur mit Änderungen im Zusammenhang mit dem Abrufen kontextbezogener Anzeigen und der Unterstützung von Egress
  • Aktualisierte reportWin-Dokumentation, einschließlich Unterstützung für den Datenexport
  • Dokumentation zur Ad Retrieval API aktualisieren, um die Unterstützung für die BYOS-Anzeigenabfrage zu entfernen und die UDF für die Anzeigenabfrage zu dokumentieren

API-Übersicht

Die Protected Signals API-Oberfläche umfasst verschiedene Teilmengen der API auf unterschiedlichen Systemen:

  • Android-APIs:
    • Signal Curation API, bestehend aus:
    • Update Signals API
    • Signals Encoding API
    • Protected Auction Support API: Diese API wird von SDKs verwendet, um die geschützte Auktion auf den Bidding and Auction-Servern (B&A-Servern) mit Protected App Signals auszuführen.
  • Serverseitige APIs:
    • Protected Auction API: Eine Reihe von JS-Skripts, die auf den Gebots- und Auktionsservern ausgeführt werden. Mit dieser API können Verkäufer und Käufer die Logik für die Implementierung der geschützten Auktion schreiben.
    • Ad Retrieval API: Diese API ist dafür verantwortlich, eine Liste mit infrage kommenden Anzeigen bereitzustellen, die auf den Kontext- und Nutzerinformationen basieren, die dem Gebotsserver des Käufers zur Verfügung gestellt werden.

Android-Client

Auf der Clientseite besteht die Protected App Signals-Oberfläche aus drei verschiedenen APIs:

  • Update Signals: Eine Android-System-API, mit der Signale auf dem Gerät kuratiert werden können.
  • Signals Encoding: Eine JavaScript API, mit der die Signale vorbereitet werden, die während der Auktion an den Server gesendet werden.
  • Unterstützung für geschützte Auktionen: Eine API zur Unterstützung der Ausführung einer geschützten Auktion auf den Gebots- und Auktionsservern. Diese API ist nicht spezifisch für Protected App Signals und wird auch zur Unterstützung von Auktionen für die Protected Audience API verwendet.

Update Signals API

Mit der Update Signals API können Ad-Tech-Unternehmen Nutzer- und appbezogene Signale im Namen eines Käufers registrieren. Die API basiert auf einem Delegierungsmodell. Der Aufrufer stellt einen URI bereit, über den das Framework die entsprechenden Signale und die Logik zum Codieren dieser Signale für die Verwendung in der Auktion abruft.

Für die API ist die Berechtigung android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS erforderlich.

Über die updateSignals() API wird ein JSON-Objekt vom URI abgerufen, das beschreibt, welche Signale hinzugefügt oder entfernt werden sollen und wie diese Signale für die Auktion vorbereitet werden.

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);

Die Plattform sendet eine HTTPS-Anfrage an den in der Anfrage angegebenen URI, um die Signalaktualisierungen abzurufen. Zusammen mit den Signalaktualisierungen kann die Antwort einen Endpunkt enthalten, der die Codierungslogik für die Umwandlung der Rohsignale in eine codierte Nutzlast hostet. Die Signalaktualisierungen müssen im JSON-Format vorliegen und können die folgenden Schlüssel enthalten:

Die Schlüssel der obersten Ebene für das JSON-Objekt müssen einem von fünf Befehlen entsprechen:

key

Beschreibung

put

Fügt ein neues Signal hinzu und überschreibt alle vorhandenen Signale mit demselben Schlüssel. Der Wert

Dabei handelt es sich um ein JSON-Objekt, bei dem die Schlüssel Base64-Strings sind, die dem einzufügenden Schlüssel entsprechen, und die Werte Base64-Strings sind, die dem einzufügenden Wert entsprechen.

append

Fügt einer Zeitreihe von Signalen ein neues Signal oder neue Signale hinzu und entfernt das älteste.

Signale, um Platz für die neuen zu schaffen, wenn die Größe der Reihe das angegebene Maximum überschreitet. Der Wert dafür ist ein JSON-Objekt, bei dem die Schlüssel Base64-Strings sind, die dem anzuhängenden Schlüssel entsprechen, und die Werte Objekte mit zwei Feldern: „values“ und „maxSignals“.

„values“: Eine Liste von Base64-Strings, die den Signalwerten entsprechen, die an die Zeitachse angehängt werden sollen.

„maxSignals“: Die maximale Anzahl von Werten, die in dieser Zeitreihe zulässig sind. Wenn

Die aktuelle Anzahl der mit dem Schlüssel verknüpften Signale überschreitet „maxSignals“. Die ältesten Signale werden entfernt. Sie können einen mit „put“ hinzugefügten Schlüssel ergänzen. Wenn Sie mehr als die maximale Anzahl von Werten anhängen, tritt ein Fehler auf.

put_if_not_present

Fügt ein neues Signal nur hinzu, wenn keine vorhandenen Signale mit demselben Schlüssel vorhanden sind. Der Wert dafür ist ein JSON-Objekt, bei dem die Schlüssel Base64-Strings sind, die dem einzufügenden Schlüssel entsprechen, und die Werte Base64-Strings sind, die dem einzufügenden Wert entsprechen.

remove

Entfernt das Signal für einen Schlüssel. Der Wert ist eine Liste von Base64-Strings, die den Schlüsseln der Signale entsprechen, die gelöscht werden sollen.

update_encoder

Bietet eine Aktion zum Aktualisieren des Endpunkts und einen URI, der verwendet werden kann.

um eine Codierungslogik abzurufen. Der untergeordnete Schlüssel für die Angabe einer Aktualisierungsaktion ist „action“ und der

Der einzige unterstützte Wert ist „REGISTER“. Dadurch wird der Encoder-Endpunkt registriert, wenn er zum ersten Mal angegeben wird, oder der vorhandene Endpunkt wird mit dem neu angegebenen Endpunkt überschrieben. Die Angabe des Endpunkts ist für die Aktion „REGISTER“ erforderlich. Der untergeordnete Schlüssel für die Angabe eines Encoder-Endpunkts ist „endpoint“ und der Wert ist der URI.

String für den Endpunkt.

Eine Beispiel-JSON-Anfrage sieht so aus:

{
    "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"
    }
}

Signale haben ein Kontingent auf dem Gerät von etwa 10 bis 15 KB. Sobald das Kontingent überschritten ist, werden Signale von PPAPI nach dem FIFO-Prinzip (First In, First Out) entfernt. Beim Entfernen von Inhalten kann das Kontingent für kurze Zeit leicht überschritten werden, um die Häufigkeit von Entfernungen zu verringern.

Signals Encoding API

Käufer müssen eine JavaScript-Funktion bereitstellen, mit der die auf dem Gerät gespeicherten Signale codiert werden, die während der geschützten Auktion an den Server gesendet werden sollen. Käufer können dieses Script bereitstellen, indem sie die URL, von der es abgerufen werden kann, mit dem Schlüssel „update_encoder“ in eine der Antworten auf eine UpdateSignal API-Anfrage einfügen. Das Skript hat die folgende Signatur:

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)};
}

Der Parameter signals ist eine Zuordnung von Schlüsseln in Form von UInt8Arrays der Größe 4 zu Listen von Protected App Signals-Objekten. Jedes Protected App Signals-Objekt hat drei Felder:

  • signal_value: Ein UInt8Array, das den Wert des Signals darstellt.
  • creation_time: Eine Zahl, die die Erstellungszeit der Signale in Epochensekunden darstellt.
  • package_name: Ein String, der den Namen des Pakets darstellt, das das Signal erstellt hat.

Der Parameter maxSize ist eine Zahl, die die maximal zulässige Arraygröße für die Ausgabe beschreibt.

Die Funktion sollte ein Objekt mit zwei Feldern ausgeben:

  • status: Sollte 0 sein, wenn das Skript erfolgreich ausgeführt wurde.
  • results: Sollte ein UInt8Array mit einer Länge von höchstens „maxSize“ sein. Dieses Array wird während Auktionen an den Server gesendet und vom prepareDataForAdRetrieval-Skript vorbereitet.

Die Codierung bietet Ad-Tech-Unternehmen eine erste Phase der Feature-Entwicklung, in der sie Transformationen wie das Komprimieren von Rohsignalen in verkettete Versionen basierend auf ihrer eigenen benutzerdefinierten Logik durchführen können. Bei einer geschützten Auktion, die in der vertrauenswürdigen Ausführungsumgebung (Trusted Execution Environment, TEE) ausgeführt wird, hat die benutzerdefinierte Logik der Ad-Tech-Anbieter Lesezugriff auf die Signal-Payloads, die durch die Codierung generiert werden. Die benutzerdefinierte Logik, die als nutzerdefinierte Funktion (User Defined Function, UDF) bezeichnet wird und in der B&A-TEE des Käufers ausgeführt wird, hat Lesezugriff auf die codierten Signale und andere kontextbezogene Signale, die von der Publisher-App bereitgestellt werden, um die Anzeigenauswahl (Abruf und Gebotsabgabe) durchzuführen.

Signals encoding

Stündlich werden die Signale von Käufern, die eine Codierungslogik mit ihren registrierten Signalen bereitgestellt haben, in eine Auktionsnutzlast codiert.Das Byte-Array für die Auktionsnutzlast wird auf dem Gerät gespeichert, verschlüsselt und von Verkäufern als Teil der Daten zur Anzeigenauswahl erfasst, um in eine Protected Audience-Auktion aufgenommen zu werden. Zum Testen können Sie diese Codierung außerhalb des stündlichen Rhythmus auslösen, indem Sie den folgenden Befehl ausführen:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
Versionsverwaltung der Encoder-Logik

Wenn eine Anfrage zum Herunterladen der benutzerdefinierten Encoder-Logik für Ad‑Tech gestellt wird, kann der Ad‑Tech-Endpunkt mit einer Versionsnummer in den Antwortheadern antworten. Diese Version wird zusammen mit der Encoder-Logik auf dem Gerät gespeichert. Wenn die Rohsignale codiert werden, wird die codierte Nutzlast zusammen mit der für die Codierung verwendeten Version gespeichert. Diese Version wird auch während einer geschützten Auktion an den B&A-Server gesendet, damit Ad-Tech-Unternehmen ihre Gebots- und Codierungslogik an die Version anpassen können.

Response header for providing encoder version : X_ENCODER_VERSION

Protected Auction Support API

Auf dem Gerät ist die Ausführung einer Auktion für Protected App Signals identisch mit der Ausführung einer Auktion für geschützte Zielgruppen.

Gebots- und Auktionsdienste

Die serverseitigen APIs umfassen:

  • Protected Auction API: Eine Reihe von JS-Funktionen oder benutzerdefinierten Funktionen, die Käufer und Verkäufer in den B&A-Komponenten bereitstellen können, die ihnen gehören, um die Gebots- und Auktionslogik zu bestimmen.
  • Ad Retrieval API: Käufer können diese API implementieren, indem sie einen REST-Endpunkt implementieren, der für die Bereitstellung einer Reihe von infrage kommenden Anzeigen für die Protected App Signal-Auktion verantwortlich ist.

Protected Auction API

Die Protected Auction API besteht aus JS-APIs oder UDFs, mit denen Käufer und Verkäufer ihre Auktions- und Gebotslogik implementieren können.

UDFs für die Werbetechnologie von Käufern
UDF „prepareDataForAdRetrieval“

Bevor geschützte App-Signale verwendet werden können, um Anzeigenkandidaten vom TEE-Anzeigenabrufdienst abzurufen, müssen Käufer die geschützten App-Signale und andere vom Verkäufer bereitgestellte Daten decodieren und vorbereiten. Die prepareDataForAdRetrieval-UDF-Ausgabe wird an den Dienst zum Abrufen von Anzeigen übergeben, um die k besten Kandidatenanzeigen für Gebote abzurufen.

// 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 ad tech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
   return {};
}
UDF für die Gebotsgenerierung

Nachdem die k besten Anzeigenkandidaten zurückgegeben wurden, werden sie an die benutzerdefinierte Gebotslogik des Käufers, die generateBid benutzerdefinierte Funktion, übergeben:

// 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>
    };
}

Die Ausgabe dieser Funktion ist ein einzelnes Gebot für einen Anzeigenkandidaten, das als JSON-Entsprechung von ProtectedAppSignalsAdWithBidMetadata dargestellt wird. Die Funktion kann auch zwei Arrays zurückgeben, die dann an reportWin übergeben werden, um das Modelltraining zu ermöglichen. Weitere Informationen zum Egress und Modelltraining finden Sie im Abschnitt „Berichte“ in der PAS-Erklärung.

UDF für „Bericht – Gewinn“

Wenn eine Auktion abgeschlossen ist, generiert der Auktionsdienst Berichts-URLs für die Käufer und registriert Beacons mit der reportWin-UDF (dies ist dieselbe reportWin-Funktion, die für Protected Audiences verwendet wird). Das Gerät wird benachrichtigt, sobald die Anzeige vom Client gerendert wurde. Die Signatur dieser Methode ist fast dieselbe wie die Protected Audience-Version, mit Ausnahme von zwei zusätzlichen Parametern egressPayload und temporaryUnlimitedEgressPayload, die zum Aktivieren des Modelltrainings verwendet werden und mit den Ergebnissen von generateBid gefüllt werden.

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals,
                   egressPayload, temporaryUnlimitedEgressPayload) {
  // ...
}
UDFs für Anzeigentechnologie für Verkäufer
UDF „scoreAd“

Diese benutzerdefinierte Funktion wird von Verkäufern verwendet, um auszuwählen, welche der von Käufern erhaltenen Anzeigen die Auktion gewinnen.

function scoreAd(adMetadata, bid, auctionConfig,
                 trustedScoringSignals, bid_metadata) {
  // ...
  return {desirability: desirabilityScoreForThisAd,
              allowComponentAuction: true_or_false};
}
UDF „reportResult“

Mit dieser benutzerdefinierten Funktion kann der Verkäufer (eventuell) Berichte auf Ereignisebene mit den Informationen zur Gewinneranzeige erstellen.

function reportResult(auctionConfig, reporting_metadata) {
  // ...
  registerAdBeacon({"click", clickUrl,"view", viewUrl});
  sendReportTo(reportResultUrl);
  return signalsForWinner;
}

Ad Retrieval API

In der MVP-Version ist der Dienst zum Abrufen von Anzeigen ein vom Käufer verwalteter und gehosteter Dienst. Der Gebotsdienst ruft Anzeigenkandidaten von diesem Dienst ab. Ab April 2024 muss der Server zum Abrufen von Anzeigen in einem Trusted Execution Environment (TEE) ausgeführt werden und eine GRPC-/Proto-Schnittstelle bereitstellen. Ad-Tech-Unternehmen müssen diesen Server einrichten und seine URL im Rahmen der Bereitstellung des B&A-Stacks angeben. Eine Implementierung dieses Dienstes, der in der TEE ausgeführt wird, ist im Privacy Sandbox GitHub verfügbar. In der restlichen Dokumentation gehen wir davon aus, dass dieser Code in der Bereitstellung verwendet wird.

Ab April 2024 unterstützen B&A-Versionen das Abrufen von Anzeigen über den Kontextpfad. In diesem Fall erhält der Gebotsserver eine Liste der Anzeigen-IDs, die vom RTB-Server während des kontextbezogenen Teils der Auktion gesendet werden. Die Kennungen werden an einen TEE-KV-Server gesendet, um alle anzeigenbezogenen Informationen abzurufen, die während der Gebotsphase verwendet werden sollen (z. B. die URL zum Rendern von Anzeigen, Metadaten und Anzeigeneinbettungen, die bei der Top-k-Auswahl verwendet werden sollen). Für diesen zweiten Pfad muss keine spezielle Logik bereitgestellt werden. Daher wird hier nur beschrieben, wie der Anwendungsfall für den Anzeigenabruf auf TEE-Basis konfiguriert wird.

UDF „getCandidateAds“
function getCandidateAds(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals, contextualAdIds,) {
    return adsMetadataString;
}

Wobei:

  • requestMetadata: JSON. Metadaten des Servers pro Anfrage an die UDF. Derzeit leer.
  • preparedDataForAdRetrieval: Der Inhalt dieses Felds hängt von der Strategie zum Abrufen von Anzeigen ab. Bei der kontextbezogenen Anzeigenabfrage enthält dieser Parameter die Rohsignale, die vom Gerät stammen und vom Gebotsdienst übergeben werden. Bei der TEE-Anzeigenabfrage über den Ad Retrieval Server enthält dieser Parameter das Ergebnis der prepareDataForAdRetrieval-UDF. Hinweis: An dieser Stelle werden die Protected App Signals decodiert und entschlüsselt.
  • deviceMetadata: JSON-Objekt mit Gerätemetadaten, die vom Werbedienst des Verkäufers weitergeleitet werden. Weitere Informationen finden Sie in der B&A-Dokumentation.
    • X-Accept-Language: Die auf dem Gerät verwendete Sprache.
    • X-User-Agent: Auf dem Gerät verwendeter User-Agent.
    • X-BnA-Client-IP: Die IP-Adresse des Geräts.
  • contextualSignals: Beliebiger String, der vom Server für kontextbezogene Gebote der DSP stammt. Die UDF muss den String decodieren und verwenden können. Kontextbezogene Signale können beliebige Informationen enthalten, z. B. Informationen zur Version des ML-Modells für das geschützte Embedding, das über Protected App Signals übergeben wird.
  • contextualAdIds: JSON-Objekt mit einer optionalen Liste von Anzeigen-IDs.

Die UDF sollte bei Erfolg einen String zurückgeben. Der String wird an den Gebotsserver zurückgegeben, der ihn dann an die UDF generateBid übergibt. Der String kann zwar ein einfacher String sein, aber höchstwahrscheinlich sollte es sich um ein serialisiertes Objekt handeln, dessen Schema von jedem Ad-Tech-Unternehmen selbst definiert wird. Es gibt keine Einschränkungen für das Schema, solange die generateBid-Logik der Ad-Tech-Plattform den String erkennen und verwenden kann.

System für die Entwicklung einrichten

Android

So richten Sie Ihre Android-Entwicklungsumgebung ein:

  1. Erstellen Sie einen Emulator (empfohlen) oder ein physisches Gerät, auf dem das Developer Preview 10-Image ausgeführt wird.
  2. Führen Sie den folgenden Befehl aus:
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity

Wählen Sie dann die angezeigte Option aus, um der Anzeige von App-Vorschlagsanzeigen zuzustimmen.

  1. Führen Sie den folgenden Befehl aus, um die relevanten APIs zu aktivieren. Möglicherweise müssen Sie diesen Befehl gelegentlich noch einmal ausführen, da die Standardkonfiguration „disabled“ regelmäßig synchronisiert wird.
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;
  1. Starten Sie das Gerät neu.
  2. Überschreiben Sie die Auktionsschlüssel des Geräts, damit sie auf Ihren Auktionsschlüsselserver verweisen. Es ist wichtig, diesen Schritt auszuführen, bevor Sie versuchen, eine Auktion durchzuführen, um zu verhindern, dass falsche Schlüssel im Cache gespeichert werden.

Gebots- und Auktionsdienste

Eine Anleitung zum Einrichten der B&A-Server finden Sie in der Dokumentation zur Einrichtung.

In diesem Dokument wird beschrieben, wie die käuferspezifischen Server konfiguriert werden. Für Verkäufer sind keine Änderungen erforderlich.

Vorbereitung

Bevor ein B&A-Servicestack bereitgestellt wird, muss die Ad-Tech-Lösung des Käufers Folgendes tun:

  • Prüfen Sie, ob der Entwickler einen eigenen TEE-Dienst zum Abrufen von Anzeigen bereitgestellt hat (siehe entsprechender Abschnitt).
  • Prüfen Sie, ob für die AdTech alle erforderlichen nutzerdefinierten Funktionen (prepareDataForAdRetrieval, generateBid, reportWin, getCandidateAds) definiert und gehostet sind.

Es ist auch hilfreich, wenn Sie wissen, wie die Protected Auction mit Protected Audience mit B&A funktioniert, aber nicht zwingend erforderlich.

Terraform-Konfiguration

Um Protected App Signals zu verwenden, müssen Ad-Tech-Unternehmen

  • Unterstützung für Protected App Signals in B&A aktivieren
  • Geben Sie URL-Endpunkte an, von denen die neuen UDFs für prepareDataForAdRetrieval, generateBid und reportWin abgerufen werden können.

Außerdem wird in dieser Anleitung davon ausgegangen, dass Anzeigentechnologien, die B&A für Remarketing verwenden möchten, weiterhin alle vorhandenen Konfigurationsflags für die Remarketing-Auktion wie gewohnt festlegen.

Konfiguration der Werbetechnologie für Käufer

Anhand dieser Demodatei müssen Käufer die folgenden Flags festlegen:

  • Protected App Signals aktivieren: Aktiviert, um Daten zu Protected App Signals zu erheben.
  • URLs für Protected App Signals: Auf die URLs der Protected App Signals-Server festgelegt.

Ad-Tech-Anbieter müssen die richtigen URLs in die Platzhalter für die folgenden Felder einfügen:

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"

Konfiguration der Anzeigentechnologie durch den Verkäufer

Anhand dieser Demodatei müssen Verkäufer die folgenden Flags festlegen. Hinweis: Hier wird nur die Konfiguration für Protected App Signals hervorgehoben. Anzeigentechnologien müssen überprüfen, ob sie die richtigen URLs in die Platzhalter einfügen:

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"

KV- und Anzeigenabrufdienste

Je nach den Strategien, die zur Unterstützung des Abrufs von Anzeigen ausgewählt wurden, muss das System eine oder zwei Instanzen des KV-Dienstes bereitstellen. Die KV-Instanz, die für den TEE-basierten Anzeigenabruf verwendet wird, wird als Ad Retrieval Server bezeichnet, die Instanz zur Unterstützung des kontextbezogenen pfadbasierten Abrufs als KV Lookup Server.

In beiden Fällen folgt die Serverbereitstellung der Dokumentation, die auf KV-Server GitHub verfügbar ist. Der Unterschied zwischen den beiden Fällen besteht darin, dass der Lookup-Fall ohne zusätzliche Konfiguration funktioniert, während für den Abruf die Bereitstellung der getCandidateAds-UDF zur Implementierung der Abrufslogik erforderlich ist. Weitere Informationen finden Sie im Onboarding-Leitfaden für den KV-Server. Beachten Sie, dass B&A erwartet, dass beide Dienste im selben Service Mesh wie der Gebotsdienst bereitgestellt werden.

Beispiel für die Einrichtung

Stellen Sie sich folgendes Szenario vor: Ein Ad-Tech-Unternehmen verwendet die Protected App Signals API, um relevante Signale basierend auf der App-Nutzung durch Nutzer zu speichern. In unserem Beispiel werden Signale gespeichert, die In-App-Käufe aus mehreren Apps darstellen. Während einer Auktion werden die verschlüsselten Signale erfasst und an eine Protected Auction übergeben, die in B&A ausgeführt wird. Die benutzerdefinierten Funktionen des Käufers, die in B&A ausgeführt werden, verwenden die Signale, um Anzeigekandidaten abzurufen und ein Gebot zu berechnen.

Beispiele für [Käufer]-Signale

Fügt ein Signal mit dem Schlüssel 0 und dem Wert 1 hinzu.

{
  "put": {
    "AA==": "AQ=="
  },
  "update_encoder": {
    "action": "REGISTER",
    "endpoint": "https://example.com/example_script"
  }
}

Fügt ein Signal mit dem Schlüssel 1 und dem Wert 2 hinzu.

{
  "put": {
    "AQ==": "Ag=="
  },
  "update_encoder": {
    "action": "REGISTER",
    "endpoint": "https://example.com/example_script"
  }
}

[Buyer] encodeSignals-Beispiel

Codiert jedes Signal in zwei Byte. Das erste Byte ist das erste Byte des Signalschlüssels und das zweite Byte das erste Byte des Signalwerts.

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-Beispiel

/**
 * `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, an 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 ad tech 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;
}

[Käufer] Beispiel-UDF für den Anzeigenabruf

In unserem Beispiel sendet der Server zum Abrufen von Anzeigen Metadaten (d.h. die ID für jede Anzeige in diesem Beispiel, kann aber auch andere Daten für jede Anzeige enthalten, die später beim Generieren von Geboten hilfreich sein können) für jeden der k besten Anzeigenkandidaten.

function getCandidateAds(requestMetadata, protectedSignals, deviceMetadata,
                      contextualSignals,   contextualAdIds,) {
 return "[{\"adId\":\"0\"},{\"adId\":\"1\"}]"

[Buyers] generateBid-Beispiel

/**
 * 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};
}

[Buyers] reportWin example

Mit der reportWin-UDF wird dem Käufer mitgeteilt, dass er die Auktion gewonnen hat.

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] KV server setup

Verkäufer müssen einen KV-Server für Scoring-Signale einrichten, damit eine Zuordnung von den URLs für das Rendern von Anzeigen zu den entsprechenden Scoring-Signalen verfügbar ist. Beispiel: Wenn https:/buyer-domain.com/get-fitness-app und https:/buyer-domain.com/get-fastfood-app vom Käufer zurückgegeben werden, kann der Verkäufer die folgende Beispielantwort für Scoring-Signale erhalten, wenn der SFE eine Anfrage mit einem GET auf https://key-value-server-endpoint.com?client_type=1&renderUrls=<render-url-returned-by-the-buyer> sendet:

{
   "renderUrls" : {
      "https:/buyer-domain.com/get-fitness-app" : [
         "1",
         "2"
      ],
      "https:/buyer-domain.com/get-fastfood-app" : [
         "3",
         "4"
      ]
   }
}

[Seller] scoreAd-Beispiel

/**
 * 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
  };
}

Beispiel für [Seller] reportResult

function reportResult(auctionConfig, sellerReportingSignals, directFromSellerSignals){
  let signalsForWinner = {};
    sendReportTo("https://seller-controlled-domain.com");
    registerAdBeacon({"clickEvent":
                    "https://seller-controlled-domain.com/clickEvent"});
    return signalsForWinner;
}

Beispiel-App

Als Beispiel für die Verwendung der API zum Erstellen einer App, die diesen Ablauf nutzt, haben wir eine Beispiel-App für Protected App Signals erstellt, die in diesem Beispiel-Repository zu finden ist.