Under the Google
EU User Consent
Policy
, you must
make certain disclosures to your users in the European Economic Area (EEA) along
with the UK and obtain their consent to use cookies or other local storage,
where legally required, and to use personal data (such as AdID) to serve ads.
This policy reflects the requirements of the EU ePrivacy Directive and the
General Data Protection Regulation (GDPR).
To support publishers in meeting their duties under this policy, Google offers
the User Messaging Platform (UMP) SDK. The UMP SDK has been updated to support
the latest IAB standards. All of these configurations can now conveniently be
handled in AdMob privacy & messaging.
Prerequisites
Create a message type
Create user messages with one of the
available user message types
under the
Privacy & messaging
tab of your
AdMob
account. The UMP SDK attempts to display a
user message created from the AdMob Application ID
set in your project. If no message is configured for your application, the SDK
returns an error.
For more details, see
About privacy and messaging
.
Import the SDK
CocoaPods (preferred)
The easiest way to import the SDK into an iOS project is to use
CocoaPods
. Open your project's
Podfile and add this line to your app's target:
pod 'GoogleUserMessagingPlatform'
Then, run the following command:
pod install --repo-update
If you're new to CocoaPods, see
Using
CocoaPods
for details on how to
create and use Podfiles.
Swift Package Manager
The UMP SDK also supports the Swift Package Manager. Follow these steps to
import the Swift package.
In Xcode, install the UMP SDK Swift Package by navigating to
File > Add Packages...
.
In the prompt that appears, search for the UMP SDK Swift Package GitHub
repository:
https://github.com/googleads/swift-package-manager-google-user-messaging-platform.git
Select the version of the UMP SDK Swift Package you want to use. For new
projects, we recommend using the
Up to Next Major Version
.
Xcode then resolves your package dependencies and downloads them in the
background. For more details on how to add package dependencies, see
Apple's
article
.
Manual download
The other way of importing the SDK is doing it manually.
Download the SDK
Then, drag the framework into your Xcode project, ensuring you select
Copy
items if needed
.
You can then include the framework in any file you need using:
Swift
import UserMessagingPlatform
Objective-C
#include <UserMessagingPlatform/UserMessagingPlatform.h>
Request for consent information
You should request an update of the user's consent information at every app
launch, using
requestConsentInfoUpdateWithParameters:completionHandler:
. This determines
whether your user needs to provide consent if they haven't done so already, or
if their consent has expired.
Here is an example of how to check the status from a
UIViewController
in the
viewDidLoad()
method.
Swift
override func viewDidLoad() {
super.viewDidLoad()
// Request an update for the consent information.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) {
[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];
// Request an update for the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:nil
completionHandler:^(NSError *_Nullable requestConsentError) {
if (requestConsentError) {
// Consent gathering failed.
NSLog(@"Error: %@", requestConsentError.localizedDescription);
return;
}
// TODO: Load and present the consent form.
}];
}
After you have received the most up-to-date consent status, call
loadAndPresentIfRequiredFromViewController:completionHandler:
on the
UMPConsentForm
class to load a consent form. If the
consent status is required, the SDK loads a form and immediately presents it
from the provided view controller. The completion handler
is called after the form is dismissed. If consent is not required, the completion handler
is called immediately.
Swift
override func viewDidLoad() {
super.viewDidLoad()
// Request an update for the consent information.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) {
[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];
__weak __typeof__(self) weakSelf = self;
// Request an update for the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:nil
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.
}];
}];
}
If you need to perform any actions after the user has made a choice or dismissed
the form, place that logic in the completion handler
for your form.
Request ads
Before requesting ads in your app, check if you have obtained consent
from the user using
UMPConsentInformation.sharedInstance.canRequestAds
. There are two
places to check while gathering consent:
- Once consent has been gathered in the current session.
- Immediately after you have called
requestConsentInfoUpdateWithParameters:completionHandler:
.
It is possible consent has been obtained in the previous session. As a latency
best practice, we recommend not waiting for the callback to complete so you can
start loading ads as soon as possible after your app launches.
If an error occurs during the consent gathering process, you should still
attempt to request ads. The UMP SDK uses the consent status from the previous
session.
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()
// Request an update for the consent information.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) {
[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];
__weak __typeof__(self) weakSelf = self;
// Request an update for the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:nil
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...];
});
}
Privacy options
Some consent forms require the user to modify their consent at any time. Adhere
to the following steps to implement a privacy options button if required.
To accomplish this:
- Implement a UI element, such as a button in your app's settings page,
that can trigger a privacy options form.
- Once
loadAndPresentIfRequiredFromViewController:completionHandler:
completes, check
privacyOptionsRequirementStatus
to determine whether to display
the UI element that can present the privacy options form.
- When a user interacts with your UI element, call
presentPrivacyOptionsFormFromViewController:completionHandler:
to show the form so the user can
update their privacy options at any time.
The following example shows how to present the privacy options form from
a
UIBarButtonItem
.
Swift
@IBOutlet weak var privacySettingsButton: UIBarButtonItem!
var isPrivacyOptionsRequired: Bool {
return UMPConsentInformation.sharedInstance.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.
}
}];
}
Testing
If you want to test the integration in your app as you're developing, follow
these steps to programmatically register your test device. Be sure to remove the
code that sets these test device IDs before you release your app.
- Call
requestConsentInfoUpdateWithParameters:completionHandler:
.
Check the log output for a message similar to the following example, which
shows your device ID and how to add it as a test device:
<UMP SDK>To enable debug mode for this device, set: UMPDebugSettings.testDeviceIdentifiers = @[2077ef9a63d2b398840261c8221a0c9b]
Copy your test device ID to your clipboard.
Modify your code to call
UMPDebugSettings().testDeviceIdentifiers
and pass in
a list of your test device IDs.
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){
...
}];
Force a geography
The UMP SDK provides a way to test your app's behavior as though the device was
located in the EEA or UK using the
debugGeography
property of type
UMPDebugGeography
on
UMPDebugSettings
. Note that
debug settings only work on test devices.
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){
...
}];
Reset consent state
In testing your app with the UMP SDK, you might find it helpful to reset the
state of the SDK so that you can simulate a user's first install experience.
The SDK provides the
reset
method to do this.
Swift
UMPConsentInformation.sharedInstance.reset()
Objective-C
[UMPConsentInformation.sharedInstance reset];
Examples on GitHub
UMP SDK integration examples:
Swift
|
Objective-C