Integrating Consent with Google Ads Outside of TCF

This article is for clients that need to action consent manually outside of the IAB TCF framework for programmatic advertising served through Google Ads.

iOS

IAB TCF 2.0

When using the Google Ads Mobile SDK, IAB TCF values are picked up automatically per Google’s documentation.

GDPR consent forwarding outside of the IAB Framework takes advantage of Google’s NPA (Non-Personalized Advertising) flag. There are two methods to implement this while utilizing OneTrust’s iOS SDK, depending on your use of Ad Requests.

If your application uses a common ad request bundle

  1. Default the NPA status to 1, meaning that no non-personalized ads will be displayed until consent is given.

  2. Listen for changes to the user's consent and update the ad request bundle.

    JAVASCRIPT
    /* App Startup
      In this case, we've created a singleton AdManager class so that
      the ad request can be reused. The Extras object and Request object
      have already been created at initialization.
     */
    let extras = AdManager.shared.extras
    extras.additionalParameters = ["npa": "1"]
    AdManager.shared.request.register(extras)
    
    //Listener for changes
    @objc func onAdConsentChanged(_ notification:Notification){
      if let consentStatus = notification.object as? Int{
        let extras = AdManager.shared.extras
        extras.additionalPararmeters = ["npa":consentStatus]
        AdManager.shared.request.register(extras)
      }
    }
    
    /* Register Observer
      In this example, we're actioning based on the status of category
      C0004, which is the Targeting category in OneTrust by default.
     */
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(onAdConsentChanged(_:)),
                                           name: NSNotification.Name("C0004"),
                                           object: nil)

If your application does not reuse an ad request bundle

  1. Query for the current consent status.

  2. Update the ad request bundle.

    CAUTION:

    It’s important to action a user’s consent as soon as possible after they update their consent. With this approach, it’s possible that a GADRequest was created before a user has updated their consent and thus is using an old consent value. For this reason, it’s important to check the consent status often, and potentially use UI Interaction Listeners to detect when a user has opened the preference center.

    JAVASCRIPT
    let request = GADRequest()
    let extras = GADExtras()
    
    /* In this example, we're using C0004, which corresponds to the default
    Targeting category in OneTrust. The getConsentStatus function has the potential
    to return a -1 if the OneTrust data hasn't ever been downloaded successfully 
    or the category ID does not exist. Because of this, we'll do a ternary check
    so that we always get a 1 or a 0 back. */
    let categoryConsent = OTPublishersHeadlessSDK.shared.getConsentStatus(forCategory:"C0004")
    let consent = categoryConsent == 1 ? 1 : 0
    
    extras.additionalParameters = ["npa": consent]
    request.register(extras)

Android

IAB TCF 2.0

When using the Google Ads Mobile SDK, IAB TCF values are picked up automatically per Google’s documentation.

GDPR consent forwarding outside of the IAB Framework takes advantage of Google’s NPA (Non-Personalized Advertising) flag. There are two methods to implement this while utilizing OneTrust’s iOS SDK, depending on your use of Ad Requests.

If your application uses a common ad request bundle

  1. Default the NPA status to 1, meaning that no non-personalized ads will be displayed until consent is given.

  2. Listen for changes to the user's consent and update the bundle.

    CODE
    //By default
    Bundle extras = new Bundle();
    extras.putString("npa", "1");
    
    AdRequest request = new AdRequest.Builder()
        .addNetworkExtrasBundle(AdMobAdapter.class, extras)
        .build();
    
    //Build a new AdRequest when consent changes
    BroadcastReceiver onAdConsentChanged = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
              int consent = intent.getIntExtra(OTBroadcastServiceKeys.EVENT_STATUS, -1);
              extras = new Bundle();
              extras.putString("npa", consent);
              
              request = new AdRequest.Builder()
                .addNetworkExtrasBundle(AdMobAdapter.class, extras)
                .build();
          }
    };
    
    /* Register Broadcast Receiver
      In this example, we're actioning based on the status of category
      C0004, which is the Targeting category in OneTrust by default.
    */
    registerReceiver(onAdConsentChanged, new IntentFilter("C0004"));

If your application does not reuse an ad request bundle

  1. Query for the current consent status.

  2. Update the ad request bundle.

    Attention:

    It’s important to action a user’s consent as soon as possible after they update their consent. With this approach, it’s possible that a GADRequest was created before a user has updated their consent and thus is using an old consent value. For this reason, it’s important to check the consent status often, and potentially use UI Interaction Listeners to detect when a user has opened the preference center.

    JAVASCRIPT
    /* In this example, we're using C0004, which corresponds to the default
    Targeting category in OneTrust. The getConsentStatus function has the potential
    to return a -1 if the OneTrust data hasn't ever been downloaded successfully 
    or the category ID does not exist. Because of this, we'll do a ternary check
    so that we always get a 1 or a 0 back. */
    
    OTPublishersHeadlessSDK ot = new OTPublishersHeadlessSDK(context);
    int categoryConsent = getConsentStatusForGroupId("C0004");
    int consent = categoryConsent == 1 ? 1 : 0;
    
    Bundle extras = new Bundle();
    extras.putString("npa", consent);
    
    AdRequest request = new AdRequest.Builder()
        .addNetworkExtrasBundle(AdMobAdapter.class, extras)
        .build();