开始使用

根据 Google 欧盟地区用户意见征求政策,您必须向位于欧洲经济区 (EEA) 和英国境内的用户披露相关信息,在法律有相应要求的情况下,必须就 Cookie 或其他本地存储方式的使用征得他们的同意,并使用个人数据(例如 AdID)来投放广告。此政策反映了欧盟《电子隐私指令》和《一般数据保护条例》(GDPR) 的要求。

为了帮助发布商履行此政策规定的职责,Google 提供了 User Messaging Platform (UMP) SDK。UMP SDK 现已更新,支持最新的 IAB 标准。所有这些配置现在都可以 AdMob 在“隐私权和消息”中轻松处理。

前提条件

创建消息类型

创建用户消息时,应选择 可用的用户消息类型 , (在您的 AdMob 帐号的隐私权和消息标签页下)。UMP SDK 会尝试显示通过项目中设置的 AdMob 应用 ID 创建的用户消息。如果没有为您的应用配置消息,SDK 会返回错误。

如需了解详情,请参阅 隐私权和消息简介

导入 SDK

CocoaPods(首选)

如要将该 SDK 导入 iOS 项目,最简便的方法就是使用 CocoaPods。请打开项目的 Podfile 并将下面这行代码添加到应用的目标中:

pod 'GoogleUserMessagingPlatform'

然后运行以下命令:

pod install --repo-update

如果您刚开始接触 CocoaPods,请参阅使用 CocoaPods,详细了解如何创建和使用 Podfile。

手动下载

另一种方法是手动导入 SDK。

下载 SDK

然后,将框架拖入您的 Xcode 项目中,确保已选中 Copy items if needed

然后,您便可将该框架包含在需要使用的任何文件中:

Swift

import UserMessagingPlatform

Objective-C

#include <UserMessagingPlatform/UserMessagingPlatform.h>

每次启动应用时,您都应使用 requestConsentInfoUpdateWithParameters:completionHandler:请求更新用户的意见征求信息。这决定了您的用户是需要提供用户意见征求(如果尚未提供)或用户意见征求是否已过期。

以下示例说明了如何在 viewDidLoad() 方法中从 UIViewController 检查状态。

Swift

override func viewDidLoad() {
  super.viewDidLoad()

  // Create a UMPRequestParameters object.
  let parameters = UMPRequestParameters()
  // Set tag for under age of consent. false means users are not under age
  // of consent.
  parameters.tagForUnderAgeOfConsent = false

  // Request an update for the consent information.
  UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: parameters) {
    [weak self] requestConsentError in
    guard let self else { return }

    if let consentError = requestConsentError {
      // Consent gathering failed.
      return print("Error: \(consentError.localizedDescription)")
    }

    // TODO: Load and present the consent form.
  }
}

Objective-C

- (void)viewDidLoad {
  [super viewDidLoad];

  // Create a UMPRequestParameters object.
  UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
  // Set tag for under age of consent. NO means users are not under age
  // of consent.
  parameters.tagForUnderAgeOfConsent = NO;

  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:parameters
          completionHandler:^(NSError *_Nullable requestConsentError) {
            if (requestConsentError) {
              // Consent gathering failed.
              NSLog(@"Error: %@", requestConsentError.localizedDescription);
              return;
            }

            // TODO: Load and present the consent form.
          }];
}

根据需要加载并显示用户意见征求表单

重要提示:以下 API 与 UMP SDK 2.1.0 或更高版本兼容。

收到最新的用户意见征求状态后,请对UMPConsentForm 类调用loadAndPresentIfRequiredFromViewController:completionHandler: 以加载用户意见征求表单。如果需要提供同意情况,SDK 会加载一个表单,并立即 从提供的 view controller显示该表单。用户关闭表单后,系统会调用 completion handler 。如果不需要征得用户同意,系统会立即调用 completion handler 。

Swift

override func viewDidLoad() {
  super.viewDidLoad()

  // Create a UMPRequestParameters object.
  let parameters = UMPRequestParameters()
  // Set tag for under age of consent. false means users are not under age
  // of consent.
  parameters.tagForUnderAgeOfConsent = false

  // Request an update for the consent information.
  UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: parameters) {
    [weak self] requestConsentError in
    guard let self else { return }

    if let consentError = requestConsentError {
      // Consent gathering failed.
      return print("Error: \(consentError.localizedDescription)")
    }

    UMPConsentForm.loadAndPresentIfRequired(from: self) {
      [weak self] loadAndPresentError in
      guard let self else { return }

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

      // Consent has been gathered.
    }
  }
}

Objective-C

- (void)viewDidLoad {
  [super viewDidLoad];

  // Create a UMPRequestParameters object.
  UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
  // Set tag for under age of consent. NO means users are not under age
  // of consent.
  parameters.tagForUnderAgeOfConsent = NO;

  __weak __typeof__(self) weakSelf = self;
  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:parameters
          completionHandler:^(NSError *_Nullable requestConsentError) {
            if (requestConsentError) {
              // Consent gathering failed.
              NSLog(@"Error: %@", requestConsentError.localizedDescription);
              return;
            }

            __strong __typeof__(self) strongSelf = weakSelf;
            if (!strongSelf) {
              return;
            }

            [UMPConsentForm loadAndPresentIfRequiredFromViewController:strongSelf
                completionHandler:^(NSError *loadAndPresentError) {
                  if (loadAndPresentError) {
                    // Consent gathering failed.
                    NSLog(@"Error: %@", loadAndPresentError.localizedDescription);
                    return;
                  }

                  // Consent has been gathered.
                }];
          }];
}

如果您需要在用户做出选择或关闭表单后执行操作,请将相应逻辑放入表单的 completion handler中。

提出广告请求

在您的应用中请求广告之前,请检查您是否已使用 UMPConsentInformation.sharedInstance.canRequestAds征得用户同意。在征求用户意见时,可在以下两个位置进行检查:

  1. 在当前会话中征求用户意见后。
  2. 调用 requestConsentInfoUpdateWithParameters:completionHandler:后立即执行。 可能是在之前的会话中已征得用户同意。作为延迟时间最佳做法,我们建议您不要等待回调完成,这样您就可以在应用启动后尽快开始加载广告。
之前, UMPConsentInformation.sharedInstance.canRequestAds 始终返回 false

如果在征求用户意见的过程中发生错误,您仍应尝试请求广告。UMP SDK 会使用上一个会话的用户意见征求状态。

Swift

class ViewController: UIViewController {

  // Use a boolean to initialize the Google Mobile Ads SDK and load ads once.
  private var isMobileAdsStartCalled = false

  override func viewDidLoad() {
    super.viewDidLoad()

    // Create a UMPRequestParameters object.
    let parameters = UMPRequestParameters()
    // Set tag for under age of consent. false means users are not under age
    // of consent.
    parameters.tagForUnderAgeOfConsent = false

    // Request an update for the consent information.
    UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: parameters) {
      [weak self] requestConsentError in
      guard let self else { return }

      if let consentError = requestConsentError {
        // Consent gathering failed.
        return print("Error: \(consentError.localizedDescription)")
      }

      UMPConsentForm.loadAndPresentIfRequired(from: self) {
        [weak self] loadAndPresentError in
        guard let self else { return }

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

        // Consent has been gathered.
        if UMPConsentInformation.sharedInstance.canRequestAds {
          self.startGoogleMobileAdsSDK()
        }
      }
    }
    
    // Check if you can initialize the Google Mobile Ads SDK in parallel
    // while checking for new consent information. Consent obtained in
    // the previous session can be used to request ads.
    if UMPConsentInformation.sharedInstance.canRequestAds {
      startGoogleMobileAdsSDK()
    }
  }
  
  private func startGoogleMobileAdsSDK() {
    DispatchQueue.main.async {
      guard !self.isMobileAdsStartCalled else { return }

      self.isMobileAdsStartCalled = true

      // Initialize the Google Mobile Ads SDK.
      GADMobileAds.sharedInstance().start()

      // TODO: Request an ad.
      // GADInterstitialAd.load(...)
    }
  }
}

Objective-C

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  // Create a UMPRequestParameters object.
  UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
  // Set tag for under age of consent. NO means users are not under age
  // of consent.
  parameters.tagForUnderAgeOfConsent = NO;

  __weak __typeof__(self) weakSelf = self;
  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:parameters
          completionHandler:^(NSError *_Nullable requestConsentError) {
            if (requestConsentError) {
              // Consent gathering failed.
              NSLog(@"Error: %@", requestConsentError.localizedDescription);
              return;
            }
            __strong __typeof__(self) strongSelf = weakSelf;
            if (!strongSelf) {
              return;
            }

            [UMPConsentForm loadAndPresentIfRequiredFromViewController:strongSelf
                completionHandler:^(NSError *loadAndPresentError) {
                  if (loadAndPresentError) {
                    // Consent gathering failed.
                    NSLog(@"Error: %@", loadAndPresentError.localizedDescription);
                    return;
                  }

                  // Consent has been gathered.
                  __strong __typeof__(self) strongSelf = weakSelf;
                  if (!strongSelf) {
                    return;
                  }

                  if (UMPConsentInformation.sharedInstance.canRequestAds) {
                    [strongSelf startGoogleMobileAdsSDK];
                  }
                }];
          }];

  // Check if you can initialize the Google Mobile Ads SDK in parallel
  // while checking for new consent information. Consent obtained in
  // the previous session can be used to request ads.
  if (UMPConsentInformation.sharedInstance.canRequestAds) {
    [self startGoogleMobileAdsSDK];
  }
}

- (void)startGoogleMobileAdsSDK {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    // Initialize the Google Mobile Ads SDK.
    [GADMobileAds.sharedInstance startWithCompletionHandler:nil];

    // TODO: Request an ad.
    // [GADInterstitialAd loadWithAdUnitID...];
  });
}

隐私权选项

某些意见征求表单要求用户随时修改其同意声明。如果需要,请按照以下步骤实现隐私设置选项按钮。

要实现这一目标,需要完成以下步骤:

  1. 实现可以触发隐私设置选项表单的界面元素,例如应用设置页面中的按钮。
  2. loadAndPresentIfRequiredFromViewController:completionHandler: 完成后,检查privacyOptionsRequirementStatus 以确定是否显示可呈现隐私设置选项表单的界面元素。
  3. 当用户与您的界面元素互动时,调用presentPrivacyOptionsFormFromViewController:completionHandler: 以显示该表单,以便用户随时更新其隐私设置选项。

以下示例展示了如何通过 UIBarButtonItem 显示隐私权选项表单。

Swift

@IBOutlet weak var privacySettingsButton: UIBarButtonItem!

var isPrivacyOptionsRequired: Bool {
  return UMPConsentInformation.shared.privacyOptionsRequirementStatus == .required
}

override func viewDidLoad() {
  // ...

  // Request an update for the consent information.
  UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: parameters) {
    // ...

    UMPConsentForm.loadAndPresentIfRequired(from: self) {
      //...

      // Consent has been gathered.

      // Show the button if privacy options are required.
      self.privacySettingsButton.isEnabled = isPrivacyOptionsRequired
    }
  }
  // ...
}

// Present the privacy options form when a user interacts with the
// privacy settings button.
@IBAction func privacySettingsTapped(_ sender: UIBarButtonItem) {
  UMPConsentForm.presentPrivacyOptionsForm(from: self) {
    [weak self] formError in
    guard let self, let formError else { return }

    // Handle the error.
  }
}

Objective-C

@interface ViewController ()
@property(weak, nonatomic) IBOutlet UIBarButtonItem *privacySettingsButton;
@end

- (BOOL)isPrivacyOptionsRequired {
  return UMPConsentInformation.sharedInstance.privacyOptionsRequirementStatus ==
         UMPPrivacyOptionsRequirementStatusRequired;
}

- (void)viewDidLoad {
  // ...

  __weak __typeof__(self) weakSelf = self;
  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:parameters
          completionHandler:^(NSError *_Nullable requestConsentError) {
            // ...

            [UMPConsentForm loadAndPresentIfRequiredFromViewController:strongSelf
                completionHandler:^(NSError *loadAndPresentError) {
                  // ...

                  // Consent has been gathered.

                  // Show the button if privacy options are required.
                  strongSelf.privacySettingsButton.enabled = isPrivacyOptionsRequired;
                }];
          }];
}

// Present the privacy options form when a user interacts with your
// privacy settings button.
- (IBAction)privacySettingsTapped:(UIBarButtonItem *)sender {
  [UMPConsentForm presentPrivacyOptionsFormFromViewController:self
                                completionHandler:^(NSError *_Nullable formError) {
                                  if (formError) {
                                    // Handle the error.
                                  }
                                }];
}

测试

如果您希望在开发过程中测试应用中的集成,请按照以下步骤以编程方式注册测试设备。

  1. 调用 requestConsentInfoUpdateWithParameters:completionHandler:
  2. 检查日志输出中是否有类似如下的消息,该消息显示了您的设备 ID 以及如何将其添加为测试设备:

    <UMP SDK>To enable debug mode for this device, set: UMPDebugSettings.testDeviceIdentifiers = @[2077ef9a63d2b398840261c8221a0c9b]
    
  3. 将测试设备 ID 复制到剪贴板。

  4. 修改代码,将其调用 UMPDebugSettings().testDeviceIdentifiers ,并传入您的测试设备 ID 列表。

Swift

let parameters = UMPRequestParameters()
let debugSettings = UMPDebugSettings()
debugSettings.testDeviceIdentifiers = ["TEST-DEVICE-HASHED-ID"]
parameters.debugSettings = debugSettings
// Include the UMPRequestParameters in your consent request.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
    with: parameters,
    completionHandler: { error in
      ...
    })

Objective-C

UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
UMPDebugSettings *debugSettings = [[UMPDebugSettings alloc] init];
debugSettings.testDeviceIdentifiers = @[ @"TEST-DEVICE-HASHED-ID" ];
parameters.debugSettings = debugSettings;
// Include the UMPRequestParameters in your consent request.
[UMPConsentInformation.sharedInstance
    requestConsentInfoUpdateWithParameters:parameters
                        completionHandler:^(NSError *_Nullable error){
                          ...
}];

强制应用地理位置

UMP SDK 提供了一种使用 the debugGeography property of type UMPDebugGeography on UMPDebugSettings测试应用行为的方式,就像设备位于欧洲经济区 (EEA) 或英国一样。请注意,调试设置仅适用于测试设备。

Swift

let parameters = UMPRequestParameters()
let debugSettings = UMPDebugSettings()
debugSettings.testDeviceIdentifiers = ["TEST-DEVICE-HASHED-ID"]
debugSettings.geography = .EEA
parameters.debugSettings = debugSettings
// Include the UMPRequestParameters in your consent request.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
    with: parameters,
    completionHandler: { error in
      ...
    })

Objective-C

UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
UMPDebugSettings *debugSettings = [[UMPDebugSettings alloc] init];
debugSettings.testDeviceIdentifiers = @[ @"TEST-DEVICE-HASHED-ID" ];
debugSettings.geography = UMPDebugGeographyEEA;
parameters.debugSettings = debugSettings;
// Include the UMPRequestParameters in your consent request.
[UMPConsentInformation.sharedInstance
    requestConsentInfoUpdateWithParameters:parameters
                         completionHandler:^(NSError *_Nullable error){
                           ...
}];

使用 UMP SDK 测试应用时,您可能会发现重置 SDK 的状态有助于模拟用户的首次安装体验。SDK 提供了 reset 方法来实现此目的。

Swift

UMPConsentInformation.sharedInstance.reset()

Objective-C

[UMPConsentInformation.sharedInstance reset];

GitHub 上的示例

UMP SDK 集成示例: Swift | Objective-C