همانطور که در اسناد Android Sandbox Privacy می خوانید، از دکمه Developer Preview یا Beta برای انتخاب نسخه برنامه ای که با آن کار می کنید استفاده کنید، زیرا ممکن است دستورالعمل ها متفاوت باشد.
Attribution Reporting API برای ارائه بهبود حریم خصوصی کاربر با حذف اتکا به شناسههای کاربر بین حزبی و پشتیبانی از موارد استفاده کلیدی برای اندازهگیری اسناد و تبدیل در بین برنامهها طراحی شده است. این راهنمای توسعهدهنده نحوه پیکربندی و آزمایش APIهای گزارش Attribution را برای ثبت کلیکها، بازدیدها و تبدیلهای تبلیغاتی با فراخوانی روشهایی که محرکها و منابع مربوطه را برای چنین رویدادهایی ثبت میکنند، شرح میدهد.
این راهنما به شما می آموزد که چگونه نقاط پایانی سرور را تنظیم کنید و یک برنامه مشتری بسازید که این خدمات را فراخوانی کند. درباره طراحی کلی Attribution Reporting API در طرح پیشنهادی بیشتر بیاموزید.
- منابع انتساب به کلیک ها یا بازدیدها اشاره دارد.
- محرک ها رویدادهایی هستند که می توانند به تبدیل ها نسبت داده شوند.
- گزارشها حاوی دادههایی درباره یک ماشه و منبع انتساب مربوطه هستند. این گزارش ها در پاسخ به رویدادهای محرک ارسال می شوند. Attribution Reporting API از گزارشهای سطح رویداد و گزارشهای جمعآوریشده پشتیبانی میکند.
برای استفاده از Attribution Reporting API، وظایف سمت سرور و سمت سرویس گیرنده فهرست شده در بخشهای زیر را تکمیل کنید.
Attribution Reporting API به مجموعهای از نقاط پایانی نیاز دارد که میتوانید از دستگاه آزمایشی یا شبیهساز به آنها دسترسی داشته باشید. برای هر یک از وظایف سمت سرور زیر یک نقطه پایانی ایجاد کنید:
- ثبت منبع انتساب (مشاهده یا کلیک کنید)
- ثبت یک ماشه (تبدیل)
- گزارش های سطح رویداد را بپذیرید
- گزارش های انبوه را بپذیرید
چندین روش برای تنظیم نقاط پایانی مورد نیاز وجود دارد:
- سریع ترین راه برای راه اندازی و اجرا، استقرار تعاریف سرویس 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 شرکای فناوری تبلیغات باشد، API گزارش Attribution درخواست مشابهی را برای هر URI ارسال می کند. هر شریک فناوری تبلیغاتی باید سروری را پیکربندی کند که با این هدرها پاسخ دهد:
Attribution-Reporting-Register-Source: {
"destination": "[app package name]",
"web_destination": "[eTLD+1]",
"source_event_id": "[64 bit unsigned integer]",
"expiry": "[64 bit signed integer]",
"event_report_window": "[64-bit signed integer]",
"aggregatable_report_window": "[64-bit signed integer]",
"priority": "[64 bit signed integer]",
"filter_data": {
"[key name 1]": ["key1 value 1", "key1 value 2"],
"[key name 2]": ["key2 value 1", "key2 value 2"],
// Note: "source_type" key will be automatically generated as
// one of {"navigation", "event"}.
},
"aggregation_keys": {
"[key1 name]": "[key1 value]",
"[key2 name]": "[key2 value]",
}
}
// The Attribution-Reporting-Redirect header is ignored for ad tech partners.
این نقطه پایانی باید از یک URI مشابه زیر قابل آدرس دهی باشد:
https://adtech.example/attribution_trigger
هنگامی که یک برنامه مشتری یک رویداد ماشه را ثبت می کند ، URI را برای این نقطه پایانی سرور ارائه می دهد. سپس Attribution Reporting API درخواستی می دهد و یکی از سرصفحه های زیر را شامل می شود:
نقطه پایانی سرور خود را پیکربندی کنید تا با موارد زیر پاسخ دهد:
// Metadata associated with trigger.
Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
// "trigger_data returned" in event reports is truncated to
// the last 1 or 3 bits, based on conversion type.
"trigger_data": "[unsigned 64-bit integer]",
"priority": "[signed 64-bit integer]",
"deduplication_key": "[signed 64-bit integer]",
// "filter" and "not_filters" are optional fields which allow configuring
// event trigger data based on source's filter_data. They consist of a
// filter set, which is a list of filter maps. An event_trigger_data object
// is ignored if none of the filter maps in the set match the source's
// filter data.
// Note: "source_type" can be used as a key in a filter map to filter based
// on the source's "navigation" or "event" type. The first
// Event-Trigger that matches (based on the filters/not_filters) will be
// used for report generation. If none of the event-triggers match, no
// event report will be generated.
"filters": [{
"[key name 1]": ["key1 value 1", "key1 value 2"],
// If a key is missing from filters or source's filter_data, it won't be
// used during matching.
"[key name 2]": ["key2 value 1", "key2 value 2"],
}],
"not_filters": [{
"[key name 1]": ["key1 value 1", "key1 value 2"],
// If a key is missing from not_filters or source's filter_data, it won't
// be used during matching.
"[key name 2]": ["key2 value 1", "key2 value 2"],
}]
}],
// Specify a list of dictionaries that generates aggregation keys.
"aggregatable_trigger_data": [
// Each dictionary entry independently adds pieces to multiple source keys.
{
"key_piece": "[key piece value]",
"source_keys": ["[key name the key piece value applies to]",
["list of IDs in source to match. Non-matching IDs are ignored"]]
// filters/not_filters are optional fields similar to event trigger data
// filter fields.
"filters": [{
"[key name 1]": ["key1 value 1", "key1 value 2"]
}],
"not_filters": [{
"[key name 1]": ["key1 value 1", "key1 value 2"],
"[key name 2]": ["key2 value 1", "key2 value 2"],
}]
},
..
],
// Specify an amount of an abstract value which can be integers in [1, 2^16]
// to contribute to each key that is attached to aggregation keys in the
// order they are generated.
"aggregatable_values": [
// Each source event can contribute a maximum of L1 = 2^16 to the
// aggregate histogram.
{
"[key_name]": [value]
},
..
],
aggregatable_deduplication_keys: [{
deduplication_key": [unsigned 64-bit integer],
"filters": {
"category": [filter_1, …, filter_H]
},
"not_filters": {
"category": [filter_1, …, filter_J]
}
},
...
{
"deduplication_key": [unsigned 64-bit integer],
"filters": {
"category": [filter_1, …, filter_D]
},
"not_filters": {
"category": [filter_1, …, filter_J]
}
}
]
"debug_key": "[64-bit unsigned integer]",
"debug_reporting": [boolean]
}
// Specify additional ad tech URLs to register this trigger with.
// Repeated Header field "Attribution-Reporting-Redirect"
Attribution-Reporting-Redirect: <Ad Tech Partner URI 1>
Attribution-Reporting-Redirect: <Ad Tech Partner URI 2>
در اینجا یک مثال با مقادیر نمونه اضافه شده است:
Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
"trigger_data": "1122", // Returns 010 for CTCs and 0 for VTCs in reports.
"priority": "3",
"deduplication_key": "3344"
"filters": [{ // Filter strings can not exceed 25 characters
"product_id": ["1234"],
"source_type": ["event"]
}]
},
{
"trigger_data": "4", // Returns 100 for CTCs and 0 for VTCs in reports.
"priority": "3",
"deduplication_key": "3344"
"filters": [{ // Filter strings can not exceed 25 characters
"product_id": ["1234"],
"source_type": ["navigation"]
}]
}],
"aggregatable_trigger_data": [
// Each dictionary independently adds pieces to multiple source keys.
{
// Conversion type purchase = 2 at a 9-bit offset, i.e. 2 << 9.
// A 9-bit offset is needed because there are 511 possible campaigns,
// which takes up 9 bits in the resulting key.
"key_piece": "0x400",// Conversion type purchase = 2
// Apply this key piece to:
"source_keys": ["campaignCounts"]
// Filter strings can not exceed 25 characters
},
{
// Purchase category shirts = 21 at a 7-bit offset, i.e. 21 << 7.
// A 7-bit offset is needed because there are ~100 regions for the geo
// key, which takes up 7 bits of space in the resulting key.
"key_piece": "0xA80",
// Apply this key piece to:
"source_keys": ["geoValue", "nonMatchingIdsAreIgnored"]
// source_key values must not exceed the limit of 25 characters
}
],
"aggregatable_values":
{
// Privacy budget for each key is L1 / 2 = 2^15 (32768).
// Conversion count was 1.
// Scale the count to use the full budget allocated: 1 * 32768 = 32768.
"campaignCounts": 32768,
// Purchase price was $52.
// Purchase values for the app range from $1 to $1,024 (integers only).
// Scaling factor applied is 32768 / 1024 = 32.
// For $52 purchase, scale the value by 32 ($52 * 32 = $1,664).
"geoValue": 1664
}
,
// aggregatable_deduplication_keys is an optional field. Up to 50 "keys"
// can be included in the aggregatable_deduplication_keys list. Filters, not
// filters, and deduplication_key are optional fields. If deduplication_key
// is omitted, it will be treated as a null value. See
// https://wicg.github.io/attribution-reporting-api/#triggering-aggregatable-attribution
aggregatable_deduplication_keys:
[
{
deduplication_key": 3,
"filters": {
"category": [A]
}
},
{
"deduplication_key": 4,
"filters": {
"category": [C, D]
},
"not_filters": {
"category": [F]
}
}
]
// Opts into receiving verbose debug reports
"debug_reporting": true
}
Attribution-Reporting-Redirect:https://adtechpartner.example?app_install=567
محدودیت 25 بایت برای هر شناسه کلید تجمعی و رشته فیلتر وجود دارد. این بدان معناست که شناسههای کلید تجمعی و رشتههای فیلتر نباید از ۲۵ کاراکتر تجاوز کنند. در این مثال، campaignCounts
14 کاراکتر است، بنابراین یک شناسه کلید تجمعی معتبر است، و 1234
4 کاراکتر است، بنابراین یک رشته فیلتر معتبر است. اگر شناسه کلید تجمیع یا رشته فیلتر بیش از 25 کاراکتر باشد، ماشه نادیده گرفته می شود.
اگر Attribution-Reporting-Redirect
شامل URI شرکای فناوری تبلیغات باشد، API گزارش Attribution درخواست مشابهی را برای هر 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، به ثبت نام برای یک حساب 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، به ثبت نام برای یک حساب 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 برای استفاده از Attribution Reporting API، موارد زیر را انجام دهید:
- محیط توسعه خود را برای Privacy Sandbox در Android تنظیم کنید .
- یک تصویر سیستم را روی یک دستگاه پشتیبانی شده نصب کنید یا یک شبیهساز راهاندازی کنید که شامل پشتیبانی از Privacy Sandbox در Android است.
با اجرای دستور ADB زیر دسترسی به Attribution Reporting API را فعال کنید . (API به طور پیش فرض غیرفعال است.)
adb shell device_config put adservices ppapi_app_allow_list \"\*\"
اگر به صورت محلی API گزارش Attribution را آزمایش می کنید (مانند آزمایش روی دستگاهی که به صورت فیزیکی به آن دسترسی دارید)، این دستور را برای غیرفعال کردن ثبت نام اجرا کنید:
adb shell device_config put adservices disable_measurement_enrollment_check "true"
مجوز
ACCESS_ADSERVICES_ATTRIBUTION
را در فایل Manifest Android خود وارد کنید و یک پیکربندی خدمات تبلیغاتی برای برنامه خود ایجاد کنید تا از APIهای گزارش Attribution استفاده کند:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
(اختیاری) اگر قصد دریافت گزارش های اشکال زدایی را دارید، مجوز
ACCESS_ADSERVICES_AD_ID
را در فایل Manifest Android خود قرار دهید:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />
به پیکربندی سرویس های تبلیغاتی در عنصر
<application>
مانیفست خود ارجاع دهید:<property android:name="android.adservices.AD_SERVICES_CONFIG" android:resource="@xml/ad_services_config" />
منبع XML خدمات تبلیغاتی را که در مانیفست ارجاع داده شده است، مشخص کنید، مانند
res/xml/ad_services_config.xml
. درباره مجوزهای خدمات تبلیغات و کنترل دسترسی SDK بیشتر بیاموزید.<ad-services-config> <attribution allowAllToAccess="true" /> </ad-services-config>
برنامه شما باید منابع و تبدیل ها را در صورت وقوع ثبت کند تا اطمینان حاصل شود که به درستی گزارش شده اند. کلاس MeasurementManager
دارای روش هایی است که به شما کمک می کند رویدادهای منبع اسناد و محرک های تبدیل را ثبت کنید.
هنگامی که یک تبلیغ مشاهده یا کلیک می شود، یک برنامه ناشر registerSource()
برای ثبت منبع انتساب همانطور که در قطعه کد نشان داده شده است فرا می خواند.
Attribution Reporting API از انواع رویدادهای منبع انتساب زیر پشتیبانی می کند:
- کلیکهایی که معمولاً در یک روش پاسخ به تماس مشابه
onClick()
ثبت میکنید. رویداد ماشه مربوطه معمولاً بلافاصله پس از رویداد کلیک رخ می دهد. این نوع رویداد اطلاعات بیشتری در مورد تعامل کاربر ارائه می دهد و بنابراین نوع خوبی از منبع انتساب برای اولویت بالا است. نماهایی که معمولاً آنها را در یک روش بازگشت به تماس مشابه با
onAdShown()
ثبت میکنید. رویداد آغازگر مربوطه ممکن است ساعت ها یا روزها پس از رویداد مشاهده رخ دهد.
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)
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" است و اگر هر دو وجود داشته باشند، "Attribution-Reporting-Redirect" اولویت دارد.
برای ثبت یک رویداد تریگر تبدیل، با registerTrigger()
در برنامه خود تماس بگیرید:
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)
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هایی باشد که متعلق به سایر پلتفرمهای فناوری تبلیغات هستند. محدودیت ها و قوانین قابل اعمال برای تغییر مسیرها در پیشنهاد فنی به تفصیل آمده است.
در موردی که هر دو برنامه و مرورگر در سفر کاربر از منبع به راهانداز نقش دارند ، تفاوتهای ظریفی در اجرای ثبت رویدادهای تبلیغاتی وجود دارد. اگر کاربر تبلیغی را در یک برنامه ببیند و برای تبدیل به یک مرورگر هدایت شود، منبع توسط برنامه و تبدیل توسط مرورگر وب ثبت می شود. به طور مشابه، اگر کاربر از یک مرورگر وب شروع به کار کند و برای تبدیل به برنامه ای هدایت شود، مرورگر منبع را ثبت می کند و برنامه تبدیل را ثبت می کند.
از آنجایی که تفاوتهایی در نحوه سازماندهی فناوریهای تبلیغاتی در وب و اندروید وجود دارد، ما APIهای جدیدی را برای ثبت منابع و محرکها در مرورگرها اضافه کردهایم. تفاوت اصلی بین این APIها و APIهای مبتنی بر برنامه مربوطه در این است که ما از مرورگر انتظار داریم ریدایرکت ها را دنبال کند، فیلترهای خاص مرورگر را اعمال کند و با فراخوانی registerWebSource()
یا registerWebTrigger()
ثبت نام های معتبر را به پلتفرم منتقل کند.
قطعه کد زیر نمونهای از فراخوانی API را نشان میدهد که مرورگر قبل از هدایت کاربر به یک برنامه برای ثبت منبع انتساب انجام میدهد:
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)
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 را نشان می دهد که مرورگر برای ثبت تبدیل پس از هدایت کاربر از برنامه انجام می دهد:
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)
private static final Executor CALLBACK_EXECUTOR =
Executors.newCachedThreadPool();
MeasurementManager measurementManager =
context.getSystemService(MeasurementManager.class);
// Use the URIs of the server-side endpoints that accept trigger registration.
WebTriggerParams triggerParam1 = WebTriggerParams.Builder(Uri.parse(
"https://adtech1.example/trigger?AD_TECH_PROVIDED_METADATA"))
// True, if debugging is allowed for the ad tech.
.setDebugKeyAllowed(true)
.build();
WebTriggerParams triggerParam2 = WebTriggerParams.Builder(Uri.parse(
"https://adtech2.example/trigger?AD_TECH_PROVIDED_METADATA"))
.setDebugKeyAllowed(false)
.build();
List<WebTriggerParams> triggerParams =
Arrays.asList(triggerParam1, triggerParam2);
Uri advertiserOrigin = Uri.parse("https://advertiser.example");
CompletableFuture<Void> future = new CompletableFuture<>();
WebTriggerRegistrationRequest triggerRegistrationRequest =
new WebTriggerRegistrationRequest.Builder(
triggerParams, advertiserOrigin)
.build();
// Register the web trigger (conversion).
measurementManager.registerWebTrigger( triggerRegistrationRequest,
CALLBACK_EXECUTOR, future::complete);
گزارشهای سطح رویداد حاوی مقصد، شناسه منبع انتساب و دادههای راهانداز است. آنها در قالب اصلی (غیر رمزگذاری نشده) به منبع گزارش ارسال می شوند. برای محافظت از حریم خصوصی کاربر، می توان نویز اضافه کرد تا شناسایی یک کاربر را دشوارتر کند. گزارشهای نویز در سطح رویداد مطابق با چارچوب تفاوت حریم خصوصی تولید و ارسال میشوند. این مقادیر درصد نویز پیش فرض برای سناریوهای مختلف است:
نوع منبع | مقدار مقصد منبع | احتمال گزارش نویز در هر ثبت منبع |
چشم انداز | یا برنامه یا وب | 0.0000025 |
چشم انداز | اپلیکیشن و وب | 0.0000042 |
کلیک | یا برنامه یا وب | 0.0024263 |
کلیک | اپلیکیشن و وب | 0.0170218 |
در اندازهگیری اسناد برنامه به وب، که در آن منابع میتوانند تبدیل به مقصد برنامه و وب را ایجاد کنند، گزارشهای سطح رویداد میتوانند مشخص کنند که آغازگر در برنامه یا وب رخ داده است. برای جبران این جزئیات بیشتر، گزارشهای نویز تولید شده تا 7 برابر برای کلیک و ~ 1.7 برابر برای بازدید هستند.
برخی از فناوریهای تبلیغاتی برای مشخص کردن اینکه راهانداز در مقصد برنامه یا وب رخ داده است، به گزارشهای سطح رویداد نیاز ندارند. فنآوران تبلیغات میتوانند از قسمت coarse_event_report_destinations
در زیر عنوان Attribution-Reporting-Register-Source
برای کاهش نویز استفاده کنند. اگر منبعی با فیلد coarse_event_report_destinations
مشخص شده برنده انتساب شود، گزارش حاصله شامل هر دو مقصد برنامه و وب بدون تمایز در مورد محل وقوع واقعی است.
در مثالهای زیر، کاربر روی یک تبلیغ کلیک میکند و آن منبع در API ثبت میشود. سپس کاربر هم در برنامه تبلیغ کننده و هم در وب سایت تبلیغ کننده تبدیل می کند. هر دوی این تبدیل ها به عنوان محرک ثبت می شوند و به کلیک اولیه نسبت داده می شوند.
هدر HTTP ثبت منبع مبتنی بر کلیک:
Attribution-Reporting-Register-Source: {
"destination": "android-app://com.advertiser.example",
"web_destination": "https://advertiser.com",
"source_event_id": "234",
"expiry": "60000",
"priority": "5",
// Ad tech opts out of receiving app-web destination distinction
// in event report, avoids additional noise
"coarse_event_report_destinations": "true"
}
یک ماشه از برنامه با نام بسته com.advertiser.example
ثبت شده است:
Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
"trigger_data": "1",
"priority": "1"
}],
}
یک ماشه از یک مرورگر از وب سایت با دامنه eTLD+1 https://advertiser.com
ثبت می شود:
Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
"trigger_data": "2",
"priority": "2"
}],
}
گزارشهای سطح رویداد حاصل تولید میشوند. با فرض اینکه هر دو محرک به منبع نسبت داده شوند، گزارشهای سطح رویداد زیر تولید میشوند:
{
"attribution_destination": ["android-app://com.advertiser.example,https://advertiser.com"],
"scheduled_report_time": "800176400",
"source_event_id": "53234",
"trigger_data": "1",
// Can be "event" if source were registered by user viewing the ad
"source_type": "navigation",
// Would be 0.0170218 without coarse_event_report_destinations as true in the source
"randomized_trigger_rate": 0.0024263
}
Attribution Reporting API گزارشهایی را به نقاط پایانی سرور شما ارسال میکند که گزارشهای سطح رویداد و گزارشهای جمعآوریشده را میپذیرند.
پس از ثبت یک رویداد منبع انتساب یا ثبت یک رویداد آغازگر، سیستم کار گزارش را برای اجرا برنامه ریزی می کند. به طور پیش فرض، این کار هر 4 ساعت یکبار اجرا می شود. برای اهداف آزمایشی، میتوانید کارهای گزارشدهی را مجبور به اجرا کنید یا فواصل بین کارها را کوتاه کنید.
اجباری کردن کار انتساب برای اجرا:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 5
اجباری کردن کار گزارشدهی در سطح رویداد:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 3
کار گزارش انبوهی را مجبور به اجرا کنید:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 7
خروجی logcat را بررسی کنید تا ببینید کارها چه زمانی اجرا شده اند. باید چیزی شبیه به زیر باشد:
JobScheduler: executeRunCommand(): com.google.android.adservices.api/0 5 s=false f=true
حتی اگر کار گزارشدهی مجبور به اجرا شود، سیستم همچنان گزارشها را طبق زمانهای تحویل برنامهریزی شده ارسال میکند که از چند ساعت تا چند روز متغیر است. برای اهداف آزمایشی، میتوانید زمان سیستم دستگاه را پس از تأخیرهای برنامهریزیشده برای شروع تحویل گزارش پیش ببرید.
پس از ارسال گزارشها، با بررسی گزارشهای دریافتی، گزارشهای مربوط به سرور مانند تاریخچه سرور ساختگی یا سیستم سفارشی خود، تحویل را تأیید کنید.
هنگام دریافت گزارش انبوه، فیلد debug_cleartext_payload
یک نسخه رمزگذاری نشده از گزارش انبوه شما را نگه می دارد. در حالی که این نسخه از گزارش شما رمزگذاری نشده است، هنوز باید رمزگشایی شود.
در زیر نمونه ای از رمزگشایی محتویات فیلد debug_cleartext_payload
در دو مرحله آورده شده است: اولی با استفاده از رمزگشایی Base 64 و دومی با استفاده از رمزگشایی CBOR.
String base64DebugPayload = "omRkYXRhgqJldmFsdWVEAAAGgGZidWNrZXRQAAAAAAAAAAAAAAAAAAAKhaJldmFsdWVEAACAAGZidWNrZXRQAAAAAAAAAAAAAAAAAAAFWWlvcGVyYXRpb25paGlzdG9ncmFt";
byte[] cborEncoded = Base64.getDecoder().decode(base64DebugPayload);
// CbodDecoder comes from this library https://github.com/c-rack/cbor-java
final List<DataItem> dataItems = new CborDecoder(new ByteArrayInputStream(cborEncoded)).decode();
// In here you can see the contents, but the value will be something like:
// Data items: [{ data: [{ value: co.nstant.in.cbor.model.ByteString@a8b5c07a,
// bucket: co.nstant.in.cbor.model.ByteString@f812097d },
// { value: co.nstant.in.cbor.model.ByteString@a8b5dfc0,
// bucket: co.nstant.in.cbor.model.ByteString@f8120934 }], operation: histogram }]
Log.d("Data items : " + dataItems);
// In order to see the value for bucket and value, you can traverse the data
// and get their values, something like this:
final Map payload = (Map) dataItems.get(0);
final Array payloadArray = (Array) payload.get(new UnicodeString("data"));
payloadArray.getDataItems().forEach(i -> {
BigInteger value = new BigInteger(((ByteString) ((Map)i).get(new UnicodeString("value"))).getBytes());
BigInteger bucket = new BigInteger(((ByteString) ((Map)i).get(new UnicodeString("bucket"))).getBytes());
Log.d("value : " + value + " ;bucket : " + bucket);
});
برای کمک به شما در شروع کار با Attribution Reporting API، میتوانید از پروژه MeasurementSampleApp در GitHub استفاده کنید. این برنامه نمونه ثبت منبع منبع و ثبت راهانداز را نشان میدهد.
برای نقاط پایانی سرور، منابع مرجع زیر یا راه حل سفارشی خود را در نظر بگیرید:
- MeasurementAdTechServerSpec شامل تعاریف سرویس OpenAPI است که می تواند در پلتفرم های ساختگی یا میکروسرویس پشتیبانی شده مستقر شود.
- MeasurementAdTechServer شامل اجرای مرجع یک سرور ساختگی بر اساس برنامه Spring Boot برای Google App Engine است.
APIهای ساختگی را در نقاط پایانی راه دور قابل دسترسی از دستگاه آزمایشی یا شبیه ساز خود مستقر کنید. برای سهولت تست، به پروژه های نمونه MeasurementAdTechServerSpec و MeasurementAdTechServer مراجعه کنید. پیکربندی پیشفرض برای گزارش سطح رویداد برای شروع آزمایش ابزار توصیه میشود، اما ممکن است برای همه موارد استفاده ایدهآل نباشد. Attribution Reporting API از پیکربندیهای اختیاری و انعطافپذیرتر پشتیبانی میکند تا فناوریهای تبلیغاتی کنترل ساختار گزارشهای سطح رویداد خود را افزایش دهند و بتوانند کاربرد دادهها را به حداکثر برسانند. این انعطافپذیری اضافی در دو مرحله به API گزارش اسناد معرفی میشود: ما دو پارامتر اختیاری زیر را در این پیکربندی نمونه از توسعهدهندهای پشتیبانی میکند که میخواهد برای دریافت گزارشها در پنجرههای گزارش قبلی بهینهسازی کند. علاوه بر پارامترهایی که در فاز 1 اضافه شدند، یک پارامتر اختیاری این پیکربندی فضای خروجی گزارشهای سطح رویداد را بهازای ثبت منبع، کاملاً مشخص میکند. برای هر مشخصات ماشه، ما به طور کامل مشخص می کنیم: تریگرها همچنین از افزودن یک پارامتر مقدار اختیاری در فرهنگ لغت در هر ثبت ماشه حداکثر با یک مشخصات ماشه مطابقت دارد و مقدار خلاصه مربوط به آن را به روز می کند. در سطح بالا، در زمان شروع ما: هنگامی که موارد زیر به ترتیب پیکربندیهای معادل رویداد فعلی و منابع ناوبری APIها هستند. به خصوص برای منابع ناوبری، این نشان می دهد که چرا سطوح نویز نسبت به منابع رویداد بسیار زیاد است تا مقادیر اپسیلون یکسانی حفظ شود: منابع ناوبری فضای خروجی بسیار بزرگتری دارند. با توجه به اینکه برخی از پارامترها را می توان به عنوان پیش فرض یا هرس کرد، ممکن است چندین پیکربندی معادل وجود داشته باشد. در زیر برخی از تنظیمات اضافی خارج از تنظیمات پیش فرض وجود دارد. در همه این مثال ها، مبادلات توسعه دهنده عبارتند از: این پیکربندی مثال از توسعهدهندهای پشتیبانی میکند که میخواهد دادههای ارزش را تنها برای یک پنجره گزارش (مثلاً 7 روز) بهینه کند و پنجرههای گزارش کمتری را با نویز کمتر معامله کند. در این مثال، هر عاملی که تریگرها را می توان با مجموعه فیلد مقادیر به 8 جمع می شوند و پس از 7 روز + 1 ساعت در گزارش های زیر گزارش می شوند: در 7 روز بعدی، محرک های زیر ثبت می شوند: مقادیر به 8 + 50 + 45 = 103 جمع می شوند. این گزارشات زیر را در 14 روز + 1 ساعت به دست می دهد: این مثال نشان میدهد که چگونه یک توسعهدهنده میتواند یک منبع را پیکربندی کند تا تعداد محرکها را تا 10 دریافت کند. محرکهای منتسب با این پیکربندی مثال از توسعهدهندهای پشتیبانی میکند که میخواهد بداند که آیا حداقل یک تبدیل در 10 روز اول اتفاق افتاده است یا نه (بدون توجه به مقدار)، اما میخواهد گزارشها را در فواصل زمانی بیشتر از پیشفرض دریافت کند. مجدداً، در این مثال، هر راهاندازی که ما توسعه دهندگان را تشویق می کنیم موارد استفاده متفاوتی را که ممکن است برای این برنامه افزودنی API داشته باشند پیشنهاد کنند، و ما این توضیح دهنده را با پیکربندی های نمونه برای آن موارد استفاده به روز می کنیم. فنآوران تبلیغات باید از تغییر مسیرها برای ثبت چندین راهانداز منبع انتساب و انجام اسناد بین شبکهای استفاده کنند. این ویژگی به پشتیبانی از انتساب بین شبکهای کمک میکند که در آن تغییر مسیرها در سراسر شبکهها امکانپذیر نیست. بیشتر بدانید . فناوری های تبلیغاتی می توانند پیکربندی را در پاسخ ثبت ماشه ارسال کنند که بر اساس آن منابع ثبت شده توسط سایر فناوری های تبلیغاتی برای تولید منابع مشتق شده انتخاب می شوند. این منابع مشتق شده سپس برای انتساب استفاده می شوند. اگر ماشه به یک منبع مشتق شده نسبت داده شود، گزارشهای انبوه تولید میشوند. تولید گزارش رویداد برای منابع مشتق شده پشتیبانی نمی شود. فناوریهای تبلیغاتی میتوانند از میان منابع مشتق شده بر اساس پیکربندی تحت عنوان هدر ثبت ماشه در اینجا نسخه ای با مقادیر نمونه اضافه شده است: دو فیلد اختیاری جدید برای شروع هدر ثبت اضافه شده است. این فیلدها شناسه فناوری تبلیغات برنده را در کلیدهای گزارش انبوهی فعال میکنند: در اینجا محاسبه قطعه کلید ماشه در هنگام ایجاد گزارش برای منبع AdTechB آمده است: برای فهرستی از قابلیتهای در حال پیشرفت برای زمان اجرا SDK، یادداشتهای انتشار را مشاهده کنید. بازخورد شما بخش مهمی از جعبه ایمنی حریم خصوصی در Android است! هر مشکلی را که پیدا کردید یا ایده ای برای بهبود Privacy Sandbox در Android به ما اطلاع دهید. همانطور که در اسناد Android Sandbox Privacy می خوانید، از دکمه Developer Preview یا Beta برای انتخاب نسخه برنامه ای که با آن کار می کنید استفاده کنید، زیرا ممکن است دستورالعمل ها متفاوت باشد. Attribution Reporting API برای ارائه بهبود حریم خصوصی کاربر با حذف اتکا به شناسههای کاربر بین حزبی و پشتیبانی از موارد استفاده کلیدی برای اندازهگیری اسناد و تبدیل در بین برنامهها طراحی شده است. این راهنمای توسعهدهنده نحوه پیکربندی و آزمایش APIهای گزارش Attribution را برای ثبت کلیکها، بازدیدها و تبدیلهای تبلیغاتی با فراخوانی روشهایی که محرکها و منابع مربوطه را برای چنین رویدادهایی ثبت میکنند، شرح میدهد. این راهنما به شما می آموزد که چگونه نقاط پایانی سرور را تنظیم کنید و یک برنامه مشتری بسازید که این خدمات را فراخوانی کند. درباره طراحی کلی Attribution Reporting API در طرح پیشنهادی بیشتر بیاموزید. برای استفاده از Attribution Reporting API، وظایف سمت سرور و سمت سرویس گیرنده فهرست شده در بخشهای زیر را تکمیل کنید. Attribution Reporting API به مجموعهای از نقاط پایانی نیاز دارد که میتوانید از دستگاه آزمایشی یا شبیهساز به آنها دسترسی داشته باشید. برای هر یک از وظایف سمت سرور زیر یک نقطه پایانی ایجاد کنید: چندین روش برای تنظیم نقاط پایانی مورد نیاز وجود دارد: این نقطه پایانی باید از یک URI مشابه زیر قابل آدرس دهی باشد: هنگامی که یک برنامه مشتری یک منبع انتساب را ثبت می کند ، URI را برای این نقطه پایانی سرور ارائه می دهد. سپس Attribution Reporting API درخواستی می دهد و یکی از سرصفحه های زیر را شامل می شود: برای رویدادهای کلیک کنید: برای مشاهده رویدادها: نقطه پایانی سرور خود را پیکربندی کنید تا با موارد زیر پاسخ دهد: در اینجا یک مثال با مقادیر نمونه اضافه شده است: اگر این نقطه پایانی باید از یک URI مشابه زیر قابل آدرس دهی باشد: هنگامی که یک برنامه مشتری یک رویداد ماشه را ثبت می کند ، URI را برای این نقطه پایانی سرور ارائه می دهد. سپس Attribution Reporting API درخواستی می دهد و یکی از سرصفحه های زیر را شامل می شود: نقطه پایانی سرور خود را پیکربندی کنید تا با موارد زیر پاسخ دهد: در اینجا یک مثال با مقادیر نمونه اضافه شده است: محدودیت 25 بایت برای هر شناسه کلید تجمعی و رشته فیلتر وجود دارد. این بدان معناست که شناسههای کلید تجمعی و رشتههای فیلتر نباید از ۲۵ کاراکتر تجاوز کنند. در این مثال، اگر این نقطه پایانی باید از یک URI آدرس دهی شود. برای کسب اطلاعات بیشتر در مورد ثبت نام URIS ، به ثبت نام در حساب Sandbox حریم خصوصی مراجعه کنید. . _ این سرور را پیکربندی کنید تا درخواست های JSON را که از قالب زیر استفاده می کنند ، بپذیرید: کلیدهای اشکال زدایی امکان بینش اضافی در مورد گزارش های انتساب شما را فراهم می کند. در مورد پیکربندی آنها بیشتر بدانید . این نقطه پایانی باید از URI قابل پرداخت باشد. برای کسب اطلاعات بیشتر در مورد ثبت نام URIS ، به ثبت نام در حساب Sandbox حریم خصوصی مراجعه کنید. . _ هر دو زمینه رمزگذاری شده و بدون رمزگذاری برای گزارش های قابل جمع شدن جمع می شوند. گزارش های رمزگذاری شده شما را قادر می سازد تا با سرویس جمع آوری آزمایش را شروع کنید ، در حالی که زمینه رمزگذاری نشده بینشی را در مورد نحوه تنظیم جفت های ارزش کلید در حال ساخت داده ها فراهم می کند. این سرور را پیکربندی کنید تا درخواست های JSON را که از قالب زیر استفاده می کنند ، بپذیرید: کلیدهای اشکال زدایی امکان بینش اضافی در مورد گزارش های انتساب شما را فراهم می کند. در مورد پیکربندی آنها بیشتر بدانید . برنامه مشتری منابع انتساب و محرک را ثبت می کند و تولید گزارش سطح و قابل جمع شدن را امکان پذیر می کند. برای تهیه یک دستگاه یا شبیه ساز مشتری Android برای استفاده از API گزارش انتساب ، موارد زیر را انجام دهید: با اجرای دستور ADB زیر ، دسترسی به API گزارش انتساب را فعال کنید . (API به طور پیش فرض غیرفعال است.) اگر به صورت محلی در حال آزمایش API گزارش انتساب (مانند آزمایش بر روی دستگاهی هستید که به جسمی دسترسی دارید) ، این دستور را برای غیرفعال کردن ثبت نام اجرا کنید: مجوز (اختیاری) اگر قصد دریافت گزارش های اشکال زدایی را دارید ، مجوز پیکربندی خدمات تبلیغاتی را در عنصر خدمات AD Services XML را که در مانیفست ارجاع شده است ، مانند برنامه شما باید منابع و تبدیل ها را به عنوان اتفاق بیفتد تا اطمینان حاصل شود که به درستی گزارش شده است. کلاس هنگامی که یک آگهی مشاهده یا کلیک می شود ، یک برنامه ناشر برای ثبت نام منبع انتساب همانطور که در قطعه کد نشان داده شده است ، با ثبت API گزارش انتساب از انواع زیر از رویدادهای منبع انتساب پشتیبانی می کند: بازدیدها ، که شما به طور معمول در یک روش پاسخ به تماس مشابه با پس از ثبت نام ، API درخواست HTTP Post را به نقطه پایانی سرویس در آدرس مشخص شده توسط اگر فناوری تبلیغاتی مبداء بخواهد ثبت نام های منبع را به اشتراک بگذارد ، منبع اصلی انتساب URI می تواند شامل تغییر مسیر به سایر نقاط پایانی فناوری باشد. محدودیت ها و قوانینی که در مورد تغییر مسیر اعمال می شود ، در پیشنهاد فنی به تفصیل شرح داده شده است. پشتیبانی برای تغییر مسیر زنجیره دیزی برای فقط قسمت "مقصد" ارائه شده در اولین بازدید در سراسر زنجیره دیزی استفاده می شود. تعداد بازدیدها همان حد را با عنوان های "انتساب-گزارشگر-REDIRECT" دارد. این پشتیبانی تغییر مسیر علاوه بر پشتیبانی موجود "انتساب-گزارشگر-REDIRECT" موجود است و اگر هر دو وجود داشته باشند ، "انتساب-گزارشگر-REDIRECT" اولویت می گیرد. برای ثبت یک رویداد ماشه تبدیل ، با پس از ثبت نام ، API درخواست HTTP Post را به نقطه پایانی سرویس در آدرس مشخص شده توسط اگر بستر تبلیغاتی AD Tech اجازه می دهد تا ثبت نام های ماشه به اشتراک گذاشته شود ، URI می تواند شامل تغییر مسیر به URI ها باشد که متعلق به سایر سیستم عامل های AD Tech است. محدودیت ها و قوانینی که در مورد تغییر مسیر اعمال می شود ، در پیشنهاد فنی به تفصیل شرح داده شده است. در موردی که هم یک برنامه و هم مرورگر در سفر کاربر از منبع به تحریک نقش داشته باشند ، تفاوت های ظریف در اجرای ثبت نام رویدادهای تبلیغاتی وجود دارد. اگر کاربر تبلیغی را در یک برنامه مشاهده کند و برای تبدیل به یک مرورگر هدایت شود ، منبع توسط برنامه ثبت شده و تبدیل توسط مرورگر وب است. به همین ترتیب ، اگر کاربر از یک مرورگر وب شروع کند و برای تبدیل به یک برنامه هدایت شود ، مرورگر منبع را ثبت می کند و برنامه تبدیل را ثبت می کند. از آنجا که تفاوت هایی در نحوه سازماندهی فناوری های تبلیغاتی در وب و Android وجود دارد ، ما API های جدیدی را برای ثبت منابع و محرک ها در هنگام انجام آنها در مرورگرها اضافه کرده ایم. تفاوت اصلی بین این API ها و API های مبتنی بر برنامه مربوطه در این است که ما انتظار داریم مرورگر از تغییر مسیر پیروی کند ، از هر فیلترهای خاص مرورگر استفاده کند و با فراخوانی قطعه کد زیر نمونه ای از تماس API را نشان می دهد که مرورگر قبل از هدایت کاربر به یک برنامه ، یک منبع انتساب را ثبت می کند: قطعه کد زیر نمونه ای از تماس API را نشان می دهد که مرورگر برای ثبت یک تبدیل پس از کارگردانی کاربر از برنامه ایجاد می کند: گزارش های سطح رویداد حاوی مقصد ، شناسه منبع انتساب و داده های ماشه است. آنها در قالب اصلی (رمزگذاری نشده) به مبدا گزارش ارسال می شوند. برای محافظت از حریم خصوصی کاربر ، می توان سر و صدای اضافه کرد تا شناسایی یک کاربر فردی دشوارتر شود. گزارش های سطح رویداد Noised مطابق با چارچوب نهیاری دیفرانسیل تولید و ارسال می شوند. این مقادیر پیش فرض درصد نویز برای سناریوهای مختلف است: نوع منبع مقدار مقصد مقصد احتمال گزارش بدون ثبت در هر منبع ثبت نام چشم انداز یا برنامه یا وب 0.0000025 چشم انداز برنامه و وب 0.0000042 کلیک یا برنامه یا وب 0.0024263 کلیک برنامه و وب 0.0170218 در اندازه گیری انتساب برنامه به WEB ، که در آن منابع می توانند به هر دو برنامه و مقصد وب تبدیل شوند ، گزارش های سطح رویداد می توانند مشخص کنند که آیا ماشه در برنامه یا وب رخ داده است. برای جبران این جزئیات اضافی ، گزارش های Noised تولید شده تا 7 برابر برای کلیک و 1.7 برابر پوند برای نماها است. برخی از فناوری های تبلیغاتی برای مشخص کردن اینکه آیا ماشه در برنامه یا مقصد وب رخ داده است ، نیازی به گزارش های سطح رویداد ندارند. فناوری های تبلیغاتی می توانند از قسمت در مثالهای زیر ، کاربر روی یک تبلیغ کلیک می کند و آن منبع در API ثبت می شود. کاربر سپس به برنامه تبلیغ کننده و وب سایت تبلیغ کننده تبدیل می کند. هر دو این تبدیل به عنوان محرک ثبت شده و به کلیک اولیه نسبت داده می شوند. ثبت نام منبع مبتنی بر کلیک هدر HTTP: یک ماشه از برنامه با نام بسته یک ماشه از یک مرورگر از وب سایت با دامنه ETLD+1 گزارش های سطح رویداد حاصل می شود. با فرض اینکه هر دو محرک به منبع نسبت داده می شوند ، گزارش های سطح رویداد زیر تولید می شوند: API گزارشگر انتساب گزارش ها را به نقاط پایانی روی سرور شما ارسال می کند که گزارش های سطح رویداد و گزارش های قابل جمع را می پذیرند. پس از ثبت یک رویداد منبع Attribution یا یک رویداد ماشه را ثبت کنید ، سیستم برنامه گزارش دهی را برنامه ریزی می کند. به طور پیش فرض ، این کار هر 4 ساعت یکبار انجام می شود. برای اهداف آزمایش ، می توانید مشاغل گزارش دهی را مجبور به اجرای یا کوتاه کردن فواصل بین مشاغل کنید. کار انتساب نیرو برای اجرای: کار گزارش در سطح رویداد را برای اجرای: کار گزارشگری قابل جمع شدن را به اجرا درآورد: خروجی موجود در LogCat را بررسی کنید تا ببینید چه موقع کار انجام شده است. باید چیزی شبیه به زیر باشد: حتی اگر کار گزارشگری مجبور به اجرای آن شود ، سیستم هنوز گزارش هایی را با توجه به زمان تحویل برنامه ریزی شده خود ارسال می کند ، که از چند ساعت تا چند روز متغیر است. برای اهداف آزمایش ، می توانید زمان سیستم دستگاه را پس از تأخیرهای برنامه ریزی شده برای شروع تحویل گزارش پیش ببرید. پس از ارسال گزارش ها ، تحویل را با بررسی گزارش های دریافت شده ، گزارش های سرور قابل اجرا مانند تاریخچه سرور Mock یا سیستم سفارشی خود تأیید کنید. هنگام دریافت گزارش کل ، قسمت در زیر نمونه ای از رمزگشایی محتوای قسمت برای کمک به شما در شروع کار با API گزارش انتساب ، می توانید از پروژه اندازه گیری AMPLEAPP در GitHub استفاده کنید. این برنامه نمونه ثبت نام منبع انتساب و ثبت نام را نشان می دهد. برای نقاط پایانی سرور ، منابع مرجع زیر یا راه حل سفارشی خود را در نظر بگیرید: API های مسخره را در نقاط پایانی از راه دور که از دستگاه تست یا شبیه ساز خود قابل دسترسی است ، مستقر کنید. برای سهولت در آزمایش ، به پروژه های نمونه SeasureAdtechserverspec و اندازه گیری adtechserver مراجعه کنید. پیکربندی پیش فرض برای گزارش سطح رویداد برای شروع آزمایش ابزار توصیه شده است ، اما ممکن است برای همه موارد استفاده ایده آل نباشد. API گزارشگر انتساب از تنظیمات اختیاری و انعطاف پذیر تر پشتیبانی می کند به طوری که تکنیک های تبلیغاتی کنترل ساختار گزارش های سطح رویداد خود را افزایش داده و قادر به به حداکثر رساندن کاربرد داده ها هستند. این انعطاف پذیری اضافی در دو مرحله به API گزارش انتساب معرفی می شود: ما دو پارامتر اختیاری زیر را به JSON در این پیکربندی مثال از یک توسعه دهنده پشتیبانی می کند که می خواهد برای دریافت گزارش در ویندوزهای گزارش قبلی بهینه شود. علاوه بر پارامترهایی که در فاز 1 اضافه شده اند ، ما یک پارامتر اختیاری اضافی این پیکربندی به طور کامل فضای خروجی گزارش های سطح رویداد ، در هر ثبت منبع را مشخص می کند. برای هر مشخصات ماشه ، ما کاملاً مشخص می کنیم: Triggers همچنین از اضافه کردن یک پارامتر مقدار اختیاری در فرهنگ لغت در هر ثبت نام ماشه با حداکثر یک ویژگی ماشه مطابقت دارد و مقدار خلاصه مرتبط با آن را به روز می کند. در سطح بالا ، در زمان ماشه ما: هنگامی که موارد زیر به ترتیب تنظیمات معادل رویداد و منابع ناوبری APIS است. به خصوص برای منابع ناوبری ، این نشان می دهد که چرا سطح سر و صدا نسبت به منابع رویداد برای حفظ همان مقادیر اپسیلون بسیار زیاد است: منابع ناوبری فضای خروجی بسیار بیشتری دارند. این امکان وجود دارد که با توجه به اینکه برخی از پارامترها می توانند به صورت پیش فرض یا هرس تنظیم شوند ، تنظیمات متعددی وجود داشته باشد. در زیر برخی از تنظیمات اضافی در خارج از پیش فرض وجود دارد. در تمام این مثالها ، معاملات توسعه دهنده شامل موارد زیر است: این پیکربندی مثال از یک توسعه دهنده پشتیبانی می کند که می خواهد داده های ارزش را فقط برای یک پنجره گزارش دهی بهینه کند (به عنوان مثال 7 روز) ، و تجارت کمتری از ویندوز را برای سر و صدای کمتر معامله می کند. در این مثال ، هر ماشه ای که ماشه ها می توانند در مجموعه قسمت مقادیر خلاصه شده به 8 و در گزارش های زیر پس از 7 روز + 1 ساعت گزارش شده است: در 7 روز بعد ، محرک های زیر ثبت شده اند: مقادیر به 8 + 50 + 45 = 103 خلاصه می شوند. این گزارش های زیر را در 14 روز + 1 ساعت ارائه می دهد: این مثال نشان می دهد که چگونه یک توسعه دهنده می تواند یک منبع را پیکربندی کند تا تعداد محرک های حداکثر 10 را بدست آورد. محرک های انتهایی با تنظیم این پیکربندی مثال از یک توسعه دهنده پشتیبانی می کند که می خواهد یاد بگیرد که آیا حداقل یک تبدیل در 10 روز اول (صرف نظر از ارزش) رخ داده است ، اما می خواهد گزارش ها را در فواصل مکرر نسبت به پیش فرض دریافت کند. باز هم ، در این مثال هر ماشه ای که ما توسعه دهندگان را ترغیب می کنیم تا موارد استفاده متفاوتی را که ممکن است برای این پسوند API داشته باشند ، پیشنهاد کنند و این توضیح دهنده را با تنظیمات نمونه برای موارد استفاده به روز خواهیم کرد. فناوری های تبلیغاتی باید از Redirects برای ثبت چندین محرک منبع انتساب و انجام انتساب شبکه متقابل استفاده کنند. این ویژگی به پشتیبانی از انتساب شبکه متقابل کمک می کند که در آن تغییر مسیر در شبکه ها امکان پذیر نیست. بیشتر بدانید . فناوری های تبلیغاتی می توانند پیکربندی را در پاسخ ثبت نام ماشه بر اساس اینکه منابع ثبت شده توسط سایر فناوری های تبلیغاتی برای تولید منابع مشتق شده انتخاب شده اند ، ارسال کنند. این منابع مشتق شده سپس برای انتساب استفاده می شوند. اگر ماشه به یک منبع مشتق شده نسبت داده شود ، گزارش های کل تولید می شوند. تولید گزارش رویداد برای منابع مشتق شده پشتیبانی نمی شود. تکنیک های تبلیغاتی می توانند از منابع مشتق شده بر اساس پیکربندی تحت عنوان ثبت نام در اینجا یک نسخه با مقادیر مثال اضافه شده است: دو قسمت اختیاری جدید برای ایجاد هدر ثبت نام اضافه می شود. این زمینه ها شناسه AD Tech برنده را در کلیدهای گزارش قابل جمع کردن فعال می کنند: در اینجا محاسبه قطعه اصلی ماشه هنگام تولید گزارشی برای منبع ADTECHB ارائه شده است: برای لیستی از قابلیت های در حال پیشرفت برای زمان اجرا SDK ، یادداشت های انتشار را مشاهده کنید. بازخورد شما بخش مهمی از ماسهبازی حریم خصوصی در Android است! به ما اطلاع دهید و از هرگونه مسائلی که می یابید یا ایده هایی را برای بهبود ماسهبازی حریم خصوصی در اندروید به ما اطلاع دهید. همانطور که از طریق Sandbox حریم خصوصی در مستندات Android خوانده اید ، از دکمه پیش نمایش توسعه دهنده یا Beta برای انتخاب نسخه برنامه ای که با آنها کار می کنید استفاده کنید ، زیرا ممکن است دستورالعمل ها متفاوت باشد. API گزارشگر Attribution به گونه ای طراحی شده است که با از بین بردن اعتماد به شناسه های کاربر متقابل ، و پشتیبانی از موارد استفاده کلیدی برای اندازه گیری و اندازه گیری تبدیل در برنامه ها ، حریم شخصی بهبود یافته را فراهم می کند. این راهنمای توسعه دهنده نحوه پیکربندی و آزمایش API های گزارش انتساب را برای ثبت کلیک ها ، نماها و تبدیل های تبلیغاتی با استفاده از روش هایی که باعث ثبت محرک ها و منابع مربوطه برای چنین رویدادهایی می شود ، توصیف می کند. این راهنما به شما می آموزد که چگونه می توانید نقاط پایانی سرور را تنظیم کنید و یک برنامه مشتری ایجاد کنید که این سرویس ها را فراخوانی می کند. در مورد طراحی کلی API گزارشگر API در پیشنهاد طراحی بیشتر بدانید. برای استفاده از API گزارش انتساب ، وظایف سمت سرور و سمت مشتری را که در بخش های بعدی ذکر شده است ، انجام دهید. API گزارشگر Attribution به مجموعه ای از نقاط پایانی نیاز دارد که می توانید از یک دستگاه تست یا شبیه ساز به آن دسترسی پیدا کنید. برای هر یک از کارهای سمت زیر سرور یک نقطه پایانی ایجاد کنید: چندین روش برای تنظیم نقاط پایانی مورد نیاز وجود دارد: این نقطه پایانی باید از URI مشابه موارد زیر قابل دسترسی باشد: هنگامی که یک برنامه مشتری یک منبع انتساب را ثبت می کند ، URI را برای این نقطه پایانی سرور فراهم می کند. سپس API گزارش انتساب درخواست می کند و یکی از هدرهای زیر را شامل می شود: برای رویدادهای کلیک: برای مشاهده رویدادها: نقطه پایانی سرور خود را پیکربندی کنید تا با موارد زیر پاسخ دهید: در اینجا مثالی با مقادیر نمونه اضافه شده است: اگر این نقطه پایانی باید از URI مشابه موارد زیر قابل دسترسی باشد: هنگامی که یک برنامه مشتری یک رویداد ماشه را ثبت می کند ، URI را برای این نقطه پایانی سرور فراهم می کند. سپس API گزارش انتساب درخواست می کند و یکی از هدرهای زیر را شامل می شود: نقطه پایانی سرور خود را پیکربندی کنید تا با موارد زیر پاسخ دهید: در اینجا مثالی با مقادیر نمونه اضافه شده است: در هر شناسه کلید و رشته فیلتر محدود 25 بایت وجود دارد. این بدان معنی است که شناسه های کلیدی جمع آوری و رشته های فیلتر شما نباید از 25 کاراکتر تجاوز کنند. در این مثال ، اگر این نقطه پایانی باید از URI قابل پرداخت باشد. برای کسب اطلاعات بیشتر در مورد ثبت نام URIS ، به ثبت نام در حساب Sandbox حریم خصوصی مراجعه کنید. . _ این سرور را پیکربندی کنید تا درخواست های JSON را که از قالب زیر استفاده می کنند ، بپذیرید: کلیدهای اشکال زدایی امکان بینش اضافی در مورد گزارش های انتساب شما را فراهم می کند. در مورد پیکربندی آنها بیشتر بدانید . این نقطه پایانی باید از URI قابل پرداخت باشد. برای کسب اطلاعات بیشتر در مورد ثبت نام URIS ، به ثبت نام در حساب Sandbox حریم خصوصی مراجعه کنید. . _ هر دو زمینه رمزگذاری شده و بدون رمزگذاری برای گزارش های قابل جمع شدن جمع می شوند. گزارش های رمزگذاری شده شما را قادر می سازد تا با سرویس جمع آوری آزمایش را شروع کنید ، در حالی که زمینه رمزگذاری نشده بینشی را در مورد نحوه تنظیم جفت های ارزش کلید در حال ساخت داده ها فراهم می کند. این سرور را پیکربندی کنید تا درخواست های JSON را که از قالب زیر استفاده می کنند ، بپذیرید: کلیدهای اشکال زدایی امکان بینش اضافی در مورد گزارش های انتساب شما را فراهم می کند. در مورد پیکربندی آنها بیشتر بدانید . برنامه مشتری منابع انتساب و محرک را ثبت می کند و تولید گزارش سطح و قابل جمع شدن را امکان پذیر می کند. برای تهیه یک دستگاه یا شبیه ساز مشتری Android برای استفاده از API گزارش انتساب ، موارد زیر را انجام دهید: با اجرای دستور ADB زیر ، دسترسی به API گزارش انتساب را فعال کنید . (API به طور پیش فرض غیرفعال است.) اگر به صورت محلی در حال آزمایش API گزارش انتساب (مانند آزمایش بر روی دستگاهی هستید که به جسمی دسترسی دارید) ، این دستور را برای غیرفعال کردن ثبت نام اجرا کنید: مجوز (اختیاری) اگر قصد دریافت گزارش های اشکال زدایی را دارید ، مجوز پیکربندی خدمات تبلیغاتی را در عنصر خدمات AD Services XML را که در مانیفست ارجاع شده است ، مانند برنامه شما باید منابع و تبدیل ها را به عنوان اتفاق بیفتد تا اطمینان حاصل شود که به درستی گزارش شده است. کلاس هنگامی که یک آگهی مشاهده یا کلیک می شود ، یک برنامه ناشر برای ثبت نام منبع انتساب همانطور که در قطعه کد نشان داده شده است ، با ثبت API گزارش انتساب از انواع زیر از رویدادهای منبع انتساب پشتیبانی می کند: بازدیدها ، که شما به طور معمول در یک روش پاسخ به تماس مشابه با پس از ثبت نام ، API درخواست HTTP Post را به نقطه پایانی سرویس در آدرس مشخص شده توسط اگر فناوری تبلیغاتی مبداء بخواهد ثبت نام های منبع را به اشتراک بگذارد ، منبع اصلی انتساب URI می تواند شامل تغییر مسیر به سایر نقاط پایانی فناوری باشد. محدودیت ها و قوانینی که در مورد تغییر مسیر اعمال می شود ، در پیشنهاد فنی به تفصیل شرح داده شده است. پشتیبانی برای تغییر مسیر زنجیره دیزی برای فقط قسمت "مقصد" ارائه شده در اولین بازدید در سراسر زنجیره دیزی استفاده می شود. تعداد بازدیدها همان حد را با عنوان های "انتساب-گزارشگر-REDIRECT" دارد. این پشتیبانی تغییر مسیر علاوه بر پشتیبانی موجود "انتساب-گزارشگر-REDIRECT" موجود است و اگر هر دو وجود داشته باشند ، "انتساب-گزارشگر-REDIRECT" اولویت می گیرد. To register a conversion trigger event, call After registration, the API issues an HTTP POST request to the service endpoint at the address specified by If the originating ad tech platform allows trigger registrations to be shared, the URI can include redirects to URIs that belong to other ad tech platforms. The limits and rules applicable to the redirects are detailed in the technical proposal . In the case where both an app and browser play a part in the user's journey from source to trigger, there are subtle differences in the implementation of registering ad events. If a user sees an ad on an app and is redirected to a browser for a conversion, the source is registered by the app, and the conversion by the web browser. Similarly, if a user starts on a web browser and is directed to an app for conversion, the browser registers the source, and the app registers the conversion. Since there are differences in the way ad techs are organized on the web and on Android, we have added new APIs to register sources and triggers when they take place on browsers. The key difference between these APIs and the corresponding app-based APIs is that we expect the browser to follow the redirects, apply any browser-specific filters, and pass on the valid registrations to the platform by calling The following code snippet shows an example of the API call that the browser makes to register an attribution source before directing the user to an app: The following code snippet shows an example of the API call that the browser makes to register a conversion after the user has been directed from the app: Event-level reports contain destination, attribution source ID and trigger data. They are sent in the original (unencrypted) format to the reporting origin. To protect user's privacy, noise can be added to make it more difficult to identify an individual user. Noised event-level reports are generated and sent in accordance with the differential-privacy framework. These are the default noise percentage values for different scenarios: نوع منبع Source destination value Noised report probability per source registration چشم انداز Either app or web 0.0000025 چشم انداز App and web 0.0000042 کلیک Either app or web 0.0024263 کلیک App and web 0.0170218 In app-to-web attribution measurement, where sources can drive conversion to both app and web destinations, event-level reports can specify whether the trigger occurred on app or web. To compensate for this additional detail, the noised reports generated are up to ~7x for clicks and ~1.7x for views. Some ad techs don't require event-level reports to specify whether the trigger occurred on either the app or web destination. Ad techs can use the In the following examples, a user clicks on an ad, and that source is registered with the API. The user then converts on both the advertiser app and the advertiser's website. Both of these conversions are registered as triggers and attributed to the initial click. A click-based source registration HTTP header: A trigger is registered from the app with the package name A trigger is registered from a browser from the website with the eTLD+1 domain The resulting event-level reports are generated. Assuming both triggers get attributed to the source, the following event-level reports are generated: The Attribution Reporting API sends reports to the endpoints on your server that accept event-level reports and aggregatable reports . After you register an attribution source event or register a trigger event, the system schedules the reporting job to run. By default, this job runs every 4 hours. For testing purposes, you can force the reporting jobs to run or shorten the intervals between jobs. Force attribution job to run: Force event-level reporting job to run: Force aggregatable reporting job to run: Check the output in logcat to see when the jobs have run. It should look something like the following: Even if the reporting job is forced to run, the system still sends out reports according to their scheduled delivery times , which range from a couple of hours to several days. For testing purposes, you can advance the device system time to be after the scheduled delays to initiate the report delivery. Once reports are sent, verify delivery by checking received reports, applicable server logs such as the mock server history or your custom system. When receiving an aggregate report, the Below is an example of decoding the contents of the To help you get started with the Attribution Reporting API, you can use the MeasurementSampleApp project on GitHub. This sample app demonstrates attribution source registration and trigger registration. For server endpoints, consider the following reference resources or your custom solution: Deploy mock APIs on remote endpoints accessible from your test device or emulator. For ease of testing, refer to the MeasurementAdTechServerSpec and MeasurementAdTechServer sample projects. The default configuration for event level reporting is advised for starting utility testing, but may not be ideal for all use cases. The Attribution Reporting API will support optional, more flexible configurations so that ad techs have increased control over the structure of their event level reports and are able to maximize the utility of the data. This additional flexibility will be introduced into the Attribution Reporting API in two phases: We will add the following two optional parameters to the JSON in This example configuration supports a developer who wants to optimize for receiving reports at earlier reporting windows. In addition to the parameters that were added in Phase 1, we will add an additional optional parameter This configuration fully specifies the output space of the event-level reports, per source registration. For every trigger spec, we fully specify: Triggers will also support adding an optional value parameter in the dictionaries within Every trigger registration will match with at most one trigger spec and update its associated summary value. At a high level, at trigger time we will: When the The following are equivalent configurations for the APIs current event and navigation sources, respectively. Especially for navigation sources, this illustrates why the noise levels are so high relative to event sources to maintain the same epsilon values: navigation sources have a much larger output space. It is possible that there are multiple configurations that are equivalent, given that some parameters can be set as default or pruned. Below are some additional configurations outside the defaults. In all of these examples, the developer trade-offs include: This example configuration supports a developer who wants to optimize for value data for only one reporting window (eg 7 days), trading fewer reporting windows for less noise. In this example any trigger that sets Triggers could be registered with the The values are summed to 8 and reported in the following reports after 7 days + 1 hour: In the subsequent 7 days, the following triggers are registered: The values are summed to 8 + 50 + 45 = 103. This yields the following reports at 14 days + 1 hour: This example shows how a developer can configure a source to get a count of triggers up to 10. Attributed triggers with This example configuration supports a developer who wants to learn whether at least one conversion occurred in the first 10 days (regardless of value), but wants to receive reports at more frequent intervals than the default. Again, in this example any trigger that sets We encourage developers to suggest different use cases they may have for this API extension, and we will update this explainer with sample configurations for those use cases. Ad techs should use redirects to register multiple attribution source triggers and to perform cross-network attribution. This feature helps support cross-network attribution where redirects aren't feasible across networks. بیشتر بدانید . Ad techs can send configuration in the trigger registration response based on which sources registered by other ad techs are selected to generate derived sources; these derived sources are then used for attribution. Aggregate reports are generated if the trigger gets attributed to a derived source. Event report generation for derived sources is not supported. Ad techs can choose from the Derived sources are generated based on the configuration under the trigger registration header Here's a version with example values added: Two new optional fields are added to trigger registration header. These fields enable the winning ad tech's identifier in aggregatable report keys: Here's the resulting trigger key piece calculation when generating a report for AdTechB's source: For a list of in-progress capabilities for the SDK Runtime, view the release notes . Your feedback is a crucial part of the Privacy Sandbox on Android! Let us know of any issues you find or ideas for improving Privacy Sandbox on Android.Attribution-Reporting-Register-Source
به JSON اضافه می کنیم: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
}
}
trigger_specs
به JSON در Attribution-Reporting-Register-Source
اضافه می کنیم.{
// A trigger spec is a set of matching criteria, along with a scheme to
// generate bucketized output based on accumulated values across multiple
// triggers within the specified event_report_window. There will be a limit on
// the number of specs possible to define for a source.
"trigger_specs": [{
// This spec will only apply to registrations that set one of the given
// trigger data values (non-negative integers) in the list.
// trigger_data will still appear in the event-level report.
"trigger_data": [<int>, ...]
// Represents a series of time windows, starting at the source registration
// time. Reports for this spec will be delivered an hour after the end of
// each window. Time is encoded as seconds after source registration.
// end_times must consist of strictly increasing positive integers.
//
// Note: specs with identical trigger_data cannot have overlapping windows;
// this ensures that triggers match at most one spec. If
// event_report_windows is omitted, will use the "event_report_window" or
// "event_report_windows" field specified at the global level for the source
// (or the default windows if none are specified). End time is exclusive.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...],
}
// Represents an operator that summarizes the triggers within a window
// count: number of triggers attributed within a window
// value_sum: sum of the value of triggers within a window
// The summary is reported as an index into a bucketization scheme. Defaults
// to "count"
"summary_window_operator": <one of "count" or "value_sum">,
// Represents a bucketization of the integers from [0, MAX_INT], encoded as
// a list of integers where new buckets begin (excluding 0 which is
// implicitly included).
// It must consist of strictly increasing positive integers.
//
// e.g. [5, 10, 100] encodes the following ranges:
// [[0, 4], [5, 9], [10, 99], [100, MAX_INT]]
//
// At the end of each reporting window, triggers will be summarized into an
// integer which slots into one of these ranges. Reports will be sent for
// every new range boundary that is crossed. Reports will never be sent for
// the range that includes 0, as every source is initialized in this range.
//
// If omitted, then represents a trivial mapping
// [1, 2, ... , MAX_INT]
// With MAX_INT being the maximum int value defined by the browser.
"summary_buckets": [<bucket start>, ...]
}, {
// Next trigger_spec
} ...],
// See description in phase 1.
"max_event_level_reports": <int>
// See description in phase 1.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...]
}
}
trigger_data
مشخص شده در trigger_specs
را دارند، واجد شرایط مطابقت است. به عبارت دیگر، اگر ماشه با این منبع مطابقت داشت اما trigger_data
آن یکی از مقادیر موجود در پیکربندی منبع نباشد، ماشه نادیده گرفته میشود.event_report_windows
). توجه داشته باشید که علیرغم عدم موفقیت در دو معیار تطبیق ذکر شده در بالا، باز هم میتوان ماشه را با منبعی برای گزارشهای جمعآوری مطابقت داد.value
را مشخص کنند که برای یک مشخصات خاص خلاصه می شود، اما به عنوان یک مقدار سطلی گزارش می شود.event_trigger_data
پشتیبانی میکنند.{
"event_trigger_data": [
{
"trigger_data": "2",
"value": 100, // Defaults to 1
"filters": ...
},
...
]
}
event_trigger_data
را روی مشخصات ارزیابی کنید تا با استفاده از event_reporting_window
spec، مطابقت را پیدا کنید. event_reporting_windows
سطح بالا به عنوان یک مقدار پیشفرض عمل میکند در صورتی که هر یک از مشخصات ماشه، قسمت فرعی event_report_windows
از دست رفته باشد.value
افزایش مییابد.event_report_window
برای یک مشخصات کامل شد، مقدار خلاصه آن را به یک سطل نگاشت میکنیم، و یک گزارش در سطح رویداد برای هر افزایش در سطل خلاصه ناشی از مقادیر ماشه نسبت داده شده ارسال میکنیم. گزارشها با یک فیلد اضافی ارائه میشوند، trigger_summary_bucket
.{
...
"trigger_summary_bucket": [<bucket start>, <bucket end>],
}
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1],
"event_report_windows": {
"end_times": [<30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1],
}],
"max_event_level_reports": 1,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3, 4, 5, 6, 7],
"event_report_windows": {
"end_times": [<2 days>, <7 days>, <30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3],
}],
"max_event_level_reports": 3,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
trigger_data
روی مقداری غیر از 0 تنظیم کند، برای انتساب واجد شرایط نیست.{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
"end_times": [604800, 1209600] // 7 days, 14 days represented in seconds
},
"summary_window_operator": "value_sum",
"summary_buckets": [5, 10, 100]
}],
}
value
ثبت کرد که خلاصه و سطل می شود. به عنوان مثال اگر در عرض 7 روز از ثبت منبع با مقادیر 1، 3 و 4، سه تریگر وجود داشته باشد.{ "event_trigger_data": [{"trigger_data": "0", "value": 1}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 3}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 4}] }
// Report 1
{
...
"trigger_summary_bucket": [5, 9]
}
{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }
// Report 2
{
...
"trigger_summary_bucket": [10, 99]
},
// Report 3
{
...
"trigger_summary_bucket": [100, MAX_INT]
}
{
"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]
}
trigger_data
روی مقداری غیر از 0 تنظیم کند، برای انتساب واجد شرایط نیست. به همین دلیل است که این مورد استفاده باینری نامیده می شود.{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
// 1 day, 2 days, 3 days, 5 days, 7 days, 10 days represented in seconds
"end_times": [86400, 172800, 259200, 432000, 604800, 864000]
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1]
}],
}
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
{
"trigger_specs": [
{
"trigger_data": [4, 5, 6, 7],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
aggregation_keys
در منابع ثبتشده خود که قصد دارند با فنآوران تبلیغات شریک به اشتراک بگذارند، انتخاب کنند. این کلیدها را می توان در قسمت اختیاری shared_aggregation_keys
که در زیر سرصفحه ثبت منبع Attribution-Reporting-Register-Source
قرار دارد، اعلام کرد:"shared_aggregation_keys": ["[key name1]", "[key name2]"]
Attribution-Reporting-Register-Trigger
تولید می شوند: // Specifies the configuration based on which derived sources should be
// generated. Those derived sources will be included for source matching at the
// time of attribution. For example, if adtech2 is registering a trigger with an
// attribution_config with source_network as adtech1, available sources
// registered by adtech1 will be considered with additional filtering criteria
// applied to that set as mentioned in the attribution_config. Derived
// sources can have different values to priority, post_install_exclusivity_window
// etc.
"attribution_config": [
{
// Derived sources are created from this adtech's registered sources
"source_network": "[original source's adtech enrollment ID]",
//(optional) Filter sources whose priority falls in this range
"source_priority_range": {
"start": [priority filter lower bound],
"end": [priority filter upper bound]
},
// (optional) Filter sources whose at least one of filter maps matches these
// filters
"source_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Filter sources whose none of filter map matches these
// filters
"source_not_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Apply this priority to the generated derived sources
"priority": "[64 bit signed integer]",
// (optional) The derived source will have expiry set as this or parent
// source's, whichever is earlier
"expiry": "[64 bit signed integer]",
// (optional) set on the derived source
"filter_data": {
"key name 1": ["key1 value 1"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "[64-bit unsigned integer]"
}
]
"attribution_config": [
{
"source_network": "adtech1-enrollment-id",
"source_priority_range": {
"start": 50,
"end": 100
},
"source_filters": {
"source_type": ["NAVIGATION"]
},
"source_not_filters": {
"product_id": ["789"]
},
"priority": "30",
"expiry": "78901",
// (optional) set on the derived source
"filter_data": {
"product_id": ["1234"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "7890"
}
]
x_network_bit_mapping
: شناسه ثبت نام در نگاشت بیت شناسه فناوری تبلیغاتx_network_data
: آفست (تغییر به چپ) برای عملیات x_network_bit_mapping
OR فناوری تبلیغات برنده با قطعه کلید ماشه"Attribution-Reporting-Register-Trigger": {
"attribution_config": [...],
"aggregatable_trigger_data": [
{
"key_piece": "0x400",
"source_keys": ["campaignCounts"]
"x_network_data" : {
"key_offset" : 12 // [64 bit unsigned integer]
}
}
…
]
…
"x_network_bit_mapping": {
// This mapping is used to generate trigger key pieces with 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
}
…
}
key_piece
: 0x400 (010000000000)
key_offset
: 12
enrollment_id
AdtechB: 2 (010)
(از x_network_bit_mapping
)0x400 | 0x2 << 12 = 0x2400
https://adtech.example/attribution_source
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 شرکای فناوری تبلیغات باشد، API گزارش Attribution درخواست مشابهی را برای هر 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.
https://adtech.example/attribution_trigger
// 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
campaignCounts
14 کاراکتر است، بنابراین یک شناسه کلید تجمعی معتبر است، و 1234
4 کاراکتر است، بنابراین یک رشته فیلتر معتبر است. اگر شناسه کلید تجمیع یا رشته فیلتر بیش از 25 کاراکتر باشد، ماشه نادیده گرفته می شود.Attribution-Reporting-Redirect
شامل URI شرکای فناوری تبلیغات باشد، API گزارش Attribution درخواست مشابهی را برای هر 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.
https://adtech.example/.well-known/attribution-reporting/report-event-attribution
{
"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]",
}
https://adtech.example/.well-known/attribution-reporting/report-aggregate-attribution
{
// 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]"
}
adb shell device_config put adservices ppapi_app_allow_list \"\*\"
adb shell device_config put adservices disable_measurement_enrollment_check "true"
ACCESS_ADSERVICES_ATTRIBUTION
را در پرونده مانیفست Android خود قرار دهید و یک پیکربندی خدمات تبلیغاتی را برای برنامه خود ایجاد کنید تا از API های گزارشگری Attribution استفاده کنید:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
ACCESS_ADSERVICES_AD_ID
را در پرونده مانیفست اندرویدی خود قرار دهید:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />
<application>
مانیفست خود ارجاع دهید:<property android:name="android.adservices.AD_SERVICES_CONFIG"
android:resource="@xml/ad_services_config" />
res/xml/ad_services_config.xml
مشخص کنید. در مورد مجوزهای خدمات تبلیغاتی و کنترل دسترسی SDK بیشتر بدانید.<ad-services-config>
<attribution allowAllToAccess="true" />
</ad-services-config>
MeasurementManager
روش هایی را برای کمک به شما در ثبت وقایع منبع انتساب و محرک های تبدیل به شما کمک می کند.registerSource()
تماس می گیرد.onClick()
ثبت می کنید. رویداد ماشه مربوطه معمولاً به زودی پس از رویداد کلیک اتفاق می افتد. این نوع رویداد اطلاعات بیشتری در مورد تعامل کاربر ارائه می دهد و بنابراین نوع خوبی از منبع انتساب برای اولویت بالایی است.onAdShown()
ثبت می کنید. رویداد ماشه مربوطه ممکن است ساعات یا چند روز پس از رویداد مشاهده رخ دهد. 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)
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);
attributionSourceUri
صادر می کند. پاسخ نقطه پایانی شامل مقادیر destination, source_event_id, expiry
و source_priority
است.registerSource
و registerTrigger
اضافه شده است. علاوه بر عنوان ثبت نام ، مصرف کننده API هم اکنون می تواند HTTP را به عنوان پاسخ سرور که شامل یک کد وضعیت 302 و یک هدر "مکان" با URL بعدی برای بازدید برای ثبت نام اضافی است ، ارائه دهد.registerTrigger()
در برنامه خود تماس بگیرید: 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)
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)
attributionTriggerUri
صادر می کند. پاسخ نقطه پایانی شامل مقادیر گزارش های رویداد و کل است.registerWebSource()
یا registerWebTrigger()
ثبت نام های معتبر را به سیستم عامل منتقل کند.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)
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);
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)
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);
coarse_event_report_destinations
تحت عنوان Attribution-Reporting-Register-Source
برای کاهش نویز استفاده کنند. اگر یک منبع با قسمت coarse_event_report_destinations
مشخص شده برنده شده باشد ، گزارش حاصل شامل برنامه و مقصد وب بدون تمایز در مورد اینکه ماشه واقعی در کجا رخ داده است.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"
}],
}
https://advertiser.com
ثبت شده است:Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
"trigger_data": "2",
"priority": "2"
}],
}
{
"attribution_destination": ["android-app://com.advertiser.example,https://advertiser.com"],
"scheduled_report_time": "800176400",
"source_event_id": "53234",
"trigger_data": "1",
// Can be "event" if source were registered by user viewing the ad
"source_type": "navigation",
// Would be 0.0170218 without coarse_event_report_destinations as true in the source
"randomized_trigger_rate": 0.0024263
}
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
JobScheduler: executeRunCommand(): com.google.android.adservices.api/0 5 s=false f=true
debug_cleartext_payload
یک نسخه رمزگذاری نشده از گزارش کل شما را در خود جای داده است. در حالی که این نسخه از گزارش شما رمزگذاری نشده است ، هنوز هم باید رمزگشایی شود.debug_cleartext_payload
در دو مرحله وجود دارد: اولین با استفاده از رمزگشایی پایه 64 و دوم با استفاده از رمزگشایی CBOR.String base64DebugPayload = "omRkYXRhgqJldmFsdWVEAAAGgGZidWNrZXRQAAAAAAAAAAAAAAAAAAAKhaJldmFsdWVEAACAAGZidWNrZXRQAAAAAAAAAAAAAAAAAAAFWWlvcGVyYXRpb25paGlzdG9ncmFt";
byte[] cborEncoded = Base64.getDecoder().decode(base64DebugPayload);
// CbodDecoder comes from this library https://github.com/c-rack/cbor-java
final List<DataItem> dataItems = new CborDecoder(new ByteArrayInputStream(cborEncoded)).decode();
// In here you can see the contents, but the value will be something like:
// Data items: [{ data: [{ value: co.nstant.in.cbor.model.ByteString@a8b5c07a,
// bucket: co.nstant.in.cbor.model.ByteString@f812097d },
// { value: co.nstant.in.cbor.model.ByteString@a8b5dfc0,
// bucket: co.nstant.in.cbor.model.ByteString@f8120934 }], operation: histogram }]
Log.d("Data items : " + dataItems);
// In order to see the value for bucket and value, you can traverse the data
// and get their values, something like this:
final Map payload = (Map) dataItems.get(0);
final Array payloadArray = (Array) payload.get(new UnicodeString("data"));
payloadArray.getDataItems().forEach(i -> {
BigInteger value = new BigInteger(((ByteString) ((Map)i).get(new UnicodeString("value"))).getBytes());
BigInteger bucket = new BigInteger(((ByteString) ((Map)i).get(new UnicodeString("bucket"))).getBytes());
Log.d("value : " + value + " ;bucket : " + bucket);
});
Attribution-Reporting-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
}
}
trigger_specs
را به JSON در Attribution-Reporting-Register-Source
اضافه خواهیم کرد.{
// A trigger spec is a set of matching criteria, along with a scheme to
// generate bucketized output based on accumulated values across multiple
// triggers within the specified event_report_window. There will be a limit on
// the number of specs possible to define for a source.
"trigger_specs": [{
// This spec will only apply to registrations that set one of the given
// trigger data values (non-negative integers) in the list.
// trigger_data will still appear in the event-level report.
"trigger_data": [<int>, ...]
// Represents a series of time windows, starting at the source registration
// time. Reports for this spec will be delivered an hour after the end of
// each window. Time is encoded as seconds after source registration.
// end_times must consist of strictly increasing positive integers.
//
// Note: specs with identical trigger_data cannot have overlapping windows;
// this ensures that triggers match at most one spec. If
// event_report_windows is omitted, will use the "event_report_window" or
// "event_report_windows" field specified at the global level for the source
// (or the default windows if none are specified). End time is exclusive.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...],
}
// Represents an operator that summarizes the triggers within a window
// count: number of triggers attributed within a window
// value_sum: sum of the value of triggers within a window
// The summary is reported as an index into a bucketization scheme. Defaults
// to "count"
"summary_window_operator": <one of "count" or "value_sum">,
// Represents a bucketization of the integers from [0, MAX_INT], encoded as
// a list of integers where new buckets begin (excluding 0 which is
// implicitly included).
// It must consist of strictly increasing positive integers.
//
// e.g. [5, 10, 100] encodes the following ranges:
// [[0, 4], [5, 9], [10, 99], [100, MAX_INT]]
//
// At the end of each reporting window, triggers will be summarized into an
// integer which slots into one of these ranges. Reports will be sent for
// every new range boundary that is crossed. Reports will never be sent for
// the range that includes 0, as every source is initialized in this range.
//
// If omitted, then represents a trivial mapping
// [1, 2, ... , MAX_INT]
// With MAX_INT being the maximum int value defined by the browser.
"summary_buckets": [<bucket start>, ...]
}, {
// Next trigger_spec
} ...],
// See description in phase 1.
"max_event_level_reports": <int>
// See description in phase 1.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...]
}
}
trigger_data
مشخص شده در trigger_specs
دارند ، مطابقت دارد. به عبارت دیگر ، اگر ماشه با این منبع مطابقت داشته باشد اما trigger_data
آن یکی از مقادیر موجود در پیکربندی منبع نیست ، ماشه نادیده گرفته می شود.event_report_windows
). توجه داشته باشید که این ماشه با وجود عدم موفقیت در معیارهای دو مسابقه که قبلاً ذکر شد ، می تواند با منبع گزارش های قابل جمع شدن مطابقت داشته باشد.value
را مشخص کنند که برای یک مشخصات خاص خلاصه می شود ، اما به عنوان یک مقدار سطل گزارش شده است.event_trigger_data
پشتیبانی می کند.{
"event_trigger_data": [
{
"trigger_data": "2",
"value": 100, // Defaults to 1
"filters": ...
},
...
]
}
event_reporting_window
event_trigger_data
در مشخصات مشخص کنید. سطح بالا event_reporting_windows
به عنوان یک مقدار پیش فرض عمل می کند در صورتی که هرگونه ویژگی ماشه از دست رفته event_report_windows
Sub-Field باشد.value
افزایش می یابد.event_report_window
برای مشخصات مشخص شود ، ما مقدار خلاصه آن را به یک سطل ترسیم می کنیم و برای هر افزایش در سطل خلاصه ناشی از مقادیر ماشه نسبت داده شده ، گزارش سطح رویداد را ارسال می کنیم. گزارش ها با یک قسمت اضافی ، trigger_summary_bucket
ارائه می شود.{
...
"trigger_summary_bucket": [<bucket start>, <bucket end>],
}
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1],
"event_report_windows": {
"end_times": [<30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1],
}],
"max_event_level_reports": 1,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3, 4, 5, 6, 7],
"event_report_windows": {
"end_times": [<2 days>, <7 days>, <30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3],
}],
"max_event_level_reports": 3,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
trigger_data
به مقدار دیگری غیر از 0 تنظیم کند ، برای انتساب واجد شرایط نیست.{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
"end_times": [604800, 1209600] // 7 days, 14 days represented in seconds
},
"summary_window_operator": "value_sum",
"summary_buckets": [5, 10, 100]
}],
}
value
، که خلاصه و سطل می شوند ، ثبت شوند. به عنوان مثال اگر در طی 7 روز از ثبت نام منبع با مقادیر 1 ، 3 و 4 سه محرک وجود داشته باشد.{ "event_trigger_data": [{"trigger_data": "0", "value": 1}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 3}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 4}] }
// Report 1
{
...
"trigger_summary_bucket": [5, 9]
}
{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }
// Report 2
{
...
"trigger_summary_bucket": [10, 99]
},
// Report 3
{
...
"trigger_summary_bucket": [100, MAX_INT]
}
{
"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]
}
trigger_data
به مقدار دیگری غیر از 0 تنظیم کند ، برای انتساب واجد شرایط نیست. به همین دلیل این مورد استفاده به عنوان باینری گفته می شود.{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
// 1 day, 2 days, 3 days, 5 days, 7 days, 10 days represented in seconds
"end_times": [86400, 172800, 259200, 432000, 604800, 864000]
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1]
}],
}
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
{
"trigger_specs": [
{
"trigger_data": [4, 5, 6, 7],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
aggregation_keys
در منابع ثبت شده خود که قصد دارند با فناوری های تبلیغاتی شریک به اشتراک بگذارند ، انتخاب کنند. این کلیدها را می توان در قسمت اختیاری shared_aggregation_keys
، واقع در زیر منبع ثبت نام منبع Attribution-Reporting-Register-Source
اعلام کرد:"shared_aggregation_keys": ["[key name1]", "[key name2]"]
Attribution-Reporting-Register-Trigger
تولید می شوند: // Specifies the configuration based on which derived sources should be
// generated. Those derived sources will be included for source matching at the
// time of attribution. For example, if adtech2 is registering a trigger with an
// attribution_config with source_network as adtech1, available sources
// registered by adtech1 will be considered with additional filtering criteria
// applied to that set as mentioned in the attribution_config. Derived
// sources can have different values to priority, post_install_exclusivity_window
// etc.
"attribution_config": [
{
// Derived sources are created from this adtech's registered sources
"source_network": "[original source's adtech enrollment ID]",
//(optional) Filter sources whose priority falls in this range
"source_priority_range": {
"start": [priority filter lower bound],
"end": [priority filter upper bound]
},
// (optional) Filter sources whose at least one of filter maps matches these
// filters
"source_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Filter sources whose none of filter map matches these
// filters
"source_not_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Apply this priority to the generated derived sources
"priority": "[64 bit signed integer]",
// (optional) The derived source will have expiry set as this or parent
// source's, whichever is earlier
"expiry": "[64 bit signed integer]",
// (optional) set on the derived source
"filter_data": {
"key name 1": ["key1 value 1"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "[64-bit unsigned integer]"
}
]
"attribution_config": [
{
"source_network": "adtech1-enrollment-id",
"source_priority_range": {
"start": 50,
"end": 100
},
"source_filters": {
"source_type": ["NAVIGATION"]
},
"source_not_filters": {
"product_id": ["789"]
},
"priority": "30",
"expiry": "78901",
// (optional) set on the derived source
"filter_data": {
"product_id": ["1234"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "7890"
}
]
x_network_bit_mapping
: شناسه ثبت نام به نقشه برداری بیت شناسه آگهی تبلیغاتیx_network_data
: افست (شیفت سمت چپ) برای برنده شدن در زمینه تبلیغات x_network_bit_mapping
یا عملیات با قطعه کلید ماشه"Attribution-Reporting-Register-Trigger": {
"attribution_config": [...],
"aggregatable_trigger_data": [
{
"key_piece": "0x400",
"source_keys": ["campaignCounts"]
"x_network_data" : {
"key_offset" : 12 // [64 bit unsigned integer]
}
}
…
]
…
"x_network_bit_mapping": {
// This mapping is used to generate trigger key pieces with AdTech identifier
// bits. eg. If AdTechA's sources wins the attribution then 0x1 here will be
// OR'd with the trigger key pieces to generate the final key piece.
"AdTechA-enrollment_id": "0x1", // Identifier bits in hex for A
"AdTechB-enrollment_id": "0x2" // Identifier bits in hex for B
}
…
}
key_piece
: 0x400 (010000000000)
key_offset
: 12
enrollment_id
Adtechb: 2 (010)
(از x_network_bit_mapping
)0x400 | 0x2 << 12 = 0x2400
https://adtech.example/attribution_source
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 شرکای فناوری تبلیغاتی باشد ، API گزارشگر انتساب سپس درخواست مشابهی را برای هر URI ایجاد می کند. هر شریک AD Tech باید سرور را پیکربندی کند که با این هدرها پاسخ دهد: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.
https://adtech.example/attribution_trigger
// 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
campaignCounts
14 کاراکتر است ، بنابراین یک شناسه کلید جمع آوری معتبر است و 1234
4 نویسه است ، بنابراین یک رشته فیلتر معتبر است. اگر یک شناسه کلید جمع آوری یا رشته فیلتر از 25 کاراکتر فراتر رود ، ماشه نادیده گرفته می شود.Attribution-Reporting-Redirect
حاوی URI از شرکای فناوری تبلیغاتی باشد ، API گزارش انتساب سپس درخواست مشابهی را برای هر URI ایجاد می کند. هر شریک AD Tech باید سرور را پیکربندی کند که با این هدرها پاسخ دهد:// 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.
https://adtech.example/.well-known/attribution-reporting/report-event-attribution
{
"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]",
}
https://adtech.example/.well-known/attribution-reporting/report-aggregate-attribution
{
// 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]"
}
adb shell device_config put adservices ppapi_app_allow_list \"\*\"
adb shell device_config put adservices disable_measurement_enrollment_check "true"
ACCESS_ADSERVICES_ATTRIBUTION
را در پرونده مانیفست Android خود قرار دهید و یک پیکربندی خدمات تبلیغاتی را برای برنامه خود ایجاد کنید تا از API های گزارشگری Attribution استفاده کنید:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
ACCESS_ADSERVICES_AD_ID
را در پرونده مانیفست اندرویدی خود قرار دهید:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />
<application>
مانیفست خود ارجاع دهید:<property android:name="android.adservices.AD_SERVICES_CONFIG"
android:resource="@xml/ad_services_config" />
res/xml/ad_services_config.xml
مشخص کنید. در مورد مجوزهای خدمات تبلیغاتی و کنترل دسترسی SDK بیشتر بدانید.<ad-services-config>
<attribution allowAllToAccess="true" />
</ad-services-config>
MeasurementManager
روش هایی را برای کمک به شما در ثبت وقایع منبع انتساب و محرک های تبدیل به شما کمک می کند.registerSource()
تماس می گیرد.onClick()
ثبت می کنید. رویداد ماشه مربوطه معمولاً به زودی پس از رویداد کلیک اتفاق می افتد. این نوع رویداد اطلاعات بیشتری در مورد تعامل کاربر ارائه می دهد و بنابراین نوع خوبی از منبع انتساب برای اولویت بالایی است.onAdShown()
ثبت می کنید. رویداد ماشه مربوطه ممکن است ساعات یا چند روز پس از رویداد مشاهده رخ دهد. 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)
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);
attributionSourceUri
صادر می کند. پاسخ نقطه پایانی شامل مقادیر destination, source_event_id, expiry
و source_priority
است.registerSource
و registerTrigger
اضافه شده است. علاوه بر عنوان ثبت نام ، مصرف کننده API هم اکنون می تواند HTTP را به عنوان پاسخ سرور که شامل یک کد وضعیت 302 و یک هدر "مکان" با URL بعدی برای بازدید برای ثبت نام اضافی است ، ارائه دهد.registerTrigger()
in your app: 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)
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)
attributionTriggerUri
. The endpoint's response includes values for event and aggregate reports.registerWebSource()
or registerWebTrigger()
.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)
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);
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)
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);
coarse_event_report_destinations
field under the Attribution-Reporting-Register-Source
header to reduce noise. If a source with the coarse_event_report_destinations
field specified wins attribution, the resulting report includes both app and web destinations without distinction as to where the actual trigger occurred.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"
}],
}
https://advertiser.com
:Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
"trigger_data": "2",
"priority": "2"
}],
}
{
"attribution_destination": ["android-app://com.advertiser.example,https://advertiser.com"],
"scheduled_report_time": "800176400",
"source_event_id": "53234",
"trigger_data": "1",
// Can be "event" if source were registered by user viewing the ad
"source_type": "navigation",
// Would be 0.0170218 without coarse_event_report_destinations as true in the source
"randomized_trigger_rate": 0.0024263
}
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
JobScheduler: executeRunCommand(): com.google.android.adservices.api/0 5 s=false f=true
debug_cleartext_payload
field holds an unencrypted version of your aggregate report. While this version of your report is unencrypted, it still needs to be decoded.debug_cleartext_payload
field in two steps: the first using Base 64 decoding, and the second using CBOR decoding.String base64DebugPayload = "omRkYXRhgqJldmFsdWVEAAAGgGZidWNrZXRQAAAAAAAAAAAAAAAAAAAKhaJldmFsdWVEAACAAGZidWNrZXRQAAAAAAAAAAAAAAAAAAAFWWlvcGVyYXRpb25paGlzdG9ncmFt";
byte[] cborEncoded = Base64.getDecoder().decode(base64DebugPayload);
// CbodDecoder comes from this library https://github.com/c-rack/cbor-java
final List<DataItem> dataItems = new CborDecoder(new ByteArrayInputStream(cborEncoded)).decode();
// In here you can see the contents, but the value will be something like:
// Data items: [{ data: [{ value: co.nstant.in.cbor.model.ByteString@a8b5c07a,
// bucket: co.nstant.in.cbor.model.ByteString@f812097d },
// { value: co.nstant.in.cbor.model.ByteString@a8b5dfc0,
// bucket: co.nstant.in.cbor.model.ByteString@f8120934 }], operation: histogram }]
Log.d("Data items : " + dataItems);
// In order to see the value for bucket and value, you can traverse the data
// and get their values, something like this:
final Map payload = (Map) dataItems.get(0);
final Array payloadArray = (Array) payload.get(new UnicodeString("data"));
payloadArray.getDataItems().forEach(i -> {
BigInteger value = new BigInteger(((ByteString) ((Map)i).get(new UnicodeString("value"))).getBytes());
BigInteger bucket = new BigInteger(((ByteString) ((Map)i).get(new UnicodeString("bucket"))).getBytes());
Log.d("value : " + value + " ;bucket : " + bucket);
});
Attribution-Reporting-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
}
}
trigger_specs
to the JSON in 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
values in the trigger_specs
. In other words, if the trigger would have matched this source but its trigger_data
is not one of the values in the source's configuration, the trigger is ignored.event_report_windows
). Note that the trigger could still be matched with a source for aggregatable reports despite failing the two match criteria mentioned earlier.value
parameter that gets summed up for a particular spec, but reported as a bucketed value.event_trigger_data
.{
"event_trigger_data": [
{
"trigger_data": "2",
"value": 100, // Defaults to 1
"filters": ...
},
...
]
}
event_trigger_data
on the spec to find a match, using the spec's event_reporting_window
. The top level event_reporting_windows
acts as a default value in case any trigger spec is the missing event_report_windows
sub-field.value
.event_report_window
for a spec completes, we will map its summary value to a bucket, and send an event-level report for every increment in the summary bucket caused by attributed trigger values. Reports will come with one extra field, trigger_summary_bucket
.{
...
"trigger_summary_bucket": [<bucket start>, <bucket end>],
}
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1],
"event_report_windows": {
"end_times": [<30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1],
}],
"max_event_level_reports": 1,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3, 4, 5, 6, 7],
"event_report_windows": {
"end_times": [<2 days>, <7 days>, <30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3],
}],
"max_event_level_reports": 3,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
trigger_data
to a value other than 0 is ineligible for attribution.{
"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
field set, which are summed up and bucketed. For example if there are three triggers within 7 days of source registrations with values 1, 3 and 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}] }
// Report 1
{
...
"trigger_summary_bucket": [5, 9]
}
{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }
// Report 2
{
...
"trigger_summary_bucket": [10, 99]
},
// Report 3
{
...
"trigger_summary_bucket": [100, MAX_INT]
}
{
"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
set to 0 are counted and capped at 10. The trigger value is ignored since summary_window_operator
is set to count. If 4 triggers are registered and attributed to the source, the report would look like this:// 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]
}
trigger_data
to a value other than 0 is ineligible for attribution. This is why this use case is referred to as binary .{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
// 1 day, 2 days, 3 days, 5 days, 7 days, 10 days represented in seconds
"end_times": [86400, 172800, 259200, 432000, 604800, 864000]
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1]
}],
}
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
{
"trigger_specs": [
{
"trigger_data": [4, 5, 6, 7],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
aggregation_keys
in their registered sources that they intend to share with partner ad techs. These keys can be declared in the optional shared_aggregation_keys
field, located under the source registration header Attribution-Reporting-Register-Source
:"shared_aggregation_keys": ["[key name1]", "[key name2]"]
Attribution-Reporting-Register-Trigger
: // Specifies the configuration based on which derived sources should be
// generated. Those derived sources will be included for source matching at the
// time of attribution. For example, if adtech2 is registering a trigger with an
// attribution_config with source_network as adtech1, available sources
// registered by adtech1 will be considered with additional filtering criteria
// applied to that set as mentioned in the attribution_config. Derived
// sources can have different values to priority, post_install_exclusivity_window
// etc.
"attribution_config": [
{
// Derived sources are created from this adtech's registered sources
"source_network": "[original source's adtech enrollment ID]",
//(optional) Filter sources whose priority falls in this range
"source_priority_range": {
"start": [priority filter lower bound],
"end": [priority filter upper bound]
},
// (optional) Filter sources whose at least one of filter maps matches these
// filters
"source_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Filter sources whose none of filter map matches these
// filters
"source_not_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Apply this priority to the generated derived sources
"priority": "[64 bit signed integer]",
// (optional) The derived source will have expiry set as this or parent
// source's, whichever is earlier
"expiry": "[64 bit signed integer]",
// (optional) set on the derived source
"filter_data": {
"key name 1": ["key1 value 1"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "[64-bit unsigned integer]"
}
]
"attribution_config": [
{
"source_network": "adtech1-enrollment-id",
"source_priority_range": {
"start": 50,
"end": 100
},
"source_filters": {
"source_type": ["NAVIGATION"]
},
"source_not_filters": {
"product_id": ["789"]
},
"priority": "30",
"expiry": "78901",
// (optional) set on the derived source
"filter_data": {
"product_id": ["1234"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "7890"
}
]
x_network_bit_mapping
: Enrollment id to ad tech identifier bit mappingx_network_data
: Offset (left shift) for the winning ad tech's x_network_bit_mapping
OR operation with the trigger key piece"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
}
…
}
key_piece
: 0x400 (010000000000)
key_offset
: 12
enrollment_id
value: 2 (010)
(from x_network_bit_mapping
)0x400 | 0x2 << 12 = 0x2400