دليل مطوّري برامج Attribution Reporting API

أثناء قراءة مستندات "مبادرة حماية الخصوصية" على Android، استخدِم الزر الإصدار التجريبي للمطوّرين أو الإصدار التجريبي لاختيار إصدار البرنامج الذي تستخدمه، لأنّ التعليمات قد تختلف.


تمّ تصميم Attribution Reporting API لتعزيز خصوصية المستخدِمين من خلال إنهاء الاعتماد على معرّفات المستخدِمين من الجهات المختلفة، إضافةً إلى توفير حالات استخدام مهمّة تتيح قياس الإحالات الناجحة وتحديد المصدر على جميع التطبيقات. يصف دليل المطوّرين هذا كيفية ضبط واجهات برمجة التطبيقات Attribution Reporting API واختبارها لتسجيل النقرات على الإعلانات ومرّات مشاهدتها والإحالات الناجحة من خلال استدعاء طُرق تسجِّل عوامل التشغيل والمصادر ذات الصلة بهذه الأحداث.

يشرح لك هذا الدليل كيفية إعداد نقاط نهاية الخادم وإنشاء تطبيق العميل الذي يستدعي هذه الخدمات. اطّلِع على مزيد من المعلومات عن التصميم العام لواجهة برمجة التطبيقات Attribution Reporting API في اقتراح التصميم.

العبارات الرئيسية

  • تشير مصادر تحديد المصدر إلى النقرات أو المشاهدات.
  • العوامل المُشغِّلة هي الأحداث التي يمكن إسنادها إلى الإحالات الناجحة.
  • تحتوي التقارير على بيانات عن عامل تشغيل ومصدر تحديد مصدر الاستجابة المقابل. يتم إرسال هذه التقارير استجابةً للأحداث المشغّلة. تتيح واجهة برمجة التطبيقات Attribution Reporting API التقارير على مستوى الحدث و التقارير القابلة للتجميع.

قبل البدء

لاستخدام Attribution Reporting API، أكمِل المهام المُدرَجة في الأقسام التالية على جانب الخادم وجانب العميل.

إعداد نقاط نهاية Attribution Reporting API

تتطلّب واجهة برمجة التطبيقات Attribution Reporting API مجموعة من نقاط النهاية التي يمكنك الوصول إليها من جهاز اختباري أو محاكي. أنشئ نقطة نهاية واحدة لكل من المهام التالية على الجانب الخادم:

هناك عدة طرق لإعداد نقاط النهاية المطلوبة:

  • إنّ أسرع طريقة لبدء استخدام هذه الميزة هي نشر تعريفات خدمات OpenAPI v3 من مستودع نماذج الرموز البرمجية إلى منصة نموذجية أو منصة خدمات صغيرة. يمكنك استخدام Postman أو Prism أو أي منصة أخرى لخادم mock متوافقة مع هذا التنسيق. يمكنك نشر كل نقطة نهاية وتتبُّع عناوين URL لتحديد ما إذا كانت مناسبة للاستخدام في تطبيقك. للتأكّد من إرسال التقارير، يمكنك الرجوع إلى طلبات البحث التي تم إجراؤها في السابق إلى المنصة التجريبية أو المنصة التي لا تستخدِم خادمًا.
  • يمكنك تشغيل خادم مستقل باستخدام نموذج Kotlin المستنِد إلى Spring Boot. يمكنك نشر هذا الخادم على مقدّم خدمات السحابة الإلكترونية أو على البنية الأساسية الداخلية.
  • استخدِم تعريفات الخدمة كأمثلة لدمج نقاط النهاية في نظامك الحالي.

قبول تسجيل المصدر

يجب أن تكون نقطة النهاية هذه قابلة للتوجيه من عنوان URL مشابه لما يلي:

https://adtech.example/attribution_source

عندما يسجّل تطبيق العميل مصدر إحالة، يقدّم معرّف الموارد المنتظم (URI) ل نقطة نهاية الخادم هذه. بعد ذلك، تُجري Attribution Reporting API طلبًا وأحد الرؤوس التالية:

  • بالنسبة إلى أحداث النقر:

    Attribution-Reporting-Source-Info: navigation
    
  • لعرض الأحداث:

    Attribution-Reporting-Source-Info: event
    

اضبط نقطة نهاية الخادم للردّ بما يلي:

// Metadata associated with attribution source.
Attribution-Reporting-Register-Source: {
  "destination": "[app package name]",
  "web_destination": "[eTLD+1]",
  "source_event_id": "[64 bit unsigned integer]",
  "expiry": "[64 bit signed integer]",
  "event_report_window": "[64-bit signed integer]",
  "aggregatable_report_window": "[64-bit signed integer]",
  "priority": "[64 bit signed integer]",
  "filter_data": {
    "[key name 1]": ["key1 value 1", "key1 value 2"],
    "[key name 2]": ["key2 value 1", "key2 value 2"],
    // Note: "source_type" key will be automatically generated as
    // one of {"navigation", "event"}.
  },
  // Attribution source metadata specifying histogram contributions in aggregate
  // report.
  "aggregation_keys": {
    "[key1 name]": "[key1 value]",
    "[key2 name]": "[key2 value]",
  },

    "debug_key": "[64-bit unsigned integer]",
    "debug_reporting": [boolean]
}
// Specify additional ad tech URLs to register this source with.
Attribution-Reporting-Redirect: <Ad Tech Partner URI 1>
Attribution-Reporting-Redirect: <Ad Tech Partner URI 2>

في ما يلي مثال تم فيه إضافة عيّنات من القيم:

Attribution-Reporting-Register-Source: {
  "destination": "android-app://com.example.advertiser",
  "source_event_id": "234",
  "expiry": "259200",
  "event_report_window": "172800",
  "aggregatable_report_window": "172800",
  "priority": "5",
  "filter_data": {
    "product_id": ["1234"]
  },
  "aggregation_keys": {
  // Generates a "0x159" key piece named (low order bits of the key) for the key
  // named "campaignCounts".
  // User saw an ad from campaign 345 (out of 511).
    "campaignCounts": "0x159",

  // Generates a "0x5" key piece (low order bits of the key) for the key named
  // "geoValue".
  // Source-side geo region = 5 (US), out of a possible ~100 regions.
    "geoValue": "0x5",
  },
  // Opts in to receiving verbose debug reports
  "debug_reporting": true
}

Attribution-Reporting-Redirect:
https://adtechpartner1.example?their_ad_click_id=567
Attribution-Reporting-Redirect:
https://adtechpartner2.example?their_ad_click_id=890

إذا كان Attribution-Reporting-Redirects يحتوي على معرّفات الموارد المنتظمة لشركاء تكنولوجيا الإعلان، تقدّم واجهة برمجة التطبيقات Attribution Reporting API طلبًا مشابهًا لكلّ معرّف موارد منتظم. على كل شريك تكنولوجيا إعلانات ضبط خادم يستجيب بالرؤوس التالية:

Attribution-Reporting-Register-Source: {
  "destination": "[app package name]",
  "web_destination": "[eTLD+1]",
  "source_event_id": "[64 bit unsigned integer]",
  "expiry": "[64 bit signed integer]",
  "event_report_window": "[64-bit signed integer]",
  "aggregatable_report_window": "[64-bit signed integer]",
  "priority": "[64 bit signed integer]",
  "filter_data": {
    "[key name 1]": ["key1 value 1", "key1 value 2"],
    "[key name 2]": ["key2 value 1", "key2 value 2"],
    // Note: "source_type" key will be automatically generated as
    // one of {"navigation", "event"}.
  },
  "aggregation_keys": {
    "[key1 name]": "[key1 value]",
    "[key2 name]": "[key2 value]",
  }
}
// The Attribution-Reporting-Redirect header is ignored for ad tech partners.

قبول تسجيل عامل تشغيل الإحالة الناجحة

يجب أن تكون نقطة النهاية هذه قابلة للتوجيه من عنوان URL مشابه لما يلي:

https://adtech.example/attribution_trigger

عندما يسجِّل تطبيق العميل حدثًا مشغِّلاً، يقدّم عنوان URL لنقطة نهاية الخادم هذه. بعد ذلك، تقدّم Attribution Reporting API طلبًا وتُدرِج أحد العناوين التالية:

اضبط نقطة نهاية الخادم للردّ بما يلي:

// Metadata associated with trigger.
Attribution-Reporting-Register-Trigger: {
  "event_trigger_data": [{
    // "trigger_data returned" in event reports is truncated to
    // the last 1 or 3 bits, based on conversion type.
    "trigger_data": "[unsigned 64-bit integer]",
    "priority": "[signed 64-bit integer]",
    "deduplication_key": "[signed 64-bit integer]",
    // "filter" and "not_filters" are optional fields which allow configuring
    // event trigger data based on source's filter_data. They consist of a
    // filter set, which is a list of filter maps. An event_trigger_data object
    // is ignored if none of the filter maps in the set match the source's
    // filter data.
    // Note: "source_type" can be used as a key in a filter map to filter based
    // on the source's "navigation" or "event" type. The first
    // Event-Trigger that matches (based on the filters/not_filters) will be
    // used for report generation. If none of the event-triggers match, no
    // event report will be generated.
    "filters": [{
      "[key name 1]": ["key1 value 1", "key1 value 2"],
      // If a key is missing from filters or source's filter_data, it won't be
      // used during matching.
      "[key name 2]": ["key2 value 1", "key2 value 2"],
    }],
    "not_filters":  [{
      "[key name 1]": ["key1 value 1", "key1 value 2"],
      // If a key is missing from not_filters or source's filter_data, it won't
      // be used during matching.
      "[key name 2]": ["key2 value 1", "key2 value 2"],
    }]
  }],
  // Specify a list of dictionaries that generates aggregation keys.
  "aggregatable_trigger_data": [
    // Each dictionary entry independently adds pieces to multiple source keys.
    {
      "key_piece": "[key piece value]",
      "source_keys": ["[key name the key piece value applies to]",
      ["list of IDs in source to match. Non-matching IDs are ignored"]]
      // filters/not_filters are optional fields similar to event trigger data
      // filter fields.
      "filters": [{
        "[key name 1]": ["key1 value 1", "key1 value 2"]
      }],
      "not_filters":  [{
          "[key name 1]": ["key1 value 1", "key1 value 2"],
          "[key name 2]": ["key2 value 1", "key2 value 2"],
      }]
    },
    ..
  ],
  // Specify an amount of an abstract value which can be integers in [1, 2^16]
  // to contribute to each key that is attached to aggregation keys in the
  // order they are generated.
  "aggregatable_values": [
     // Each source event can contribute a maximum of L1 = 2^16 to the
     // aggregate histogram.
    {
     "[key_name]": [value]
    },
    ..
  ],
  aggregatable_deduplication_keys: [{
  deduplication_key": [unsigned 64-bit integer],
    "filters": {
        "category": [filter_1, …, filter_H]
      },
    "not_filters": {
        "category": [filter_1, …, filter_J]
      }
  },
  ...
  {
  "deduplication_key": [unsigned 64-bit integer],
    "filters": {
        "category": [filter_1, …, filter_D]
      },
    "not_filters": {
        "category": [filter_1, …, filter_J]
      }
    }
  ]

  "debug_key": "[64-bit unsigned integer]",
  "debug_reporting": [boolean]

}
// Specify additional ad tech URLs to register this trigger with.
// Repeated Header field "Attribution-Reporting-Redirect"
Attribution-Reporting-Redirect: <Ad Tech Partner URI 1>
Attribution-Reporting-Redirect: <Ad Tech Partner URI 2>

في ما يلي مثال تم فيه إضافة عيّنات من القيم:

Attribution-Reporting-Register-Trigger: {
  "event_trigger_data": [{
    "trigger_data": "1122", // Returns 010 for CTCs and 0 for VTCs in reports.
    "priority": "3",
    "deduplication_key": "3344"
    "filters": [{ // Filter strings can not exceed 25 characters
      "product_id": ["1234"],
      "source_type": ["event"]
    }]
  },
  {
    "trigger_data": "4", // Returns 100 for CTCs and 0 for VTCs in reports.
    "priority": "3",
    "deduplication_key": "3344"
    "filters": [{ // Filter strings can not exceed 25 characters
      "product_id": ["1234"],
      "source_type": ["navigation"]
    }]
  }],
  "aggregatable_trigger_data": [
    // Each dictionary independently adds pieces to multiple source keys.
    {
      // Conversion type purchase = 2 at a 9-bit offset, i.e. 2 << 9.
      // A 9-bit offset is needed because there are 511 possible campaigns,
      // which takes up 9 bits in the resulting key.
      "key_piece": "0x400",// Conversion type purchase = 2
      // Apply this key piece to:
      "source_keys": ["campaignCounts"]
       // Filter strings can not exceed 25 characters
    },
    {
      // Purchase category shirts = 21 at a 7-bit offset, i.e. 21 << 7.
      // A 7-bit offset is needed because there are ~100 regions for the geo
      // key, which takes up 7 bits of space in the resulting key.
      "key_piece": "0xA80",
      // Apply this key piece to:
      "source_keys": ["geoValue", "nonMatchingIdsAreIgnored"]
      // source_key values must not exceed the limit of 25 characters
    }
  ],
  "aggregatable_values":
    {
      // Privacy budget for each key is L1 / 2 = 2^15 (32768).
      // Conversion count was 1.
      // Scale the count to use the full budget allocated: 1 * 32768 = 32768.
      "campaignCounts": 32768,

      // Purchase price was $52.
      // Purchase values for the app range from $1 to $1,024 (integers only).
      // Scaling factor applied is 32768 / 1024 = 32.
      // For $52 purchase, scale the value by 32 ($52 * 32 = $1,664).
      "geoValue": 1664
    }
  ,
  // aggregatable_deduplication_keys is an optional field. Up to 50 "keys"
  // can be included in the aggregatable_deduplication_keys list. Filters, not
  // filters, and deduplication_key are optional fields. If deduplication_key
  // is omitted, it will be treated as a null value. See
  // https://wicg.github.io/attribution-reporting-api/#triggering-aggregatable-attribution
  aggregatable_deduplication_keys:
  [
    {
    deduplication_key": 3,
        "filters": {
          "category": [A]
        }
    },
    {
    "deduplication_key": 4,
        "filters": {
          "category": [C, D]
        },
        "not_filters": {
          "category": [F]
        }
    }
  ]
  // Opts into receiving verbose debug reports
  "debug_reporting": true
}
Attribution-Reporting-Redirect:https://adtechpartner.example?app_install=567

يبلغ الحد الأقصى 25 بايت لكل معرّف مفتاح تجميع وسلسلة فلتر. ويعني ذلك أنّه يجب ألا تتجاوز أرقام تعريف مفاتيح التجميع وسلاسل الفلاتر 25 حرفًا. في هذا المثال، يتكون campaignCounts من 14 حرفًا، لذا فهو معرّف صالح لمفتاح التجميع، ويتكون 1234 من 4 أحرف، لذا فهو سلسلة فلتر صالحة. إذا كان معرّف مفتاح التجميع أو سلسلة الفلتر تتجاوز 25 حرفًا، يتم تجاهل عامل التفعيل.

إذا كان Attribution-Reporting-Redirect يحتوي على معرّفات الموارد المنتظمة لشركاء تكنولوجيا الإعلان، تقدّم واجهة برمجة التطبيقات Attribution Reporting API طلبًا مشابهًا لكلّ معرّف موارد منتظم. على كل شريك تكنولوجيا إعلانات ضبط خادم يستجيب بالرؤوس التالية:

// Metadata associated with trigger.
Attribution-Reporting-Register-Trigger: {
  "event_trigger_data": [{
    // "trigger_data" returned in event reports is truncated to
    // the last 1 or 3 bits, based on conversion type.
    "trigger_data": "[unsigned 64-bit integer]",
    "priority": "[signed 64-bit integer]",
    "deduplication_key": "[signed 64-bit integer]",
    // filter and not_filters are optional fields which allow configuring
    // different event trigger data based on source's filter_data. They
    // consist of a filter set, which is a list of filter maps. An
    // event_trigger_data object is ignored if none of the filter maps in the
    // set match the source's filter data. Note: "source_type" can be used as
    // a key in a filter map to filter based on the source's "navigation" or
    // "event" type. The first Event-Trigger that matches (based on the
    // filters/not_filters) will be used for report generation. If none of the
    // event-triggers match, no report will be generated.
    "filters": [{
      "[key name 1]": ["key1 value 1", "key1 value 2"],
      // If a key is missing from filters or source's filter_data, it will not be
      // used during matching.
      "[key name 2]": ["key2 value 1", "key2 value 2"],
    }],
    "not_filters":  [{
      "[key name 1]": ["key1 value 1", "key1 value 2"],
      // If a key is missing from not_filters or source's filter_data, it will not
      // be used during matching.
      "[key name 2]": ["key2 value 1", "key2 value 2"],
    }]
  }],
  "aggregatable_trigger_data": [
    // Each dictionary entry independently adds pieces to multiple source keys.
    {
      "key_piece": "[key piece value]",
      "source_keys": ["[key name the key piece value applies to]",
      ["list of IDs in source to match. Non-matching IDs are ignored"]],
      // filters/not_filters are optional fields similar to event trigger data
      // filter fields.
      "filters": [{
        "[key name 1]": ["key1 value 1", "key1 value 2"]
      }],
      "not_filters":  [{
          "[key name 1]": ["key1 value 1", "key1 value 2"],
          "[key name 2]": ["key2 value 1", "key2 value 2"],
      }]
    },
    ..
  ],
  // Specify an amount of an abstract value which can be integers in [1, 2^16] to
  // contribute to each key that is attached to aggregation keys in the order they
  // are generated.
  "aggregatable_values": [
    // Each source event can contribute a maximum of L1 = 2^16 to the aggregate
    // histogram.
    {
     "[key_name]": [value]
    }
  ]
}
// The Attribution-Reporting-Redirect header is ignored for ad tech partners.

قبول التقارير على مستوى الحدث

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

https://adtech.example/.well-known/attribution-reporting/report-event-attribution

يمكنك ضبط هذا الخادم لقبول طلبات JSON التي تستخدم التنسيق التالي:

{
  "attribution_destination": "android-app://com.advertiser.example",
  "source_event_id": "12345678",
  "trigger_data": "2",
  "report_id": "12324323",
  "source_type": "navigation",
  "randomized_trigger_rate": "0.02"
   [Optional] "source_debug_key": "[64-bit unsigned integer]",
   [Optional] "trigger_debug_key": "[64-bit unsigned integer]",
}

توفّر مفاتيح تصحيح الأخطاء إحصاءات إضافية حول تقارير تحديد المصدر. اطّلِع على مزيد من المعلومات حول ضبطها.

قبول التقارير القابلة للتجميع

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

https://adtech.example/.well-known/attribution-reporting/report-aggregate-attribution

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

يمكنك ضبط هذا الخادم لقبول طلبات JSON التي تستخدم التنسيق التالي:

{
  // Info that the aggregation services also need encoded in JSON
  // for use with AEAD. Line breaks added for readability.
  "shared_info": "{
     \"api\":\"attribution-reporting\",
     \"attribution_destination\": \"android-app://com.advertiser.example.advertiser\",
     \"scheduled_report_time\":\"[timestamp in seconds]\",
     \"source_registration_time\": \"[timestamp in seconds]\",
     \"version\":\"[api version]\",
     \"report_id\":\"[UUID]\",
     \"reporting_origin\":\"https://reporter.example\" }",

  // In the current Developer Preview release, The "payload" and "key_id" fields
  // are not used because the platform does not yet encrypt aggregate reports.
  // Currently, the "debug_cleartext_payload" field holds unencrypted reports.
  "aggregation_service_payloads": [
    {
      "payload": "[base64 HPKE encrypted data readable only by the aggregation service]",
      "key_id": "[string identifying public key used to encrypt payload]",

      "debug_cleartext_payload": "[unencrypted payload]"
    },
  ],

  "source_debug_key": "[64 bit unsigned integer]",
  "trigger_debug_key": "[64 bit unsigned integer]"
}

توفّر مفاتيح تصحيح الأخطاء إحصاءات إضافية حول تقارير الإحالة. مزيد من المعلومات حول ضبطها

إعداد برنامج Android

يسجِّل تطبيق العميل مصادر تحديد المصدر وعوامل التفعيل، ويفعّل إنشاء تقارير على مستوى الحدث وقابلة للتجميع. لإعداد جهاز أو محاكي عميل Android لاستخدام واجهة برمجة التطبيقات Attribution Reporting API، اتّبِع الخطوات التالية:

  1. إعداد بيئة التطوير لـ "مبادرة حماية الخصوصية" على Android
  2. تثبيت صورة نظام على جهاز متوافق أو إعداد محاكي يتيح استخدام "مبادرة حماية الخصوصية" على Android
  3. فعِّل الوصول إلى Attribution Reporting API من خلال تنفيذ يليه. (تكون واجهة برمجة التطبيقات غير مفعّلة تلقائيًا).

    adb shell device_config put adservices ppapi_app_allow_list \"\*\"
  4. إذا كنت تختبر Attribution Reporting API على الجهاز (مثل الاختبار على جهاز يمكنك الوصول إليه)، يمكنك تنفيذ هذا الأمر لإيقاف التسجيل:

    adb shell device_config put adservices disable_measurement_enrollment_check "true"
  5. أدرِج الإذن ACCESS_ADSERVICES_ATTRIBUTION في ملف بيان Android وأدخِل إعدادات خدمات الإعلان لتطبيقك لكي تتمكّن من استخدام واجهات برمجة التطبيقات Attribution Reporting API:

    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
    
  6. (اختياري) إذا كنت تخطّط لتلقّي تقارير تصحيح الأخطاء، أدرِج الإذن ACCESS_ADSERVICES_AD_ID في ملف بيان Android:

    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />
    
  7. يمكنك الإشارة إلى إعدادات خدمات الإعلانات في عنصر <application> ضمن بيانك:

    <property android:name="android.adservices.AD_SERVICES_CONFIG"
              android:resource="@xml/ad_services_config" />
    
  8. حدِّد مرجع XML لخدمات الإعلانات المُشار إليه في البيان، مثل res/xml/ad_services_config.xml. مزيد من المعلومات حول أذونات خدمات عرض الإعلانات والتحكّم في الوصول إلى حِزم تطوير البرامج (SDK)

    <ad-services-config>
        <attribution allowAllToAccess="true" />
    </ad-services-config>
    

تسجيل أحداث الإعلانات

يجب أن يسجِّل تطبيقك المصادر والإحالات الناجحة عند حدوثها لضمان تسجيلها بشكلٍ سليم. تتضمّن فئة MeasurementManager طُرقًا لمساعدتك في تسجيل أحداث مصادر تحديد المصدر و عوامل تشغيل الإحالات الناجحة.

تسجيل حدث مصدر إحالة

عند عرض إعلان أو النقر عليه، يطلب تطبيق الناشر من registerSource() تسجيل مصدر تحديد المصدر كما هو موضّح في مقتطف الرمز.

تتيح واجهة برمجة التطبيقات Attribution Reporting API الأنواع التالية من أحداث مصدر تحديد المصدر:

  • النقرات التي تسجّلها عادةً ضمن طريقة طلب معاودة الاتصال مشابهة لمحاولة onClick(). ويحدث عادةً الحدث المشغِّل المقابل بعد حدث النقرة بوقت قصير. يقدّم هذا النوع من الأحداث المزيد من المعلومات عن تفاعل المستخدِم، وبالتالي فهو نوع جيد من مصادر تحديد المصدر لمنحه أولوية عالية.
  • المشاهدات التي تسجّلها عادةً ضمن طريقة طلب معاودة الاتصال مشابهة لمحاولة onAdShown(). قد يحدث الحدث المشغِّل المقابل بعد ساعات أو أيام من حدث العرض.

Kotlin

companion object {
    private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}

val measurementManager = context.getSystemService(MeasurementManager::class.java)
var exampleClickEvent: InputEvent? = null

// Use the URI of the server-side endpoint that accepts attribution source
// registration.
val attributionSourceUri: Uri =
  Uri.parse("https://adtech.example/attribution_source?AD_TECH_PROVIDED_METADATA")

val future = CompletableFuture<Void>()

adView.setOnTouchListener(_: View?, event: MotionEvent?)) ->
    exampleClickEvent = event
    true
}

// Register Click Event
measurementManager.registerSource(
        attributionSourceUri,
        exampleClickEvent,
        CALLBACK_EXECUTOR,
        future::complete)

// Register View Event
measurementManager.registerSource(
        attributionSourceUri,
        null,
        CALLBACK_EXECUTOR,
        future::complete)

Java

private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();
private InputEvent exampleClickEvent;

MeasurementManager measurementManager =
        context.getSystemService(MeasurementManager.class);

// Use the URI of the server-side endpoint that accepts attribution source
// registration.
Uri attributionSourceUri =
Uri.parse("https://adtech.example/attribution_source?AD_TECH_PROVIDED_METADATA");

CompletableFuture<Void> future = new CompletableFuture<>();

adView.setOnTouchListener(v, event)) -> {
    exampleClickEvent = event;
    return true;
}

// Register Click Event
measurementManager.registerSource(attributionSourceUri, exampleClickEvent,
        CALLBACK_EXECUTOR, future::complete);

// Register View Event
measurementManager.registerSource(attributionSourceUri, null,
        CALLBACK_EXECUTOR, future::complete);

بعد التسجيل، تُصدر واجهة برمجة التطبيقات طلب HTTP POST إلى نقطة نهاية الخدمة على العنوان الذي حدّده attributionSourceUri. يتضمّن استجابة نقطة النهاية قيمتَي destination, source_event_id, expiry و source_priority.

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

تمت إضافة إمكانية استخدام سلاسل عمليات إعادة التوجيه في registerSource و registerTrigger. بالإضافة إلى عنوان التسجيل، يمكن لمستخدِم واجهة برمجة التطبيقات الآن تقديم إعادة توجيه HTTP كاستجابة الخادم التي تتضمّن رمز حالة 302 وعنوان "الموقع الجغرافي" مع عنوان URL التالي الذي يجب الانتقال إليه من أجل تسجيل إضافي.

لا يتم استخدام سوى حقل "الوجهة" المقدَّم في الزيارة الأولى في سلسلة الربط. يكون عدد الزيارات مساويًا لعدد الزيارات المسموح به في عناوين "Attribution-Reporting-Redirect". يُعدّ هذا الإجراء متاحًا لإعادة التوجيه بالإضافة إلى الإجراء الحالي "Attribution-Reporting-Redirect"، وإذا كان كلاهما متوفّرًا، يتم منح الأولوية لـ "Attribution-Reporting-Redirect".

تسجيل حدث تشغيل إحالة ناجحة

لتسجيل حدث مشغّل إحالة ناجحة، استخدِم registerTrigger() في تطبيقك:

Kotlin

companion object {
    private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}

val measurementManager = context.getSystemService(MeasurementManager::class.java)

// Use the URI of the server-side endpoint that accepts trigger registration.
val attributionTriggerUri: Uri =
    Uri.parse("https://adtech.example/trigger?AD_TECH_PROVIDED_METADATA")

val future = CompletableFuture<Void>()

// Register trigger (conversion)
measurementManager.registerTrigger(
        attributionTriggerUri,
        CALLBACK_EXECUTOR,
        future::complete)

Java

private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();

MeasurementManager measurementManager =
        context.getSystemService(MeasurementManager.class);

// Use the URI of the server-side endpoint that accepts trigger registration.
Uri attributionTriggerUri =
        Uri.parse("https://adtech.example/trigger?AD_TECH_PROVIDED_METADATA");

CompletableFuture<Void> future = new CompletableFuture<>();

// Register trigger (conversion)
measurementManager.registerTrigger(
        attributionTriggerUri,
        CALLBACK_EXECUTOR,
        future::complete)

بعد التسجيل، تُصدر واجهة برمجة التطبيقات طلب HTTP POST إلى نقطة نهاية الخدمة على العنوان الذي حدّده attributionTriggerUri. يتضمّن استجابة نقطة النهاية قيم التقارير عن الأحداث والتقارير المجمّعة.

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

تسجيل قياس على مستوى التطبيق والويب

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

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

يعرض مقتطف الرمز التالي مثالاً على طلب البيانات من واجهة برمجة التطبيقات الذي يُجريه المتصفّح لتسجيل مصدر تحديد المصدر قبل توجيه المستخدم إلى أحد التطبيقات:

Kotlin

companion object {
    private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}

val measurementManager =
        context.getSystemService(MeasurementManager::class.java)
var exampleClickEvent: InputEvent? = null

// Use the URIs of the server-side endpoints that accept attribution source
// registration.
val sourceParam1 = WebSourceParams.Builder(Uri.parse(
        "https://adtech1.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
// True, if debugging is allowed for the ad tech.
    .setDebugKeyAllowed(true)
    .build()

val sourceParam2 = WebSourceParams.Builder(Uri.parse(
        "https://adtech2.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
    .setDebugKeyAllowed(false)
    .build()

val sourceParam3 = WebSourceParams.Builder(Uri.parse(
        "https://adtech3.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
    .build()

val sourceParams = Arrays.asList(sourceParam1, sourceParam2, sourceParam3)
val publisherOrigin = Uri.parse("https://publisher.example")
val appDestination = Uri.parse("android-app://com.example.store")
val webDestination = Uri.parse("https://example.com")

val future = CompletableFuture<Void>()

adView.setOnTouchListener {_: View?, event: MotionEvent? ->
    exampleClickEvent = event
    true
}
val clickRegistrationRequest = WebSourceRegistrationRequest.Builder(
          sourceParams,
          publisherOrigin)
      .setAppDestination(appDestination)
      .setWebDestination(webDestination)
      .setInputEvent(event)
      .build()
val viewRegistrationRequest = WebSourceRegistrationRequest.Builder(
          sourceParams,
          publisherOrigin)
      .setAppDestination(appDestination)
      .setWebDestination(webDestination)
      .setInputEvent(null)
      .build()

// Register a web source for a click event.
measurementManager.registerWebSource(
        clickRegistrationRequest,
        CALLBACK_EXECUTOR,
        future::complete)

// Register a web source for a view event.
measurementManager.registerWebSource(
        viewRegistrationRequest,
        CALLBACK_EXECUTOR,
        future::complete)

Java

private static final Executor CALLBACK_EXECUTOR =
        Executors.newCachedThreadPool();
private InputEvent exampleClickEvent;

MeasurementManager measurementManager =
        context.getSystemService(MeasurementManager.class);

// Use the URIs of the server-side endpoints that accept attribution source
// registration.
WebSourceParams sourceParam1 = WebSourceParams.Builder(Uri.parse(
        "https://adtech1.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
    // True, if debugging is allowed for the ad tech.
    .setDebugKeyAllowed(true)
    .build();

WebSourceParams sourceParam2 = WebSourceParams.Builder(Uri.parse(
        "https://adtech2.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
    .setDebugKeyAllowed(false)
    .build();

WebSourceParams sourceParam3 = WebSourceParams.Builder(Uri.parse(
        "https://adtech3.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
    .build();

List<WebSourceParams> sourceParams =
        Arrays.asList(sourceParam1, sourceParam2, sourceParam3);
Uri publisherOrigin = Uri.parse("https://publisher.example");
Uri appDestination = Uri.parse("android-app://com.example.store");
Uri webDestination = Uri.parse("https://example.com");

CompletableFuture<Void> future = new CompletableFuture<>();

adView.setOnTouchListener(v, event) -> {
    exampleClickEvent = event;
    return true;
}

WebSourceRegistrationRequest clickRegistrationRequest =
        new WebSourceRegistrationRequest.Builder(sourceParams, publisherOrigin)
    .setAppDestination(appDestination)
    .setWebDestination(webDestination)
    .setInputEvent(event)
    .build();
WebSourceRegistrationRequest viewRegistrationRequest =
        new WebSourceRegistrationRequest.Builder(sourceParams, publisherOrigin)
    .setAppDestination(appDestination)
    .setWebDestination(webDestination)
    .setInputEvent(null)
    .build();

// Register a web source for a click event.
measurementManager.registerWebSource(clickRegistrationRequest,
        CALLBACK_EXECUTOR, future::complete);

// Register a web source for a view event.
measurementManager.registerWebSource(viewRegistrationRequest,
        CALLBACK_EXECUTOR, future::complete);

يعرض مقتطف الرمز التالي مثالاً على طلب البيانات من واجهة برمجة التطبيقات الذي يُجريه المتصفّح لتسجيل إحالة ناجحة بعد توجيه المستخدِم من التطبيق:

Kotlin

companion object {
    private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}

val measurementManager = context.getSystemService(MeasurementManager::class.java)

// Use the URIs of the server-side endpoints that accept trigger registration.
val triggerParam1 = WebTriggerParams.Builder(Uri.parse(
        "https://adtech1.example/trigger?AD_TECH_PROVIDED_METADATA"))
    // True, if debugging is allowed for the ad tech.
    .setDebugKeyAllowed(true)
    .build()

val triggerParam2 = WebTriggerParams.Builder(Uri.parse(
        "https://adtech2.example/trigger?AD_TECH_PROVIDED_METADATA"))
    .setDebugKeyAllowed(false)
    .build()

val triggerParams = Arrays.asList(triggerParam1, triggerParam2)
val advertiserOrigin = Uri.parse("https://advertiser.example")

val future = CompletableFuture<Void>()

val triggerRegistrationRequest = WebTriggerRegistrationRequest.Builder(
        triggerParams,
        advertiserOrigin)
    .build()

// Register the web trigger (conversion).
measurementManager.registerWebTrigger(
    triggerRegistrationRequest,
    CALLBACK_EXECUTOR,
    future::complete)

Java

private static final Executor CALLBACK_EXECUTOR =
        Executors.newCachedThreadPool();

MeasurementManager measurementManager =
        context.getSystemService(MeasurementManager.class);

// Use the URIs of the server-side endpoints that accept trigger registration.
WebTriggerParams triggerParam1 = WebTriggerParams.Builder(Uri.parse(
        "https://adtech1.example/trigger?AD_TECH_PROVIDED_METADATA"))
    // True, if debugging is allowed for the ad tech.
    .setDebugKeyAllowed(true)
    .build();

WebTriggerParams triggerParam2 = WebTriggerParams.Builder(Uri.parse(
        "https://adtech2.example/trigger?AD_TECH_PROVIDED_METADATA"))
    .setDebugKeyAllowed(false)
    .build();

List<WebTriggerParams> triggerParams =
        Arrays.asList(triggerParam1, triggerParam2);
Uri advertiserOrigin = Uri.parse("https://advertiser.example");

CompletableFuture<Void> future = new CompletableFuture<>();

WebTriggerRegistrationRequest triggerRegistrationRequest =
        new WebTriggerRegistrationRequest.Builder(
            triggerParams, advertiserOrigin)
    .build();

// Register the web trigger (conversion).
measurementManager.registerWebTrigger( triggerRegistrationRequest,
        CALLBACK_EXECUTOR, future::complete);

إضافة تشويش للحفاظ على الخصوصية

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

نوع المصدر

قيمة مصدر الوجهة

احتمالية حدوث تقرير يتضمّن بيانات غير دقيقة لكل تسجيل مصدر

عرض

إما تطبيق أو موقع إلكتروني

0.0000025

عرض

التطبيقات والإنترنت

0.0000042

النقر

إما تطبيق أو موقع إلكتروني

0.0024263

النقر

التطبيقات والإنترنت

0.0170218

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

لا تتطلّب بعض تقنيات عرض الإعلانات تقارير على مستوى الحدث لتحديد ما إذا كان عامل التفعيل قد حدث في التطبيق أو وجهة الويب. يمكن لتكنولوجيات الإعلان استخدام الحقل coarse_event_report_destinations ضمن العنوان Attribution-Reporting-Register-Source لتقليل الضوضاء. إذا حصل مصدر يحتوي على الحقل coarse_event_report_destinations المحدّد على الإحالة، سيتضمّن التقرير الناتج كلاً من وجهات التطبيق والويب بدون تمييز بشأن مكان حدوث العامل المشغِّل الفعلي.

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

عنوان HTTP لتسجيل مصدر يستند إلى النقرات:

Attribution-Reporting-Register-Source: {
    "destination": "android-app://com.advertiser.example",
    "web_destination": "https://advertiser.com",
    "source_event_id": "234",
    "expiry": "60000",
    "priority": "5",
    // Ad tech opts out of receiving app-web destination distinction
    // in event report, avoids additional noise
    "coarse_event_report_destinations": "true"
}

يتم تسجيل عامل تشغيل من التطبيق الذي يحمل اسم الحزمة com.advertiser.example:

Attribution-Reporting-Register-Trigger: {
    "event_trigger_data": [{
    "trigger_data": "1",
    "priority": "1"
    }],
}

يتم تسجيل عامل تشغيل من متصفّح من الموقع الإلكتروني الذي يتضمّن نطاق eTLD+1. https://advertiser.com:

Attribution-Reporting-Register-Trigger: {
    "event_trigger_data": [{
    "trigger_data": "2",
    "priority": "2"
    }],
}

يتمّ إنشاء التقارير الناتجة على مستوى الحدث. بافتراض أنّه تم تحديد مصدر كلا المشغّلين، يتم إنشاء التقارير التالية على مستوى الحدث:

  {
    "attribution_destination": ["android-app://com.advertiser.example,https://advertiser.com"],
    "scheduled_report_time": "800176400",
    "source_event_id": "53234",
    "trigger_data": "1",
    // Can be "event" if source were registered by user viewing the ad
    "source_type": "navigation",
    // Would be 0.0170218 without coarse_event_report_destinations as true in the source
    "randomized_trigger_rate": 0.0024263
  }

إنشاء التقارير وإرسالها

تُرسِل Attribution Reporting API التقارير إلى نقاط النهاية على خادمك التي تقبِّل التقارير على مستوى الحدث والتقارير القابلة للتجميع.

فرض تنفيذ مهام إعداد التقارير

بعد تسجيل حدث مصدر تحديد المصدر أو تسجيل حدث مشغّل، يحدّد النظام موعدًا لتشغيل وظيفة إعداد التقارير. يتم تنفيذ هذه المهمة تلقائيًا كل 4 ساعات. لأغراض الاختبار، يمكنك فرض تنفيذ مهام إعداد التقارير أو تقصير الفاصل الزمني بين المهام.

فرض تنفيذ مهمة تحديد المصدر:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 5

فرض تنفيذ مهمة إعداد التقارير على مستوى الحدث:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 3

فرض تنفيذ مهمة إعداد التقارير القابلة للتجميع:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 7

راجِع الإخراج في logcat لمعرفة وقت تنفيذ المهام. من المفترض أن يظهر بالشكل التالي:

JobScheduler: executeRunCommand(): com.google.android.adservices.api/0 5 s=false f=true

فرض تسليم التقارير

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

التحقّق من التقارير على خادمك

بعد إرسال التقارير، تأكَّد من تسليمها من خلال التحقّق من التقارير المستلَمة وملفّات سجلّ الخادم السارية، مثل سجلّ الخادم النموذجي أو النظام المخصّص.

فك ترميز تقريرك المجمّع

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

في ما يلي مثال على فك ترميز محتوى الحقل debug_cleartext_payload بخطوتَين: الأولى باستخدام فك ترميز Base 64 والثانية باستخدام فك ترميز CBOR.

String base64DebugPayload  = "omRkYXRhgqJldmFsdWVEAAAGgGZidWNrZXRQAAAAAAAAAAAAAAAAAAAKhaJldmFsdWVEAACAAGZidWNrZXRQAAAAAAAAAAAAAAAAAAAFWWlvcGVyYXRpb25paGlzdG9ncmFt";
byte[] cborEncoded = Base64.getDecoder().decode(base64DebugPayload);

// CbodDecoder comes from this library https://github.com/c-rack/cbor-java
final List<DataItem> dataItems = new CborDecoder(new ByteArrayInputStream(cborEncoded)).decode();

// In here you can see the contents, but the value will be something like:
// Data items: [{ data: [{ value: co.nstant.in.cbor.model.ByteString@a8b5c07a,
//   bucket: co.nstant.in.cbor.model.ByteString@f812097d },
//   { value: co.nstant.in.cbor.model.ByteString@a8b5dfc0,
//   bucket: co.nstant.in.cbor.model.ByteString@f8120934 }], operation: histogram }]
Log.d("Data items : " + dataItems);

// In order to see the value for bucket and value, you can traverse the data
// and get their values, something like this:
final Map payload = (Map) dataItems.get(0);
final Array payloadArray = (Array) payload.get(new UnicodeString("data"));

payloadArray.getDataItems().forEach(i -> {
    BigInteger value = new BigInteger(((ByteString) ((Map)i).get(new UnicodeString("value"))).getBytes());
    BigInteger bucket = new BigInteger(((ByteString) ((Map)i).get(new UnicodeString("bucket"))).getBytes());
    Log.d("value : " + value + " ;bucket : " + bucket);
});

الاختبار

لمساعدتك في بدء استخدام Attribution Reporting API، يمكنك استخدام مشروع MeasurementSampleApp على GitHub. يوضّح نموذج التطبيق هذا تسجيل مصدر تحديد المصدر وتسجيل المشغِّل.

بالنسبة إلى نقاط نهاية الخادم، يمكنك الاطّلاع على المراجع التالية أو على الحلّ المخصّص:

  • يتضمّن MeasurementAdTechServerSpec تعريفات خدمات OpenAPI، التي يمكن نشرها على منصات تطبيقات مصغّرة أو خدمات مصغرة متوافقة.
  • يتضمّن MeasurementAdTechServer عملية تنفيذ مرجعية لخادم mock استنادًا إلى تطبيق Spring Boot لـ Google App Engine.

المتطلبات الأساسية

يمكنك نشر واجهات برمجة تطبيقات وهمية على نقاط نهاية عن بُعد يمكن الوصول إليها من جهازك الاختباري أو المحاكي. لتسهيل الاختبار، يمكنك الرجوع إلى نموذجَي المشروع MeasurementAdTechServerSpec وMeasurementAdTechServer.

الوظائف التي يجب اختبارها

  • اتّبِع الخطوات اللازمة لتسجيل مصدر تحديد المصدر وعوامل تشغيل الإحالات الناجحة. تأكَّد من أنّ نقاط النهاية من جهة الخادم تستجيب بالتنسيق الصحيح.
  • تنفيذ مهام إعداد التقارير
  • تحقّق من تسليم التقارير في الخلفية أو وحدة التحكّم في الخادم التجريبي.

الميزات القادمة

إعدادات مرنة على مستوى الحدث

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

  • المرحلة 1: إعدادات بسيطة ومرنة على مستوى الحدث، وهي مجموعة فرعية من المرحلة 2.
  • المرحلة 2: إصدار كامل من الإعدادات المرنة على مستوى الحدث.

المرحلة 1: مستوى الحدث المرن البسيط

سنضيف المَعلمتَين الاختياريتَين التاليتَين إلى ملف JSON في Attribution-Reporting-Register-Source:

  • max_event_level_reports
  • event_report_windows
{
  ...
  // Optional. This is a parameter that acts across all trigger types for the
  // lifetime of this source. It restricts the total number of event-level
  // reports that this source can generate. After this maximum is hit, the
  // source is no longer capable of producing any new data. The use of
  // priority in the trigger attribution algorithm in the case of multiple
  // attributable triggers remains unchanged. Defaults to 3 for navigation
  // sources and 1 for event sources
  "max_event_level_reports": <int>,

  // Optional. Represents a series of time windows, starting at 0. Reports
  // for this source will be delivered an hour after the end of each window.
  // Time is encoded as seconds after source registration. If
  // event_report_windows is omitted, will use the default windows. This
  // field is mutually exclusive with the existing `event_report_window` field.
  // // End time is exclusive.
  "event_report_windows": {
    "start_time": <int>,
    "end_times": [<int>, ...]
  }
}

مثال على الإعداد المخصّص

يساعد هذا المثال على ضبط الإعدادات للمطوّر الذي يريد تحسين تلقي التقارير في الفترات السابقة لإعداد التقارير.

{
  ...
  "max_event_level_reports": 2,
  "event_report_windows": {
    "end_times": [7200, 43200, 86400] // 2 hours, 12 hours, 1 day in seconds
  }
}

المرحلة 2: مستوى الحدث المرن بالكامل

بالإضافة إلى المَعلمات التي تمت إضافتها في المرحلة 1، سنضيف trigger_specs مَعلمة اختيارية إضافية إلى ملف JSON في Attribution-Reporting-Register-Source.

{
  // A trigger spec is a set of matching criteria, along with a scheme to
  // generate bucketized output based on accumulated values across multiple
  // triggers within the specified event_report_window. There will be a limit on
  // the number of specs possible to define for a source.
  "trigger_specs": [{
    // This spec will only apply to registrations that set one of the given
    // trigger data values (non-negative integers) in the list.
    // trigger_data will still appear in the event-level report.
    "trigger_data": [<int>, ...]

    // Represents a series of time windows, starting at the source registration
    // time. Reports for this spec will be delivered an hour after the end of
    // each window. Time is encoded as seconds after source registration.
    // end_times must consist of strictly increasing positive integers.
    //
    // Note: specs with identical trigger_data cannot have overlapping windows;
    // this ensures that triggers match at most one spec. If
    // event_report_windows is omitted, will use the "event_report_window" or
    // "event_report_windows" field specified at the global level for the source
    // (or the default windows if none are specified). End time is exclusive.
    "event_report_windows": {
      "start_time": <int>,
      "end_times": [<int>, ...],
    }

    // Represents an operator that summarizes the triggers within a window
    // count: number of triggers attributed within a window
    // value_sum: sum of the value of triggers within a window
    // The summary is reported as an index into a bucketization scheme. Defaults
    // to "count"
    "summary_window_operator": <one of "count" or "value_sum">,

    // Represents a bucketization of the integers from [0, MAX_INT], encoded as
    // a list of integers where new buckets begin (excluding 0 which is
    // implicitly included).
    // It must consist of strictly increasing positive integers.
    //
    // e.g. [5, 10, 100] encodes the following ranges:
    // [[0, 4], [5, 9], [10, 99], [100, MAX_INT]]
    //
    // At the end of each reporting window, triggers will be summarized into an
    // integer which slots into one of these ranges. Reports will be sent for
    // every new range boundary that is crossed. Reports will never be sent for
    // the range that includes 0, as every source is initialized in this range.
    //
    // If omitted, then represents a trivial mapping
    // [1, 2, ... , MAX_INT]
    // With MAX_INT being the maximum int value defined by the browser.
    "summary_buckets": [<bucket start>, ...]
  }, {
    // Next trigger_spec
  } ...],

  // See description in phase 1.
  "max_event_level_reports": <int>
  // See description in phase 1.
  "event_report_windows": {
    "start_time": <int>,
    "end_times": [<int>, ...]
  }
}

تحدّد هذه الإعدادات بالكامل مساحة الإخراج للتقارير على مستوى الحدث، حسب تسجيل المصدر. بالنسبة إلى كل مواصفات المشغِّل، نحدِّد بالكامل ما يلي:

  • مجموعة من معايير المطابقة:
    • بيانات العوامل المشغِّلة المحدّدة التي تنطبق عليها هذه المواصفات يكون هذا المصدر مؤهَّلاً للمطابقة فقط مع عوامل التشغيل التي تحتوي على إحدى قيم trigger_data المحدّدة في trigger_specs. بعبارة أخرى، إذا كان المشغِّل سيتطابق مع هذا المصدر ولكن trigger_data ليس أحد قيمه في إعدادات المصدر، سيتم تجاهل المشغِّل.
    • عندما يتطابق مشغِّل محدّد مع هذه المواصفات (باستخدام event_report_windows). يُرجى العِلم أنّه لا يزال من الممكن مطابقة المشغِّل مع مصدر للتقارير القابلة للتجميع على الرغم من عدم استيفاء معيارَي المطابقة الواردَين سابقًا.
  • خوارزمية محدّدة لتلخيص جميع عوامل التفعيل وتجميعها ضمن نافذة تحديد المصدر يسمح ذلك للعوامل المشغِّلة بتحديد مَعلمة value يتم تجميعها لمواصفات معيّنة، ولكن يتم تسجيلها كقيمة مجمّعة.

ستتيح المشغّلات أيضًا إضافة مَعلمة قيمة اختيارية في القاموس ضمن event_trigger_data.

{
  "event_trigger_data": [
    {
      "trigger_data": "2",
      "value": 100,  // Defaults to 1
      "filters": ...
    },
    ...
  ]
}

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

  • تطبيق فلاتر تحديد المصدر على مستوى الحساب
  • بالنسبة إلى كلّ مواصفات عامل التفعيل، قيِّم event_trigger_data في المواصفة للعثور على مطابقة، باستخدام event_reporting_window للمواصفة. يعمل المستوى الأعلى event_reporting_windows كقيمة تلقائية في حال كانت أيّ مواصفات للعامل المشغِّل هي الحقل الفرعي event_report_windows غير المتوفّر.
  • يتم اختيار المواصفة الأولى التي تتطابق مع القيمة لتحديد المصدر، ويتم زيادة قيمة الملخّص بمقدار value.

عند اكتمال event_report_window لمواصفة معيّنة، سنربط قيمة الملخّص بمجموعة، ونرسل تقريرًا على مستوى الحدث لكل زيادة في مجموعة الملخّص ناتجة عن قيم المشغّلات المنسوبة. ستتضمّن التقارير حقلًا إضافيًا واحدًا، وهو trigger_summary_bucket.

{
  ...
  "trigger_summary_bucket": [<bucket start>, <bucket end>],
}

الإعدادات التي تُعادل الإصدار الحالي

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

من الممكن أن تكون هناك إعدادات متعددة متكافئة، نظرًا لإمكانية ضبط بعض المَعلمات على أنّها تلقائية أو مُهمّلة.

مصادر الأحداث المماثلة
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
  "trigger_specs": [
  {
    "trigger_data": [0, 1],
    "event_report_windows": {
      "end_times": [<30 days>]
    },
    "summary_window_operator": "count",
    "summary_buckets": [1],
  }],
  "max_event_level_reports": 1,
  ...
  // expiry must be greater than or equal to the last element of the end_times
  "expiry": <30 days>,
}
مصادر التنقّل المكافئة
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
  "trigger_specs": [
  {
    "trigger_data": [0, 1, 2, 3, 4, 5, 6, 7],
    "event_report_windows": {
      "end_times": [<2 days>, <7 days>, <30 days>]
    },
    "summary_window_operator": "count",
    "summary_buckets": [1, 2, 3],
  }],
  "max_event_level_reports": 3,
  ...
  // expiry must be greater than or equal to the last element of the end_times
  "expiry": <30 days>,
}

أمثلة على الإعدادات المخصّصة

في ما يلي بعض الإعدادات الإضافية خارج الإعدادات التلقائية. في كل هذه المثال، تشمل المفاضلات التي يحصل عليها المطوّر ما يلي:

  • تقليل بعض سمات الإعداد التلقائي (#triggers وعدد القيم الفريدة لبيانات المشغِّل و#windows) لزيادة سمة أخرى للحفاظ على مستوى التشويش
  • تقليل بعض سمات الإعداد التلقائي (#triggers، وبيانات المشغِّل وعدد القيم الفريدة للسمة، و#windows) لخفض مستوى التشويش

مجموعات قيم المشغّلات في التقارير

يتيح مثال الإعداد هذا للمطوّر تحسين قيمة البيانات لفترة إعداد تقارير واحدة فقط (مثلاً 7 أيام)، مع تقليل عدد فترات إعداد التقارير لتقليل التشويش. في هذا المثال، أيّ عامل تشغيل يضبط trigger_data على قيمة غير 0 غير مؤهّل للإحالة.

{
  "trigger_specs": [
  {
    "trigger_data": [0],
    "event_report_windows": {
      "end_times": [604800, 1209600] // 7 days, 14 days represented in seconds
    },
    "summary_window_operator": "value_sum",
    "summary_buckets": [5, 10, 100]
  }],
}

يمكن تسجيل عوامل التفعيل باستخدام مجموعة الحقول value، والتي يتم تجميعها و تجميعها. على سبيل المثال، إذا كانت هناك ثلاث عوامل تشغيل خلال 7 أيام من مصدر تسجيلات بالقيم 1 و3 و4.

{ "event_trigger_data": [{"trigger_data": "0", "value": 1}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 3}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 4}] }

يتم جمع القيم إلى 8 ويتم الإبلاغ عنها في التقارير التالية بعد 7 أيام + ساعة واحدة:

// Report 1
{
  ...
  "trigger_summary_bucket": [5, 9]
}

في الأيام السبعة اللاحقة، يتم تسجيل عوامل التفعيل التالية:

{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }

يتم تجميع القيم على النحو التالي: 8 + 50 + 45 = 103. يؤدي ذلك إلى ظهور التقارير التالية في مدّة 14 يومًا + ساعة واحدة:

// Report 2
{
  ...
  "trigger_summary_bucket": [10, 99]
},

// Report 3
{
  ...
  "trigger_summary_bucket": [100, MAX_INT]
}
الإبلاغ عن أعداد عوامل التفعيل

يوضّح هذا المثال كيفية ضبط المطوّر لمصدر للحصول على عدد من عوامل التفعيل يصل إلى 10.

{
  "trigger_specs": [
  {
    "trigger_data": [0],
    "event_report_windows": {
      "end_times": [604800] // 7 days represented in seconds
    },
    // This field could be omitted to save bandwidth since the default is "count"
    "summary_window_operator": "count",
    "summary_buckets": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  }],
}

يتم احتساب عدد عوامل التشغيل المنسوبة التي تم ضبط trigger_data فيها على 0، ويكون الحدّ الأقصى لها 10. يتم تجاهل قيمة المشغِّل لأنّه تم ضبط summary_window_operator على "العدّ". إذا تم تسجيل 4 عوامل تشغيل وربطها بالمصدر، سيظهر التقرير على النحو التالي:

// Report 1
{
  ...
  "trigger_summary_bucket": [1, 1]
}
// Report 2
{
  ...
  "trigger_summary_bucket": [2, 2]
}
// Report 3
{
  ...
  "trigger_summary_bucket": [3, 3]
}
// Report 4
{
  ...
  "trigger_summary_bucket": [4, 4]
}
ثنائي مع إعداد تقارير أكثر تكرارًا

يساعد هذا المثال على إعداد المطوّر الذي يريد معرفة ما إذا حدثت إحالة ناجحة واحدة على الأقل في أوّل 10 أيام (بغض النظر عن القيمة)، ولكن يريد تلقّي التقارير على فترات متكرّرة أكثر من الإعداد التلقائي. مرة أخرى، في هذا المثال، أيّ عامل تشغيل يضبط trigger_data على قيمة غير 0 هو غير مؤهّل للإحالة. لهذا السبب، يُشار إلى حالة الاستخدام هذه باسم ثنائية.

{
  "trigger_specs": [
  {
    "trigger_data": [0],
    "event_report_windows": {
      // 1 day, 2 days, 3 days, 5 days, 7 days, 10 days represented in seconds
      "end_times": [86400, 172800, 259200, 432000, 604800, 864000]
    },
    // This field could be omitted to save bandwidth since the default is "count"
    "summary_window_operator": "count",
    "summary_buckets": [1]
  }],
}
تختلف مواصفات المشغّل من مصدر إلى آخر
{
  "trigger_specs": [
  {
    "trigger_data": [0, 1, 2, 3],
    "event_report_windows": {
      "end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
    }
  }],
  "max_event_level_reports": 3
}
{
  "trigger_specs": [
  {
    "trigger_data": [4, 5, 6, 7],
    "event_report_windows": {
      "end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
    }
  }],
  "max_event_level_reports": 3
}

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

تحديد المصدر على جميع الشبكات بدون عمليات إعادة التوجيه

على تكنولوجيات الإعلان استخدام عمليات إعادة التوجيه لتسجيل مثبّطات مصادر تحديد المصدر المتعدّدة ولإجراء عملية تحديد المصدر على جميع الشبكات. تساعد هذه الميزة في إتاحة تحديد المصدر على مستوى الشبكات المختلفة عندما لا تكون عمليات إعادة التوجيه ممكنة على جميع الشبكات. مزيد من المعلومات

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

يمكن لتقنيات الإعلان الاختيار من بين aggregation_keys في مصادرها المسجّلة التي تنوي مشاركتها مع تقنيات الإعلان الشريكة. يمكن الإفصاح عن هذه المفاتيح في الحقل shared_aggregation_keys الاختياري، والذي يقع ضمن عنوان تسجيل المصدر Attribution-Reporting-Register-Source:

"shared_aggregation_keys": ["[key name1]", "[key name2]"]

يتم إنشاء المصادر المشتقة استنادًا إلى الإعدادات ضمن عنوان التفعيل تسجيل Attribution-Reporting-Register-Trigger:

  // Specifies the configuration based on which derived sources should be
  // generated. Those derived sources will be included for source matching at the
  // time of attribution. For example, if adtech2 is registering a trigger with an
  // attribution_config with source_network as adtech1, available sources
  // registered by adtech1 will be considered with additional filtering criteria
  // applied to that set as mentioned in the attribution_config. Derived
  // sources can have different values to priority, post_install_exclusivity_window
  // etc.

  "attribution_config": [
    {
      // Derived sources are created from this adtech's registered sources
      "source_network": "[original source's adtech enrollment ID]",
      //(optional) Filter sources whose priority falls in this range
      "source_priority_range": {
        "start": [priority filter lower bound],
        "end": [priority filter upper bound]
      },
      // (optional) Filter sources whose at least one of filter maps matches these
      // filters
      "source_filters": {
        "key name 1": ["key1 value 1"]
      },
      // (optional) Filter sources whose none of filter map matches these
      // filters
        "source_not_filters": {
          "key name 1": ["key1 value 1"]
        },
      // (optional) Apply this priority to the generated derived sources
      "priority": "[64 bit signed integer]",
      // (optional) The derived source will have expiry set as this or parent
      // source's, whichever is earlier
      "expiry": "[64 bit signed integer]",
      // (optional) set on the derived source
      "filter_data": {
        "key name 1": ["key1 value 1"]
      },
      // (optional) set on the derived source
      "post_install_exclusivity_window": "[64-bit unsigned integer]"
    }
  ]

في ما يلي نسخة تم فيها إضافة أمثلة على القيم:

  "attribution_config": [
    {
      "source_network": "adtech1-enrollment-id",
      "source_priority_range": {
        "start": 50,
        "end": 100
      },
      "source_filters": {
        "source_type": ["NAVIGATION"]
      },
      "source_not_filters": {
        "product_id": ["789"]
      },
      "priority": "30",
      "expiry": "78901",
      // (optional) set on the derived source
      "filter_data": {
        "product_id": ["1234"]
        },
      // (optional) set on the derived source
      "post_install_exclusivity_window": "7890"
    }
  ]

تمت إضافة حقلَين اختياريَين جديدَين لعنوان التسجيل. تُفعِّل هذه الحقول معرّف تكنولوجيا الإعلان الفائزة في مفاتيح التقارير القابلة للتجميع:

  • x_network_bit_mapping: تعيين بتات معرّف تقنية الإعلان إلى معرّف التسجيل
  • x_network_data: الإزاحة (الترحيل لليسار) لتقنية الإعلان الفائزة x_network_bit_mapping أو العملية باستخدام مفتاح التفعيل
مثال:
"Attribution-Reporting-Register-Trigger": {
  "attribution_config": [...],
  "aggregatable_trigger_data": [
    {
     "key_piece": "0x400",
     "source_keys": ["campaignCounts"]
      "x_network_data" : {
        "key_offset" : 12 // [64 bit unsigned integer]
      }
    }
    
  ]
  
  "x_network_bit_mapping": {
   // This mapping is used to generate trigger key pieces with AdTech identifier
   // bits. eg. If AdTechA's sources wins the attribution then 0x1 here will be
   // OR'd with the trigger key pieces to generate the final key piece.
    "AdTechA-enrollment_id": "0x1", // Identifier bits in hex for A
    "AdTechB-enrollment_id": "0x2"  // Identifier bits in hex for B
  }
  
}

في ما يلي عملية احتساب مفتاح التفعيل الناتجة عند إنشاء تقرير ل مصدر AdTechB:

  • key_piece: 0x400 (010000000000)
  • key_offset: 12
  • قيمة enrollment_id لخدمة AdtechB: 2 (010) (من x_network_bit_mapping)
  • جزء مفتاح التفعيل الناتج: 0x400 | 0x2 << 12 = 0x2400

القيود

للحصول على قائمة بالميزات قيد التطوير في "وقت تشغيل حزمة SDK"، يمكنك الاطّلاع على ملاحظات الإصدار.

الإبلاغ عن الأخطاء والمشاكل

إنّ ملاحظاتك وآرائك هي جزء أساسي من "مبادرة حماية الخصوصية" على Android. يُرجى إعلامنا بأي مشاكل تواجهها أو أفكار لتحسين "مبادرة حماية الخصوصية" على Android.