Saat Anda membaca dokumentasi Privacy Sandbox di Android, gunakan tombol Pratinjau Developer atau Beta untuk memilih versi program yang sedang Anda gunakan, karena petunjuknya dapat bervariasi.
Attribution Reporting API dirancang untuk memberikan privasi pengguna yang lebih baik dengan menghapus ketergantungan pada ID pengguna lintas pihak, dan untuk mendukung kasus penggunaan utama untuk atribusi dan pengukuran konversi di berbagai aplikasi. Panduan developer ini menjelaskan cara mengonfigurasi dan menguji Attribution Reporting API untuk mendaftarkan klik, penayangan, dan konversi iklan dengan memanggil metode yang mendaftarkan pemicu dan sumber peristiwa yang relevan untuk peristiwa tersebut.
Panduan ini menunjukkan cara menyiapkan endpoint server dan membuat aplikasi klien yang memanggil layanan tersebut. Pelajari lebih lanjut desain keseluruhan Attribution Reporting API dalam proposal desain.
Istilah Penting
- Sumber atribusi merujuk pada klik atau penayangan.
- Pemicu adalah peristiwa yang dapat diatribusikan ke konversi.
- Laporan berisi data tentang pemicu dan sumber atribusi yang sesuai. Laporan ini dikirim sebagai respons terhadap peristiwa pemicu. Attribution Reporting API mendukung laporan tingkat peristiwa dan laporan agregat.
Sebelum memulai
Untuk menggunakan Attribution Reporting API, selesaikan tugas sisi server dan sisi klien yang tercantum di bagian berikut.
Menyiapkan endpoint Attribution Reporting API
Attribution Reporting API memerlukan sekumpulan endpoint yang dapat Anda akses dari perangkat pengujian atau emulator. Buat satu endpoint untuk setiap tugas sisi server berikut:
- Mendaftarkan sumber atribusi (penayangan atau klik)
- Mendaftarkan pemicu (konversi)
- Menerima laporan tingkat peristiwa
- Menerima laporan agregat
Ada beberapa metode untuk menyiapkan endpoint yang diperlukan:
- Cara tercepat untuk memulai dan menjalankan adalah men-deploy definisi layanan OpenAPI v3 dari repositori kode contoh kami ke platform tiruan atau microservice. Anda dapat menggunakan Postman, Prism, atau platform server tiruan lainnya yang menerima format ini. Deploy setiap endpoint dan lacak URI untuk digunakan di aplikasi. Untuk memverifikasi pengiriman laporan, lihat panggilan yang sebelumnya dilakukan ke platform tiruan atau tanpa server.
- Jalankan server mandiri menggunakan contoh Kotlin berbasis Spring Boot. Deploy server ini di penyedia cloud atau infrastruktur internal Anda.
- Gunakan definisi layanan sebagai contoh untuk mengintegrasikan endpoint ke dalam sistem yang ada.
Menerima pendaftaran sumber
Endpoint ini harus dapat ditangani dari URI yang mirip dengan yang berikut ini:
https://adtech.example/attribution_source
Saat mendaftarkan sumber atribusi, aplikasi klien akan memberikan URI untuk endpoint server ini. Kemudian, Attribution Reporting API akan membuat permintaan dan menyertakan salah satu header berikut:
Untuk peristiwa klik:
Attribution-Reporting-Source-Info: navigation
Untuk peristiwa penayangan:
Attribution-Reporting-Source-Info: event
Konfigurasikan endpoint server Anda untuk merespons hal-hal berikut:
// 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>
Berikut adalah contoh dengan nilai sampel yang ditambahkan:
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
Jika Attribution-Reporting-Redirects
berisi URI partner teknologi iklan, Attribution
Reporting API akan membuat permintaan yang serupa ke setiap URI. Setiap partner teknologi iklan harus mengonfigurasi server yang merespons dengan header ini:
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.
Menerima pendaftaran pemicu konversi
Endpoint ini harus dapat ditangani dari URI yang mirip dengan yang berikut ini:
https://adtech.example/attribution_trigger
Saat mendaftarkan peristiwa pemicu, aplikasi klien memberikan URI untuk endpoint server ini. Kemudian, Attribution Reporting API akan membuat permintaan dan menyertakan salah satu header berikut:
Konfigurasikan endpoint server Anda untuk merespons hal-hal berikut:
// 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>
Berikut adalah contoh dengan nilai sampel yang ditambahkan:
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
ID kunci agregasi dan string filter dibatasi hanya 25 byte. Artinya,
ID kunci agregasi dan string filter tidak boleh melebihi 25
karakter. Dalam contoh ini, panjang campaignCounts
adalah 14 karakter sehingga ID kunci agregasi
ini valid, dan panjang 1234
adalah 4 karakter sehingga string filter ini valid.
Jika ID kunci atau string filter agregasi melebihi 25 karakter, pemicu akan
diabaikan.
Jika Attribution-Reporting-Redirect
berisi URI partner teknologi iklan, Attribution
Reporting API akan membuat permintaan yang serupa ke setiap URI. Setiap partner teknologi iklan harus mengonfigurasi server yang merespons dengan header ini:
// 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.
Menerima laporan tingkat peristiwa
Endpoint ini harus dapat ditangani dari URI. Lihat Mendaftar ke akun Privacy Sandbox untuk mengetahui informasi selengkapnya tentang mendaftarkan URI. (URI akan disimpulkan dari asal server yang digunakan untuk menerima pendaftaran sumber dan pendaftaran pemicu.) Dengan menggunakan contoh URI untuk endpoint yang menerima pendaftaran sumber dan menerima pendaftaran pemicu, URI endpoint ini adalah:
https://adtech.example/.well-known/attribution-reporting/report-event-attribution
Konfigurasikan server ini untuk menerima permintaan JSON yang menggunakan format berikut:
{
"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]",
}
Kunci debug memungkinkan insight tambahan dalam laporan atribusi Anda; pelajari lebih lanjut cara mengonfigurasinya.
Menerima laporan agregat
Endpoint ini harus dapat ditangani dari URI. Lihat Mendaftar ke akun Privacy Sandbox untuk mengetahui informasi selengkapnya tentang mendaftarkan URI. (URI akan disimpulkan dari asal server yang digunakan untuk menerima pendaftaran sumber dan pendaftaran pemicu.) Dengan menggunakan contoh URI untuk endpoint yang menerima pendaftaran sumber dan menerima pendaftaran pemicu, URI endpoint ini adalah:
https://adtech.example/.well-known/attribution-reporting/report-aggregate-attribution
Kolom terenkripsi dan tidak terenkripsi diisi untuk laporan agregat. Laporan terenkripsi memungkinkan Anda untuk memulai pengujian dengan layanan agregasi, sementara kolom yang tidak dienkripsi memberikan insight tentang cara struktur pasangan nilai kunci ditetapkan dalam data.
Konfigurasikan server ini untuk menerima permintaan JSON yang menggunakan format berikut:
{
// 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]"
}
Kunci debug memungkinkan insight tambahan dalam laporan atribusi Anda; pelajari lebih lanjut cara mengonfigurasinya.
Menyiapkan klien Android
Aplikasi klien mendaftarkan sumber dan pemicu atribusi, serta mengaktifkan pembuatan laporan tingkat peristiwa dan agregat. Untuk menyiapkan perangkat klien atau emulator Android untuk menggunakan Attribution Reporting API, lakukan hal berikut:
- Menyiapkan lingkungan pengembangan Anda untuk Privacy Sandbox di Android.
- Menginstal image sistem ke perangkat yang didukung atau menyiapkan emulator yang menyertakan dukungan untuk Privacy Sandbox di Android.
Aktifkan akses ke Attribution Reporting API dengan menjalankan perintah ADB berikut. (API tersebut dinonaktifkan secara default.)
adb shell device_config put adservices ppapi_app_allow_list \"\*\"
Jika Anda menguji Attribution Reporting API secara lokal (seperti menguji pada perangkat yang aksesnya Anda miliki secara fisik), jalankan perintah ini untuk menonaktifkan pendaftaran:
adb shell device_config put adservices disable_measurement_enrollment_check "true"
Sertakan izin
ACCESS_ADSERVICES_ATTRIBUTION
dalam file Manifes Android Anda dan buat konfigurasi layanan iklan agar aplikasi Anda dapat menggunakan Attribution Reporting API:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
(Opsional) Jika berencana untuk menerima laporan debug, sertakan izin
ACCESS_ADSERVICES_AD_ID
dalam file Manifes Android Anda:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />
Referensikan konfigurasi layanan iklan di elemen
<application>
manifes Anda:<property android:name="android.adservices.AD_SERVICES_CONFIG" android:resource="@xml/ad_services_config" />
Tentukan resource XML layanan iklan yang dirujuk dalam manifes, seperti
res/xml/ad_services_config.xml
. Pelajari lebih lanjut izin layanan iklan dan kontrol akses SDK.<ad-services-config> <attribution allowAllToAccess="true" /> </ad-services-config>
Mendaftarkan peristiwa iklan
Aplikasi Anda harus mendaftarkan sumber dan konversi saat keduanya terjadi untuk memastikan
sumber dan konversi tersebut dilaporkan dengan benar. Class MeasurementManager
memiliki metode
untuk membantu Anda mendaftarkan peristiwa sumber atribusi dan
pemicu konversi.
Mendaftarkan peristiwa sumber atribusi
Saat iklan ditayangkan atau diklik, aplikasi penayang akan memanggil registerSource()
untuk
mendaftarkan sumber atribusi seperti yang ditampilkan dalam cuplikan kode.
Attribution Reporting API mendukung jenis peristiwa sumber atribusi berikut:
- Klik, yang biasanya Anda daftarkan dalam metode callback yang mirip dengan
onClick()
. Peristiwa pemicu yang sesuai biasanya akan segera terjadi setelah peristiwa klik. Jenis peristiwa ini memberikan lebih banyak informasi interaksi pengguna, dan oleh karena itu, merupakan jenis sumber atribusi yang baik untuk memberikan prioritas yang tinggi. Penayangan, yang biasanya Anda daftarkan dalam metode callback yang mirip dengan
onAdShown()
. Peristiwa pemicu yang sesuai mungkin terjadi beberapa jam atau hari setelah peristiwa penayangan.
Kotlin
companion object {
private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}
val measurementManager = context.getSystemService(MeasurementManager::class.java)
var exampleClickEvent: InputEvent? = null
// Use the URI of the server-side endpoint that accepts attribution source
// registration.
val attributionSourceUri: Uri =
Uri.parse("https://adtech.example/attribution_source?AD_TECH_PROVIDED_METADATA")
val future = CompletableFuture<Void>()
adView.setOnTouchListener(_: View?, event: MotionEvent?)) ->
exampleClickEvent = event
true
}
// Register Click Event
measurementManager.registerSource(
attributionSourceUri,
exampleClickEvent,
CALLBACK_EXECUTOR,
future::complete)
// Register View Event
measurementManager.registerSource(
attributionSourceUri,
null,
CALLBACK_EXECUTOR,
future::complete)
Java
private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();
private InputEvent exampleClickEvent;
MeasurementManager measurementManager =
context.getSystemService(MeasurementManager.class);
// Use the URI of the server-side endpoint that accepts attribution source
// registration.
Uri attributionSourceUri =
Uri.parse("https://adtech.example/attribution_source?AD_TECH_PROVIDED_METADATA");
CompletableFuture<Void> future = new CompletableFuture<>();
adView.setOnTouchListener(v, event)) -> {
exampleClickEvent = event;
return true;
}
// Register Click Event
measurementManager.registerSource(attributionSourceUri, exampleClickEvent,
CALLBACK_EXECUTOR, future::complete);
// Register View Event
measurementManager.registerSource(attributionSourceUri, null,
CALLBACK_EXECUTOR, future::complete);
Setelah pendaftaran, API mengeluarkan permintaan POST HTTP ke endpoint
layanan di alamat yang ditentukan oleh attributionSourceUri
. Respons
endpoint menyertakan nilai untuk destination, source_event_id, expiry
, dan
source_priority
.
Jika teknologi iklan asal ingin membagikan pendaftaran sumber, URI sumber atribusi asli dapat menyertakan pengalihan ke endpoint teknologi iklan lainnya. Batas dan aturan yang berlaku untuk pengalihan dijelaskan secara terperinci di proposal teknis.
Dukungan telah ditambahkan untuk pengalihan daisy-chain untuk registerSource
dan registerTrigger
. Selain header pendaftaran, konsumen API kini
dapat menyediakan pengalihan HTTP sebagai respons server yang menyertakan kode status
302 dan header "Location" dengan URL berikutnya yang akan dikunjungi untuk pendaftaran
tambahan.
Hanya kolom "destination" yang disediakan dalam kunjungan pertama yang digunakan di seluruh daisy-chain. Jumlah kunjungan memiliki batas yang sama dengan header "Attribution-Reporting-Redirect". Dukungan pengalihan ini merupakan tambahan untuk dukungan "Attribution-Reporting-Redirect" yang sudah ada, dan jika keduanya ada, "Attribution-Reporting-Redirect" akan mendapatkan preferensi.
Mendaftarkan peristiwa pemicu konversi
Untuk mendaftarkan peristiwa pemicu konversi, panggil registerTrigger()
di aplikasi Anda:
Kotlin
companion object {
private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}
val measurementManager = context.getSystemService(MeasurementManager::class.java)
// Use the URI of the server-side endpoint that accepts trigger registration.
val attributionTriggerUri: Uri =
Uri.parse("https://adtech.example/trigger?AD_TECH_PROVIDED_METADATA")
val future = CompletableFuture<Void>()
// Register trigger (conversion)
measurementManager.registerTrigger(
attributionTriggerUri,
CALLBACK_EXECUTOR,
future::complete)
Java
private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();
MeasurementManager measurementManager =
context.getSystemService(MeasurementManager.class);
// Use the URI of the server-side endpoint that accepts trigger registration.
Uri attributionTriggerUri =
Uri.parse("https://adtech.example/trigger?AD_TECH_PROVIDED_METADATA");
CompletableFuture<Void> future = new CompletableFuture<>();
// Register trigger (conversion)
measurementManager.registerTrigger(
attributionTriggerUri,
CALLBACK_EXECUTOR,
future::complete)
Setelah pendaftaran, API mengeluarkan permintaan POST HTTP ke endpoint
layanan di alamat yang ditentukan oleh attributionTriggerUri
. Respons
endpoint mencakup nilai untuk laporan peristiwa dan gabungan.
Jika platform teknologi iklan asal memungkinkan pendaftaran pemicu dibagikan, URI dapat menyertakan pengalihan ke URI yang merupakan bagian dari platform teknologi iklan lainnya. Batas dan aturan yang berlaku untuk pengalihan dijelaskan dalam proposal teknis.
Mendaftarkan pengukuran lintas aplikasi dan web
Jika aplikasi dan browser memainkan peran dalam perjalanan pengguna dari sumber ke pemicu, ada sedikit perbedaan dalam penerapan pendaftaran peristiwa iklan. Jika pengguna melihat iklan pada aplikasi dan dialihkan ke browser untuk konversi, sumber akan didaftarkan oleh aplikasi, dan konversi oleh browser web. Demikian pula, jika pengguna memulai di browser web dan diarahkan ke aplikasi untuk dikonversi, browser akan mendaftarkan sumbernya dan aplikasi akan mendaftarkan konversi.
Karena ada perbedaan dalam cara pengaturan teknologi iklan di web dan Android, kami telah menambahkan API baru untuk mendaftarkan sumber dan pemicu saat pendaftaran dilakukan di browser. Perbedaan utama antara API ini dan API berbasis aplikasi
yang sesuai adalah browser akan mengikuti pengalihan, menerapkan
filter khusus browser, dan meneruskan pendaftaran yang valid ke platform dengan
memanggil registerWebSource()
atau registerWebTrigger()
.
Cuplikan kode berikut menampilkan contoh panggilan API yang dibuat browser untuk mendaftarkan sumber atribusi sebelum mengarahkan pengguna ke aplikasi:
Kotlin
companion object {
private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}
val measurementManager =
context.getSystemService(MeasurementManager::class.java)
var exampleClickEvent: InputEvent? = null
// Use the URIs of the server-side endpoints that accept attribution source
// registration.
val sourceParam1 = WebSourceParams.Builder(Uri.parse(
"https://adtech1.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
// True, if debugging is allowed for the ad tech.
.setDebugKeyAllowed(true)
.build()
val sourceParam2 = WebSourceParams.Builder(Uri.parse(
"https://adtech2.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
.setDebugKeyAllowed(false)
.build()
val sourceParam3 = WebSourceParams.Builder(Uri.parse(
"https://adtech3.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
.build()
val sourceParams = Arrays.asList(sourceParam1, sourceParam2, sourceParam3)
val publisherOrigin = Uri.parse("https://publisher.example")
val appDestination = Uri.parse("android-app://com.example.store")
val webDestination = Uri.parse("https://example.com")
val future = CompletableFuture<Void>()
adView.setOnTouchListener {_: View?, event: MotionEvent? ->
exampleClickEvent = event
true
}
val clickRegistrationRequest = WebSourceRegistrationRequest.Builder(
sourceParams,
publisherOrigin)
.setAppDestination(appDestination)
.setWebDestination(webDestination)
.setInputEvent(event)
.build()
val viewRegistrationRequest = WebSourceRegistrationRequest.Builder(
sourceParams,
publisherOrigin)
.setAppDestination(appDestination)
.setWebDestination(webDestination)
.setInputEvent(null)
.build()
// Register a web source for a click event.
measurementManager.registerWebSource(
clickRegistrationRequest,
CALLBACK_EXECUTOR,
future::complete)
// Register a web source for a view event.
measurementManager.registerWebSource(
viewRegistrationRequest,
CALLBACK_EXECUTOR,
future::complete)
Java
private static final Executor CALLBACK_EXECUTOR =
Executors.newCachedThreadPool();
private InputEvent exampleClickEvent;
MeasurementManager measurementManager =
context.getSystemService(MeasurementManager.class);
// Use the URIs of the server-side endpoints that accept attribution source
// registration.
WebSourceParams sourceParam1 = WebSourceParams.Builder(Uri.parse(
"https://adtech1.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
// True, if debugging is allowed for the ad tech.
.setDebugKeyAllowed(true)
.build();
WebSourceParams sourceParam2 = WebSourceParams.Builder(Uri.parse(
"https://adtech2.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
.setDebugKeyAllowed(false)
.build();
WebSourceParams sourceParam3 = WebSourceParams.Builder(Uri.parse(
"https://adtech3.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
.build();
List<WebSourceParams> sourceParams =
Arrays.asList(sourceParam1, sourceParam2, sourceParam3);
Uri publisherOrigin = Uri.parse("https://publisher.example");
Uri appDestination = Uri.parse("android-app://com.example.store");
Uri webDestination = Uri.parse("https://example.com");
CompletableFuture<Void> future = new CompletableFuture<>();
adView.setOnTouchListener(v, event) -> {
exampleClickEvent = event;
return true;
}
WebSourceRegistrationRequest clickRegistrationRequest =
new WebSourceRegistrationRequest.Builder(sourceParams, publisherOrigin)
.setAppDestination(appDestination)
.setWebDestination(webDestination)
.setInputEvent(event)
.build();
WebSourceRegistrationRequest viewRegistrationRequest =
new WebSourceRegistrationRequest.Builder(sourceParams, publisherOrigin)
.setAppDestination(appDestination)
.setWebDestination(webDestination)
.setInputEvent(null)
.build();
// Register a web source for a click event.
measurementManager.registerWebSource(clickRegistrationRequest,
CALLBACK_EXECUTOR, future::complete);
// Register a web source for a view event.
measurementManager.registerWebSource(viewRegistrationRequest,
CALLBACK_EXECUTOR, future::complete);
Cuplikan kode berikut menampilkan contoh panggilan API yang dilakukan browser untuk mendaftarkan konversi setelah pengguna diarahkan dari aplikasi:
Kotlin
companion object {
private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}
val measurementManager = context.getSystemService(MeasurementManager::class.java)
// Use the URIs of the server-side endpoints that accept trigger registration.
val triggerParam1 = WebTriggerParams.Builder(Uri.parse(
"https://adtech1.example/trigger?AD_TECH_PROVIDED_METADATA"))
// True, if debugging is allowed for the ad tech.
.setDebugKeyAllowed(true)
.build()
val triggerParam2 = WebTriggerParams.Builder(Uri.parse(
"https://adtech2.example/trigger?AD_TECH_PROVIDED_METADATA"))
.setDebugKeyAllowed(false)
.build()
val triggerParams = Arrays.asList(triggerParam1, triggerParam2)
val advertiserOrigin = Uri.parse("https://advertiser.example")
val future = CompletableFuture<Void>()
val triggerRegistrationRequest = WebTriggerRegistrationRequest.Builder(
triggerParams,
advertiserOrigin)
.build()
// Register the web trigger (conversion).
measurementManager.registerWebTrigger(
triggerRegistrationRequest,
CALLBACK_EXECUTOR,
future::complete)
Java
private static final Executor CALLBACK_EXECUTOR =
Executors.newCachedThreadPool();
MeasurementManager measurementManager =
context.getSystemService(MeasurementManager.class);
// Use the URIs of the server-side endpoints that accept trigger registration.
WebTriggerParams triggerParam1 = WebTriggerParams.Builder(Uri.parse(
"https://adtech1.example/trigger?AD_TECH_PROVIDED_METADATA"))
// True, if debugging is allowed for the ad tech.
.setDebugKeyAllowed(true)
.build();
WebTriggerParams triggerParam2 = WebTriggerParams.Builder(Uri.parse(
"https://adtech2.example/trigger?AD_TECH_PROVIDED_METADATA"))
.setDebugKeyAllowed(false)
.build();
List<WebTriggerParams> triggerParams =
Arrays.asList(triggerParam1, triggerParam2);
Uri advertiserOrigin = Uri.parse("https://advertiser.example");
CompletableFuture<Void> future = new CompletableFuture<>();
WebTriggerRegistrationRequest triggerRegistrationRequest =
new WebTriggerRegistrationRequest.Builder(
triggerParams, advertiserOrigin)
.build();
// Register the web trigger (conversion).
measurementManager.registerWebTrigger( triggerRegistrationRequest,
CALLBACK_EXECUTOR, future::complete);
Menambahkan derau untuk privasi
Laporan tingkat peristiwa berisi data tujuan, ID sumber atribusi, dan pemicu. Seluruhnya dikirim dalam format asli (tidak terenkripsi) ke origin pelaporan. Untuk melindungi privasi pengguna, kami dapat menambahkan derau agar lebih sulit mengidentifikasi masing-masing pengguna. Laporan tingkat peristiwa dengan derau dibuat dan dikirim sesuai dengan framework privasi diferensial. Berikut adalah nilai persentase derau default untuk berbagai skenario:
Jenis sumber |
Nilai tujuan sumber |
Probabilitas laporan bising per pendaftaran sumber |
Lihat |
Aplikasi atau web |
0,0000025 |
Lihat |
Aplikasi dan web |
0,0000042 |
Klik |
Aplikasi atau web |
0,0024263 |
Klik |
Aplikasi dan web |
0,0170218 |
Dalam pengukuran atribusi aplikasi ke web, tempat sumber dapat mendorong konversi ke tujuan aplikasi dan web, laporan tingkat peristiwa dapat menentukan apakah pemicu terjadi di aplikasi atau web. Sebagai kompensasi atas detail tambahan ini, laporan derau yang dihasilkan hingga ~7x untuk klik dan ~1,7x untuk penayangan.
Beberapa teknologi iklan tidak memerlukan laporan tingkat peristiwa untuk menentukan apakah pemicu
terjadi di tujuan aplikasi atau web. Teknologi iklan dapat menggunakan
kolom coarse_event_report_destinations
di bawah
header Attribution-Reporting-Register-Source
untuk mengurangi derau. Jika sumber dengan
kolom coarse_event_report_destinations
yang ditentukan memenangkan atribusi,
laporan yang dihasilkan akan menyertakan tujuan aplikasi dan web tanpa membedakan
tempat sebenarnya pemicu terjadi.
Pada contoh berikut, pengguna mengklik iklan dan sumber tersebut didaftarkan dengan API. Pengguna kemudian melakukan konversi di aplikasi pengiklan dan situs pengiklan. Kedua konversi ini terdaftar sebagai pemicu dan diatribusikan ke klik awal.
Header HTTP pendaftaran sumber berbasis klik:
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"
}
Pemicu didaftarkan dari aplikasi dengan nama paket
com.advertiser.example
:
Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
"trigger_data": "1",
"priority": "1"
}],
}
Pemicu didaftarkan dari browser dari situs dengan domain eTLD+1
https://advertiser.com
:
Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
"trigger_data": "2",
"priority": "2"
}],
}
Hasil laporan tingkat peristiwa akan dibuat. Dengan asumsi kedua pemicu tersebut diatribusikan ke sumber, laporan tingkat peristiwa berikut akan dibuat:
{
"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
}
Membuat dan mengirimkan laporan
Attribution Reporting API mengirimkan laporan ke endpoint di server Anda yang menerima laporan tingkat peristiwa dan laporan agregat.
Memaksa tugas pelaporan agar berjalan
Setelah Anda mendaftarkan peristiwa sumber atribusi atau mendaftarkan peristiwa pemicu, sistem akan menjadwalkan tugas pelaporan untuk dijalankan. Secara default, tugas ini berjalan setiap 4 jam. Untuk tujuan pengujian, Anda dapat memaksa tugas pelaporan untuk dijalankan atau mempersingkat interval antartugas.
Memaksa tugas atribusi untuk dijalankan:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 5
Memaksa tugas pelaporan tingkat peristiwa untuk dijalankan:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 3
Memaksa tugas pelaporan agregat untuk dijalankan:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 7
Memeriksa output di logcat untuk melihat kapan tugas telah berjalan. Output tersebut harus terlihat seperti berikut:
JobScheduler: executeRunCommand(): com.google.android.adservices.api/0 5 s=false f=true
Memaksa pengiriman laporan
Meskipun tugas pelaporan dipaksa untuk dijalankan, sistem masih akan mengirimkan laporan sesuai dengan waktu pengiriman terjadwal yang berkisar dari beberapa jam hingga beberapa hari. Untuk tujuan pengujian, Anda dapat meningkatkan waktu sistem perangkat menjadi setelah keterlambatan yang dijadwalkan untuk memulai pengiriman laporan.
Memverifikasi laporan di server
Setelah laporan dikirim, verifikasi pengiriman dengan memeriksa laporan yang diterima, log server yang berlaku, seperti histori server tiruan atau sistem kustom.
Mendekode laporan agregat
Saat menerima laporan agregat, kolom debug_cleartext_payload
akan menyimpan versi laporan agregat yang tidak dienkripsi. Meskipun versi laporan
tidak dienkripsi, versi ini masih perlu didekode.
Di bawah ini adalah contoh decoding konten kolom debug_cleartext_payload
dalam dua langkah: langkah pertama menggunakan decoding Base 64, dan langkah kedua menggunakan
decoding 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);
});
Pengujian
Untuk membantu Anda memulai Attribution Reporting API, Anda dapat menggunakan project MeasurementSampleApp di GitHub. Aplikasi contoh ini menunjukkan pendaftaran sumber atribusi dan pendaftaran pemicu.
Untuk endpoint server, pertimbangkan resource referensi berikut atau solusi kustom Anda:
- MeasurementAdTechServerSpec mencakup definisi layanan OpenAPI yang dapat di-deploy ke platform tiruan atau microservice yang didukung.
- MeasurementAdTechServer menyertakan implementasi referensi server tiruan berdasarkan aplikasi Spring Boot untuk Google App Engine.
Prasyarat
Deploy API tiruan di endpoint jarak jauh yang dapat diakses dari perangkat pengujian atau emulator. Untuk memudahkan pengujian, lihat project contoh MeasurementAdTechServerSpec dan MeasurementAdTechServer.
Fungsi yang akan diuji
- Menggunakan pendaftaran sumber atribusi dan pemicu konversi. Pastikan endpoint sisi server merespons dengan format yang benar.
- Menjalankan tugas pelaporan.
- Memverifikasi pengiriman laporan di backend atau konsol server pengujian Anda.
Fitur mendatang
Konfigurasi tingkat peristiwa fleksibel
Konfigurasi default untuk pelaporan tingkat peristiwa disarankan untuk memulai pengujian utilitas, tetapi mungkin tidak ideal untuk semua kasus penggunaan. Attribution Reporting API akan mendukung konfigurasi opsional yang lebih fleksibel sehingga teknologi iklan meningkatkan kontrol terhadap struktur laporan tingkat peristiwa dan dapat memaksimalkan utilitas data. Fleksibilitas tambahan ini akan diperkenalkan ke Attribution Reporting API dalam dua fase:
- Fase 1: Konfigurasi tingkat peristiwa fleksibel lite; bagian dari Fase 2.
- Fase 2: Versi penuh konfigurasi tingkat peristiwa fleksibel.
Fase 1: Tingkat peristiwa fleksibel lite
Kami akan menambahkan dua parameter opsional berikut ke JSON di
Attribution-Reporting-Register-Source
:
max_event_level_reports
event_report_windows
{
...
// Optional. This is a parameter that acts across all trigger types for the
// lifetime of this source. It restricts the total number of event-level
// reports that this source can generate. After this maximum is hit, the
// source is no longer capable of producing any new data. The use of
// priority in the trigger attribution algorithm in the case of multiple
// attributable triggers remains unchanged. Defaults to 3 for navigation
// sources and 1 for event sources
"max_event_level_reports": <int>,
// Optional. Represents a series of time windows, starting at 0. Reports
// for this source will be delivered an hour after the end of each window.
// Time is encoded as seconds after source registration. If
// event_report_windows is omitted, will use the default windows. This
// field is mutually exclusive with the existing `event_report_window` field.
// // End time is exclusive.
"event_report_windows": {
"start_time": <int>,
"end_times": [<int>, ...]
}
}
Contoh konfigurasi kustom
Contoh konfigurasi ini mendukung developer yang ingin mengoptimalkan penerimaan laporan pada periode pelaporan sebelumnya.
{
...
"max_event_level_reports": 2,
"event_report_windows": {
"end_times": [7200, 43200, 86400] // 2 hours, 12 hours, 1 day in seconds
}
}
Fase 2: Tingkat peristiwa fleksibel penuh
Selain parameter yang ditambahkan pada Fase 1, kami akan menambahkan
parameter opsional tambahan trigger_specs
ke JSON di
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>, ...]
}
}
Konfigurasi ini sepenuhnya menentukan ruang output laporan tingkat peristiwa, per pendaftaran sumber. Untuk setiap spesifikasi pemicu, kami sepenuhnya menentukan:
- Serangkaian kriteria yang cocok:
- Data pemicu tertentu yang diterapkan dengan spesifikasi ini. Sumber ini
memenuhi syarat untuk dicocokkan hanya dengan pemicu yang memiliki salah satu nilai
trigger_data
yang ditentukan ditrigger_specs
. Dengan kata lain, jika pemicu akan cocok dengan sumber ini, tetapitrigger_data
-nya bukan salah satu dari nilai dalam konfigurasi sumber, pemicu akan diabaikan. - Saat pemicu tertentu cocok dengan spesifikasi ini (menggunakan
event_report_windows
). Perhatikan bahwa pemicu masih dapat dicocokkan dengan sumber untuk laporan agregat meskipun dua kriteria pencocokan yang disebutkan sebelumnya gagal.
- Data pemicu tertentu yang diterapkan dengan spesifikasi ini. Sumber ini
memenuhi syarat untuk dicocokkan hanya dengan pemicu yang memiliki salah satu nilai
- Algoritma spesifik untuk meringkas dan menjadikan semua pemicu satu bucket dalam
periode atribusi. Hal ini memungkinkan pemicu menentukan parameter
value
yang akan diringkas untuk spesifikasi tertentu, tetapi dilaporkan sebagai nilai dalam bucket.
Pemicu juga akan mendukung penambahan parameter nilai opsional di
kamus dalam event_trigger_data
.
{
"event_trigger_data": [
{
"trigger_data": "2",
"value": 100, // Defaults to 1
"filters": ...
},
...
]
}
Setiap pendaftaran pemicu akan cocok dengan maksimal satu spesifikasi pemicu dan memperbarui nilai ringkasan yang terkait. Pada level yang tinggi, pada waktu pemicu, kami akan:
- Menerapkan filter atribusi global.
- Untuk setiap spesifikasi pemicu, evaluasi
event_trigger_data
pada spesifikasi untuk menemukan kecocokan, menggunakanevent_reporting_window
spesifikasi.event_reporting_windows
level teratas bertindak sebagai nilai default jika spesifikasi pemicu adalah sub-kolomevent_report_windows
yang tidak ada. - Spesifikasi pertama yang cocok dipilih untuk atribusi, dan nilai ringkasan
ditambah dengan
value
.
Jika event_report_window
untuk spesifikasi selesai, kami akan memetakan nilai ringkasannya
ke bucket, dan mengirim laporan tingkat peristiwa untuk setiap penambahan dalam
bucket ringkasan yang disebabkan oleh nilai pemicu yang diatribusikan. Laporan akan dilengkapi dengan satu
kolom tambahan, yaitu trigger_summary_bucket
.
{
...
"trigger_summary_bucket": [<bucket start>, <bucket end>],
}
Konfigurasi yang setara dengan versi saat ini
Berikut konfigurasi yang setara untuk masing-masing peristiwa dan sumber navigasi API saat ini. Khusus untuk sumber navigasi, konfigurasi ini menggambarkan alasan level derau sangat tinggi dibandingkan dengan sumber peristiwa untuk mempertahankan nilai epsilon yang sama: sumber navigasi memiliki ruang output yang jauh lebih besar.
Mungkin saja ada beberapa konfigurasi yang setara, mengingat beberapa parameter dapat ditetapkan sebagai default atau di-pruning.
Sumber peristiwa yang setara
// 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>,
}
Sumber navigasi yang setara
// 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>,
}
Contoh konfigurasi kustom
Berikut beberapa konfigurasi tambahan selain default. Dalam semua contoh ini, kompromi developer mencakup:
- mengurangi beberapa dimensi konfigurasi default (#pemicu, kardinalitas data pemicu, #jendela) untuk meningkatkan dimensi lainnya guna mempertahankan level derau
- mengurangi beberapa dimensi konfigurasi default (#pemicu, kardinalitas data pemicu, #jendela) untuk mengurangi level derau
Melaporkan bucket nilai pemicu
Contoh konfigurasi ini mendukung developer yang ingin mengoptimalkan data
nilai hanya untuk satu periode pelaporan (mis. 7 hari), dengan mengorbankan periode pelaporan yang lebih sedikit untuk mengurangi derau. Dalam contoh ini, pemicu apa pun yang menetapkan trigger_data
ke
nilai selain 0 tidak memenuhi syarat untuk atribusi.
{
"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]
}],
}
Pemicu dapat didaftarkan dengan kumpulan kolom value
, yang dijumlahkan dan
dibuat bucket. Misalnya, jika ada tiga pemicu dalam waktu 7 hari sejak pendaftaran sumber
dengan nilai 1, 3, dan 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}] }
Nilainya dijumlahkan menjadi 8 dan dilaporkan dalam laporan berikut setelah 7 hari + 1 jam:
// Report 1
{
...
"trigger_summary_bucket": [5, 9]
}
Dalam 7 hari berikutnya, pemicu berikut akan didaftarkan:
{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }
Nilai-nilainya dijumlahkan menjadi 8 + 50 + 45 = 103. Hal ini menghasilkan laporan berikut pada 14 hari + 1 jam:
// Report 2
{
...
"trigger_summary_bucket": [10, 99]
},
// Report 3
{
...
"trigger_summary_bucket": [100, MAX_INT]
}
Melaporkan jumlah pemicu
Contoh ini menunjukkan cara developer dapat mengonfigurasi sumber untuk mendapatkan jumlah pemicu hingga 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]
}],
}
Pemicu atribusi dengan trigger_data
yang disetel ke 0 dihitung dan dibatasi hingga 10.
Nilai pemicu diabaikan karena summary_window_operator
disetel ke penghitungan. Jika
4 pemicu didaftarkan dan diatribusikan ke sumber, laporan akan terlihat
seperti ini:
// 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]
}
Biner dengan pelaporan yang lebih sering
Contoh konfigurasi ini mendukung developer yang ingin mengetahui apakah
setidaknya satu konversi terjadi dalam 10 hari pertama (terlepas dari nilainya), tetapi
ingin menerima laporan dengan interval yang lebih sering daripada default. Perlu diingat,
pemicu apa pun di contoh ini yang menetapkan trigger_data
ke
nilai selain 0 tidak memenuhi syarat untuk atribusi. Inilah alasan kasus penggunaan ini disebut sebagai
biner.
{
"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]
}],
}
Memvariasikan spesifikasi pemicu dari sumber ke sumber
{
"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
}
Sebaiknya developer menyarankan berbagai kasus penggunaan yang mungkin mereka miliki untuk ekstensi API ini, dan kami akan memperbarui penjelasan ini dengan contoh konfigurasi untuk kasus penggunaan tersebut.
Atribusi lintas-jaringan tanpa pengalihan
Teknologi iklan harus menggunakan pengalihan untuk mendaftarkan beberapa pemicu sumber atribusi dan untuk melakukan atribusi lintas jaringan. Fitur ini membantu mendukung atribusi lintas jaringan saat pengalihan tidak memungkinkan di seluruh jaringan. Pelajari lebih lanjut.
Teknologi iklan dapat mengirim konfigurasi dalam respons pendaftaran pemicu berdasarkan sumber mana yang didaftarkan oleh teknologi iklan lain yang dipilih untuk menghasilkan sumber turunan; sumber turunan ini kemudian digunakan untuk atribusi. Laporan agregat dibuat jika pemicu diatribusikan ke sumber turunan. Pembuatan laporan peristiwa untuk sumber turunan tidak didukung.
Teknologi iklan dapat memilih dari aggregation_keys
di sumber terdaftar mereka yang
ingin mereka bagikan kepada teknologi iklan partner. Kunci ini dapat dideklarasikan dalam
kolom shared_aggregation_keys
opsional yang terletak di bawah header pendaftaran
sumber Attribution-Reporting-Register-Source
:
"shared_aggregation_keys": ["[key name1]", "[key name2]"]
Sumber turunan dihasilkan berdasarkan konfigurasi di bawah header pendaftaran pemicu 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]"
}
]
Berikut adalah versi dengan nilai contoh yang ditambahkan:
"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"
}
]
Dua kolom opsional baru ditambahkan untuk memicu header pendaftaran. Kolom ini memungkinkan ID teknologi iklan pemenang di kunci laporan agregat:
x_network_bit_mapping
: ID pendaftaran ke pemetaan bit ID teknologi iklanx_network_data
: Offset (geser kiri) untuk operasi ORx_network_bit_mapping
teknologi iklan pemenang dengan bagian kunci pemicu
Contoh:
"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
}
…
}
Berikut adalah penghitungan bagian kunci pemicu yang dihasilkan saat membuat laporan untuk sumber AdTechB:
key_piece
:0x400 (010000000000)
key_offset
:12
- Nilai
enrollment_id
AdtechB:2 (010)
(darix_network_bit_mapping
) - Bagian Kunci Pemicu yang Dihasilkan:
0x400 | 0x2 << 12 = 0x2400
Batasan
Untuk daftar kemampuan yang sedang berlangsung untuk Runtime SDK, lihat catatan rilis.
Melaporkan bug dan masalah
Masukan Anda adalah bagian penting dari Privacy Sandbox di Android. Beri tahu kami jika Anda menemukan masalah atau memiliki ide untuk meningkatkan Privacy Sandbox di Android.