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

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


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 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 ที่หัวข้อลงทะเบียนบัญชี 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 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. ตั้งค่าสภาพแวดล้อมการพัฒนาสําหรับ 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 ไว้ในไฟล์ Manifest ของ Android

    <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 แหล่งที่มาของการระบุแหล่งที่มาเดิมอาจมีการเปลี่ยนเส้นทางไปยังปลายทางเทคโนโลยีโฆษณาอื่นๆ ขีดจํากัดและกฎที่มีผลกับการเปลี่ยนเส้นทางมีรายละเอียดอยู่ในข้อเสนอทางเทคนิค

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

ระบบจะใช้เฉพาะช่อง "ปลายทาง" ที่ระบุในการเข้าชมครั้งแรกเท่านั้นใน Daisy Chain จํานวนการเข้าชมมีขีดจํากัดเดียวกับส่วนหัว "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);

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

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

ประเภทแหล่งที่มา

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

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

ดู

แอปหรือเว็บ

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 ขั้นตอน โดยขั้นตอนแรกใช้การถอดรหัส Base 64 และขั้นตอนที่ 2 ใช้การถอดรหัส 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);
});

การทดสอบ

คุณสามารถใช้โปรเจ็กต์ MeasurementSampleApp ใน GitHub เพื่อช่วยในการเริ่มต้นใช้งาน Attribution Reporting API แอปตัวอย่างนี้แสดงการลงทะเบียนแหล่งที่มาของการระบุแหล่งที่มาและการลงทะเบียนทริกเกอร์

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

  • MeasurementAdTechServerSpec มีคำจำกัดความบริการ OpenAPI ซึ่งสามารถนำไปใช้งานได้ในแพลตฟอร์มจำลองหรือแพลตฟอร์มไมโครเซอร์วิสที่รองรับ
  • 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 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) โปรดทราบว่าทริกเกอร์อาจยังคงจับคู่กับแหล่งที่มาของรายงานที่รวบรวมได้แม้ว่าจะไม่ตรงกับเกณฑ์การจับคู่ 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 ตามลําดับ โดยเฉพาะอย่างยิ่งสําหรับแหล่งที่มาของการนําทาง ข้อมูลนี้แสดงให้เห็นว่าเหตุใดระดับสัญญาณรบกวนจึงสูงมากเมื่อเทียบกับแหล่งที่มาของเหตุการณ์เพื่อรักษาค่า epsilon เดียวกัน นั่นคือแหล่งที่มาของการนําทางมีพื้นที่เอาต์พุตขนาดใหญ่กว่ามาก

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

แหล่งที่มาของเหตุการณ์ที่เทียบเท่า
// 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" "จำนวนกรอบเวลา") เพื่อเพิ่มอีกมิติข้อมูลหนึ่งเพื่อรักษาระดับสัญญาณรบกวน
  • การลดมิติข้อมูลบางอย่างของการกําหนดค่าเริ่มต้น ("#triggers", "trigger data", "cardinality", "#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 ซึ่งจะรวมและจัดกลุ่ม เช่น หากมีการทริกเกอร์ 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 จะไม่มีสิทธิ์ได้รับการระบุแหล่งที่มา ด้วยเหตุนี้ กรณีการใช้งานนี้จึงเรียกว่าแบบ 2 ค่า

{
  "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: ระยะห่าง (การเลื่อนไปทางซ้าย) ของการดำเนินการ OR ของเทคโนโลยีโฆษณาที่ชนะ 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 ได้ที่บันทึกประจำรุ่น

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

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