คู่มือนักพัฒนาซอฟต์แวร์ 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 จากที่เก็บโค้ดตัวอย่างของเราใช้งานได้ไปยังแพลตฟอร์มจำลองหรือ Microservice คุณสามารถใช้ Postman, Prism หรือแพลตฟอร์มเซิร์ฟเวอร์จำลองอื่นๆ ที่ยอมรับรูปแบบนี้ ทำให้แต่ละปลายทางใช้งานได้และติดตาม URI ที่จะใช้ในแอป หากต้องการยืนยันการส่งรายงาน โปรดดูการเรียกก่อนหน้านี้สำหรับแพลตฟอร์มจำลองหรือแพลตฟอร์มแบบ Serverless
  • เรียกใช้เซิร์ฟเวอร์แบบสแตนด์อโลนของคุณเองโดยใช้ตัวอย่าง Kotlin ที่อิงตาม Spring Boot ทำให้เซิร์ฟเวอร์นี้ใช้งานได้กับผู้ให้บริการระบบคลาวด์หรือโครงสร้างพื้นฐานภายใน
  • ใช้คำจำกัดความของบริการเป็นตัวอย่างในการผสานรวมปลายทางกับระบบที่มีอยู่

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

ปลายทางนี้ควรระบุที่อยู่ได้จาก URI ที่คล้ายกับ URL ต่อไปนี้

https://adtech.example/attribution_source

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

  • สำหรับกิจกรรมการคลิก:

    Attribution-Reporting-Source-Info: navigation
    
  • สำหรับกิจกรรมการดู

    Attribution-Reporting-Source-Info: event
    

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

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

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

ต่อไปนี้คือตัวอย่างที่มีการเพิ่มค่าตัวอย่าง

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

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

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

หาก Attribution-Reporting-Redirects มี URI ของพาร์ทเนอร์เทคโนโลยีโฆษณา จากนั้น Attribution Reporting API จะส่งคำขอที่คล้ายกันกับ URI แต่ละรายการ พาร์ทเนอร์เทคโนโลยีโฆษณาแต่ละรายต้องกำหนดค่าเซิร์ฟเวอร์ที่ตอบสนองด้วยส่วนหัวต่อไปนี้

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

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

ปลายทางนี้ควรระบุที่อยู่ได้จาก URI ที่คล้ายกับ URL ต่อไปนี้

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 (URL สรุปมาจากต้นทางของเซิร์ฟเวอร์ที่ใช้สำหรับการยอมรับการลงทะเบียนแหล่งที่มาและการลงทะเบียนทริกเกอร์) เมื่อใช้ 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 (URL สรุปมาจากต้นทางของเซิร์ฟเวอร์ที่ใช้สำหรับการยอมรับการลงทะเบียนแหล่งที่มาและการลงทะเบียนทริกเกอร์) เมื่อใช้ 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 ในไฟล์ Manifest ของ Android และสร้างการกำหนดค่าบริการโฆษณาเพื่อให้แอปใช้ 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 แหล่งที่มาของการระบุแหล่งที่มาเดิมอาจรวมการเปลี่ยนเส้นทางไปยังปลายทางเทคโนโลยีโฆษณาอื่นๆ ด้วย ดูรายละเอียดข้อจำกัดและกฎที่เกี่ยวข้องกับการเปลี่ยนเส้นทางได้ในข้อเสนอทางเทคนิค

เพิ่มการรองรับการเปลี่ยนเส้นทางเชนสำหรับ registerSource และ registerTrigger นอกเหนือจากส่วนหัวการลงทะเบียนแล้ว ตอนนี้ผู้บริโภค API สามารถระบุการเปลี่ยนเส้นทาง HTTP เป็นการตอบสนองของเซิร์ฟเวอร์ที่มีรหัสสถานะ 302 และส่วนหัว "ตำแหน่ง" พร้อม 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);

การเพิ่มเสียงเพื่อความเป็นส่วนตัว

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

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

ค่าปลายทางต้นทาง

ความน่าจะเป็นของรายงานที่มีโหนดต่อการลงทะเบียนแหล่งที่มา

ดู

แอปหรือเว็บไซต์

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 ซึ่งสามารถใช้งานได้กับแพลตฟอร์มจำลองหรือ 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 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>,
}

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

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

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

ที่เก็บข้อมูลค่าของทริกเกอร์รายงาน

การกำหนดค่าตัวอย่างนี้รองรับนักพัฒนาซอฟต์แวร์ที่ต้องการเพิ่มประสิทธิภาพข้อมูลมูลค่าสำหรับกรอบเวลาการรายงานเพียง 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
}

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

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

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

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

เทคโนโลยีโฆษณาสามารถเลือกจาก 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: ออฟเซ็ต (Shift ซ้าย) สำหรับเทคโนโลยีโฆษณาที่ชนะการประมูล 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