如何向您的iOS应用添加AppTrackingTransparency权限 1.在Xcode中添加框架2.添加NSUserTrackingUsageDescription3. import AppTrackingTransparency 适当4. ATTrackingManager.requestTrackingAuthorizationWithCompletionHandler:5. ATTrackingManager.trackingAuthorizationStatus6.在内

问题描述

我对iOS极为陌生,完全没有iOS开发经验,但是我得到了与preparing for iOS 14+相关的任务。根据我发现的https://support.google.com/admanager/answer/9997589,要确保没有收入损失,我需要做两件事。

  1. 为AdMob或Ad Manager安装最新的iOS版Google移动广告SDK(7.64或更高版本)
  2. 向您的iOS应用添加AppTrackingTransparency权限。

我已遵循一些指南,现在正准备将AppTrackingTransparency permission添加到iOS应用中。这是我正在使用的指南,https://developers.google.com/admob/ios/ios14#swift

我设法在Info.plist

添加键/值,如下所示
<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>

但这是我希望得到帮助的地方。我认为我仍然需要在AppTrackingTransparency的某处添加代码来请求用户权限。根据该指南,我认为需要以下代码才能显示App Tracking Transparency dialog BoxQuestion 1,我的假设正确吗?

import AppTrackingTransparency
import AdSupport
...
func requestIDFA() {
  ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
    // Tracking authorization completed. Start loading ads here.
    // loadAd()
  })
}

Question 2代码是否存在于AppDelegate.swift中?还是真的只是某个适合代码库的地方?谢谢。

解决方法

如果用户没有向应用授予跟踪权限会怎样?那么当用户不允许跟踪权限时,您将无法获得 IDFA,那么您的收入将再次下降...有关更多信息,请参阅 Answer

为了解决这个问题,Google 移动广告 SDK 支持使用 Apple 的 SKAdNetwork 进行转化跟踪,即使 IDFA 不可用,Google 也可以将应用安装归因。

面向广告商的 SKAdNetwork 解决方案,为 Apple 的 SKAdNetwork 提供开箱即用的支持,并最大限度地提高您未来在 iOS 14 及更高版本上的增长。

要解决此问题,请启用 SKAdNetwork 以跟踪转化

Google 移动广告 SDK 支持使用 Apple 的 SKAdNetwork 进行转化跟踪,即使 IDFA 不可用,Google 也可以将应用安装归因。

要启用此功能,请使用附加字典更新 SKAdNetworkItems 键,该字典定义了 Info.plist 中 Google 的 SKAdNetworkIdentifier 值。

    <key>SKAdNetworkItems</key>
  <array>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>cstr6suwn9.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>4fzdc2evr5.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>2fnua5tdw4.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>ydx93a7ass.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>5a6flpkh64.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>p78axxw29g.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>v72qych5uu.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>c6k4g5qg8m.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>s39g8k73mm.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>3qy4746246.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>3sh42y64q3.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>f38h382jlk.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>hs6bdukanm.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>prcb7njmu6.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>wzmmz9fp6w.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>yclnxrl5pm.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>4468km3ulz.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>t38b2kh725.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>7ug5zh24hu.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>9rd848q2bz.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>n6fk4nfna4.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>kbd757ywx3.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>9t245vhmpl.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>2u9pt9hc89.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>8s468mfl3y.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>av6w8kgt66.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>klf5c3l5u5.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>ppxm28t8ap.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>424m5254lk.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>uw77j35x4d.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>e5fvkxwrpn.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>zq492l623r.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>3qcr597p9d.skadnetwork</string>
    </dict>
  </array>
,

对于那些可能会遇到相同问题的人,我看到了带有功能的AppTrackingTransparency对话框,

import AppTrackingTransparency
import AdSupport

//NEWLY ADDED PERMISSIONS FOR iOS 14
func requestPermission() {
    if #available(iOS 14,*) {
        ATTrackingManager.requestTrackingAuthorization { status in
            switch status {
            case .authorized:
                // Tracking authorization dialog was shown
                // and we are authorized
                print("Authorized")
                
                // Now that we are authorized we can get the IDFA
                print(ASIdentifierManager.shared().advertisingIdentifier)
            case .denied:
                // Tracking authorization dialog was
                // shown and permission is denied
                print("Denied")
            case .notDetermined:
                // Tracking authorization dialog has not been shown
                print("Not Determined")
            case .restricted:
                print("Restricted")
            @unknown default:
                print("Unknown")
            }
        }
    }
}
//

然后我在应用程序的登录页面上简单地调用了函数requestPermission(),因此用户在登录之前会看到权限对话框。如果不调用该函数,则本指南https://developers.google.com/admob/ios/ios14中显示的对话框不会不会出现在我身上。

本文有一个示例github项目:https://medium.com/@nish.bhasin/how-to-get-idfa-in-ios14-54f7ea02aa42

,

我们正在使用 Firebase 和 Facebook,为了让应用获得批准,我们将这两个调用都置于 ATT 保护“背后”,即:

对于 Facebook(来自 AppDelegate):

        if #available(iOS 14,*) {
            ATTrackingManager.requestTrackingAuthorization { status in
                if status == .authorized {
                        ApplicationDelegate.shared.application(
                            application,didFinishLaunchingWithOptions: launchOptions
                        )
                }
            }

对于 Firebase:

    if #available(iOS 14,*) {
        ATTrackingManager.requestTrackingAuthorization { status in
            if status == .authorized {
                Analytics.logEvent(eventName,parameters: [:])
            }
        }
    }

至于通知的 firebase 令牌,我们没有将它们包含在保护之后,也没有问题。

,

根据您发布的链接:

https://developers.google.com/admob/ios/ios14#swift

避免 AdMob 收入损失的主要方式是将其添加到 Info.plist 中:

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\bin

我不知道何时/是否需要 AppTrackingTransparency 权限。我知道苹果说你需要它,但他们没有给出最后期限。 Google 说“如果您决定包含 App Tracking Transparency”,这对我来说是暗示不要打扰!

,

还有其他事情,Apple已通过“允许应用程序请求跟踪”添加了新的隐私设置“跟踪”。如果禁用此选项,iOS将忽略所有权限屏幕请求。

您可以在article here

中查看更多详细信息 ,

作为对@mark 答案的补充,您还应该在关键隐私 - 跟踪使用说明中的 plist 文件中添加权限声明

,

根据 iOS 14.0+ 中的 App Tracking Transparency 提交到 App Store 的所有新应用现在都需要这样做。

1.在Xcode中添加框架

这可以通过导航到 <PROJECT_NAME>.xcproject / <PROJECT_NAME>.xcworkspace -> General -> Frameworks,Libraries,and Embedded Content 来实现。

General Xcode Tab with ATT.framework

2.添加NSUserTrackingUsageDescription

这是一个需要添加到 Info.plist 的字符串键。

3. import AppTrackingTransparency 适当

4. ATTrackingManager.requestTrackingAuthorizationWithCompletionHandler:

在首次启动应用程序时建议使用此函数,以确保捕获该值。该提示仅显示应用是否为全新安装且用户同意状态未知。

Apple 只返回两个值,分别映射到 grant 或 denied:

ATTrackingManagerAuthorizationStatusAuthorized 表示授权同意跟踪的用户。

ATTrackingManagerAuthorizationStatusDenied 表示用户拒绝同意跟踪。

注意:UI 逻辑需要包装在 DispatchQueue.main 队列中,因为完成块当前在并发 DispatchQueue 上执行。

5. ATTrackingManager.trackingAuthorizationStatus

通过具有 4 possible enum valuesATTrackingManager.trackingAuthorizationStatus 跟踪同意更改:

  1. ATTrackingManagerAuthorizationStatusAuthorized
  2. ATTrackingManagerAuthorizationStatusDenied
  3. ATTrackingManagerAuthorizationStatusNotDetermined
  4. ATTrackingManagerAuthorizationStatusRestricted

6.在内部服务器上跟踪用户的同意状态

如果您要捕获自己的分析,则此步骤是必要的,因为用户可以随时使用 iOS 设置切换同意。我们还需要在拒绝同意时读取状态值后,在应用启动时从配置中禁用 Firebase AnalyticsFlurry Analytics 或其他分析提供程序。

重要提示

包裹

if #available(iOS 14.0,*)

无论您在哪里调用 ATTrackingManager,因为该请求将无法在较旧的 iOS 版本上完成?。使用您自己的后端标志或在设备本地跟踪旧版 iOS 上的同意情况。

如果您跟踪用户,Apple 建议尽快实施新的 ATT 要求,因为在此期间您将无法获得 App Store 的新更新,即使生产崩溃也是如此。如果您定期更新您的应用,不仅您的用户会更开心,而且您的 App Store 排名也会提高。

想要在应用中切换用户同意吗?有关详细信息,请参阅 here

,
  1. 打开 info.plist 文件,添加 SKAdNetworkIdentifierNSUserTrackingUsageDescription。以下仅适用于 Google (Admob),您可以找到完整列表 here

    <key>SKAdNetworkItems</key>
    <array>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>cstr6suwn9.skadnetwork</string>
        </dict>
    </array>
    
    //..
    
    <key>NSUserTrackingUsageDescription</key>
    <string>This identifier will be used to deliver personalized ads to you.</string>
    
  2. 请求 ATT 对话。 (为简单起见,我在应用加载后立即请求)

    #import <AppTrackingTransparency/AppTrackingTransparency.h>
    #import <AdSupport/AdSupport.h>
    
    //...
    
    - (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
        // ...
    
        if (@available(iOS 14.0,*))
        {
            [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
            // Tracking authorization completed. Start loading ads here.
            // [self loadAd];
          }];
    
      return [super application:application didFinishLaunchingWithOptions:launchOptions];
    
    }