iOS / Android

AdMobのGDPR 同意メッセージ対応を解説

Admobの、欧州個人情報保護法令GDPR対応の期限2024/1/16が迫ってきました!
莫大な制裁金を請求されて人生が終わらないよう、対応方法を解説していきます。

僕もまさに今対応しているので、その最新情報を解説していきます。
この記事の内容でiOS、Androidどちらも審査には問題なく通過しました。

 

GDPRの同意メッセージの作成

まずはGDPRの同意メッセージを作成しますがこれはガイダンスに従っていくだけで簡単に作成できます。

AdMobの管理画面左のメニューから「プライバシーとメッセージ」を選択。
表示される画面にある「欧州の規制」カードの「作成」をクリック。

次の画面で「使ってみる」をクリック。

次の画面で「欧州の規制に関するメッセージを作成する」をクリック。

すると欧州の規制に関するメッセージが表示されます。
右上の「アプリ」の欄を押すと、メッセージを表示させたいアプリを選択する画面がでるのでチェックを入れ、プライバシーポリシーのURLを追加します。

後は、右上の「公開」ボタンを押してメッセージの作成は完了です。
「同意しない」ボタンはオンにするかオフにするか選ばないとだめですが、特に理由がなければ「オフ」が良いと思います。

 

UMP (User Messaging Platform) SDKの実装

次にGDPRの同意画面を表示して同意してもらうためのSDKを実装していきます。

iOSの場合

Google推奨のCocoapods経由でライブラリーをインストールします。

pod 'GoogleUserMessagingPlatform'

 

インストールが終わったら、UMPライブラリーの呼び出しを追加します。

import UserMessagingPlatform

....

// Admobを1回だけ初期化するためのフラグ
private var isMobileAdsStartCalled = false

....

override func viewDidLoad() {
  super.viewDidLoad()

  ....


  // まだ同意していない場合に同意が必要か、または同意の有効期限が切れているかを判断
  UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) {
    [weak self] requestConsentError in
    guard let self else { return }

    if let consentError = requestConsentError {
      // 同意画面の呼び出し失敗
      return print("Error: \(consentError.localizedDescription)")
    }

    // GDPR同意画面を表示する。同意済み/拒否済みの場合はすぐcompleteが呼ばれる
    UMPConsentForm.loadAndPresentIfRequired(from: self) {
      [weak self] loadAndPresentError in
      guard let self else { return }

      if let consentError = loadAndPresentError {
        return print("Error: \(consentError.localizedDescription)")
      }

      // 同意画面の処理が終了していたら広告を表示させる
      if UMPConsentInformation.sharedInstance.canRequestAds {
        self.startGoogleMobileAdsSDK()
      }

      // 同意内容の変更オプションが必要かをUserDefaultsに保存しておき、必要なら設定画面に変更オプションの表示処理を追加する
      MyUtil.needGDPROption = (UMPConsentInformation.sharedInstance.privacyOptionsRequirementStatus == .required)
    }
  }

  // 同意済の場合に合わせて並行してリクエストしておく
  if UMPConsentInformation.sharedInstance.canRequestAds {
    startGoogleMobileAdsSDK()
  }

  ....

}


// 広告の初期化
private func startGoogleMobileAdsSDK() {
  DispatchQueue.main.async {
    if !self.isMobileAdsStartCalled {
      self.isMobileAdsStartCalled = true
            
      // Admobの初期化
      GADMobileAds.sharedInstance().start()
            
      // TODO: 広告の読み込み
      // GADInterstitialAd.load(...)
    }
  }
}

...

 

これで、対象の欧州圏内ではGDPRの同意画面が表示されます。

Androidでも同様の結果でしたが、「Consent」を選ぶと、無事広告が表示されます。

「Mange options」を押して、全ての項目をOFFにしてみると、広告が表示されませんでした。
広告のエラーをハンドリングしてみると「No ad to show.」というエラーが来ますが「制限された広告」という条件に出稿する人はいないのでこういう結果になるようです。

「Mange options」で一部を同意した場合も広告は出ました。

 

同意画面の表示処理の最後に次のようなコードがありますが、同意内容の変更機能が求められる場合があるようなので、そのフラグを保存しておき、必要なら設定画面に追加します。
GDPR圏外ではfalseがちゃんと来ました。

// 同意内容の変更オプションが必要かをUserDefaultsに保存しておき、必要なら設定画面に変更オプションの表示処理を追加する
MyUtil.needGDPROption = (UMPConsentInformation.sharedInstance.privacyOptionsRequirementStatus == .required)

設定画面の同意内容変更ボタンを押したら次のコードを実行させることで、再びGDPRの同意画面が表示されます。

UMPConsentForm.presentPrivacyOptionsForm(from: self) {
    [weak self] formError in
    guard let self, let formError else { return }

    // Handle the error.
  }

 

必要な時だけこっそり下にメニューを追加の例

 

iOSでのテスト方法

次のように、UMPの呼び出し処理の最初に、テスト端末のデバイスID登録と、現在の地域を強制的に欧州に設定することでテストが行なえます。

シミュレータは自動的にテスト端末扱いになるのでシミュレータでテストをするのが簡単です。
実機の場合は、下記の「consentInformation.requestConsentInfoUpdate」を呼び出すと次のようなログが表示されて、デバイスIDが分かります。

Use new ConsentDebugSettings.Builder().addTestDeviceHashedId(“FF0D4D179CD18E786E74923E44DDE416“) to set this as a debug device.

 

// まだ同意していない場合に同意が必要か、または同意の有効期限が切れているかを判断
let parameters = UMPRequestParameters()

// 何回もテストできるように同意状況をリセット
UMPConsentInformation.sharedInstance.reset()
        
let debugSettings = UMPDebugSettings()
debugSettings.testDeviceIdentifiers = ["TEST-DEVICE-HASHED-ID"]
debugSettings.geography = .EEA // 地域を欧州圏内に強制セット
parameters.debugSettings = debugSettings

// parametersをセット
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: parameters) {

....

 

IDFA対応 (ATT)はいつだすの?

iOS14から追加になった広告規制の確認ダイアログ(ATT)もUMPで一緒に行うのが一番簡単です。

Admobの管理画面で「プライバシーとメッセージ」を選び、IDFA説明メッセージ欄の「作成」を選びIDFA用のメッセージを作成すると、後は今まで説明した実装そのままで、自動的にATTの確認ダイアログも表示されます。

確認した所、GDPRに完全同意した場合、その後ATTダイアログが表示されますが、GDPRに一部同意もしくは完全拒否した場合はATTが表示されなかったのですが、Google側で自動的に処理しているので、正しいものと勝手に思っています。

 

Androidの場合

まずは、Moduleレベルのbuild.gradleに追記をしてライブラリーをインストールします。

dependencies {
  implementation("com.google.android.ump:user-messaging-platform:2.1.0")
}

 

インストールが終わったら、UMPライブラリーの呼び出しを追加します。

UMPの同意画面の処理が終わるまでどんな広告を出せばいいのか判定できないので広告の表示処理は行わず、同意処理が完了次第、Admobの初期化と広告の表示を実行するようにします。

import com.google.android.gms.ads.AdSize
import com.google.android.gms.ads.MobileAds
import com.google.android.gms.ads.admanager.AdManagerAdRequest
import com.google.android.gms.ads.admanager.AdManagerAdView

import com.google.android.ump.ConsentDebugSettings
import com.google.android.ump.ConsentForm
import com.google.android.ump.ConsentInformation
import com.google.android.ump.ConsentRequestParameters
import com.google.android.ump.UserMessagingPlatform
import java.util.concurrent.atomic.AtomicBoolean

....

class MainActivity : AppCompatActivity() {
  private lateinit var consentInformation: ConsentInformation
  private var isMobileAdsInitializeCalled = AtomicBoolean(false)

....

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)


    // まだ同意していない場合に同意が必要か、または同意の有効期限が切れているかを判断
    val params = ConsentRequestParameters
            .Builder()
            .build()
    consentInformation = UserMessagingPlatform.getConsentInformation(this)
    consentInformation.requestConsentInfoUpdate(this, params, {

      // GDPR同意画面の表示
      UserMessagingPlatform.loadAndShowConsentFormIfRequired(
        this@MainActivity,
        ConsentForm.OnConsentFormDismissedListener {
            loadAndShowError ->
          // 同意画面表示エラー
          if (loadAndShowError != null) {
            Log.w("GDPR 同意画面表示エラー", String.format("%s: %s",
              loadAndShowError.errorCode,
              loadAndShowError.message))
          }

          // GDPR同意画面の処理が完了
          if (consentInformation.canRequestAds()) {
            // 広告を表示させる
            initializeMobileAdsSdk()
          }

          // 同意内容の変更オプションが必要かをSharedPreferencesに保存しておき、必要なら設定画面に変更オプションの表示処理を追加する
          MyUtil.needGDPROption = (consentInformation.privacyOptionsRequirementStatus ==
      ConsentInformation.PrivacyOptionsRequirementStatus.REQUIRED)
        }
      )
    },
    {
      // エラー
        requestConsentError ->
      // Consent gathering failed.
      Log.w("GDPR error", String.format("%s: %s",
      requestConsentError.errorCode,
      requestConsentError.message))
    })

  ....

  }

  private fun initializeMobileAdsSdk() {
    if (isMobileAdsInitializeCalled.getAndSet(true)) {
      return
    }

    // AdMobの初期化
    MobileAds.initialize(this)

    // 広告の表示
    // InterstitialAd.load(...)
  }

....
  

 

これで、対象の欧州圏内ではGDPRの同意画面が表示されます。

iOSでも同様の結果でしたが、「Consent」を選ぶと、無事広告が表示されます。

「Mange options」を押して、全ての項目をOFFにしてみると、広告が表示されませんでした。
広告のエラーをハンドリングしてみると「No ad to show.」というエラーが来ますが「制限された広告」という条件に出稿する人はいないのでこういう結果になるようです。

「Mange options」で一部を同意した場合も広告は出ました。

 

同意画面の表示処理の最後に次のようなコードがありますが、同意内容の変更機能が求められる場合があるようなので、そのフラグを保存しておき、必要なら設定画面に追加します。
GDPR圏外ではfalseがちゃんと来ました。

// 同意内容の変更オプションが必要かをSharedPreferencesに保存しておき、必要なら設定画面に変更オプションの表示処理を追加する
MyUtil.needGDPROption = (consentInformation.privacyOptionsRequirementStatus ==
      ConsentInformation.PrivacyOptionsRequirementStatus.REQUIRED)

設定画面の同意内容変更ボタンを押したら次のコードを実行させることで、再びGDPRの同意画面が表示されます。

UserMessagingPlatform.showPrivacyOptionsForm(this) { formError ->
          formError?.let {
            // Handle the error.
          }
        }

 

Androidでのテスト方法

次のように、UMPの呼び出し処理の最初に、テスト端末のデバイスID登録と、現在の地域を強制的に欧州に設定することでテストが行なえます。

下記の「consentInformation.requestConsentInfoUpdate」を呼び出すと次のようなログが表示されて、デバイスIDが分かります。

Use new ConsentDebugSettings.Builder().addTestDeviceHashedId(“FF0D4D179CD18E786E74923E44DDE416“) to set this as a debug device.

 

// テスト端末を登録し、強制的に地域を欧州にセット
val debugSettings = ConsentDebugSettings.Builder(this)
  .setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA) // 強制欧州
  .addTestDeviceHashedId("FF0D4D179CD18E786E74923E44DDE416")  // テスト端末のデバイスIDをセット
  .build()

val params = ConsentRequestParameters
  .Builder()
  .setConsentDebugSettings(debugSettings)  // debugSettingsを追加
  .build()

consentInformation = UserMessagingPlatform.getConsentInformation(this)

// 何回もテストできるよう、GDPRの同意ステータスをリセット
consentInformation.reset()

// まだ同意していない場合に同意が必要か、または同意の有効期限が切れているかを判断
consentInformation.requestConsentInfoUpdate(

....