راهنمای توسعه دهنده API مخاطبین محافظت شده

همانطور که در اسناد Android Sandbox Privacy می خوانید، از دکمه Developer Preview یا Beta برای انتخاب نسخه برنامه ای که با آن کار می کنید استفاده کنید، زیرا ممکن است دستورالعمل ها متفاوت باشد.


API مخاطب محافظت شده در Android (که قبلاً به عنوان FLEDGE شناخته می شد) شامل API مخاطبان سفارشی و API انتخاب آگهی است. پلتفرم‌های فناوری تبلیغات و تبلیغ‌کنندگان می‌توانند از این APIها برای ارائه آگهی‌های سفارشی‌شده براساس تعامل قبلی با برنامه استفاده کنند که اشتراک‌گذاری شناسه‌ها را در بین برنامه‌ها محدود می‌کند و اشتراک‌گذاری اطلاعات تعامل برنامه کاربر را با اشخاص ثالث محدود می‌کند.

Custom Audience API حول انتزاع "مخاطب سفارشی" متمرکز شده است که نشان دهنده گروهی از کاربران با اهداف مشترک است. یک تبلیغ‌کننده می‌تواند کاربری را با یک مخاطب سفارشی ثبت کند و تبلیغات مرتبط را با آن مرتبط کند. این اطلاعات به صورت محلی ذخیره می‌شوند و می‌توانند برای اطلاع‌رسانی به مناقصه‌های آگهی‌دهنده، فیلتر کردن آگهی‌ها و ارائه آگهی استفاده شوند.

Ad Selection API چارچوبی را ارائه می دهد که به چندین برنامه نویس اجازه می دهد یک حراج را به صورت محلی برای مخاطبان سفارشی اجرا کنند. برای دستیابی به این هدف، سیستم تبلیغات مرتبط مرتبط با مخاطبان سفارشی را در نظر می‌گیرد و پردازش بیشتری را روی تبلیغاتی انجام می‌دهد که یک پلتفرم فناوری تبلیغات به دستگاه برمی‌گرداند.

پلتفرم‌های فناوری تبلیغات می‌توانند این APIها را برای پیاده‌سازی بازاریابی مجدد که حریم خصوصی کاربر را حفظ می‌کند، ادغام کنند. پشتیبانی از موارد استفاده اضافی، از جمله تبلیغات نصب برنامه، برای نسخه های بعدی برنامه ریزی شده است. در طرح پیشنهادی، درباره API مخاطب محافظت شده در Android بیشتر بیاموزید.

این راهنما نحوه کار با Protected Audience API در Android را برای انجام کارهای زیر شرح می دهد:

  1. مخاطبان سفارشی را مدیریت کنید
  2. انتخاب آگهی را در دستگاهی تنظیم و اجرا کنید
  3. گزارش نمایش تبلیغات

قبل از شروع

قبل از شروع، موارد زیر را کامل کنید:

  1. محیط توسعه خود را برای Privacy Sandbox در Android تنظیم کنید .
  2. یا یک تصویر سیستم را روی یک دستگاه پشتیبانی شده نصب کنید یا یک شبیه‌ساز راه‌اندازی کنید که شامل پشتیبانی از Privacy Sandbox در Android باشد.
  3. در ترمینال، با دستور adb زیر ، دسترسی به API مخاطبان محافظت شده (به طور پیش فرض غیرفعال) را فعال کنید .

      adb shell device_config put adservices ppapi_app_allow_list \"*\"
    
  4. در یک ترمینال، گزارش beacon را با دستورات adb زیر فعال کنید.

     adb shell device_config put adservices fledge_beacon_reporting_metrics_enabled true
     adb shell device_config put adservices fledge_register_ad_beacon_enabled true
    
  5. یک مجوز ACCESS_ADSERVICES_CUSTOM_AUDIENCE را در مانیفست برنامه خود قرار دهید:

      <uses-permission android:name="android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCE" />
    
  6. به پیکربندی سرویس های تبلیغاتی در عنصر <application> مانیفست خود ارجاع دهید:

      <property android:name="android.adservices.AD_SERVICES_CONFIG"
                android:resource="@xml/ad_services_config" />
    
  7. منبع XML خدمات تبلیغاتی را که در مانیفست خود ارجاع داده شده است، مانند res/xml/ad_services_config.xml مشخص کنید. درباره مجوزهای خدمات تبلیغات و کنترل دسترسی SDK بیشتر بیاموزید .

      <ad-services-config>
        <custom-audiences allowAllToAccess="true" />
      </ad-services-config>
    
  8. به‌طور پیش‌فرض، Ad Selection API محدودیت‌هایی را برای حداکثر مقدار حافظه‌ای که یک حراج یا اسکریپت گزارش‌دهی نمایش می‌تواند اختصاص دهد اعمال می‌کند. ویژگی محدودیت حافظه به WebView نسخه 105.0.5195.58 یا بالاتر نیاز دارد. این پلتفرم یک بررسی نسخه را اعمال می‌کند و در صورت عدم رضایت، تماس‌های مربوط به selectAds و APIهای reportImpression با شکست مواجه می‌شوند. دو گزینه برای تنظیم این وجود دارد:

    • گزینه 1: دستور adb زیر را برای غیرفعال کردن این چک اجرا کنید:

      adb device_config put fledge_js_isolate_enforce_max_heap_size false
      
    • گزینه 2: WebView Beta را از فروشگاه Google Play نصب کنید. این باید برابر یا بالاتر از نسخه ذکر شده قبلی باشد.

به یک مخاطب سفارشی بپیوندید

یک مخاطب سفارشی نشان دهنده گروهی از کاربران با اهداف یا علایق مشترک است که توسط یک برنامه تبلیغ کننده تصمیم می گیرد. یک برنامه یا SDK ممکن است از یک مخاطب سفارشی برای نشان دادن یک مخاطب خاص استفاده کند، مانند شخصی که مواردی را در سبد خرید گذاشته است. برای ایجاد یا پیوستن به یک مخاطب سفارشی به صورت ناهمزمان، موارد زیر را انجام دهید:

  1. شی CustomAudienceManager را راه اندازی کنید.
  2. با تعیین پارامترهای کلیدی مانند بسته خریدار و نام مرتبط، یک شی CustomAudience ایجاد کنید. سپس، شی JoinCustomAudienceRequest را با شی CustomAudience مقداردهی اولیه کنید.
  3. joinCustomAudience() ناهمزمان را با شی JoinCustomAudienceRequest و اشیاء Executor و OutcomeReceiver مربوطه فراخوانی کنید.

کاتلین

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)

جاوا

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 به‌روزرسانی روزانه : یک نشانی وب HTTPS که هر روز در پس‌زمینه جستجو می‌شود تا سیگنال‌های پیشنهادی کاربر مخاطب سفارشی، داده‌های مناقصه مورد اعتماد را به‌روزرسانی کند، و نشانی‌های وب و ابرداده‌ها را برای تبلیغات نمایش دهد.
  • URL منطقی مناقصه : یک نشانی اینترنتی HTTPS که در حین انتخاب آگهی برای واکشی منطق پیشنهادی جاوا اسکریپت خریدار درخواست شده است. امضاهای تابع مورد نیاز را در این جاوا اسکریپت مشاهده کنید.
  • شناسه‌های رندر آگهی : یک شناسه دلخواه که توسط فناوری آگهی خریدار تنظیم می‌شود. این یک بهینه سازی برای تولید محموله برای B&A است.

پارامترهای اختیاری برای یک شی CustomAudience ممکن است شامل موارد زیر باشد:

  • زمان فعال‌سازی : مخاطبان سفارشی فقط می‌توانند پس از زمان فعال‌سازی در انتخاب آگهی و به‌روزرسانی‌های روزانه شرکت کنند. به عنوان مثال، این می تواند برای جذب کاربران از کار افتاده یک برنامه مفید باشد.
  • زمان انقضا : زمان آینده که پس از آن مخاطبان سفارشی از دستگاه حذف می‌شوند.
  • سیگنال‌های مناقصه کاربر : یک رشته JSON حاوی سیگنال‌های کاربر، مانند منطقه محلی ترجیحی کاربر، که جاوا اسکریپت منطق پیشنهاد خریدار برای تولید پیشنهادها در طول فرآیند انتخاب آگهی مصرف می‌کند. این فرمت به پلتفرم‌های فناوری تبلیغات کمک می‌کند تا از کد در سراسر پلتفرم‌ها استفاده مجدد کنند و مصرف در توابع جاوا اسکریپت را کاهش می‌دهد.
  • داده‌های مناقصه مورد اعتماد : یک نشانی اینترنتی HTTPS و فهرستی از رشته‌های مورد استفاده در فرآیند انتخاب آگهی که سیگنال‌های پیشنهاد قیمت را از یک سرویس کلید/مقدار قابل اعتماد دریافت می‌کنند.
  • تبلیغات : فهرستی از اشیاء AdData مربوط به تبلیغاتی که در انتخاب آگهی شرکت می کنند. هر شیء AdData شامل موارد زیر است:
    • Render URL : یک نشانی اینترنتی HTTPS که برای نمایش آگهی نهایی درخواست می شود.
    • فراداده : یک شی JSON که به صورت رشته ای حاوی اطلاعاتی است که باید توسط منطق پیشنهاد خریدار در طول فرآیند انتخاب آگهی مصرف شود.
    • فیلترهای تبلیغات : کلاسی که شامل تمام اطلاعات لازم برای فیلتر کردن آگهی نصب برنامه و محدودیت فرکانس در هنگام انتخاب آگهی است.

در اینجا یک مثال از یک نمونه شئ CustomAudience آورده شده است:

کاتلین

// 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()

جاوا

// 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 استفاده می کند.

  • onResult() onResult نشان می‌دهد که مخاطب سفارشی با موفقیت ایجاد یا به‌روزرسانی شده است.
  • onError() دو شرط ممکن را نشان می دهد.
    • اگر JoinCustomAudienceRequest با آرگومان های نامعتبر مقداردهی اولیه شود، AdServicesException یک IllegalArgumentException را به عنوان علت نشان می دهد.
    • همه خطاهای دیگر AdServicesException با یک IllegalStateException به عنوان علت دریافت می کنند.

در اینجا نمونه ای از مدیریت نتیجه joinCustomAudience() آورده شده است:

کاتلین

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

جاوا

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 مربوطه فراخوانی کنید.

کاتلین

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)

جاوا

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 را نشان می دهد. برای کمک به محافظت از حریم خصوصی، نتیجه خطا بین خطاهای داخلی و آرگومان های نامعتبر تمایز قائل نمی شود. onResult() onResult زمانی فراخوانی می شود که فراخوانی API تکمیل شود، خواه مخاطب سفارشی منطبق با موفقیت حذف شود یا خیر.

انتخاب آگهی را اجرا کنید

برای استفاده از Protected Audience API برای انتخاب تبلیغات، متد selectAds() را فراخوانی کنید:

  1. یک شی AdSelectionManager راه اندازی کنید.
  2. یک شی AdSelectionConfig بسازید.
  3. متد selectAds() ناهمزمان را با شی AdSelectionConfig و اشیاء Executor و OutcomeReceiver مربوطه فراخوانی کنید.

کاتلین

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
)

جاوا

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 منطق تصمیم : یک نشانی اینترنتی HTTPS که برای به دست آوردن منطق جاوا اسکریپت شبکه تبلیغات فروشنده درخواست شده است.
    • نشانی وب HTTPS : برای به دست آوردن منطق جاوا اسکریپت شبکه تبلیغات فروشنده درخواست شد. امضاهای تابع مورد نیاز را مشاهده کنید.
    • URI از پیش ساخته شده : که از قالب انتخاب آگهی FLEDGE پیروی می کند. IllegalArgumentException پرتاب می شود، اگر یک uri از پیش ساخته شده پشتیبانی نشده یا نادرست ارسال شود.
  • خریداران مخاطب سفارشی : فهرست کاملی از شناسه‌های شبکه‌های تبلیغاتی خریدار که توسط فروشنده مجاز به شرکت در فرآیند انتخاب آگهی هستند. این شناسه‌های خریدار با CustomAudience.getBuyer() مخاطبان سفارشی شرکت‌کننده مطابقت دارند.

پارامترهای زیر را می توان به صورت اختیاری برای انتخاب آگهی سفارشی تر مشخص کرد:

  • سیگنال‌های انتخاب آگهی : یک شی JSON، به‌صورت رشته‌ای، حاوی سیگنال‌هایی است که باید توسط جاوا اسکریپت منطق پیشنهاد خریدار مصرف شود که از CustomAudience.getBiddingLogicUrl() واکشی شده است.
  • سیگنال‌های فروشنده : یک شی JSON، سریال‌سازی شده به صورت رشته، حاوی سیگنال‌هایی است که توسط منطق تصمیم‌گیری جاوا اسکریپت واکشی شده فروشنده از AdSelectionConfig.getDecisionLogicUrl() مصرف می‌شود.
  • سیگنال‌های هر خریدار : نقشه‌ای از اشیاء JSON، به‌صورت رشته‌ای، حاوی سیگنال‌هایی است که باید توسط جاوا اسکریپت منطق پیشنهادی خریداران خاص مصرف شود که از CustomAudience.getBiddingLogicUrl() واکشی شده است، که توسط فیلدهای خریدار مخاطبان سفارشی شرکت‌کننده شناسایی می‌شوند.
  • تبلیغات متنی: مجموعه ای از کاندیداهای تبلیغاتی که مستقیماً از خریداران در طول حراجی که خارج از حراج مخاطب محافظت شده انجام می شود جمع آوری می شود.

پس از انتخاب یک تبلیغ، نتایج، پیشنهادات و سیگنال‌ها به صورت داخلی برای گزارش‌دهی باقی می‌مانند. فراخوانی OutcomeReceiver.onResult() یک AdSelectionOutcome برمی گرداند که حاوی:

  • یک URL رندر برای تبلیغ برنده، که از AdData.getRenderUrl() بدست آمده است.
  • شناسه انتخاب آگهی منحصر به فرد برای کاربر دستگاه. این شناسه برای گزارش نمایش تبلیغات استفاده می شود.

اگر به دلایلی مانند آرگومان‌های نامعتبر، مهلت زمانی یا مصرف بیش از حد منابع، انتخاب آگهی با موفقیت انجام نشود، فراخوانی OutcomeReceiver.onError() یک AdServicesException با رفتارهای زیر ارائه می‌کند:

  • اگر انتخاب آگهی با آرگومان های نامعتبر آغاز شود، AdServicesException یک IllegalArgumentException را به عنوان علت نشان می دهد.
  • همه خطاهای دیگر AdServicesException با یک IllegalStateException به عنوان علت دریافت می کنند.

تبلیغات متنی

مخاطب محافظت شده می تواند تبلیغات متنی را در یک حراج محافظت شده بگنجاند. تبلیغات متنی باید در سرور فناوری تبلیغات انتخاب شوند و خارج از APIهای مخاطب محافظت شده به دستگاه بازگردانده شوند. سپس تبلیغات متنی را می‌توان با استفاده از AdSelectionConfig در حراج گنجاند که در آن نقطه مانند تبلیغات دستگاه عمل می‌کنند، از جمله واجد شرایط بودن برای فیلتر تبلیغات منفی. پس از اتمام حراج مخاطب محافظت شده، باید reportImpression() فراخوانی کنید. این reportWin() را در تبلیغات متنی برنده، به همان الگوی گزارش نمایش ، فراخوانی می‌کند تا آگهی برنده را در دستگاه دریافت کند. هر آگهی متنی به یک خریدار، یک پیشنهاد، یک پیوند به منطق گزارش، یک URL رندر و ابرداده تبلیغات نیاز دارد.

برای استقرار تبلیغات متنی در برنامه، برنامه هدف باید یک شی ContextualAds ایجاد کند:

کاتلین

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

جاوا

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

شی ContextualAds حاصل می‌تواند هنگام ایجاد AdSelectionConfig شما ارسال شود:

کاتلین

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

جاوا

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

فیلتر کردن تبلیغات نصب برنامه

فیلتر کردن تبلیغات نصب برنامه به شما کمک می کند تا تبلیغات نصب را برای برنامه هایی که قبلاً روی دستگاه نصب شده اند فیلتر کنید.

اولین گام در این فرآیند این است که مشخص کنیم کدام تبلیغ‌کنندگان توانایی فیلتر کردن بسته نصب شده را دارند. این باید در برنامه‌ای که می‌خواهید با یک تبلیغ هدف قرار دهید اتفاق بیفتد.

کاتلین

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

جاوا

//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 خود را با اطلاعاتی در مورد تبلیغات مرتبط با برنامه هایی که می خواهند فیلتر کنند، مقداردهی اولیه کند:

کاتلین

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

جاوا

// 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 ارسال شود:

کاتلین

// 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()

جاوا

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

فیلتر درب فرکانس

فیلتر کردن درب فرکانس به متخصصان تبلیغات امکان می دهد تعداد دفعات نمایش یک تبلیغ را محدود کنند. فیلتر کردن درب فرکانس نوردهی بیش از حد تبلیغات را کاهش می‌دهد و انتخاب تبلیغات جایگزین را برای یک کمپین تبلیغاتی خاص بهینه می‌کند.

دو جزء اصلی فیلتر درب فرکانس وجود دارد: نوع رویداد تبلیغاتی و کلید شمارنده تبلیغات. انواع رویدادهای تبلیغاتی موجود که می توانند استفاده شوند عبارتند از:

  • برنده شدن : یک رویداد برنده نشان می دهد که آگهی برنده یک حراج شده است. رویدادهای Win به‌طور خودکار توسط Protected Audience API به‌روزرسانی می‌شوند و برنامه‌نویس نمی‌تواند مستقیماً آنها را فراخوانی کند. داده‌های Win فقط برای تبلیغات در یک مخاطب خاص قابل مشاهده است.
  • Impression : جدا از reportImpression ، تماس گیرنده روی دستگاه (SSP یا MMP) از updateAdCounterHistogram() برای فراخوانی رویدادهای impression در نقطه کدی که انتخاب می کند استفاده می کند. رویدادهای Impression برای همه تبلیغات متعلق به یک DSP مشخص قابل مشاهده است و محدود به تبلیغات در همان مخاطبان سفارشی نیست.
  • نمایش : رویداد توسط تماس گیرنده روی دستگاه (SSP یا MMP) در نقطه ای از کد که با استفاده از فراخوانی برای updateAdCounterHistogram() انتخاب می کند، فراخوانی می شود. مشاهده رویدادها برای همه تبلیغات متعلق به یک DSP مشخص قابل مشاهده است و به تبلیغات در همان مخاطب سفارشی محدود نمی شود.
  • کلیک کنید : رویداد توسط تماس گیرنده روی دستگاه (SSP یا MMP) در نقطه ای از کد که با استفاده از فراخوانی برای updateAdCounterHistogram() انتخاب می کند، فراخوانی می شود. رویدادهای کلیک برای همه تبلیغات متعلق به یک DSP مشخص قابل مشاهده است و به تبلیغات در همان مخاطبان سفارشی محدود نمی شود.

در برنامه ناشر، یک SSP یا MMP که در دستگاه حضور دارد رویدادهای تبلیغاتی را فراخوانی می کند. هنگامی که updateAdCounterHistogram() فراخوانی می شود، شمارنده فیلتر درب فرکانس افزایش می یابد تا مزایده های آینده اطلاعات به روزی در مورد مواجهه کاربر با یک تبلیغ خاص داشته باشند. انواع رویدادهای تبلیغاتی به اجبار به عملکرد کاربر مربوطه گره نمی‌خورند و دستورالعمل‌هایی هستند که به تماس‌گیرندگان کمک می‌کنند تا سیستم رویداد خود را ساختار دهند. برای افزایش شمارنده آگهی در زمان یک رویداد، بازیگر روی دستگاه شناسه انتخاب آگهی مزایده آگهی برنده را ارائه می‌کند.

کلیدهای شمارنده آگهی، اعداد صحیح امضا شده 32 بیتی هستند که توسط فناوری تبلیغاتی خریدار تخصیص داده شده‌اند، و مطابق با مجموعه‌ای از تبلیغات هستند که توسط DSP تعریف شده است. از آنجایی که کلیدهای شمارنده تبلیغات فقط به تبلیغاتی محدود می‌شوند که به یک DSP معین تعلق دارند، این کلیدها را می‌توان بدون همپوشانی با هیستوگرام‌های یک فناوری تبلیغاتی دیگر انتخاب کرد. کلیدهای شمارنده تبلیغات برای افزایش شناسه‌های خاص DSP در تبلیغات DSP یا در یک مخاطب سفارشی خاص برای فیلتر کردن تبلیغات از حراج‌های آینده استفاده می‌شوند.

از کلیدهای شمارنده می توان برای اولویت بندی تبلیغاتی استفاده کرد که بر اساس تعامل آنها با سایر تبلیغات از یک فناوری تبلیغاتی خریدار خاص، برای یک کاربر خاص جالب تر هستند. به عنوان مثال، تبلیغی که سطح بالایی از تعامل را از برنده مزایده ها، بازدیدها و کلیک ها دریافت کرده است، یک نقطه داده استنباط شده را نشان می دهد. برای نشان دادن بیشتر این نکته: یک تبلیغ برای چوب گلف چپ دست ممکن است نشان دهد که کاربر علاقه ای به چپ دست ها ندارد. یک فیلتر درپوش فرکانس تنظیم شده برای یک کلید شمارنده که به تبلیغات چپ دست اختصاص داده شده است، می تواند تبلیغات باشگاه های راست دست را فیلتر کند.

برای استفاده از محدودیت فرکانس در حراج خود، ابتدا باید اشیاء KeyedFrequencyCap مطابق شکل زیر ایجاد کنید:

کاتلین

// 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()

جاوا

// 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 منتقل کنید.

کاتلین

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

جاوا

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

هنگامی که شیء AdFilters با فیلترهای درب فرکانس پر می شود، می توان آن را در هنگام ایجاد مخاطب سفارشی به آن منتقل کرد:

کاتلین

// 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()

جاوا

// 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 می تواند رویدادهای کلیک، مشاهده یا نمایش لازم را فراخوانی کند.

کاتلین

val callerAdTech: AdTechIdentifier = mAdSelectionConfig.getSeller()

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

جاوا

AdTechIdentifier callerAdTech = mAdSelectionConfig.getSeller();

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

تبلیغاتی که به محدودیت های فیلتر فرکانس از پیش تعیین شده خود رسیده اند، از حراج فیلتر می شوند. فیلتر کردن قبل از اجرای منطق مناقصه برای مزایده‌های روی دستگاه انجام می‌شود، و از آنجایی که بار برای مزایده‌های خدمات مزایده و مزایده ایجاد می‌شود. این جعبه ابزار به فناوری‌های تبلیغات انعطاف‌پذیری می‌دهد تا از تعاملات بین کاربران و تبلیغات درون مخاطبان سفارشی خود برای متمرکز کردن تبلیغات استفاده کنند. هدف گذاری در حالی که نوردهی بیش از حد تبلیغات را به حداقل می رساند.

فیلتر کردن تبلیغات متنی بدون تماس شبکه

اگر تقاضای بازاریابی مجدد در دستگاه وجود ندارد، می توانید انتخاب آگهی را برای تبلیغات متنی بدون تماس شبکه اجرا کنید. با URI های از پیش ساخته شده و لیستی از تبلیغات متنی با پیشنهاد، این پلتفرم می تواند از بازیابی منطق مناقصه، سیگنال های مناقصه و سیگنال های امتیازدهی صرف نظر کند. این پلتفرم از یک URI از پیش ساخته شده برای انتخاب آگهی متنی با بالاترین پیشنهاد استفاده می کند.

برای بهبود تأخیر، فناوری‌های تبلیغاتی می‌توانند یک جریان انتخاب آگهی را اجرا کنند که فقط شامل تبلیغات متنی با قابلیت فیلتر کردن آگهی بدون تماس شبکه است. این با استفاده از URI های از پیش ساخته شده برای امتیاز دهی سیگنال ها به دست می آید. برای لیستی از پیاده سازی های scoreAds ، به بخش موارد استفاده و نام های URI از پیش ساخته شده پشتیبانی شده مراجعه کنید.

برای اجرای انتخاب آگهی بدون تماس شبکه:

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

هنگام استفاده از URI های از پیش ساخته شده، جاوا اسکریپت گزارشی خود را اجرا کنید

امروزه، پلتفرم Privacy Sandbox تنها دارای یک پیاده‌سازی اولیه جاوا اسکریپت گزارش‌دهی برای URI‌های از پیش ساخته شده است. اگر می‌خواهید جاوا اسکریپت گزارش‌دهی خود را اجرا کنید در حالی که هنوز از 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);
    

میانجی گری آبشار را اجرا کنید

میانجیگری Waterfall به چندین SDK شخص ثالث (شبکه های 3P) نیاز دارد که توسط یک شبکه میانجی SDK شخص اول هماهنگ شوند. میانجی گری آبشار صرف نظر از اینکه مزایده روی دستگاه انجام شده باشد یا در خدمات Bidding & Auction (B&A) انجام شود، به همین ترتیب انجام می شود.

شبکه های 3P

شبکه های 3P باید یک آداپتور فراهم کنند که به شبکه میانجی اجازه می دهد تا روش های لازم را برای اجرای حراج فراخوانی کند:

  • انتخاب آگهی را اجرا کنید
  • گزارش برداشت ها

در اینجا نمونه ای از آداپتور شبکه میانجی آورده شده است:

کاتلین

class NetworkAdaptor {
    private val adSelectionManager : AdSelectionManager

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

    fun selectAds() {...}

    fun reportImpressions() {...}
}

جاوا

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 برای گزارش‌گیری.

شبکه میانجیگری

مشابه شبکه‌های 3P، شبکه‌های میانجی به اجرای selectAds و reportImpression نیاز دارند. برای اطلاعات بیشتر به بخش نحوه اجرای انتخاب آگهی و نحوه گزارش نمایش تبلیغات مراجعه کنید.

شبکه های میانجی مسئولیت اجرای زنجیره میانجیگری و قرار دادن خود در زنجیره میانجیگری را بر عهده دارند. بخش بعدی نحوه راه اندازی و اجرای این فرآیند را پوشش می دهد.

بازیابی زنجیره میانجیگری و طبقات پیشنهادی

شبکه میانجی مسئولیت بازیابی آگهی‌های متنی شخص اول (1P)، زنجیره میانجی‌گری و طبقات پیشنهادی شبکه‌های شخص ثالث (3P) را بر عهده دارد. این می تواند در یک درخواست برای بازیابی تبلیغات متنی اجرا شده توسط شبکه میانجی اتفاق بیفتد. زنجیره میانجی نحوه تکرار از طریق شبکه‌های 3P را تعیین می‌کند و طبقات پیشنهادی را می‌توان به عنوان adSelectionSignals به فرآیند حراج منتقل کرد.

قرارگیری شبکه در زنجیره میانجیگری

یک SDK میانجی می‌تواند خود را در زنجیره میانجی‌گری بر اساس eCPM زنده پیشنهادهای تبلیغاتی 1P قرار دهد. در Protected Audience API، پیشنهادات تبلیغاتی غیرشفاف هستند. یک SDK میانجی باید از AdSelectionFromOutcomesConfig استفاده کند تا بتواند پیشنهاد یک آگهی 1P معین را با طبقه پیشنهادی شبکه 3P بعدی در زنجیره مقایسه کند. اگر پیشنهاد 1P بالاتر از کف قیمت باشد، این بدان معناست که SDK میانجی در مقابل آن شبکه 3P قرار می گیرد.

انتخاب آگهی را اجرا کنید

برای بازیابی یک نامزد تبلیغات 1P، شبکه میانجی می‌تواند یک حراج روی دستگاه را به دنبال مراحل بخش انتخاب آگهی اجرا اجرا کند. این یک نامزد تبلیغ 1P، یک پیشنهاد قیمت و یک AdSelectionId ایجاد می کند که در فرآیند میانجیگری استفاده می شود.

یک AdSelectionFromOutcomesConfig ایجاد کنید

یک AdSelectionFromOutcomesConfig به شبکه میانجی اجازه می‌دهد تا فهرستی از AdSelectionIds (نتایج حراج‌های قبلی)، سیگنال‌های انتخاب آگهی و یک URI را برای واکشی جاوا اسکریپت که یک آگهی را از بین چندین نامزد انتخاب می‌کند، ارسال کند. فهرست AdSelectionIds به همراه پیشنهادات و سیگنال‌های آن‌ها به جاوا اسکریپت منتقل می‌شود که می‌تواند یکی از AdSelectionIds در صورتی که کف قیمت را شکست دهد، یا اگر زنجیره میانجی‌گری ادامه یابد، هیچ کدام را برگرداند.

شبکه‌های میانجی یک AdSelectionFromOutcomesConfig را با استفاده از 1P AdSelectionId از بخش قبل ایجاد می‌کنند و کف پیشنهادی برای شبکه 3P در نظر گرفته می‌شود. یک AdSelectionFromOutcomesConfig جدید باید برای هر مرحله در زنجیره میانجی ایجاد شود.

کاتلین

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

جاوا

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() برای واسطه آبشار به یک ورودی AdSelectionFromOutcomesConfig نیاز دارد که در آن باید پارامترهای مورد نیاز زیر را مشخص کنید:

  • فروشنده : شناسه شبکه تبلیغات فروشنده که انتخاب آگهی را آغاز می کند.
  • AdSelectionIds : یک لیست تکی از selectAds() قبلی که برای یک تبلیغ 1P اجرا می شود.
  • سیگنال‌های انتخاب آگهی : یک شی JSON، به صورت رشته‌ای، حاوی سیگنال‌هایی برای استفاده توسط منطق پیشنهاد خریدار. در این مورد، کف پیشنهادی بازیابی شده برای شبکه 3P داده شده را درج کنید.
  • Selection Logic URI : یک نشانی وب HTTPS که در حین انتخاب تبلیغ برای واکشی جاوا اسکریپت شبکه میانجی برای انتخاب یک تبلیغ برنده درخواست شده است. امضاهای تابع مورد نیاز را در این جاوا اسکریپت مشاهده کنید. جاوا اسکریپت باید تبلیغ 3P را برگرداند اگر قیمت پیشنهادی بالاتر از سطح قیمت پیشنهادی باشد، یا در غیر این صورت null برگرداند. این به SDK واسطه‌ای اجازه می‌دهد تا زنجیره میانجی‌گری را وقتی برنده پیدا شد، کوتاه کند.

با ایجاد AdSelectionOutcomesConfig ، متد selectAds() شبکه 3P را که اولین بار در زنجیره قرار دارد فراخوانی کنید.

کاتلین

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)

جاوا

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

وساطت آبشار ارکستر

در زیر ترتیب عملیات برای اجرای فرآیند میانجیگری آمده است.

  1. انتخاب آگهی 1P را اجرا کنید.
  2. در زنجیره میانجی تکرار کنید. برای هر شبکه 3P موارد زیر را انجام دهید:
    1. ایجاد AdSelectionFromOutcomeConfig شامل 1P outcomeId و کف پیشنهادی SDK 3P.
    2. selectAds() با پیکربندی مرحله قبل فراخوانی کنید.
    3. اگر نتیجه خالی نبود، آگهی را برگردانید.
    4. متد selectAds() آداپتور شبکه SDK فعلی را فراخوانی کنید. اگر نتیجه خالی نبود، آگهی را برگردانید.
  3. اگر هیچ برنده ای از زنجیره پیدا نشد، تبلیغ 1P را برگردانید.

کاتلین

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

جاوا

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 مجرد هستید که حراجی را اجرا می کند، این بخش را دنبال کنید. اگر می‌خواهید میانجی‌گری آبشار را پیاده‌سازی کنید، مراحلی را که در بخش گزارش‌گیری میانجی‌گری آبشار یافت می‌شود دنبال کنید.

گزارش برداشت SSP منفرد

پس از انتخاب یک تبلیغ برنده از گردش کار انتخاب آگهی، می‌توانید با متد AdSelectionManager.reportImpression() نمایش را به پلتفرم‌های طرف خرید و فروش شرکت‌کننده گزارش دهید. برای گزارش یک نمایش آگهی:

  1. یک شی AdSelectionManager راه اندازی کنید.
  2. یک شی ReportImpressionRequest با شناسه انتخاب آگهی بسازید.
  3. متد ناهمزمان reportImpression() با شی ReportImpressionRequest و اشیاء Executor و OutcomeReceiver مربوطه فراخوانی کنید.

جاوا

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

کاتلین

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 استفاده می کند.

  • فراخوانی onResult() نشان می‌دهد که آیا URLهای گزارش‌دهنده impression ایجاد شده‌اند و درخواست زمان‌بندی شده است.
  • فراخوانی onError() شرایط احتمالی زیر را نشان می دهد:
    • اگر تماس با یک آرگومان ورودی نامعتبر مقداردهی اولیه شود، AdServicesException یک IllegalArgumentException را به عنوان علت نشان می دهد.
    • همه خطاهای دیگر AdServicesException با یک IllegalStateException به عنوان علت دریافت می کنند.

گزارش برداشت میانجی آبشار

یک SDK میانجی باید SDK برنده را ردیابی کند تا جریان گزارش آن را فعال کند. SDKهای شرکت کننده در یک زنجیره میانجی باید روشی را برای میانجی فراهم کنند تا بتواند جریان گزارش خود را راه اندازی کند. یک SDK که در یک حراج میانجی شرکت می‌کند، می‌تواند مراحل بالا را برای پیاده‌سازی گزارش‌های خود دنبال کند.

SSP ها می توانند از این نمونه کد 3P SDK به عنوان نمونه اولیه برای نحوه پیوستن به جریان های میانجی استفاده کنند:

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

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

نقاط پایانی گزارش گیری

API impression گزارش درخواست‌های HTTPS GET را به نقاط پایانی ارائه‌شده توسط پلتفرم سمت فروش و پلتفرم سمت خرید برنده ارسال می‌کند:

نقطه پایانی پلت فرم سمت خرید:

  • API از URL منطقی Bidding مشخص شده در مخاطبان سفارشی برای واکشی جاوا اسکریپت ارائه شده توسط خریدار استفاده می کند که شامل منطق برای بازگرداندن URL گزارش نمایش است.
  • تابع جاوا اسکریپت reportWin() را فراخوانی کنید، که انتظار می‌رود نشانی اینترنتی گزارش تصویری خریدار را برگرداند.

نقطه پایان پلت فرم سمت فروش:

  • از URL منطقی تصمیم مشخص شده در شی AdSelectionConfig برای واکشی جاوا اسکریپت منطق تصمیم فروشنده استفاده کنید.
  • تابع جاوا اسکریپت reportResult() فراخوانی کنید، که انتظار می‌رود نشانی اینترنتی گزارش‌دهی نمایشی فروشنده را برگرداند.

گزارش خدمات مناقصه و مزایده

حراجی که در سرویس‌های Bidding & Auction اجرا می‌شود، تمام اطلاعات گزارش‌دهی لازم، از جمله نشانی‌های اینترنتی تولید شده برای گزارش تعامل با تبلیغات را خواهد داشت که در پاسخ رمزگذاری‌شده از حراج سمت سرور گنجانده شده است. هنگامی که پاسخ رمزگشایی می شود، URL های مناسب در پلتفرم ثبت می شوند، بنابراین گزارش تبلیغات و نمایش از همان مراحل ذکر شده در بالا پیروی می کند.

بهترین تلاش گزارش گیری

متد reportImpression() برای ارائه بهترین تلاش برای تکمیل گزارش طراحی شده است.

گزارش تعاملات تبلیغاتی

مخاطب محافظت شده پشتیبانی می‌کند تا تعاملات دقیق‌تری را برای یک آگهی رندر شده گزارش دهد. این می تواند شامل تعاملاتی مانند زمان مشاهده، کلیک ها، شناورها یا هر معیار مفید دیگری باشد که می توان جمع آوری کرد. فرآیند دریافت این گزارش ها به دو مرحله نیاز دارد. ابتدا، خریداران و فروشندگان باید برای دریافت این گزارش ها در جاوا اسکریپت گزارش خود ثبت نام کنند. سپس، مشتری باید این رویدادها را گزارش کند.

ثبت نام برای دریافت رویدادهای تعاملی

ثبت نام برای رویدادهای تعامل در توابع جاوا اسکریپت reportWin() خریدار و reportResult() فروشنده با استفاده از یک تابع جاوا اسکریپت ارائه شده توسط پلتفرم انجام می شود: registerAdBeacon . برای ثبت نام برای دریافت گزارش رویداد، به سادگی با پلتفرم تابع جاوا اسکریپت از جاوا اسکریپت گزارشی خود تماس بگیرید. قطعه زیر از reportWin() خریدار استفاده می کند، اما همین رویکرد برای reportResult() نیز اعمال می شود.

reportWin(
  adSelectionSignals,
  perBuyerSignals,
  signalsForBuyer,
  contextualSignals,
  customAudienceSignals) {
    ...
    // Calculate reportingUri, clickUri, viewUri, and hoverUri

    registerAdBeacon({"click": clickUri, "view": viewUri, "hover": hoverUri});

    return reportingUri;
}

گزارش رویدادهای تعامل

پس از گزارش یک نمایش، مشتریان می‌توانند با متد 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 که قبلاً بازگردانده شده است.
  • کلید تعامل : یک کلید رشته ای که توسط مشتری تعریف می شود و عمل گزارش شده را توصیف می کند. این باید با کلیدی مطابقت داشته باشد که توسط فروشنده یا خریدار در عملکردهای جاوا اسکریپت گزارش ثبت شده است.
  • داده‌های تعامل : رشته‌ای حاوی داده‌هایی که باید در گزارش رویداد گنجانده شود تا به سرورهای گزارش‌دهی ارسال شود.
  • مقاصد گزارش : یک ماسک بیتی که مشخص می کند آیا رویدادها باید به خریدار، فروشنده یا هر دو گزارش شوند. این پرچم ها توسط پلت فرم ارائه می شوند و می توان ماسک مقصد نهایی را با استفاده از عملیات بیتی ایجاد کرد. برای گزارش به یک مقصد، می توانید از پرچم ارائه شده توسط پلت فرم به طور مستقیم استفاده کنید. برای گزارش دهی به مقصدهای متعدد، می توانید از OR ( | ) بیتی برای ترکیب مقادیر پرچم استفاده کنید.

متد ناهمزمان reportInteraction() از شی OutcomeReceiver برای سیگنال دادن به نتیجه فراخوانی API استفاده می کند.

  • فراخوانی onResult() نشان می‌دهد که تماس تعاملی گزارش معتبر است.
  • فراخوانی onError() شرایط احتمالی زیر را نشان می دهد:
    • اگر تماس زمانی برقرار شود که برنامه در پس‌زمینه اجرا می‌شود، یک IllegalStateException با شرح خرابی برگردانده می‌شود.
    • اگر کلاینت از فراخوانی reportInteraction() محروم شود، یک LimitExceededException برمی گردد.
    • اگر بسته برای فراخوانی APIهای حفظ حریم خصوصی ثبت نام نکرده باشد، یک SecurityException() برگردانده می شود.
    • اگر تعاملات گزارش برنامه با برنامه ای که selectAds() نامیده می شود متفاوت باشد، یک IllegalStateException برگردانده می شود.
  • اگر کاربر با فعال کردن APIهای Privacy Sandbox موافقت نکرده باشد، تماس بی‌صدا انجام نمی‌شود.

نقاط پایانی گزارش تعامل

API تعامل گزارش درخواست‌های HTTPS POST را به نقاط پایانی ارائه شده توسط پلتفرم سمت فروش و پلتفرم سمت خرید برنده ارسال می‌کند. مخاطب محافظت شده کلیدهای تعامل را با URI های اعلام شده در گزارش جاوا اسکریپت مطابقت می دهد و برای هر تعاملی که گزارش می شود یک درخواست POST برای هر نقطه پایانی صادر می کند. نوع محتوای درخواست متن ساده است که بدنه آن داده های تعامل است.

بهترین تلاش گزارش تعامل

reportInteraction() برای ارائه بهترین تلاش از گزارش از طریق HTTP Post طراحی شده است.

به روزرسانی پس زمینه روزانه

هنگام ایجاد مخاطب سفارشی ، برنامه یا SDK شما می تواند ابرداده مخاطبان سفارشی را آغاز کند. علاوه بر این ، این پلتفرم می تواند بخش های زیر از ابرداده مخاطبان سفارشی را با یک فرآیند به روزرسانی پس زمینه روزانه به روز کند.

  • سیگنال های مناقصه کاربر
  • داده های پیشنهادی قابل اعتماد
  • لیست AdData

این فرآیند در برابر URL به روزرسانی روزانه تعریف شده در مخاطبان سفارشی و URL ممکن است پاسخ JSON را بازگرداند.

  • پاسخ JSON ممکن است شامل هر یک از قسمتهای ابرداده پشتیبانی شده باشد که باید به روز شوند.
  • هر زمینه JSON به طور مستقل تأیید می شود. مشتری از هر زمینه ناقص که منجر به به روزرسانی در آن قسمت خاص در پاسخ می شود ، نادیده می گیرد.
  • پاسخ HTTP خالی یا یک شیء JSON خالی " {} " منجر به به روزرسانی ابرداده نمی شود.
  • اندازه پیام پاسخ باید به 10 کیلوبایت محدود شود.
  • تمام 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 با ارائه دهنده خریدار از URL منطق مناقصه مشخص شده در مخاطبان سفارشی گرفته شده است. جاوا اسکریپت برگشتی باید شامل توابع زیر باشد:

JavaScript با ارائه دهنده فروشنده از URL منطق تصمیم گیری شده در پارامتر AdSelectionConfig برای API انتخاب آگهی گرفته شده است. جاوا اسکریپت برگشتی باید شامل توابع زیر باشد:

تولید ()

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 زمان فعال سازی و انقضاء مخاطبان سفارشی است که از زمان دوره یونیکس به عنوان ثانیه بیان شده است
    • ca_user_bidding_signals یک رشته JSON است که در قسمت userBiddingSignals از CustomAudience در زمان ایجاد مشخص شده است
    • trusted_bidding_signals, contextual_signals و user_signals اشیاء JSON هستند. آنها به عنوان اشیاء خالی منتقل می شوند و در نسخه های بعدی پر می شوند. قالب آنها توسط این پلتفرم اجرا نمی شود و توسط فناوری تبلیغاتی اداره می شود.

نتیجه:

  • ad : آیا تبلیغی که پیشنهاد به آن اشاره دارد. این اسکریپت مجاز است نسخه ای از تبلیغی را که با ابرداده های مختلف دریافت کرده است ، بازگرداند. انتظار می رود خاصیت render_url تبلیغات بدون تغییر باشد.
  • bid : یک مقدار شناور که مقدار پیشنهاد این تبلیغ را نشان می دهد
  • status : یک مقدار عدد صحیح که می تواند باشد:
    • 0 : برای یک اعدام موفق
    • 1 : (یا هر مقدار غیر صفر) در صورت نامعتبر بودن هر یک از سیگنال های ورودی. در صورت بازگشت مقدار غیر صفر توسط تولید-پیشنهاد ، روند مناقصه برای همه تبلیغات CA باطل می شود

نقص ()

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 از پارامتر API sellerSignals AdSelectionConfig خوانده شده

  • 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(
  beacons
)

پارامترهای ورودی :

  • beacons : یک شیء حاوی جفت ارزش کلیدی کلیدهای تعامل و گزارش URI. قالب این است:

    let beacons = {
      'interaction_key': 'reporting_uri',
      'interaction_key': 'reporting_uri',
      ...
    }
    
    • interaction_key : رشته ای که نمایانگر این رویداد است. این مورد بعداً هنگام گزارش تعامل رویداد توسط این پلتفرم استفاده می شود تا reporting_uri که باید به آنها اطلاع داده شود ، جستجو کنید. این کلید باید بین آنچه خریدار یا فروشنده ثبت می کند مطابقت داشته باشد و فروشنده گزارش می دهد.
    • reporting_uri : URI برای دریافت گزارش های رویداد. این باید مخصوص نوع رویداد گزارش شده باشد. این باید یک درخواست پست را برای رسیدگی به هرگونه داده گزارش شده به همراه این رویداد بپذیرد.

    به عنوان مثال:

      let beacons = {
        'click': 'https://reporting.example.com/click_event',
        'view': 'https://reporting.example.com/view_event'
      }
    

انتخاب تبلیغات از پیش ساخته شده

URI های پیش ساخته به فناوری های تبلیغاتی امکان تعیین توابع JavaScript را برای منطق تصمیم گیری در انتخاب AD در کلاسهای AdSelectionConfig و AdSelectionFromOutcomesConfig می دهند. URI های پیش ساخته برای بارگیری JavaScript مربوطه نیازی به تماس های شبکه ندارند. فناوری های تبلیغاتی می توانند بدون نیاز به تنظیم دامنه ثبت نام شده برای میزبانی جاوا اسکریپت از URI های از پیش ساخته استفاده کنند.

URI از پیش ساخته با استفاده از قالب زیر ساخته می شود:

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

پلت فرم Sandbox Privacy Platem با استفاده از اطلاعات این URI در زمان اجرا ، JavaScript را ارائه می دهد.

اگر IllegalArgumentException

  • هر یک از پارامترهای مورد نیاز در URI وجود ندارد
  • پارامترهای ناشناخته در URI وجود دارد

موارد و نام های URI از پیش ساخته پشتیبانی شده

از مورد 1: انتخاب تبلیغات استفاده کنید

URI های پیش ساخته تحت مورد استفاده از ad-selection در جریان selectAds(AdSelectionConfig) پشتیبانی می شوند.

نام 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 URI 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`

تست کردن

برای کمک به شما در شروع کار با API مخاطبان محافظت شده ، ما برنامه های نمونه را در کوتلین و جاوا ایجاد کرده ایم که می توانید در GitHub پیدا کنید.

پیش نیازها

API مخاطبان محافظت شده در هنگام انتخاب AD و گزارش تصور ، به JavaScript نیاز دارد. دو روش ارائه این جاوا اسکریپت در یک محیط آزمایش وجود دارد:

  • سرور را با نقاط پایانی HTTPS مورد نیاز اجرا کنید که JavaScript را برمی گرداند
  • با تهیه کد لازم از یک منبع محلی ، واکشی از راه دور را نادیده بگیرید

در هر دو رویکرد برای تنظیم گزارش تصور نیاز به تنظیم نقطه پایانی HTTPS دارد.

نقاط پایانی HTTPS

برای آزمایش انتخاب تبلیغات و گزارش تصور ، باید 7 نقطه پایانی HTTPS را تنظیم کنید که دستگاه تست یا شبیه ساز شما می تواند به آن دسترسی پیدا کند:

  1. نقطه پایانی خریدار که در خدمت منطق مناقصه جاوا اسکریپت است.
  2. نقطه پایانی که در خدمت سیگنال های مناقصه است.
  3. نقطه پایانی فروشنده که در خدمت منطق تصمیم گیری جاوا اسکریپت است.
  4. نقطه پایانی که در خدمت سیگنال های به ثمر رساندن است.
  5. برنده شدن در مورد تصور خریدار ، نقطه پایانی.
  6. گزارش فروشنده فروشنده نقطه پایانی.
  7. نقطه پایانی برای ارائه به روزرسانی های روزانه برای مخاطبان سفارشی.

برای راحتی ، repo github کد اساسی جاوا اسکریپت را برای اهداف آزمایش ارائه می دهد. این همچنین شامل تعاریف سرویس OpenAPI است که می تواند به یک پلت فرم پشتیبانی شده یا MicroService پشتیبانی شود. برای اطلاعات بیشتر ، به پروژه readme مراجعه کنید.

واکشی از راه دور جاوا اسکریپت را نادیده بگیرید

این ویژگی در نظر گرفته شده است که برای آزمایش پایان به پایان استفاده شود. برای نادیده گرفتن واکشی از راه دور ، برنامه شما باید در حالت اشکال زدایی با گزینه های توسعه دهنده فعال شود.

برای فعال کردن حالت اشکال زدایی برای برنامه خود ، خط زیر را به ویژگی برنامه در AndroidManifest.xml خود اضافه کنید:

<application
  android:debuggable="true">

برای نمونه ای از نحوه استفاده از این Overrides ، لطفاً به برنامه API API مخاطبان محافظت شده در GitHub مراجعه کنید.

شما باید JavaScript سفارشی خود را برای رسیدگی به روالهای انتخاب آگهی مانند مناقصه ، تصمیمات به ثمر رساندن و گزارش دهی اضافه کنید. می توانید نمونه های اساسی کد JavaScript را پیدا کنید که تمام درخواست های مورد نیاز را در repo github انجام می دهد. برنامه نمونه API مخاطبان محافظت شده نحوه خواندن کد از آن پرونده را نشان می دهد و آن را برای استفاده به عنوان نادیده گرفتن آماده می کند.

می توان به طور مستقل از فروش و خرید جاوا اسکریپت در سمت فروش و خرید و فروش غافلگیر شد ، اگرچه به یک نقطه پایانی HTTPS نیاز دارید تا به هر جاوا اسکریپت که برای آن ارائه نمی دهید ، خدمت کنید. لطفاً برای اطلاعات در مورد نحوه تنظیم سرور این موارد ، به README مراجعه کنید.

فقط می توان از جاوا اسکریپت برای مخاطبان سفارشی که متعلق به بسته شما هستند ، نادیده بگیرید.

جاوا اسکریپت سمت فروش را نادیده بگیرید

برای تنظیم نادیده گرفتن جاوا اسکریپت طرف فروش ، موارد زیر را همانطور که در کد زیر نشان داده شده است انجام دهید:

  1. یک شیء AdSelectionManager اولیه کنید.
  2. از شیء AdSelectionManager به TestAdSelectionManager مراجعه کنید.
  3. یک شیء AdSelectionConfig بسازید.
  4. با استفاده از شیء AdSelectionConfig و یک String که به عنوان جاوا اسکریپت شما قصد استفاده از آن را به عنوان یک نادیده گرفته است ، یک AddAdSelectionOverrideRequest بسازید.
  5. با روش AddAdSelectionOverrideRequest اجرایی مربوطه و Executor مربوطه و اشیاء OutcomeReceiver با روش ناهمزمان overrideAdSelectionConfigRemoteInfo() تماس بگیرید.

کاتلین

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)

جاوا

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 نشان می دهد ، به بخش انتخاب AD مراجعه کنید. تفاوت اصلی این است که DeCtICLOGICURL را می توان به یک مقدار نگهدارنده محلول تنظیم کرد زیرا نادیده گرفته می شود.

به منظور نادیده گرفتن جاوا اسکریپت مورد استفاده در هنگام انتخاب آگهی ، decisionLogicJs باید شامل امضاهای مناسب عملکرد طرف فروشنده باشد. برای نمونه ای از نحوه خواندن یک فایل JavaScript به عنوان یک رشته ، لطفاً به برنامه API API مخاطبان محافظت شده در GitHub مراجعه کنید.

روش ناهمزمان overrideAdSelectionConfigRemoteInfo() از شیء OutcomeReceiver برای نشان دادن نتیجه تماس API استفاده می کند.

onResult() نشان می دهد که نادیده گرفتن با موفقیت اعمال شده است. تماس های آینده به selectAds() از هر تصمیم و منطق گزارش دهی که در آن تصویب کرده اید به عنوان نادیده گرفتن استفاده می کند.

onError() پاسخ به دو شرط ممکن است:

  • اگر با استدلال های نامعتبر تلاش شود ، AdServiceException نشانگر IllegalArgumentException به عنوان علت است.
  • اگر اقدامات ناشایست با برنامه ای که در حالت اشکال زدایی با گزینه های توسعه دهنده فعال نشده است ، تلاش می شود ، AdServiceException نشانگر IllegalStateException است.

بازنشانی طرف فروش

این بخش فرض می کند که شما جاوا اسکریپت طرف فروش را نادیده گرفته اید و به شما اشاره می کنید به TestAdSelectionManager و AdSelectionConfig که در بخش قبلی استفاده شده است.

به منظور بازنشانی بیش از حد برای همه AdSelectionConfigs :

  1. با روش resetAllAdSelectionConfigRemoteOverrides() با استفاده از شیء OutcomeReceiver مربوطه ، با استفاده از روش resteLadeSelectionConfigRemoteOverrides () تماس بگیرید.

کاتلین

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

جاوا

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

پس از تنظیم مجدد طرف فروش ، تماس با selectAds() از هر چیزی که تصمیم گیری در AdSelectionConfig ذخیره می شود برای تلاش برای واکشی جاوا اسکریپت مورد نیاز استفاده کنید.

در صورت عدم موفقیت در تماس با resetAllAdSelectionConfigRemoteOverrides() ، بازپرداخت OutComeReceiver.onError() یک AdServiceException فراهم می کند. اگر حذف Overrides با برنامه ای که در حالت اشکال زدایی با گزینه های توسعه دهنده فعال نشده است ، تلاش می شود ، AdServiceException نشانگر IllegalStateException است.

جاوا اسکریپت سمت خرید را نادیده بگیرید

  1. مراحل پیوستن به مخاطب سفارشی را دنبال کنید
  2. با خریدار و نام مخاطبان سفارشی که می خواهید نادیده بگیرید ، علاوه بر منطق مناقصه و داده هایی که می خواهید از آنها به عنوان نادیده گرفتن استفاده کنید ، یک AddCustomAudienceOverrideRequest بسازید.
  3. با روش AddCustomAudienceOverrideRequest و اجرایی مربوطه و Executor مربوطه و اشیاء OutcomeReceiver با روش ناهمزمان overrideCustomAudienceRemoteInfo() تماس بگیرید

کاتلین

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)

جاوا

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

مقادیر خریدار و نام همان مواردی است که برای ایجاد مخاطب سفارشی استفاده می شود. در مورد این زمینه ها بیشتر بدانید .

علاوه بر این ، می توانید دو پارامتر اضافی را مشخص کنید:

  • biddingLogicJs : JavaScript که منطق خریدار را که در هنگام انتخاب تبلیغ استفاده می شود ، نگه می دارد. امضاهای عملکرد مورد نیاز را در این جاوا اسکریپت مشاهده کنید.
  • trustedBiddingSignals : سیگنال های مناقصه ای که در هنگام انتخاب تبلیغ استفاده می شوند. برای اهداف آزمایش این می تواند یک رشته خالی باشد.

روش ناهمزمان overrideCustomAudienceRemoteInfo() از شیء OutcomeReceiver برای نشان دادن نتیجه تماس API استفاده می کند.

onResult() نشان می دهد که نادیده گرفتن با موفقیت اعمال شده است. تماس های بعدی برای selectAds() از هرگونه منطق مناقصه و گزارش دهی که در آن به عنوان نادیده گرفته شده است استفاده کنید.

onError() پاسخ به دو شرط ممکن است.

  • اگر با استدلال های نامعتبر تلاش شود ، AdServiceException نشانگر IllegalArgumentException به عنوان علت است.
  • اگر اقدامات ناشایست با برنامه ای که در حالت اشکال زدایی با گزینه های توسعه دهنده فعال نشده است ، تلاش می شود ، AdServiceException نشانگر IllegalStateException است.

تنظیم مجدد طرف خرید

در این بخش فرض می شود که شما جاوا اسکریپت سمت خرید را نادیده گرفته اید و به TestCustomAudienceManager که در بخش قبلی استفاده می شود ، اشاره دارید.

برای تنظیم مجدد برای همه مخاطبان سفارشی:

  1. با روش Executor مربوطه و اشیاء OutcomeReceiver با resetAllCustomAudienceOverrides() با مجری مربوطه تماس بگیرید.

کاتلین

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

جاوا

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

پس از تنظیم مجدد طرف خرید ، تماس های بعدی به selectAds() از هر چیزی که biddingLogicUrl و trustedBiddingData در CustomAudience ذخیره می شود ، برای تلاش برای واکشی جاوا اسکریپت مورد نیاز استفاده می شود.

در صورت عدم موفقیت تماس با resetCustomAudienceRemoteInfoOverride() ، بازپرداخت OutComeReceiver.onError() یک AdServiceException فراهم می کند. اگر حذف Overrides با برنامه ای که در حالت اشکال زدایی با گزینه های توسعه دهنده فعال نشده است ، انجام می شود ، AdServiceException نشانگر IllegalStateException است.

سرور گزارشگری را تنظیم کنید

هنگامی که از Overrides Remote Fetching استفاده می کنید ، هنوز هم نیاز به تنظیم سرور دارید که دستگاه یا شبیه ساز شما بتواند برای پاسخ به رویدادهای گزارش دهی به آن برسد. یک نقطه پایانی ساده که 200 باز می گردد برای آزمایش کافی است. Repo GitHub شامل تعاریف سرویس OpenAPI است که می تواند به یک پلت فرم مسخره پشتیبانی شده یا میکروسرویس مستقر شود. برای اطلاعات بیشتر ، به پروژه readme مراجعه کنید.

وقتی به دنبال تعاریف OpenAPI هستید ، به دنبال گزارش دهی-سرور .Json باشید. این پرونده حاوی یک نقطه پایانی ساده است که 200 را باز می گرداند و یک کد پاسخ HTTP را نشان می دهد. این نقطه پایانی در طول selectAds() و سیگنال های API مخاطبان محافظت شده استفاده می شود که گزارشگری را با موفقیت انجام می دهد.

عملکرد برای آزمایش

  • عضویت در ورزش یا ترک و راه اندازی مخاطبان سفارشی بر اساس اقدامات قبلی کاربر.
  • شروع به انتخاب تبلیغات در دستگاه از طریق جاوا اسکریپت ها از راه دور استفاده کنید.
  • مشاهده کنید که چگونه ارتباط یک برنامه با تنظیمات مخاطبان سفارشی ممکن است بر نتایج انتخاب آگهی تأثیر بگذارد.
  • گزارش تصور ورزش پس از انتخاب تبلیغ.

محدودیت ها

در جدول زیر محدودیت هایی برای پردازش API مخاطبان محافظت شده ذکر شده است. محدودیت های ارائه شده می تواند بر اساس بازخورد قابل تغییر باشد. برای قابلیت های در حال پیشرفت ، یادداشت های انتشار را بخوانید.

جزء توصیف محدود مقدار محدود
مخاطبان سفارشی (CA) حداکثر تعداد تبلیغات در هر CA 100
حداکثر تعداد CAS در هر برنامه 1000
حداکثر تعداد برنامه هایی که می توانند یک CA ایجاد کنند 1000
حداکثر تأخیر در زمان فعال سازی یک CA از زمان ایجاد آن 60 روز
حداکثر زمان انقضا یک CA از زمان فعال سازی آن 60 روز
حداکثر تعداد CAS در دستگاه 4000
حداکثر اندازه نام CA 200 بایت
حداکثر اندازه روزانه URI 400 بایت
حداکثر اندازه منطق مناقصه URI 400 بایت
حداکثر اندازه داده های پیشنهادی قابل اعتماد 10 کیلوبایت
حداکثر اندازه سیگنال های مناقصه کاربر 10 کیلوبایت
حداکثر نرخ تماس برای leaveCustomAudience برای هر خریدار 1 در ثانیه
حداکثر میزان تماس برای joinCustomAudience برای هر خریدار 1 در ثانیه
پس زمینه کالیفرنیا مهلت زمانی اتصال 5 ثانیه
HTTP زمان خواندن را بخوانید 30 ثانیه
حداکثر اندازه بارگیری کل 10 کیلوبایت
حداکثر مدت زمان تکرار واکشی 5 دقیقه
حداکثر تعداد CAS در هر کار به روز شده است 1000
انتخاب آگهی حداکثر تعداد خریداران TBD
حداکثر تعداد CAS برای هر خریدار TBD
حداکثر تعداد تبلیغات در حراج TBD
زمان اتصال اولیه 5 ثانیه
اتصال زمان خواندن 5 ثانیه
حداکثر زمان اجرای AdSelection کلی 10 ثانیه
حداکثر زمان اجرای مناقصه در هر CA در AdSelection 5 ثانیه
حداکثر زمان اجرای امتیاز در AdSelection 5 ثانیه
حداکثر زمان اجرای برای هر خریدار در AdSelection TBD
حداکثر اندازه انتخاب آگهی/فروشنده/سیگنال های خریدار TBD
حداکثر اندازه اسکریپت های فروشنده/خریدار TBD
حداکثر نرخ تماس برای selectAds 1 QPS
گزارش تصور حداقل زمان قبل از حذف انتخاب تبلیغات از پایداری 24 ساعت
حداکثر تعداد انتخاب آگهی ذخیره سازی TBD
حداکثر اندازه گزارش url خروجی TBD
حداکثر زمان برای گزارش برداشت TBD
حداکثر تعداد آزمایشات برای تماس های اعلان TBD
پایان زمان اتصال 5 ثانیه
حداکثر زمان اجرای کلی برای reportImpression 2 ثانیه
حداکثر نرخ تماس برای reportImpressions 1 QPS
گزارش رویداد حداکثر تعداد چراغهای خریدار در هر حراج 10

حداکثر تعداد چراغ در هر فروشنده در هر حراج

10

حداکثر اندازه کلید رویداد

40 بایت

حداکثر اندازه داده های رویداد

64 کیلوبایت

تبلیغات حداکثر اندازه لیست تبلیغات 10 KB که توسط Ald AdData در یک CA واحد به اشتراک گذاشته شده است
URL ها حداکثر طول هر رشته URL که به عنوان ورودی گرفته شده است TBD
جاوا اسکریپت حداکثر زمان اجرا 1 ثانیه برای مناقصه و امتیاز دهی برای گزارش برداشت
حداکثر حافظه مورد استفاده 10 مگابایت

گزارش اشکالات و مسائل

بازخورد شما بخش مهمی از ماسهبازی حریم خصوصی در Android است! به ما اطلاع دهید و از هرگونه مسائلی که می یابید یا ایده هایی را برای بهبود ماسهبازی حریم خصوصی در اندروید به ما اطلاع دهید.

{٪ کلمه ٪} {٪ EndverBatim ٪} {٪ کلمه ٪} {٪ EndverBatim ٪} ،

همانطور که از طریق Sandbox حریم خصوصی در مستندات Android خوانده اید ، از دکمه پیش نمایش توسعه دهنده یا Beta برای انتخاب نسخه برنامه ای که با آنها کار می کنید استفاده کنید ، زیرا ممکن است دستورالعمل ها متفاوت باشد.


API مخاطبان محافظت شده در Android (که قبلاً با عنوان Fledge شناخته می شد) شامل API مخاطبان سفارشی و API Selection API است. سیستم عامل های تبلیغاتی و تبلیغ کنندگان می توانند از این API ها برای ارائه تبلیغات سفارشی بر اساس تعامل برنامه قبلی استفاده کنند که به اشتراک گذاری شناسه ها در برنامه ها محدود می شود و به اشتراک گذاری اطلاعات تعامل برنامه کاربر با اشخاص ثالث محدود می شود.

API مخاطبان سفارشی در اطراف انتزاع "مخاطب سفارشی" متمرکز است ، که نمایانگر گروهی از کاربران با اهداف مشترک است. یک تبلیغ کننده می تواند یک کاربر را با مخاطب سفارشی ثبت کرده و تبلیغات مربوطه را با آن مرتبط کند. این اطلاعات به صورت محلی ذخیره می شود و می تواند برای اطلاع رسانی به پیشنهادات تبلیغ کننده ، فیلتر تبلیغات و ارائه تبلیغات استفاده شود.

AD Selection API چارچوبی را فراهم می کند که به چندین توسعه دهنده اجازه می دهد حراج را به صورت محلی برای مخاطبان سفارشی اجرا کنند. برای دستیابی به این هدف ، سیستم تبلیغات مربوطه مرتبط با مخاطب سفارشی را در نظر می گیرد و پردازش اضافی را در تبلیغات انجام می دهد که یک پلت فرم فناوری تبلیغی به دستگاه باز می گردد.

سیستم عامل های AD Tech می توانند این API ها را برای اجرای بازاریابی که باعث حفظ حریم خصوصی کاربر می شود ، ادغام کنند. پشتیبانی از موارد استفاده اضافی ، از جمله تبلیغات نصب برنامه ، برای نسخه های آینده برنامه ریزی شده است. در پیشنهاد طراحی در مورد API مخاطبان محافظت شده در Android بیشتر بدانید.

این راهنما نحوه کار با API مخاطبان محافظت شده در Android را برای انجام موارد زیر شرح می دهد:

  1. مخاطبان سفارشی را مدیریت کنید
  2. انتخاب و اجرای تبلیغ را بر روی یک دستگاه تنظیم و اجرا کنید
  3. گزارش های تبلیغاتی را گزارش دهید

قبل از شروع

قبل از شروع کار ، موارد زیر را تکمیل کنید:

  1. محیط توسعه خود را برای ماسهبازی حریم خصوصی در Android تنظیم کنید .
  2. یا یک تصویر سیستم را بر روی یک دستگاه پشتیبانی شده نصب کنید یا یک شبیه ساز را تنظیم کنید که شامل پشتیبانی از جعبه ماسه حریم خصوصی در Android باشد.
  3. در یک ترمینال ، دسترسی به API مخاطبان محافظت شده (به طور پیش فرض) را با دستور ADB زیر فعال کنید .

      adb shell device_config put adservices ppapi_app_allow_list \"*\"
    
  4. در یک ترمینال ، گزارش Beacon را با دستورات ADB زیر فعال کنید.

     adb shell device_config put adservices fledge_beacon_reporting_metrics_enabled true
     adb shell device_config put adservices fledge_register_ad_beacon_enabled true
    
  5. در برنامه خود یک مجوز ACCESS_ADSERVICES_CUSTOM_AUDIENCE را درج کنید:

      <uses-permission android:name="android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCE" />
    
  6. پیکربندی خدمات تبلیغاتی را در عنصر <application> مانیفست خود ارجاع دهید:

      <property android:name="android.adservices.AD_SERVICES_CONFIG"
                android:resource="@xml/ad_services_config" />
    
  7. خدمات AD Services XML را که در مانیفست خود ارجاع شده است ، مانند res/xml/ad_services_config.xml مشخص کنید. در مورد مجوزهای خدمات تبلیغاتی و کنترل دسترسی SDK بیشتر بدانید .

      <ad-services-config>
        <custom-audiences allowAllToAccess="true" />
      </ad-services-config>
    
  8. به طور پیش فرض ، API Selection AD محدودیت هایی را در حداکثر مقدار حافظه که یک حراج یا اسکریپت گزارش دهنده تصور می تواند اختصاص دهد ، اعمال می کند. ویژگی محدودیت حافظه به WebView نسخه 105.0.5195.58 یا بالاتر نیاز دارد. این پلتفرم یک بررسی نسخه را اجرا می کند و به selectAds فراخوانی می کند و در صورت عدم رضایت ، API های reportImpression شکست می خورند. دو گزینه برای تنظیم این وجود دارد:

    • گزینه 1: دستور ADB زیر را برای غیرفعال کردن این بررسی اجرا کنید:

      adb device_config put fledge_js_isolate_enforce_max_heap_size false
      
    • گزینه 2: WebView Beta را از فروشگاه Google Play نصب کنید. این باید برابر یا بالاتر از نسخه قبلی باشد.

به مخاطبان سفارشی بپیوندید

مخاطب سفارشی گروهی از کاربران با اهداف یا علایق مشترک را که توسط یک برنامه تبلیغ کننده تصمیم گرفته شده است ، نشان می دهد. یک برنامه یا SDK ممکن است از مخاطب سفارشی برای نشان دادن مخاطبان خاص استفاده کند ، مانند کسی که مواردی را در یک سبد خرید ترک کرده است. برای ایجاد یا پیوستن به مخاطب سفارشی به طور غیر همزمان ، موارد زیر را انجام دهید:

  1. شیء CustomAudienceManager را اولیه کنید.
  2. با مشخص کردن پارامترهای کلیدی مانند بسته خریدار و یک نام مربوطه ، یک شی CustomAudience ایجاد کنید. سپس ، شیء JoinCustomAudienceRequest را با شیء CustomAudience آغاز کنید.
  3. با JoinCustomAudienceRequest مجری و Executor مربوطه و اشیاء OutcomeReceiver joinCustomAudience() ناهمزمان تماس بگیرید.

کاتلین

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)

جاوا

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 Logic Logic : URL HTTPS در هنگام انتخاب تبلیغ پرس و جو برای واکشی منطق مناقصه JavaScript خریدار. امضاهای عملکرد مورد نیاز را در این جاوا اسکریپت مشاهده کنید.
  • آگهی رندر شناسه : شناسه دلخواه تنظیم شده توسط فناوری تبلیغات خریدار. این یک بهینه سازی برای تولید بار برای B&A است.

پارامترهای اختیاری برای یک شیء CustomAudience ممکن است شامل موارد زیر باشد:

  • زمان فعال سازی : مخاطب سفارشی فقط می تواند در انتخاب تبلیغات و به روزرسانی های روزانه پس از زمان فعال سازی آن شرکت کند. به عنوان مثال این می تواند برای درگیر کردن کاربران از یک برنامه مفید باشد.
  • زمان انقضا : زمان آینده که پس از آن مخاطبان سفارشی از دستگاه حذف می شوند.
  • سیگنال های مناقصه کاربر : یک رشته JSON حاوی سیگنال های کاربر ، مانند محل مورد نظر کاربر ، که منطق مناقصه خریدار JavaScript برای تولید پیشنهادات در طی فرآیند انتخاب آگهی مصرف می کند. این فرمت به سیستم عامل های تبلیغاتی کمک می کند تا از کد در سیستم عامل ها استفاده مجدد کند و مصرف در توابع JavaScript را کاهش می دهد.
  • داده های مناقصه قابل اعتماد : URL HTTPS و لیستی از رشته های مورد استفاده در فرآیند انتخاب آگهی که سیگنال های مناقصه را از یک سرویس کلید/ارزش قابل اعتماد دریافت می کنند.
  • تبلیغات : لیستی از اشیاء AdData مربوط به تبلیغاتی که در انتخاب تبلیغات شرکت می کنند. هر شی AdData شامل موارد زیر است:
    • URL RENDER : URL HTTPS که برای ارائه تبلیغ نهایی پرسیده می شود.
    • ابرداده : یک شیء JSON به عنوان یک رشته حاوی اطلاعاتی که توسط منطق مناقصه خریدار در طی فرآیند انتخاب آگهی مصرف می شود ، سریال می شود.
    • فیلترهای تبلیغاتی : کلاس که شامل کلیه اطلاعات لازم برای نصب برنامه فیلتر آگهی و پوشش فرکانس در هنگام انتخاب آگهی است.

در اینجا نمونه ای از یک شیء شیء CustomAudience وجود دارد:

کاتلین

// 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()

جاوا

// 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 استفاده می کند.

  • onResult() نشان می دهد مخاطب سفارشی با موفقیت ایجاد شده یا به روز می شود.
  • onError() پاسخ به دو شرط ممکن است.
    • اگر JoinCustomAudienceRequest با استدلال های نامعتبر آغاز شود ، AdServicesException نشانگر IllegalArgumentException به عنوان علت است.
    • همه خطاهای دیگر با استفاده از علت IllegalStateException ، یک AdServicesException را دریافت می کنند.

در اینجا نمونه ای از رسیدگی به نتیجه joinCustomAudience() :

کاتلین

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

جاوا

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. با buyer و name مخاطبان سفارشی ، LeaveCustomAudienceRequest را آغاز کنید. برای کسب اطلاعات بیشتر در مورد این زمینه های ورودی ، " به مخاطب سفارشی بپیوندید " بخوانید.
  3. با روش leaveCustomAudience() ناهمزمان با شیء LeaveCustomAudienceRequest و Executor و اجرایی مربوطه و اشیاء OutcomeReceiver تماس بگیرید.

کاتلین

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)

جاوا

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 را نشان می دهد. برای کمک به محافظت از حریم خصوصی ، نتیجه خطا بین خطاهای داخلی و استدلال های نامعتبر تمایز قائل نیست. پس از اتمام تماس API ، آیا مخاطب سفارشی مطابق با موفقیت حذف می شود ، پاسخ به تماس onResult() فراخوانی می شود.

انتخاب تبلیغات

برای استفاده از API مخاطبان محافظت شده برای انتخاب تبلیغات ، با روش selectAds() تماس بگیرید:

  1. یک شیء AdSelectionManager اولیه کنید.
  2. یک شیء AdSelectionConfig بسازید.
  3. با روش AdSelectionConfig و Executor مربوطه و اشیاء OutcomeReceiver با روش selectAds() ناهمزمان تماس بگیرید.

کاتلین

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
)

جاوا

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 Preduilt : این فرمت انتخاب آگهی Fledge است. در صورت عبور از URI از پیش ساخته نشده یا ناقص ، URI از پیش ساخته نشده یا ناقص ، IllegalArgumentException پرتاب می شود.
  • خریداران مخاطبان سفارشی : لیست کاملی از شناسه ها برای شبکه های تبلیغاتی خریدار که توسط فروشنده مجاز به شرکت در فرآیند انتخاب آگهی هستند. این شناسه های خریدار با CustomAudience.getBuyer() از مخاطبان سفارشی شرکت کننده مطابقت دارند.

پارامترهای زیر را می توان به صورت اختیاری برای انتخاب آگهی سفارشی تر مشخص کرد:

  • سیگنال های انتخاب آگهی : یک شیء JSON ، به عنوان یک رشته ، حاوی سیگنالهایی که توسط منطق مناقصه خریدار استفاده می شود JavaScript که از CustomAudience.getBiddingLogicUrl() استفاده می شود.
  • سیگنال های فروشنده : یک شیء JSON ، به عنوان یک رشته ، حاوی سیگنال های مصرف شده توسط منطق تصمیم گیری جاوا اسکریپت فروشنده از AdSelectionConfig.getDecisionLogicUrl() .
  • سیگنال های خریدار : نقشه اشیاء JSON ، سریال شده به عنوان رشته ها ، حاوی سیگنالهایی که توسط منطق مناقصه خریداران خاص جاوا اسکریپت از CustomAudience.getBiddingLogicUrl() مصرف می شوند ، که توسط زمینه های خریدار شرکت کننده مخاطبان سفارشی مشخص می شوند.
  • Contextual ads: A collection of ad candidates that are collected directly from buyers during an auction that happens outside of a Protected Audience auction.

Once an ad is selected, the results, bids, and signals are persisted internally for reporting. The OutcomeReceiver.onResult() callback returns an AdSelectionOutcome that contains:

  • A render URL for the winning ad, obtained from AdData.getRenderUrl() .
  • An ad selection ID unique to the device user. This ID is used for reporting the ad impression.

If the ad selection can't be completed successfully due to reasons such as invalid arguments, timeouts, or excessive resource consumption, the OutcomeReceiver.onError() callback provides an AdServicesException with the following behaviors:

  • If the ad selection is initiated with invalid arguments, the AdServicesException indicates an IllegalArgumentException as the cause.
  • All other errors receive an AdServicesException with an IllegalStateException as the cause.

تبلیغات متنی

Protected Audience can incorporate contextual ads into a Protected Auction. Contextual ads need to be selected on the ad tech server and returned to the device outside of Protected Audience APIs. Contextual ads can then be included in the auction using the AdSelectionConfig at which point they function the same as on device ads, including eligibility for negative ad filtering. Once the Protected Audience auction has completed, you need to invoke reportImpression() . This calls reportWin() in the winning contextual ad, in the same pattern as impression reporting , to receive the winning ad on a device. Each contextual ad needs a buyer, a bid, a link to reporting logic, a render URL, and ad metadata.

To deploy contextual ads in app, the target app needs to create a ContextualAds object:

کاتلین

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

جاوا

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

The resulting ContextualAds object can then be passed along when creating your AdSelectionConfig :

کاتلین

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

جاوا

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

App install ad filtering

App install ads filtering helps you to filter installation ads for apps that are already installed on a device.

The first step in this process is to define which advertisers have the ability to filter on the installed package. This needs to happen in the app you want to target with an ad.

کاتلین

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

جاوا

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

When the preceding code executes, the advertisers passed in are then able to filter out the installed apps that you specify during their bid generation. If you need to remove an advertiser from having access to this app's install status, run this code again with the advertiser's information removed.

The next step is to set up ad filtering inside the publisher app. The party that serves the ad inside of the publisher app (most likely to be a supply-side SDK) must initialize their AdFilters object with information about which ads related to apps they'd like to filter out:

کاتلین

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

جاوا

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

Demand-side publishers may also set an AdFilter for ads that exist inside of their custom audiences.

AdFilters can also be passed in at the point of instantiating a new AdData object:

کاتلین

// 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()

جاوا

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

Frequency cap filtering

Frequency cap filtering enables ad techs to limit the number of times an ad is shown. Frequency cap filtering reduces ad overexposure and optimizes alternate ad selection for a given ad campaign.

There are two main components of a frequency cap filter: the ad event type, and the ad counter key. The available ad event types that can be used are:

  • Win : A win event indicates that the ad has won an auction. Win events are automatically updated by the Protected Audience API and cannot be called directly by the developer. Win data is only visible to ads within a given custom audience.
  • Impression : Separate from reportImpression , an on-device caller (SSP or MMP) uses updateAdCounterHistogram() to invoke impression events at the point in code they choose. Impression events are visible to all ads belonging to a given DSP, and are not limited to ads in the same custom audience.
  • View : Event is invoked by the on-device caller (SSP or MMP) at a point in code they choose using a call to updateAdCounterHistogram() . View events are visible to all ads belonging to a given DSP and not limited to ads in the same Custom Audience.
  • Click : Event is invoked by the on-device caller (SSP or MMP) at a point in code they choose using a call to updateAdCounterHistogram() . Click events are visible to all ads belonging to a given DSP and not limited to ads in the same Custom Audience.

In the publisher app, an SSP or MMP that has a presence on the device invokes ad events. When updateAdCounterHistogram() is called, the counter of a frequency cap filter is incremented so that future auctions will have up to date information about a user's exposure to a given ad. The ad event types are not forcibly tied to the corresponding user action and are guidelines given to help callers to structure their event system. To increment ad counters at the time of an event, the on-device actor provides the winning ad auction's ad selection ID.

Ad counter keys are arbitrary 32-bit signed integers assigned by a buyer ad tech, and they correspond to a given set of ads as defined by the DSP. Since ad counter keys are limited only to ads that belong to a given DSP, these keys can be selected without overlapping with histograms from another ad tech. Ad counter keys are used to increment DSP-specific identifiers across a DSP's ads or within a given custom audience to filter out ads from future auctions.

Counter keys can be leveraged to prioritize ads that are more likely to be interesting to a given user based on their interactions with other ads from a given buyer ad tech. For example, an ad that has received a high level of engagement from winning ad auctions, views, and clicks, represents an inferred data point. To further illustrate this point: an ad for left handed golf clubs might indicate that the user wouldn't be interested in right handed ones. A frequency cap filter set for a counter key assigned to left-handed ads could filter out ads for right handed clubs.

To use frequency capping in your auction, you must first create KeyedFrequencyCap objects as shown below:

کاتلین

// 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()

جاوا

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

Once the KeyedFrequencyCap objects are created, you can pass them into an AdFilters object.

کاتلین

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

جاوا

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

When the AdFilters object is populated with frequency cap filters, it can be passed along when the custom audience is created:

کاتلین

// 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()

جاوا

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

When frequency cap filters are implemented into a custom audience, the SSP can then invoke the necessary click, view, or impression events.

کاتلین

val callerAdTech: AdTechIdentifier = mAdSelectionConfig.getSeller()

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

جاوا

AdTechIdentifier callerAdTech = mAdSelectionConfig.getSeller();

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

Ads that have hit their pre-set frequency cap filter limits are filtered out of the auction. Filtering happens before the bidding logic is executed for on-device auctions, and as the payload is generating for Bidding & Auction services auctions.This toolkit gives ad techs the flexibility to use the interactions between users and the ads within their custom audiences to focus ad targeting while minimizing ad overexposure.

Contextual ad filtering without network calls

If there is no remarketing demand on the device, you can run ad selection for contextual ads without network calls. With prebuilt URIs and a list of contextual ads with bids, the platform can skip retrieving bidding logic, bidding signals, and scoring signals. The platform uses a prebuilt URI to select the contextual ad with the highest bid.

To improve latency, ad techs can run an ad selection flow that includes only contextual ads with ad filtering functionality without network calls. This is achieved by using prebuilt URIs for scoring signals. Refer to the Supported prebuilt URI use cases and names section for a list of scoreAds implementations.

To run ad selection without network calls:

  1. Set up ad filtering
  2. Create your contextual ads
  3. Create a AdSelectionConfig object with the following:

    1. An empty list of buyers
    2. A prebuilt URI to select the highest bid
    3. تبلیغات متنی
    4. An empty URI for the scoring signals. The empty URI is allowed to indicate that you don't want to use the fetching of trusted signals for scoring:
    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. Run ad selection:

    adSelectionManager.selectAds(
        adSelectionConfig,
        executor,
        outcomeReceiver);
    

Run your own reporting JavaScript while using prebuilt URIs

Today, the Privacy Sandbox platform only has a basic reporting JavaScript implementation available for prebuilt URIs. If you want to run your own reporting JavaScript while still using prebuilt URIs for a low latency ad selection, you can override the DecisionLogicUri between ad selection and reporting runs.

  1. Run steps to run ad selection for contextual ads using prebuilt URIs
  2. Create a copy of your AdSelectionConfig before running reporting

    adSelectionConfigWithYourReportingJS = adSelectionConfig.cloneToBuilder()
      // Replace <urlToFetchYourReportingJS> with your own URL:
      .setDecisionLogicUri(Uri.parse(<urlToFetchYourReportingJS>))
      .build();
    
  3. Run impression reporting

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

Run waterfall mediation

Waterfall mediation requires multiple third party SDKs (3P networks) to be orchestrated by a first party SDK mediation network. Waterfall mediation is done the same way regardless if the auction took place on device or ran on Bidding & Auction services (B&A).

3P networks

3P networks need to provide an adapter that allows the mediation network to invoke the necessary methods for running an auction:

  • Run ad selection
  • Report impressions

Here's an example of a mediation network adapter:

کاتلین

class NetworkAdaptor {
    private val adSelectionManager : AdSelectionManager

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

    fun selectAds() {...}

    fun reportImpressions() {...}
}

جاوا

class NetworkAdaptor {
    AdSelectionManager adSelectionManager;

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

    public void selectAds() {...}

    public void reportImpressions() {...}
}

Each SDK has their own ad selection service managers and clients, and their own selectAds and reportImpressions implementation. SDK providers can refer to the sections on how to run ad selection for on-device auctions or the B&A explainer for B&A auctions. Follow how to report ad impressions (following the single SSP impression reporting for reporting.

Mediation network

Similar to 3P networks, mediation networks need selectAds and reportImpression implementations. Refer to the sections on how to run ad selection and how to report ad impressions for more information.

Mediation networks are responsible for running the mediation chain and placing themselves in the mediation chain. The next section covers how to set up and execute this process.

Retrieve mediation chain and bid floors

The mediation network is responsible for retrieving the first party (1P) contextual ads, mediation chain, and third party networks' bid floors (3P). This can happen in a request to retrieve contextual ads executed by the mediation network. The mediation chain determines how to iterate through the 3P Networks, and the bid floors can be passed to the auction process as adSelectionSignals .

Network placement in the mediation chain

A mediation SDK can place itself in the mediation chain based on their live eCPM of 1P ad bids. In the Protected Audience API, ad bids are opaque. A mediation SDK should use AdSelectionFromOutcomesConfig to be able to compare a given 1P ad's bid to the bid floor of the next 3P network in the chain. If the 1P bid is higher than the bid floor then that means the mediation SDK is placed in front of that 3P network.

Run ad selection

To retrieve a 1P ad candidate, the mediation network can execute an on-device auction following the steps in the run ad selection section. This generates a 1P ad candidate, a bid, and an AdSelectionId that is used in the mediation process.

Create an AdSelectionFromOutcomesConfig

An AdSelectionFromOutcomesConfig allows the mediation network to pass a list of AdSelectionIds (results from previous auctions), ad selection signals, and a URI to fetch JavaScript that selects an ad from multiple candidates. The list of AdSelectionIds along with their bids and the signals are passed to the JavaScript which can return one of the AdSelectionIds if it beats the bid floor, or none if the mediation chain should continued.

Mediation Networks create an AdSelectionFromOutcomesConfig using the 1P AdSelectionId from the previous section, and the bid floor for the 3P Network being considered. A new AdSelectionFromOutcomesConfig should be created for each step in the mediation chain.

کاتلین

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

جاوا

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

The selectAds() method override for waterfall mediation requires an AdSelectionFromOutcomesConfig input, where you must specify the following required parameters:

  • Seller : Identifier for the seller ad network initiating the ad selection.
  • AdSelectionIds : A singleton list of a previous selectAds() run for a 1P ad.
  • Ad selection signals : A JSON object, serialized as a string, containing signals to be used by buyer bidding logic. In this case, include the bid floor retrieved for the given 3P network.
  • Selection Logic URI : An HTTPS URL queried during ad selection to fetch the mediation network's JavaScript for selecting a winning ad. See the required function signatures in this JavaScript. The JavaScript should return the 3P ad if the bid is higher than the bid floor, or otherwise return null . This allows the mediation SDK to truncate the mediation chain when a winner is found.

With the AdSelectionOutcomesConfig created, call the selectAds() method of the 3P network that is first in the chain.

کاتلین

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)

جاوا

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

Orchestrate waterfall mediation

The following is the order of operations for running through the mediation process.

  1. Run 1P ad selection.
  2. Iterate over the mediation chain. For each 3P network, do the following:
    1. Build AdSelectionFromOutcomeConfig including the 1P outcomeId and the 3P SDK's bid floor.
    2. Call selectAds() with the config from the previous step.
    3. If the result is not empty, return the ad.
    4. Call the current SDK network adapter's selectAds() method. If the result is not empty, return the ad.
  3. If no winner is found from the chain, return the 1P ad.

کاتلین

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

جاوا

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) { ... }
}

Report ad impressions

There are two flows for reporting an ad impression depending on how the auction is run. If you are a single SSP running an auction, follow this section. If you are going to implement waterfall mediation, follow the steps found in the waterfall mediation impression reporting section .

Single SSP impression reporting

After a winning ad has been chosen from the ad selection workflow, you can report the impression back to participating buy-side and sell-side platforms with the AdSelectionManager.reportImpression() method. To report an ad impression:

  1. Initialize an AdSelectionManager object.
  2. Build a ReportImpressionRequest object with the ad selection ID.
  3. Call the asynchronous reportImpression() method with the ReportImpressionRequest object and relevant Executor and OutcomeReceiver objects.

جاوا

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

کاتلین

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)

Initialize the ReportImpressionRequest with the following required parameters:

  • Ad selection ID : An ID unique only to a device user that identifies a successful ad selection.
  • Ad selection config : The same configuration used in the selectAds() call identified by the provided ad selection ID.

The asynchronous reportImpression() method uses the OutcomeReceiver object to signal the result of the API call.

  • The onResult() callback indicates if impression reporting URLs have been created and the request has been scheduled.
  • The onError() callback indicates the following possible conditions:
    • If the call is initialized with an invalid input argument, the AdServicesException indicates an IllegalArgumentException as the cause.
    • All other errors receive an AdServicesException with an IllegalStateException as the cause.

Waterfall mediation impression reporting

A mediation SDK needs to keep track of the winning SDK to trigger their reporting flows. The SDKs participating in a mediation chain should provide a method for the mediator to invoke to trigger their own reporting flow. An SDK participating in a mediated auction can follow the steps above to implement their own reporting.

SSPs can use this 3P SDK code example as a prototype for how to join in mediation flows:

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

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

Impression reporting endpoints

The report impression API issues HTTPS GET requests to endpoints provided by the sell-side platform and the winning buy-side platform:

Buy-side platform endpoint:

  • The API uses the Bidding logic URL specified in the custom audience to fetch the buyer-provided JavaScript that includes logic to return an impression reporting URL.
  • Invoke the reportWin() JavaScript function, which is expected to return the buyer's impression reporting URL.

Sell-side platform endpoint:

  • Use the Decision logic URL specified in the AdSelectionConfig object to fetch the seller's decision logic JavaScript.
  • Invoke the reportResult() JavaScript function, which is expected to return the seller's impression reporting URL.

Bidding & Auction services reporting

An auction executed on Bidding & Auction services will have all the necessary reporting information, including generated URLs for ad interaction reporting , included in the encrypted response from the server-side auction. When the response is decrypted, the appropriate URLs are registered with the platform, so ad and impression reporting follows the same steps listed above.

Best effort Impression reporting

The reportImpression() method is designed to offer a best-effort completion of reporting.

Report Ad Interactions

Protected Audience provides support to report on more granular interactions for a rendered ad. This can include interactions such as view time, clicks, hovers, or any other useful metric that can be collected. The process to receive these reports requires two steps. First, buyers and sellers must register to receive these reports in their reporting JavaScript. Then, the client will need to report these events.

Registering to receive interaction events

Registering for interaction events happens in the buyer's reportWin() and seller's reportResult() JavaScript functions using a JavaScript function provided by the platform: registerAdBeacon . To register to receive an event report, simply call the platform JavaScript Function from your reporting JavaScript. The following snippet is using a buyer's reportWin() , but the same approach applies to reportResult() .

reportWin(
  adSelectionSignals,
  perBuyerSignals,
  signalsForBuyer,
  contextualSignals,
  customAudienceSignals) {
    ...
    // Calculate reportingUri, clickUri, viewUri, and hoverUri

    registerAdBeacon({"click": clickUri, "view": viewUri, "hover": hoverUri});

    return reportingUri;
}

Reporting interaction events

After reporting an impression, clients can report the interactions back to previously registered winning buy-side and sell-side platforms with the AdSelectionManager.reportInteraction() method. To report an ad event:

  1. Initialize an AdSelectionManager object.
  2. Build a ReportInteractionRequest object with the ad selection ID, interaction key, interaction data, and reporting destination.
  3. Call the asynchronous reportInteraction() method with the request object and relevant Executor and OutcomeReceiver objects.
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);

Initialize the ReportInteractionRequest with the following required parameters:

  • Ad selection ID : An ad selection ID retrieved from a previously returned AdSelectionOutcome .
  • Interaction Key : A string key defined by the client describing the action being reported. This must match the key that was registered by the seller or buyer in the reporting JavaScript functions.
  • Interaction Data : A string containing data to be included with the event report, to be POSTed back to the reporting servers.
  • Reporting Destinations : A bit mask specifying if the events should be reported to the buyer, seller, or both. These flags are provided by the platform and the final destination mask can be created using bitwise operations. To report to one destination, you can use the flag provided by the platform directly. To report to multiple destinations, you can use the bitwise OR ( | ) to combine flag values.

The asynchronous reportInteraction() method uses the OutcomeReceiver object to signal the result of the API call.

  • The onResult() callback indicates the report interaction call is valid.
  • The onError() callback indicates the following possible conditions:
    • If the call is made when the app is running in the background, an IllegalStateException with a description of the failure is returned.
    • If the client is throttled from calling reportInteraction() , a LimitExceededException is returned.
    • If the package is not enrolled to call the Privacy Preserving APIs, a SecurityException() is returned.
    • If the app reporting interactions is different from the app that called selectAds() , an IllegalStateException is returned.
  • If the user has not consented to enable the Privacy Sandbox APIs, the call will fail silently.

Interaction reporting endpoints

The report interaction API issues HTTPS POST requests to endpoints provided by the sell-side platform and the winning buy-side platform. Protected Audience will match the interaction keys with the URIs declared in reporting JavaScript and issue a POST request to each endpoint for each interaction being reported. The content type of the request is plain text with the body being the Interaction Data.

Best effort Interaction reporting

The reportInteraction() is designed to offer a best-effort completion of reporting through HTTP POST.

Daily background update

When creating a custom audience, your app or SDK can initialize custom audience metadata. Additionally, the platform can update the following pieces of custom audience metadata with a daily background update process.

  • User bidding signals
  • Trusted bidding data
  • AdData list

This process queries against the Daily update URL defined in the custom audience and the URL may return a JSON response.

  • The JSON response may contain any of the supported metadata fields that needs to be updated.
  • Each JSON field is validated independently. The client ignores any malformed fields which results in no updates to that particular field in the response.
  • An empty HTTP response or an empty JSON object " {} " results in no metadata updates.
  • The response message size must be limited to 10 KB.
  • All URIs are required to use HTTPS.
  • trusted_bidding_uri must share the same ETLD+1 as the buyer.

Example: JSON response for background daily update

{
    "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 for ad selection

The ad selection workflow orchestrates the execution of buyer-provided and seller-provided JavaScript.

Buyer-provided JavaScript is fetched from the Bidding logic URL specified in the custom audience. The returned JavaScript should include the following functions:

Seller-provided JavaScript is fetched from the decision logic URL specified in the AdSelectionConfig parameter for the ad selection API. The returned JavaScript should include the following functions:

generateBid()

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 : a JSON object with the format var ad = { 'render_url': url, 'metadata': json_metadata };
  • auction_signals, per_buyer_signals : JSON objects specified in the auction configuration object
  • custom_audience_bidding_signals : JSON object generated by the platform. The format for this JSON object is:

    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 , and name are string taken from the properties with the same name of the Custom Audience participating to the ad selection
    • activation_time and expiration_time are the time of activation and expiration of the custom audience, expressed as seconds since the Unix epoch
    • ca_user_bidding_signals is a JSON string specified in the userBiddingSignals field of the CustomAudience at creation time
    • trusted_bidding_signals, contextual_signals , and user_signals are JSON objects. They are passed as empty objects and will be filled up in future releases. Their format is not enforced by the platform and is managed by the ad tech.

نتیجه:

  • ad : is the ad the bid refers to. The script is allowed to return a copy of the ad it received with different metadata. The render_url property of the ad is expected to be unaltered.
  • bid : a float value representing the bid value for this ad
  • status : an integer value that can be:
    • 0 : for a successful execution
    • 1 : (or any non-zero value) in case any of the input signals is invalid. In case a non-zero value is returned by generate-bid the bidding process is invalidated for all the CA ads

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 : see the generateBid documentation
  • bid : the bid value for the ad
  • ad_selection_config : a JSON object representing the AdSelectionConfig parameter of the selectAds API. قالب این است:

    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 objects read from the sellerSignals AdSelectionConfig API parameter

  • trusted_scoring_signal : read from the adSelectionSignals field in the AdSelectionConfig API parameter

  • contextual_signals, user_signals : JSON objects. They are currently passed as empty objects and will be filled up in future releases. Their format is not enforced by the platform and is managed by the ad tech.

  • per_buyer_signals : JSON object read from the perBuyerSignal map in the AdSelectionConfig API parameter using as key the current Custom Audience buyer. Empty if the map doesn't contain any entry for the given buyer.

خروجی:

  • score : a float value representing the score value for this ad
  • status : an integer value that can be:
    • 0: for a successful execution
    • 1: in case the customAudienceSignals are invalid
    • 2: in case the AdSelectionConfig is invalid
    • 3: in case any of the other signals is invalid
    • Any non-zero value causes the failure of the process, the value determines the type of exception thrown

selectOutcome()

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

پارامترهای ورودی:

  • outcomes : a JSON object {"id": id_string, "bid": bid_double}
  • selection_signals : JSON objects specified in the auction configuration object

خروجی:

  • status : 0 for success, non-zero for failure
  • result : one of the outcomes passed in or null

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 : see the documentation of scoreAds
  • render_url : the render URL of the winning ad
  • bid : the bid offered for the winning ad
  • contextual_signals : see the documentation of generateBid

خروجی:

  • status: 0 for success and non-zero for failure
  • results : a JSON objects containing:
    • signals_for_buyer : a JSON object that is passed to the reportWin function
    • reporting_url : a URL that is used by the platform to notify the impression to the buyer

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 : see the documentation for scoreAd
  • signals_for_buyer : a JSON object returned by reportResult
  • contextual_signals, custom_audience_signals : see the documentation for generateBid

خروجی:

  • status: 0 for success and non-zero for failure
  • results : a JSON object containing:
    • reporting_url : a URL that is used by the platform to notify the impression to the seller

registerAdBeacon()

function registerAdBeacon(
  beacons
)

Input Parameters :

  • beacons : An object containing key-value pairs of interaction keys and reporting URIs. قالب این است:

    let beacons = {
      'interaction_key': 'reporting_uri',
      'interaction_key': 'reporting_uri',
      ...
    }
    
    • interaction_key : A string representing the event. This is used by the platform later when reporting event interactions to look up the reporting_uri that should be notified. This key needs to match between what the buyer or seller is registering, and what the seller is reporting.
    • reporting_uri : A URI to receive event reports. This should be specific to the event type being reported. It must accept a POST request to handle any data reported along with the event.

    به عنوان مثال:

      let beacons = {
        'click': 'https://reporting.example.com/click_event',
        'view': 'https://reporting.example.com/view_event'
      }
    

Ad Selection prebuilt URIs

Prebuilt URIs give ad techs the ability to appoint JavaScript functions for ad selection decision logic in the AdSelectionConfig and AdSelectionFromOutcomesConfig classes. Prebuilt URIs don't require network calls to download the corresponding JavaScript. Ad techs can use prebuilt URIs without having to set up an enrolled domain to host the JavaScript.

A prebuilt URI is constructed using the following format:

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

The Privacy Sandbox platform provides JavaScript using the information from this URI in the runtime.

An IllegalArgumentException is thrown if:

  • any of the required parameters are not present in the URI
  • there are unrecognized parameters in the URI

Supported prebuilt URI use cases and names

Use case 1: ad-selection

Prebuilt URIs under the ad-selection use case are supported in the selectAds(AdSelectionConfig) flow.

Prebuilt URI name: highest-bid-wins

This prebuilt URI provides a JavaScript that picks the ad with the highest bid after bidding. It also provides a basic reporting function to report the winner's render_uri and bid .

Required parameters

reportingUrl : The base reporting URL that is parameterized with the render_uri and the bid of the winning ad:

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

استفاده

If your base reporting URL is https://www.ssp.com/reporting then the prebuilt URI would be:

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

Use case 2: ad-selection-from-outcomes

Prebuilt URIs under the ad-selection-from-outcomes use case support the selectAds(AdSelectionFromOutcomesConfig) workflow.

Prebuilt URI name: waterfall-mediation-truncation

The waterfall-mediation-truncation prebuilt URI provides JavaScript that implements waterfall mediation truncation logic where the JavaScript returns a first-party ad if the bid is higher then or equal to the bid floor , and otherwise returns null .

Required parameters

bidFloor : The key of the bid floor value passed in the getSelectionSignals() that is compared against the mediation SDK's ad.

استفاده

If your ad selection signals look like {"bid_floor": 10} then the resulting prebuilt URI would be:

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

تست کردن

To help you get started with the Protected Audience API, we've created sample apps in Kotlin and Java, which can be found on GitHub .

پیش نیازها

The Protected Audience API requires some JavaScript during ad selection and impression reporting. There are two methods of providing this JavaScript in a testing environment:

  • Run a server with the required HTTPS endpoints that returns the JavaScript
  • Override remote fetching by providing the necessary code from a local source

Either approach requires setting up an HTTPS endpoint to handle impression reporting.

HTTPS endpoints

To test ad selection and impression reporting, you need to set up 7 HTTPS endpoints that your test device or emulator can access:

  1. Buyer endpoint that serves the bidding logic JavaScript.
  2. An endpoint that serves the bidding signals.
  3. Seller endpoint that serves the decision logic JavaScript.
  4. An endpoint that serves scoring signals.
  5. Winning buyer impression reporting endpoint.
  6. Seller impression reporting endpoint.
  7. An endpoint to serve the daily updates for a custom audience.

For convenience, the GitHub repo provides basic JavaScript code for testing purposes. It also includes OpenAPI service definitions which can be deployed to a supported mock or microservices platform. For more details, see the project README .

Override remote fetching of JavaScript

This feature is intended to be used for end-to-end testing. To override remote fetching, your app must run in debug mode with developer options enabled.

To enable debug mode for your application, add the following line to the application attribute in your AndroidManifest.xml:

<application
  android:debuggable="true">

For an example of how to use these overrides, please see the the Protected Audience API sample app on GitHub.

You need to add your own custom JavaScript to handle ad selection routines such as bidding, scoring decisions, and reporting. You can find basic JavaScript code examples that handle all required requests in the GitHub repo . The Protected Audience API sample application demonstrates how to read code from that file and prepare it for use as an override.

It is possible to override sell-side and buy-side JavaScript fetching independently, though you need an HTTPS endpoint to serve any JavaScript you aren't providing overrides for. Please see the README for information about how to set up a server that handles these cases.

It is only possible to override JavaScript fetching for custom audiences that are owned by your package.

Override sell-side JavaScript

To set up an override of sell-side JavaScript, do the following as demonstrated in the following code example:

  1. Initialize an AdSelectionManager object.
  2. Get a reference to TestAdSelectionManager from the AdSelectionManager object.
  3. Build an AdSelectionConfig object.
  4. Build an AddAdSelectionOverrideRequest with the AdSelectionConfig object and a String representing the JavaScript you intend to use as an override.
  5. Call the asynchronous overrideAdSelectionConfigRemoteInfo() method with the AddAdSelectionOverrideRequest object and relevant Executor and OutcomeReceiver objects.

کاتلین

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)

جاوا

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

See the Run ad selection section for more information about what each of the fields in the AdSelectionConfig represent. The key difference is that the decisionLogicUrl can be set to a placeholder value as it will be ignored.

In order to override the JavaScript used during ad selection, the decisionLogicJs must contain the proper seller-side function signatures . For an example of how to read a JavaScript file as a string, please see the Protected Audience API sample app on GitHub.

The asynchronous overrideAdSelectionConfigRemoteInfo() method uses the OutcomeReceiver object to signal the result of the API call.

The onResult() callback signifies the override was applied successfully. Future calls to selectAds() will use whatever decision and reporting logic you have passed in as the override.

The onError() callback signifies two possible conditions:

  • If the override is attempted with invalid arguments, the AdServiceException indicates an IllegalArgumentException as the cause.
  • If the override is attempted with an app not running in debug mode with developer options enabled, the AdServiceException indicates IllegalStateException as the cause.

Reset sell-side overrides

This section assumes that you have overridden the sell-side JavaScript and that you have a reference to the TestAdSelectionManager and AdSelectionConfig used in the previous section.

In order to reset the overrides for all AdSelectionConfigs :

  1. Call the asynchronous resetAllAdSelectionConfigRemoteOverrides() method with the relevant OutcomeReceiver object.

کاتلین

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

جاوا

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

After you reset sell-side overrides, calls to selectAds() use whatever decisionLogicUrl is stored in the AdSelectionConfig to attempt to fetch the required JavaScript.

If the call to resetAllAdSelectionConfigRemoteOverrides() fails, the OutComeReceiver.onError() callback provides an AdServiceException . If the removal of overrides is attempted with an app not running in debug mode with developer options enabled, AdServiceException indicates IllegalStateException as the cause.

Override buy-side JavaScript

  1. Follow the steps to join a custom audience
  2. Build an AddCustomAudienceOverrideRequest with the buyer and name of the custom audience you wish to override, in addition to the bidding logic and data you wish to use as an override
  3. Call the asynchronous overrideCustomAudienceRemoteInfo() method with the AddCustomAudienceOverrideRequest object and relevant Executor and OutcomeReceiver objects

کاتلین

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)

جاوا

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

The values for buyer and name are the same ones used to create the custom audience. Learn more about these fields .

Additionally, you can specify two additional parameters:

  • biddingLogicJs : JavaScript that holds the buyer's logic that is used during ad selection. See the required function signatures in this JavaScript.
  • trustedBiddingSignals : Bidding signals to be used during ad selection. For testing purposes this can be an empty string.

The asynchronous overrideCustomAudienceRemoteInfo() method uses the OutcomeReceiver object to signal the result of the API call.

The onResult() callback signifies the override was applied successfully. Subsequent calls to selectAds() use whatever bidding and reporting logic you have passed in as the override.

The onError() callback signifies two possible conditions.

  • If the override is attempted with invalid arguments, the AdServiceException indicates an IllegalArgumentException as the cause.
  • If the override is attempted with an app not running in debug mode with developer options enabled, the AdServiceException indicates IllegalStateException as the cause.

Reset buy-side overrides

This section assumes that you have overridden the buy-side JavaScript and that you have a reference to the TestCustomAudienceManager used in the previous section.

To reset overrides for all custom audiences:

  1. Call the asynchronous resetAllCustomAudienceOverrides() method with relevant Executor and OutcomeReceiver objects.

کاتلین

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

جاوا

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

After you reset buy-side overrides, subsequent calls to selectAds() use whatever biddingLogicUrl and trustedBiddingData is stored in the CustomAudience to attempt to fetch the required JavaScript.

If the call to resetCustomAudienceRemoteInfoOverride() fails, the OutComeReceiver.onError() callback provides an AdServiceException . If the removal of overrides is attempted with an app not running in debug mode with developer options enabled, the AdServiceException indicates IllegalStateException as the cause.

Set Up a Reporting Server

When you use remote fetching overrides, you'll still need to set up a server that your device or emulator can reach to respond to reporting events. A simple endpoint that returns 200 is sufficient for testing. The GitHub repo includes OpenAPI service definitions which can be deployed to a supported mock or microservices platform. For more details, see the project README .

When looking for the OpenAPI definitions, look for the reporting-server.json. This file contains a simple endpoint that returns 200, representing an HTTP response code. This endpoint is used during selectAds() and signals to the Protected Audience API that impression reporting completed successfully.

Functionality to test

  • Exercise joining or leaving and setting up a custom audience based on prior user actions.
  • Exercise the initiation of on-device ad selection through JavaScripts hosted remotely.
  • Observe how an app's association with custom audience settings may affect ad selection outcomes.
  • Exercise impression reporting after ad selection.

محدودیت ها

The following table lists limitations for the Protected Audience API processing. The limits presented could be subject to change based on feedback. For in-progress capabilities, read the release notes .

جزء Limit Description مقدار محدود
Custom audience (CA) Maximum number of ads per CA 100
Maximum number of CAs per application 1000
Maximum number of apps that can create a CA 1000
Maximum delay in the activation time of a CA from its creation time 60 روز
Maximum expiration time of a CA from its activation time 60 روز
Maximum number of CAs on device 4000
Maximum size of CA name 200 bytes
Maximum size of daily fetch URI 400 bytes
Maximum size of bidding logic URI 400 bytes
Maximum size of trusted bidding data 10 کیلوبایت
Maximum size of user bidding signals 10 کیلوبایت
Maximum call rate for leaveCustomAudience per buyer 1 در ثانیه
Maximum call rate for joinCustomAudience per buyer 1 در ثانیه
CA Background Fetch مهلت زمانی اتصال 5 ثانیه
HTTP read timeout 30 ثانیه
Maximum total download size 10 کیلوبایت
Max duration of a fetch iteration 5 دقیقه
Maximum number of CAs updated per job 1000
انتخاب آگهی Maximum number of buyers TBD
Maximum number of CAs per buyer TBD
Maximum number of ads in an auction TBD
Initial connection timeout 5 ثانیه
Connection read timeout 5 ثانیه
Maximum execution time of overall AdSelection 10 ثانیه
Maximum execution time of bidding per CA in AdSelection 5 second
Maximum execution time of scoring in AdSelection 5 second
Maximum execution time for per buyer in AdSelection TBD
Maximum size of ad selection/seller/per buyer signals TBD
Maximum size of seller/buyer scripts TBD
Maximum call rate for selectAds 1 QPS
Impression reporting Minimum time before removing ad selection from persistence 24 ساعت
Maximum number of storage ad selections TBD
Maximum size of reporting output URL TBD
Maximum time for impression reporting TBD
Maximum number of retries for notification calls TBD
پایان زمان اتصال 5 ثانیه
Maximum overall execution time for reportImpression 2 ثانیه
Maximum call rate for reportImpressions 1 QPS
گزارش رویداد Maximum number of beacons per buyer per auction 10

Maximum number of beacons per seller per auction

10

Maximum size of event key

40 bytes

Maximum size of event data

64 کیلوبایت

تبلیغات Maximum size of ad list 10 KB shared by all AdData in a single CA for contextual
URL ها Maximum length of any URL string taken as input TBD
جاوا اسکریپت حداکثر زمان اجرا 1 second for bidding and scoring for impression reporting
Maximum memory used 10 مگابایت

Report bugs and issues

Your feedback is a crucial part of the Privacy Sandbox on Android! Let us know of any issues you find or ideas for improving Privacy Sandbox on Android.

{% verbatim %} {% endverbatim %} {% verbatim %} {% endverbatim %} ,

As you read through the Privacy Sandbox on Android documentation, use the Developer Preview or Beta button to select the program version that you're working with, as instructions may vary.


The Protected Audience API on Android (formerly known as FLEDGE) includes the Custom Audience API and the Ad Selection API. Ad tech platforms and advertisers can use these APIs to serve customized ads based on previous app engagement that limits the sharing of identifiers across apps and limits sharing a user's app interaction information with third-parties.

The Custom Audience API is centered around the "custom audience" abstraction, which represents a group of users with common intentions. An advertiser can register a user with a custom audience and associate relevant ads with it. This information is stored locally and can be used to inform advertiser bids, ad filtering, and ad rendering.

The Ad Selection API provides a framework that allows multiple developers to run an auction locally for a custom audience. To achieve this, the system considers relevant ads associated with the custom audience and performs additional processing on ads that an ad tech platform returns to the device.

Ad tech platforms can integrate these APIs to implement remarketing that preserves user privacy. Support for additional use cases, including app install ads, are planned for future releases. Learn more about the Protected Audience API on Android in the design proposal .

This guide describes how to work with the Protected Audience API on Android to do the following:

  1. Manage custom audiences
  2. Set up and run ad selection on a device
  3. Report ad impressions

قبل از شروع

Before you get started, complete the following:

  1. Set up your development environment for the Privacy Sandbox on Android.
  2. Either install a system image onto a supported device or set up an emulator that includes support for the Privacy Sandbox on Android.
  3. In a terminal, enable access to the Protected Audience API (disabled by default) with the following adb command.

      adb shell device_config put adservices ppapi_app_allow_list \"*\"
    
  4. In a terminal, enable beacon reporting with the following adb commands.

     adb shell device_config put adservices fledge_beacon_reporting_metrics_enabled true
     adb shell device_config put adservices fledge_register_ad_beacon_enabled true
    
  5. Include an ACCESS_ADSERVICES_CUSTOM_AUDIENCE permission in your app manifest:

      <uses-permission android:name="android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCE" />
    
  6. Reference an ad services configuration in the <application> element of your manifest:

      <property android:name="android.adservices.AD_SERVICES_CONFIG"
                android:resource="@xml/ad_services_config" />
    
  7. Specify the ad services XML resource referenced in your manifest, such as res/xml/ad_services_config.xml . Learn more about ad services permissions and SDK access control .

      <ad-services-config>
        <custom-audiences allowAllToAccess="true" />
      </ad-services-config>
    
  8. By default, the Ad Selection API enforces limits on the maximum amount of memory that an auction or impression reporting script can allocate. The memory limitation feature requires WebView version 105.0.5195.58 or higher. The platform enforces a version check and calls to the selectAds and reportImpression APIs fail if this isn't satisfied. There are two options to set this up:

    • Option 1: Run the following adb command to deactivate this check:

      adb device_config put fledge_js_isolate_enforce_max_heap_size false
      
    • Option 2: Install WebView Beta from the Google Play store. This must be equal to or higher than the version stated earlier.

Join a custom audience

A custom audience represents a group of users with common intentions or interests as decided by an advertiser app. An app or SDK may use a custom audience to indicate a particular audience, such as someone who has left items in a shopping cart. To create or join a custom audience asynchronously, do the following:

  1. Initialize the CustomAudienceManager object.
  2. Create a CustomAudience object by specifying key parameters such as the buyer's package and a relevant name. Then, initialize the JoinCustomAudienceRequest object with the CustomAudience object.
  3. Call the asynchronous joinCustomAudience() with the JoinCustomAudienceRequest object and relevant Executor and OutcomeReceiver objects.

کاتلین

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)

جاوا

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

The combination of the following parameters uniquely identifies each CustomAudience object on a device:

  • owner : Package name of the owner app. This is implicitly set to the package name of the caller app.
  • buyer : Identifier for the buyer ad network which manages ads for this custom audience.
  • name : An arbitrary name or identifier for the custom audience.

Calling joinCustomAudience() repeatedly with a different instance of CustomAudience updates any existing CustomAudience with matching owner, buyer , and name parameters. To help preserve privacy, the result of the API does not distinguish between "creation" and "update."

Additionally, the CustomAudience must be created with these required parameters:

Optional parameters for a CustomAudience object may include:

  • Activation time : A custom audience can only participate in ad selection and daily updates after its activation time. This can be useful to engage lapsed users of an app, for example.
  • Expiration time : A future time after which the custom audience is removed from the device.
  • User bidding signals : A JSON string containing user signals, such as the user's preferred locale, that a buyer's bidding logic JavaScript consumes to generate bids during the ad selection process. This format helps ad tech platforms reuse code across platforms and eases the consumption in JavaScript functions.
  • Trusted bidding data : An HTTPS URL and a list of strings used during the ad selection process that fetch bidding signals from a trusted Key/Value service.
  • Ads : A list of AdData objects corresponding to the ads that participate in ad selection. Each AdData object consists of:
    • Render URL : An HTTPS URL that is queried to render the final ad.
    • Metadata : A JSON object serialized as a string containing information to be consumed by buyer bidding logic during the ad selection process.
    • Ad Filters : A class that contains all necessary information for app install ad filtering and frequency capping during ad selection.

Here's an example of a CustomAudience object instantiation:

کاتلین

// 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()

جاوا

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

Handle joinCustomAudience() outcomes

The asynchronous joinCustomAudience() method uses the OutcomeReceiver object to signal the result of the API call.

  • The onResult() callback signifies the custom audience is successfully created or updated.
  • The onError() callback signifies two possible conditions.

Here's an example of handling the outcome of joinCustomAudience() :

کاتلین

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

جاوا

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

Leave a custom audience

If the user no longer satisfies the business criteria for a given custom audience, an app or SDK can call leaveCustomAudience() to remove the custom audience from the device. To remove a CustomAudience based on its unique parameters, do the following:

  1. Initialize the CustomAudienceManager object.
  2. Initialize the LeaveCustomAudienceRequest with the custom audience's buyer and name . To learn more about these input fields, read " Join a custom audience ."
  3. Call the asynchronous leaveCustomAudience() method with the LeaveCustomAudienceRequest object and relevant Executor and OutcomeReceiver objects.

کاتلین

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)

جاوا

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

Similar to calling joinCustomAudience() , the OutcomeReceiver signals the end of an API call. To help protect privacy, an error outcome doesn't distinguish between internal errors and invalid arguments. The onResult() callback is called when the API call has completed, whether or not a matching custom audience is removed successfully.

Run ad selection

To use the Protected Audience API to select ads, call the selectAds() method:

  1. Initialize an AdSelectionManager object.
  2. Build an AdSelectionConfig object.
  3. Call the asynchronous selectAds() method with the AdSelectionConfig object and relevant Executor and OutcomeReceiver objects.

کاتلین

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
)

جاوا

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

The selectAds() method requires an AdSelectionConfig input, where you must specify the following required parameters:

  • Seller : Identifier for the seller ad network initiating the ad selection.
  • Decision logic URL : An HTTPS URL queried to obtain the seller ad network's JavaScript logic.
    • HTTPS URL : queried to obtain the seller ad network's JavaScript logic. See the required function signatures .
    • Prebuilt URI : that follows FLEDGE's ad selection format. IllegalArgumentException is thrown, if an unsupported or malformed prebuilt uri is passed.
  • Custom audience buyers : A full list of identifiers for buyer ad networks that are allowed by the seller to participate in the ad selection process. These buyer identifiers correspond to CustomAudience.getBuyer() of participating custom audiences.

The following parameters can be optionally specified for more customized ad selection:

  • Ad selection signals : A JSON object, serialized as a string, containing signals to be consumed by buyer bidding logic JavaScript fetched from CustomAudience.getBiddingLogicUrl() .
  • Seller signals : A JSON object, serialized as a string, containing signals consumed by the seller's fetched JavaScript decision logic from AdSelectionConfig.getDecisionLogicUrl() .
  • Per buyer signals : A map of JSON objects, serialized as strings, containing signals to be consumed by specific buyers' bidding logic JavaScript fetched from CustomAudience.getBiddingLogicUrl() , which are identified by the buyer fields of participating custom audiences.
  • Contextual ads: A collection of ad candidates that are collected directly from buyers during an auction that happens outside of a Protected Audience auction.

Once an ad is selected, the results, bids, and signals are persisted internally for reporting. The OutcomeReceiver.onResult() callback returns an AdSelectionOutcome that contains:

  • A render URL for the winning ad, obtained from AdData.getRenderUrl() .
  • An ad selection ID unique to the device user. This ID is used for reporting the ad impression.

If the ad selection can't be completed successfully due to reasons such as invalid arguments, timeouts, or excessive resource consumption, the OutcomeReceiver.onError() callback provides an AdServicesException with the following behaviors:

  • If the ad selection is initiated with invalid arguments, the AdServicesException indicates an IllegalArgumentException as the cause.
  • All other errors receive an AdServicesException with an IllegalStateException as the cause.

تبلیغات متنی

Protected Audience can incorporate contextual ads into a Protected Auction. Contextual ads need to be selected on the ad tech server and returned to the device outside of Protected Audience APIs. Contextual ads can then be included in the auction using the AdSelectionConfig at which point they function the same as on device ads, including eligibility for negative ad filtering. Once the Protected Audience auction has completed, you need to invoke reportImpression() . This calls reportWin() in the winning contextual ad, in the same pattern as impression reporting , to receive the winning ad on a device. Each contextual ad needs a buyer, a bid, a link to reporting logic, a render URL, and ad metadata.

To deploy contextual ads in app, the target app needs to create a ContextualAds object:

کاتلین

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

جاوا

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

The resulting ContextualAds object can then be passed along when creating your AdSelectionConfig :

کاتلین

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

جاوا

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

App install ad filtering

App install ads filtering helps you to filter installation ads for apps that are already installed on a device.

The first step in this process is to define which advertisers have the ability to filter on the installed package. This needs to happen in the app you want to target with an ad.

کاتلین

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

جاوا

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

When the preceding code executes, the advertisers passed in are then able to filter out the installed apps that you specify during their bid generation. If you need to remove an advertiser from having access to this app's install status, run this code again with the advertiser's information removed.

The next step is to set up ad filtering inside the publisher app. The party that serves the ad inside of the publisher app (most likely to be a supply-side SDK) must initialize their AdFilters object with information about which ads related to apps they'd like to filter out:

کاتلین

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

جاوا

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

Demand-side publishers may also set an AdFilter for ads that exist inside of their custom audiences.

AdFilters can also be passed in at the point of instantiating a new AdData object:

کاتلین

// 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()

جاوا

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

Frequency cap filtering

Frequency cap filtering enables ad techs to limit the number of times an ad is shown. Frequency cap filtering reduces ad overexposure and optimizes alternate ad selection for a given ad campaign.

There are two main components of a frequency cap filter: the ad event type, and the ad counter key. The available ad event types that can be used are:

  • Win : A win event indicates that the ad has won an auction. Win events are automatically updated by the Protected Audience API and cannot be called directly by the developer. Win data is only visible to ads within a given custom audience.
  • Impression : Separate from reportImpression , an on-device caller (SSP or MMP) uses updateAdCounterHistogram() to invoke impression events at the point in code they choose. Impression events are visible to all ads belonging to a given DSP, and are not limited to ads in the same custom audience.
  • View : Event is invoked by the on-device caller (SSP or MMP) at a point in code they choose using a call to updateAdCounterHistogram() . View events are visible to all ads belonging to a given DSP and not limited to ads in the same Custom Audience.
  • Click : Event is invoked by the on-device caller (SSP or MMP) at a point in code they choose using a call to updateAdCounterHistogram() . Click events are visible to all ads belonging to a given DSP and not limited to ads in the same Custom Audience.

In the publisher app, an SSP or MMP that has a presence on the device invokes ad events. When updateAdCounterHistogram() is called, the counter of a frequency cap filter is incremented so that future auctions will have up to date information about a user's exposure to a given ad. The ad event types are not forcibly tied to the corresponding user action and are guidelines given to help callers to structure their event system. To increment ad counters at the time of an event, the on-device actor provides the winning ad auction's ad selection ID.

Ad counter keys are arbitrary 32-bit signed integers assigned by a buyer ad tech, and they correspond to a given set of ads as defined by the DSP. Since ad counter keys are limited only to ads that belong to a given DSP, these keys can be selected without overlapping with histograms from another ad tech. Ad counter keys are used to increment DSP-specific identifiers across a DSP's ads or within a given custom audience to filter out ads from future auctions.

Counter keys can be leveraged to prioritize ads that are more likely to be interesting to a given user based on their interactions with other ads from a given buyer ad tech. For example, an ad that has received a high level of engagement from winning ad auctions, views, and clicks, represents an inferred data point. To further illustrate this point: an ad for left handed golf clubs might indicate that the user wouldn't be interested in right handed ones. A frequency cap filter set for a counter key assigned to left-handed ads could filter out ads for right handed clubs.

To use frequency capping in your auction, you must first create KeyedFrequencyCap objects as shown below:

کاتلین

// 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()

جاوا

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

Once the KeyedFrequencyCap objects are created, you can pass them into an AdFilters object.

کاتلین

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

جاوا

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

When the AdFilters object is populated with frequency cap filters, it can be passed along when the custom audience is created:

کاتلین

// 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()

جاوا

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

When frequency cap filters are implemented into a custom audience, the SSP can then invoke the necessary click, view, or impression events.

کاتلین

val callerAdTech: AdTechIdentifier = mAdSelectionConfig.getSeller()

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

جاوا

AdTechIdentifier callerAdTech = mAdSelectionConfig.getSeller();

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

Ads that have hit their pre-set frequency cap filter limits are filtered out of the auction. Filtering happens before the bidding logic is executed for on-device auctions, and as the payload is generating for Bidding & Auction services auctions.This toolkit gives ad techs the flexibility to use the interactions between users and the ads within their custom audiences to focus ad targeting while minimizing ad overexposure.

Contextual ad filtering without network calls

If there is no remarketing demand on the device, you can run ad selection for contextual ads without network calls. With prebuilt URIs and a list of contextual ads with bids, the platform can skip retrieving bidding logic, bidding signals, and scoring signals. The platform uses a prebuilt URI to select the contextual ad with the highest bid.

To improve latency, ad techs can run an ad selection flow that includes only contextual ads with ad filtering functionality without network calls. This is achieved by using prebuilt URIs for scoring signals. Refer to the Supported prebuilt URI use cases and names section for a list of scoreAds implementations.

To run ad selection without network calls:

  1. Set up ad filtering
  2. Create your contextual ads
  3. Create a AdSelectionConfig object with the following:

    1. An empty list of buyers
    2. A prebuilt URI to select the highest bid
    3. تبلیغات متنی
    4. An empty URI for the scoring signals. The empty URI is allowed to indicate that you don't want to use the fetching of trusted signals for scoring:
    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. Run ad selection:

    adSelectionManager.selectAds(
        adSelectionConfig,
        executor,
        outcomeReceiver);
    

Run your own reporting JavaScript while using prebuilt URIs

Today, the Privacy Sandbox platform only has a basic reporting JavaScript implementation available for prebuilt URIs. If you want to run your own reporting JavaScript while still using prebuilt URIs for a low latency ad selection, you can override the DecisionLogicUri between ad selection and reporting runs.

  1. Run steps to run ad selection for contextual ads using prebuilt URIs
  2. Create a copy of your AdSelectionConfig before running reporting

    adSelectionConfigWithYourReportingJS = adSelectionConfig.cloneToBuilder()
      // Replace <urlToFetchYourReportingJS> with your own URL:
      .setDecisionLogicUri(Uri.parse(<urlToFetchYourReportingJS>))
      .build();
    
  3. Run impression reporting

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

Run waterfall mediation

Waterfall mediation requires multiple third party SDKs (3P networks) to be orchestrated by a first party SDK mediation network. Waterfall mediation is done the same way regardless if the auction took place on device or ran on Bidding & Auction services (B&A).

3P networks

3P networks need to provide an adapter that allows the mediation network to invoke the necessary methods for running an auction:

  • Run ad selection
  • Report impressions

Here's an example of a mediation network adapter:

کاتلین

class NetworkAdaptor {
    private val adSelectionManager : AdSelectionManager

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

    fun selectAds() {...}

    fun reportImpressions() {...}
}

جاوا

class NetworkAdaptor {
    AdSelectionManager adSelectionManager;

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

    public void selectAds() {...}

    public void reportImpressions() {...}
}

Each SDK has their own ad selection service managers and clients, and their own selectAds and reportImpressions implementation. SDK providers can refer to the sections on how to run ad selection for on-device auctions or the B&A explainer for B&A auctions. Follow how to report ad impressions (following the single SSP impression reporting for reporting.

Mediation network

Similar to 3P networks, mediation networks need selectAds and reportImpression implementations. Refer to the sections on how to run ad selection and how to report ad impressions for more information.

Mediation networks are responsible for running the mediation chain and placing themselves in the mediation chain. The next section covers how to set up and execute this process.

Retrieve mediation chain and bid floors

The mediation network is responsible for retrieving the first party (1P) contextual ads, mediation chain, and third party networks' bid floors (3P). This can happen in a request to retrieve contextual ads executed by the mediation network. The mediation chain determines how to iterate through the 3P Networks, and the bid floors can be passed to the auction process as adSelectionSignals .

Network placement in the mediation chain

A mediation SDK can place itself in the mediation chain based on their live eCPM of 1P ad bids. In the Protected Audience API, ad bids are opaque. A mediation SDK should use AdSelectionFromOutcomesConfig to be able to compare a given 1P ad's bid to the bid floor of the next 3P network in the chain. If the 1P bid is higher than the bid floor then that means the mediation SDK is placed in front of that 3P network.

Run ad selection

To retrieve a 1P ad candidate, the mediation network can execute an on-device auction following the steps in the run ad selection section. This generates a 1P ad candidate, a bid, and an AdSelectionId that is used in the mediation process.

Create an AdSelectionFromOutcomesConfig

An AdSelectionFromOutcomesConfig allows the mediation network to pass a list of AdSelectionIds (results from previous auctions), ad selection signals, and a URI to fetch JavaScript that selects an ad from multiple candidates. The list of AdSelectionIds along with their bids and the signals are passed to the JavaScript which can return one of the AdSelectionIds if it beats the bid floor, or none if the mediation chain should continued.

Mediation Networks create an AdSelectionFromOutcomesConfig using the 1P AdSelectionId from the previous section, and the bid floor for the 3P Network being considered. A new AdSelectionFromOutcomesConfig should be created for each step in the mediation chain.

کاتلین

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

جاوا

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

The selectAds() method override for waterfall mediation requires an AdSelectionFromOutcomesConfig input, where you must specify the following required parameters:

  • Seller : Identifier for the seller ad network initiating the ad selection.
  • AdSelectionIds : A singleton list of a previous selectAds() run for a 1P ad.
  • Ad selection signals : A JSON object, serialized as a string, containing signals to be used by buyer bidding logic. In this case, include the bid floor retrieved for the given 3P network.
  • Selection Logic URI : An HTTPS URL queried during ad selection to fetch the mediation network's JavaScript for selecting a winning ad. See the required function signatures in this JavaScript. The JavaScript should return the 3P ad if the bid is higher than the bid floor, or otherwise return null . This allows the mediation SDK to truncate the mediation chain when a winner is found.

With the AdSelectionOutcomesConfig created, call the selectAds() method of the 3P network that is first in the chain.

کاتلین

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)

جاوا

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

Orchestrate waterfall mediation

The following is the order of operations for running through the mediation process.

  1. Run 1P ad selection.
  2. Iterate over the mediation chain. For each 3P network, do the following:
    1. Build AdSelectionFromOutcomeConfig including the 1P outcomeId and the 3P SDK's bid floor.
    2. Call selectAds() with the config from the previous step.
    3. If the result is not empty, return the ad.
    4. Call the current SDK network adapter's selectAds() method. If the result is not empty, return the ad.
  3. If no winner is found from the chain, return the 1P ad.

کاتلین

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

جاوا

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) { ... }
}

Report ad impressions

There are two flows for reporting an ad impression depending on how the auction is run. If you are a single SSP running an auction, follow this section. If you are going to implement waterfall mediation, follow the steps found in the waterfall mediation impression reporting section .

Single SSP impression reporting

After a winning ad has been chosen from the ad selection workflow, you can report the impression back to participating buy-side and sell-side platforms with the AdSelectionManager.reportImpression() method. To report an ad impression:

  1. Initialize an AdSelectionManager object.
  2. Build a ReportImpressionRequest object with the ad selection ID.
  3. Call the asynchronous reportImpression() method with the ReportImpressionRequest object and relevant Executor and OutcomeReceiver objects.

جاوا

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

کاتلین

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)

Initialize the ReportImpressionRequest with the following required parameters:

  • Ad selection ID : An ID unique only to a device user that identifies a successful ad selection.
  • Ad selection config : The same configuration used in the selectAds() call identified by the provided ad selection ID.

The asynchronous reportImpression() method uses the OutcomeReceiver object to signal the result of the API call.

  • The onResult() callback indicates if impression reporting URLs have been created and the request has been scheduled.
  • The onError() callback indicates the following possible conditions:
    • If the call is initialized with an invalid input argument, the AdServicesException indicates an IllegalArgumentException as the cause.
    • All other errors receive an AdServicesException with an IllegalStateException as the cause.

Waterfall mediation impression reporting

A mediation SDK needs to keep track of the winning SDK to trigger their reporting flows. The SDKs participating in a mediation chain should provide a method for the mediator to invoke to trigger their own reporting flow. An SDK participating in a mediated auction can follow the steps above to implement their own reporting.

SSPs can use this 3P SDK code example as a prototype for how to join in mediation flows:

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

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

Impression reporting endpoints

The report impression API issues HTTPS GET requests to endpoints provided by the sell-side platform and the winning buy-side platform:

Buy-side platform endpoint:

  • The API uses the Bidding logic URL specified in the custom audience to fetch the buyer-provided JavaScript that includes logic to return an impression reporting URL.
  • Invoke the reportWin() JavaScript function, which is expected to return the buyer's impression reporting URL.

Sell-side platform endpoint:

  • Use the Decision logic URL specified in the AdSelectionConfig object to fetch the seller's decision logic JavaScript.
  • Invoke the reportResult() JavaScript function, which is expected to return the seller's impression reporting URL.

Bidding & Auction services reporting

An auction executed on Bidding & Auction services will have all the necessary reporting information, including generated URLs for ad interaction reporting , included in the encrypted response from the server-side auction. When the response is decrypted, the appropriate URLs are registered with the platform, so ad and impression reporting follows the same steps listed above.

Best effort Impression reporting

The reportImpression() method is designed to offer a best-effort completion of reporting.

Report Ad Interactions

Protected Audience provides support to report on more granular interactions for a rendered ad. This can include interactions such as view time, clicks, hovers, or any other useful metric that can be collected. The process to receive these reports requires two steps. First, buyers and sellers must register to receive these reports in their reporting JavaScript. Then, the client will need to report these events.

Registering to receive interaction events

Registering for interaction events happens in the buyer's reportWin() and seller's reportResult() JavaScript functions using a JavaScript function provided by the platform: registerAdBeacon . To register to receive an event report, simply call the platform JavaScript Function from your reporting JavaScript. The following snippet is using a buyer's reportWin() , but the same approach applies to reportResult() .

reportWin(
  adSelectionSignals,
  perBuyerSignals,
  signalsForBuyer,
  contextualSignals,
  customAudienceSignals) {
    ...
    // Calculate reportingUri, clickUri, viewUri, and hoverUri

    registerAdBeacon({"click": clickUri, "view": viewUri, "hover": hoverUri});

    return reportingUri;
}

Reporting interaction events

After reporting an impression, clients can report the interactions back to previously registered winning buy-side and sell-side platforms with the AdSelectionManager.reportInteraction() method. To report an ad event:

  1. Initialize an AdSelectionManager object.
  2. Build a ReportInteractionRequest object with the ad selection ID, interaction key, interaction data, and reporting destination.
  3. Call the asynchronous reportInteraction() method with the request object and relevant Executor and OutcomeReceiver objects.
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);

Initialize the ReportInteractionRequest with the following required parameters:

  • Ad selection ID : An ad selection ID retrieved from a previously returned AdSelectionOutcome .
  • Interaction Key : A string key defined by the client describing the action being reported. This must match the key that was registered by the seller or buyer in the reporting JavaScript functions.
  • Interaction Data : A string containing data to be included with the event report, to be POSTed back to the reporting servers.
  • Reporting Destinations : A bit mask specifying if the events should be reported to the buyer, seller, or both. These flags are provided by the platform and the final destination mask can be created using bitwise operations. To report to one destination, you can use the flag provided by the platform directly. To report to multiple destinations, you can use the bitwise OR ( | ) to combine flag values.

The asynchronous reportInteraction() method uses the OutcomeReceiver object to signal the result of the API call.

  • The onResult() callback indicates the report interaction call is valid.
  • The onError() callback indicates the following possible conditions:
    • If the call is made when the app is running in the background, an IllegalStateException with a description of the failure is returned.
    • If the client is throttled from calling reportInteraction() , a LimitExceededException is returned.
    • If the package is not enrolled to call the Privacy Preserving APIs, a SecurityException() is returned.
    • If the app reporting interactions is different from the app that called selectAds() , an IllegalStateException is returned.
  • If the user has not consented to enable the Privacy Sandbox APIs, the call will fail silently.

Interaction reporting endpoints

The report interaction API issues HTTPS POST requests to endpoints provided by the sell-side platform and the winning buy-side platform. Protected Audience will match the interaction keys with the URIs declared in reporting JavaScript and issue a POST request to each endpoint for each interaction being reported. The content type of the request is plain text with the body being the Interaction Data.

Best effort Interaction reporting

The reportInteraction() is designed to offer a best-effort completion of reporting through HTTP POST.

Daily background update

When creating a custom audience, your app or SDK can initialize custom audience metadata. Additionally, the platform can update the following pieces of custom audience metadata with a daily background update process.

  • User bidding signals
  • Trusted bidding data
  • AdData list

This process queries against the Daily update URL defined in the custom audience and the URL may return a JSON response.

  • The JSON response may contain any of the supported metadata fields that needs to be updated.
  • Each JSON field is validated independently. The client ignores any malformed fields which results in no updates to that particular field in the response.
  • An empty HTTP response or an empty JSON object " {} " results in no metadata updates.
  • The response message size must be limited to 10 KB.
  • All URIs are required to use HTTPS.
  • trusted_bidding_uri must share the same ETLD+1 as the buyer.

Example: JSON response for background daily update

{
    "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 for ad selection

The ad selection workflow orchestrates the execution of buyer-provided and seller-provided JavaScript.

Buyer-provided JavaScript is fetched from the Bidding logic URL specified in the custom audience. The returned JavaScript should include the following functions:

Seller-provided JavaScript is fetched from the decision logic URL specified in the AdSelectionConfig parameter for the ad selection API. The returned JavaScript should include the following functions:

generateBid()

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 : a JSON object with the format var ad = { 'render_url': url, 'metadata': json_metadata };
  • auction_signals, per_buyer_signals : JSON objects specified in the auction configuration object
  • custom_audience_bidding_signals : JSON object generated by the platform. The format for this JSON object is:

    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 , and name are string taken from the properties with the same name of the Custom Audience participating to the ad selection
    • activation_time and expiration_time are the time of activation and expiration of the custom audience, expressed as seconds since the Unix epoch
    • ca_user_bidding_signals is a JSON string specified in the userBiddingSignals field of the CustomAudience at creation time
    • trusted_bidding_signals, contextual_signals , and user_signals are JSON objects. They are passed as empty objects and will be filled up in future releases. Their format is not enforced by the platform and is managed by the ad tech.

نتیجه:

  • ad : is the ad the bid refers to. The script is allowed to return a copy of the ad it received with different metadata. The render_url property of the ad is expected to be unaltered.
  • bid : a float value representing the bid value for this ad
  • status : an integer value that can be:
    • 0 : for a successful execution
    • 1 : (or any non-zero value) in case any of the input signals is invalid. In case a non-zero value is returned by generate-bid the bidding process is invalidated for all the CA ads

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 : see the generateBid documentation
  • bid : the bid value for the ad
  • ad_selection_config : a JSON object representing the AdSelectionConfig parameter of the selectAds API. قالب این است:

    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 objects read from the sellerSignals AdSelectionConfig API parameter

  • trusted_scoring_signal : read from the adSelectionSignals field in the AdSelectionConfig API parameter

  • contextual_signals, user_signals : JSON objects. They are currently passed as empty objects and will be filled up in future releases. Their format is not enforced by the platform and is managed by the ad tech.

  • per_buyer_signals : JSON object read from the perBuyerSignal map in the AdSelectionConfig API parameter using as key the current Custom Audience buyer. Empty if the map doesn't contain any entry for the given buyer.

خروجی:

  • score : a float value representing the score value for this ad
  • status : an integer value that can be:
    • 0: for a successful execution
    • 1: in case the customAudienceSignals are invalid
    • 2: in case the AdSelectionConfig is invalid
    • 3: in case any of the other signals is invalid
    • Any non-zero value causes the failure of the process, the value determines the type of exception thrown

selectOutcome()

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

پارامترهای ورودی:

  • outcomes : a JSON object {"id": id_string, "bid": bid_double}
  • selection_signals : JSON objects specified in the auction configuration object

خروجی:

  • status : 0 for success, non-zero for failure
  • result : one of the outcomes passed in or null

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 : see the documentation of scoreAds
  • render_url : the render URL of the winning ad
  • bid : the bid offered for the winning ad
  • contextual_signals : see the documentation of generateBid

خروجی:

  • status: 0 for success and non-zero for failure
  • results : a JSON objects containing:
    • signals_for_buyer : a JSON object that is passed to the reportWin function
    • reporting_url : a URL that is used by the platform to notify the impression to the buyer

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 : see the documentation for scoreAd
  • signals_for_buyer : a JSON object returned by reportResult
  • contextual_signals, custom_audience_signals : see the documentation for generateBid

خروجی:

  • status: 0 for success and non-zero for failure
  • results : a JSON object containing:
    • reporting_url : a URL that is used by the platform to notify the impression to the seller

registerAdBeacon()

function registerAdBeacon(
  beacons
)

Input Parameters :

  • beacons : An object containing key-value pairs of interaction keys and reporting URIs. قالب این است:

    let beacons = {
      'interaction_key': 'reporting_uri',
      'interaction_key': 'reporting_uri',
      ...
    }
    
    • interaction_key : A string representing the event. This is used by the platform later when reporting event interactions to look up the reporting_uri that should be notified. This key needs to match between what the buyer or seller is registering, and what the seller is reporting.
    • reporting_uri : A URI to receive event reports. This should be specific to the event type being reported. It must accept a POST request to handle any data reported along with the event.

    به عنوان مثال:

      let beacons = {
        'click': 'https://reporting.example.com/click_event',
        'view': 'https://reporting.example.com/view_event'
      }
    

Ad Selection prebuilt URIs

Prebuilt URIs give ad techs the ability to appoint JavaScript functions for ad selection decision logic in the AdSelectionConfig and AdSelectionFromOutcomesConfig classes. Prebuilt URIs don't require network calls to download the corresponding JavaScript. Ad techs can use prebuilt URIs without having to set up an enrolled domain to host the JavaScript.

A prebuilt URI is constructed using the following format:

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

The Privacy Sandbox platform provides JavaScript using the information from this URI in the runtime.

An IllegalArgumentException is thrown if:

  • any of the required parameters are not present in the URI
  • there are unrecognized parameters in the URI

Supported prebuilt URI use cases and names

Use case 1: ad-selection

Prebuilt URIs under the ad-selection use case are supported in the selectAds(AdSelectionConfig) flow.

Prebuilt URI name: highest-bid-wins

This prebuilt URI provides a JavaScript that picks the ad with the highest bid after bidding. It also provides a basic reporting function to report the winner's render_uri and bid .

Required parameters

reportingUrl : The base reporting URL that is parameterized with the render_uri and the bid of the winning ad:

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

استفاده

If your base reporting URL is https://www.ssp.com/reporting then the prebuilt URI would be:

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

Use case 2: ad-selection-from-outcomes

Prebuilt URIs under the ad-selection-from-outcomes use case support the selectAds(AdSelectionFromOutcomesConfig) workflow.

Prebuilt URI name: waterfall-mediation-truncation

The waterfall-mediation-truncation prebuilt URI provides JavaScript that implements waterfall mediation truncation logic where the JavaScript returns a first-party ad if the bid is higher then or equal to the bid floor , and otherwise returns null .

Required parameters

bidFloor : The key of the bid floor value passed in the getSelectionSignals() that is compared against the mediation SDK's ad.

استفاده

If your ad selection signals look like {"bid_floor": 10} then the resulting prebuilt URI would be:

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

تست کردن

To help you get started with the Protected Audience API, we've created sample apps in Kotlin and Java, which can be found on GitHub .

پیش نیازها

The Protected Audience API requires some JavaScript during ad selection and impression reporting. There are two methods of providing this JavaScript in a testing environment:

  • Run a server with the required HTTPS endpoints that returns the JavaScript
  • Override remote fetching by providing the necessary code from a local source

Either approach requires setting up an HTTPS endpoint to handle impression reporting.

HTTPS endpoints

To test ad selection and impression reporting, you need to set up 7 HTTPS endpoints that your test device or emulator can access:

  1. Buyer endpoint that serves the bidding logic JavaScript.
  2. An endpoint that serves the bidding signals.
  3. Seller endpoint that serves the decision logic JavaScript.
  4. An endpoint that serves scoring signals.
  5. Winning buyer impression reporting endpoint.
  6. Seller impression reporting endpoint.
  7. An endpoint to serve the daily updates for a custom audience.

For convenience, the GitHub repo provides basic JavaScript code for testing purposes. It also includes OpenAPI service definitions which can be deployed to a supported mock or microservices platform. For more details, see the project README .

Override remote fetching of JavaScript

This feature is intended to be used for end-to-end testing. To override remote fetching, your app must run in debug mode with developer options enabled.

To enable debug mode for your application, add the following line to the application attribute in your AndroidManifest.xml:

<application
  android:debuggable="true">

For an example of how to use these overrides, please see the the Protected Audience API sample app on GitHub.

You need to add your own custom JavaScript to handle ad selection routines such as bidding, scoring decisions, and reporting. You can find basic JavaScript code examples that handle all required requests in the GitHub repo . The Protected Audience API sample application demonstrates how to read code from that file and prepare it for use as an override.

It is possible to override sell-side and buy-side JavaScript fetching independently, though you need an HTTPS endpoint to serve any JavaScript you aren't providing overrides for. Please see the README for information about how to set up a server that handles these cases.

It is only possible to override JavaScript fetching for custom audiences that are owned by your package.

Override sell-side JavaScript

To set up an override of sell-side JavaScript, do the following as demonstrated in the following code example:

  1. Initialize an AdSelectionManager object.
  2. Get a reference to TestAdSelectionManager from the AdSelectionManager object.
  3. Build an AdSelectionConfig object.
  4. Build an AddAdSelectionOverrideRequest with the AdSelectionConfig object and a String representing the JavaScript you intend to use as an override.
  5. Call the asynchronous overrideAdSelectionConfigRemoteInfo() method with the AddAdSelectionOverrideRequest object and relevant Executor and OutcomeReceiver objects.

کاتلین

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)

جاوا

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

See the Run ad selection section for more information about what each of the fields in the AdSelectionConfig represent. The key difference is that the decisionLogicUrl can be set to a placeholder value as it will be ignored.

In order to override the JavaScript used during ad selection, the decisionLogicJs must contain the proper seller-side function signatures . For an example of how to read a JavaScript file as a string, please see the Protected Audience API sample app on GitHub.

The asynchronous overrideAdSelectionConfigRemoteInfo() method uses the OutcomeReceiver object to signal the result of the API call.

The onResult() callback signifies the override was applied successfully. Future calls to selectAds() will use whatever decision and reporting logic you have passed in as the override.

The onError() callback signifies two possible conditions:

  • If the override is attempted with invalid arguments, the AdServiceException indicates an IllegalArgumentException as the cause.
  • If the override is attempted with an app not running in debug mode with developer options enabled, the AdServiceException indicates IllegalStateException as the cause.

Reset sell-side overrides

This section assumes that you have overridden the sell-side JavaScript and that you have a reference to the TestAdSelectionManager and AdSelectionConfig used in the previous section.

In order to reset the overrides for all AdSelectionConfigs :

  1. Call the asynchronous resetAllAdSelectionConfigRemoteOverrides() method with the relevant OutcomeReceiver object.

کاتلین

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

جاوا

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

After you reset sell-side overrides, calls to selectAds() use whatever decisionLogicUrl is stored in the AdSelectionConfig to attempt to fetch the required JavaScript.

If the call to resetAllAdSelectionConfigRemoteOverrides() fails, the OutComeReceiver.onError() callback provides an AdServiceException . If the removal of overrides is attempted with an app not running in debug mode with developer options enabled, AdServiceException indicates IllegalStateException as the cause.

Override buy-side JavaScript

  1. Follow the steps to join a custom audience
  2. Build an AddCustomAudienceOverrideRequest with the buyer and name of the custom audience you wish to override, in addition to the bidding logic and data you wish to use as an override
  3. Call the asynchronous overrideCustomAudienceRemoteInfo() method with the AddCustomAudienceOverrideRequest object and relevant Executor and OutcomeReceiver objects

کاتلین

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)

جاوا

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

The values for buyer and name are the same ones used to create the custom audience. Learn more about these fields .

Additionally, you can specify two additional parameters:

  • biddingLogicJs : JavaScript that holds the buyer's logic that is used during ad selection. See the required function signatures in this JavaScript.
  • trustedBiddingSignals : Bidding signals to be used during ad selection. For testing purposes this can be an empty string.

The asynchronous overrideCustomAudienceRemoteInfo() method uses the OutcomeReceiver object to signal the result of the API call.

The onResult() callback signifies the override was applied successfully. Subsequent calls to selectAds() use whatever bidding and reporting logic you have passed in as the override.

The onError() callback signifies two possible conditions.

  • If the override is attempted with invalid arguments, the AdServiceException indicates an IllegalArgumentException as the cause.
  • If the override is attempted with an app not running in debug mode with developer options enabled, the AdServiceException indicates IllegalStateException as the cause.

Reset buy-side overrides

This section assumes that you have overridden the buy-side JavaScript and that you have a reference to the TestCustomAudienceManager used in the previous section.

To reset overrides for all custom audiences:

  1. Call the asynchronous resetAllCustomAudienceOverrides() method with relevant Executor and OutcomeReceiver objects.

کاتلین

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

جاوا

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

After you reset buy-side overrides, subsequent calls to selectAds() use whatever biddingLogicUrl and trustedBiddingData is stored in the CustomAudience to attempt to fetch the required JavaScript.

If the call to resetCustomAudienceRemoteInfoOverride() fails, the OutComeReceiver.onError() callback provides an AdServiceException . If the removal of overrides is attempted with an app not running in debug mode with developer options enabled, the AdServiceException indicates IllegalStateException as the cause.

Set Up a Reporting Server

When you use remote fetching overrides, you'll still need to set up a server that your device or emulator can reach to respond to reporting events. A simple endpoint that returns 200 is sufficient for testing. The GitHub repo includes OpenAPI service definitions which can be deployed to a supported mock or microservices platform. For more details, see the project README .

When looking for the OpenAPI definitions, look for the reporting-server.json. This file contains a simple endpoint that returns 200, representing an HTTP response code. This endpoint is used during selectAds() and signals to the Protected Audience API that impression reporting completed successfully.

Functionality to test

  • Exercise joining or leaving and setting up a custom audience based on prior user actions.
  • Exercise the initiation of on-device ad selection through JavaScripts hosted remotely.
  • Observe how an app's association with custom audience settings may affect ad selection outcomes.
  • Exercise impression reporting after ad selection.

محدودیت ها

The following table lists limitations for the Protected Audience API processing. The limits presented could be subject to change based on feedback. For in-progress capabilities, read the release notes .

جزء Limit Description مقدار محدود
Custom audience (CA) Maximum number of ads per CA 100
Maximum number of CAs per application 1000
Maximum number of apps that can create a CA 1000
Maximum delay in the activation time of a CA from its creation time 60 روز
Maximum expiration time of a CA from its activation time 60 روز
Maximum number of CAs on device 4000
Maximum size of CA name 200 bytes
Maximum size of daily fetch URI 400 bytes
Maximum size of bidding logic URI 400 bytes
Maximum size of trusted bidding data 10 کیلوبایت
Maximum size of user bidding signals 10 کیلوبایت
Maximum call rate for leaveCustomAudience per buyer 1 در ثانیه
Maximum call rate for joinCustomAudience per buyer 1 در ثانیه
CA Background Fetch مهلت زمانی اتصال 5 ثانیه
HTTP read timeout 30 ثانیه
Maximum total download size 10 کیلوبایت
Max duration of a fetch iteration 5 دقیقه
Maximum number of CAs updated per job 1000
انتخاب آگهی Maximum number of buyers TBD
Maximum number of CAs per buyer TBD
Maximum number of ads in an auction TBD
Initial connection timeout 5 ثانیه
Connection read timeout 5 ثانیه
Maximum execution time of overall AdSelection 10 ثانیه
Maximum execution time of bidding per CA in AdSelection 5 second
Maximum execution time of scoring in AdSelection 5 second
Maximum execution time for per buyer in AdSelection TBD
Maximum size of ad selection/seller/per buyer signals TBD
Maximum size of seller/buyer scripts TBD
Maximum call rate for selectAds 1 QPS
Impression reporting Minimum time before removing ad selection from persistence 24 ساعت
Maximum number of storage ad selections TBD
Maximum size of reporting output URL TBD
Maximum time for impression reporting TBD
Maximum number of retries for notification calls TBD
پایان زمان اتصال 5 ثانیه
Maximum overall execution time for reportImpression 2 ثانیه
Maximum call rate for reportImpressions 1 QPS
گزارش رویداد Maximum number of beacons per buyer per auction 10

Maximum number of beacons per seller per auction

10

Maximum size of event key

40 bytes

Maximum size of event data

64 کیلوبایت

تبلیغات Maximum size of ad list 10 KB shared by all AdData in a single CA for contextual
URL ها Maximum length of any URL string taken as input TBD
جاوا اسکریپت حداکثر زمان اجرا 1 second for bidding and scoring for impression reporting
Maximum memory used 10 مگابایت

Report bugs and issues

Your feedback is a crucial part of the Privacy Sandbox on Android! Let us know of any issues you find or ideas for improving Privacy Sandbox on Android.

{% verbatim %} {% endverbatim %} {% verbatim %} {% endverbatim %}