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

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


تقديم ملاحظات

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

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

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

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

قبل البدء

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

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

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

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

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

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

يجب أن تكون نقطة النهاية هذه قابلة للاستهداف من معرف موارد منتظم (URI) مشابه لما يلي:

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.

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

يجب أن تكون نقطة النهاية هذه قابلة للاستهداف من معرف موارد منتظم (URI) مشابه لما يلي:

https://adtech.example/attribution_trigger

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

// 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). راجِع المقالة التسجيل للحصول على خصوصية حساب وضع الحماية لمزيد من المعلومات حول تسجيل معرّفات الموارد المنتظمة (URI). (عنوان 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]",
}

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

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

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

    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 تنفيذًا مرجعيًا لنموذج تجريبي تطبيق يستند إلى تطبيق Spring Boot في Google App Engine.

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

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

وظائف الاختبار

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

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

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

ننصحك بالضبط التلقائي لإعداد التقارير على مستوى الحدث للبدء لاختبار الأداة، ولكنه قد لا يكون مثاليًا لجميع حالات الاستخدام. تحديد المصدر وستوفر 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>,
}

أمثلة على عمليات الضبط المخصّصة

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

  • تقليل بعض أبعاد التهيئة الافتراضية (#عوامل تشغيل، تشغيل البيانات عدد القيم الفريدة للسمة، و#نوافذ) لزيادة قيمة سلعة أخرى للحفاظ على مستوى التشويش
  • تقليل بعض أبعاد التهيئة الافتراضية (#عوامل تشغيل، تشغيل البيانات عدد القيم الفريدة للسمة، #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.