คู่มือนักพัฒนาซอฟต์แวร์ Attribution Reporting API

ขณะอ่านเอกสารประกอบเกี่ยวกับ Privacy Sandbox บน Android ให้ใช้ปุ่มDeveloper Preview หรือเบต้าเพื่อเลือก เวอร์ชันโปรแกรมที่คุณกำลังใช้งาน เนื่องจากวิธีการอาจแตกต่างกัน


Attribution Reporting API ได้รับการออกแบบมาเพื่อปรับปรุงความเป็นส่วนตัวของผู้ใช้โดย ยกเลิกการพึ่งพาตัวระบุผู้ใช้ข้ามฝ่ายต่างๆ รวมถึงเพื่อรองรับ Use Case ที่สำคัญๆ สำหรับการวัดการระบุแหล่งที่มาและการวัด Conversion ในแอป คู่มือสำหรับนักพัฒนาซอฟต์แวร์นี้ อธิบายวิธีกำหนดค่าและทดสอบ Attribution Reporting API เพื่อลงทะเบียน การคลิกโฆษณา การดู และ Conversion โดยการเรียกใช้เมธอดที่ลงทะเบียนทริกเกอร์และแหล่งที่มาที่เกี่ยวข้อง สำหรับเหตุการณ์ดังกล่าว

คู่มือนี้จะสอนวิธีตั้งค่าปลายทางของเซิร์ฟเวอร์และสร้างแอปไคลเอ็นต์ ที่เรียกใช้บริการเหล่านี้ ดูข้อมูลเพิ่มเติมเกี่ยวกับการออกแบบโดยรวมของ Attribution Reporting API ได้ในข้อเสนอการออกแบบ

คีย์เวิร์ด

  • แหล่งที่มาของการระบุแหล่งที่มาหมายถึงการคลิกหรือการดู
  • ทริกเกอร์คือเหตุการณ์ที่ระบุแหล่งที่มาของ Conversion ได้
  • รายงานมีข้อมูลเกี่ยวกับทริกเกอร์และแหล่งที่มาของการระบุแหล่งที่มาที่เกี่ยวข้อง ระบบจะส่งรายงานเหล่านี้เพื่อตอบสนองต่อเหตุการณ์ทริกเกอร์ Attribution Reporting API รองรับรายงานระดับเหตุการณ์และ รายงานที่รวบรวมได้

ก่อนเริ่มต้น

หากต้องการใช้ Attribution Reporting API ให้ทําภารกิจฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ ที่ระบุไว้ในส่วนต่อไปนี้ให้เสร็จสมบูรณ์

ตั้งค่าปลายทางของ Attribution Reporting API

Attribution Reporting API ต้องมีชุดอุปกรณ์ปลายทางที่คุณเข้าถึงได้ จากอุปกรณ์ทดสอบหรือโปรแกรมจำลอง สร้างปลายทาง 1 รายการสำหรับงานฝั่งเซิร์ฟเวอร์ต่อไปนี้แต่ละรายการ

การตั้งค่าปลายทางที่จำเป็นทำได้หลายวิธี ดังนี้

  • วิธีที่เร็วที่สุดในการเริ่มต้นใช้งานคือการติดตั้งใช้งานคำจำกัดความของบริการ OpenAPI v3 จากที่เก็บโค้ดตัวอย่างของเราไปยังแพลตฟอร์มจำลองหรือแพลตฟอร์มไมโครเซอร์วิส คุณใช้ Postman, Prism หรือแพลตฟอร์มเซิร์ฟเวอร์จำลองอื่นๆ ที่ยอมรับรูปแบบนี้ได้ ติดตั้งใช้งานแต่ละอุปกรณ์ปลายทางและติดตาม URI เพื่อใช้ในแอป หากต้องการยืนยันการนำส่งรายงาน ให้ดูการเรียก ที่ทำก่อนหน้านี้ไปยังแพลตฟอร์มจำลองหรือแบบไร้เซิร์ฟเวอร์
  • เรียกใช้เซิร์ฟเวอร์แบบสแตนด์อโลนของคุณเองโดยใช้ตัวอย่าง Kotlin ที่อิงตาม Spring Boot ติดตั้งใช้งานเซิร์ฟเวอร์นี้ในผู้ให้บริการระบบคลาวด์หรือโครงสร้างพื้นฐานภายใน
  • ใช้คำจำกัดความของบริการเป็นตัวอย่างในการผสานรวมปลายทางเข้ากับระบบที่มีอยู่

ยอมรับการลงทะเบียนแหล่งที่มา

ปลายทางนี้ควรเข้าถึงได้จาก 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.

ยอมรับการลงทะเบียนทริกเกอร์ Conversion

ปลายทางนี้ควรเข้าถึงได้จาก 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't 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't 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't 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 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"],
    }]
  }],
  "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 ได้ที่ลงทะเบียนบัญชี Privacy Sandbox (ระบบจะอนุมาน 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 ได้ที่ลงทะเบียนบัญชี Privacy Sandbox (ระบบจะอนุมาน 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 doesn't yet encrypt aggregate reports.
  // 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. ตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์สำหรับ Privacy Sandbox ใน Android
  2. ติดตั้งอิมเมจระบบลงในอุปกรณ์ที่รองรับหรือ ตั้งค่าโปรแกรมจำลองที่รองรับ Privacy Sandbox ใน Android
  3. เปิดใช้สิทธิ์เข้าถึง Attribution Reporting API โดยเรียกใช้คำสั่ง ADB ต่อไปนี้ (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 Manifest และสร้างการกำหนดค่าบริการโฆษณาสำหรับแอปเพื่อใช้ Attribution Reporting API โดยทำดังนี้

    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
    
  6. (ไม่บังคับ) หากวางแผนที่จะรับรายงานการแก้ไขข้อบกพร่อง ให้รวมสิทธิ์ ACCESS_ADSERVICES_AD_ID ไว้ในไฟล์ Android Manifest

    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />
    
  7. อ้างอิงการกำหนดค่าบริการโฆษณาในองค์ประกอบ <application> ของ ไฟล์ Manifest

    <property android:name="android.adservices.AD_SERVICES_CONFIG"
              android:resource="@xml/ad_services_config" />
    
  8. ระบุทรัพยากร XML ของบริการโฆษณาที่อ้างอิงในไฟล์ Manifest เช่น res/xml/ad_services_config.xml ดูข้อมูลเพิ่มเติมเกี่ยวกับ สิทธิ์ของบริการโฆษณาและการควบคุมการเข้าถึง SDK

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

ลงทะเบียนเหตุการณ์โฆษณา

แอปของคุณควรลงทะเบียนแหล่งที่มาและ Conversion เมื่อเกิดขึ้นเพื่อยืนยัน ว่ามีการรายงานอย่างถูกต้อง คลาส MeasurementManager มีเมธอด ที่จะช่วยให้คุณลงทะเบียนเหตุการณ์แหล่งที่มาของการระบุแหล่งที่มาและ ทริกเกอร์ Conversion

ลงทะเบียนเหตุการณ์แหล่งที่มาของการระบุแหล่งที่มา

เมื่อมีการดูหรือคลิกโฆษณา แอปของผู้เผยแพร่โฆษณาจะเรียกใช้ 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);

หลังจากลงทะเบียนแล้ว API จะส่งคำขอ HTTP POST ไปยังปลายทางบริการ ที่อยู่ที่ระบุโดย attributionSourceUri การตอบกลับของ ปลายทางมีค่าสำหรับ destination, source_event_id, expiry และ source_priority

หากเทคโนโลยีโฆษณาต้นทางต้องการแชร์การลงทะเบียนแหล่งที่มา URI แหล่งที่มาของการระบุแหล่งที่มาเดิม สามารถรวมการเปลี่ยนเส้นทางไปยังปลายทางเทคโนโลยีโฆษณาอื่นๆ ได้ โปรดดูรายละเอียดขีดจำกัดและกฎที่ใช้กับการเปลี่ยนเส้นทางได้ในข้อเสนอทางเทคนิค

เพิ่มการรองรับการเปลี่ยนเส้นทางแบบเดซี่เชนสำหรับ registerSource และ registerTrigger นอกเหนือจากส่วนหัวการลงทะเบียนแล้ว ผู้ใช้ API ยังสามารถ ระบุการเปลี่ยนเส้นทาง HTTP เป็นการตอบกลับของเซิร์ฟเวอร์ซึ่งมีรหัสสถานะ 302 และส่วนหัว "Location" พร้อม URL ถัดไปที่จะเข้าชมเพื่อลงทะเบียนเพิ่มเติมได้ด้วย

ระบบจะใช้เฉพาะช่อง "ปลายทาง" ที่ระบุในการเข้าชมครั้งแรกสุด ในเชนการเปลี่ยนเส้นทาง จำนวนการเข้าชมมีขีดจำกัดเดียวกับส่วนหัว "Attribution-Reporting-Redirect" การรองรับการเปลี่ยนเส้นทางนี้เป็นการรองรับเพิ่มเติม จากการรองรับ "Attribution-Reporting-Redirect" ที่มีอยู่ และหากมีทั้ง 2 รายการ "Attribution-Reporting-Redirect" จะได้รับค่ากำหนด

ลงทะเบียนเหตุการณ์ทริกเกอร์ Conversion

หากต้องการลงทะเบียนเหตุการณ์ทริกเกอร์ Conversion ให้เรียกใช้ 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)

หลังจากลงทะเบียนแล้ว API จะส่งคำขอ HTTP POST ไปยังปลายทางบริการ ที่อยู่ที่ระบุโดย attributionTriggerUri การตอบกลับของปลายทางมีค่าสําหรับรายงานเหตุการณ์และรายงานรวม

หากแพลตฟอร์มเทคโนโลยีโฆษณาต้นทางอนุญาตให้แชร์การลงทะเบียนทริกเกอร์ URI จะมีการเปลี่ยนเส้นทางไปยัง URI ที่เป็นของแพลตฟอร์มเทคโนโลยีโฆษณาอื่นๆ ได้ โปรดดูรายละเอียดขีดจำกัดและกฎที่ใช้กับการเปลี่ยนเส้นทางได้ในข้อเสนอทางเทคนิค

ลงทะเบียนการวัดผลข้ามแอปและเว็บ

ในกรณีที่ทั้งแอปและเบราว์เซอร์มีส่วนร่วมในเส้นทางของผู้ใช้ ตั้งแต่แหล่งที่มาจนถึงทริกเกอร์ การลงทะเบียนเหตุการณ์โฆษณามีความแตกต่างเล็กน้อย ในการติดตั้งใช้งาน หากผู้ใช้เห็นโฆษณาในแอปและระบบ เปลี่ยนเส้นทางไปยังเบราว์เซอร์เพื่อทํา Conversion แอปจะลงทะเบียนแหล่งที่มา และเว็บเบราว์เซอร์จะลงทะเบียน Conversion ในทํานองเดียวกัน หากผู้ใช้เริ่มต้นในเว็บ เบราว์เซอร์และถูกนําไปยังแอปเพื่อทํา Conversion เบราว์เซอร์จะลงทะเบียนแหล่งที่มา และแอปจะลงทะเบียน Conversion

เนื่องจากเทคโนโลยีโฆษณาบนเว็บและใน Android มีการจัดระเบียบที่แตกต่างกัน เราจึงได้เพิ่ม API ใหม่เพื่อลงทะเบียนแหล่งที่มาและทริกเกอร์เมื่อเกิดขึ้นในเบราว์เซอร์ ความแตกต่างที่สำคัญระหว่าง API เหล่านี้กับ API ที่อิงตามแอปที่เกี่ยวข้องคือ เราคาดหวังให้เบราว์เซอร์ทำตามการเปลี่ยนเส้นทาง ใช้ตัวกรองเฉพาะเบราว์เซอร์ และส่งต่อการลงทะเบียนที่ถูกต้องไปยังแพลตฟอร์มโดยการเรียกใช้ registerWebSource() หรือ registerWebTrigger()

ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างการเรียก API ที่เบราว์เซอร์ ทําเพื่อลงทะเบียนแหล่งที่มาของการระบุแหล่งที่มาก่อนนําผู้ใช้ไปยังแอป

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

ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างการเรียก API ที่เบราว์เซอร์ ทําเพื่อลงทะเบียน Conversion หลังจากที่ระบบนําผู้ใช้จากแอปไปแล้ว

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

การเพิ่มสัญญาณรบกวนเพื่อความเป็นส่วนตัว

รายงานระดับเหตุการณ์มีข้อมูลปลายทาง รหัสแหล่งที่มาของการระบุแหล่งที่มา และทริกเกอร์ โดยจะส่งในรูปแบบเดิม (ไม่ได้เข้ารหัส) ไปยังแหล่งที่มารายงาน เพื่อปกป้องความเป็นส่วนตัวของผู้ใช้ คุณสามารถเพิ่มสัญญาณรบกวนเพื่อให้ระบุตัวตนของผู้ใช้แต่ละรายได้ยากขึ้น ระบบจะสร้างและส่งรายงานระดับเหตุการณ์ที่มีการเพิ่ม Noise ตามกรอบความเป็นส่วนตัวเชิงแตกต่าง ค่าเปอร์เซ็นต์สัญญาณรบกวนเริ่มต้นสำหรับสถานการณ์ต่างๆ มีดังนี้

ประเภทแหล่งข้อมูล

มูลค่าแหล่งที่มาของปลายทาง

ความน่าจะเป็นของรายงานที่มีการเพิ่มสัญญาณรบกวนต่อการลงทะเบียนแหล่งที่มา

ดู

ทั้งแอปและเว็บ

0.0000025

ดู

แอปและเว็บ

0.0000042

คลิก

ทั้งแอปและเว็บ

0.0024263

คลิก

แอปและเว็บ

0.0170218

ในการวัดการระบุแหล่งที่มาของแอปไปยังเว็บ ซึ่งแหล่งที่มาสามารถกระตุ้น Conversion ไปยังปลายทางทั้งในแอปและเว็บ รายงานระดับเหตุการณ์จะระบุได้ว่าทริกเกอร์เกิดขึ้นในแอปหรือเว็บ เพื่อชดเชยรายละเอียดเพิ่มเติมนี้ รายงานที่สร้างขึ้นซึ่งมีการเพิ่มสัญญาณรบกวนจะเพิ่มขึ้นสูงสุดประมาณ 7 เท่าสำหรับการคลิก และประมาณ 1.7 เท่าสำหรับการดู

เทคโนโลยีโฆษณาบางอย่างไม่จำเป็นต้องใช้รายงานระดับเหตุการณ์เพื่อระบุว่าทริกเกอร์ เกิดขึ้นในแอปหรือปลายทางบนเว็บ เทคโนโลยีโฆษณาสามารถใช้ฟิลด์ coarse_event_report_destinations ภายใต้ส่วนหัว Attribution-Reporting-Register-Source เพื่อลดสัญญาณรบกวนได้ หากแหล่งที่มาที่มีการระบุฟิลด์ coarse_event_report_destinations ชนะการระบุแหล่งที่มา รายงานที่ได้จะรวมทั้งปลายทางของแอปและเว็บโดยไม่แยกความแตกต่างว่าทริกเกอร์จริงเกิดขึ้นที่ใด

ในตัวอย่างต่อไปนี้ ผู้ใช้คลิกโฆษณาและระบบจะลงทะเบียนแหล่งที่มานั้น ด้วย API จากนั้นผู้ใช้จะทำ Conversion ทั้งในแอปของผู้ลงโฆษณาและเว็บไซต์ของผู้ลงโฆษณา Conversion ทั้ง 2 รายการนี้จะได้รับการลงทะเบียนเป็นทริกเกอร์และ ระบุแหล่งที่มาเป็นการคลิกเริ่มต้น

ส่วนหัว 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"
    }],
}

ระบบจะสร้างรายงานระดับเหตุการณ์ที่ได้ สมมติว่าทริกเกอร์ทั้ง 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

บังคับส่งรายงาน

แม้ว่าระบบจะบังคับให้งานการรายงานทำงาน แต่ระบบจะยังคงส่งรายงานตามเวลาที่กำหนดไว้ ซึ่งอาจใช้เวลาตั้งแต่ 2-3 ชั่วโมงไปจนถึงหลายวัน คุณสามารถเลื่อนเวลาของระบบอุปกรณ์ให้เป็นหลังจากเวลาที่ล่าช้าตามกำหนดเพื่อเริ่มการนำส่งรายงานได้เพื่อวัตถุประสงค์ในการทดสอบ

ยืนยันรายงานในเซิร์ฟเวอร์

เมื่อส่งรายงานแล้ว ให้ยืนยันการนำส่งโดยตรวจสอบรายงานที่ได้รับ บันทึกเซิร์ฟเวอร์ที่เกี่ยวข้อง เช่น ประวัติเซิร์ฟเวอร์จำลองหรือระบบที่กำหนดเอง

ถอดรหัสรายงานรวม

เมื่อได้รับรายงานรวม ฟิลด์ debug_cleartext_payload จะมีรายงานรวมเวอร์ชันที่ไม่ได้เข้ารหัส แม้ว่ารายงานเวอร์ชันนี้จะไม่ได้เข้ารหัส แต่ก็ยังต้องถอดรหัส

ต่อไปนี้คือตัวอย่างการถอดรหัสเนื้อหาของฟิลด์ debug_cleartext_payload ใน 2 ขั้นตอน ขั้นตอนแรกใช้การถอดรหัส Base64 และขั้นตอนที่สองใช้การถอดรหัส 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 ซึ่งสามารถนําไปใช้กับแพลตฟอร์มจำลองหรือแพลตฟอร์ม Microservice ที่รองรับได้
  • MeasurementAdTechServer มีการติดตั้งใช้งานอ้างอิงของเซิร์ฟเวอร์จำลอง ที่อิงตามแอป Spring Boot สำหรับ Google App Engine

ข้อกำหนดเบื้องต้น

ติดตั้งใช้งาน API จำลองในปลายทางระยะไกลที่เข้าถึงได้จากอุปกรณ์ทดสอบหรือ โปรแกรมจำลอง โปรดดูโปรเจ็กต์ตัวอย่าง MeasurementAdTechServerSpec และ MeasurementAdTechServer เพื่อให้ทดสอบได้ง่าย

ฟังก์ชันการทำงานที่จะทดสอบ

  • ใช้แหล่งที่มาของการระบุแหล่งที่มาและการลงทะเบียนทริกเกอร์ Conversion ตรวจสอบว่า ปลายทางฝั่งเซิร์ฟเวอร์ตอบกลับด้วยรูปแบบที่ถูกต้อง
  • เรียกใช้งานการรายงาน
  • ยืนยันการนำส่งรายงานในแบ็กเอนด์หรือคอนโซลของเซิร์ฟเวอร์ทดสอบ

ฟีเจอร์ที่กำลังจะเปิดตัว

การกำหนดค่าที่ยืดหยุ่นในระดับเหตุการณ์

เราขอแนะนำให้ใช้การกำหนดค่าเริ่มต้นสำหรับการรายงานระดับเหตุการณ์เพื่อเริ่มต้นการทดสอบยูทิลิตี แต่อาจไม่เหมาะกับ Use Case บางอย่าง Attribution Reporting API จะรองรับการกำหนดค่าที่ยืดหยุ่นมากขึ้นและไม่บังคับ เพื่อให้เทคโนโลยีโฆษณาสามารถควบคุมโครงสร้างของรายงานระดับเหตุการณ์ได้มากขึ้นและเพิ่มประโยชน์ของข้อมูลได้สูงสุด ความยืดหยุ่นเพิ่มเติมนี้จะ นำมาใช้ใน Attribution Reporting API ใน 2 ระยะ ดังนี้

  • เฟส 1: การกำหนดค่าระดับเหตุการณ์แบบยืดหยุ่น Lite ซึ่งเป็นส่วนย่อยของเฟส 2
  • ระยะที่ 2: การกำหนดค่าระดับเหตุการณ์แบบยืดหยุ่นเวอร์ชันเต็ม

ระยะที่ 1: ระดับเหตุการณ์แบบยืดหยุ่น Lite

เราจะเพิ่มพารามิเตอร์ที่ไม่บังคับ 2 รายการต่อไปนี้ลงใน 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 makes sure 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) โปรดทราบว่าระบบอาจยังคงจับคู่ทริกเกอร์กับแหล่งที่มาสำหรับรายงานที่รวบรวมได้แม้ว่าทริกเกอร์จะไม่ผ่านเกณฑ์การจับคู่ 2 รายการที่กล่าวถึงก่อนหน้านี้ก็ตาม
  • อัลกอริทึมเฉพาะสำหรับการสรุปและจัดกลุ่มทริกเกอร์ทั้งหมดภายใน กรอบเวลาการระบุแหล่งที่มา ซึ่งจะช่วยให้ทริกเกอร์ระบุvalueพารามิเตอร์ ที่รวมกันสำหรับข้อมูลจำเพาะหนึ่งๆ แต่รายงานเป็นค่าที่จัดกลุ่ม

ทริกเกอร์จะรองรับการเพิ่มพารามิเตอร์ค่าที่ไม่บังคับใน พจนานุกรมภายใน event_trigger_data ด้วย

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

การลงทะเบียนทริกเกอร์ทุกรายการจะจับคู่กับข้อกำหนดทริกเกอร์อย่างน้อย 1 รายการและอัปเดต ค่าสรุปที่เชื่อมโยง ในระดับสูง เมื่อถึงเวลาทริกเกอร์ เราจะดำเนินการต่อไปนี้

  • ใช้ตัวกรองการระบุแหล่งที่มาระดับโลก
  • สำหรับข้อกำหนดทริกเกอร์ทุกรายการ ให้ประเมิน event_trigger_data ในข้อกำหนดเพื่อค้นหารายการที่ตรงกันโดยใช้ event_reporting_window ของข้อกำหนด ระดับบนสุด event_reporting_windows จะทำหน้าที่เป็นค่าเริ่มต้นในกรณีที่ข้อกำหนดทริกเกอร์มีฟิลด์ย่อยevent_report_windowsที่ขาดหายไป
  • ระบบจะเลือกข้อมูลจำเพาะที่ตรงกันรายการแรกสำหรับการระบุแหล่งที่มา และจะเพิ่มค่าสรุปขึ้น value

เมื่อevent_report_windowสำหรับข้อกำหนดเสร็จสมบูรณ์แล้ว เราจะแมปค่าสรุป กับที่เก็บข้อมูล และส่งรายงานระดับเหตุการณ์สำหรับการเพิ่มขึ้นทุกครั้งในที่เก็บข้อมูลสรุป ที่เกิดจากค่าทริกเกอร์ที่มา รายงานจะมีฟิลด์เพิ่มเติม 1 รายการคือ trigger_summary_bucket

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

การกำหนดค่าที่เทียบเท่ากับเวอร์ชันปัจจุบัน

การกำหนดค่าต่อไปนี้เทียบเท่ากับการกำหนดค่าสำหรับเหตุการณ์ปัจจุบันของ API และแหล่งที่มาของการนําทางตามลําดับ โดยเฉพาะอย่างยิ่งสำหรับแหล่งที่มาของการนําทาง สิ่งนี้จะแสดงให้เห็นว่าเหตุใดระดับสัญญาณรบกวนจึงสูงมากเมื่อเทียบกับแหล่งที่มาของเหตุการณ์เพื่อรักษาค่าเอปซิลอนเดียวกันไว้ เนื่องจากแหล่งที่มาของการนําทางมีพื้นที่เอาต์พุตที่ใหญ่กว่ามาก

การกำหนดค่าหลายรายการอาจเทียบเท่ากันได้ เนื่องจากพารามิเตอร์บางรายการสามารถตั้งค่าเป็นค่าเริ่มต้นหรือตัดออกได้

แหล่งที่มาของเหตุการณ์ที่เทียบเท่า
// 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>,
}

ตัวอย่างการกำหนดค่าที่กำหนดเอง

ต่อไปนี้คือการกำหนดค่าเพิ่มเติมบางอย่างที่อยู่นอกเหนือค่าเริ่มต้น ในตัวอย่างทั้งหมดนี้ การแลกเปลี่ยนของนักพัฒนาแอป ได้แก่

  • ลดมิติข้อมูลบางอย่างของการกำหนดค่าเริ่มต้น (#ทริกเกอร์, ข้อมูลทริกเกอร์ Cardinality, #หน้าต่าง) เพื่อเพิ่มอีกมิติข้อมูลหนึ่งเพื่อรักษาระดับสัญญาณรบกวน
  • ลดมิติข้อมูลบางอย่างของการกำหนดค่าเริ่มต้น (#ทริกเกอร์, ข้อมูลทริกเกอร์ คาร์ดินาลิตี, #หน้าต่าง) เพื่อลดระดับสัญญาณรบกวน

รายงานกลุ่มมูลค่าทริกเกอร์

การกำหนดค่าตัวอย่างนี้รองรับนักพัฒนาแอปที่ต้องการเพิ่มประสิทธิภาพสำหรับข้อมูลมูลค่า สำหรับกรอบเวลาการรายงานเพียง 1 กรอบ (เช่น 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 ซึ่งจะมีการสรุปและ จัดกลุ่ม เช่น หากมีทริกเกอร์ 3 รายการภายใน 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 วัน + 1 ชั่วโมง

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

ในช่วง 7 วันถัดมา ระบบจะลงทะเบียนทริกเกอร์ต่อไปนี้

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

ค่าจะรวมกันเป็น 8 + 50 + 45 = 103 ซึ่งจะทำให้เกิดรายงานต่อไปนี้ที่ 14 วัน + 1 ชั่วโมง

// 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]
}
ไบนารีที่มีการรายงานบ่อยขึ้น

การกำหนดค่าตัวอย่างนี้รองรับนักพัฒนาซอฟต์แวร์ที่ต้องการทราบว่ามี Conversion อย่างน้อย 1 รายการเกิดขึ้นในช่วง 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
}

เราขอแนะนำให้นักพัฒนาแอปเสนอ Use Case ต่างๆ ที่อาจมีสำหรับการขยาย API นี้ และเราจะอัปเดตคำอธิบายนี้ด้วยการกำหนดค่าตัวอย่างสำหรับ Use Case เหล่านั้น

การระบุแหล่งที่มาข้ามเครือข่ายโดยไม่มีการเปลี่ยนเส้นทาง

เทคโนโลยีโฆษณาควรใช้การเปลี่ยนเส้นทางเพื่อลงทะเบียนทริกเกอร์แหล่งที่มาของการระบุแหล่งที่มาหลายรายการ และเพื่อทำการระบุแหล่งที่มาข้ามเครือข่าย ฟีเจอร์นี้ช่วยรองรับ การระบุแหล่งที่มาแบบข้ามเครือข่ายในกรณีที่การเปลี่ยนเส้นทางไม่สามารถทำได้ในเครือข่ายต่างๆ ดูข้อมูลเพิ่มเติม

เทคโนโลยีโฆษณาสามารถส่งการกำหนดค่าในการตอบกลับการลงทะเบียนทริกเกอร์โดยอิงตาม แหล่งที่มาที่เทคโนโลยีโฆษณาอื่นๆ ลงทะเบียนไว้ซึ่งได้รับการเลือกเพื่อสร้างแหล่งที่มาที่ได้มา จากนั้นระบบจะใช้แหล่งที่มาที่ได้มาเหล่านี้สำหรับการระบุแหล่งที่มา ระบบจะสร้างรายงานรวม หากทริกเกอร์ได้รับการระบุแหล่งที่มาเป็นแหล่งที่มาที่ได้มา ระบบไม่รองรับการสร้างรายงานเหตุการณ์ สำหรับแหล่งที่มาที่ได้มา

เทคโนโลยีโฆษณาสามารถเลือกจาก 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"
    }
  ]

เพิ่มฟิลด์ใหม่ 2 รายการ (ไม่บังคับ) เพื่อทริกเกอร์ส่วนหัวของการลงทะเบียน ฟิลด์เหล่านี้ เปิดใช้ตัวระบุของเทคโนโลยีโฆษณาที่ชนะในคีย์รายงานที่รวบรวมได้

  • x_network_bit_mapping: การแมปรหัสการลงทะเบียนกับบิตตัวระบุเทคโนโลยีโฆษณา
  • x_network_data: ออฟเซ็ต (เลื่อนไปทางซ้าย) สำหรับเทคโนโลยีโฆษณาที่ชนะ x_network_bit_mapping หรือการดำเนินการ OR กับชิ้นส่วนคีย์ทริกเกอร์
ตัวอย่าง
"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 ad tech identifier
   // bits. eg. If Ad Tech-A's sources wins the attribution then 0x1 here will be
   // OR'd with the trigger key pieces to generate the final key piece.
    "Ad-Tech-A-enrollment_id": "0x1", // Identifier bits in hex for A
    "Ad-Tech-B-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 ได้ในบันทึกประจำรุ่น

รายงานข้อบกพร่องและปัญหา

ความคิดเห็นของคุณเป็นส่วนสำคัญของ Privacy Sandbox ใน Android โปรดแจ้งให้เราทราบหากพบปัญหาหรือมีไอเดียในการปรับปรุง Privacy Sandbox ใน Android