راهنمای توسعه دهنده برنامه Protected Signals

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

تاریخچه نسخه

ژانویه ۲۰۲۴

اولین انتشار راهنمای توسعه‌دهندگان که از انتشار PAS MVP پشتیبانی می‌کند

مارس ۲۰۲۴

تغییرات در API برای پشتیبانی از نسخه M-2024-05 رابط برنامه‌نویسی اندروید و نسخه آوریل 2024 اجزای سمت سرور. قابل توجه‌ترین تغییرات:

  • جزئیات مربوط به مجوزهای مورد نیاز برای API روی دستگاه اضافه شد
  • جزئیاتی در مورد مدیریت سهمیه سیگنال‌های روی دستگاه اضافه شد
  • امضای generateBid با تغییرات مرتبط با بازیابی تبلیغات متنی و پشتیبانی از خروجی به‌روزرسانی شد.
  • مستندات reportWin به‌روزرسانی شد که شامل پشتیبانی از خروجی (egress) نیز می‌شود.
  • به‌روزرسانی مستندات API بازیابی تبلیغات، حذف پشتیبانی از بازیابی تبلیغات BYOS و مستندسازی UDF بازیابی تبلیغات

مرور کلی API

رابط برنامه‌نویسی کاربردی سیگنال‌های محافظت‌شده (Protected Signals API) شامل زیرمجموعه‌های مختلفی از API در سیستم‌های مختلف است:

  • API های اندروید:
    • API مربوط به گزینش سیگنال، متشکل از:
    • به‌روزرسانی API سیگنال‌ها
    • API رمزگذاری سیگنال‌ها
    • API پشتیبانی از حراج محافظت‌شده: برای استفاده توسط SDKها جهت اجرای حراج محافظت‌شده روی سرورهای پیشنهاد قیمت و حراج (B&A) با استفاده از سیگنال‌های برنامه محافظت‌شده.
  • API های سمت سرور:
    • API حراج محافظت‌شده: مجموعه‌ای از اسکریپت‌های JS که در سرورهای پیشنهاد قیمت و حراج اجرا می‌شوند. این API به فروشندگان و خریداران امکان می‌دهد منطق لازم برای پیاده‌سازی حراج محافظت‌شده را بنویسند.
    • رابط برنامه‌نویسی کاربردی بازیابی آگهی: مسئول ارائه فهرستی از آگهی‌های کاندید با توجه به اطلاعات زمینه‌ای و کاربری که در اختیار سرور پیشنهاددهنده خریدار قرار می‌گیرد.

کلاینت اندروید

در سمت کلاینت، سطح Protected App Signals از سه API مختلف تشکیل شده است:

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

به‌روزرسانی API سیگنال‌ها

API مربوط به به‌روزرسانی سیگنال‌ها (Update Signals API) به تکنسین‌های تبلیغات این امکان را می‌دهد که سیگنال‌های مرتبط با کاربر و برنامه را از طرف خریدار ثبت کنند. این API بر اساس مدل واگذاری (delegation model) کار می‌کند. فراخوانی‌کننده (caller) یک URI ارائه می‌دهد که چارچوب، سیگنال‌های مربوطه و منطق لازم برای رمزگذاری آن سیگنال‌ها را برای استفاده در حراج، از آن دریافت می‌کند.

این API به مجوز android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS نیاز دارد.

API updateSignals() یک شیء JSON را از URI بازیابی می‌کند که شرح می‌دهد کدام سیگنال‌ها باید اضافه یا حذف شوند و چگونه می‌توان آن سیگنال‌ها را برای حراج آماده کرد.

Executor executor = Executors.newCachedThreadPool();
ProtectedSignalsManager protectedSignalsManager
     =  ProtectedSignalsManager.get(context);

// Initialize a UpdateSignalsRequest
UpdateSignalsRequest updateSignalsRequest = new
  UpdateSignalsRequest.Builder(Uri.parse("https://example-adtech1.com/signals"))
      .build();

OutcomeReceiver<Object, Exception> outcomeReceiver = new OutcomeReceiver<Object, Exception>() {
  @Override
  public void onResult(Object o) {
    //Post-success actions
  }

  @Override
  public void onError(Exception error) {
    //Post-failure actions
  };

// Call updateSignals
protectedSignalsManager.updateSignals(updateSignalsRequest,
    executor,
    outcomeReceiver);

این پلتفرم یک درخواست https به URI ارائه شده در درخواست برای دریافت به‌روزرسانی‌های سیگنال ارسال می‌کند. همراه با به‌روزرسانی‌های سیگنال، پاسخ می‌تواند شامل یک نقطه پایانی باشد که منطق کدگذاری را برای تبدیل سیگنال‌های خام به محتوای کدگذاری شده میزبانی می‌کند. انتظار می‌رود به‌روزرسانی‌های سیگنال به شکل JSON باشند و می‌توانند کلیدهای زیر را داشته باشند:

کلیدهای سطح بالا برای شیء JSON باید با یکی از پنج دستور زیر مطابقت داشته باشند:

کلید

توضیحات

put

یک سیگنال جدید اضافه می‌کند و سیگنال‌های موجود را با همان کلید بازنویسی می‌کند. مقدار

برای این یک شیء JSON وجود دارد که در آن کلیدها رشته‌های پایه ۶۴ مربوط به کلیدی هستند که باید قرار داده شوند و مقادیر رشته‌های پایه ۶۴ مربوط به مقداری هستند که باید قرار داده شوند.

append

سیگنال/سیگنال‌های جدیدی را به یک سری زمانی از سیگنال‌ها اضافه می‌کند و قدیمی‌ترین را حذف می‌کند.

سیگنال‌هایی برای ایجاد فضا برای سیگنال‌های جدید در صورتی که اندازه سری از حداکثر داده شده بیشتر شود. مقدار این یک شیء JSON است که در آن کلیدها رشته‌های پایه ۶۴ مربوط به کلیدی هستند که باید به آن اضافه شود و مقادیر، اشیاء با دو فیلد هستند: "values" و "maxSignals".

«مقادیر»: فهرستی از رشته‌های پایه ۶۴ تایی مربوط به مقادیر سیگنال برای افزودن به سری زمانی.

"maxSignals": حداکثر تعداد مقادیری که در این سری زمانی مجاز هستند. اگر

اگر تعداد فعلی سیگنال‌های مرتبط با کلید از maxSignals بیشتر شود، قدیمی‌ترین سیگنال‌ها حذف خواهند شد. توجه داشته باشید که می‌توانید با put به کلیدی که اضافه کرده‌اید، مقدار اضافه کنید. توجه داشته باشید که اضافه کردن بیش از حداکثر تعداد مقادیر باعث خرابی می‌شود.

put_if_not_present

فقط در صورتی که هیچ سیگنال موجودی با کلید مشابه وجود نداشته باشد، یک سیگنال جدید اضافه می‌کند. مقدار این یک شیء JSON است که در آن کلیدها رشته‌های پایه ۶۴ مربوط به کلیدی هستند که باید قرار داده شوند و مقادیر رشته‌های پایه ۶۴ مربوط به مقداری هستند که باید قرار داده شوند.

remove

سیگنال مربوط به یک کلید را حذف می‌کند. مقدار این، فهرستی از رشته‌های پایه ۶۴ است که مربوط به کلیدهای سیگنال‌هایی است که باید حذف شوند.

update_encoder

یک اقدام برای به‌روزرسانی نقطه پایانی و یک URI که می‌تواند مورد استفاده قرار گیرد، ارائه می‌دهد.

برای بازیابی منطق کدگذاری. زیرکلید برای ارائه یک عمل به‌روزرسانی، "action" است و

مقادیر پشتیبانی‌شده فقط "REGISTER" است که در صورت ارائه برای اولین بار، نقطه پایانی رمزگذار را ثبت می‌کند یا نقطه پایانی موجود را با نقطه پایانی جدید ارائه شده جایگزین می‌کند. ارائه نقطه پایانی برای اقدام "REGISTER" الزامی است. زیرکلید برای ارائه نقطه پایانی رمزگذار، "endpoint" و مقدار آن URI است.

رشته برای نقطه پایانی.

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

{
    "put": {
        "AAAAAQ==": "AAAAZQ==",
        "AAAAAg==": "AAAAZg=="
    },
    "append": {
        "AAAAAw==": {
            "values": [
                "AAAAZw=="
            ],
            "max_signals": 3
        }
    },
    "put_if_not_present": {
        "AAAABA==": "AAAAaQ==",
        "AAAABQ==": "AAAAag=="
    },
    "update_encoder": {
        "action": "REGISTER",
        "endpoint": "https://adtech1.com/Protected App Signals_encode_script.js"
    }
}

سیگنال‌ها سهمیه‌ای در حدود ۱۰ تا ۱۵ کیلوبایت روی دستگاه خواهند داشت. به محض اینکه سهمیه از حد مجاز فراتر رود، PPAPI با استفاده از استراتژی FIFO سیگنال‌ها را حذف می‌کند. فرآیند حذف سیگنال‌ها به شما این امکان را می‌دهد که برای مدت کوتاهی از سهمیه تعیین شده کمی فراتر بروید تا تعداد دفعات حذف سیگنال‌ها کاهش یابد.

API رمزگذاری سیگنال‌ها

خریداران ملزم به ارائه یک تابع جاوا اسکریپت هستند که برای رمزگذاری سیگنال‌های ذخیره شده در دستگاه جهت ارسال به سرور در طول حراج محافظت‌شده استفاده می‌شود. خریداران می‌توانند این اسکریپت را با اضافه کردن URL که می‌توان آن را با استفاده از کلید "update_encoder" در هر یک از پاسخ‌ها به درخواست UpdateSignal API دریافت کرد، ارائه دهند. این اسکریپت دارای امضای زیر خواهد بود:

function encodeSignals(signals, maxSize) {
  let result = new Uint8Array(maxSize);
  // first entry will contain the total size
  let size = 1;
  let keys = 0;
  
  for (const [key, values] of signals.entries()) {
    keys++;
    // In this encoding we only care about the first byte
    console.log("key " + keys + " is " + key)
    result[size++] = key[0];
    result[size++] = values.length;
    for(const value of values) {
      result[size++] = value.signal_value[0];
    }
  }
  result[0] = keys;
  
  return { 'status': 0, 'results': result.subarray(0, size)};
}

پارامتر signals یک نگاشت از کلیدهایی به شکل آرایه‌های UInt8 با اندازه ۴ به لیست‌هایی از اشیاء Protected App Signals است. هر شیء Protected App Signals دارای سه فیلد است:

  • signal_value : یک آرایه UInt8Array که مقدار سیگنال را نشان می‌دهد.
  • creation_time : عددی که زمان ایجاد سیگنال‌ها را بر حسب epoch-seconds نشان می‌دهد.
  • package_name : رشته‌ای که نام بسته‌ای که سیگنال را ایجاد کرده است را نشان می‌دهد.

پارامتر maxSize عددی است که بزرگترین اندازه آرایه مجاز برای خروجی را توصیف می‌کند.

این تابع باید یک شیء با دو فیلد را خروجی دهد:

  • status : اگر اسکریپت با موفقیت اجرا شود، باید 0 باشد.
  • results : باید یک UInt8Array با طول کمتر یا مساوی maxSize باشد. این آرایه در طول مزایده‌ها به سرور ارسال می‌شود و توسط اسکریپت prepareDataForAdRetrieval آماده می‌شود.

این کدگذاری، مرحله اولیه مهندسی ویژگی را در اختیار تکنسین‌های تبلیغات قرار می‌دهد، جایی که می‌توانند بر اساس منطق سفارشی خود، تبدیل‌هایی مانند فشرده‌سازی سیگنال‌های خام به نسخه‌های به‌هم‌پیوسته را انجام دهند. توجه داشته باشید که در طول یک حراج محافظت‌شده که در محیط‌های اجرای مطمئن (TEE) اجرا می‌شود، منطق سفارشی تکنسین تبلیغات به داده‌های سیگنال تولید شده توسط کدگذاری دسترسی خواهد داشت. منطق سفارشی، که به عنوان یک تابع تعریف‌شده توسط کاربر (UDF) شناخته می‌شود و در TEE B&A خریدار اجرا می‌شود، به سیگنال‌های کدگذاری‌شده و سایر سیگنال‌های زمینه‌ای ارائه شده توسط برنامه ناشر برای انجام انتخاب آگهی (بازیابی و پیشنهاد قیمت آگهی) دسترسی خواهد داشت.

رمزگذاری سیگنال‌ها

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

adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
نسخه‌بندی منطق انکودر

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

Response header for providing encoder version : X_ENCODER_VERSION

API پشتیبانی حراج محافظت‌شده

از طرف دستگاه، اجرای حراج برای سیگنال‌های برنامه محافظت‌شده مشابه اجرای حراج برای مخاطبان محافظت‌شده است.

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

API های سمت سرور شامل موارد زیر هستند:

  • API حراج محافظت‌شده: مجموعه‌ای از توابع JS یا UDFها که خریداران و فروشندگان می‌توانند روی اجزای B&A که در اختیار دارند، مستقر کنند تا منطق پیشنهاد قیمت و حراج را تعیین کنند.
  • API بازیابی تبلیغات: خریداران می‌توانند این API را با پیاده‌سازی یک REST Endpoint پیاده‌سازی کنند که مسئول ارائه مجموعه‌ای از تبلیغات کاندید برای حراج Protected App Signal خواهد بود.

API حراج محافظت‌شده

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

UDF های فناوری تبلیغات خریدار
آماده‌سازی داده‌ها برای بازیابی تبلیغات UDF

قبل از اینکه بتوان از Protected App Signals برای دریافت نامزدهای تبلیغاتی از سرویس TEE Ad Retrieval استفاده کرد، خریداران باید Protected App Signals و سایر داده‌های ارائه شده توسط فروشنده را رمزگشایی و آماده کنند. خروجی UDF خریداران prepareDataForAdRetrieval به سرویس بازیابی تبلیغات منتقل می‌شود تا k نامزد برتر تبلیغات را برای پیشنهاد قیمت بازیابی کند .

// Inputs
// ------
// encodedOnDeviceSignals: A Uint8Array of bytes from the device.
// encodedOnDeviceSignalsVersion: An integer representing the encoded
//   version of the signals.
// sellerAuctionSignals: Information about auction (ad format, size) derived
//                       contextually.
// contextualSignals: Additional contextual signals that could help in
//                    generating bids.
//
// Outputs
// -------
// Returns a JSON structure to be used for retrieval.
// The structure of this object is left to the ad tech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
   return {};
}
تولید UDF با قیمت پیشنهادی

پس از اینکه k تبلیغ برتر انتخاب شدند، تبلیغات به منطق پیشنهاد قیمت سفارشی خریدار، generateBid UDF ، ارسال می‌شوند:

// Inputs
// ------
// ads: Data string returned by the ads retrieval service. This can include Protected App Signals
//   ads and related ads metadata.
// sellerAuctionSignals: Information about the auction (ad format, size),
//                       derived contextually
// buyerSignals: Any additional contextual information provided by the buyer
// preprocessedDataForRetrieval: This is the output of this UDF.
function generateBid(ads, sellerAuctionSignals, buyerSignals,
                    preprocessedDataForRetrieval,
                    rawSignals, rawSignalsVersion) {
    return { "ad": <ad Value Object>,
             "bid": <float>,
             "render": <render URL string>,
             'adCost': <optional float ad cost>,
             "egressPayload": <limitedEgressPayload>,
             "temporaryUnlimitedEgressPayload": <temporaryUnlimitedEgressPayload>
    };
}

خروجی این تابع یک پیشنهاد قیمت واحد برای یک کاندید تبلیغ است که به صورت یک JSON معادل ProtectedAppSignalsAdWithBidMetadata نمایش داده می‌شود. این تابع همچنین می‌تواند دو آرایه را برگرداند که سپس به reportWin منتقل می‌شوند تا آموزش مدل را فعال کنند (برای جزئیات بیشتر در مورد خروجی و آموزش مدل به بخش گزارش‌دهی در توضیح PAS مراجعه کنید).

گزارش ویندوز UDF

وقتی یک حراج به پایان می‌رسد، سرویس حراج، URLهای گزارش‌دهی را برای خریداران ایجاد می‌کند و با استفاده از reportWin UDF (این همان تابع reportWin است که برای مخاطبان محافظت‌شده استفاده می‌شود) بیکن‌ها را ثبت می‌کند. این تابع پس از رندر شدن تبلیغ توسط کلاینت، توسط دستگاه پینگ می‌شود. امضای این متد تقریباً مشابه نسخه مخاطبان محافظت‌شده است، به جز دو پارامتر اضافی egressPayload و temporaryUnlimitedEgressPayload که برای فعال کردن آموزش مدل استفاده می‌شوند و با نتایج generateBid پر می‌شوند.

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals,
                   egressPayload, temporaryUnlimitedEgressPayload) {
  // ...
}
UDF های فناوری تبلیغات فروشنده
امتیاز تبلیغات UDF

این UDF توسط فروشندگان برای انتخاب اینکه کدام یک از تبلیغات دریافتی از خریداران در حراج برنده شود، استفاده می‌شود.

function scoreAd(adMetadata, bid, auctionConfig,
                 trustedScoringSignals, bid_metadata) {
  // ...
  return {desirability: desirabilityScoreForThisAd,
              allowComponentAuction: true_or_false};
}
گزارش نتیجه UDF

این UDF به فروشنده اجازه می‌دهد (در نهایت) گزارش سطح رویداد را با اطلاعات مربوط به آگهی برنده انجام دهد.

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

API بازیابی تبلیغات

در نسخه MVP، سرویس بازیابی تبلیغات، یک سرویس مدیریت و میزبانی شده توسط خریدار خواهد بود و سرویس پیشنهاد قیمت، نامزدهای تبلیغاتی را از این سرویس بازیابی می‌کند. از آوریل 2024، سرور بازیابی تبلیغات باید در یک محیط اجرای قابل اعتماد (TEE) اجرا شود و یک رابط GRPC/proto را در معرض نمایش قرار دهد. شرکت‌های فناوری تبلیغات باید این سرور را راه‌اندازی کرده و URL آن را به عنوان بخشی از استقرار پشته B&A ارائه دهند. پیاده‌سازی این سرویس که در TEE اجرا می‌شود، در Privacy Sandbox GitHub موجود است و در بقیه مستندات، فرض می‌کنیم که این کدی است که در استقرار استفاده می‌شود.

از آوریل ۲۰۲۴، نسخه‌های B&A از بازیابی تبلیغات مبتنی بر مسیر متنی پشتیبانی می‌کنند. در این حالت، سرور پیشنهاددهنده فهرستی از شناسه‌های تبلیغاتی ارسال‌شده توسط سرور RTB را در طول بخش متنی حراج دریافت می‌کند. شناسه‌ها به یک سرور TEE KV ارسال می‌شوند تا تمام اطلاعات مربوط به تبلیغات را که قرار است در طول مرحله پیشنهاددهی استفاده شوند (به عنوان مثال، ad-render-url، فراداده و جاسازی‌های تبلیغاتی که در انتخاب k مورد برتر استفاده می‌شوند) دریافت کنند. این مسیر دوم نیازی به منطق خاصی برای پیاده‌سازی ندارد، بنابراین ما در اینجا فقط نحوه پیکربندی مورد استفاده بازیابی تبلیغات مبتنی بر TEE را مستند خواهیم کرد.

دریافت UDF کاندیدای تبلیغات
function getCandidateAds(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals, contextualAdIds,) {
    return adsMetadataString;
}

کجا:

  • requestMetadata : JSON. فراداده‌های سرور به ازای هر درخواست به UDF. فعلاً خالی است.
  • preparedDataForAdRetrieval : محتوای این فیلد به استراتژی بازیابی تبلیغ بستگی دارد. در صورت بازیابی تبلیغ زمینه‌ای، این پارامتر شامل سیگنال‌های خامی خواهد بود که از دستگاه سرچشمه می‌گیرند و از سرویس پیشنهاد دهنده منتقل می‌شوند. در صورت بازیابی تبلیغ TEE با استفاده از سرور بازیابی تبلیغ، این پارامتر شامل نتیجه UDF prepareDataForAdRetrieval خواهد بود. توجه: در این مرحله، سیگنال‌های برنامه محافظت‌شده رمزگشایی و رمزگشایی می‌شوند.
  • deviceMetadata : شیء JSON حاوی فراداده‌های دستگاه که توسط سرویس تبلیغات فروشنده ارسال می‌شود. برای جزئیات بیشتر به مستندات B&A مراجعه کنید.
    • X-Accept-Language : زبانی که در دستگاه استفاده می‌شود.
    • X-User-Agent : عامل کاربری که روی دستگاه استفاده می‌شود.
    • X-BnA-Client-IP : آدرس IP دستگاه.
  • contextualSignals : رشته دلخواهی که از سرور پیشنهاد دهنده متنی که توسط همان DSP اداره می‌شود، سرچشمه گرفته است. انتظار می‌رود UDF بتواند رشته را رمزگشایی کرده و از آن استفاده کند. Contextual Signals ممکن است حاوی هرگونه اطلاعاتی مانند اطلاعات نسخه مدل ML برای جاسازی محافظت‌شده ارسال شده با استفاده از Protected App Signals باشد.
  • contextualAdIds : شیء JSON حاوی لیستی اختیاری از شناسه‌های تبلیغ.

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

سیستم خود را برای توسعه تنظیم کنید

اندروید

برای راه‌اندازی محیط توسعه اندروید خود، باید موارد زیر را انجام دهید:

  1. یک شبیه‌ساز (ترجیحاً) یا دستگاه فیزیکی که تصویر Developer Preview 10 را اجرا می‌کند، ایجاد کنید.
  2. دستور زیر را اجرا کنید:
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity

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

  1. دستور زیر را برای فعال کردن APIهای مربوطه اجرا کنید. ممکن است لازم باشد گاهی اوقات این دستور را دوباره اجرا کنید زیرا پیکربندی پیش‌فرض غیرفعال به صورت دوره‌ای همگام‌سازی می‌شود.
adb shell device_config put adservices fledge_custom_audience_service_kill_switch false;  adb shell device_config put adservices fledge_select_ads_kill_switch false; adb shell device_config put adservices fledge_on_device_auction_kill_switch false; adb shell device_config put adservices fledge_auction_server_kill_switch false; adb shell "device_config put adservices disable_fledge_enrollment_check true";  adb shell device_config put adservices ppapi_app_allow_list '\*'; adb shell device_config put adservices fledge_auction_server_overall_timeout_ms 60000;
  1. دستگاه را مجدداً راه اندازی کنید.
  2. کلیدهای حراج دستگاه را برای اشاره به سرور کلید حراج خود لغو کنید. اجرای این مرحله قبل از تلاش برای اجرای حراج برای جلوگیری از ذخیره کلیدهای نادرست، مهم است.

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

برای راه‌اندازی سرورهای B&A، به مستندات راه‌اندازی سلف سرویس مراجعه کنید.

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

پیش‌نیازها

قبل از استقرار یک مجموعه خدمات B&A، تکنسین تبلیغات خریدار باید:

  • تأیید کنید که آنها سرویس بازیابی تبلیغات TEE خود را مستقر کرده‌اند (به بخش مربوطه مراجعه کنید).
  • تأیید کنید که تکنسین تبلیغات، تمام UDF های لازم ( prepareDataForAdRetrieval ، generateBid ، reportWin ، getCandidateAds ) را تعریف و میزبانی کرده باشد.

درک نحوه‌ی عملکرد حراج محافظت‌شده با مخاطب محافظت‌شده با B&A نیز مفید خواهد بود اما اجباری نیست.

پیکربندی Terraform

برای استفاده از سیگنال‌های برنامه محافظت‌شده، تکنسین‌های تبلیغات باید:

  • پشتیبانی از سیگنال‌های برنامه‌ی محافظت‌شده را در B&A فعال کنید.
  • نقاط انتهایی URL را ارائه دهید که UDF های جدید برای prepareDataForAdRetrieval, generateBid و reportWin بتوانند از آنها دریافت شوند.

علاوه بر این، این راهنما فرض می‌کند که تکنسین‌های تبلیغاتی که می‌خواهند از B&A برای بازاریابی مجدد استفاده کنند، طبق معمول تمام پرچم‌های پیکربندی موجود را برای حراج بازاریابی مجدد تنظیم می‌کنند.

پیکربندی فناوری تبلیغات خریدار

با استفاده از این فایل نمایشی به عنوان نمونه، خریداران باید پرچم‌های زیر را تنظیم کنند:

  • فعال کردن سیگنال‌های برنامه محافظت‌شده : برای جمع‌آوری داده‌های سیگنال‌های برنامه محافظت‌شده فعال شده است.
  • URLهای سیگنال‌های برنامه محافظت‌شده : روی URLهای سرورهای سیگنال‌های برنامه محافظت‌شده تنظیم کنید.

تکنسین‌های تبلیغات باید URL های صحیح را در متغیرهای فیلدهای زیر جایگزین کنند:

module "buyer" {
  # ... More config here.

  runtime_flags = {
    # ... More config here.

    ENABLE_PROTECTED_APP_SIGNALS                  = "true"
    PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS = "60000"
    TEE_AD_RETRIEVAL_KV_SERVER_ADDR               = "<service mesh address of the instance>"
    AD_RETRIEVAL_TIMEOUT_MS                       = "60000"
    BUYER_CODE_FETCH_CONFIG                       = <<EOF
    {
        "protectedAppSignalsBiddingJsUrl": "<URL to Protected App Signals generateBid UDF>",
        "urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
        "urlFetchPeriodMs": 13000000,
        "prepareDataForAdsRetrievalJsUrl": "<URL to the UDF>"
    }
    EOF

  }  # runtime_flags

}  # Module "buyer"

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

با استفاده از این فایل نمایشی به عنوان مثال، فروشندگان باید پرچم‌های زیر را تنظیم کنند. (توجه: فقط پیکربندی مربوط به Protected App Signals در اینجا هایلایت شده است). تکنسین‌های تبلیغات باید تأیید کنند که URL های صحیح را در placeholders جایگزین می‌کنند:

module "seller" {
  # ... More config here.

  runtime_flags = {
    # ... More config here.

    ENABLE_PROTECTED_APP_SIGNALS                  = "true"

    SELLER_CODE_FETCH_CONFIG                           = <<EOF
  {
    "urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
    "urlFetchPeriodMs": 13000000,
    "protectedAppSignalsBuyerReportWinJsUrls": {"<Buyer Domain>": "URL to reportWin UDF"}
  }
  EOF

  }  # runtime_flags

}  # Module "seller"

خدمات بازیابی اطلاعات و تبلیغات (KV)

بسته به استراتژی‌های انتخاب شده برای پشتیبانی از بازیابی آگهی، سیستم به استقرار یک یا دو نمونه از سرویس KV نیاز خواهد داشت. ما به نمونه KV مورد استفاده برای بازیابی آگهی مبتنی بر TEE، Ad Retrieval Server و به نمونه‌ای که از بازیابی مبتنی بر مسیر زمینه‌ای پشتیبانی می‌کند، KV Lookup Server می‌گوییم.

در هر دو مورد، استقرار سرورها از مستندات موجود در GitHub سرور KV پیروی می‌کند، تفاوت بین این دو مورد این است که مورد جستجو بدون هیچ پیکربندی اضافی به صورت آماده کار می‌کند، در حالی که مورد بازیابی نیاز به استقرار getCandidateAds UDF برای پیاده‌سازی منطق بازیابی دارد. برای جزئیات بیشتر، به راهنمای راه‌اندازی سرور KV نگاهی بیندازید. توجه داشته باشید که B&A انتظار دارد هر دو سرویس در همان شبکه سرویس به عنوان سرویس پیشنهاد دهنده مستقر شوند.

مثال راه‌اندازی

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

[خریدار] نمونه‌های سیگنال

سیگنالی با کلید ۰ و مقدار ۱ اضافه می‌کند.

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

سیگنالی با کلید ۱ و مقدار ۲ اضافه می‌کند.

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

[خریدار] مثال رمزگذاری سیگنال‌ها

هر سیگنال را به دو بایت رمزگذاری می‌کند، که بایت اول، اولین بایت کلید سیگنال و بایت دوم، اولین بایت مقدار سیگنال است.

function encodeSignals(signals, maxSize) {
  // if there are no signals don't write a payload
  if (signals.size === 0) {
      return {};
  }

  let result = new Uint8Array(signals.size * 2);
  let index = 0;
  
  for (const [key, values] of signals.entries()) {
    result[index++] = key[0];
    result[index++] = values[0].signal_value[0];
  }
  
  return { 'status': 0, 'results': result};
}

[خریدار] مثال بازیابی اطلاعات برای تبلیغات

/**
 * `encodedOnDeviceSignals` is a Uint8Array and would contain
 * the app signals emanating from device. For purpose of the
 * demo, in our sample example, we assume that device is sending
 * the signals with pair of bytes formatted as following:
 * "<ID><In app spending>". Where ID corresponds to an ad category
 * that user uses on device, and the in app spending is a measure
 * of how much money the user has spent in this app category
 * previously. In our example, an ID of 0 will correspond to a
 * fitness ad category and a non-zero ID will correspond to
 * food app category -- though this info will be useful
 * later in the B&A pipeline.
 *
 * Returns a JSON object indicating what type of ad(s) may be
 * most relevant to the user. In a real setup ad techs might
 * want to decode the signals as part of this script.
 *
 * Note: This example script makes use of only encoded device signals
 * but ad tech can take other signals into account as well to prepare
 * the data that will be useful down stream for ad retrieval and
 * bid generation. The max length of the app signals used in this
 * sample example is arbitrarily limited to 4 bytes.
 */
function prepareDataForAdRetrieval(encodedOnDeviceSignals,
                                   encodedOnDeviceSignalsVersion,
                                   sellerAuctionSignals,
                                   contextualSignals) {
  if (encodedOnDeviceSignals.length === 0 || encodedOnDeviceSignals.length > 4 ||
      encodedOnDeviceSignals.length % 2 !== 0) {
     throw "Expected encoded signals length to be an even number in (0, 4]";
  }

  var preparedDataForAdRetrieval = {};
  for (var i = 0; i < encodedOnDeviceSignals.length; i += 2) {
    preparedDataForAdRetrieval[encodedOnDeviceSignals[i]] = encodedOnDeviceSignals[i + 1];
  }
  return preparedDataForAdRetrieval;
}

[خریداران] نمونه UDF بازیابی تبلیغات

در مثال ما، سرور بازیابی آگهی، فراداده (یعنی شناسه هر آگهی در این مثال، اما می‌تواند شامل داده‌های دیگری برای هر کدام باشد که می‌تواند در تولید پیشنهادهای بعدی مفید باشد) را برای هر یک از k کاندیدای برتر آگهی ارسال می‌کند.

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

[خریداران] تولید کنید مثال پیشنهاد قیمت

/**
 * This script receives the data returned by the ad retrieval service
 * in the `ads` argument. This argument is supposed to contain all
 * the Protected App Signals related ads and the metadata obtained from the retrieval
 * service.
 *
 * `preparedDataForAdRetrieval` argument contains the data returned
 * from the `prepareDataForAdRetrieval` UDF.
 *
 * This script is responsible for generating bids for the ads
 * collected from the retrieval service and ad techs can decide to
 * run a small inference model as part of this script in order to
 * decide the best bid given all the signals available to them.
 *
 * For the purpose of the demo, this sample script assumes
 * that ad retrieval service has sent us most relevant ads for the
 * user and this scripts decides on the ad render URL as well as
 * what value to bid for each ad based on the previously decoded
 * device signals. For simplicity sake, this script only considers
 * 2 types of app categories i.e. fitness and food.
 *
 * Note: Only one bid is returned among all the
 * input ad candidates.
 */
function generateBid(ads, sellerAuctionSignals, buyerSignals, preparedDataForAdRetrieval) {
  if (ads === null) {
    console.log("No ads obtained from the ad retrieval service")
    return {};
  }     
        
  const kFitnessAd = "0";
  const kFoodAd = "1";
  const kBuyerDomain = "https://buyer-domain.com";
        
  let resultingBid = 0;
  let resultingRender = kBuyerDomain + "/no-ad";
  for (let i = 0 ; i < ads.length; ++i) {
    let render = "";
    let bid = 0;
    switch (ads[i].adId) {
      case kFitnessAd:
        render = kBuyerDomain + "/get-fitness-app";
        bid = preparedDataForAdRetrieval[kFitnessAd];
        break;
      case kFoodAd:
        render = kBuyerDomain + "/get-fastfood-app";
        bid = preparedDataForAdRetrieval[kFoodAd];
        break;
      default:
        console.log("Unknown ad category");
        render = kBuyerDomain + "/no-ad";
        break;
    }
    console.log("Existing bid: " + resultingBid + ", incoming candidate bid: " + bid);
    if (bid > resultingBid) {
      resultingBid = bid;
      resultingRender = render;
    }
  }
  return {"render": resultingRender, "bid": resultingBid};
}

مثال گزارش [خریداران] برنده شوید

reportWin UDF به خریدار گزارش می‌دهد که آنها در مزایده برنده شده‌اند.

function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                                       buyerReportingSignals, directFromSellerSignals,
                                       egressPayload,
                                       temporaryUnlimitedEgressPayload) {
  sendReportTo("https://buyer-controlled-domain.com/");
  registerAdBeacon({"clickEvent":"https://buyer-controlled-domain.com/clickEvent"});
  return;
}

[فروشنده] راه اندازی سرور KV

فروشندگان باید یک سرور KV برای سیگنال‌های امتیازدهی راه‌اندازی کنند تا نگاشتی از URLهای رندر تبلیغات به سیگنال‌های امتیازدهی مربوطه در دسترس باشد، برای مثال: اگر https:/buyer-domain.com/get-fitness-app و https:/buyer-domain.com/get-fastfood-app توسط خریدار بازگردانده شوند، فروشنده می‌تواند هنگام درخواست SFE با استفاده از GET در https://key-value-server-endpoint.com?client_type=1&renderUrls=<render-url-returned-by-the-buyer> ، پاسخ سیگنال‌های امتیازدهی نمونه زیر را داشته باشد:

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

[فروشنده] امتیاز مثال تبلیغ

/**
 * This module generates a random desirability score for the Protected App
 * Signals ad in this example. In a production deployment,
 * however, the sellers would want to use all the available signals to generate
 * a score for the ad.
 */
function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

function scoreAd(adMetadata, bid, auctionConfig,
                                   trustedScoringSignals, deviceSignals,
                                   directFromSellerSignals) {
  return {
    "desirability": getRandomInt(10000),
    "allowComponentAuction": false
  };
}

مثال گزارش نتیجه [فروشنده]

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

نمونه برنامه

به عنوان مثالی از نحوه استفاده از API برای ایجاد برنامه‌ای که از این جریان استفاده می‌کند، ما یک برنامه نمونه Protected App Signals ایجاد کرده‌ایم که می‌توانید آن را در این مخزن نمونه پیدا کنید.