Obtaining Consent with the User Messaging Platform

Prerequisites

Read How IAB requirements affect EU consent messages.

Introduction

The UMP SDK provides tools for publishers to request consent for personalized ads as well as to handle Apple's App Tracking Transparency (ATT) requirements. Publishers can use the UMP SDK to handle either or both of these requests by showing a single form, as all of the configuration happens in Ad Manager Privacy & messaging.

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, which replaces the previous open source Consent SDK. The UMP SDK has been updated to support the latest IAB standards. We've also simplified the process of setting up consent forms and listing ad partners. All of these configurations can now conveniently be handled in Ad Manager Privacy & messaging.

This guide walks you through how to install the SDK, implement the IAB solutions, and enable testing features.

Import the SDK

CocoaPods (preferred)

The UMP SDK is included as a dependency of the Google Mobile Ads SDK Pod starting with Google Mobile Ads SDK 7.64.0.

The simplest 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 'Google-Mobile-Ads-SDK'

Then from the command line run:

pod install --repo-update

If you're new to CocoaPods, see their official documentation for info on how to create and use Podfiles.

Manual download

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>

Update your Info.plist

Add app ID to Info.plist

Obtain your app ID from the Mobile apps section of Ad Manager:

Add your app ID to your Info.plist:

<key>GADApplicationIdentifier</key>
<string>YOUR-APP-ID</string>

App Tracking Transparency

If you plan to use the UMP SDK to handle Apple's App Tracking Transparency requirements, ensure you've created, configured, and published your ATT message using Ad Manager Privacy & messaging.

In order for the UMP SDK to display a custom alert message, update your Info.plist to add the NSUserTrackingUsageDescription key with a custom message string describing your usage.

<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>

The usage description appears as part of the ATT dialog when you present the consent form:

Next, you'll need to link the AppTrackingTransparency framework:

While testing, remember that per Apple's requirements, the IDFA ATT dialog will only appear a single time since requestTrackingAuthorization: is a one-time request. To make the alert appear a second time, you must uninstall and reinstall your app on your test device.

Using the SDK

The SDK is designed to be used in a linear fashion. The steps for using the SDK are:

  1. Request the latest consent information.
  2. Check if consent is required.
  3. Check if a form is available and if so load a form.
  4. Present the form.
  5. Provide a way for users to change their consent.

It is recommended that you request an update of the consent information at every app launch. This will determine whether or not your user needs to provide consent.

This method should only be called from the main thread.

Swift

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

// Request an update to the consent information.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
    with: parameters,
    completionHandler: { error in
      if error != nil {
        // Handle the error.
      } else {
        // The consent information state was updated.
        // You are now ready to check if a form is
        // available.
      }
    })

Objective-C

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

// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
    requestConsentInfoUpdateWithParameters:parameters
                         completionHandler:^(NSError *_Nullable error) {
                           if (error) {
                             // Handle the error.
                           } else {
                             // The consent information state was updated.
                             // You are now ready to check if a form is
                             // available.
                           }
                         }];

Load a form if available

It is a best practice to load a form every time the user launches your app, even if you determine consent is not required, so that the form is ready to display in case the user wishes to change their consent setting.

The forms for obtaining consent are created in Interactive Media Ads UI. Once you have determined that you will ask a user for consent, the next step is to determine if a form is available. There are a variety of reasons why a form may not be available, such as:

  • The user has limit ad tracking enabled.
  • You tagged the user as under the age of consent.

To check if a form is available, use the formStatus property on UMPConsentInformation, which returns an enum of type UMPFormStatus. There are three possible values for UMPFormStatus:

  • UMPFormStatusUnknown: Form status unknown. You should call requestConsentInfoUpdateWithParameters:completionHandler: in this case.
  • UMPFormStatusAvailable: A consent form is available and can be loaded.
  • UMPFormStatusUnavailable: A consent form is not available.

Add a wrapper method for loading a form like so:

Swift

// Request an update to the consent information.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
    withParameters: parameters,
    completionHandler: { [self] error in

      // The consent information has updated.
      if error != nil {
        // Handle the error.
      } else {
        // The consent information state was updated.
        // You are now ready to see if a form is available.
        let formStatus = UMPConsentInformation.sharedInstance.formStatus
        if formStatus == UMPFormStatus.available {
          loadForm()
        }
      }
    })
...
func loadForm() {

}

Objective-C

// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
    requestConsentInfoUpdateWithParameters:parameters
                         completionHandler:^(NSError* _Nullable error) {

                           // The consent information has updated.
                           if (error) {
                             // Handle the error.
                           } else {
                             // The consent information state was updated.
                             // You are now ready to see if a form is available.
                             UMPFormStatus formStatus =
                                 UMPConsentInformation.sharedInstance
                                     .formStatus;
                             if (formStatus == UMPFormStatusAvailable) {
                               [self loadForm];
                             }
                           }
                         }];
...
- (void) loadForm {

}

To load the form you will use the static loadWithCompletionHandler: method on the UMPConsentForm class. This method must only be called from the main thread. Alter your loadForm method like so:

Swift

func loadForm() {
  UMPConsentForm.load(
      withCompletionHandler: { form, loadError in
        if loadError != nil {
          // Handle the error
        } else {
          // Present the form
        }
      })
}

Objective-C

- (void)loadForm {
  [UMPConsentForm
      loadWithCompletionHandler:^(UMPConsentForm *form, NSError *loadError) {
        if (loadError) {
          // Handle the error
        } else {
          // Present the form
        }
      }];
}

Present the form if required

To present the consent form, use the presentFromViewController:completionHandler: method on the UMPConsentForm class. You must determine if the user requires consent prior to presenting the form. To check if consent is required, examine the consentStatus property of the UMPConsentInformation object, which returns an enum of type UMPConsentStatus. There are four possible values for UMPConsentStatus:

  • UMPConsentStatusUnknown: Unknown consent status.
  • UMPConsentStatusRequired: User consent required but not yet obtained.
  • UMPConsentStatusNotRequired: User consent not required. For example, the user is not in the EEA or UK.
  • UMPConsentStatusObtained: User consent obtained. Personalization not defined.

Alter your loadForm method like so:

Swift

func loadForm() {
  UMPConsentForm.load(withCompletionHandler: { form, loadError in
    if loadError != nil {
      // Handle the error.
    } else {
      // Present the form. You can also hold on to the reference to present
      // later.
      if UMPConsentInformation.sharedInstance.consentStatus == UMPConsentStatus.required {
        form?.present(
            from: self,
            completionHandler: { dismissError in
              if UMPConsentInformation.sharedInstance.consentStatus == UMPConsentStatus.obtained {
                // App can start requesting ads.
              }

            })
      } else {
        // Keep the form available for changes to user consent.
      }
    }
  })
}

Objective-C

- (void)loadForm {
  [UMPConsentForm loadWithCompletionHandler:^(UMPConsentForm *form,
                                              NSError *loadError) {
    if (loadError) {
      // Handle the error.
    } else {
      // Present the form. You can also hold on to the reference to present
      // later.
      if (UMPConsentInformation.sharedInstance.consentStatus ==
          UMPConsentStatusRequired) {
        [form
            presentFromViewController:self
                    completionHandler:^(NSError *_Nullable dismissError) {
                      if (UMPConsentInformation.sharedInstance.consentStatus ==
                          UMPConsentStatusObtained) {
                        // App can start requesting ads.
                      }

                    }];
      } else {
        // Keep the form available for changes to user consent.
      }
    }
  }];
}

If consent is not required, you can maintain a reference to the form so that your user can change their consent status.

Testing

Force a geography

The UMP SDK provides a simple 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.

You will need to provide your test device's hashed ID in your app's debug settings to use the debug functionality. If you call requestConsentInfoUpdateWithParameters without setting this value, your app will log the required ID hash when run.

Swift

let parameters = UMPRequestParameters()
let debugSettings = UMPDebugSettings()
debugSettings.testDeviceIdentifiers = ["TEST-DEVICE-HASHED-ID"]
debugSettings.geography = UMPDebugGeography.EEA
parameters.debugSettings = debugSettings
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;
[UMPConsentInformation.sharedInstance
    requestConsentInfoUpdateWithParameters:parameters
                         completionHandler:^(NSError *_Nullable error){
                           ...
}];

To force the SDK to treat the device as though it is not in the EEA or UK, use UMPDebugGeographyNotEEA. Note that debug settings only work on test devices. Emulators do not need to be added to the device id list as they have testing enabled by default.

In testing your app with the UMP SDK, you may 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];

You should also call reset if you decide to remove the UMP SDK completely from your project.