広告を入れたアプリを、EEA(EU加盟国)・英国・スイスを含む177か国に配信していた。

そこにUMP(User Messaging Platform、AdMobの同意管理ツール)を一切実装していなかった。

ConsentInformationConsentFormも、コードのどこにも出てこない。広告を読み込む処理は、素のAdRequest()を呼んでいるだけだった。

何がまずいのか

AdMobの広告を配信するには、EEA・英国・スイスのユーザーから同意を取ることがGoogleの規約で義務づけられている。個人データを広告目的で使っていいかを、ユーザーに選ばせる画面のことだ。

これをやっていないまま該当地域に配信し続けると、最悪の場合AdMobアカウントが停止される。厄介なのは、複数アプリを同じAdMobアカウントで運用していると、違反していないアプリまで巻き添えになることだ。自分はアプリを3本、同じアカウントで運用していた。

なぜ気づかなかったのか

利用規約への同意広告の同意(CMP)を、同じものだと思い込んでいた。

自分のアプリには、起動時に利用規約とプライバシーポリシーへの同意を求める画面が既にあった。位置情報の利用許可を取る画面もあった。「同意まわりは対応済み」という認識でいた。

だが、この2つは全くの別物だ。

  • 利用規約・プライバシーポリシーへの同意 → アプリの利用条件についての同意
  • UMP(CMP) → 広告配信のために個人データを使うことについての同意

前者をやっていても、後者の代わりにはならない。この勘違いに気づいたのが、たまたま複数アプリを並行運用していて、あるアプリの実装を別のアプリと見比べたときだった。一つのアプリだけを見ていたら、おそらくずっと気づかなかった。

配信国をEEAから外せばいいのでは

一瞬そう思ったが、自分のケースでは選べなかった。

あるアプリは海外の開発コンテストに提出していて、審査員が実機にアプリをインストールして評価する規約になっていた。審査員の所在地はコンテスト側の裁量なので、こちらではコントロールできない。EEAを配信対象から外すと、そこにいる審査員がインストールできなくなるリスクがあった。

つまり「配信を絞って回避する」という選択肢が使えない状況で、UMPを実装する以外の道がなかった。

実装したこと

Googleが配布しているUMP SDKを使い、次の構成にした。

  • ConsentServiceを新規作成。起動時に同意状態を取得する
  • 広告を読み込む処理は、同意が取れていなければnullを返して広告を出さない(fail-closed)
  • 設定画面に「広告のプライバシー設定」を追加。ただしEEA圏のユーザーにだけ表示する(対象外の地域では従来どおり)

方針は2つに絞った。

  1. fail-closed: 同意状態が確認できない場合は、広告を出さない側に倒す。「たぶん大丈夫だろう」で出す方を選ばない
  2. 日本の体験は変えない: 対象地域外のユーザーには、今までどおり何も表示しない

実装後、flutter analyzeはエラーゼロ、新しい依存パッケージも追加していない(SDKは既存のAdMob関連パッケージに含まれていた)。ビルドサイズの増加も8.73KB程度で、実用上は誤差の範囲だった。

リリースして分かったこと

リリースしてすぐには終わらない。審査に通るまでは、違反状態が技術的には続いている。 審査待ちの数日間、何もできることはない。

もう一つ、複数アプリを同時に運用していると、「対応が終わったアプリ」と「まだのアプリ」が同時に存在する期間ができる。 3本のうち1本を直しても、残り2本が同じ穴を抱えたままなら、リスクは消えていない。1本ずつ直すのではなく、見つかった時点で全アプリを横断して確認する必要がある。

まとめ

  • 利用規約への同意と、広告配信のための同意(UMP/CMP)は別物。片方をやっていても、もう片方の代わりにはならない
  • 複数アプリで同じAdMobアカウントを使っていると、1本の違反が全アプリに波及しうる
  • 配信国を絞って回避する手が使えない場面もある(審査員・海外ユーザーへのアクセスが必要な場合など)
  • 実装自体は新規依存なしでできた。気づくのが遅れることの方がリスクが大きい