دليل مطوّري "إشارات التطبيقات المحمية"

لمساعدة المطوّرين على بدء تجربة واجهة برمجة التطبيقات Protected App Signals API، يوضّح هذا المستند جميع واجهات برمجة التطبيقات المتاحة في مساحة عرض واجهة برمجة التطبيقات، ويوضّح كيفية إعداد بيئة اختبار، ويقدم أمثلة حول الإعدادات والنصوص البرمجية.

سجلّ التعديلات

كانون الثاني (يناير) 2024

الإصدار الأول من دليل المطوّر الذي يتوافق مع إصدار PAS MVP

March 2024

التغييرات في واجهة برمجة التطبيقات لإتاحة الإصدار M-2024-05 من Android API وإصدار نيسان (أبريل) 2024 للمكوّنات من جهة الخادم أهم التغييرات:

  • تمت إضافة تفاصيل حول الأذونات المطلوبة لواجهة برمجة التطبيقات على الجهاز فقط.
  • تمت إضافة تفاصيل حول إدارة حصة الإشارات على الجهاز فقط.
  • تم تعديل توقيع generateBid ليشمل تغييرات ذات صلة بإتاحة استرجاع الإعلانات السياقية والخروج
  • تم تعديل مستندات reportWin، بما في ذلك إتاحة الخروج
  • تحديث وثائق واجهة برمجة التطبيقات لاسترجاع الإعلانات لإزالة دعم استرداد إعلانات نظام التشغيل BYOS وتوثيق أداة UDF لاسترجاع الإعلانات

نظرة عامة على واجهة برمجة التطبيقات

يتضمّن سطح Protected Signals API مجموعات فرعية مختلفة من واجهة برمجة التطبيقات على أنظمة مختلفة:

  • واجهات برمجة تطبيقات Android:
    • واجهة برمجة التطبيقات لتنظيم الإشارات، وتتألف من:
    • تعديل واجهة برمجة تطبيقات Signals
    • واجهة برمجة التطبيقات لترميز الإشارات
    • Protected Auction Support API: يجب استخدامها من خلال حِزم تطوير البرامج (SDK) لتنفيذ نظام مزاد الإعلانات المحمي على خوادم "عروض الأسعار والمزادات" (B&A) باستخدام "إشارات التطبيقات" المحمية.
  • واجهات برمجة التطبيقات من جهة الخادم:
    • Protected Auction API: هي سلسلة من نصوص JavaScript البرمجية التي يتم تشغيلها في عروض الأسعار وخوادم المزادات. تتيح واجهة برمجة التطبيقات هذه للبائعين والمشترين كتابة المنطق لتنفيذ المزاد المحمي.
    • واجهة برمجة التطبيقات لاسترجاع الإعلانات: تتحمّل مسؤولية تقديم قائمة بالإعلانات المرشحة بناءً على المعلومات السياقية ومعلومات المستخدم التي يتم إتاحتها لخادم عروض أسعار المشتري.

عميل Android

من جهة العميل، يتألف سطح "إشارات التطبيق المحمية" من ثلاث واجهات برمجة تطبيقات مختلفة:

  • تحديث الإشارات: هي واجهة برمجة تطبيقات لنظام Android للسماح بتنظيم الإشارات على الجهاز.
  • ترميز الإشارات: واجهة برمجة تطبيقات JavaScript لإعداد الإشارات التي سيتم إرسالها إلى الخادم أثناء المزاد.
  • دعم مزاد الإعلانات المحمي: واجهة برمجة تطبيقات لدعم تنفيذ مزاد محمي على خوادم عروض الأسعار والمزادات. ولا تقتصر واجهة برمجة التطبيقات هذه على إشارات التطبيقات المحمية، وتُستخدَم أيضًا لإتاحة المزادات في Protected Audience API.

تعديل واجهة برمجة تطبيقات Signals

توفّر واجهة برمجة التطبيقات Update Signals API لتكنولوجيا الإعلانات إمكانية تسجيل الإشارات ذات الصلة بالمستخدمِين والتطبيقات بالنيابة عن المشتري. تعمل واجهة برمجة التطبيقات على نموذج التفويض. يوفّر المتصل معرّف موارد منتظم (URI) يسترجع منه إطار العمل الإشارات المقابلة ومنطق ترميز تلك الإشارات لاستخدامها في المزاد.

تتطلّب واجهة برمجة التطبيقات إذن android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS.

ستسترجع واجهة برمجة التطبيقات 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 حيث تكون المفاتيح عبارة عن سلاسل 64 أساسية مقابلة للمفتاح المطلوب وضعه والقيم هي سلسلة أساسية 64 تتوافق مع القيمة المطلوب وضعها.

append

إلحاق إشارة/إشارات جديدة بسلسلة زمنية من الإشارات، ما يؤدي إلى إزالة الأقدم

لتوفير مساحة للإشارات الجديدة إذا تجاوز حجم السلسلة الحد الأقصى المحدد. وتكون قيمة هذا كائن JSON حيث تكون المفاتيح عبارة عن سلاسل 64 أساسية تتجاوب مع المفتاح المراد إلحاقه والقيم هي كائنات لها حقلان: "values" و "maxSignals".

"القيم": قائمة من سلاسل 64 الأساسية المقابلة لقيم الإشارة المطلوب إلحاقها بالسلسلة الزمنية.

"maxSignals": الحد الأقصى لعدد القيم المسموح بها في هذه السلسلة الزمنية. إذا

يكون العدد الحالي من الإشارات المرتبطة بالمفتاح يتجاوز الحد الأقصى للإشارات التي ستتم إزالة الإشارات الأقدم. تجدر الإشارة إلى أنّه يمكنك إلحاق عبارة بمفتاح يضيفه وضع. يُرجى العِلم أنّ إلحاق عدد أكبر من الحدّ الأقصى لعدد القيم سيؤدي إلى حدوث إخفاق.

put_if_not_present

لا تتم إضافة إشارة جديدة إلا إذا لم تكن هناك أي إشارات حالية لها المفتاح نفسه. وقيمته هي كائن JSON حيث تكون المفاتيح عبارة عن سلاسل 64 أساسية مقابلة للمفتاح المطلوب وضعه والقيم هي سلسلة الأساس 64 المقابلة للقيمة المطلوب وضعها.

remove

يؤدي هذا الإجراء إلى إزالة إشارة المفتاح. قيمة هذه هي قائمة من سلاسل 64 الأساسية المقابلة لمفاتيح الإشارات التي يجب حذفها.

update_encoder

توفر إجراءً لتعديل نقطة النهاية ومعرّف الموارد المنتظم (URI) الذي يمكن استخدامه

لاسترداد منطق الترميز. المفتاح الفرعي لتوفير إجراء التحديث هو "إجراء"

والقيم المتوافقة حاليًا هي "التسجيل" فقط والتي ستسجِّل نقطة نهاية برنامج الترميز إذا تم توفيرها لأول مرة أو ستستبدل نقطة النهاية الحالية بنقطة النهاية التي تم توفيرها حديثًا. يجب توفير نقطة النهاية لإجراء "التسجيل". المفتاح الفرعي لتوفير نقطة نهاية لبرنامج الترميز هو "نقطة النهاية" والقيمة هي معرّف الموارد المنتظم (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"
    }
}

سيتم تخصيص حصة من الإشارات بحجم يتراوح بين 10 و15 كيلوبايت. بعد تجاوز الحصة، سيتم إخراج الإشارات باستخدام FIFO، وسيتم التخلص من إشارات PPAPI. ستسمح عملية الإخلاء بتجاوز الحصة قليلاً لفترات زمنية قصيرة بهدف تقليل وتيرة عمليات الإخلاء.

واجهة برمجة التطبيقات لترميز الإشارات

يُطلب من المشترين تقديم دالة Java Script ليتم استخدامها في ترميز الإشارات المخزنة على الجهاز من أجل إرسالها إلى الخادم أثناء المزاد المحمي. ويمكن للمشترين توفير هذا النص البرمجي عن طريق إضافة عنوان URL الذي يمكن جلبه من استخدام المفتاح "update_encoder" في أيّ من الاستجابات لطلب واجهة برمجة التطبيقات UpdateSignal. سيحمل النص البرمجي التوقيع التالي:

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 هي خريطة تبدأ من مفاتيح على شكل مصفوفة UInt8Array بحجم 4 إلى قوائم كائنات إشارات التطبيقات المحمية. يتضمّن كل عنصر من عناصر "إشارات التطبيقات المحمية" ثلاثة حقول:

  • signal_value: مصفوفة UInt8Array تمثل قيمة الإشارة.
  • creation_time: رقم يمثّل وقت إنشاء الإشارات بالثواني.
  • package_name: سلسلة تمثل اسم الحزمة التي أنشأت الإشارة

المعلمة maxSize هي رقم يصف أكبر حجم صفيف مسموح به للناتج.

يجب أن تُخرج الدالة كائنًا بحقلين:

  • status: يجب أن تكون القيمة 0 في حال تشغيل النص البرمجي بنجاح.
  • results: يجب أن يكون مصفوفة UInt8Ar تقل عن الحد الأقصى أو مساويًا له. سيتم إرسال هذه المصفوفة إلى الخادم أثناء المزادات، وإعدادها باستخدام النص البرمجي prepareDataForAdRetrieval.

ويوفّر الترميز تكنولوجيات الإعلانات لمرحلة أولية من هندسة الخصائص، حيث يمكن لهذه التقنيات إجراء عمليات تحويل مثل ضغط الإشارات الأولية إلى نُسخ تسلسلية استنادًا إلى منطقها الخاص. تجدر الإشارة إلى أنّه خلال مزاد محمي يتم إجراؤه في بيئات التنفيذ الموثوقة (TEE)، سيحصل منطق تكنولوجيا الإعلان المخصّص على إذن وصول للقراءة إلى حمولات الإشارات التي يُنشئها برنامج الترميز. إنّ المنطق المخصّص، الذي يُعرف باسم دالة تحديد المستخدم (UDF)، الذي يعمل في بيئة التنفيذ الموثوقة (TEE) الخاصة بالمشتري وسيكون متاحًا لقراءة الإشارات المشفرة والإشارات السياقية الأخرى التي يوفرها تطبيق الناشر لتنفيذ اختيار الإعلانات (استرجاع الإعلانات وعروض الأسعار).

ترميز الإشارات

وكل ساعة، سيتم تشفير إشاراتهم في حمولة مزاد من خلال إشاراتهم المسجَّلة.ويستمر ترميز مصفوفة البايت الخاصة بحمولة المزاد على الجهاز، وسيتم تشفيره وسيجمعه البائعون كجزء من بيانات "اختيار الإعلانات" لتضمينها كجزء من مزاد محمي. ولإجراء الاختبار، يمكنك تشغيل هذا الترميز خارج نطاق الإيقاع كل ساعة من خلال تنفيذ الأمر التالي:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
تحديد إصدارات منطقية برنامج الترميز

عند تقديم طلب لتنزيل منطق برنامج الترميز المخصّص لتقنية الإعلان، يمكن أن تستجيب نقطة نهاية تقنية الإعلان برقم إصدار في عناوين الاستجابة. يُرجى استخدام هذا الإصدار مع منطق برنامج الترميز على الجهاز. عند ترميز الإشارات الأولية، يستمر حمولة البيانات المشفرة مع الإصدار المستخدَم في الترميز. يتم إرسال هذه النسخة أيضًا إلى خادم B&A خلال مزاد محمي، حتى تتمكّن تقنيات الإعلانات من مواءمة منطق عرض الأسعار والترميز استنادًا إلى الإصدار.

Response header for providing encoder version : X_ENCODER_VERSION

واجهة برمجة التطبيقات Protected Auction Support API

على جانب الجهاز، فإنّ إجراء مزاد لإشارات التطبيقات المحمية مثل إجراء مزاد لشرائح الجمهور المحمية.

خدمات عروض الأسعار والمزادات

تشمل واجهات برمجة التطبيقات من جهة الخادم ما يلي:

  • Protected Auction API: هي سلسلة من دوال JavaScript أو UDF التي يمكن للمشترين والبائعين نشرها على مكوّنات B&A التي يملكونها لتحديد عروض الأسعار ومنطق المزاد.
  • واجهة برمجة التطبيقات لاسترجاع الإعلانات: يمكن للمشترين تنفيذ واجهة برمجة التطبيقات هذه من خلال تنفيذ نقطة نهاية REST تكون مسؤولة عن توفير مجموعة من الإعلانات المرشحة لمزاد "إشارات التطبيقات المحمية".

Protected Auction API

تتكوّن Protected Auction API من واجهات برمجة التطبيقات JS أو واجهات UDF التي يمكن للمشترين والبائعين استخدامها لتنفيذ منطق مزاداتهم وعروض أسعارهم.

الدوال المعرَّفة من قِبل المستخدم لتكنولوجيا الإعلانات للمشتري
PrepareDataForAdRetrieval UDF

قبل أن تتمكّن من استخدام "إشارات التطبيقات المحمية" لاسترجاع الإعلانات المرشحة من خلال خدمة استرجاع الإعلانات في بيئة التنفيذ الموثوقة (TEE)، على المشترين فك ترميز "إشارات التطبيقات المحمية" والبيانات الأخرى التي يقدّمها البائع وإعدادها. يتم تمرير مخرجات prepareDataForAdRetrieval UDF للمشترين إلى خدمة استرجاع الإعلانات لاسترداد أهم ألف إعلان مرشح من أجل عرض الأسعار.

// Inputs
// ------
// encodedOnDeviceSignals: A Uint8Array of bytes from the device.
// encodedOnDeviceSignalsVersion: An integer representing the encoded
//   version of the signals.
// sellerAuctionSignals: Information about auction (ad format, size) derived
//                       contextually.
// contextualSignals: Additional contextual signals that could help in
//                    generating bids.
//
// Outputs
// -------
// Returns a JSON structure to be used for retrieval.
// The structure of this object is left to the adtech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
   return {};
}
إنشاء عرض السعر UDF

بعد عرض أفضل آلاف من الإعلانات المرشّحة، يتم تمريرها إلى منطق عروض الأسعار المخصّصة للمشتري، 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)

reportWin UDF

عند انتهاء المزاد، ستنشئ خدمة المزاد عناوين URL لإعداد التقارير للمشترين وإشارات التسجيل باستخدام reportWin UDF (هذه هي دالة reportWin نفسها المستخدَمة لشرائح الجمهور المحمية). سيُرسل الجهاز إشعارًا بذلك بعد عرض الإعلان من قِبل العميل. يشبه توقيع هذه الطريقة تقريبًا إصدار "الجمهور المحمي" باستثناء مَعلمتَين إضافيتَين egressPayload وtemporaryUnlimitedEgressPayload يتم استخدامهما لتفعيل تدريب النموذج، وتتم تعبئتهما بالنتائج من generateBid.

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals,
                   egressPayload, temporaryUnlimitedEgressPayload) {
  // ...
}
الوحدات الأساسية لتكنولوجيا الإعلانات للبائع (UDF)
نتيجة الإعلان UDF

يستخدم البائعون هذه الميزة لتحديد الإعلانات التي يتم استلامها من المشترين والتي ستفوز بالمزاد.

function scoreAd(adMetadata, bid, auctionConfig,
                 trustedScoringSignals, bid_metadata) {
  // ...
  return {desirability: desirabilityScoreForThisAd,
              allowComponentAuction: true_or_false};
}
UDF لنتيجة reportResult

تتيح هذه الأداة للبائع (في النهاية) إعداد تقارير على مستوى الحدث باستخدام المعلومات المتعلقة بالإعلان الفائز.

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

واجهة برمجة تطبيقات استرجاع الإعلانات

في إصدار MVP (منتج الحد الأدنى القابل للتطبيق)، ستكون خدمة استرجاع الإعلانات عبارة عن خدمة يديرها المشتري ويستضيفها وتسترد خدمة عروض الأسعار المرشحين للإعلانات من هذه الخدمة. اعتبارًا من نيسان (أبريل) 2024، يجب أن يعمل خادم استرداد الإعلانات في بيئة تنفيذ موثوقة (TEE) وسيعرض واجهة GRPC/proto. وعلى شركات تكنولوجيا الإعلان إعداد هذا الخادم وتقديم عنوان URL كجزء من عملية نشر حزمة B&A. يتوفّر تنفيذ لهذه الخدمة التي تعمل في بيئة التنفيذ الموثوقة (TEE) في مبادرة حماية الخصوصية على GitHub وفي باقي المستندات، نفترض أنّ هذا هو الرمز المستخدَم في عملية النشر.

اعتبارًا من نيسان (أبريل) 2024، ستوفّر إصدارات B&A إمكانية استرداد إعلانات المسار السياقي. في هذه الحالة، سيتلقّى خادم "عروض الأسعار" قائمة بمعرّفات الإعلانات التي يرسلها خادم "عرض الأسعار في الوقت الفعلي" (RTB) خلال الجزء السياقي من المزاد. سيتم إرسال المعرّفات إلى خادم TeE KV لجلب جميع المعلومات المرتبطة بالإعلانات والتي سيتم استخدامها خلال مرحلة تقديم عروض الأسعار (على سبيل المثال، عنوان URL لعرض الإعلان والبيانات الوصفية وعمليات تضمين الإعلانات التي سيتم استخدامها في اختيار أعلى ترتيب). لا يحتاج هذا المسار الثاني إلى أي منطق محدد ليتم نشره، لذا سنوثّق هنا فقط كيفية تهيئة حالة استخدام استرداد الإعلان استنادًا إلى بيئة التنفيذ الموثوقة (TEE).

معالجة الطلب باستخدام واجهة المستخدم الأساسية (UDF)
function HandleRequest(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals) {
    return adsMetadataString;
}

المكان:

  • requestMetadata: JSON البيانات الوصفية للخادم حسب الطلب في إطار عمل UDF. هذا الحقل فارغ في الوقت الحالي.
  • preparedDataForAdRetrieval: يعتمد محتوى هذا الحقل على استراتيجية استرجاع الإعلانات. وفي حال استرداد الإعلان حسب السياق، ستحتوي هذه المَعلمة على الإشارات الأولية التي تنشأ من الجهاز، والتي يتم تمريرها من خدمة عروض الأسعار. في حال استرداد إعلان TEE باستخدام خادم استرجاع الإعلانات، ستحتوي هذه المعلمة على نتيجة prepareDataForAdRetrieval UDF. ملاحظة: في هذه المرحلة، سيتم فك ترميز "إشارات التطبيقات المحمية" ولن يتم تشفيرها.
  • deviceMetadata: عنصر JSON يحتوي على البيانات الوصفية للجهاز التي تمت إعادة توجيهها من خلال خدمة إعلانات البائع راجِع وثائق B&A للحصول على مزيد من التفاصيل.
    • X-Accept-Language: اللغة المستخدمة على الجهاز
    • X-User-Agent: وكيل المستخدم المُستخدَم في الجهاز
    • X-BnA-Client-IP: عنوان IP للجهاز
  • contextualSignals: سلسلة عشوائية نشأت من خادم عروض الأسعار السياقية الذي يديره نظام وسيط عرض الطلب نفسه. من المتوقع أن تتمكن الدالة UDF من فك ترميز السلسلة واستخدامها. قد تحتوي "الإشارات السياقية" على أي معلومات، مثل معلومات إصدار نموذج تعلُّم الآلة لميزة التضمين المحمي التي تم تمريرها باستخدام "إشارات التطبيقات المحمية".

يجب أن تعرض الدالة UDF سلسلة عند النجاح. يتم إرجاع السلسلة إلى خادم عروض الأسعار الذي يمرّرها بعد ذلك إلى generateBid UDF. مع أنّ السلسلة يمكن أن تكون مجرد سلسلة بسيطة، يجب أن تكون السلسلة في الغالب كائنًا تسلسليًا يتم تحديد مخططه من خلال كل تقنية إعلان بمفردها. ما مِن قيود على المخطط طالما أنّ منطق generateBid في تقنية الإعلان يمكنه التعرّف على السلسلة واستخدامها.

إعداد النظام للتطوير

Android

لإعداد بيئة تطوير Android، عليك تنفيذ ما يلي:

  1. إنشاء محاكي (الخيار المفضّل) أو جهاز مادي يشغّل نسخة "معاينة المطوِّر" 10
  2. نفِّذ ما يلي:
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity

وبعد ذلك، حدِّد الخيار المعروض للموافقة على الإعلانات المقترَحة من التطبيقات.

  1. شغِّل الأمر التالي لتفعيل واجهات برمجة التطبيقات ذات الصلة. قد تحتاج إلى إعادة تشغيل هذا الإعداد من حين لآخر حيث ستتم مزامنة الضبط التلقائي للإيقاف غير التلقائي بشكل دوري.
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) (راجِع القسم ذي الصلة).
  • تأكَّد من أنّ تكنولوجيا الإعلان قد تم تحديد كل الدوال المعرَّفة من قِبل المستخدم (prepareDataForAdRetrieval، وgenerateBid، وreportWin، وHandleRequest) واستضافتها.

سيكون التعرّف على كيفية عمل "المزاد المحمي مع الجمهور المحمي" مع ميزة "المبيعات والتوزيع" مفيدًا أيضًا ولكنّه ليس إلزاميًا.

إعدادات Terraform

لاستخدام إشارات التطبيقات المحمية، يجب أن تستوفي تقنيات الإعلانات ما يلي:

  • تفعيل ميزة "إشارات التطبيقات المحمية" في "عمليات الفوترة وحلّ المشاكل"
  • يُرجى توفير نقاط نهاية عناوين URL يمكن من خلالها جلب الدوال الجديدة المعرَّفة من قِبل المستخدم prepareDataForAdRetrieval, generateBid وreportWin.

بالإضافة إلى ذلك، يفترض هذا الدليل أنّ تقنيات الإعلانات التي تريد استخدام البيانات والأجوبة في تجديد النشاط التسويقي ستستمر في إعداد جميع علامات الإعداد الحالية لمزاد تجديد النشاط التسويقي كالمعتاد.

إعداد تكنولوجيا إعلانات المشتري

باستخدام هذا الملف التجريبي كمثال، على المشترين وضع العلامات التالية:

  • تفعيل إشارات التطبيقات المحمية: يتم تفعيله لجمع بيانات "إشارات التطبيقات المحمية".
  • عناوين 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"

إعدادات تكنولوجيا الإعلان للبائعين

باستخدام ملف العرض التوضيحي هذا كمثال، على البائعين وضع العلامات التالية. (ملاحظة: يتم هنا تمييز الإعدادات المتعلّقة بإشارات التطبيقات المحمية فقط). تحتاج تكنولوجيا الإعلان إلى التأكّد من استبدال عناوين URL الصحيحة في العناصر النائبة:

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

  runtime_flags = {
    # ... More config here.

    ENABLE_PROTECTED_APP_SIGNALS                  = "true"

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

  }  # runtime_flags

}  # Module "seller"

خدمات KV واسترجاع الإعلانات

استنادًا إلى الاستراتيجيات المُختارة لدعم استرجاع الإعلانات، سيطلب النظام نشر مثيل واحد أو نسختين من خدمة KV. وسنشير إلى مثيل KV المستخدَم لاسترجاع الإعلان استنادًا إلى TEE على أنّه Ad Retrieval Server، كما سنشير إلى المثيل لإتاحة استرداد المسار المستند إلى المسار باعتباره KV Lookup Server.

في كلتا الحالتين، يتّبع نشر الخادم الوثائق المتوفرة في GitHub لخادم KV، الفرق بين الحالتين هو أن حالة البحث تعمل بدون أي إعدادات إضافية، بينما تتطلب حالة الاسترجاع نشر HandleRequest UDF لتنفيذ منطق الاسترداد. للاطّلاع على مزيد من التفاصيل، يمكنك الاطّلاع على دليل إعداد خادم KV. تجدر الإشارة إلى أنّ "B&A" تتوقع نشر كلتا الخدمتَين في شبكة الخدمة المتداخلة نفسها كخدمة عروض الأسعار.

مثال على الإعداد

ضَع في اعتبارك السيناريو التالي: باستخدام Protected App Signals API، تخزِّن تكنولوجيا الإعلان الإشارات ذات الصلة بناءً على استخدام المستخدِم للتطبيق. في مثالنا، يتم تخزين الإشارات التي تمثل عمليات الشراء داخل التطبيق من عدة تطبيقات. وخلال المزاد، يتم جمع الإشارات المشفّرة وتمريرها إلى مزاد محمي يتم إجراؤه في عملية B&A. إنّ الإعلانات القابلة لإعادة الضبط (UDF) للمشتري التي تعمل في اتفاقية B&A تستخدم الإشارات لجلب المرشحين للإعلانات واحتساب عرض السعر.

[المشتري] أمثلة على الإشارات

تتم إضافة إشارة تحتوي على مفتاح 0 والقيمة 1.

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

تتم إضافة إشارة تحتوي على مفتاح 1 والقيمة 2.

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

مثال على encodeSignals [المشتري]

يشفِّر كل إشارة إلى 2 بايت، بحيث يكون البايت الأول هو البايت الأول من مفتاح الإشارة والبايت الثاني هو البايت الأول من قيمة الإشارة.

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

[المشترون] مثال علىPrepareDataForAdRetrieval

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

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

[المشترون] نموذج UDF لاسترجاع الإعلانات

في المثال الذي نعرضه، يرسل خادم استرداد الإعلانات بيانات وصفية (أي رقم تعريف لكل إعلان في هذا المثال، لكن يمكن أن يحتوي على بيانات أخرى لكل إعلان يمكن أن تساعد في إنشاء عروض أسعار لاحقًا) لكل إعلان من أهم المرشحين للإعلانات.

function HandleRequest(requestMetadata, protectedSignals, deviceMetadata,
                      contextualSignals) {
 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

أبلغت شركة 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
  };
}

مثال على reportResult [البائع]

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

نموذج تطبيق

كمثال على كيفية استخدام واجهة برمجة التطبيقات لإنشاء تطبيق يستخدم مسارًا بسيطًا كما هو موضّح أعلاه، أنشأنا نموذجًا لتطبيق "إشارات تطبيقات محمية" والذي يمكن العثور عليه في نموذج المستودع هذا.