💡

Google Funding Choicesを使ってIDFAの事前許諾プロンプトを提示

2021/02/04に公開

Funding Choices(ファンディング チョイス)

ユーザーから各種許諾を得る為に、カスタムメッセージと選択肢のプロンプトを簡単に作成できる。
義務付けられた同意やオプトアウト(orアウト)をスムーズに得られるGoogleのソリューション。

対応している同意項目

  • IDFA
  • EU 一般データ保護規則(GDPR
  • カリフォルニア州消費者プライバシー法(CCPA

機能

  • 説明プロンプトのUIやメッセージのカスタマイズ、ローカライズ
  • レポーティング
  • Contributor(オプション):ユーザから収益を得て、広告を削除できるらしい

メリット

iOS14.5(恐らく)では、AppTrackingTransparency(ATT)プロンプトを通じて、ユーザーから許諾を得ない限り、ユーザーをトラッキングしたり、IDFAにアクセス出来なくなる。

Funding Choicesを使用すると、トラッキングの許諾を得る前(ATTプロンプトを出す前)に
許諾率を上げる為の事前説明のフォームを簡単に提示できる。

つまり

事前許諾プロンプトを提示してユーザに説明
プロンプト内のボタンタップ

ATTプロンプト提示

というフローを簡単に作れる。(別途UIなどの実装をする必要がない)

AdMob側とFunding Choices側での手順

AdMobへログイン

  • 「プライバシーとメッセージ」タブ
  • 「ファンディング チョイスに移動」ボタン
  • 規約同意を行う
  • 「アプリ」タブ
  • 対象のアプリを選択
  • 「作成」をクリック
  • IDFAメッセージを選択
  • メッセージのタイトル(管理用)とデフォルト言語設定
  • 対応言語をチェックボックス選択
  • 「続行」
  • メッセージやUI編集
    最後は「保存」で終了。
    ※ なおこの時点では、メッセージは「非公開」ステータス。全ての準備が終わったら別途「公開」する。

アプリ側

AdMob SDKをインストール

  • CocoaPods
pod 'Google-Mobile-Ads-SDK'

「Info.plist」

  • AdMobのAppIDを設定
<key>GADApplicationIdentifier</key>
<string>YOUR-ADMOB-APP-ID</string>
  • App Tracking Transparency
    ※ ここのメッセージ設定は、ATTプロンプトで出すメッセージ(Funding Choicesで作成したメッセージとは別)
<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>

AppTrackingTransparency framework

  • Xcode > TARGETS > BuildPhases > Link Binary with Libraries
    AppTrackingTransparency frameworkを追加。

実装

import UserMessagingPlatform

事前許諾プロンプトを提示

    func requestPrompt(){
        
        // UMPRequestParameters
        let parameters = UMPRequestParameters()
        // 許諾年齢未満であるか?
        parameters.tagForUnderAgeOfConsent = false
        
        // 事前許諾プロンプトの提示状況をリクエスト
        // メインスレッドで呼ぶ必要あり
        UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
            with: parameters,
            completionHandler: { error in
                
            if error != nil {
                // Error
                debugPrint(error?.localizedDescription ?? "any error")
            } else {
                // 事前許諾プロンプトが利用可能かチェック
                let formStatus = UMPConsentInformation.sharedInstance.formStatus
//                UMPFormStatus.unknown:0 不明
//                UMPFormStatus.available:1 利用可能
//                UMPFormStatus.unavailable:2 利用不可
                if formStatus == .available {
                    DispatchQueue.main.async {
                        // プロンプトをロード
                        self.loadForm()
                    }
                }
            }
        })
    }

事前許諾プロンプトのロード

    private func loadForm() {
        // メインスレッドで呼ぶ必要あり
        UMPConsentForm.load { (form, loadError) in
            if loadError != nil{
                debugPrint(loadError?.localizedDescription ?? "any error")
            }else{
                // プロンプトの読み込み完了
                // 事前許諾の提示ステータスをチェック(※ATTステータスではない
//                UMPConsentStatus.unknown:0 不明
//                UMPConsentStatus.required:1 提示が必要
//                UMPConsentStatus.notRequired:2 提示の必要なし
//                UMPConsentStatus.obtained:3 提示済み(プロンプト内アクション済み
                if UMPConsentInformation.sharedInstance.consentStatus == .required {
                    // プロンプトの提示が必要
                    guard let vc = UIViewController.getFrontViewController() else {
                        return
                    }
                    form?.present(from: vc, completionHandler: { dismissError in
                        // ATTのプロンプト決定後コールバック
                        self.updateATTStatus()
                    })
                }
            }
        }
    }
    
    fileprivate func updateATTStatus(){
        if isAdvertisingTrackingEnabled() {
            debugPrint("😇")	    
        }else{
            debugPrint("ATT Status >> Deny, etc")
        }
    }    
    

注意点

  • UMPConsentInformation.sharedInstance.consentStatusはATTの許諾ステータスではないので、別途ATTrackingManager.trackingAuthorizationStatusを見る必要がある
  • Funding Choicesダッシュボード側で「公開」ステータスにする
  • ATTプロンプトは1度しか出せない
    もう一度表示するには、アプリを削除して再インストールする必要あり
  • 念のため、削除する前にリセットした方が良い?
    UMPConsentInformation.sharedInstance.reset()
    

参考

Discussion