Privacy Sandbox Attribution Setup for Android Apps
Google announced abandoning Google Advertising ID (GAID) in favor of Privacy Sandbox APIs—technologies preserving user privacy while enabling ad attribution. Attribution Reporting API inside Privacy Sandbox is the Android equivalent of SKAdNetwork, but works differently and has its own integration specifics.
Privacy Sandbox Attribution: What It Is and How It Differs from GAID
With GAID attribution was deterministic: ad network got precise device identifier, MMP matched it with click, you knew concrete user. Privacy Sandbox Attribution works at device level without passing user-level data:
- Browser or ad network registers source (ad impression/click) via Attribution Reporting API
- On install or in-app event registers trigger
- Device independently matches source and trigger
- Aggregated reports send through secure server without raw user data
Fundamental difference from GAID: data aggregates on device, not on server. Ad network gets statistical noise (differential privacy), not concrete records.
Current Status and Requirements
Privacy Sandbox Attribution API on Android requires:
- Android 13+ (SDK 33+) for testing
- App must request
android.permission.ACCESS_ADSERVICES_ATTRIBUTIONpermission -
<uses-sdk>declaration with minSdkVersion compatible with Ad Services
In AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
<application>
<property
android:name="android.adservices.AD_SERVICES_CONFIG"
android:resource="@xml/ad_services_config" />
</application>
File res/xml/ad_services_config.xml:
<ad-services-config>
<attribution shouldAllowAdServicesApi="true" />
</ad-services-config>
Registering Conversion Trigger
After install or target in-app action app registers trigger via MeasurementManager:
import android.adservices.measurement.MeasurementManager
import android.adservices.measurement.TriggerRequest
import android.net.Uri
import androidx.annotation.RequiresApi
@RequiresApi(33)
fun reportConversion(eventType: String, revenue: Double) {
val measurementManager = MeasurementManager.get(context)
// Trigger URI must match destination in source-registration from ad network
val triggerUri = Uri.parse("https://your-ad-network.com/trigger")
val triggerRequest = TriggerRequest.Builder(triggerUri)
.build()
measurementManager.registerTrigger(
triggerRequest,
Executors.newSingleThreadExecutor()
) { outcomeReceiver ->
// outcomeReceiver.result = true on successful registration
}
}
Trigger registers locally on device. System independently matches it with previously registered source from ad network.
MMP Support
Direct Attribution Reporting API integration is labor-intensive and requires server infrastructure for processing aggregated reports. In practice better to go through MMP:
AppsFlyer supports Privacy Sandbox Attribution from SDK 6.10+. At initialization enough to enable Privacy Sandbox mode:
AppsFlyerLib.getInstance().init(devKey, conversionListener, context)
AppsFlyerLib.getInstance().setConsentData(
AppsFlyerConsent.forGDPRUser(
hasConsentForDataUsage = true,
hasConsentForAdsPersonalization = true
)
)
AppsFlyerLib.getInstance().start(context)
SDK itself accesses Attribution Reporting API if available (Android 13+), and falls back to Google Play Referrer for older versions.
Adjust similarly—Adjust SDK 4.36+ natively supports Privacy Sandbox.
Aggregated Reports vs Summary Reports
Privacy Sandbox offers two report types:
Event-level reports — contain limited data about specific events (up to 3 bits of trigger information). Arrive with 2–30 day delay, with added noise.
Aggregatable reports — summary data by campaigns. Processed via Aggregation Service in Google Cloud or AWS—secure computing environment (Trusted Execution Environment). More complete data, but require server infrastructure.
For most mobile apps on launch event-level reports via MMP are sufficient—aggregation service needed at scale of thousands of conversions per day.
Backward Compatibility: GAID Still Works
Google didn't disable GAID immediately. On Android 12 and below GAID works as before. Privacy Sandbox is parallel infrastructure for Android 13+. Code must support both:
fun getAttributionMethod(context: Context): AttributionMethod {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
AttributionMethod.PRIVACY_SANDBOX
} else {
AttributionMethod.GAID
}
}
MMP SDKs do this automatically, but direct integration needs explicit differentiation.
What's Included
- Add permissions and Ad Services configuration to manifest
- MMP SDK integration supporting Privacy Sandbox (AppsFlyer 6.10+ / Adjust 4.36+)
- Trigger registration for key conversion events
- Testing on Android 13+ emulator with Privacy Sandbox enabled
- Configure postbacks in ad network dashboards
Timeline
3–5 days working through MMP. Direct integration with aggregation service—up to 2 weeks. Cost calculated individually.







