همانطور که در اسناد Android Sandbox Privacy می خوانید، از دکمه Developer Preview یا Beta برای انتخاب نسخه برنامه ای که با آن کار می کنید استفاده کنید، زیرا ممکن است دستورالعمل ها متفاوت باشد.
Attribution Reporting API برای ارائه بهبود حریم خصوصی کاربر با حذف اتکا به شناسههای کاربر بین حزبی و پشتیبانی از موارد استفاده کلیدی برای اندازهگیری اسناد و تبدیل در بین برنامهها طراحی شده است. این راهنمای توسعهدهنده نحوه پیکربندی و آزمایش APIهای گزارش Attribution را برای ثبت کلیکها، بازدیدها و تبدیلهای تبلیغاتی با فراخوانی روشهایی که محرکها و منابع مربوطه را برای چنین رویدادهایی ثبت میکنند، شرح میدهد.
این راهنما به شما می آموزد که چگونه نقاط پایانی سرور را تنظیم کنید و یک برنامه مشتری بسازید که این خدمات را فراخوانی کند. درباره طراحی کلی Attribution Reporting API در طرح پیشنهادی بیشتر بیاموزید.
شرایط کلیدی
- منابع انتساب به کلیک ها یا بازدیدها اشاره دارد.
- محرک ها رویدادهایی هستند که می توانند به تبدیل ها نسبت داده شوند.
- گزارشها حاوی دادههایی درباره یک ماشه و منبع انتساب مربوطه هستند. این گزارش ها در پاسخ به رویدادهای محرک ارسال می شوند. Attribution Reporting API از گزارشهای سطح رویداد و گزارشهای جمعآوریشده پشتیبانی میکند.
قبل از شروع
برای استفاده از Attribution Reporting API، وظایف سمت سرور و سمت سرویس گیرنده فهرست شده در بخشهای زیر را تکمیل کنید.
نقاط پایانی API Reporting Attribution را تنظیم کنید
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 : پیکربندی سطح رویداد انعطاف پذیر Lite. زیر مجموعه ای از فاز 2
- فاز 2 : نسخه کامل پیکربندی سطح رویداد انعطاف پذیر.
مرحله 1: سطح رویداد انعطاف پذیر Lite
ما دو پارامتر اختیاری زیر را در 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
}
}
فاز 2: سطح رویداد کاملا انعطاف پذیر
علاوه بر پارامترهایی که در فاز 1 اضافه شدند، یک پارامتر اختیاری trigger_specs
به JSON در Attribution-Reporting-Register-Source
اضافه می کنیم.
{
// A trigger spec is a set of matching criteria, along with a scheme to
// generate bucketized output based on accumulated values across multiple
// triggers within the specified event_report_window. There will be a limit on
// the number of specs possible to define for a source.
"trigger_specs": [{
// This spec will only apply to registrations that set one of the given
// trigger data values (non-negative integers) in the list.
// trigger_data will still appear in the event-level report.
"trigger_data": [<int>, ...]
// Represents a series of time windows, starting at the source registration
// time. Reports for this spec will be delivered an hour after the end of
// each window. Time is encoded as seconds after source registration.
// end_times must consist of strictly increasing positive integers.
//
// Note: specs with identical trigger_data cannot have overlapping windows;
// this ensures that triggers match at most one spec. If
// event_report_windows is omitted, will use the "event_report_window" or
// "event_report_windows" field specified at the global level for the source
// (or the default windows if none are specified). End time is exclusive.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...],
}
// Represents an operator that summarizes the triggers within a window
// count: number of triggers attributed within a window
// value_sum: sum of the value of triggers within a window
// The summary is reported as an index into a bucketization scheme. Defaults
// to "count"
"summary_window_operator": <one of "count" or "value_sum">,
// Represents a bucketization of the integers from [0, MAX_INT], encoded as
// a list of integers where new buckets begin (excluding 0 which is
// implicitly included).
// It must consist of strictly increasing positive integers.
//
// e.g. [5, 10, 100] encodes the following ranges:
// [[0, 4], [5, 9], [10, 99], [100, MAX_INT]]
//
// At the end of each reporting window, triggers will be summarized into an
// integer which slots into one of these ranges. Reports will be sent for
// every new range boundary that is crossed. Reports will never be sent for
// the range that includes 0, as every source is initialized in this range.
//
// If omitted, then represents a trivial mapping
// [1, 2, ... , MAX_INT]
// With MAX_INT being the maximum int value defined by the browser.
"summary_buckets": [<bucket start>, ...]
}, {
// Next trigger_spec
} ...],
// See description in phase 1.
"max_event_level_reports": <int>
// See description in phase 1.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...]
}
}
این پیکربندی فضای خروجی گزارشهای سطح رویداد را بهازای ثبت منبع، کاملاً مشخص میکند. برای هر مشخصات ماشه، ما به طور کامل مشخص می کنیم:
- مجموعه ای از معیارهای تطبیق:
- این مشخصات برای کدام داده های ماشه خاص اعمال می شود. این منبع فقط با محرک هایی که یکی از مقادیر
trigger_data
مشخص شده درtrigger_specs
را دارند، واجد شرایط مطابقت است. به عبارت دیگر، اگر تریگر با این منبع مطابقت داشت اماtrigger_data
آن یکی از مقادیر موجود در پیکربندی منبع نباشد، ماشه نادیده گرفته میشود. - هنگامی که یک ماشه خاص با این مشخصات مطابقت دارد (با استفاده از
event_report_windows
). توجه داشته باشید که علیرغم عدم موفقیت در دو معیار تطبیق ذکر شده در بالا، باز هم میتوان ماشه را با منبعی برای گزارشهای جمعآوری مطابقت داد.
- این مشخصات برای کدام داده های ماشه خاص اعمال می شود. این منبع فقط با محرک هایی که یکی از مقادیر
- یک الگوریتم خاص برای خلاصه کردن و سطلبندی تمام محرکها در یک پنجره اسناد. این به تریگرها اجازه می دهد تا پارامتر
value
را مشخص کنند که برای یک مشخصات خاص خلاصه می شود، اما به عنوان یک مقدار سطلی گزارش می شود.
تریگرها همچنین از افزودن یک پارامتر مقدار اختیاری در فرهنگ لغت در event_trigger_data
پشتیبانی میکنند.
{
"event_trigger_data": [
{
"trigger_data": "2",
"value": 100, // Defaults to 1
"filters": ...
},
...
]
}
هر ثبت ماشه حداکثر با یک مشخصات ماشه مطابقت دارد و مقدار خلاصه مربوط به آن را به روز می کند. در سطح بالا، در زمان شروع ما:
- فیلترهای ارجاع جهانی را اعمال کنید.
- برای هر مشخصات ماشه،
event_trigger_data
را روی مشخصات ارزیابی کنید تا با استفاده ازevent_reporting_window
spec، مطابقت را پیدا کنید.event_reporting_windows
سطح بالا به عنوان یک مقدار پیشفرض عمل میکند در صورتی که هر یک از مشخصات ماشه، قسمت فرعیevent_report_windows
از دست رفته باشد. - اولین مشخصات منطبق برای انتساب انتخاب میشود و مقدار خلاصه با
value
افزایش مییابد.
هنگامی که event_report_window
برای یک مشخصات کامل شد، مقدار خلاصه آن را به یک سطل نگاشت میکنیم و گزارشی در سطح رویداد برای هر افزایش در سطل خلاصه ناشی از مقادیر ماشه نسبت داده شده ارسال میکنیم. گزارشها با یک فیلد اضافی ارائه میشوند، trigger_summary_bucket
.
{
...
"trigger_summary_bucket": [<bucket start>, <bucket end>],
}
تنظیماتی که معادل نسخه فعلی هستند
موارد زیر به ترتیب پیکربندیهای معادل رویداد فعلی و منابع ناوبری APIها هستند. به خصوص برای منابع ناوبری، این نشان می دهد که چرا سطوح نویز نسبت به منابع رویداد بسیار زیاد است تا مقادیر اپسیلون یکسانی حفظ شود: منابع ناوبری فضای خروجی بسیار بزرگتری دارند.
با توجه به اینکه برخی از پارامترها را می توان به عنوان پیش فرض یا هرس کرد، ممکن است چندین پیکربندی معادل وجود داشته باشد.
منابع رویداد معادل
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1],
"event_report_windows": {
"end_times": [<30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1],
}],
"max_event_level_reports": 1,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
منابع ناوبری معادل
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3, 4, 5, 6, 7],
"event_report_windows": {
"end_times": [<2 days>, <7 days>, <30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3],
}],
"max_event_level_reports": 3,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
نمونه تنظیمات سفارشی
در زیر برخی از تنظیمات اضافی خارج از تنظیمات پیش فرض وجود دارد. در همه این مثال ها، مبادلات توسعه دهنده عبارتند از:
- کاهش برخی از ابعاد پیکربندی پیشفرض (#تریگرها، کاردینالیته دادههای ماشه، #پنجرهها) برای افزایش یکی دیگر برای حفظ سطح نویز
- کاهش برخی از ابعاد پیکربندی پیشفرض (#تریگرها، کاردینالیته دادههای ماشه، #پنجرهها) برای کاهش سطح نویز
سطلهای مقدار ماشه را گزارش کنید
این پیکربندی مثال از توسعهدهندهای پشتیبانی میکند که میخواهد دادههای ارزش را تنها برای یک پنجره گزارش (مثلاً 7 روز) بهینه کند، و پنجرههای گزارش کمتری را با نویز کمتر معامله کند. در این مثال، هر عاملی که trigger_data
روی مقداری غیر از 0 تنظیم کند، برای انتساب واجد شرایط نیست.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
"end_times": [604800, 1209600] // 7 days, 14 days represented in seconds
},
"summary_window_operator": "value_sum",
"summary_buckets": [5, 10, 100]
}],
}
تریگرها را می توان با مجموعه فیلد value
ثبت کرد که خلاصه و سطل می شود. به عنوان مثال، اگر در عرض 7 روز پس از ثبت منبع، سه راهانداز با مقادیر 1، 3 و 4 وجود داشته باشد.
{ "event_trigger_data": [{"trigger_data": "0", "value": 1}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 3}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 4}] }
مقادیر به 8 جمع می شوند و پس از 7 روز + 1 ساعت در گزارش های زیر گزارش می شوند:
// Report 1
{
...
"trigger_summary_bucket": [5, 9]
}
در 7 روز بعدی، محرک های زیر ثبت می شوند:
{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }
مقادیر به 8 + 50 + 45 = 103 جمع می شوند. این گزارشات زیر را در 14 روز + 1 ساعت به دست می دهد:
// Report 2
{
...
"trigger_summary_bucket": [10, 99]
},
// Report 3
{
...
"trigger_summary_bucket": [100, MAX_INT]
}
تعداد ماشه ها را گزارش کنید
این مثال نشان میدهد که چگونه یک توسعهدهنده میتواند یک منبع را پیکربندی کند تا تعداد محرکها را تا 10 دریافت کند.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
"end_times": [604800] // 7 days represented in seconds
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}],
}
محرکهای منتسب با trigger_data
روی 0 شمارش میشوند و روی 10 محدود میشوند. از آنجایی که summary_window_operator
برای شمارش تنظیم شده است، مقدار ماشه نادیده گرفته میشود. اگر 4 محرک ثبت شده و به منبع نسبت داده شود، گزارش به شکل زیر خواهد بود:
// Report 1
{
...
"trigger_summary_bucket": [1, 1]
}
// Report 2
{
...
"trigger_summary_bucket": [2, 2]
}
// Report 3
{
...
"trigger_summary_bucket": [3, 3]
}
// Report 4
{
...
"trigger_summary_bucket": [4, 4]
}
باینری با گزارش های مکرر
این پیکربندی مثال از توسعهدهندهای پشتیبانی میکند که میخواهد بداند که آیا حداقل یک تبدیل در 10 روز اول اتفاق افتاده است یا نه (بدون توجه به مقدار)، اما میخواهد گزارشها را در فواصل زمانی بیشتر از پیشفرض دریافت کند. مجدداً، در این مثال، هر راهاندازی که trigger_data
روی مقداری غیر از 0 تنظیم کند، برای انتساب واجد شرایط نیست. به همین دلیل است که این مورد استفاده باینری نامیده می شود.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
// 1 day, 2 days, 3 days, 5 days, 7 days, 10 days represented in seconds
"end_times": [86400, 172800, 259200, 432000, 604800, 864000]
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1]
}],
}
مشخصات ماشه را از منبعی به منبع دیگر تغییر دهید
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
{
"trigger_specs": [
{
"trigger_data": [4, 5, 6, 7],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
ما توسعهدهندگان را تشویق میکنیم موارد استفاده متفاوتی را که ممکن است برای این برنامه افزودنی API داشته باشند پیشنهاد کنند، و این توضیحدهنده را با پیکربندیهای نمونه برای آن موارد استفاده بهروزرسانی میکنیم.
انتساب شبکه بدون تغییر مسیر
فنآوران تبلیغات باید از تغییر مسیرها برای ثبت چندین راهانداز منبع انتساب و انجام اسناد بین شبکهای استفاده کنند. این ویژگی به پشتیبانی از انتساب بین شبکهای کمک میکند که در آن تغییر مسیرها در سراسر شبکهها امکانپذیر نیست. بیشتر بدانید .
فناوری های تبلیغاتی می توانند پیکربندی را در پاسخ ثبت ماشه ارسال کنند که بر اساس آن منابع ثبت شده توسط سایر فناوری های تبلیغاتی برای تولید منابع مشتق شده انتخاب می شوند. این منابع مشتق شده سپس برای انتساب استفاده می شوند. اگر ماشه به یک منبع مشتق شده نسبت داده شود، گزارشهای انبوه تولید میشوند. تولید گزارش رویداد برای منابع مشتق شده پشتیبانی نمی شود.
فناوریهای تبلیغاتی میتوانند از میان aggregation_keys
در منابع ثبتشده خود که قصد دارند با فنآوران تبلیغات شریک به اشتراک بگذارند، انتخاب کنند. این کلیدها را می توان در قسمت اختیاری shared_aggregation_keys
که در زیر سرصفحه ثبت منبع Attribution-Reporting-Register-Source
قرار دارد، اعلام کرد:
"shared_aggregation_keys": ["[key name1]", "[key name2]"]
منابع مشتق شده بر اساس پیکربندی تحت عنوان هدر ثبت ماشه Attribution-Reporting-Register-Trigger
تولید می شوند:
// Specifies the configuration based on which derived sources should be
// generated. Those derived sources will be included for source matching at the
// time of attribution. For example, if adtech2 is registering a trigger with an
// attribution_config with source_network as adtech1, available sources
// registered by adtech1 will be considered with additional filtering criteria
// applied to that set as mentioned in the attribution_config. Derived
// sources can have different values to priority, post_install_exclusivity_window
// etc.
"attribution_config": [
{
// Derived sources are created from this adtech's registered sources
"source_network": "[original source's adtech enrollment ID]",
//(optional) Filter sources whose priority falls in this range
"source_priority_range": {
"start": [priority filter lower bound],
"end": [priority filter upper bound]
},
// (optional) Filter sources whose at least one of filter maps matches these
// filters
"source_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Filter sources whose none of filter map matches these
// filters
"source_not_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Apply this priority to the generated derived sources
"priority": "[64 bit signed integer]",
// (optional) The derived source will have expiry set as this or parent
// source's, whichever is earlier
"expiry": "[64 bit signed integer]",
// (optional) set on the derived source
"filter_data": {
"key name 1": ["key1 value 1"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "[64-bit unsigned integer]"
}
]
در اینجا نسخه ای با مقادیر نمونه اضافه شده است:
"attribution_config": [
{
"source_network": "adtech1-enrollment-id",
"source_priority_range": {
"start": 50,
"end": 100
},
"source_filters": {
"source_type": ["NAVIGATION"]
},
"source_not_filters": {
"product_id": ["789"]
},
"priority": "30",
"expiry": "78901",
// (optional) set on the derived source
"filter_data": {
"product_id": ["1234"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "7890"
}
]
دو فیلد اختیاری جدید برای شروع هدر ثبت اضافه شده است. این فیلدها شناسه فناوری تبلیغات برنده را در کلیدهای گزارش انبوهی فعال میکنند:
-
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
}
…
}
در اینجا محاسبه قطعه کلید ماشه در هنگام ایجاد گزارش برای منبع AdTechB آمده است:
-
key_piece
:0x400 (010000000000)
-
key_offset
:12
- مقدار
enrollment_id
AdtechB:2 (010)
(ازx_network_bit_mapping
) - قطعه کلید ماشه نتیجه:
0x400 | 0x2 << 12 = 0x2400
محدودیت ها
برای فهرستی از قابلیتهای در حال پیشرفت برای زمان اجرا 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، وظایف سمت سرور و سمت سرویس گیرنده فهرست شده در بخشهای زیر را تکمیل کنید.
نقاط پایانی API Reporting Attribution را تنظیم کنید
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 : پیکربندی سطح رویداد انعطاف پذیر Lite. زیر مجموعه ای از فاز 2
- فاز 2 : نسخه کامل پیکربندی سطح رویداد انعطاف پذیر.
مرحله 1: سطح رویداد انعطاف پذیر Lite
ما دو پارامتر اختیاری زیر را در 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
}
}
فاز 2: سطح رویداد کاملا انعطاف پذیر
علاوه بر پارامترهایی که در فاز 1 اضافه شدند، یک پارامتر اختیاری trigger_specs
به JSON در Attribution-Reporting-Register-Source
اضافه می کنیم.
{
// A trigger spec is a set of matching criteria, along with a scheme to
// generate bucketized output based on accumulated values across multiple
// triggers within the specified event_report_window. There will be a limit on
// the number of specs possible to define for a source.
"trigger_specs": [{
// This spec will only apply to registrations that set one of the given
// trigger data values (non-negative integers) in the list.
// trigger_data will still appear in the event-level report.
"trigger_data": [<int>, ...]
// Represents a series of time windows, starting at the source registration
// time. Reports for this spec will be delivered an hour after the end of
// each window. Time is encoded as seconds after source registration.
// end_times must consist of strictly increasing positive integers.
//
// Note: specs with identical trigger_data cannot have overlapping windows;
// this ensures that triggers match at most one spec. If
// event_report_windows is omitted, will use the "event_report_window" or
// "event_report_windows" field specified at the global level for the source
// (or the default windows if none are specified). End time is exclusive.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...],
}
// Represents an operator that summarizes the triggers within a window
// count: number of triggers attributed within a window
// value_sum: sum of the value of triggers within a window
// The summary is reported as an index into a bucketization scheme. Defaults
// to "count"
"summary_window_operator": <one of "count" or "value_sum">,
// Represents a bucketization of the integers from [0, MAX_INT], encoded as
// a list of integers where new buckets begin (excluding 0 which is
// implicitly included).
// It must consist of strictly increasing positive integers.
//
// e.g. [5, 10, 100] encodes the following ranges:
// [[0, 4], [5, 9], [10, 99], [100, MAX_INT]]
//
// At the end of each reporting window, triggers will be summarized into an
// integer which slots into one of these ranges. Reports will be sent for
// every new range boundary that is crossed. Reports will never be sent for
// the range that includes 0, as every source is initialized in this range.
//
// If omitted, then represents a trivial mapping
// [1, 2, ... , MAX_INT]
// With MAX_INT being the maximum int value defined by the browser.
"summary_buckets": [<bucket start>, ...]
}, {
// Next trigger_spec
} ...],
// See description in phase 1.
"max_event_level_reports": <int>
// See description in phase 1.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...]
}
}
این پیکربندی فضای خروجی گزارشهای سطح رویداد را بهازای ثبت منبع، کاملاً مشخص میکند. برای هر مشخصات ماشه، ما به طور کامل مشخص می کنیم:
- مجموعه ای از معیارهای تطبیق:
- این مشخصات برای کدام داده های ماشه خاص اعمال می شود. این منبع فقط با محرک هایی که یکی از مقادیر
trigger_data
مشخص شده درtrigger_specs
را دارند، واجد شرایط مطابقت است. به عبارت دیگر، اگر تریگر با این منبع مطابقت داشت اماtrigger_data
آن یکی از مقادیر موجود در پیکربندی منبع نباشد، ماشه نادیده گرفته میشود. - هنگامی که یک ماشه خاص با این مشخصات مطابقت دارد (با استفاده از
event_report_windows
). توجه داشته باشید که علیرغم عدم موفقیت در دو معیار تطبیق ذکر شده در بالا، باز هم میتوان ماشه را با منبعی برای گزارشهای جمعآوری مطابقت داد.
- این مشخصات برای کدام داده های ماشه خاص اعمال می شود. این منبع فقط با محرک هایی که یکی از مقادیر
- یک الگوریتم خاص برای خلاصه کردن و سطلبندی تمام محرکها در یک پنجره اسناد. این به تریگرها اجازه می دهد تا پارامتر
value
را مشخص کنند که برای یک مشخصات خاص خلاصه می شود، اما به عنوان یک مقدار سطلی گزارش می شود.
تریگرها همچنین از افزودن یک پارامتر مقدار اختیاری در فرهنگ لغت در event_trigger_data
پشتیبانی میکنند.
{
"event_trigger_data": [
{
"trigger_data": "2",
"value": 100, // Defaults to 1
"filters": ...
},
...
]
}
هر ثبت ماشه حداکثر با یک مشخصات ماشه مطابقت دارد و مقدار خلاصه مربوط به آن را به روز می کند. در سطح بالا، در زمان شروع ما:
- فیلترهای ارجاع جهانی را اعمال کنید.
- برای هر مشخصات ماشه،
event_trigger_data
را روی مشخصات ارزیابی کنید تا با استفاده ازevent_reporting_window
spec، مطابقت را پیدا کنید.event_reporting_windows
سطح بالا به عنوان یک مقدار پیشفرض عمل میکند در صورتی که هر یک از مشخصات ماشه، قسمت فرعیevent_report_windows
از دست رفته باشد. - اولین مشخصات منطبق برای انتساب انتخاب میشود و مقدار خلاصه با
value
افزایش مییابد.
هنگامی که event_report_window
برای یک مشخصات کامل شد، مقدار خلاصه آن را به یک سطل نگاشت میکنیم و گزارشی در سطح رویداد برای هر افزایش در سطل خلاصه ناشی از مقادیر ماشه نسبت داده شده ارسال میکنیم. گزارشها با یک فیلد اضافی ارائه میشوند، trigger_summary_bucket
.
{
...
"trigger_summary_bucket": [<bucket start>, <bucket end>],
}
تنظیماتی که معادل نسخه فعلی هستند
موارد زیر به ترتیب پیکربندیهای معادل رویداد فعلی و منابع ناوبری APIها هستند. به خصوص برای منابع ناوبری، این نشان می دهد که چرا سطوح نویز نسبت به منابع رویداد بسیار زیاد است تا مقادیر اپسیلون یکسانی حفظ شود: منابع ناوبری فضای خروجی بسیار بزرگتری دارند.
با توجه به اینکه برخی از پارامترها را می توان به عنوان پیش فرض یا هرس کرد، ممکن است چندین پیکربندی معادل وجود داشته باشد.
منابع رویداد معادل
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1],
"event_report_windows": {
"end_times": [<30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1],
}],
"max_event_level_reports": 1,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
منابع ناوبری معادل
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3, 4, 5, 6, 7],
"event_report_windows": {
"end_times": [<2 days>, <7 days>, <30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3],
}],
"max_event_level_reports": 3,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
نمونه تنظیمات سفارشی
در زیر برخی از تنظیمات اضافی خارج از تنظیمات پیش فرض وجود دارد. در همه این مثال ها، مبادلات توسعه دهنده عبارتند از:
- کاهش برخی از ابعاد پیکربندی پیشفرض (#تریگرها، کاردینالیته دادههای ماشه، #پنجرهها) برای افزایش یکی دیگر برای حفظ سطح نویز
- کاهش برخی از ابعاد پیکربندی پیشفرض (#تریگرها، کاردینالیته دادههای ماشه، #پنجرهها) برای کاهش سطح نویز
سطلهای مقدار ماشه را گزارش کنید
این پیکربندی مثال از توسعهدهندهای پشتیبانی میکند که میخواهد دادههای ارزش را تنها برای یک پنجره گزارش (مثلاً 7 روز) بهینه کند، و پنجرههای گزارش کمتری را با نویز کمتر معامله کند. در این مثال، هر عاملی که trigger_data
روی مقداری غیر از 0 تنظیم کند، برای انتساب واجد شرایط نیست.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
"end_times": [604800, 1209600] // 7 days, 14 days represented in seconds
},
"summary_window_operator": "value_sum",
"summary_buckets": [5, 10, 100]
}],
}
تریگرها را می توان با مجموعه فیلد value
ثبت کرد که خلاصه و سطل می شود. به عنوان مثال، اگر در عرض 7 روز پس از ثبت منبع، سه راهانداز با مقادیر 1، 3 و 4 وجود داشته باشد.
{ "event_trigger_data": [{"trigger_data": "0", "value": 1}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 3}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 4}] }
مقادیر به 8 جمع می شوند و پس از 7 روز + 1 ساعت در گزارش های زیر گزارش می شوند:
// Report 1
{
...
"trigger_summary_bucket": [5, 9]
}
در 7 روز بعدی، محرک های زیر ثبت می شوند:
{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }
مقادیر به 8 + 50 + 45 = 103 جمع می شوند. این گزارشات زیر را در 14 روز + 1 ساعت به دست می دهد:
// Report 2
{
...
"trigger_summary_bucket": [10, 99]
},
// Report 3
{
...
"trigger_summary_bucket": [100, MAX_INT]
}
تعداد ماشه ها را گزارش کنید
این مثال نشان میدهد که چگونه یک توسعهدهنده میتواند یک منبع را پیکربندی کند تا تعداد محرکها را تا 10 دریافت کند.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
"end_times": [604800] // 7 days represented in seconds
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}],
}
محرکهای منتسب با trigger_data
روی 0 شمارش میشوند و روی 10 محدود میشوند. از آنجایی که summary_window_operator
برای شمارش تنظیم شده است، مقدار ماشه نادیده گرفته میشود. اگر 4 محرک ثبت شده و به منبع نسبت داده شود، گزارش به شکل زیر خواهد بود:
// Report 1
{
...
"trigger_summary_bucket": [1, 1]
}
// Report 2
{
...
"trigger_summary_bucket": [2, 2]
}
// Report 3
{
...
"trigger_summary_bucket": [3, 3]
}
// Report 4
{
...
"trigger_summary_bucket": [4, 4]
}
باینری با گزارش های مکرر
این پیکربندی مثال از توسعهدهندهای پشتیبانی میکند که میخواهد بداند که آیا حداقل یک تبدیل در 10 روز اول اتفاق افتاده است یا نه (بدون توجه به مقدار)، اما میخواهد گزارشها را در فواصل زمانی بیشتر از پیشفرض دریافت کند. مجدداً، در این مثال، هر راهاندازی که trigger_data
روی مقداری غیر از 0 تنظیم کند، برای انتساب واجد شرایط نیست. به همین دلیل است که این مورد استفاده باینری نامیده می شود.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
// 1 day, 2 days, 3 days, 5 days, 7 days, 10 days represented in seconds
"end_times": [86400, 172800, 259200, 432000, 604800, 864000]
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1]
}],
}
مشخصات ماشه را از منبعی به منبع دیگر تغییر دهید
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
{
"trigger_specs": [
{
"trigger_data": [4, 5, 6, 7],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
ما توسعهدهندگان را تشویق میکنیم موارد استفاده متفاوتی را که ممکن است برای این برنامه افزودنی API داشته باشند پیشنهاد کنند، و این توضیحدهنده را با پیکربندیهای نمونه برای آن موارد استفاده بهروزرسانی میکنیم.
انتساب شبکه بدون تغییر مسیر
فنآوران تبلیغات باید از تغییر مسیرها برای ثبت چندین راهانداز منبع انتساب و انجام اسناد بین شبکهای استفاده کنند. این ویژگی به پشتیبانی از انتساب بین شبکهای کمک میکند که در آن تغییر مسیرها در سراسر شبکهها امکانپذیر نیست. بیشتر بدانید .
فناوری های تبلیغاتی می توانند پیکربندی را در پاسخ ثبت ماشه ارسال کنند که بر اساس آن منابع ثبت شده توسط سایر فناوری های تبلیغاتی برای تولید منابع مشتق شده انتخاب می شوند. این منابع مشتق شده سپس برای انتساب استفاده می شوند. اگر ماشه به یک منبع مشتق شده نسبت داده شود، گزارشهای انبوه تولید میشوند. تولید گزارش رویداد برای منابع مشتق شده پشتیبانی نمی شود.
فناوریهای تبلیغاتی میتوانند از میان aggregation_keys
در منابع ثبتشده خود که قصد دارند با فنآوران تبلیغات شریک به اشتراک بگذارند، انتخاب کنند. این کلیدها را می توان در قسمت اختیاری shared_aggregation_keys
که در زیر سرصفحه ثبت منبع Attribution-Reporting-Register-Source
قرار دارد، اعلام کرد:
"shared_aggregation_keys": ["[key name1]", "[key name2]"]
منابع مشتق شده بر اساس پیکربندی تحت عنوان هدر ثبت ماشه Attribution-Reporting-Register-Trigger
تولید می شوند:
// Specifies the configuration based on which derived sources should be
// generated. Those derived sources will be included for source matching at the
// time of attribution. For example, if adtech2 is registering a trigger with an
// attribution_config with source_network as adtech1, available sources
// registered by adtech1 will be considered with additional filtering criteria
// applied to that set as mentioned in the attribution_config. Derived
// sources can have different values to priority, post_install_exclusivity_window
// etc.
"attribution_config": [
{
// Derived sources are created from this adtech's registered sources
"source_network": "[original source's adtech enrollment ID]",
//(optional) Filter sources whose priority falls in this range
"source_priority_range": {
"start": [priority filter lower bound],
"end": [priority filter upper bound]
},
// (optional) Filter sources whose at least one of filter maps matches these
// filters
"source_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Filter sources whose none of filter map matches these
// filters
"source_not_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Apply this priority to the generated derived sources
"priority": "[64 bit signed integer]",
// (optional) The derived source will have expiry set as this or parent
// source's, whichever is earlier
"expiry": "[64 bit signed integer]",
// (optional) set on the derived source
"filter_data": {
"key name 1": ["key1 value 1"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "[64-bit unsigned integer]"
}
]
در اینجا نسخه ای با مقادیر نمونه اضافه شده است:
"attribution_config": [
{
"source_network": "adtech1-enrollment-id",
"source_priority_range": {
"start": 50,
"end": 100
},
"source_filters": {
"source_type": ["NAVIGATION"]
},
"source_not_filters": {
"product_id": ["789"]
},
"priority": "30",
"expiry": "78901",
// (optional) set on the derived source
"filter_data": {
"product_id": ["1234"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "7890"
}
]
دو فیلد اختیاری جدید برای شروع هدر ثبت اضافه شده است. این فیلدها شناسه فناوری تبلیغات برنده را در کلیدهای گزارش انبوهی فعال میکنند:
-
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
}
…
}
در اینجا محاسبه قطعه کلید ماشه در هنگام ایجاد گزارش برای منبع AdTechB آمده است:
-
key_piece
:0x400 (010000000000)
-
key_offset
:12
- مقدار
enrollment_id
AdtechB:2 (010)
(ازx_network_bit_mapping
) - قطعه کلید ماشه نتیجه:
0x400 | 0x2 << 12 = 0x2400
محدودیت ها
برای فهرستی از قابلیتهای در حال پیشرفت برای زمان اجرا 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، وظایف سمت سرور و سمت سرویس گیرنده فهرست شده در بخشهای زیر را تکمیل کنید.
نقاط پایانی API Reporting Attribution را تنظیم کنید
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 : پیکربندی سطح رویداد انعطاف پذیر Lite. زیر مجموعه ای از فاز 2
- فاز 2 : نسخه کامل پیکربندی سطح رویداد انعطاف پذیر.
مرحله 1: سطح رویداد انعطاف پذیر Lite
ما دو پارامتر اختیاری زیر را در 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
}
}
فاز 2: سطح رویداد کاملا انعطاف پذیر
علاوه بر پارامترهایی که در فاز 1 اضافه شدند، یک پارامتر اختیاری trigger_specs
به JSON در Attribution-Reporting-Register-Source
اضافه می کنیم.
{
// A trigger spec is a set of matching criteria, along with a scheme to
// generate bucketized output based on accumulated values across multiple
// triggers within the specified event_report_window. There will be a limit on
// the number of specs possible to define for a source.
"trigger_specs": [{
// This spec will only apply to registrations that set one of the given
// trigger data values (non-negative integers) in the list.
// trigger_data will still appear in the event-level report.
"trigger_data": [<int>, ...]
// Represents a series of time windows, starting at the source registration
// time. Reports for this spec will be delivered an hour after the end of
// each window. Time is encoded as seconds after source registration.
// end_times must consist of strictly increasing positive integers.
//
// Note: specs with identical trigger_data cannot have overlapping windows;
// this ensures that triggers match at most one spec. If
// event_report_windows is omitted, will use the "event_report_window" or
// "event_report_windows" field specified at the global level for the source
// (or the default windows if none are specified). End time is exclusive.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...],
}
// Represents an operator that summarizes the triggers within a window
// count: number of triggers attributed within a window
// value_sum: sum of the value of triggers within a window
// The summary is reported as an index into a bucketization scheme. Defaults
// to "count"
"summary_window_operator": <one of "count" or "value_sum">,
// Represents a bucketization of the integers from [0, MAX_INT], encoded as
// a list of integers where new buckets begin (excluding 0 which is
// implicitly included).
// It must consist of strictly increasing positive integers.
//
// e.g. [5, 10, 100] encodes the following ranges:
// [[0, 4], [5, 9], [10, 99], [100, MAX_INT]]
//
// At the end of each reporting window, triggers will be summarized into an
// integer which slots into one of these ranges. Reports will be sent for
// every new range boundary that is crossed. Reports will never be sent for
// the range that includes 0, as every source is initialized in this range.
//
// If omitted, then represents a trivial mapping
// [1, 2, ... , MAX_INT]
// With MAX_INT being the maximum int value defined by the browser.
"summary_buckets": [<bucket start>, ...]
}, {
// Next trigger_spec
} ...],
// See description in phase 1.
"max_event_level_reports": <int>
// See description in phase 1.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...]
}
}
این پیکربندی فضای خروجی گزارشهای سطح رویداد را بهازای ثبت منبع، کاملاً مشخص میکند. برای هر مشخصات ماشه، ما به طور کامل مشخص می کنیم:
- مجموعه ای از معیارهای تطبیق:
- این مشخصات برای کدام داده های ماشه خاص اعمال می شود. این منبع فقط با محرک هایی که یکی از مقادیر
trigger_data
مشخص شده درtrigger_specs
را دارند، واجد شرایط مطابقت است. به عبارت دیگر، اگر تریگر با این منبع مطابقت داشت اماtrigger_data
آن یکی از مقادیر موجود در پیکربندی منبع نباشد، ماشه نادیده گرفته میشود. - هنگامی که یک ماشه خاص با این مشخصات مطابقت دارد (با استفاده از
event_report_windows
). توجه داشته باشید که علیرغم عدم موفقیت در دو معیار تطبیق ذکر شده در بالا، باز هم میتوان ماشه را با منبعی برای گزارشهای جمعآوری مطابقت داد.
- این مشخصات برای کدام داده های ماشه خاص اعمال می شود. این منبع فقط با محرک هایی که یکی از مقادیر
- یک الگوریتم خاص برای خلاصه کردن و سطلبندی تمام محرکها در یک پنجره اسناد. این به تریگرها اجازه می دهد تا پارامتر
value
را مشخص کنند که برای یک مشخصات خاص خلاصه می شود، اما به عنوان یک مقدار سطلی گزارش می شود.
تریگرها همچنین از افزودن یک پارامتر مقدار اختیاری در فرهنگ لغت در event_trigger_data
پشتیبانی میکنند.
{
"event_trigger_data": [
{
"trigger_data": "2",
"value": 100, // Defaults to 1
"filters": ...
},
...
]
}
هر ثبت ماشه حداکثر با یک مشخصات ماشه مطابقت دارد و مقدار خلاصه مربوط به آن را به روز می کند. در سطح بالا، در زمان شروع ما:
- فیلترهای ارجاع جهانی را اعمال کنید.
- برای هر مشخصات ماشه،
event_trigger_data
را روی مشخصات ارزیابی کنید تا با استفاده ازevent_reporting_window
spec، مطابقت را پیدا کنید.event_reporting_windows
سطح بالا به عنوان یک مقدار پیشفرض عمل میکند در صورتی که هر یک از مشخصات ماشه، قسمت فرعیevent_report_windows
از دست رفته باشد. - اولین مشخصات منطبق برای انتساب انتخاب میشود و مقدار خلاصه با
value
افزایش مییابد.
هنگامی که event_report_window
برای یک مشخصات کامل شد، مقدار خلاصه آن را به یک سطل نگاشت میکنیم و گزارشی در سطح رویداد برای هر افزایش در سطل خلاصه ناشی از مقادیر ماشه نسبت داده شده ارسال میکنیم. گزارشها با یک فیلد اضافی ارائه میشوند، trigger_summary_bucket
.
{
...
"trigger_summary_bucket": [<bucket start>, <bucket end>],
}
تنظیماتی که معادل نسخه فعلی هستند
موارد زیر به ترتیب پیکربندیهای معادل رویداد فعلی و منابع ناوبری APIها هستند. به خصوص برای منابع ناوبری، این نشان می دهد که چرا سطوح نویز نسبت به منابع رویداد بسیار زیاد است تا مقادیر اپسیلون یکسانی حفظ شود: منابع ناوبری فضای خروجی بسیار بزرگتری دارند.
با توجه به اینکه برخی از پارامترها را می توان به عنوان پیش فرض یا هرس کرد، ممکن است چندین پیکربندی معادل وجود داشته باشد.
منابع رویداد معادل
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1],
"event_report_windows": {
"end_times": [<30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1],
}],
"max_event_level_reports": 1,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
منابع ناوبری معادل
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3, 4, 5, 6, 7],
"event_report_windows": {
"end_times": [<2 days>, <7 days>, <30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3],
}],
"max_event_level_reports": 3,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
نمونه تنظیمات سفارشی
در زیر برخی از تنظیمات اضافی خارج از تنظیمات پیش فرض وجود دارد. در همه این مثال ها، مبادلات توسعه دهنده عبارتند از:
- کاهش برخی از ابعاد پیکربندی پیشفرض (#تریگرها، کاردینالیته دادههای ماشه، #پنجرهها) برای افزایش یکی دیگر برای حفظ سطح نویز
- کاهش برخی از ابعاد پیکربندی پیشفرض (#تریگرها، کاردینالیته دادههای ماشه، #پنجرهها) برای کاهش سطح نویز
سطلهای مقدار ماشه را گزارش کنید
این پیکربندی مثال از توسعهدهندهای پشتیبانی میکند که میخواهد دادههای ارزش را تنها برای یک پنجره گزارش (مثلاً 7 روز) بهینه کند، و پنجرههای گزارش کمتری را با نویز کمتر معامله کند. در این مثال، هر عاملی که trigger_data
روی مقداری غیر از 0 تنظیم کند، برای انتساب واجد شرایط نیست.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
"end_times": [604800, 1209600] // 7 days, 14 days represented in seconds
},
"summary_window_operator": "value_sum",
"summary_buckets": [5, 10, 100]
}],
}
تریگرها را می توان با مجموعه فیلد value
ثبت کرد که خلاصه و سطل می شود. به عنوان مثال، اگر در عرض 7 روز پس از ثبت منبع، سه راهانداز با مقادیر 1، 3 و 4 وجود داشته باشد.
{ "event_trigger_data": [{"trigger_data": "0", "value": 1}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 3}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 4}] }
مقادیر به 8 جمع می شوند و پس از 7 روز + 1 ساعت در گزارش های زیر گزارش می شوند:
// Report 1
{
...
"trigger_summary_bucket": [5, 9]
}
در 7 روز بعدی، محرک های زیر ثبت می شوند:
{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }
مقادیر به 8 + 50 + 45 = 103 جمع می شوند. این گزارشات زیر را در 14 روز + 1 ساعت به دست می دهد:
// Report 2
{
...
"trigger_summary_bucket": [10, 99]
},
// Report 3
{
...
"trigger_summary_bucket": [100, MAX_INT]
}
تعداد ماشه ها را گزارش کنید
این مثال نشان میدهد که چگونه یک توسعهدهنده میتواند یک منبع را پیکربندی کند تا تعداد محرکها را تا 10 دریافت کند.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
"end_times": [604800] // 7 days represented in seconds
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}],
}
محرکهای منتسب با trigger_data
روی 0 شمارش میشوند و روی 10 محدود میشوند. از آنجایی که summary_window_operator
برای شمارش تنظیم شده است، مقدار ماشه نادیده گرفته میشود. اگر 4 محرک ثبت شده و به منبع نسبت داده شود، گزارش به شکل زیر خواهد بود:
// Report 1
{
...
"trigger_summary_bucket": [1, 1]
}
// Report 2
{
...
"trigger_summary_bucket": [2, 2]
}
// Report 3
{
...
"trigger_summary_bucket": [3, 3]
}
// Report 4
{
...
"trigger_summary_bucket": [4, 4]
}
باینری با گزارش های مکرر
این پیکربندی مثال از توسعهدهندهای پشتیبانی میکند که میخواهد بداند که آیا حداقل یک تبدیل در 10 روز اول اتفاق افتاده است یا نه (بدون توجه به مقدار)، اما میخواهد گزارشها را در فواصل زمانی بیشتر از پیشفرض دریافت کند. مجدداً، در این مثال، هر راهاندازی که trigger_data
روی مقداری غیر از 0 تنظیم کند، برای انتساب واجد شرایط نیست. به همین دلیل است که این مورد استفاده باینری نامیده می شود.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
// 1 day, 2 days, 3 days, 5 days, 7 days, 10 days represented in seconds
"end_times": [86400, 172800, 259200, 432000, 604800, 864000]
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1]
}],
}
مشخصات ماشه را از منبعی به منبع دیگر تغییر دهید
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
{
"trigger_specs": [
{
"trigger_data": [4, 5, 6, 7],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
ما توسعهدهندگان را تشویق میکنیم موارد استفاده متفاوتی را که ممکن است برای این برنامه افزودنی API داشته باشند پیشنهاد کنند، و این توضیحدهنده را با پیکربندیهای نمونه برای آن موارد استفاده بهروزرسانی میکنیم.
انتساب شبکه بدون تغییر مسیر
فنآوران تبلیغات باید از تغییر مسیرها برای ثبت چندین راهانداز منبع انتساب و انجام اسناد بین شبکهای استفاده کنند. این ویژگی به پشتیبانی از انتساب بین شبکهای کمک میکند که در آن تغییر مسیرها در سراسر شبکهها امکانپذیر نیست. بیشتر بدانید .
فناوری های تبلیغاتی می توانند پیکربندی را در پاسخ ثبت ماشه ارسال کنند که بر اساس آن منابع ثبت شده توسط سایر فناوری های تبلیغاتی برای تولید منابع مشتق شده انتخاب می شوند. این منابع مشتق شده سپس برای انتساب استفاده می شوند. اگر ماشه به یک منبع مشتق شده نسبت داده شود، گزارشهای انبوه تولید میشوند. تولید گزارش رویداد برای منابع مشتق شده پشتیبانی نمی شود.
فناوریهای تبلیغاتی میتوانند از میان aggregation_keys
در منابع ثبتشده خود که قصد دارند با فنآوران تبلیغات شریک به اشتراک بگذارند، انتخاب کنند. این کلیدها را می توان در قسمت اختیاری shared_aggregation_keys
که در زیر سرصفحه ثبت منبع Attribution-Reporting-Register-Source
قرار دارد، اعلام کرد:
"shared_aggregation_keys": ["[key name1]", "[key name2]"]
منابع مشتق شده بر اساس پیکربندی تحت عنوان هدر ثبت ماشه Attribution-Reporting-Register-Trigger
تولید می شوند:
// Specifies the configuration based on which derived sources should be
// generated. Those derived sources will be included for source matching at the
// time of attribution. For example, if adtech2 is registering a trigger with an
// attribution_config with source_network as adtech1, available sources
// registered by adtech1 will be considered with additional filtering criteria
// applied to that set as mentioned in the attribution_config. Derived
// sources can have different values to priority, post_install_exclusivity_window
// etc.
"attribution_config": [
{
// Derived sources are created from this adtech's registered sources
"source_network": "[original source's adtech enrollment ID]",
//(optional) Filter sources whose priority falls in this range
"source_priority_range": {
"start": [priority filter lower bound],
"end": [priority filter upper bound]
},
// (optional) Filter sources whose at least one of filter maps matches these
// filters
"source_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Filter sources whose none of filter map matches these
// filters
"source_not_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Apply this priority to the generated derived sources
"priority": "[64 bit signed integer]",
// (optional) The derived source will have expiry set as this or parent
// source's, whichever is earlier
"expiry": "[64 bit signed integer]",
// (optional) set on the derived source
"filter_data": {
"key name 1": ["key1 value 1"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "[64-bit unsigned integer]"
}
]
در اینجا نسخه ای با مقادیر نمونه اضافه شده است:
"attribution_config": [
{
"source_network": "adtech1-enrollment-id",
"source_priority_range": {
"start": 50,
"end": 100
},
"source_filters": {
"source_type": ["NAVIGATION"]
},
"source_not_filters": {
"product_id": ["789"]
},
"priority": "30",
"expiry": "78901",
// (optional) set on the derived source
"filter_data": {
"product_id": ["1234"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "7890"
}
]
دو فیلد اختیاری جدید برای شروع هدر ثبت اضافه شده است. این فیلدها شناسه فناوری تبلیغات برنده را در کلیدهای گزارش انبوهی فعال میکنند:
-
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
}
…
}
در اینجا محاسبه قطعه کلید ماشه در هنگام ایجاد گزارش برای منبع AdTechB آمده است:
-
key_piece
:0x400 (010000000000)
-
key_offset
:12
- مقدار
enrollment_id
AdtechB:2 (010)
(ازx_network_bit_mapping
) - قطعه کلید ماشه نتیجه:
0x400 | 0x2 << 12 = 0x2400
محدودیت ها
برای فهرستی از قابلیتهای در حال پیشرفت برای زمان اجرا 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، وظایف سمت سرور و سمت سرویس گیرنده فهرست شده در بخشهای زیر را تکمیل کنید.
نقاط پایانی API Reporting Attribution را تنظیم کنید
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 : پیکربندی سطح رویداد انعطاف پذیر Lite. زیر مجموعه ای از فاز 2
- فاز 2 : نسخه کامل پیکربندی سطح رویداد انعطاف پذیر.
مرحله 1: سطح رویداد انعطاف پذیر Lite
ما دو پارامتر اختیاری زیر را در 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
}
}
فاز 2: سطح رویداد کاملا انعطاف پذیر
علاوه بر پارامترهایی که در فاز 1 اضافه شدند، یک پارامتر اختیاری trigger_specs
به JSON در Attribution-Reporting-Register-Source
اضافه می کنیم.
{
// A trigger spec is a set of matching criteria, along with a scheme to
// generate bucketized output based on accumulated values across multiple
// triggers within the specified event_report_window. There will be a limit on
// the number of specs possible to define for a source.
"trigger_specs": [{
// This spec will only apply to registrations that set one of the given
// trigger data values (non-negative integers) in the list.
// trigger_data will still appear in the event-level report.
"trigger_data": [<int>, ...]
// Represents a series of time windows, starting at the source registration
// time. Reports for this spec will be delivered an hour after the end of
// each window. Time is encoded as seconds after source registration.
// end_times must consist of strictly increasing positive integers.
//
// Note: specs with identical trigger_data cannot have overlapping windows;
// this ensures that triggers match at most one spec. If
// event_report_windows is omitted, will use the "event_report_window" or
// "event_report_windows" field specified at the global level for the source
// (or the default windows if none are specified). End time is exclusive.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...],
}
// Represents an operator that summarizes the triggers within a window
// count: number of triggers attributed within a window
// value_sum: sum of the value of triggers within a window
// The summary is reported as an index into a bucketization scheme. Defaults
// to "count"
"summary_window_operator": <one of "count" or "value_sum">,
// Represents a bucketization of the integers from [0, MAX_INT], encoded as
// a list of integers where new buckets begin (excluding 0 which is
// implicitly included).
// It must consist of strictly increasing positive integers.
//
// e.g. [5, 10, 100] encodes the following ranges:
// [[0, 4], [5, 9], [10, 99], [100, MAX_INT]]
//
// At the end of each reporting window, triggers will be summarized into an
// integer which slots into one of these ranges. Reports will be sent for
// every new range boundary that is crossed. Reports will never be sent for
// the range that includes 0, as every source is initialized in this range.
//
// If omitted, then represents a trivial mapping
// [1, 2, ... , MAX_INT]
// With MAX_INT being the maximum int value defined by the browser.
"summary_buckets": [<bucket start>, ...]
}, {
// Next trigger_spec
} ...],
// See description in phase 1.
"max_event_level_reports": <int>
// See description in phase 1.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...]
}
}
این پیکربندی فضای خروجی گزارشهای سطح رویداد را بهازای ثبت منبع، کاملاً مشخص میکند. برای هر مشخصات ماشه، ما به طور کامل مشخص می کنیم:
- مجموعه ای از معیارهای تطبیق:
- این مشخصات برای کدام داده های ماشه خاص اعمال می شود. این منبع فقط با محرک هایی که یکی از مقادیر
trigger_data
مشخص شده درtrigger_specs
را دارند، واجد شرایط مطابقت است. به عبارت دیگر، اگر تریگر با این منبع مطابقت داشت اماtrigger_data
آن یکی از مقادیر موجود در پیکربندی منبع نباشد، ماشه نادیده گرفته میشود. - هنگامی که یک ماشه خاص با این مشخصات مطابقت دارد (با استفاده از
event_report_windows
). توجه داشته باشید که علیرغم عدم موفقیت در دو معیار تطبیق ذکر شده در بالا، باز هم میتوان ماشه را با منبعی برای گزارشهای جمعآوری مطابقت داد.
- این مشخصات برای کدام داده های ماشه خاص اعمال می شود. این منبع فقط با محرک هایی که یکی از مقادیر
- یک الگوریتم خاص برای خلاصه کردن و سطلبندی تمام محرکها در یک پنجره اسناد. این به تریگرها اجازه می دهد تا پارامتر
value
را مشخص کنند که برای یک مشخصات خاص خلاصه می شود، اما به عنوان یک مقدار سطلی گزارش می شود.
تریگرها همچنین از افزودن یک پارامتر مقدار اختیاری در فرهنگ لغت در event_trigger_data
پشتیبانی میکنند.
{
"event_trigger_data": [
{
"trigger_data": "2",
"value": 100, // Defaults to 1
"filters": ...
},
...
]
}
هر ثبت ماشه حداکثر با یک مشخصات ماشه مطابقت دارد و مقدار خلاصه مربوط به آن را به روز می کند. در سطح بالا، در زمان شروع ما:
- فیلترهای ارجاع جهانی را اعمال کنید.
- برای هر مشخصات ماشه،
event_trigger_data
را روی مشخصات ارزیابی کنید تا با استفاده ازevent_reporting_window
spec، مطابقت را پیدا کنید.event_reporting_windows
سطح بالا به عنوان یک مقدار پیشفرض عمل میکند در صورتی که هر یک از مشخصات ماشه، قسمت فرعیevent_report_windows
از دست رفته باشد. - اولین مشخصات منطبق برای انتساب انتخاب میشود و مقدار خلاصه با
value
افزایش مییابد.
هنگامی که event_report_window
برای یک مشخصات کامل شد، مقدار خلاصه آن را به یک سطل نگاشت میکنیم و گزارشی در سطح رویداد برای هر افزایش در سطل خلاصه ناشی از مقادیر ماشه نسبت داده شده ارسال میکنیم. گزارشها با یک فیلد اضافی ارائه میشوند، trigger_summary_bucket
.
{
...
"trigger_summary_bucket": [<bucket start>, <bucket end>],
}
تنظیماتی که معادل نسخه فعلی هستند
موارد زیر به ترتیب پیکربندیهای معادل رویداد فعلی و منابع ناوبری APIها هستند. به خصوص برای منابع ناوبری، این نشان می دهد که چرا سطوح نویز نسبت به منابع رویداد بسیار زیاد است تا مقادیر اپسیلون یکسانی حفظ شود: منابع ناوبری فضای خروجی بسیار بزرگتری دارند.
با توجه به اینکه برخی از پارامترها را می توان به عنوان پیش فرض یا هرس کرد، ممکن است چندین پیکربندی معادل وجود داشته باشد.
منابع رویداد معادل
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1],
"event_report_windows": {
"end_times": [<30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1],
}],
"max_event_level_reports": 1,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
منابع ناوبری معادل
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3, 4, 5, 6, 7],
"event_report_windows": {
"end_times": [<2 days>, <7 days>, <30 days>]
},
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3],
}],
"max_event_level_reports": 3,
...
// expiry must be greater than or equal to the last element of the end_times
"expiry": <30 days>,
}
نمونه تنظیمات سفارشی
در زیر برخی از تنظیمات اضافی خارج از تنظیمات پیش فرض وجود دارد. در همه این مثال ها، مبادلات توسعه دهنده عبارتند از:
- کاهش برخی از ابعاد پیکربندی پیشفرض (#تریگرها، کاردینالیته دادههای ماشه، #پنجرهها) برای افزایش یکی دیگر برای حفظ سطح نویز
- کاهش برخی از ابعاد پیکربندی پیشفرض (#تریگرها، کاردینالیته دادههای ماشه، #پنجرهها) برای کاهش سطح نویز
سطلهای مقدار ماشه را گزارش کنید
این پیکربندی مثال از توسعهدهندهای پشتیبانی میکند که میخواهد دادههای ارزش را تنها برای یک پنجره گزارش (مثلاً 7 روز) بهینه کند، و پنجرههای گزارش کمتری را با نویز کمتر معامله کند. در این مثال، هر عاملی که trigger_data
روی مقداری غیر از 0 تنظیم کند، برای انتساب واجد شرایط نیست.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
"end_times": [604800, 1209600] // 7 days, 14 days represented in seconds
},
"summary_window_operator": "value_sum",
"summary_buckets": [5, 10, 100]
}],
}
تریگرها را می توان با مجموعه فیلد value
ثبت کرد که خلاصه و سطل می شود. به عنوان مثال، اگر در عرض 7 روز پس از ثبت منبع، سه راهانداز با مقادیر 1، 3 و 4 وجود داشته باشد.
{ "event_trigger_data": [{"trigger_data": "0", "value": 1}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 3}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 4}] }
مقادیر به 8 جمع می شوند و پس از 7 روز + 1 ساعت در گزارش های زیر گزارش می شوند:
// Report 1
{
...
"trigger_summary_bucket": [5, 9]
}
در 7 روز بعدی، محرک های زیر ثبت می شوند:
{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }
مقادیر به 8 + 50 + 45 = 103 جمع می شوند. این گزارشات زیر را در 14 روز + 1 ساعت به دست می دهد:
// Report 2
{
...
"trigger_summary_bucket": [10, 99]
},
// Report 3
{
...
"trigger_summary_bucket": [100, MAX_INT]
}
تعداد ماشه ها را گزارش کنید
این مثال نشان میدهد که چگونه یک توسعهدهنده میتواند یک منبع را پیکربندی کند تا تعداد محرکها را تا 10 دریافت کند.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
"end_times": [604800] // 7 days represented in seconds
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}],
}
محرکهای منتسب با trigger_data
روی 0 شمارش میشوند و روی 10 محدود میشوند. از آنجایی که summary_window_operator
برای شمارش تنظیم شده است، مقدار ماشه نادیده گرفته میشود. اگر 4 محرک ثبت شده و به منبع نسبت داده شود، گزارش به شکل زیر خواهد بود:
// Report 1
{
...
"trigger_summary_bucket": [1, 1]
}
// Report 2
{
...
"trigger_summary_bucket": [2, 2]
}
// Report 3
{
...
"trigger_summary_bucket": [3, 3]
}
// Report 4
{
...
"trigger_summary_bucket": [4, 4]
}
باینری با گزارش های مکرر
این پیکربندی مثال از توسعهدهندهای پشتیبانی میکند که میخواهد بداند که آیا حداقل یک تبدیل در 10 روز اول اتفاق افتاده است یا نه (بدون توجه به مقدار)، اما میخواهد گزارشها را در فواصل زمانی بیشتر از پیشفرض دریافت کند. مجدداً، در این مثال، هر راهاندازی که trigger_data
روی مقداری غیر از 0 تنظیم کند، برای انتساب واجد شرایط نیست. به همین دلیل است که این مورد استفاده باینری نامیده می شود.
{
"trigger_specs": [
{
"trigger_data": [0],
"event_report_windows": {
// 1 day, 2 days, 3 days, 5 days, 7 days, 10 days represented in seconds
"end_times": [86400, 172800, 259200, 432000, 604800, 864000]
},
// This field could be omitted to save bandwidth since the default is "count"
"summary_window_operator": "count",
"summary_buckets": [1]
}],
}
مشخصات ماشه را از منبعی به منبع دیگر تغییر دهید
{
"trigger_specs": [
{
"trigger_data": [0, 1, 2, 3],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
{
"trigger_specs": [
{
"trigger_data": [4, 5, 6, 7],
"event_report_windows": {
"end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
}
}],
"max_event_level_reports": 3
}
ما توسعهدهندگان را تشویق میکنیم موارد استفاده متفاوتی را که ممکن است برای این برنامه افزودنی API داشته باشند پیشنهاد کنند، و این توضیحدهنده را با پیکربندیهای نمونه برای آن موارد استفاده بهروزرسانی میکنیم.
انتساب شبکه بدون تغییر مسیر
فنآوران تبلیغات باید از تغییر مسیرها برای ثبت چندین راهانداز منبع انتساب و انجام اسناد بین شبکهای استفاده کنند. این ویژگی به پشتیبانی از انتساب بین شبکهای کمک میکند که در آن تغییر مسیرها در سراسر شبکهها امکانپذیر نیست. بیشتر بدانید .
فناوری های تبلیغاتی می توانند پیکربندی را در پاسخ ثبت ماشه ارسال کنند که بر اساس آن منابع ثبت شده توسط سایر فناوری های تبلیغاتی برای تولید منابع مشتق شده انتخاب می شوند. این منابع مشتق شده سپس برای انتساب استفاده می شوند. اگر ماشه به یک منبع مشتق شده نسبت داده شود، گزارشهای انبوه تولید میشوند. تولید گزارش رویداد برای منابع مشتق شده پشتیبانی نمی شود.
فناوریهای تبلیغاتی میتوانند از میان aggregation_keys
در منابع ثبتشده خود که قصد دارند با فنآوران تبلیغات شریک به اشتراک بگذارند، انتخاب کنند. این کلیدها را می توان در قسمت اختیاری shared_aggregation_keys
که در زیر سرصفحه ثبت منبع Attribution-Reporting-Register-Source
قرار دارد، اعلام کرد:
"shared_aggregation_keys": ["[key name1]", "[key name2]"]
منابع مشتق شده بر اساس پیکربندی تحت عنوان هدر ثبت ماشه Attribution-Reporting-Register-Trigger
تولید می شوند:
// Specifies the configuration based on which derived sources should be
// generated. Those derived sources will be included for source matching at the
// time of attribution. For example, if adtech2 is registering a trigger with an
// attribution_config with source_network as adtech1, available sources
// registered by adtech1 will be considered with additional filtering criteria
// applied to that set as mentioned in the attribution_config. Derived
// sources can have different values to priority, post_install_exclusivity_window
// etc.
"attribution_config": [
{
// Derived sources are created from this adtech's registered sources
"source_network": "[original source's adtech enrollment ID]",
//(optional) Filter sources whose priority falls in this range
"source_priority_range": {
"start": [priority filter lower bound],
"end": [priority filter upper bound]
},
// (optional) Filter sources whose at least one of filter maps matches these
// filters
"source_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Filter sources whose none of filter map matches these
// filters
"source_not_filters": {
"key name 1": ["key1 value 1"]
},
// (optional) Apply this priority to the generated derived sources
"priority": "[64 bit signed integer]",
// (optional) The derived source will have expiry set as this or parent
// source's, whichever is earlier
"expiry": "[64 bit signed integer]",
// (optional) set on the derived source
"filter_data": {
"key name 1": ["key1 value 1"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "[64-bit unsigned integer]"
}
]
در اینجا نسخه ای با مقادیر نمونه اضافه شده است:
"attribution_config": [
{
"source_network": "adtech1-enrollment-id",
"source_priority_range": {
"start": 50,
"end": 100
},
"source_filters": {
"source_type": ["NAVIGATION"]
},
"source_not_filters": {
"product_id": ["789"]
},
"priority": "30",
"expiry": "78901",
// (optional) set on the derived source
"filter_data": {
"product_id": ["1234"]
},
// (optional) set on the derived source
"post_install_exclusivity_window": "7890"
}
]
دو فیلد اختیاری جدید برای شروع هدر ثبت اضافه شده است. این فیلدها شناسه فناوری تبلیغات برنده را در کلیدهای گزارش انبوهی فعال میکنند:
-
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
}
…
}
در اینجا محاسبه قطعه کلید ماشه در هنگام ایجاد گزارش برای منبع AdTechB آمده است:
-
key_piece
:0x400 (010000000000)
-
key_offset
:12
- مقدار
enrollment_id
AdtechB:2 (010)
(ازx_network_bit_mapping
) - قطعه کلید ماشه نتیجه:
0x400 | 0x2 << 12 = 0x2400
محدودیت ها
برای فهرستی از قابلیتهای در حال پیشرفت برای زمان اجرا SDK، یادداشتهای انتشار را مشاهده کنید.
اشکالات و مشکلات را گزارش کنید
بازخورد شما بخش مهمی از جعبه ایمنی حریم خصوصی در Android است! هر مشکلی را که پیدا کردید یا ایده ای برای بهبود Privacy Sandbox در Android به ما اطلاع دهید.