מדריך למפתחים בנושא Protected Audience API

כשתקראו את מסמכי התיעוד של ארגז החול לפרטיות ב-Android, השתמשו בלחצן תצוגה מקדימה למפתחים או בטא כדי לבחור את גרסת התוכנית שאיתה אתם עובדים, מכיוון שההוראות עשויות להשתנות.


שליחת משוב

Protected Audience API ב-Android (לשעבר FLEDGE) כולל את Custom Audience API ואת Ad Selection API. פלטפורמות הפרסום הדיגיטלי והמפרסמים יכולים להשתמש בממשקי ה-API האלה כדי להציג מודעות מותאמות אישית על סמך אינטראקציות קודמות באפליקציה, שמגבילות את השיתוף של מזהים בין אפליקציות ומגבילות את השיתוף של פרטי האינטראקציה של המשתמשים עם צדדים שלישיים.

ה-Custom Audience API מרוכז סביב הפשטה 'קהל בהתאמה אישית', שמייצגת קבוצה של משתמשים עם כוונות משותפות. מפרסם יכול לרשום משתמש לקהל בהתאמה אישית ולשייך אליו מודעות רלוונטיות. המידע הזה מאוחסן באופן מקומי ויכול לשמש לעדכון הצעות מחיר של מפרסמים, סינון מודעות והצגת מודעות.

Ad Selection API היא מסגרת שמאפשרת למספר מפתחים לנהל מכרז באופן מקומי עבור קהל בהתאמה אישית. כדי לעשות זאת, המערכת מביאה בחשבון מודעות רלוונטיות שמשויכות לקהל בהתאמה אישית, ומבצעת עיבוד נוסף של המודעות שפלטפורמת הפרסום מחזירה למכשיר.

פלטפורמות פרסום דיגיטלי יכולות לשלב את ממשקי ה-API האלה כדי להטמיע רימרקטינג ששומר על פרטיות המשתמשים. במהדורות הבאות מתוכננת תמיכה בתרחישים נוספים לדוגמה, כולל מודעות להתקנת אפליקציה. מידע נוסף על Protected Audience API ב-Android זמין בהצעת העיצוב.

במדריך הזה מוסבר איך לעבוד עם Protected Audience API ב-Android כדי לבצע את הפעולות הבאות:

  1. ניהול קהלים בהתאמה אישית
  2. הגדרה והפעלה של מודעות נבחרות במכשיר
  3. דיווח על חשיפות של מודעות

לפני שמתחילים

לפני שמתחילים:

  1. מגדירים את סביבת הפיתוח של ארגז החול לפרטיות ב-Android.
  2. מתקינים תמונת מערכת במכשיר נתמך או מגדירים אמולטור שכולל תמיכה בארגז החול לפרטיות ב-Android.
  3. בטרמינל, מפעילים את הגישה ל-Protected Audience API (מושבת כברירת מחדל) באמצעות פקודת ה-adb הבאה.

      adb shell device_config put adservices ppapi_app_allow_list \"*\"
    
  4. כדאי לכלול את ההרשאה ACCESS_ADSERVICES_CUSTOM_AUDIENCE במניפסט של האפליקציה:

      <uses-permission android:name="android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCE" />
    
  5. אפשר להפנות להגדרה של שירותי מודעות ברכיב <application> של המניפסט:

      <property android:name="android.adservices.AD_SERVICES_CONFIG"
                android:resource="@xml/ad_services_config" />
    
  6. צריך לציין את משאב ה-XML של שירותי המודעות שיש אליו הפניה במניפסט, כמו res/xml/ad_services_config.xml. מידע נוסף על הרשאות בשירותי מודעות ועל בקרת הגישה ל-SDK

      <ad-services-config>
        <custom-audiences allowAllToAccess="true" />
      </ad-services-config>
    
  7. כברירת מחדל, ה-Ad Selection API אוכף מגבלות על כמות הזיכרון המקסימלית שאפשר להקצות לסקריפט לדיווח על חשיפות או למכירה פומבית. תכונת הגבלת הזיכרון מחייבת WebView גרסה 105.0.5195.58 ואילך. הפלטפורמה אוכפת בדיקת גרסאות וקריאות לממשקי ה-API של selectAds ו-reportImpression נכשלות אם לא תקפידו על כך. יש שתי אפשרויות להגדרה:

    • אפשרות 1: מפעילים את פקודת ה-adb הבאה כדי להשבית את הבדיקה:

      adb device_config put fledge_js_isolate_enforce_max_heap_size false
      
    • אפשרות 2: מתקינים את גרסת הבטא של WebView מחנות Google Play. הערך הזה חייב להיות שווה לגרסה שצוינה למעלה או גבוה ממנה.

הצטרפות לקהל בהתאמה אישית

קהל בהתאמה אישית מייצג קבוצה של משתמשים עם כוונות או תחומי עניין משותפים, כפי שנקבע על ידי אפליקציה של מפרסם. אפליקציה או SDK עשויים להשתמש בקהל בהתאמה אישית כדי לציין קהל מסוים, למשל מישהו שהשאיר פריטים בעגלת הקניות. כדי ליצור קהל בהתאמה אישית או להצטרף אליו באופן אסינכרוני, צריך לבצע את הפעולות הבאות:

  1. מאתחלים את האובייקט CustomAudienceManager.
  2. יוצרים אובייקט CustomAudience על ידי ציון פרמטרים מרכזיים, כמו החבילה של הקונה ושם רלוונטי. לאחר מכן, מאתחלים את האובייקט JoinCustomAudienceRequest עם האובייקט CustomAudience.
  3. קוראים לפונקציה joinCustomAudience() האסינכרונית עם האובייקט JoinCustomAudienceRequest והאובייקטים הרלוונטיים מסוג Executor ו-OutcomeReceiver.

Kotlin

val customAudienceManager: CustomAudienceManager =
    context.getSystemService(CustomAudienceManager::class.java)

// Initialize a custom audience.
val audience = CustomAudience.Builder()
    .setBuyer(buyer)
    .setName(name)
    ...
    .build()

// Initialize a custom audience request.
val joinCustomAudienceRequest: JoinCustomAudienceRequest =
    JoinCustomAudienceRequest.Builder().setCustomAudience(audience).build()

// Request to join a custom audience.
customAudienceManager.joinCustomAudience(joinCustomAudienceRequest,
    executor,
    outcomeReceiver)

Java

CustomAudienceManager customAudienceManager =
    context.getSystemService(CustomAudienceManager.class);

// Initialize a custom audience.
CustomAudience audience = new CustomAudience.Builder()
    .setBuyer(buyer)
    .setName(name)
    ...
    .build();

// Initialize a custom audience request.
JoinCustomAudienceRequest joinCustomAudienceRequest =
    new JoinCustomAudienceRequest.Builder().setCustomAudience(audience).build();

// Request to join a custom audience.
customAudienceManager.joinCustomAudience(joinCustomAudienceRequest,
    executor,
    outcomeReceiver);

שילוב הפרמטרים הבאים מזהה באופן ייחודי כל אובייקט CustomAudience במכשיר:

  • owner: שם החבילה של אפליקציית הבעלים. מוגדר באופן מרומז לשם החבילה של אפליקציית הקריאה.
  • buyer: מזהה של רשת המודעות של הקונה שמנהלת מודעות עבור הקהל המותאם אישית הזה.
  • name: שם או מזהה שרירותיים של הקהל בהתאמה אישית.

קריאה חוזרת ל-joinCustomAudience() עם מופע אחר של CustomAudience מעדכנת את כל CustomAudience הקיים עם פרמטרים תואמים מסוג owner, buyer ו-name. כדי לשמור על הפרטיות, התוצאה של ה-API לא מבדילה בין 'יצירה' ל'עדכון'.

בנוסף, יש ליצור את CustomAudience עם הפרמטרים הנדרשים הבאים:

  • כתובת URL לעדכון יומי: כתובת URL מסוג HTTPS נשלחת שאילתה מדי יום ברקע כדי לעדכן אותות של הצעות מחיר למשתמשים מותאמים אישית, נתונים מהימנים של בידינג, ולעבד כתובות URL ומטא-נתונים של מודעות.
  • כתובת URL לפי לוגיקה של בידינג: כתובת URL מסוג HTTPS שנשלחת שאילתה במהלך בחירת המודעה כדי לאחזר את לוגיקת הבידינג ב-JavaScript של הקונה. ראו את חתימות הפונקציות הנדרשות ב-JavaScript הזה.
  • מזהי עיבוד מודעות: מזהה שרירותי שהוגדר על ידי טכנולוגיית המודעות של הקונה. זוהי אופטימיזציה ליצירת המטען הייעודי (payload) ל-B&A.

פרמטרים אופציונליים לאובייקט CustomAudience יכולים לכלול:

  • זמן הפעלה: קהל בהתאמה אישית יכול להשתתף בבחירת מודעות ובעדכונים יומיים רק אחרי מועד ההפעלה. זה יכול להיות שימושי, למשל, כדי לעורר עניין במשתמשים שאינם פעילים באפליקציה.
  • Expiration time (מועד תפוגה): זמן עתידי שאחריו הקהל בהתאמה אישית יוסר מהמכשיר.
  • אותות לבידינג למשתמשים: מחרוזת JSON שמכילה אותות של משתמשים, כמו הלוקאל המועדף על המשתמש, שלוגיקת הבידינג של הקונה משתמשת בהם כדי ליצור הצעות מחיר בתהליך בחירת המודעות. הפורמט הזה עוזר לפלטפורמות של פרסום דיגיטלי לעשות שימוש חוזר בקוד בפלטפורמות שונות, ומקל על הצריכה בפונקציות JavaScript.
  • נתוני בידינג מהימנים: כתובת URL מסוג HTTPS ורשימת מחרוזות שמשמשות בתהליך בחירת המודעות כדי לאחזר אותות בידינג משירות מפתח/ערך מהימן.
  • Ads: רשימה של אובייקטים מ-AdData שתואמים למודעות שמשתתפות בבחירת המודעות. כל אובייקט AdData מורכב מהרכיבים הבאים:
    • כתובת URL לעיבוד: כתובת URL מסוג HTTPS שנשלחת בקשה להצגת המודעה הסופית.
    • מטא-נתונים: אובייקט JSON שעבר סריאליזציה כמחרוזת שמכילה מידע, על ידי לוגיקת הבידינג של הקונה בתהליך בחירת המודעה.
    • מסנני מודעות: מחלקה שמכילה את כל המידע הנדרש לסינון מודעות להתקנת אפליקציה ולמכסת התדירות במהלך בחירת המודעה.

הנה דוגמה ליצירת אובייקט CustomAudience:

Kotlin

// Minimal initialization of a CustomAudience object
val customAudience: CustomAudience = CustomAudience.Builder()
    .setBuyer(AdTechIdentifier.fromString("my.buyer.domain.name"))
    .setName("example-custom-audience-name")
    .setDailyUpdateUrl(Uri.parse("https://DAILY_UPDATE_URL"))
    .setBiddingLogicUrl(Uri.parse("https://BIDDING_LOGIC_URL"))
    .build()

Java

// Minimal initialization of a CustomAudience object
CustomAudience customAudience = CustomAudience.Builder()
    .setBuyer(AdTechIdentifier.fromString("my.buyer.domain.name"))
    .setName("example-custom-audience-name")
    .setDailyUpdateUrl(Uri.parse("https://DAILY_UPDATE_URL"))
    .setBiddingLogicUrl(Uri.parse("https://BIDDING_LOGIC_URL"))
    .build();

טיפול בתוצאות שלjoinCustomAudience()

השיטה האסינכרונית joinCustomAudience() משתמשת באובייקט OutcomeReceiver כדי לסמן את התוצאה של הקריאה ל-API.

  • הקריאה החוזרת (callback) onResult() מציינת שהקהל בהתאמה אישית נוצר או עודכן בהצלחה.
  • הקריאה החוזרת (callback) onError() מציינת שני תנאים אפשריים.

הנה דוגמה לטיפול בתוצאה של joinCustomAudience():

Kotlin

var callback: OutcomeReceiver<Void, AdServicesException> =
    object : OutcomeReceiver<Void, AdServicesException> {
    override fun onResult(result: Void) {
        Log.i("CustomAudience", "Completed joinCustomAudience")
    }

    override fun onError(error: AdServicesException) {
        // Handle error
        Log.e("CustomAudience", "Error executing joinCustomAudience", error)
    }
};

Java

OutcomeReceiver callback = new OutcomeReceiver<Void, AdServicesException>() {
    @Override
    public void onResult(@NonNull Void result) {
        Log.i("CustomAudience", "Completed joinCustomAudience");
    }

    @Override
    public void onError(@NonNull AdServicesException error) {
        // Handle error
        Log.e("CustomAudience", "Error executing joinCustomAudience", error);
    }
};

עזיבת קהל בהתאמה אישית

אם המשתמש כבר לא עומד בקריטריונים העסקיים של קהל מותאם אישית מסוים, אפליקציה או SDK יכולים לבצע קריאה ל-leaveCustomAudience() כדי להסיר את הקהל בהתאמה אישית מהמכשיר. כדי להסיר CustomAudience על סמך הפרמטרים הייחודיים שלו:

  1. מאתחלים את האובייקט CustomAudienceManager.
  2. מפעילים את LeaveCustomAudienceRequest עם buyer ו-name של הקהל בהתאמה אישית. למידע נוסף על שדות הקלט האלה, קראו את המאמר הצטרפות לקהל בהתאמה אישית.
  3. קוראים לשיטה leaveCustomAudience() האסינכרונית עם האובייקט LeaveCustomAudienceRequest והאובייקטים הרלוונטיים Executor ו-OutcomeReceiver.

Kotlin

val customAudienceManager: CustomAudienceManager =
    context.getSystemService(CustomAudienceManager::class.java)

// Initialize a LeaveCustomAudienceRequest
val leaveCustomAudienceRequest: LeaveCustomAudienceRequest =
    LeaveCustomAudienceRequest.Builder()
        .setBuyer(buyer)
        .setName(name)
        .build()

// Request to leave a custom audience
customAudienceManager.leaveCustomAudience(
    leaveCustomAudienceRequest,
    executor,
    outcomeReceiver)

Java

CustomAudienceManager customAudienceManager =
    context.getSystemService(CustomAudienceManager.class);

// Initialize a LeaveCustomAudienceRequest
LeaveCustomAudienceRequest leaveCustomAudienceRequest =
    new LeaveCustomAudienceRequest.Builder()
        .setBuyer(buyer)
        .setName(name)
        .build();

// Request to leave a custom audience
customAudienceManager.leaveCustomAudience(
    leaveCustomAudienceRequest,
    executor,
    outcomeReceiver);

בדומה לקריאה ל-joinCustomAudience(), הפרמטר OutcomeReceiver מסמן סיום קריאה ל-API. כדי להגן על הפרטיות, תוצאות השגיאה לא מבדילה בין שגיאות פנימיות לבין ארגומנטים לא חוקיים. הקריאה החוזרת (callback) onResult() מתבצעת בסיום הקריאה ל-API, גם אם לא הוסר קהל תואם בהתאמה אישית.

הפעלה של בחירת המודעות

כדי להשתמש ב-Protected Audience API לצורך בחירת מודעות, צריך לקרוא ל-method selectAds():

  1. מאתחלים אובייקט AdSelectionManager.
  2. יוצרים אובייקט AdSelectionConfig.
  3. קוראים לשיטה selectAds() האסינכרונית עם האובייקט AdSelectionConfig והאובייקטים הרלוונטיים Executor ו-OutcomeReceiver.

Kotlin

val adSelectionManager: AdSelectionManager =
  context.getSystemService(AdSelectionManager::class.java)

// Initialize AdSelectionConfig
val adSelectionConfig: AdSelectionConfig =
  AdSelectionConfig.Builder().setSeller(seller)
    .setDecisionLogicUrl(decisionLogicUrl)
    .setCustomAudienceBuyers(customAudienceBuyers)
    .setAdSelectionSignals(adSelectionSignals)
    .setSellerSignals(sellerSignals)
    .setPerBuyerSignals(perBuyerSignals)
    .setBuyerContextualAds(
      Collections.singletonMap(
        contextualAds.getBuyer(), contextualAds
      )
    ).build()

// Run ad selection with AdSelectionConfig
adSelectionManager.selectAds(
  adSelectionConfig, executor, outcomeReceiver
)

Java

AdSelectionManager adSelectionManager =
    context.getSystemService(AdSelectionManager.class);

// Initialize AdSelectionConfig
AdSelectionConfig adSelectionConfig =
  new AdSelectionConfig.Builder()
    .setSeller(seller)
    .setDecisionLogicUrl(decisionLogicUrl)
    .setCustomAudienceBuyers(customAudienceBuyers)
    .setAdSelectionSignals(adSelectionSignals)
    .setSellerSignals(sellerSignals)
    .setPerBuyerSignals(perBuyerSignals)
    .setBuyerContextualAds(
      Collections.singletonMap(contextualAds.getBuyer(), contextualAds)
    )
    .build();

// Run ad selection with AdSelectionConfig
adSelectionManager.selectAds(adSelectionConfig, executor, outcomeReceiver);

השיטה selectAds() דורשת קלט AdSelectionConfig, שבו צריך לציין את הפרמטרים הנדרשים הבאים:

  • בית עסק: מזהה של רשת המודעות של בית העסק שמפעילה את בחירת המודעות.
  • כתובת URL לוגית לקבלת החלטה: כתובת URL מסוג HTTPS שבוצעה בקשה לקבלת לוגיקת JavaScript של רשת המודעות של בית העסק.
    • כתובת URL מסוג HTTPS: התקבלה שאילתה לגבי לוגיקת JavaScript של רשת המודעות של בית העסק. עיינו בחתימות של הפונקציות הנדרשות.
    • URI מובנה מראש: תואם לפורמט בחירת המודעה של FLEDGE. מתבצעת התרעה של IllegalArgumentException אם מועבר URI שנוצר מראש ולא נתמך או פגום.
  • קונים של קהלים בהתאמה אישית: רשימה מלאה של מזהים של רשתות מודעות של קונים שמותרים על ידי בית העסק להשתתף בתהליך בחירת המודעות. מזהי הקונים האלה תואמים ל-CustomAudience.getBuyer() מהקהלים בהתאמה אישית שמשתתפים.

כדי לבחור מודעות בהתאמה אישית ברמה גבוהה יותר, ניתן לציין את הפרמטרים הבאים:

  • אותות לבחירת מודעות: אובייקט JSON שעבר סריאליזציה למחרוזת, ומכיל אותות לשימוש ב-JavaScript של לוגיקת הבידינג של הקונה, שאוחזר מ-CustomAudience.getBiddingLogicUrl().
  • אותות של בית העסק: אובייקט JSON שעבר סריאליזציה למחרוזת, ומכיל אותות שלוגיקת ההחלטה של בית העסק שאוחזרה ב-JavaScript מ-AdSelectionConfig.getDecisionLogicUrl().
  • לפי אותות של קונים: מפה של אובייקטים בפורמט JSON, מסודרת כמחרוזות, שמכילים אותות לשימוש ב-JavaScript של קונים ספציפיים לצורך בידינג, שנשלף מ-CustomAudience.getBiddingLogicUrl(). נתונים אלה מזוהים על ידי שדות הקונים של קהלים בהתאמה אישית המשתתפים.
  • מודעות לפי הקשר: אוסף של מודעות אפשריות, שנאספו ישירות מקונים במהלך מכרז שמתרחש מחוץ למכרז של Protected Audience.

אחרי שבוחרים מודעה, התוצאות, הצעות המחיר והאותות נשמרים באופן פנימי לצורך דיווח. הקריאה החוזרת (callback) OutcomeReceiver.onResult() מחזירה AdSelectionOutcome שמכיל:

  • כתובת URL לעיבוד של המודעה הזוכה, שהתקבלה מ-AdData.getRenderUrl().
  • מזהה בחירת מודעה שהוא ייחודי למשתמש במכשיר. המזהה הזה משמש לדיווח על החשיפה של המודעה.

אם בחירת המודעות לא הושלמה בגלל סיבות כמו ארגומנטים לא חוקיים, זמנים קצובים לתפוגה או צריכת משאבים מוגזמת, הקריאה החוזרת (callback) של OutcomeReceiver.onError() מספקת את הערך AdServicesException באופן הבא:

  • במקרה שבחירת המודעות מתחילה בארגומנטים לא חוקיים, השדה AdServicesException מציין שהסיבה לכך היא IllegalArgumentException.
  • כל שאר השגיאות מקבלות AdServicesException עם IllegalStateException כגורם.

מודעות לפי הקשר

Protected Audience API יכול לשלב מודעות לפי הקשר במכרז מוגן. יש לבחור מודעות לפי הקשר בשרת הפרסום הדיגיטלי ולהחזיר אותן למכשיר מחוץ לממשקי Protected Audience API. לאחר מכן ניתן יהיה לכלול מודעות לפי הקשר במכרז באמצעות AdSelectionConfig, שבו הן יפעלו כמו במודעות למכשירים, כולל כשירות לסינון מודעות שלילי. בסיום המכרז של Protected Audience API, צריך להפעיל את reportImpression(). הפעולה הזו מפעילה reportWin() במודעה לפי הקשר הזוכה, באותו דפוס כמו דיווח על חשיפות, כדי לקבל את המודעה הזוכה במכשיר. לכל מודעה לפי הקשר נדרשים קונה, הצעת מחיר, קישור ללוגיקת דיווח, כתובת URL לעיבוד ומטא-נתונים של מודעה.

כדי לפרוס מודעות לפי הקשר באפליקציה, אפליקציית היעד צריכה ליצור אובייקט ContextualAds:

Kotlin

val contextualAds: ContextualAds =
  Builder().setBuyer(AdTechIdentifier.fromString(mBiddingLogicUri.getHost()))
    //Pass in your valid app install ads
    .setDecisionLogicUri(mContextualLogicUri)
    .setAdsWithBid(appInstallAd)
    .build()

Java

ContextualAds contextualAds = new ContextualAds.Builder()
  .setBuyer(AdTechIdentifier.fromString(mBiddingLogicUri.getHost()))
  .setDecisionLogicUri(mContextualLogicUri)
  //Pass in your valid app install ads
  .setAdsWithBid(appInstallAd)
  .build();

לאחר מכן, ניתן להעביר את האובייקט ContextualAds שנוצר כשיוצרים את AdSelectionConfig:

Kotlin

// Create a new ad
val noFilterAd: AdData = Builder()
  .setMetadata(JSONObject().toString())
  .setRenderUri(Uri.parse(baseUri + NO_FILTER_RENDER_SUFFIX))
  .build()
val noFilterAdWithBid = AdWithBid(noFilterAd, NO_FILTER_BID)
contextualAds.getAdsWithBid().add(noFilterAdWithBid)

Java

// Create a new ad
AdData noFilterAd = new AdData.Builder()
  .setMetadata(new JSONObject().toString())
  .setRenderUri(Uri.parse(baseUri + NO_FILTER_RENDER_SUFFIX))
  .build();
AdWithBid noFilterAdWithBid = new AdWithBid(noFilterAd, NO_FILTER_BID);
contextualAds.getAdsWithBid().add(noFilterAdWithBid);

סינון מודעות להתקנת אפליקציה

סינון מודעות להתקנת אפליקציות עוזר לסנן מודעות התקנה לפי אפליקציות שכבר מותקנות במכשיר.

השלב הראשון בתהליך הזה הוא להגדיר אילו מפרסמים יכולים לסנן לפי החבילה שמותקנת. זה צריך להתרחש באפליקציה שאליה רוצים לטרגט באמצעות מודעה.

Kotlin

//Create a request for setting the app install advertisers
val adtech = AdTechIdentifier.fromString("your.enrolled.uri")
val adtechSet = setOf(adtech)
val request = SetAppInstallAdvertisersRequest(adtechSet)

//Set the app install advertisers in the ad selection manager
mAdSelectionManager.setAppInstallAdvertisers(
  request,
  mExecutor,
  object : OutcomeReceiver<Any?, Exception?>() {
    fun onResult(@NonNull ignoredResult: Any?) {
      Log.v("[your tag]", "Updated app install advertisers")
    }

    fun onError(@NonNull error: Exception?) {
      Log.e("[your tag]", "Failed to update app install advertisers", error)
    }
  })

Java

//Create a request for setting the app install advertisers
AdTechIdentifier adtech = AdTechIdentifier.fromString("your.enrolled.uri");
Set<AdTechIdentifier> adtechSet = Collections.singleton(adtech);
SetAppInstallAdvertisersRequest request = new SetAppInstallAdvertisersRequest(adtechSet);

//Set the app install advertisers in the ad selection manager
mAdSelectionManager.setAppInstallAdvertisers(
  request,
  mExecutor,
  new OutcomeReceiver<Object, Exception>() {
    @Override
    public void onResult(@NonNull Object ignoredResult) {
      Log.v("[your tag]", "Updated app install advertisers");
    }

    @Override
    public void onError(@NonNull Exception error) {
      Log.e("[your tag]", "Failed to update app install advertisers", error);
    }
  });

לאחר הפעלת הקוד הקודם, המפרסמים שהעבירו יוכלו לסנן את האפליקציות המותקנות שציינתם במהלך יצירת הצעות המחיר. אם צריך למנוע ממפרסם גישה לסטטוס ההתקנה של האפליקציה הזו, מריצים שוב את הקוד הזה ללא פרטי המפרסם.

השלב הבא הוא להגדיר סינון מודעות באפליקציה של בעל האתר. הגורם שמציג את המודעה באפליקציה של בעל האתר (שסביר להניח שהוא SDK בצד ההיצע) צריך להפעיל את האובייקט AdFilters שלו עם מידע על המודעות שקשורות לאפליקציות שהוא רוצה לסנן:

Kotlin

// Instantiate AdFilters object with package names.
val filters: AdFilters = Builder().setAppInstallFilters(
    Builder().setPackageNames(setOf("example.target.app")).build()
  ).build()

Java

// Instantiate AdFilters object with package names.
AdFilters filters = new AdFilters.Builder()
.setAppInstallFilters(
  new AppInstallFilters.Builder()
  .setPackageNames(Collections.singleton("example.target.app"))
  .build())
.build();

בעלי אתרים בצד הביקוש יכולים גם להגדיר AdFilter למודעות שקיימות בקהלים בהתאמה אישית שלהם.

ניתן להעביר את AdFilters גם בזמן יצירת אובייקט AdData חדש:

Kotlin

// Instantiate an AdData object with the AdFilters created in the
// previous example.
val appInstallAd: AdData =
  Builder().setMetadata("{ ... }") // Valid JSON string
    .setRenderUri(Uri.parse("www.example-dsp1.com/.../campaign123.html"))
    .setAdFilters(filters).build()

Java

// Instantiate an AdData object with the AdFilters created in the
// previous example.
AdData appInstallAd = new AdData.Builder()
.setMetadata("{ ... }") // Valid JSON string
.setRenderUri(Uri.parse("www.example-dsp1.com/.../campaign123.html"))
    .setAdFilters(filters)
    .build();

סינון של מכסת תדירות

סינון מכסת התדירות מאפשר לטכנולוגיות של מודעות להגביל את מספר הפעמים שמודעה מוצגת. סינון באמצעות מכסת תדירות מפחית את חשיפת יתר של מודעות ומבצע אופטימיזציה של בחירת המודעות החלופית בקמפיין נתון.

למסנן מכסת תדירות יש שני רכיבים עיקריים: סוג אירוע המודעה והמפתח למונה מודעות. אלה הסוגים הזמינים של אירועי מודעות שבהם אפשר להשתמש:

  • זכייה (בקרוב): אירוע זכייה מציין שהמודעה זכתה במכרז. אירועי ניצחון מתעדכנים באופן אוטומטי על ידי Protected Audience API והמפתח לא יכול להפעיל אותו ישירות. נתוני הרווח גלויים רק למודעות בקהל מותאם אישית נתון.
  • חשיפה: בנפרד מ-reportImpression, מתקשר במכשיר (SSP או MMP) משתמש ב-updateAdCounterHistogram() כדי להפעיל אירועי חשיפות בנקודת הקוד שהוא בוחר. אירועי חשיפות גלויים לכל המודעות ששייכות ל-DSP נתון, והם אינם מוגבלים למודעות באותו קהל מותאם אישית.
  • View: מבצע הקריאה במכשיר (SSP או MMP) מפעיל את האירוע בנקודה בקוד שהוא בוחר באמצעות קריאה ל-updateAdCounterHistogram(). אירועי צפייה גלויים לכל המודעות ששייכות ל-DSP נתון, ולא רק למודעות באותו קהל בהתאמה אישית.
  • קליק: מבצע הקריאה במכשיר (SSP או MMP) מפעיל את האירוע בשלב כלשהו בקוד שהוא בוחר באמצעות קריאה ל-updateAdCounterHistogram(). אירועי קליקים גלויים לכל המודעות ששייכות ל-DSP נתון, ולא רק למודעות באותו קהל בהתאמה אישית.

באפליקציה של בעל התוכן הדיגיטלי, SSP או MMP שיש להם נוכחות במכשיר מפעילים אירועי מודעות. כאשר מתבצעת קריאה לפונקציה updateAdCounterHistogram(), המונה של מסנן מכסת התדירות מצטבר, כך שבמכרזים עתידיים יהיה מידע עדכני על חשיפת המשתמש למודעה נתונה. הסוגים של אירועי המודעה לא קשורים באופן מאולץ לפעולה המתאימה של המשתמש, ומפורטים הנחיות שנועדו לעזור למתקשרים לבנות את מערכת האירועים שלהם. כדי להגדיל את מספר המודעות בזמן אירוע, הגורם במכשיר מספק את מזהה בחירת המודעות שזכה במכרז.

מפתחות מונה של מודעות הם מספרים שלמים שרירותיים וחתומים של 32 ביט שמוקצים על ידי טכנולוגיית הפרסום של הקונה, והם תואמים לקבוצת מודעות נתונה כפי שהוגדרה על ידי ה-DSP. מפתחות המונה של המודעות מוגבלים רק למודעות ששייכות ל-DSP נתון, ולכן אפשר לבחור את המפתחות האלה ללא חפיפה עם היסטוגרמות מטכנולוגיית מודעות אחרת. מפתחות מונה של מודעות משמשים להגדלה של מזהים ספציפיים ל-DSP במודעות של מערכת DSP או בקרב קהל מותאם אישית נתון, כדי לסנן מודעות ממכרזים עתידיים.

אפשר להשתמש במפתחות נגדיים כדי לתעדף מודעות שיש סיכוי גבוה יותר שיעניינו משתמש מסוים, על סמך האינטראקציות שלהם עם מודעות אחרות מטכנולוגיית מודעות נתונה של קונה. לדוגמה, מודעה שקיבלה רמת מעורבות גבוהה מזכה במכרזים של מודעות, בצפיות ובקליקים, מייצגת נתון משוער. כדי להמחיש את הנקודה הזו: מודעה המפרסמת מקלות גולף ליד שמאל עשויה להצביע על כך שהמשתמש לא יתעניין בפריטים ליד ימין. הגדרת מסנן מכסת תדירות למפתח מונה שהוקצה למודעות בצד שמאל עלולה לסנן מודעות עבור מועדונים ליד ימין.

על מנת להשתמש במכסת תדירות במכרז, ראשית עליך ליצור KeyedFrequencyCap אובייקטים, כפי שמוצג בהמשך:

Kotlin

// Value used when incrementing frequency counter
val adCounterKey = 123

// Frequency cap exceeded after 2 counts
val keyedFrequencyCapForImpression: KeyedFrequencyCap = Builder(
  adCounterKey, 2, Duration.ofSeconds(10)
).build()

// Frequency cap exceeded after 1 counts
val keyedFrequencyCapForImpression: KeyedFrequencyCap = Builder(
  adCounterKey, 1, Duration.ofSeconds(10)
).build()

Java

// Value used when incrementing frequency counter
int adCounterKey = 123;

// Frequency cap exceeded after 2 counts
KeyedFrequencyCap keyedFrequencyCapForImpression =
  new KeyedFrequencyCap.Builder(
    adCounterKey, 2, Duration.ofSeconds(10)
  ).build();

// Frequency Cap exceeded after 1 counts
KeyedFrequencyCap keyedFrequencyCapForClick =
  new KeyedFrequencyCap.Builder(
    adCounterKey, 1, Duration.ofSeconds(10)
  ).build();

אחרי שיוצרים את האובייקטים של KeyedFrequencyCap, אפשר להעביר אותם לאובייקט AdFilters.

Kotlin

val filters: AdFilters = Builder()
  .setFrequencyCapFilters(
    Builder()
      .setKeyedFrequencyCapsForImpressionEvents(
        ImmutableObject.of(keyedFrequencyCapForImpression)
      )
      .setKeyedFrequencyCapsForClickEvents(
        ImmutableObject.of(keyedFrequencyCapForClick)
      )
  ).build()

Java

AdFilters filters = new AdFilters.Builder()
    .setFrequencyCapFilters(new FrequencyCapFilters.Builder()
        .setKeyedFrequencyCapsForImpressionEvents(
            ImmutableObject.of(keyedFrequencyCapForImpression)
        )
        .setKeyedFrequencyCapsForClickEvents(
            ImmutableObject.of(keyedFrequencyCapForClick)
        )
    ).build();

כשהאובייקט AdFilters מאוכלס במסננים של מכסת תדירות, אפשר להעביר אותו בזמן היצירה של הקהל בהתאמה אישית:

Kotlin

// Initialize a custom audience.
val audience: CustomAudience = Builder()
  .setBuyer(buyer)
  .setName(name)
  .setAds(
    listOf(
      Builder()
        .setRenderUri(renderUri)
        .setMetadata(JSONObject().toString())
        .setAdFilters(filters)
        .setAdCounterKeys(adCounterKeys)
        .build()
    )
  ).build()

Java

// Initialize a custom audience.
CustomAudience audience = new CustomAudience.Builder()
    .setBuyer(buyer)
    .setName(name)
    .setAds(Collections.singletonList(new AdData.Builder()
        .setRenderUri(renderUri)
        .setMetadata(new JSONObject().toString())
        .setAdFilters(filters)
        .setAdCounterKeys(adCounterKeys)
        .build()))
    .build();

כשמסננים את מכסת התדירות בקהל בהתאמה אישית, ה-SSP יכול להפעיל את האירועים הנדרשים של קליק, צפייה או חשיפה.

Kotlin

val callerAdTech: AdTechIdentifier = mAdSelectionConfig.getSeller()

val request: UpdateAdCounterHistogramRequest = Builder(
  adSelectionId,
  FrequencyCapFilters.AD_EVENT_TYPE_CLICK,  //CLICK, VIEW, or IMPRESSION
  callerAdTech
).build()

Java

AdTechIdentifier callerAdTech = mAdSelectionConfig.getSeller();

UpdateAdCounterHistogramRequest request =
  new UpdateAdCounterHistogramRequest.Builder(
      adSelectionId,
      FrequencyCapFilters.AD_EVENT_TYPE_CLICK, //CLICK, VIEW, or IMPRESSION
      callerAdTech
).build();

מודעות שלא עומדות במגבלות הסינון של מכסת התדירות שהוגדרו מראש מסוננות מחוץ למכרז. הסינון מתרחש לפני ההפעלה של לוגיקת הבידינג במכרזים במכשיר, ומכיוון שהמטען הייעודי (payload) יוצר עבור מכרזים של שירותי בידינג ושירותי מכרזים.בעזרת ערכת הכלים הזו, טכנולוגיות המודעות גמישות להשתמש באינטראקציות בין המשתמשים לבין המודעות בקהלים המותאמים אישית שלהם, במטרה למקד את מיקוד המודעות תוך מזעור חשיפת יתר של מודעות.

סינון מודעות לפי הקשר ללא קריאות רשת

אם אין ביקוש לרימרקטינג במכשיר, אפשר להציג מודעות לפי הקשר ללא שיחות רשת. באמצעות מזהי URI מוכנים מראש ורשימה של מודעות לפי הקשר עם הצעות מחיר, הפלטפורמה יכולה לדלג על אחזור הלוגיקה של הבידינג, האותות של הבידינג ואותות הציון. הפלטפורמה משתמשת ב-URI מובנה מראש כדי לבחור את המודעה לפי הקשר עם הצעת המחיר הגבוהה ביותר.

כדי לשפר את זמן האחזור, טכנולוגיות פרסום יכולות להפעיל תהליך בחירת מודעות שכולל רק מודעות לפי הקשר עם פונקציונליות של סינון מודעות, ללא קריאות רשת. אפשר לעשות זאת באמצעות מזהי URI מוכנים מראש לציון אותות. ראו את הקטע תרחישים לדוגמה ושמות של URI נתמכים, כדי לראות רשימה של scoreAds הטמעות.

כדי להפעיל את בחירת המודעות ללא קריאות רשת:

  1. הגדרה של סינון מודעות
  2. יצירת מודעות לפי הקשר
  3. יוצרים אובייקט AdSelectionConfig עם ההגדרות הבאות:

    1. רשימה ריקה של קונים
    2. URI מובנה מראש לבחירת הצעת המחיר הגבוהה ביותר
    3. מודעות לפי הקשר
    4. URI ריק לאותות הציון. ה-URI הריק יכול לציין שאתם לא רוצים להשתמש באחזור אותות מהימנים לצורך חישוב:
    Uri prebuiltURIScoringUri = Uri.parse("ad-selection-prebuilt://ad-selection/highest-bid-wins/?reportingUrl=your.registered.uri/reporting");
    // Initialize AdSelectionConfig
    AdSelectionConfig adSelectionConfig =
      new AdSelectionConfig.Builder()
        .setSeller(seller)
        .setDecisionLogicUri(prebuiltURIScoringUri)
        .setCustomAudienceBuyers(Collections.emptyList())
        .setAdSelectionSignals(adSelectionSignals)
        .setSellerSignals(sellerSignals)
        .setPerBuyerSignals(perBuyerSignals)
        .setBuyerContextualAds(buyerContextualAds)
        .setTrustedScoringSignalsUri(Uri.EMPTY)
        .build();
    
  4. הפעלה של בחירת מודעות:

    adSelectionManager.selectAds(
        adSelectionConfig,
        executor,
        outcomeReceiver);
    

הפעלת JavaScript לצורכי דיווח משלך תוך שימוש במזהי URI מובנים מראש

כיום, בפלטפורמת ארגז החול לפרטיות יש רק הטמעת JavaScript בסיסית של דיווח, שזמינה למזהי URI שנוצרו מראש. אם אתם רוצים להריץ JavaScript משלכם לדיווח ועדיין להשתמש במזהי URI שנוצרו מראש כדי לבחור מודעות עם זמן אחזור קצר, תוכלו לשנות את DecisionLogicUri בין בחירת המודעות לבין הפעלות הדיווח.

  1. מבצעים את השלבים להפעלת בחירת המודעות לפי הקשר באמצעות מזהי URI מוכנים מראש
  2. יש ליצור עותק של AdSelectionConfig לפני הפעלת הדיווח

    adSelectionConfigWithYourReportingJS = adSelectionConfig.cloneToBuilder()
      // Replace <urlToFetchYourReportingJS> with your own URL:
      .setDecisionLogicUri(Uri.parse(<urlToFetchYourReportingJS>))
      .build();
    
  3. הפעלת דיווח על חשיפות

    // adSelectionId is from the result of the previous selectAds run
    ReportImpressionRequest request = new ReportImpressionRequest(
      adSelectionId,
      adSelectionConfigWithYourReportingJS);
    adSelectionManager.reportImpression(
      request,
      executor,
      outcomeReceiver);
    

הפעלת תהליך בחירת הרשת (Mediation) ב-Waterfall

כדי להשתמש בתהליך בחירת הרשת ב-Waterfall, נדרש תיאום של מספר ערכות SDK (רשתות צד שלישי) שרשת גישור של SDK מצד ראשון. תהליך בחירת הרשת ב-Waterfall מתבצע באותו אופן, לא משנה אם המכרז התקיים במכשיר או פעל בשירותי בידינג ומכרזים (B&A).

רשתות של צד שלישי

רשתות צד שלישי צריכות לספק מתאם שמאפשר לרשת הגישור להפעיל את השיטות הנדרשות להפעלת מכרז:

  • הפעלה של בחירת המודעות
  • דיווח על חשיפות

דוגמה למתאם רשת של גישור:

Kotlin

class NetworkAdaptor {
    private val adSelectionManager : AdSelectionManager

    init {
        adSelectionManager = context.getSystemService(AdSelectionManager::class.java)
    }

    fun selectAds() {...}

    fun reportImpressions() {...}
}

Java

class NetworkAdaptor {
    AdSelectionManager adSelectionManager;

    public NetworkAdaptor() {
        AdSelectionManager adSelectionManager =
            context.getSystemService(AdSelectionManager.class);
    }

    public void selectAds() {...}

    public void reportImpressions() {...}
}

לכל SDK יש מנהלי שירות ולקוחות משלו לבחירת מודעות, והטמעה נפרדת של selectAds ו-reportImpressions. ספקי SDK יכולים לעיין בקטעים שבהם מוסבר איך להפעיל בחירת מודעות במכרזים במכשיר או בהסבר ל-B&A במכרזים של B&A. כאן מוסבר איך לדווח על חשיפות של מודעות (לפי דיווח יחיד על חשיפות SSP).

רשת לבחירת רשת (Mediation)

בדומה לרשתות של צד שלישי, גם רשתות בתהליך בחירת הרשת צריכות הטמעות של selectAds ושל reportImpression. למידע נוסף, קראו את הסעיפים שבהם מוסבר איך מפעילים את בחירת המודעות ואיך מדווחים על חשיפות של מודעות.

רשתות בתהליך בחירת הרשת אחראיות להפעלה של שרשרת תהליך בחירת הרשת ולמיקום שלהן בשרשרת של תהליך בחירת הרשת. בחלק הבא נסביר איך להגדיר ולבצע את התהליך הזה.

אחזור של שרשרת תהליך בחירת הרשת וערכי סף תחתון להצעות מחיר

רשת הגישור אחראית לאחזור המודעות לפי הקשר של הצד הראשון (צד ראשון), שרשרת לבחירת רשת וערכי סף תחתון להצעות מחיר של רשתות צד שלישי (3P). מצב כזה יכול לקרות בתגובה לבקשה לאחזור מודעות לפי הקשר שמופעלות על ידי רשת הגישור. שרשרת לבחירת הרשת קובעת איך לבצע איטרציה דרך רשתות הצד השלישי, וניתן להעביר את ערכי הסף התחתון של הצעות המחיר לתהליך המכרז בתור adSelectionSignals.

מיקום של רשת בשרשרת לבחירת הרשת

ה-SDK של תהליך בחירת הרשת יכול למקם את עצמו בשרשרת של תהליך בחירת הרשת על סמך העלות בפועל לאלף חשיפות בזמן אמת של הצעות מחיר למודעות מאינטראקציה ישירה. ב-Protected Audience API, הצעות מחיר למודעות הן אטומות. ב-SDK של תהליך בחירת הרשת (Mediation) צריך להשתמש ב-AdSelectionFromOutcomesConfig כדי שתהיה אפשרות להשוות בין הצעת המחיר של מודעה מסוימת מאינטראקציה ישירה לבין הסף המינימלי להצעות המחיר של רשת הצד השלישי הבאה בשרשרת. אם הצעת המחיר מהאינטראקציה הישירה גבוהה מהסף המינימלי להצעת מחיר, פירוש הדבר הוא שה-SDK של תהליך בחירת הרשת ימוקם מול אותה רשת של צד שלישי.

הפעלה של בחירת המודעות

כדי לאחזר מועמד למודעה מאינטראקציה ישירה, רשת הגישור יכולה להפעיל מכרז במכשיר לפי השלבים בקטע הפעלת בחירת מודעות. הפעולה הזו יוצרת מועמד למודעה מאינטראקציה ישירה, הצעת מחיר ו-AdSelectionId שישמשו בתהליך הגישור.

יצירת AdSelectionFromResultssConfig

AdSelectionFromOutcomesConfig מאפשר לרשת תהליך בחירת הרשת להעביר רשימה של AdSelectionIds (תוצאות ממכרזים קודמים), אותות של בחירת מודעות ו-URI כדי לאחזר JavaScript שבוחר מודעה מכמה מועמדויות. הרשימה של מזהי AdSelectionId, יחד עם הצעות המחיר שלהם, והאותות, מועברים ל-JavaScript, שיכול להחזיר אחד מהAdSelectionIds אם הוא גבוה מהסף המינימלי להצעות מחיר, או אף אחד מהם אם שרשרת תהליך בחירת הרשת צריכה להמשיך.

רשתות בתהליך בחירת הרשת יוצרות AdSelectionFromOutcomesConfig על סמך הצד השלישי AdSelectionId מהקטע הקודם, והסף המינימלי להצעות מחיר לרשת של צד שלישי. צריך ליצור AdSelectionFromOutcomesConfig חדש לכל שלב בשרשרת לבחירת הרשת.

Kotlin

fun  runSelectOutcome(
    adSelectionClient : AdSelectionClient,
    outcome1p : AdSelectionOutcome,
    network3p : NetworkAdapter) : ListenableFuture<AdSelectionOutcome?> {
    val config = AdSelectionFromOutcomesConfig.Builder()
        .setSeller(seller)
        .setAdSelectionIds(listOf(outcome1p))
        .setSelectionSignals({"bid_floor": bid_floor})
        .setSelectionLogicUri(selectionLogicUri)
        .build()
    return adSelectionClient.selectAds(config)
}

Java

public ListenableFuture<AdSelectionOutcome> runSelectOutcome(AdSelectionOutcome outcome1p,
                                              NetworkAdapter network3p) {
    AdSelectionFromOutcomesConfig config = new AdSelectionFromOutcomesConfig.Builder()
            .setSeller(seller)
            .setAdSelectionIds(Collection.singletonList(outcome1p))
            .setSelectionSignals({"bid_floor": bid_floor})
            .setSelectionLogicUri(selectionLogicUri)
            .build();

    return adSelectionClient.selectAds(config){}
}

כדי לשנות את השיטה selectAds() לתהליך בחירת הרשת ב-Waterfall, צריך להזין קלט AdSelectionFromOutcomesConfig, שבו צריך לציין את הפרמטרים הנדרשים הבאים:

  • בית עסק: מזהה של רשת המודעות של בית העסק שמפעילה את בחירת המודעות.
  • AdSelectionIds: רשימת סינגלטון של הפעלה קודמת של selectAds() במודעה מאינטראקציה ישירה.
  • אותות לבחירת מודעות: אובייקט JSON שעבר סריאליזציה למחרוזת, ומכיל אותות לשימוש בלוגיקת הבידינג של הקונים. במקרה כזה, עליכם לכלול את הסף המינימלי להצעת המחיר שאוחזר עבור הרשת הנתונה של צד שלישי.
  • URI של Selection Logic: כתובת URL מסוג HTTPS שנשלחת אלינו במהלך בחירת המודעה, כדי לאחזר את ה-JavaScript של הרשת לבחירת רשת לצורך בחירת המודעה הזוכה. ראו את חתימות הפונקציות הנדרשות ב-JavaScript. קוד ה-JavaScript צריך להחזיר את המודעה מצד שלישי אם הצעת המחיר גבוהה מהסף התחתון להצעת המחיר, או להחזיר null בדרך אחרת. כך, ה-SDK של תהליך בחירת הרשת יכול לחתוך את שרשרת תהליך בחירת הרשת כשנמצא מנצח.

אחרי שיוצרים את ה-AdSelectionOutcomesConfig, מפעילים את השיטה selectAds() של רשת הצד השלישי הראשונה בשרשרת.

Kotlin

val adSelectionManager = context.getSystemService(AdSelectionManager::class.java)

// Initialize AdSelectionFromOutcomesConfig
AdSelectionFromOutcomesConfig adSelectionFromOutcomesConfig =
  AdSelectionFromOutcomesConfig.Builder()
    .setSeller(seller)
    .setAdSelectionIds(listof(outcome1p))
    .setSelectionSignals({"bid_floor": bid_floor})
    .setSelectionLogicUri(selectionLogicUri)
    .setAdSelectionIds(outcomeIds)
    .build()

// Run ad selection with AdSelectionConfig
adSelectionManager.selectAds(
    adSelectionFromOutcomesConfig,
    executor,
    outcomeReceiver)

Java

AdSelectionManager adSelectionManager =
    context.getSystemService(AdSelectionManager.class);

// Initialize AdSelectionFromOutcomesConfig
AdSelectionFromOutcomesConfig adSelectionFromOutcomesConfig =
        new AdSelectionFromOutcomesConfig.Builder()
            .setSeller(seller)
            .setAdSelectionIds(Collection.singletonList(outcome1p))
            .setSelectionSignals({"bid_floor": bid_floor})
            .setSelectionLogicUri(selectionLogicUri)
            .setAdSelectionIds(outcomeIds)
            .build();

// Run ad selection with AdSelectionConfig
adSelectionManager.selectAds(
    adSelectionFromOutcomesConfig,
    executor,
    outcomeReceiver);

תזמור של תהליך בחירת הרשת (Mediation) ב-Waterfall

בהמשך מוצג סדר הפעולות לתהליך הגישור.

  1. הפעלת בחירת מודעות מאינטראקציה ישירה.
  2. חוזרים על השלבים בשרשרת של תהליך בחירת הרשת. לכל רשת של צד שלישי, מבצעים את הפעולות הבאות:
    1. יצירת AdSelectionFromOutcomeConfig, כולל outcomeId מהאינטראקציה הישירה וסף התחתון להצעות מחיר של ה-SDK של הצד השלישי.
    2. צריך להפעיל את selectAds() עם ההגדרות הקודמות מהשלב הקודם.
    3. אם התוצאה לא ריקה, מחזירים את המודעה.
    4. צריך להפעיל את השיטה selectAds() של מתאם רשת ה-SDK הנוכחי. אם התוצאה לא ריקה, החזירו את המודעה.
  3. אם לא נמצא מנצח ברשת, מחזירים את המודעה מאינטראקציה ישירה.

Kotlin

fun runWaterfallMediation(mediationChain : List<NetworkAdapter>)
  : Pair<AdSelectionOutcome, NetworkAdapter> {
    val outcome1p = runAdSelection()

    var outcome : AdSelectionOutcome
    for(network3p in mediationChain) {
      outcome = runSelectOutcome(outcome1p, network3p)
      if (outcome1p.hasOutcome() && outcome.hasOutcome()) {
          return Pair(outcome, this)
      }

      outcome = network3p.runAdSelection()
      if(outcome.hasOutcome()) {
          return Pair(outcome, network3p)
      }
    }
  return Pair(outcome1p, this)
}

Java

class MediationNetwork {
    AdSelectionManager adSelectionManager;

    public MediationNetwork() {
        AdSelectionManager adSelectionManager =
            context.getSystemService(AdSelectionManager.class);
    }

    public void runAdSelection() {...}

    public void reportImpressions() {...}

    public Pair<AdSelectionOutcome, NetworkAdapter> runWaterfallMediation(
            List<NetworkAdapter> mediationChain) {
        AdSelectionOutcome outcome1p = runAdSelection();

        AdSelectionOutcome outcome;
        for(NetworkAdapter network3p: mediationChain) {
            if (outcome1p.hasOutcome() &&
              (outcome = runSelectOutcome(outcome1p, network3p)).hasOutcome()) {
                return new Pair<>(outcome, this);
            }

            if((outcome = network3p.runAdSelection()).hasOutcome()) {
                return new Pair<>(outcome, network3p);
            }
        }
        return new Pair<>(outcome1p, this);
    }

    /* Runs comparison by creating an AdSelectionFromOutcomesConfig */
    public AdSelectionOutcome runSelectOutcome(AdSelectionOutcome outcome1p,
                                              NetworkAdapter network3p) { ... }
}

דיווח על חשיפות של מודעות

יש שני שלבים לדיווח על חשיפה של מודעה, בהתאם לאופן שבו המכרז פועל. אם יש לכם פלטפורמת SSP יחידה שמפעילה מכרז, צריך לפעול לפי הקטע הבא. אם אתם מתכוונים להטמיע את תהליך בחירת הרשת ב-Waterfall, בצעו את השלבים שמפורטים בקטע בנושא דיווח על חשיפות של תהליך בחירת הרשת ב-Waterfall.

דיווח יחיד על חשיפות SSP

אחרי שבוחרים מודעה מנצחת בתהליך בחירת המודעות, אפשר לדווח על החשיפה לפלטפורמות בצד הקונה ובצד המוכר, באמצעות השיטה AdSelectionManager.reportImpression(). כדי לדווח על חשיפה של מודעה:

  1. מאתחלים אובייקט AdSelectionManager.
  2. יוצרים אובייקט ReportImpressionRequest עם המזהה של בחירת המודעה.
  3. קוראים לשיטה reportImpression() האסינכרונית עם האובייקט ReportImpressionRequest והאובייקטים הרלוונטיים Executor ו-OutcomeReceiver.

Java

AdSelectionManager adSelectionManager =
    context.getSystemService(AdSelectionManager.class);

// Initialize a ReportImpressionRequest
ReportImpressionRequest reportImpressionRequest =
        new ReportImpressionRequest.Builder()
                .setAdSelectionId(adSelectionId)
                .setAdSelectionConfig(adSelectionConfig)
                .build();

// Request to report the impression with the ReportImpressionRequest
adSelectionManager.reportImpression(
    reportImpressionRequest,
    executor,
    outcomeReceiver);

Kotlin

val adSelectionManager = context.getSystemService(AdSelectionManager::class.java)

// Initialize a ReportImpressionRequest
val adSelectionConfig: ReportImpressionRequest =
    ReportImpressionRequest.Builder()
        .setAdSelectionId(adSelectionId)
        .setAdSelectionConfig(adSelectionConfig)
        .build()

// Request to report the impression with the ReportImpressionRequest
adSelectionManager.reportImpression(
    reportImpressionRequest,
    executor,
    outcomeReceiver)

מאתחלים את ReportImpressionRequest באמצעות הפרמטרים הנדרשים הבאים:

  • מזהה בחירת מודעות: מזהה ייחודי למשתמש במכשיר שמזהה בחירת מודעות מוצלחת.
  • הגדרת בחירת המודעות: אותה הגדרה ששימשה בקריאה ל-selectAds() שצוינה במזהה בחירת המודעות שסופק.

השיטה האסינכרונית reportImpression() משתמשת באובייקט OutcomeReceiver כדי לסמן את התוצאה של הקריאה ל-API.

  • הקריאה החוזרת (callback) onResult() מציינת אם כתובות ה-URL לדיווח על חשיפות נוצרו והבקשה תוזמנה.
  • הקריאה החוזרת (callback) onError() מציינת את התנאים האפשריים הבאים:
    • במקרה שהקריאה מתחילה בארגומנט קלט לא חוקי, הערך AdServicesException מציין שהסיבה היא IllegalArgumentException.
    • כל שאר השגיאות מקבלות AdServicesException עם IllegalStateException כגורם.

דיווח על חשיפות בתהליך בחירת הרשת ב-Waterfall

SDK של תהליך בחירת הרשת צריך לעקוב אחר ה-SDK הזוכה כדי להפעיל את תהליכי הדיווח. ערכות ה-SDK שמשתתפות בשרשרת לבחירת הרשת צריכות לספק שיטה להפעלת תהליך הדיווח של המגשר. ערכת SDK שמשתתפת במכרז של תהליך בחירת הרשת (Mediation) יכולה לפעול לפי השלבים המפורטים למעלה כדי להטמיע את הדיווח שלה.

פלטפורמות SSP יכולות להשתמש בדוגמה הזו לקוד SDK של צד שלישי כאב-טיפוס כדי להצטרף לתהליכי הגישור:

Pair<AdSelectionOutcome, NetworkAdapter> winnerOutcomeAndNetwork =
         mediationSdk.orchestrateMediation(mediationChain);

if (winner.first.hasOutcome()) {
      winner.second.reportImpressions(winner.first.getAdSelectionId());

נקודות קצה לדיווח על חשיפות

ה-API של החשיפות של הדוח מנפיק בקשות HTTPS GET לנקודות קצה (endpoints) שסופקו על ידי הפלטפורמה בצד המוכר והפלטפורמה הזוכה בצד הקונה:

נקודת הקצה של פלטפורמה בצד הקונה:

  • ה-API משתמש בכתובת ה-URL הלוגית של הבידינג שצוינה בקהל בהתאמה אישית כדי לאחזר את ה-JavaScript שסופק על ידי הקונה, שכולל לוגיקה להחזרת כתובת URL לדיווח על חשיפות.
  • צריך להפעיל את הפונקציה reportWin() של JavaScript, שצפויה להחזיר את כתובת ה-URL לדיווח על חשיפות של הקונה.

נקודת הקצה של הפלטפורמה בצד המוכר:

  • משתמשים בכתובת ה-URL הלוגית לקבלת החלטה שצוינה באובייקט AdSelectionConfig כדי לאחזר את קוד ה-JavaScript של לוגיקת ההחלטה של בית העסק.
  • מפעילים את פונקציית ה-JavaScript reportResult(), שצפויה להחזיר את כתובת ה-URL לדיווח על חשיפות של הקונה.

דוחות של שירותי בידינג ומכרזים

כל נתוני הדיווח הנדרשים, כולל כתובות URL שנוצרו לצורך דיווח על אינטראקציות עם מודעות, ייכללו בתגובה המוצפנת מהמכרז בצד השרת במכרז שמופעלת בשירותי בידינג ומכרזים. כשהתשובה מפוענחת, כתובות ה-URL המתאימות רשומות בפלטפורמה, כך שהדיווח על מודעות ועל חשיפות מתבצע בהתאם לשלבים שצוינו למעלה.

דיווח על חשיפות לפי המאמץ הטוב ביותר

השיטה reportImpression() נועדה להשיג את השלמת הדיווח הטובה ביותר.

דיווח על אינטראקציות עם מודעות

Protected Audience API תומך בדיווח על אינטראקציות מפורטות יותר של מודעה שעברה רינדור. הנתונים האלה יכולים לכלול אינטראקציות כמו זמן צפייה, קליקים, העברת עכבר או כל מדד שימושי אחר שאפשר לאסוף. התהליך לקבלת הדוחות האלה כולל שני שלבים. ראשית, קונים ומפיצים חייבים להירשם כדי לקבל את הדוחות האלה ב-JavaScript לדיווח. לאחר מכן הלקוח יצטרך לדווח על האירועים האלה.

הרשמה לקבלת אירועי אינטראקציה

ההרשמה לאירועי אינטראקציה מתבצעת בפונקציות ה-JavaScript של הקונה reportWin() ושל reportResult(), באמצעות פונקציית JavaScript שסופקה על ידי הפלטפורמה: registerAdBeacon. על מנת להירשם לקבלת דוח אירוע, פשוט קרא לפונקציית JavaScript בפלטפורמה מהדיווח שלך על JavaScript. קטע הקוד הבא משתמש ב-reportWin() של קונה, אבל אותה גישה חלה על reportResult().

reportWin(
  adSelectionSignals,
  perBuyerSignals,
  signalsForBuyer,
  contextualSignals,
  customAudienceSignals) {
    ...
    // Calculate reportingUri, clickUri, viewUri, and hoverUri
    registerAdBeacon("click", clickUri)
    registerAdBeacon("view", viewUri)
    registerAdBeacon("hover", hoverUri)

    return reportingUrl;
}

דיווח על אירועי אינטראקציה

אחרי שהלקוחות מדווחים על חשיפה, הם יכולים לדווח על האינטראקציות חזרה לפלטפורמות מנצחות בצד הקונה ובצד המוכר, באמצעות השיטה AdSelectionManager.reportInteraction(). כך מדווחים על אירוע של מודעה:

  1. מאתחלים אובייקט AdSelectionManager.
  2. יוצרים אובייקט ReportInteractionRequest עם המזהה של בחירת המודעה, מפתח האינטראקציה, נתוני האינטראקציה ויעד הדיווח.
  3. צריך לקרוא לשיטה reportInteraction() האסינכרונית עם האובייקט request ולאובייקטים הרלוונטיים Executor ו-OutcomeReceiver.
AdSelectionManager adSelectionManager =
    context.getSystemService(AdSelectionManager.class);

// Initialize a ReportInteractionRequest
ReportInteractionRequest request =
  new ReportInteractionRequest.Builder()
    .setAdSelectionId(adSelectionId)
    .setInteractionKey("view")
    .setInteractionData("{ viewTimeInSeconds : 1 }") // Can be any string
    .setReportingDestinations(
      FLAG_REPORTING_DESTINATION_BUYER | FLAG_REPORTING_DESTINATION_SELLER
    )
    .build();

// Request to report the impression with the ReportImpressionRequest
adSelectionManager.reportInteraction(
  reportImpressionRequest,
  executor,
  outcomeReceiver);

מאתחלים את ReportInteractionRequest באמצעות הפרמטרים הנדרשים הבאים:

  • מזהה בחירת מודעה: מזהה בחירת מודעה שאוחזר מ-AdSelectionOutcome שהוחזר בעבר.
  • מפתח אינטראקציה: מפתח מחרוזת שמוגדר על ידי הלקוח ומתאר את הפעולה שמדווחת. המפתח הזה צריך להתאים למפתח שנרשם על ידי המוכר או הקונה בפונקציות ה-JavaScript לדיווח.
  • נתוני אינטראקציה: מחרוזת שמכילה נתונים שייכללו בדוח האירועים ויישלחו בחזרה לשרתי הדיווח.
  • יעדי דיווח: מסכת ביטים שמציינת אם צריך לדווח על האירועים לקונה, למוכר או לשניהם. הדגלים האלה מסופקים על ידי הפלטפורמה, ואפשר ליצור את מסכת היעד הסופית באמצעות פעולות ברמת הסיביות. על מנת לדווח ליעד אחד אפשר להשתמש ישירות בדגל שסופק על ידי הפלטפורמה. כדי לדווח על מספר יעדים, אפשר להשתמש בשדה OR (|) ברמת הסיביות כדי לשלב את ערכי הדגלים.

השיטה האסינכרונית reportInteraction() משתמשת באובייקט OutcomeReceiver כדי לסמן את התוצאה של הקריאה ל-API.

  • הקריאה החוזרת (callback) onResult() מציינת שהקריאה לאינטראקציה בדוח חוקית.
  • הקריאה החוזרת (callback) onError() מציינת את התנאים האפשריים הבאים:
    • אם השיחה מתבצעת כשהאפליקציה פועלת ברקע, מוחזר IllegalStateException עם תיאור של הכשל.
    • אם הלקוח מווסת (throttle) מהתקשרות אל reportInteraction(), מוחזר LimitExceededException.
    • אם החבילה לא רשומה לקריאה לממשקי ה-API לשמירה על הפרטיות, מוחזר SecurityException().
    • אם האינטראקציות לדיווח על האפליקציה שונות מהאפליקציה ששמה selectAds(), מוחזר IllegalStateException.
  • אם המשתמש לא הסכים להפעיל את ממשקי ה-API של ארגז החול לפרטיות, הקריאה תיכשל באופן שקט.

נקודות קצה לדיווח על אינטראקציות

ה-API של האינטראקציה בדוחות שולח בקשות HTTPS POST לנקודות הקצה שסופקו על ידי הפלטפורמה בצד המוכר והפלטפורמה הזוכה בצד הקונה. Protected Audience API יתאים את מפתחות האינטראקציה למזהי ה-URI שהוצהרו בדיווח על JavaScript, וישלח בקשת POST לכל נקודת קצה לכל אינטראקציה שמדווחת. סוג התוכן של הבקשה הוא טקסט פשוט, שהגוף הוא נתוני האינטראקציה.

דיווח על אינטראקציה עם הביצועים הטובים ביותר

reportInteraction() נועד לספק את ההשלמה הטובה ביותר של הדיווח באמצעות HTTP POST.

עדכון יומי ברקע

כשיוצרים קהל מותאם אישית, האפליקציה או ה-SDK יכולים לאתחל מטא-נתונים של קהל בהתאמה אישית. בנוסף, הפלטפורמה יכולה לעדכן את החלקים הבאים במטא-נתונים מותאמים אישית של קהלים באמצעות תהליך עדכון יומי של הרקע.

  • אותות בבידינג של משתמשים
  • נתוני בידינג מהימנים
  • רשימה אחת (AdData)

התהליך הזה מבצע שאילתות על כתובת ה-URL לעדכון יומי שהוגדרה בקהל בהתאמה אישית, וכתובת ה-URL עשויה להחזיר תגובת JSON.

  • תגובת ה-JSON עשויה להכיל כל אחד משדות המטא-נתונים הנתמכים שצריך לעדכן.
  • כל שדה JSON מאומת בנפרד. הלקוח מתעלם משדות פגומים, ולכן לא מתבצעים עדכונים לשדה הספציפי הזה בתגובה.
  • תגובת HTTP ריקה או אובייקט JSON ריק '{}' לא יגרמו לעדכוני מטא-נתונים.
  • גודל הודעת התשובה צריך להיות מוגבל ל-10KB.
  • כל מזהי ה-URI נדרשים להשתמש ב-HTTPS.
  • trusted_bidding_uri חייב לשתף את אותו ETLD+1 כמו הקונה.

דוגמה: תגובת JSON לעדכון יומי ברקע

{
    "user_bidding_signals" : { ... },  // Valid JSON object
    "trusted_bidding_data" : {
        "trusted_bidding_uri" : 'example-dsp1-key-value-service.com',
        "trusted_bidding_keys" : [ 'campaign123', 'campaign456', ... ]
    },
    'ads' : [
        {
            "render_uri" : 'www.example-dsp1.com/.../campaign123.html',
            'metadata' : { ... }  // Valid JSON object
        },
        {
            "render_uri" : 'www.example-dsp1.com/.../campaign456.html',
            'metadata' : { ... }  // Valid JSON object
        },
        ...
    ]
}

JavaScript לבחירת מודעות

תהליך העבודה לבחירת מודעות מתזמר את ההפעלה של קוד JavaScript שסופק על ידי הקונה והמוכר.

קוד JavaScript שסופק על ידי הקונה מאוחזר מכתובת ה-URL הלוגית של הבידינג, שצוינה בקהל בהתאמה אישית. ה-JavaScript שמוחזר צריך לכלול את הפונקציות הבאות:

קוד JavaScript שסופק על ידי בית העסק מאוחזר מכתובת ה-URL בלוגיקת ההחלטה שצוינה בפרמטר AdSelectionConfig של ה-API לבחירת מודעות. קוד ה-JavaScript שמוחזר צריך לכלול את הפונקציות הבאות:

createBid()

function generateBid(
  ad,
  auction_signals,
  per_buyer_signals,
  trusted_bidding_signals,
  contextual_signals,
  user_signals,
  custom_audience_bidding_signals) {
  return {'status': 0, 'ad': ad, 'bid': ad.metadata.result };
}

פרמטרים של קלט:

  • ad: אובייקט JSON בפורמט var ad = { 'render_url': url, 'metadata': json_metadata };
  • auction_signals, per_buyer_signals: אובייקטים של JSON המצוינים באובייקט התצורה של המכרז
  • custom_audience_bidding_signals: אובייקט JSON שנוצר על ידי הפלטפורמה. הפורמט של אובייקט ה-JSON הזה הוא:

    var custom_audience_signals = {
      "owner":"ca_owner",
      "buyer":"ca_buyer",
      "name":"ca_name",
      "activation_time":"ca_activation_time_epoch_ms",
      "expiration_time":"ca_expiration_time_epoch_ms",
      "user_bidding_signals":"ca_user_bidding_signals"
    }
    

    איפה:

    • owner, buyer ו-name הן מחרוזת שנלקחה מנכסים עם אותו שם של הקהל בהתאמה אישית שמשתתף בבחירת המודעות
    • activation_time ו-expiration_time הם זמני ההפעלה ותאריכי התפוגה של הקהל בהתאמה אישית, מבוטאים בשניות מאז ראשית זמן יוניקס (Unix epoch)
    • ca_user_bidding_signals היא מחרוזת JSON שצוינה בשדה userBiddingSignals של CustomAudience בזמן היצירה
    • trusted_bidding_signals, contextual_signals ו-user_signals הם אובייקטים של JSON. הם מועברים כאובייקטים ריקים, והם ימולאו בגרסאות עתידיות. הפורמט של המודעות לא נאכף על ידי הפלטפורמה ומנוהל על ידי טכנולוגיות הפרסום.

תוצאה:

  • ad: המודעה שאליה מתייחסת הצעת המחיר. הסקריפט יכול להחזיר עותק של המודעה שהוא קיבל, עם מטא-נתונים שונים. מאפיין render_url של המודעה צפוי ללא שינויים.
  • bid: ערך צף שמייצג את ערך הצעת המחיר למודעה הזו
  • status: ערך מסוג מספר שלם שיכול להיות:
    • 0: לביצוע מוצלח
    • 1: (או כל ערך שהוא לא אפס) במקרה שאחד מהאותות של הקלט לא חוקי. במקרה שמוחזר ערך שאינו אפס על ידי יצירת הצעת מחיר, תהליך הבידינג יבוטל בכל מודעות ה-CA

ScoreAd()

function scoreAd(
  ad,
  bid,
  ad_selection_config,
  seller_signals,
  trusted_scoring_signals,
  contextual_signal,
  user_signal,
  custom_audience_signal) {
    return {'status': 0, 'score': score };
}

פרמטרים של קלט:

  • ad: יש לעיין במסמכי התיעוד של generateBid
  • bid: ערך הצעת המחיר של המודעה
  • ad_selection_config: אובייקט JSON שמייצג את הפרמטר AdSelectionConfig של ה-API selectAds. הפורמט הוא:

    var ad_selection_config = {
      'seller': 'seller',
      'decision_logic_url': 'url_of_decision_logic',
      'custom_audience_buyers': ['buyer1', 'buyer2'],
      'auction_signals': auction_signals,
      'per_buyer_signals': per_buyer_signals,
      'contextual_ads': [ad1, ad2]
    }
    
  • seller_signals: אובייקטים של JSON שנקראו מהפרמטר sellerSignals AdSelectionConfig של ה-API

  • trusted_scoring_signal: קריאה מהשדה adSelectionSignals בפרמטר AdSelectionConfig API

  • contextual_signals, user_signals: אובייקטים של JSON. הם מועברים כרגע כאובייקטים ריקים, והם ימולאו בגרסאות עתידיות. הפורמט של המודעות לא נאכף על ידי הפלטפורמה ומנוהל על ידי טכנולוגיות הפרסום.

  • per_buyer_signals: אובייקט JSON שנקרא מהמפה perBuyerSignal בפרמטר AdSelectionConfig API, כשהוא משמש כמפתח הקונה הנוכחי של 'קהל בהתאמה אישית'. ריקה אם אין במפה רשומה כלשהי של הקונה הנתון.

פלט:

  • score: ערך צף שמייצג את ערך הציון של המודעה הזו
  • status: ערך מסוג מספר שלם שיכול להיות:
    • 0: לביצוע מוצלח
    • 1: במקרה שהשדות customAudienceSignals לא חוקיים
    • 2: במקרה שבו הערך בשדה AdSelectionConfig לא תקין
    • 3: במקרה שאחד מהאותות האחרים לא חוקי
    • כל ערך שאינו אפס גורם לכשל בתהליך, הערך קובע את סוג החריגה שהמערכת ביצעה.

selectOutcome()

function selectOutcome(
  outcomes,
  selection_signals) {
    return {'status': 0, 'result': null};
}

פרמטרים של קלט:

  • outcomes: אובייקט JSON {"id": id_string, "bid": bid_double}
  • selection_signals: אובייקטים של JSON המצוינים באובייקט תצורת המכרז

פלט:

  • status: 0 להצלחה, לא אפס לכישלון
  • result: אחת מהתוצאות שהועברו או אפס

reportResult()

function reportResult(ad_selection_config, render_url, bid, contextual_signals) {
   return {
      'status': status,
      'results': {'signals_for_buyer': signals_for_buyer, 'reporting_url': reporting_url }
   };
}

פרמטרים של קלט:

  • ad_selection_config: יש לעיין במסמכי התיעוד של scoreAds
  • render_url: כתובת ה-URL לעיבוד של המודעה הזוכה
  • bid: הצעת המחיר שהוצעה למודעה הזוכה
  • contextual_signals: יש לעיין במסמכי התיעוד של generateBid

פלט:

  • status: 0 להצלחה, ואפס במקרה של כישלון
  • results: אובייקט JSON שמכיל:
    • signals_for_buyer: אובייקט JSON שמועבר לפונקציה reportWin
    • reporting_url: כתובת URL שהפלטפורמה משתמשת בה כדי להודיע לקונה על החשיפה

reportWin()

function reportWin(
   ad_selection_signals,
   per_buyer_signals,
   signals_for_buyer,
   contextual_signals,
   custom_audience_signals) {
   return {'status': 0, 'results': {'reporting_url': reporting_url } };
}

פרמטרים של קלט:

  • ad_selection_signals, per_buyer_signals: אפשר לעיין במסמכי התיעוד של scoreAd
  • signals_for_buyer: אובייקט JSON שהוחזר על ידי reportResult
  • contextual_signals, custom_audience_signals: אפשר לעיין במסמכי התיעוד של generateBid

פלט:

  • status: 0 להצלחה, ואפס במקרה של כישלון
  • results: אובייקט JSON שמכיל:
    • reporting_url: כתובת URL שהפלטפורמה משתמשת בה כדי להודיע על החשיפה לבית העסק

registerAdBeacon()

function registerAdBeacon(
  interaction_key,
  reporting_uri
)

פרמטרים של קלט:

  • interaction_key: מחרוזת שמייצגת את האירוע. הפלטפורמה משתמשת בנתונים האלה בשלב מאוחר יותר בדיווח על אינטראקציות של אירועים כדי לחפש את השדה reporting_uri שאמור לקבל את ההודעה. המפתח הזה צריך להתאים בין מה שהקונה או המוכר רושם, לבין מה שהמוכר מדווח.
  • reporting_uri: URI לקבלת דוחות אירועים. היא צריכה להיות ספציפית לסוג האירוע המדווח. היא חייבת לאשר בקשת POST כדי לטפל בכל הנתונים שדווחו יחד עם האירוע.

מזהי URI מוכנים מראש לבחירת מודעה

מזהי URI מוכנים מראש מאפשרים לטכנולוגיות של מודעות למנות פונקציות JavaScript ללוגיקת החלטות של בחירת מודעות במחלקות AdSelectionConfig ו-AdSelectionFromOutcomesConfig. מזהי URI מוכנים מראש לא מחייבים קריאות רשת כדי להוריד את ה-JavaScript המתאים. טכנולוגיות פרסום יכולות להשתמש במזהי URI מוגדרים מראש, בלי להגדיר דומיין רשום לאירוח ה-JavaScript.

ה-URI שנוצר מראש נוצר בפורמט הבא:

ad-selection-prebuilt:<use-case>/<name>?<required-script-generation-parameters>

פלטפורמת ארגז החול לפרטיות מספקת JavaScript באמצעות המידע מה-URI הזה בזמן הריצה.

מתבצעת התרעה של IllegalArgumentException אם:

  • אף אחד מהפרמטרים הנדרשים לא קיים ב-URI
  • יש פרמטרים לא מזוהים ב-URI

תרחישים לדוגמה ושמות של URI מובנים מראש ונתמכים

תרחיש לדוגמה 1: בחירת מודעות

ב-selectAds(AdSelectionConfig) יש תמיכה במזהי URI מובנים מראש בתרחיש לדוגמה ad-selection.

שם URI שנוצר מראש: highest-bid-wins

ה-URI שנוצר מראש מספק קוד JavaScript שבוחר את המודעה עם הצעת המחיר הגבוהה ביותר, לאחר הגשת הצעת המחיר. הוא גם מספק פונקציית דיווח בסיסית כדי לדווח על render_uri ו-bid של הזוכה.

הפרמטרים הנדרשים

reportingUrl: כתובת ה-URL הבסיסית לדיווח, שמכילה פרמטרים של render_uri ושל bid של המודעה הזוכה:

<reportingUrl>?render_uri=<renderUriOfWinnigAd>&bid=<bidOfWinningAd>

שימוש

אם כתובת ה-URL הבסיסית לדיווח היא https://www.ssp.com/reporting, ה-URI המובנה מראש יהיה:

`ad-selection-prebuilt://ad-selection/highest-bid-wins/?reportingUrl=https://www.ssp.com/reporting`

תרחיש לדוגמה 2: בחירת מודעות מתוצאות החיפוש

מזהי URI מובנים מראש בתרחיש לדוגמה ad-selection-from-outcomes תומכים בתהליך העבודה selectAds(AdSelectionFromOutcomesConfig).

שם URI שנוצר מראש: waterfall-mediation-truncation

ה-URI שנוצר מראש waterfall-mediation-truncation מספק JavaScript שמטמיע לוגיקת חיתוך של תהליך בחירת הרשת ב-Waterfall, כאשר ה-JavaScript מחזיר מודעה של צד ראשון אם הערך של bid גבוה מהערך של bid floor או שווה לו, ואם לא, מחזיר null.

הפרמטרים הנדרשים

bidFloor: המפתח של ערך הסף התחתון להצעת המחיר שהועבר ב-getSelectionSignals(), בהשוואה למודעה של ה-SDK של תהליך בחירת הרשת.

שימוש

אם האותות לבחירת מודעות נראים כמו {"bid_floor": 10}, ה-URI שנוצר מראש שיתקבל יהיה:

`ad-selection-prebuilt://ad-selection-from-outcomes/waterfall-mediation-truncation/?bidFloor=bid_floor`

בדיקה

כדי לעזור לכם להתחיל להשתמש ב-Protected Audience API, יצרנו אפליקציות לדוגמה ב-Kotlin וב-Java ב-GitHub.

דרישות מוקדמות

ל-Protected Audience API נדרש קוד JavaScript במהלך בחירת המודעות והדיווח על החשיפות. יש שתי שיטות לספק את ה-JavaScript בסביבת הבדיקה:

  • הרצת שרת עם נקודות הקצה הנדרשות מסוג HTTPS שמחזיר את קוד ה-JavaScript
  • כדי לבטל את האחזור מרחוק, מספקים את הקוד הנחוץ ממקור מקומי

בכל אחת מההרשאות צריך להגדיר נקודת קצה (endpoint) מסוג HTTPS כדי לטפל בדיווח על חשיפות.

נקודות הקצה ב-HTTPS

כדי לבדוק את בחירת המודעות ואת הדיווח על החשיפות, צריך להגדיר 7 נקודות קצה ב-HTTPS שאליו מכשיר הבדיקה או אמולטור יכולים לגשת:

  1. נקודת הקצה של הקונה שממלאת את הלוגיקה של הבידינג ב-JavaScript.
  2. נקודת קצה (endpoint) שמגישה את האותות של הבידינג.
  3. נקודת הקצה של בית העסק שממלאת את לוגיקת ההחלטות ב-JavaScript.
  4. נקודת קצה שמציגה אותות של ציון.
  5. נקודת קצה לדיווח על חשיפות של הקונה הזוכה.
  6. נקודת קצה לדיווח על חשיפות של בית העסק.
  7. נקודת קצה להצגת העדכונים היומיים של קהל בהתאמה אישית.

לנוחיותכם, מאגר GitHub מספק קוד JavaScript בסיסי למטרות בדיקה. הוא כולל גם הגדרות של שירותי OpenAPI שאפשר לפרוס בפלטפורמת דמה או מיקרו-שירותים נתמכת. למידע נוסף, ראו README בפרויקט.

ביטול אחזור מרחוק של JavaScript

זו תכונה שמיועדת לבדיקות מקצה לקצה. כדי לבטל את השליפה מרחוק, האפליקציה צריכה לפעול במצב ניפוי באגים כאשר האפשרויות למפתחים מופעלות.

כדי להפעיל את מצב ניפוי הבאגים באפליקציה, מוסיפים את השורה הבאה למאפיין האפליקציה בקובץ AndroidManifest.xml:

<application
  android:debuggable="true">

אפשר לראות דוגמה לשימוש בשינוי הזה באפליקציה לדוגמה של Protected Audience API ב-GitHub.

אתם צריכים להוסיף JavaScript מותאם אישית משלכם כדי לטפל בתרחישים של בחירת מודעות, כמו בידינג, החלטות דירוג ודיווח. במאגר GitHub תוכלו למצוא דוגמאות בסיסיות לקוד JavaScript שמטפל בכל הבקשות הנדרשות. האפליקציה לדוגמה של Protected Audience API מדגימה איך לקרוא את הקוד מהקובץ הזה ולהכין אותו לשימוש כשינוי מברירת המחדל.

אפשר לבטל באופן עצמאי את אחזור ה-JavaScript בצד המוכר ובצד הקונה, אבל נדרשת נקודת קצה (endpoint) של HTTPS כדי להציג כל JavaScript שלא אתם מספקים שינויים מברירת המחדל שלו. במאמר README מוסבר איך להגדיר שרת שמטפל במקרים כאלה.

אפשר לבטל את האחזור של JavaScript רק לקהלים מותאמים אישית שנמצאים בבעלות החבילה.

שינוי מ-JavaScript בצד המוכר

כדי להגדיר שינוי מברירת המחדל של JavaScript בצד המוכר, מבצעים את הפעולות הבאות כפי שמוצג בדוגמת הקוד הבאה:

  1. מאתחלים אובייקט AdSelectionManager.
  2. מקבלים הפניה אל TestAdSelectionManager מהאובייקט AdSelectionManager.
  3. יוצרים אובייקט AdSelectionConfig.
  4. יוצרים AddAdSelectionOverrideRequest עם האובייקט AdSelectionConfig ו-String שמייצג את ה-JavaScript שבו אתם מתכוונים להשתמש כשינוי מברירת המחדל.
  5. קוראים לשיטה overrideAdSelectionConfigRemoteInfo() האסינכרונית עם האובייקט AddAdSelectionOverrideRequest והאובייקטים הרלוונטיים של Executor ו-OutcomeReceiver.

Kotlin

val testAdSelectionManager: TestAdSelectionManager =
  context.getSystemService(AdSelectionManager::class.java).getTestAdSelectionManager()

// Initialize AdSelectionConfig =
val adSelectionConfig = new AdSelectionConfig.Builder()
    .setSeller(seller)
    .setDecisionLogicUrl(decisionLogicUrl)
    .setCustomAudienceBuyers(customAudienceBuyers)
    .setAdSelectionSignals(adSelectionSignals)
    .setSellerSignals(sellerSignals)
    .setPerBuyerSignals(perBuyerSignals)
    .build()

// Initialize AddAddSelectionOverrideRequest
val request = AddAdSelectionOverrideRequest.Builder()
    .setAdSelectionConfig(adSelectionConfig)
    .setDecisionLogicJs(decisionLogicJS)
    .build()

// Run the call to override the JavaScript for the given AdSelectionConfig
// Note that this only takes effect in apps marked as debuggable
testAdSelectionManager.overrideAdSelectionConfigRemoteInfo(
    request,
    executor,
    outComeReceiver)

Java

TestAdSelectionManager testAdSelectionManager =
  context.getSystemService(AdSelectionManager.class).getTestAdSelectionManager();

// Initialize AdSelectionConfig =
AdSelectionConfig adSelectionConfig = new AdSelectionConfig.Builder()
    .setSeller(seller)
    .setDecisionLogicUrl(decisionLogicUrl)
    .setCustomAudienceBuyers(customAudienceBuyers)
    .setAdSelectionSignals(adSelectionSignals)
    .setSellerSignals(sellerSignals)
    .setPerBuyerSignals(perBuyerSignals)
    .build();

// Initialize AddAddSelectionOverrideRequest
AddAdSelectionOverrideRequest request = AddAdSelectionOverrideRequest.Builder()
    .setAdSelectionConfig(adSelectionConfig)
    .setDecisionLogicJs(decisionLogicJS)
    .build();

// Run the call to override the JavaScript for the given AdSelectionConfig
// Note that this only takes effect in apps marked as debuggable
testAdSelectionManager.overrideAdSelectionConfigRemoteInfo(
    request,
    executor,
    outComeReceiver);

בקטע הפעלת בחירת מודעות מוסבר מה מייצג כל אחד מהשדות ב-AdSelectionConfig. ההבדל העיקרי הוא שאפשר להגדיר את decisionLogicUrl כערך placeholder, והמערכת תתעלם ממנו.

כדי לשנות את קוד ה-JavaScript שמשמש לבחירת המודעות, השדה decisionLogicJs צריך לכלול את החתימות המתאימות בצד המוכר. לדוגמה, כדי לקרוא איך קוראים קובץ JavaScript כמחרוזת, אפשר לעיין באפליקציה לדוגמה של Protected Audience API ב-GitHub.

השיטה האסינכרונית overrideAdSelectionConfigRemoteInfo() משתמשת באובייקט OutcomeReceiver כדי לסמן את התוצאה של הקריאה ל-API.

הקריאה החוזרת onResult() מציינת שהביטול בוצע בהצלחה. קריאות עתידיות ל-selectAds() ישתמשו בכל ההחלטות ולוגיקת הדיווח שהעברתם בתור הביטול.

הקריאה החוזרת (callback) onError() מציינת שני תנאים אפשריים:

  • אם מנסים לשנות את הביטול עם ארגומנטים לא חוקיים, הערך AdServiceException מציין שהסיבה היא IllegalArgumentException.
  • אם מתבצע ניסיון לשינוי מברירת המחדל באפליקציה שלא פועלת במצב ניפוי באגים, והאפשרויות למפתחים מופעלות, AdServiceException מציין שהסיבה לכך היא IllegalStateException.

איפוס השינויים בצד המוכר

בקטע הזה ההנחה היא שביטלתם את ה-JavaScript בצד המוכר שיש לכם הפניה אל TestAdSelectionManager ואל AdSelectionConfig בקטע הקודם.

כדי לאפס את השינויים עבור כל AdSelectionConfigs:

  1. קוראים לשיטה resetAllAdSelectionConfigRemoteOverrides() האסינכרונית עם האובייקט OutcomeReceiver הרלוונטי.

Kotlin

// Resets overrides for all AdSelectionConfigs
testAadSelectionManager.resetAllAdSelectionConfigRemoteOverrides(
  outComeReceiver)

Java

// Resets overrides for all AdSelectionConfigs
testAdSelectionManager.resetAllAdSelectionConfigRemoteOverrides(
    outComeReceiver);

אחרי איפוס השינויים בצד המוכר, קריאות ל-selectAds() ישתמשו בכל decisionLogicUrl שמאוחסן ב-AdSelectionConfig כדי לנסות לאחזר את ה-JavaScript הנדרש.

אם הקריאה אל resetAllAdSelectionConfigRemoteOverrides() נכשלת, הקריאה החוזרת (callback) של OutComeReceiver.onError() מספקת AdServiceException. אם מנסים להסיר את השינויים מברירת המחדל באפליקציה שלא פועלת במצב ניפוי באגים והאפשרויות למפתחים מופעלות, AdServiceException מציין שהסיבה לכך היא IllegalStateException.

שינוי JavaScript בצד הקונה

  1. פועלים לפי השלבים להצטרפות לקהל בהתאמה אישית.
  2. יוצרים AddCustomAudienceOverrideRequest עם הקונה ושם של הקהל בהתאמה אישית שרוצים לבטל, בנוסף ללוגיקת הבידינג ולנתונים שרוצים להשתמש בהם כשינוי מברירת המחדל.
  3. קריאה לשיטה overrideCustomAudienceRemoteInfo() האסינכרונית עם האובייקט AddCustomAudienceOverrideRequest והאובייקטים הרלוונטיים Executor ו-OutcomeReceiver

Kotlin

val testCustomAudienceManager: TestCustomAudienceManager =
  context.getSystemService(CustomAudienceManager::class.java).getTestCustomAudienceManager()

// Join custom audience

// Build the AddCustomAudienceOverrideRequest
val request = AddCustomAudienceOverrideRequest.Builder()
    .setBuyer(buyer)
    .setName(name)
    .setBiddingLogicJs(biddingLogicJS)
    .setTrustedBiddingSignals(trustedBiddingSignals)
    .build()

// Run the call to override JavaScript for the given custom audience
testCustomAudienceManager.overrideCustomAudienceRemoteInfo(
    request,
    executor,
    outComeReceiver)

Java

TestCustomAudienceManager testCustomAudienceManager =
  context.getSystemService(CustomAudienceManager.class).getTestCustomAudienceManager();

// Join custom audience

// Build the AddCustomAudienceOverrideRequest
AddCustomAudienceOverrideRequest request =
    AddCustomAudienceOverrideRequest.Builder()
        .setBuyer(buyer)
        .setName(name)
        .setBiddingLogicJs(biddingLogicJS)
        .setTrustedBiddingSignals(trustedBiddingSignals)
        .build();

// Run the call to override JavaScript for the given custom audience
testCustomAudienceManager.overrideCustomAudienceRemoteInfo(
    request,
    executor,
    outComeReceiver);

הערכים של buyer ו-name זהים לערכים של הקהל בהתאמה אישית. למידע נוסף על השדות האלה

אפשר גם לציין שני פרמטרים נוספים:

  • biddingLogicJs: JavaScript שמפעיל את הלוגיקה של הקונה, שמשמשת במהלך בחירת המודעות. ראו מהן החתימות של הפונקציות הנדרשות ב-JavaScript.
  • trustedBiddingSignals: אותות של בידינג שישמשו במהלך בחירת המודעות. למטרות בדיקה, השדה הזה יכול להיות מחרוזת ריקה.

השיטה האסינכרונית overrideCustomAudienceRemoteInfo() משתמשת באובייקט OutcomeReceiver כדי לסמן את התוצאה של הקריאה ל-API.

הקריאה החוזרת onResult() מציינת שהביטול בוצע בהצלחה. הקריאות הבאות אל selectAds() ישתמשו בכל לוגיקת בידינג ודיווח שהעברתם בתור הביטול.

הקריאה החוזרת (callback) onError() מציינת שני תנאים אפשריים.

  • אם מנסים לשנות את הביטול עם ארגומנטים לא חוקיים, הערך AdServiceException מציין שהסיבה היא IllegalArgumentException.
  • אם מתבצע ניסיון לשינוי מברירת המחדל באפליקציה שלא פועלת במצב ניפוי באגים, והאפשרויות למפתחים מופעלות, AdServiceException מציין שהסיבה לכך היא IllegalStateException.

איפוס השינויים בצד הקונה

בקטע הזה ההנחה היא שביטלתם את ה-JavaScript בצד הקונה, ושיש לכם הפניה ל-TestCustomAudienceManager שבו השתמשתם בקטע הקודם.

כדי לאפס שינויים של כל הקהלים בהתאמה אישית:

  1. כדאי לקרוא לשיטה resetAllCustomAudienceOverrides() האסינכרונית עם אובייקטים רלוונטיים מסוג Executor ו-OutcomeReceiver.

Kotlin

// Resets overrides for all custom audiences
testCustomAudienceManager.resetCustomAudienceRemoteInfoOverride(
    executor,
    outComeReceiver)

Java

// Resets overrides for all custom audiences
testCustomAudienceManager.resetCustomAudienceRemoteInfoOverride(
    executor,
    outComeReceiver)

לאחר האיפוס של השינויים בצד הקונה, הקריאות הבאות אל selectAds() ישתמשו בכל מה ש-biddingLogicUrl ו-trustedBiddingData מאוחסן בCustomAudience כדי לנסות לאחזר את ה-JavaScript הנדרש.

אם הקריאה אל resetCustomAudienceRemoteInfoOverride() נכשלת, הקריאה החוזרת (callback) של OutComeReceiver.onError() מספקת AdServiceException. אם מנסים להסיר את השינויים מברירת המחדל באפליקציה שלא פועלת במצב ניפוי באגים והאפשרויות למפתחים מופעלות, AdServiceException יציין שהסיבה לכך היא IllegalStateException.

הגדרת שרת דיווח

גם כשמשתמשים בשינוי מברירת המחדל של אחזור מרחוק, צריך להגדיר שרת שאליו המכשיר או האמולטור יכולים להגיע כדי להגיב לדיווחים על אירועים. לצורך בדיקה אפשר לקבל רק נקודת קצה פשוטה שמחזירה 200. מאגר GitHub כולל הגדרות של שירות OpenAPI, שאפשר לפרוס בפלטפורמת דמה או מיקרו-שירותים נתמכת. למידע נוסף, ראו README בפרויקט.

כשמחפשים את ההגדרות של OpenAPI, צריך לאתר את Reporting-server.json. הקובץ מכיל נקודת קצה פשוטה שמחזירה 200, שמייצגת קוד תגובה של HTTP. המערכת משתמשת בנקודת הקצה הזאת במהלך selectAds() והיא מאותתת ל-Protected Audience API שדיווח על חשיפות הושלם בהצלחה.

הפונקציונליות לבדיקה

  • כדאי להצטרף או לצאת, ולהגדיר קהל בהתאמה אישית על סמך פעולות משתמש קודמות.
  • התחלת תהליך בחירת מודעות במכשיר באמצעות קובצי JavaScript שמתארחים מרחוק.
  • בוחנים איך שיוך של אפליקציה להגדרות קהל מותאמות אישית עשוי להשפיע על התוצאות של בחירות המודעות.
  • תרגול של דיווח על חשיפות לאחר בחירת המודעה.

הגבלות

בטבלה הבאה מפורטות המגבלות על עיבוד Protected Audience API. המגבלות שמוצגות עשויות להשתנות בהתאם למשוב שאנחנו מקבלים. למידע על היכולות המתקדמות, כדאי לקרוא את נתוני הגרסה.

רכיב תיאור המגבלה ערך המגבלה
קהל בהתאמה אישית (CA) מספר המודעות המקסימלי לכל רשות אישורים 100
המספר המקסימלי של רשויות אישורים לכל אפליקציה 1,000
המספר המקסימלי של אפליקציות שיכולות ליצור רשות אישורים 1,000
העיכוב המקסימלי בזמן ההפעלה של רשות אישורים מרגע היצירה שלה 60 ימים
זמן התפוגה המקסימלי של רשות אישורים ממועד ההפעלה 60 ימים
המספר המקסימלי של רשויות אישורים במכשיר 4,000
הגודל המקסימלי של שם ה-CA 200 בייטים
הגודל המקסימלי של URI לאחזור יומי 400 בייטים
גודל מקסימלי של URI לוגי של בידינג 400 בייטים
גודל מקסימלי של נתוני בידינג מהימנים 10 KB
גודל מקסימלי של אותות לבידינג של משתמשים 10 KB
מחיר שיחה מקסימלי בסך leaveCustomAudience לכל קונה אחת לשנייה
מחיר שיחה מקסימלי בסך joinCustomAudience לכל קונה אחת לשנייה
אחזור רקע מקליפורניה פג הזמן הקצוב של החיבור ‫5 שניות
פסק זמן לקריאת HTTP ‫30 שניות
גודל הורדה כולל מקסימלי 10 KB
משך הזמן המקסימלי של איטרציית אחזור 5 דקות
המספר המקסימלי של רשויות אישורים שעודכנו בכל משימה 1,000
בחירת מודעות מספר הקונים המקסימלי טרם נקבע
המספר המקסימלי של CAs לכל קונה טרם נקבע
המספר המקסימלי של מודעות במכרז טרם נקבע
זמן קצוב לתפוגה של החיבור הראשוני ‫5 שניות
תם הזמן הקצוב לקריאת החיבור ‫5 שניות
זמן ביצוע מקסימלי של AdSelection 10 שניות
זמן הביצוע המקסימלי של בידינג לכל רשות אישורים בAdSelection 5 שניות
זמן ביצוע מקסימלי של ניקוד בAdSelection 5 שניות
זמן הביצוע המקסימלי לכל קונה בAdSelection טרם נקבע
הגודל המקסימלי של בחירת מודעות/אתר מכירה/אותות של קונה טרם נקבע
הגודל המקסימלי של הסקריפטים של אתר המכירה/הקונה טרם נקבע
תעריף שיחות מקסימלי עבור selectAds QPS אחד
דיווח על חשיפות פרק זמן מינימלי עד להסרה של בחירת המודעות מההגדרה הקבועה 24 שעות
המספר המקסימלי של אפשרויות אחסון שאפשר לבחור טרם נקבע
הגודל המקסימלי של כתובת ה-URL לפלט הדיווח טרם נקבע
משך זמן מקסימלי לדיווח על חשיפות טרם נקבע
המספר המרבי של ניסיונות חוזרים לשיחות התראה טרם נקבע
תם פרק הזמן שהוקצב להתחברות ‫5 שניות
זמן הביצוע הכולל המקסימלי של reportImpression 2 שניות
תעריף שיחות מקסימלי עבור reportImpressions QPS אחד
דיווח על אירועים המספר המקסימלי של משׂואות רשת (beacon) לכל קונה בכל מכרז 10

המספר המקסימלי של משׂואות רשת לכל אתר מכירה בכל מכרז

10

גודל מקסימלי של מפתח אירוע

40 בייטים

גודל מקסימלי של נתוני אירוע

64KB

מודעות הגודל המקסימלי של רשימת המודעות 10KB ששותפו על ידי כל AdData ברשות אישורים אחת עבור הקשר
URLs האורך המקסימלי של כל מחרוזת כתובת URL שתועדה כקלט טרם נקבע
JavaScript זמן ביצוע מקסימלי שנייה אחת לבידינג ולציון בדוחות החשיפות
צריכת הזיכרון המקסימלית ‎10 MB

דיווח על באגים ובעיות

המשוב שלך הוא חלק חיוני מארגז החול לפרטיות ב-Android. דווחו לנו על בעיות שמצאתם או על רעיונות לשיפור ארגז החול לפרטיות ב-Android.