Implementing consent management mechanism (Consent Management)
Without CMP (Consent Management Platform), app with analytics and ads violates GDPR from first launch — Firebase Analytics, Facebook SDK and AppsFlyerstart collecting data before user allowed anything. Fine for this is real. Task — embed consent management so no SDK initializes before explicit permission.
IAB TCF 2.2 and why it matters
IAB Transparency & Consent Framework (TCF) 2.2 — standard for ad ecosystem. If app uses ad networks (AdMob, ironSource, AppLovin), CMP must be TCF-compatible. Otherwise ad partners don't get consent signal, monetization breaks.
Certified IAB CMPs: OneTrust, Usercentrics, Didomi, Quantcast Choice. All have mobile SDKs.
What happens technically on app launch
Before CMP dialog appears — no tracking. After acceptance:
- consent saved locally (Keychain/Keystore)
- only permitted SDKs initialize
Initialization scheme:
// iOS, simplified
func application(_ app: UIApplication, didFinishLaunchingWithOptions...) {
ConsentManager.shared.requestConsentUpdate { status in
switch status {
case .obtained:
self.initializeAnalyticsIfAllowed()
self.initializeAdsIfAllowed()
case .notRequired: // not in EU/UK
self.initializeAll()
case .required: // dialog needed
break // CMP will show dialog itself
}
}
}
func initializeAnalyticsIfAllowed() {
guard ConsentManager.shared.hasConsent(for: .analytics) else { return }
Analytics.configure()
}
On Android similarly via UserMessagingPlatform (Google UMP) or chosen CMP SDK.
Google UMP as minimal variant
Google User Messaging Platform — free option from Google, integrates into AdMob. Suits apps monetized only via Google ads:
val params = ConsentRequestParameters.Builder()
.setTagForUnderAgeOfConsent(false)
.build()
consentInformation.requestConsentInfoUpdate(
activity, params,
{
if (consentInformation.isConsentFormAvailable) {
loadForm()
}
},
{ error -> /* handle */ }
)
UMP doesn't suit if using third-party ad networks — need full TCF-compatible CMP.
Granular consents
GDPR requires separate consents by purpose. Minimal set of categories:
- Strictly Necessary — no consent needed, can't disable
- Analytics — Firebase, Amplitude, Mixpanel
- Advertising — AdMob, Facebook Audience Network
- Personalization — recommendation systems
- External services — Sentry (crash reporting), Intercom (support)
Crash reporting — controversial category. Technically needed for service, can argue as necessary. But if Sentry/Crashlytics transmits user_id — personal data, need consent.
iOS ATT Framework
On iOS 14.5+ apps must request ATTrackingManager.requestTrackingAuthorization before IDFA access (advertising identifier). Separate from GDPR consent — Apple requirement.
ATTrackingManager.requestTrackingAuthorization { status in
switch status {
case .authorized:
// IDFA accessible, can pass to ad SDKs
let idfa = ASIdentifierManager.shared().advertisingIdentifier
case .denied, .restricted, .notDetermined:
// work without IDFA, SKAdNetwork for attribution
}
}
Show ATT dialog after CMP dialog and ideally with prior explanation why needed — otherwise permission conversion very low.
Storing and syncing consents
Consent stored locally with timestamp and document versions (Privacy Policy, Terms). On version change — repeat request. On user region change — reassess applicable requirements.
Log consent server-side: on change send to backend {user_id, consent_version, purposes: {...}, timestamp, ip_hash}. This is evidence base for regulator checks.
Timeline for implementing CMP with granular consents, conditional SDK initialization, ATT flow on iOS and server-side logging — 2–3 days using ready CMP SDK. Custom implementation without ready SDK — up to 5 days.







