@byvik/capacitor-ump-consent
v0.1.0
Published
Google UMP consent form for Capacitor, with optional Firebase Consent Mode v2 mapping. No AdMob plugin required.
Maintainers
Readme
@byvik/capacitor-ump-consent
Google's User Messaging Platform (UMP) consent form for Capacitor, with the answer translated to Consent Mode v2.
- Standalone: it does not bundle or require an AdMob plugin, so it works with whatever ads integration you already have.
- Reads the TCF answer UMP stores and maps it to the four Consent Mode signals.
- Applies those signals to Firebase Analytics when your app includes it, and returns them either way.
- Never rejects: a network error or a form that fails to load cannot keep your app from starting.
- Android only. On iOS and web every method rejects, so guard calls with
Capacitor.getPlatform() === 'android'.
This plugin is a tool, not legal advice. You are responsible for how your app handles consent.
Install
npm install @byvik/capacitor-ump-consent
npx cap syncRequires Capacitor 8.
Setup
Create a consent message for your app in AdMob under Privacy & messaging.
UMP finds that message through your AdMob app ID. If your ads integration has not already added it, put it inside
<application>inandroid/app/src/main/AndroidManifest.xml:<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />If you use Firebase Analytics, deny everything by default in the same place:
<meta-data android:name="google_analytics_default_allow_analytics_storage" android:value="false" /> <meta-data android:name="google_analytics_default_allow_ad_storage" android:value="false" /> <meta-data android:name="google_analytics_default_allow_ad_user_data" android:value="false" /> <meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="false" />The defaults have to live in the manifest. Firebase starts with the process, before any plugin code runs, so defaults set from JavaScript would leave a window in which the SDK is already collecting with its permissive factory settings.
Variables
Set these in android/variables.gradle to override the defaults:
umpVersion: version ofcom.google.android.ump:user-messaging-platform(default:3.1.0)firebaseAnalyticsVersion: version ofcom.google.firebase:firebase-analyticsthe plugin compiles against (default:22.1.2). The plugin does not add Firebase to your app.
Usage
import { UmpConsent } from '@byvik/capacitor-ump-consent';
// On every launch, before initializing ads.
const state = await UmpConsent.requestConsent();
if (state.canRequestAds) {
// initialize your ads SDK
}
// In your settings screen.
if (state.privacyOptionsRequired) {
showPrivacyRow(() => UmpConsent.showPrivacyOptionsForm());
}Consent Mode
After each request or change, the plugin reads what UMP stored and derives:
| Signal | Granted when |
| -------------------- | ------------------------------- |
| analytics_storage | TCF purpose 1 is consented |
| ad_storage | TCF purpose 1 is consented |
| ad_user_data | TCF purposes 1 and 7 are consented |
| ad_personalization | TCF purposes 3 and 4 are consented |
The three ad signals follow the mapping Google documents for TCF. TCF has no purpose for analytics; tying analytics_storage to purpose 1 is this plugin's choice.
Where GDPR does not apply (UMP reports that no consent is required), all four are granted. With the manifest defaults above, users outside the regulated regions would otherwise never be measured.
Until UMP knows whether the user has to be asked, for example on a first launch without network, nothing is granted and nothing is applied: your manifest defaults stay in force.
Google's SDKs can infer the three ad signals from the TC string on their own, but only when the CMP writes IABTCF_EnableAdvertiserConsentMode = 1. This plugin does not rely on that flag, and it also sets analytics_storage.
Only TCF (GDPR) messages are mapped. Other message types, such as US state regulations, are not translated to Consent Mode: for those users the four signals are granted.
The same signals are returned in ConsentState.consentMode. To apply them yourself, turn the automatic step off:
| Prop | Type | Description | Default | Since |
| ------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ----- |
| firebaseConsentMode | boolean | Apply the consent to Firebase Analytics (Consent Mode v2) every time the consent is requested or changed. Has no effect in apps that do not include Firebase Analytics. Set it to false if you apply Consent Mode yourself from ConsentState.consentMode. | true | 0.1.0 |
Examples
In capacitor.config.json:
{
"plugins": {
"UmpConsent": {
"firebaseConsentMode": false
}
}
}In capacitor.config.ts:
/// <reference types="@byvik/capacitor-ump-consent" />
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
UmpConsent: {
firebaseConsentMode: false,
},
},
};
export default config;Testing
Run the app once, find the line UMP prints to logcat with your device's hashed ID, and pass it:
await UmpConsent.reset();
await UmpConsent.requestConsent({
debugGeography: 'eea',
testDeviceIds: ['33BE2250B43518CCDA7DE426D04EE231'],
});API
requestConsent(...)
requestConsent(options?: RequestConsentOptions | undefined) => Promise<ConsentState>Update the consent information and show the consent form if it is required. Call it on every app launch, before initializing any ads SDK.
Never rejects: when the request or the form fails it resolves with the
stored state and an error message.
| Param | Type |
| ------------- | ----------------------------------------------------------------------- |
| options | RequestConsentOptions |
Returns: Promise<ConsentState>
Since: 0.1.0
showPrivacyOptionsForm()
showPrivacyOptionsForm() => Promise<ConsentState>Show the privacy options form so the user can change their choice.
Offer it when privacyOptionsRequired is true. Never rejects.
Returns: Promise<ConsentState>
Since: 0.1.0
getConsentState()
getConsentState() => Promise<ConsentState>The stored consent state, without any network request or UI.
gdprApplies, purposeConsents and consentMode are read from storage
and are valid from the start. status and canRequestAds come from UMP,
which reports 'unknown' and false until requestConsent() has been
called in the current launch.
Returns: Promise<ConsentState>
Since: 0.1.0
reset()
reset() => Promise<void>Forget the stored consent so the form shows again. For testing only.
Since: 0.1.0
Interfaces
ConsentState
| Prop | Type | Description | Since |
| ---------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| canRequestAds | boolean | Whether ads can be requested. Initialize your ads SDK only when this is true. | 0.1.0 |
| status | ConsentStatus | UMP's consent status. | 0.1.0 |
| privacyOptionsRequired | boolean | Whether the app must offer a way to reopen the privacy options form, for example a row in its settings screen that calls showPrivacyOptionsForm(). | 0.1.0 |
| gdprApplies | boolean | Whether GDPR applies to this user, as stored by UMP in IABTCF_gdprApplies. | 0.1.0 |
| purposeConsents | string | The raw IABTCF_PurposeConsents string: character n - 1 is '1' when TCF purpose n is consented. Empty when there is none. | 0.1.0 |
| consentMode | ConsentModeSignals | The answer translated to Consent Mode v2. Everything is false until UMP knows whether this user has to be asked. | 0.1.0 |
| error | string | Message of the error that interrupted the request or the form, if any. The rest of the state is still valid: it reflects what UMP has stored. | 0.1.0 |
ConsentModeSignals
| Prop | Type | Since |
| ----------------------- | -------------------- | ----- |
| analyticsStorage | boolean | 0.1.0 |
| adStorage | boolean | 0.1.0 |
| adUserData | boolean | 0.1.0 |
| adPersonalization | boolean | 0.1.0 |
RequestConsentOptions
| Prop | Type | Description | Default | Since |
| ----------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
| tagForUnderAgeOfConsent | boolean | Tell UMP the user is under the age of consent. | false | 0.1.0 |
| debugGeography | DebugGeography | Make a test device behave as if it were in this geography. Only applies to devices listed in testDeviceIds. | | 0.1.0 |
| testDeviceIds | string[] | Hashed IDs of the test devices. UMP prints the ID of the current device to logcat the first time consent is requested. | | 0.1.0 |
Type Aliases
ConsentStatus
'unknown' | 'notRequired' | 'required' | 'obtained'
DebugGeography
'disabled' | 'eea' | 'regulatedUsState' | 'other'
License
MIT
