دليل مطوّري برامج 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 أو أي خادم وهمي آخر التي تقبل هذا التنسيق. انشر كل نقطة نهاية وتتبع معرّفات الموارد المنتظمة (URI) لاستخدامها في تطبيقك. للتحقّق من تسليم التقرير، يُرجى الرجوع إلى المكالمات. التي تم إجراؤها سابقًا على منصة نموذجية أو بدون خادم.
  • يمكنك تشغيل خادمك المستقل باستخدام التطبيق المستند إلى Spring Boot عيّنة من Kotlin يمكنك نشر هذا الخادم على مقدّم خدمات السحابة الإلكترونية أو على البنية الأساسية الداخلية.
  • استخدم تعريفات الخدمة كأمثلة لدمج نقاط النهاية في النظام الحالي.

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

يجب أن تكون نقطة النهاية هذه قابلة للتوجيه من عنوان 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 تحتوي على معرّفات الموارد المنتظمة (URI) لشركاء تقنية الإعلان، سيتم بعد ذلك، تقدِّم Attribution Reporting API طلبًا مشابهًا لكل عنوان URI. كل تقنية من تقنيات الإعلان على الشريك إعداد خادم يستجيب بهذه العناوين:

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 يحتوي على عناوين URL لشركاء تكنولوجيا الإعلان، تقدّم واجهة برمجة التطبيقات Attribution Reporting API طلبًا مشابهًا لكل عنوان URL. على كل شريك تكنولوجيا إعلانات ضبط خادم يستجيب بالرؤوس التالية:

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

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

يجب أن تكون نقطة النهاية هذه قابلة للوصول إليها من معرف موارد منتظم (URI). اطّلِع على الاشتراك في حساب على "مبادرة حماية الخصوصية" للحصول على مزيد من المعلومات عن تسجيل عناوين URL. (عنوان URI هو الاستنتاج من مصدر الخوادم المستخدمة لقبول تسجيل المصدر تسجيل مشغِّل الشبكة). استخدام أمثلة على معرّفات الموارد المنتظمة (URI) لنقاط النهاية التي تقبل المصدر التسجيل وقبول تسجيل المشغِّل، يكون معرِّف الموارد المنتظم (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 هو الاستنتاج من مصدر الخوادم المستخدمة لقبول تسجيل المصدر تسجيل مشغِّل الشبكة). استخدام أمثلة على معرّفات الموارد المنتظمة (URI) لنقاط النهاية التي تقبل المصدر التسجيل وقبول تسجيل المشغِّل، يكون معرِّف الموارد المنتظم (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-إعادة توجيه" العناوين. بالإضافة إلى ذلك، يمكنك استخدام ميزة إعادة التوجيه هذه إلى "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. يتضمّن استجابة نقطة النهاية قيم التقارير عن الأحداث والتقارير المجمّعة.

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

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

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

بما أنّ هناك اختلافات في طريقة تنظيم تكنولوجيات الإعلان على الويب وعلى Android، أضفنا واجهات برمجة تطبيقات جديدة لتسجيل المصادر وعوامل التفعيل عند حدوثها على المتصفّحات. يتمثل الاختلاف الرئيسي بين واجهات برمجة التطبيقات هذه وبين لواجهات برمجة التطبيقات (API) القائمة على التطبيق، نتوقع أن يتبع المتصفح عمليات إعادة التوجيه، وأن يطبق أي فلاتر خاصة بكل متصفح، وتمرير عمليات التسجيل الصالحة إلى النظام الأساسي من خلال يَتِمُّ الْآنَ الِاتِّصَالْ بِـ 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.