Vai al contenuto principale

Come gestire il consenso AdMob GDPR in Capacitor

Gestisci il consenso AdMob GDPR in un'app Capacitor con il modulo di consenso UMP SDK di Google: opzioni di privacy, ordine ATT, geografia di debug e gestione degli errori, con code.

Crediti dell'articolo

Martin Donadieu

Autore

Valeria

Recensore

Jordan

Editore

Come gestire il consenso AdMob GDPR in Capacitor

Per gestire il consenso AdMob GDPR in un'app Capacitor, utilizza la piattaforma di messaggi utente di Google (UMP) SDK: richiedi informazioni sul consenso ad ogni avvio, mostra la forma di consenso se richiesta e inizializza gli annunci solo quando canRequestAds è vero. Hai anche bisogno di un punto di ingresso per le opzioni di privacy affinché gli utenti possano modificare la loro scelta, e su iOS il flusso UMP dovrebbe precedere la richiesta di trasparenza dell'app. Questa guida mostra il flusso completo con due configurazioni: un plugin che avvolge UMP in JavaScript, e @capgo/capacitor-admob con un piccolo ponte di consenso nativo.

Cosa fa UMP e perché AdMob lo richiede

Dalla gennaio 2024, Google richiede ai publisher che servono annunci agli utenti dell'UE, del Regno Unito e della Svizzera di utilizzare una piattaforma di gestione del consenso certificata da Google (CMP) integrata con il Framework di trasparenza e consenso (TCF) dell'IAB. La UMP SDK è la propria CMP certificata da Google, gratuita e integrata nel console AdMob.

UMP fa tre cose per te:

  1. Rileva se l'utente è in una regione in cui è richiesto il consenso.
  2. Mostra il messaggio di consenso che hai configurato in AdMob, nella lingua dell'utente.
  3. Memorizza le scelte dell'utente come stringa TC sul dispositivo (le chiavi standard IABTCF_ su iOS e UserDefaults su iOS e SharedPreferences Sui dispositivi Android, il Google Mobile Ads SDK e i partner di mediazione leggono quando richiedono annunci.

Puoi utilizzare anche UMP per le normative sulla privacy degli Stati Uniti, che AdMob chiama "messaggi degli Stati Uniti", dallo stesso console.

Step 1: create the messages in AdMob

In console di AdMob, vai a Privacy & messaggi:

  • Crea un Regolamento europeo messaggio (GDPR). Scegli gli app che si applicano, le lingue e la tua lista di partner pubblicitari.
  • Creare optionalmente un Stati Uniti messaggio.
  • Su iOS, crea un messaggio IDFA se hai l'intenzione di richiedere la trasparenza dell'app sulle tracce. UMP lo mostrerà prima della richiesta di sistema ATT. IDFA spiegazione Se hai l'intenzione di richiedere la trasparenza delle tracce dell'app, UMP lo mostrerà prima della richiesta di sistema di ATT.
  • Passo 2: decidere l'ordine delle operazioni

Se il modulo non compare mai in tuo app successivamente, controlla prima un messaggio non pubblicato o non assegnato.

L'ordine che funziona per la maggior parte delle app:

The order that works for most apps:

  1. L'app inizia.
  2. Richiedi l'aggiornamento delle informazioni di consenso con UMP (ogni avvio).
  3. Se richiesto, caricare e visualizzare il modulo di consenso.
  4. Se canRequestAds è vero, avviare gli annunci mobili SDK e caricare gli annunci.
  5. Mostrare un'opzione "Impostazioni sulla privacy" nella schermata delle impostazioni quando UMP dice che le opzioni sulla privacy sono richieste.

Google consente anche di avviare gli annunci mobili SDK in parallelo con la richiesta di consenso quando canRequestAds Era già vero da una sessione precedente. Ciò riduce il tempo per la prima pubblicità per gli utenti ritornanti.

Opzione A: un plugin che avvolge UMP in JavaScript

@capacitor-community/admob (la versione 8 supporta Capacitor 8) esporre metodi UMP direttamente: requestConsentInfo, showConsentForm, showPrivacyOptionsForm e resetConsentInfo.

bun add @capacitor-community/admob
bunx cap sync
import {
  AdMob,
  AdmobConsentStatus,
  AdmobConsentDebugGeography,
} from '@capacitor-community/admob';

export async function initAdsWithConsent(isDebug: boolean) {
  await AdMob.initialize();

  let info = await AdMob.requestConsentInfo(
    isDebug
      ? {
          debugGeography: AdmobConsentDebugGeography.EEA,
          testDeviceIdentifiers: ['YOUR_TEST_DEVICE_ID'],
        }
      : undefined,
  );

  if (info.isConsentFormAvailable && info.status === AdmobConsentStatus.REQUIRED) {
    info = await AdMob.showConsentForm();
  }

  // The enum value is the string 'REQUIRED'
  const showPrivacyEntry = String(info.privacyOptionsRequirementStatus) === 'REQUIRED';

  return { canRequestAds: info.canRequestAds, showPrivacyEntry };
}

export async function openPrivacyOptions() {
  await AdMob.showPrivacyOptionsForm();
}

Questo plugin è l'unica eccezione all'ordine sopra: il suo README richiede AdMob.initialize() prima requestConsentInfo()e il consenso non può essere presentato fino a che initialize() has run. initialize() avvia il SDK ma non richiede annunci, quindi la regola che conta è mai caricare un annuncio fino a quando canRequestAds è vero. Se hai bisogno che il SDK rimanga fermato fino a quando l'utente ha risposto, utilizza la scelta B, dove il consenso scorre prima AdMob.start().

Controlla canRequestAds prima di ogni caricamento di annunci, non solo all'avvio, perché l'utente può revocare il consenso dalla forma di opzioni di privacy.

Scelta B: @capgo/capacitor-admob con un ponte nativo UMP

@capgo/capacitor-admob ti offre AdMob.start(), configurazione di richiesta, banner, interstiziali, annunci premiati e interstiziali premiati, più autorizzazione di tracciamento iOS. Non avvolge UMP, quindi aggiungi un piccolo plugin locale dell'applicazione che esegue il flusso di consenso prima di chiamare AdMob.start().

bun add @capgo/capacitor-admob
bunx cap sync

Aggiungi il SDK UMP

  • iOS: aggiungi Google's GoogleUserMessagingPlatform pacchetto con il gestore di pacchetti Swift (Capacitor 8 progetti utilizzano SPM di default), o il pod CocoaPods dello stesso nome se il tuo progetto utilizza ancora CocoaPods.
  • Android: in android/app/build.gradle:
dependencies {
    implementation "com.google.android.ump:user-messaging-platform:<latest version>"
}

Utilizza l'ultima versione dal repository Maven di Google.

Crea ios/App/App/ConsentPlugin.swift:

import Capacitor
import UserMessagingPlatform

@objc(ConsentPlugin)
public class ConsentPlugin: CAPPlugin, CAPBridgedPlugin {
    public let identifier = "ConsentPlugin"
    public let jsName = "Consent"
    public let pluginMethods: [CAPPluginMethod] = [
        CAPPluginMethod(name: "gather", returnType: CAPPluginReturnPromise),
        CAPPluginMethod(name: "showPrivacyOptions", returnType: CAPPluginReturnPromise),
    ]

    @objc func gather(_ call: CAPPluginCall) {
        let parameters = RequestParameters()
        DispatchQueue.main.async {
            ConsentInformation.shared.requestConsentInfoUpdate(with: parameters) { error in
                if let error = error {
                    call.reject(error.localizedDescription)
                    return
                }
                guard let vc = self.bridge?.viewController else {
                    call.reject("No view controller")
                    return
                }
                ConsentForm.loadAndPresentIfRequired(from: vc) { formError in
                    if let formError = formError {
                        call.reject(formError.localizedDescription)
                        return
                    }
                    call.resolve(self.state())
                }
            }
        }
    }

    @objc func showPrivacyOptions(_ call: CAPPluginCall) {
        DispatchQueue.main.async {
            guard let vc = self.bridge?.viewController else {
                call.reject("No view controller")
                return
            }
            ConsentForm.presentPrivacyOptionsForm(from: vc) { formError in
                if let formError = formError {
                    call.reject(formError.localizedDescription)
                    return
                }
                call.resolve(self.state())
            }
        }
    }

    private func state() -> [String: Any] {
        return [
            "canRequestAds": ConsentInformation.shared.canRequestAds,
            "privacyOptionsRequired":
                ConsentInformation.shared.privacyOptionsRequirementStatus == .required,
        ]
    }
}

Registra da un CAPBridgeViewController sottoclasse, e impostalo sulla vista del controller in Main.storyboard:

import Capacitor

class MainViewController: CAPBridgeViewController {
    override open func capacitorDidLoad() {
        bridge?.registerPluginInstance(ConsentPlugin())
    }
}

Crea android/app/src/main/java/com/example/app/ConsentPlugin.java (utilizza il tuo nome del pacchetto):

package com.example.app;

import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;
import com.google.android.ump.ConsentInformation;
import com.google.android.ump.ConsentRequestParameters;
import com.google.android.ump.UserMessagingPlatform;

@CapacitorPlugin(name = "Consent")
public class ConsentPlugin extends Plugin {

    @PluginMethod
    public void gather(PluginCall call) {
        ConsentInformation info = UserMessagingPlatform.getConsentInformation(getContext());
        ConsentRequestParameters params = new ConsentRequestParameters.Builder().build();

        getActivity().runOnUiThread(() ->
            info.requestConsentInfoUpdate(
                getActivity(),
                params,
                () -> UserMessagingPlatform.loadAndShowConsentFormIfRequired(getActivity(), formError -> {
                    if (formError != null) {
                        call.reject(formError.getMessage());
                        return;
                    }
                    call.resolve(state(info));
                }),
                requestError -> call.reject(requestError.getMessage())
            )
        );
    }

    @PluginMethod
    public void showPrivacyOptions(PluginCall call) {
        getActivity().runOnUiThread(() ->
            UserMessagingPlatform.showPrivacyOptionsForm(getActivity(), formError -> {
                if (formError != null) {
                    call.reject(formError.getMessage());
                    return;
                }
                call.resolve(state(UserMessagingPlatform.getConsentInformation(getContext())));
            })
        );
    }

    private JSObject state(ConsentInformation info) {
        JSObject ret = new JSObject();
        ret.put("canRequestAds", info.canRequestAds());
        ret.put(
            "privacyOptionsRequired",
            info.getPrivacyOptionsRequirementStatus() ==
                ConsentInformation.PrivacyOptionsRequirementStatus.REQUIRED
        );
        return ret;
    }
}

Registra in MainActivity.java before super.onCreate:

public class MainActivity extends BridgeActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        registerPlugin(ConsentPlugin.class);
        super.onCreate(savedInstanceState);
    }
}

Chiamalo da TypeScript

import { registerPlugin } from '@capacitor/core';
import { AdMob, BannerAd } from '@capgo/capacitor-admob';

interface ConsentState {
  canRequestAds: boolean;
  privacyOptionsRequired: boolean;
}

interface ConsentPlugin {
  gather(): Promise<ConsentState>;
  showPrivacyOptions(): Promise<ConsentState>;
}

const Consent = registerPlugin<ConsentPlugin>('Consent');

export async function startAds() {
  let state: ConsentState;
  try {
    state = await Consent.gather();
  } catch (err) {
    console.warn('Consent flow failed', err);
    return { showPrivacyEntry: false };
  }

  if (state.canRequestAds) {
    await AdMob.start();
    const banner = new BannerAd({
      adUnitId: 'ca-app-pub-3940256099942544/2934735716', // Google test banner (iOS)
      position: 'bottom',
    });
    await banner.show();
  }

  return { showPrivacyEntry: state.privacyOptionsRequired };
}

export const openPrivacyOptions = () => Consent.showPrivacyOptions();

Native code changes need a new store build. After that, consent copy in your settings screen and ad placement logic can be shipped with Capgo aggiornamenti in tempo reale.

Passo 3: aggiungi l'ingresso punto delle opzioni di privacy

Quando UMP segnala che le opzioni di privacy sono richieste, Google aspetta un modo visibile per riaprire le scelte di consenso. Aggiungi una riga "Impostazioni di privacy" alla tua pagina di impostazioni e nascondila quando non è richiesta:

const { showPrivacyEntry } = await startAds();
document.querySelector('#privacy-row')?.toggleAttribute('hidden', !showPrivacyEntry);
document.querySelector('#privacy-row')?.addEventListener('click', () => openPrivacyOptions());

Dopo che l'utente modifica le sue scelte, leggi canRequestAds again before the next ad request.

Passo 4: App Tracking Transparency su iOS

ATT è separato da GDPR. ATT controlla l'accesso all'IDFA su iOS. Il consenso GDPR controlla se e come i dati personali possono essere elaborati. Di solito ne hai bisogno entrambi per un utente dell'UE su iOS.

  • Aggiungi NSUserTrackingUsageDescription Mostra Info.plist.
  • Mostra il messaggio di spiegazione dell'IDFA e attiva ATT, se hai configurato quel messaggio in AdMob. Altrimenti, richiedi ATT tu stesso dopo il flusso di consenso.

With @capgo/capacitor-admob puoi leggere e richiedere lo stato ATT direttamente:

import { AdMob, TrackingAuthorizationStatus } from '@capgo/capacitor-admob';

const { status } = await AdMob.trackingAuthorizationStatus();
if (status === TrackingAuthorizationStatus.notDetermined) {
  await AdMob.requestTrackingAuthorization();
}

Capgo ha anche una versione standalone Plugin di trasparenza delle tracce dell'app se hai bisogno di ATT per altri SDK. Non dimenticare di dichiarare la tracciatura nel tuo manifesto di privacy e nei label di privacy di App Store, consulta il nostro guida al manifesto sulla privacy.

Passo 5: test con geografia di debug

La UMP mostra solo il modulo GDPR agli utenti che si trova nell'UE, nel Regno Unito o in Svizzera. Per testare altrove:

  • Esegui l'app una volta e trova la riga di log della UMP con l'ID hashato del tuo dispositivo.
  • Aggiungilo come dispositivo di test e impostare la geografia di debug su EEA. Con il plugin della community, passa debugGeography e testDeviceIdentifiers to requestConsentInfo. Imposta in un ponte nativo, DebugSettings su iOS e ConsentDebugSettings su Android solo nei build di debug.
  • Riavvia il consenso tra le esecuzioni (resetConsentInfo() nel plugin della community, ConsentInformation.reset() naturalmente) quindi il form si mostra nuovamente.

Non inviare mai impostazioni di debug nei build di rilascio. Bloccale su una bandiera di build.

Passo 6: gestisci gli errori senza bloccare l'app

Le richieste di consenso possono fallire: nessuna rete, ID app configurato male, o messaggio non pubblicato. Trattare la fallita come "nessun annuncio per ora", non come un crash.

  • Se requestConsentInfoUpdate fallisce ma canRequestAds era vero da una sessione precedente, puoi richiedere ancora gli annunci.
  • If il modulo non si carica, registralo e riprova alla prossima esecuzione.
  • Non mostrare annunci mentre il modulo di consenso è sullo schermo.

Troubleshooting

La forma non si mostra mai. Non pubblicato, non assegnato a questo ID applicazione, o sei fuori dall'UE senza geografia di debug. Controlla l'ID applicazione AdMob in Info.plist e AndroidManifest.xml corrisponde al console.

La forma si mostra ogni esecuzione. L'utente l'ha chiuso senza una scelta, o chiami reset in produzione code.

canRequestAds Falso per gli utenti statunitensi. Hai pubblicato un messaggio degli Stati Uniti e l'utente ha optato per la vendita o la condivisione. Servi annunci limitati solo attraverso il SDK, non bypassarlo.

I partner di mediazione non ottengono il consenso. Assicurati che ogni adattatore partner sia aggiornato e elencato nella lista dei partner pubblicitari del messaggio GDPR.

La richiesta di consenso ATT per iOS non compare mai. NSUserTrackingUsageDescription è mancante, o l'utente ha disabilitato "Consenti agli app di richiedere di tracciare" nelle Impostazioni.

La conformità oltre la forma

UMP gestisce il lato pubblicitario. L'applicazione richiede ancora una politica di privacy che elenchi AdMob, le regole di conservazione dei dati e un modo per gestire le richieste di dati. Il nostro elenco di controllo di conformità GDPR copre il resto dell'applicazione.

Aggiornamenti in tempo reale per le app Capacitor

Quando un bug nel layer web è attivo, invia la correzione attraverso Capgo invece di aspettare giorni per l'approvazione della store. Gli utenti ricevono l'aggiornamento in background mentre le modifiche native rimangono nel normale percorso di revisione.

Ultimi articoli dal nostro Blog

Capgo offre le migliori informazioni che ti servono per creare un'app mobile davvero professionale.