9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

iOS14【ベストプラクティス】IDFAオプトインの事前説明プロンプトをサクッと対応する方法

Posted at

概要

アプリにAdMobを導入している場合は「Google Funding Choices」を利用すると

IDFA許諾の事前説明プロンプト提示後に → App Tracking Transparency(ATT)プロンプト

というフローを簡単に実装出来る。その手順。

「Google Funding Choices」とは?

簡単な操作でユーザーにメッセージと選択肢を提示し

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

など、義務付けられた同意やオプトアウトをスムーズに得られるソリューション。

  • プロンプトUIやメッセージのカスタマイズ、ローカライズ
  • レポーティング

などの機能がある。

「Google Funding Choices」をIDFA許諾で使うメリット

IDFA許諾率を上げる為のベストプラクティスとして
ユーザにIDFA取得についての事前説明を行った後に、オプトインを求めるATTプロンプトを出す方法が推奨されている。

このフローを別途UIなどの実装をすることなく簡単に作れる。

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を追加する

実装

事前説明フォームのリクエスト

func requestPrompt(){
        
        // UMPRequestParameters
        let parameters = UMPRequestParameters()
        // 許諾年齢未満であるか? IDFAの場合はFalse固定で良いと思われる
        parameters.tagForUnderAgeOfConsent = false
        
        // 事前許諾プロンプトの提示状況をリクエスト
        // メインスレッドで呼ぶ必要あり
        UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
            with: parameters,
            completionHandler: { error in
                
            if error != nil {
                debugPrint(error?.localizedDescription ?? "any error")
            } else {
                // 事前許諾プロンプトが利用可能かチェック
                let formStatus = UMPConsentInformation.sharedInstance.formStatus
//                UMPFormStatus.unknown:0 不明
//                UMPFormStatus.available:1 利用可能
//                UMPFormStatus.unavailable:2 利用不可
                debugPrint("Pre Permission Form Status \(formStatus.rawValue)")
                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 提示済み(プロンプト内アクション済み
                debugPrint("UMPConsentInformation.sharedInstance.consentStatus >> \(UMPConsentInformation.sharedInstance.consentStatus.rawValue)")
                if UMPConsentInformation.sharedInstance.consentStatus == .required {
                    // プロンプトの提示が必要
                    guard let vc = UIViewController.getFrontViewController() else {
                        return
                    }
                    form?.present(from: vc, completionHandler: { dismissError in
                        // ATTのプロンプト決定後コールバックされる
                        self.updateATTStatus()
                    })
                }
            }
        }
    }

ATTプロンプト決定後、許諾ステータスを確認する

private func updateATTStatus(){
        let status = ATTrackingManager.trackingAuthorizationStatus
        switch status {
        case .notDetermined, .restricted, .denied:
            debugPrint("ATT >> .notDetermined, .restricted, .denied")
        case .authorized:
            debugPrint("ATT >> authorized")
        @unknown default:
            debugPrint("ATT >> unknown")
        }
 }

参考

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?