When Consent Changes

Overview

When a user updates their consent choices or interacts with the OT SDK UI, the Application needs to become aware so that it can control the next set of actions like:

  • Allowing or restricting processing of 3rd party SDKs based on their categorization
  • Passing latest user consent values to 3rd Party SDKs
  • Passing the IAB's encoded TC String to 3rd party SDKs
  • Passing the IAB's USP String to 3rd Party SDKs
  • Routing the User to another location in the App
  • Displaying messages to the User of their changes
  • Logging updates to internally owned APIs
  • etc...

The SDK offers two options to detect user consent:

  • Observing Broadcast Events
  • Querying for User Consent

The SDK also provides a way to listen for UI interaction events. More detail below: Listening for UI Interaction Events

Recommended Approach:

OneTrust recommends you set up observers and rely on the OT SDK broadcasts as the primary method to action on consent.

Observing Broadcast Events

Alternative Approach:

If for some reason you are unable to utilize broadcast events to action on consent, the SDK provides a way to rely on UI interaction events and querying for consent. In this case, OneTrust recommends you Query for Consent inside UI Interaction Events to action on consent.


Observing Broadcast Events

Every time the SDK is initialized or the user's consent changes, the OT SDK will broadcast an event for each Category ID and SDK ID and passes the latest consent value. You can use these events and consent values to trigger some action.

Your app can listen to either the categories itself or each individual SDK you want to manage. OneTrust recommends setting up observers on the category level to minimize the amount of observers you have to initialize.

The SDK will broadcast events for always active categories/SDKs as well.

Use Case: Applications needs observers for the SDKs or Categories that require some action to be taken when a user gives/withdraws their consent.

Example: When a user opts out of the "Sale of Personal Data" category, set a privacy or opt out flag in Targeting SDKs in scope so no personalized ads or ads of any kind are shown to the user.

Category IDs

When setting up your observers, you'll want to listen for changes based on the category's ID (OptanonGroupId).

Note: These OptanonGroupIds are friendly variables which can be updated in the OneTrust tenant under Cookie Consent > Categorization > Categories.

Here are the default values as set by OneTrust:

Category NameCategory ID
Strictly NecessaryC0001
PerformanceC0002
FunctionalC0003
TargetingC0004
Social MediaC0005

SDK IDs

When setting up your observers, you'll want to listen for changes based on each SDK's ID. SDK IDs can be found in your tenant under Cookie Categories > SDKs > Your App > Instructions

Notification Object

The notification object returns an integer value and indicates the consent of the user.

  • 1 = Consent is given
  • 0 = Consent is not given
  • -1 = Consent has not been collected (The SDK is not yet initialized OR there are no SDKs associated to this category)

Setting it up

  1. Create a function that will be called when the observer is triggered. If you are listening for categories, you will need to create a function for each category.
// Swift
@objc func actionConsent_Category_Name(_ notification:Notification){
  let consentValue = notification.object as? String
  NSLog("Category Consent Value = \(consentValue ?? "false")")
}

@objc func actionConsent_SDK_Name(_ notification:Notification){
  let consentValue = notification.object as? String
  NSLog("SDK Consent Value = \(consentValue ?? "false")")
}
  1. Register the observer. Your application will need to register an observer for each category you created an observer function for.
NotificationCenter.default.addObserver(
  self,
  selector: #selector(actionConsent_Category_Name(_:)),
  name: NSNotification.Name(rawValue: "C0003"),
  object: nil
)

NotificationCenter.default.addObserver(
  self,
  selector: #selector(actionConsent_SDK_Name(_:)),
  name: NSNotification.Name(rawValue: "SDK ID Value"),
  object: nil
)
  1. Unregister the observer when the view is destroyed.
NotificationCenter.default.removeObserver(NSNotification.Name(rawValue: "C0003"))

NotificationCenter.default.removeObserver(NSNotification.Name(rawValue: "SDK ID Value"))

OTConsentUpdated

The OT SDK will also broadcast a generic event every time a OneTrust UI (banner or preference center) is dismissed.

Use case: Applications need to know when they can query for latest consent for vendors, categories, SDKs, etc. This is useful in cases where you do not or cannot set up multiple observers for each category or SDK.

Event name: OTConsentUpdated

1. Observer Call Back

//observer callback 
 @objc func returnConsentOTConsentUpdated(_ notification:Notification){ 
        NSLog("OT Consent Updated Notification Fired") 
    } 

2.Registering the observer

//registering the observer
NotificationCenter.default.addObserver(self, selector:
                                       #selector(returnConsentOTConsentUpdated(_:)),
                                       name: Notification.Name("OTConsentUpdated"),
                                       object: nil) 

3.Destroying the observer

//destroying the observer 
NotificationCenter.default.removeObserver(NSNotification.Name(rawValue: "OTConsentUpdated"))

Querying for Consent

You can query for consent on a category or SDK level.

Querying Consent Status for a Category

Query the current consent status for any of the categories included in your application. This can be used to determine what privacy action is needed at app launch or anytime the consent status is needed without being notified by an event broadcast. Simply pass in the Category ID (eg. C0001) and the method will return the current consent status (integer value).

Value Returned

  • 1 = Consent is given
  • 0 = Consent is not given
  • -1 = Consent has not been collected (The SDK is not initialized or category does not exist OR there are no SDKs associated to this category)
// Swift
OTPublishersHeadlessSDK.shared.getConsentStatus(forCategory: "C0002")

// ObjC
[OTPublishersHeadlessSDK.shared getConsentStatusForCategory:@"C0002"];

Parameters

  • forCategory - This is the ID for the categories in scope. It can be found in the OneTrust tenant under Cookie Consent > Categorizations > Categories

Query Consent Status for a Specific SDK

Query the current consent status for any of the SDKs included in your application. This can be used to determine what privacy action is needed at application launch or anytime the consent status is needed without being notified by an event broadcast. Pass in the SDK ID and the method will return the current consent status (integer value).

Value Returned

  • 1 = Consent is given
  • 0 = Consent is not given
  • -1 = Consent has not been collected (The SDK is not initialized or OR there are no SDKs associated to this category)

Tip: SDK IDs can be found in your tenant under Cookie Consent > SDKs > Your App > Instructions

// Swift
OTPublishersHeadlessSDK.shared.getConsentStatus(forSDKId: "2368810c-94da-4f18-ab92-c55c5f74cca9")

// ObjC
[OTPublishersHeadlessSDK.shared getConsentStatusForSDKId:@"2368810c-94da-4f18-ab92-c55c5f74cca9"];

Parameters

  • forSDKId - This is the ID for the SDKs assigned to your app. It can be found in the OneTrust tenant under Cookie Categories > SDKs > Your App > Instructions

Query Consent for Vendors

If your app includes a list of vendors such as General Vendors, IAB Vendors or Google Vendors that you need to account for in terms of consent, you query for the status on a vendor level.

Value Returned

getVendorDetails() returns a JSON containing all information regarding a vendor list you specify. Because we're only concerned with the consent status, we'll want to target the consent key. Reference the example code below.

  • 2 = Vendor mapped to an always active category (e.g. Strictly Necessary)
  • 1 = Consent is given
  • 0 = Consent is not given

Parameters

The method takes in two parameters:

  • OTVendorListMode - Type of vendor list to retrieve
    • General: returns a list of general vendors
    • Google: returns a lsit of google vendors
    • IAB: returns a list of IAB vendors
  • Vendor ID

Tip: Vendor IDs can be found in your tenant under Cookie Consent > Vendors

General Vendor

 if let vendorConsent = OTPublishersHeadlessSDK.shared.getVendorDetails(vendorID: "vendorID", for: VendorListMode.general)?["consent"] {
      print("General Vendor Consent \(vendorConsent)")
 }

IAB Vendor

 if let vendorConsent = OTPublishersHeadlessSDK.shared.getVendorDetails(vendorID: "vendorID", for: VendorListMode.iab)?["consent"] {
      print("IAB Vendor Consent \(vendorConsent)")
 }

Google Vendor

if let vendorConsent = OTPublishersHeadlessSDK.shared.getVendorDetails(vendorID: "vendorID", for: VendorListMode.google)?["consent"] {
      print("Google ATP Vendor Consent \(vendorConsent)")
 }

Recommended Approaches

  • Set an observer to listen for the OTConsentUpdated broadcast. In the callback, query for general vendor consent
  • Use one of the UI Interaction Listener events (such as allSDKViewsDismissed) and query for general vendor consent when it is triggered

Query Consent Status for Universal Consent Purposes

If your app is utilizing Universal Consent, you can query the consent status for Universal Consent Purposes, Custom Preferences, and Topics.

Get Purpose Consent

OTPublishersHeadlessSDK.shared.getUCPurposeConsent(purposeID: "Purpose ID")

Get Topic Consent

OTPublishersHeadlessSDK.shared.getUCPurposeConsent(topicID: "Topic ID", purposeID: "Purpose ID")

Get Custom Preferences Consent

OTPublishersHeadlessSDK.shared.getUCPurposeConsent(customPreferenceOptionID: "custPrefOptionID", customPreferenceID: "custPrefID", purposeID: "purposeID")

Returns

  • 1 = Consent is given
  • 0 = Consent is not given
  • -1 = Consent has not been collected (The SDK is not initialized or purpose does not exist)

Listening for UI Interaction Events

Note: UI Interaction Events are only relevant if the app is using the out of the box OneTrust UI. If you have built your own UI, disregard this section.

When a User interacts with the OT SDK UI, the SDK sends an interaction event that the application can listen for and action on.

Use Case: The app needs to trigger certain actions based on interaction with the UI.

Use Case 2: In the event that broadcasts cannot be used to action on consent, the app can rely solely on interaction events and querying for consent to fire/suppress SDKs.

Example 1: User selects the "Confirm My Choices" button on the OT Preference Center UI, which saves their consent choices. An app might want to listen for the onPreferenceCenterConfirmChoices() to show a success toaster to the user and navigate them to the App's home page.

Example 2: In lieu of broadcast events, the app can listen for allSDKViewsDismissed to know when the OneTrust UI has been dismissed and query for user consent. It can then use this consent to fire/suppress SDKs.

Types of Events

Listed below are the supported OTEventListener events:

EventDescription
onShowBanner()Triggered when banner is shown
onHideBanner()Triggered when banner is closed
onBannerClickedAcceptAll()Triggered when user allows all consent from banner
onBannerClickedRejectAll()Triggered when user rejects all consent from banner
onShowPreferenceCenter()Triggered when Preference Center is displayed
onHidePreferenceCenter()Triggered when Preference Center is closed
onPreferenceCenterAcceptAll()Triggered when user allows all consent from Preference Center
onPreferenceCenterRejectAll()Triggered when user rejects all consent from Preference Center
onPreferenceCenterConfirmChoices()Triggered when user clicked on save choices after updating consent values from Preference Center
onShowVendorList()Triggered when vendor list UI is displayed from an IAB banner/ IAB Preference center
onHideVendorList()Triggered when vendor list UI is closed or when back button is clicked
onVendorConfirmChoices()Triggered when user updates vendor consent / legitimate interests purpose values and save the choices from vendor list
onVendorListVendorConsentChanged()Triggered when user updates consent values for a particular vendor id on vendor list UI
onVendorListVendorLegitimateInterestChanged()Triggered when user updates Legitimate interests values for a particular vendor id on vendor list UI
onPreferenceCenterPurposeConsentChanged()Triggered when user updates consent values for a particular category on Preference Center UI
onPreferenceCenterPurposeLegitimateInterestChanged()Triggered when user updates Legitimate interest values for a particular category on Preference Center UI
onShowSDKList()Triggered when the SDK List UI is displayed.
onHideSDKList()Triggered when the SDK List UI is closed or when back button is tapped.
onSDKListSDKConsentChanged(sdkId: string, consentStatus: Int8)Triggered when user opts in / out of an SDK on the SDK List view.
allSDKViewsDismissed(interactionType: ConsentInteractionType)Triggered when all the OT SDK Views are dismissed from the view hierarchy.

The allSDKViewsDismissed(interactionType: ConsentInteractionType) event is often used because:

  • It is the last event to fire
  • It only fires once all SDK UIs are dismissed from the view heirarchy
  • It passes a ConsentInteractionType to provide context to application on the user's action.

ConsentInteractionTypeDescription
bannerAllowAllThe user has consented by clicking accept all button in Banner view.
bannerRejectAllThe user has consented by clicking reject all button in Banner view.
bannerCloseThe user has clicked on close button in Banner view.
preferenceCenterAllowAllThe user has consented by clicking allow all button from Preference Center.
preferenceCenterRejectAllThe user has consented by clicking reject all button from Preference Center.
preferenceCenterConfirmThe user has consented by clicking confirm button from Preference Center.
preferenceCenterCloseThe user has clicked on cancel button in Preference Center.
vendorListConfirmThe user has consented by clicking confirm button from Vender List View.

Setting it up

First, register the class that will be extended to handle the OTEventListener events.

//Swift
OTPublishersHeadlessSDK.shared.addEventListener(self)

//Objective-C
[[OTPublishersHeadlessSDK shared] addEventListener:self];

Then, extend the class to include the protocol OTEventListener methods.

// Swift
class YourCustomClass: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    OTPublishersHeadlessSDK.shared.addEventListener(self)
  }
}

extension YourCustomClass: OTEventListener {
  func onHideBanner() {}
  func onShowBanner() {}
  func onBannerClickedRejectAll() {}
  func onBannerClickedAcceptAll() {}
  func onShowPreferenceCenter() {}
  func onHidePreferenceCenter() {}
  func onPreferenceCenterRejectAll() {}
  func onPreferenceCenterAcceptAll() {}
  func onPreferenceCenterConfirmChoices() {}
  func onPreferenceCenterPurposeLegitimateInterestChanged(purposeId: String, legitInterest: Int8) {}
  func onPreferenceCenterPurposeConsentChanged(purposeId: String, consentStatus: Int8) {}
  func onShowVendorList() {}
  func onHideVendorList() {}
  func onVendorListVendorConsentChanged(vendorId: String, consentStatus: Int8) {}
  func onVendorListVendorLegitimateInterestChanged(vendorId: String, legitInterest: Int8) {}
  func onVendorConfirmChoices() {}
  func allSDKViewsDismissed(interactionType: ConsentInteractionType) {}
}


// ObjC

@interface YourCustomClass : UIViewController <OTEventListener>
@end

@implementation YourCustomClass
- (void)viewDidLoad {
    [super viewDidLoad];
    [[OTPublishersHeadlessSDK shared] addEventListener:self];
}

@end

@interface SceneDelegate : UIResponder <UIWindowSceneDelegate, OTEventListener> {
  - (void)onHideBanner {}
  - (void)onShowBanner {}
  - (void)onBannerClickedAcceptAll {}
  - (void)onBannerClickedRejectAll {}
  - (void)onShowPreferenceCenter {}
  - (void)onHidePreferenceCenter{}
  - (void)onPreferenceCenterPurposeConsentChangedWithPurposeId:(NSString *)purposeId consentStatus:(int8_t)consentStatus {}
  - (void)onPreferenceCenterAcceptAll {}
  - (void)onPreferenceCenterRejectAll {}
  - (void)onPreferenceCenterConfirmChoices {}
  - (void)onPreferenceCenterPurposeLegitimateInterestChangedWithPurposeId:(NSString *)purposeId legitInterest:(int8_t)legitInterest {}
  - (void)onShowVendorList {}
  - (void)onHideVendorList {}
  - (void)onVendorConfirmChoices {}
  - (void)onVendorListVendorConsentChangedWithVendorId:(NSString *)vendorId consentStatus:(int8_t)consentStatus {}
  - (void)onVendorListVendorLegitimateInterestChangedWithVendorId:(NSString *)vendorId legitInterest:(int8_t)legitInterest {}
  - (void)allSDKViewsDismissed:(ConsentInteractionType)interactionType {}
}
// Swift
class YourCustomClass: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    OTPublishersHeadlessSDK.shared.addEventListener(self)
  }
}

extension YourCustomClass: OTEventListener {
  func onHideBanner() {}
  func onShowBanner() {}
  func onBannerClickedRejectAll() {}
  func onBannerClickedAcceptAll() {}
  func onShowPreferenceCenter() {}
  func onHidePreferenceCenter() {}
  func onPreferenceCenterRejectAll() {}
  func onPreferenceCenterAcceptAll() {}
  func onPreferenceCenterConfirmChoices() {}
  func onPreferenceCenterPurposeLegitimateInterestChanged(purposeId: String, legitInterest: Int8) {}
  func onPreferenceCenterPurposeConsentChanged(purposeId: String, consentStatus: Int8) {}
  func onShowVendorList() {}
  func onHideVendorList() {}
  func onVendorListVendorConsentChanged(vendorId: String, consentStatus: Int8) {}
  func onVendorListVendorLegitimateInterestChanged(vendorId: String, legitInterest: Int8) {}
  func onVendorConfirmChoices() {}
  func allSDKViewsDismissed(interactionType: ConsentInteractionType) {}
}


// ObjC

@interface YourCustomClass : UIViewController <OTEventListener>
@end

@implementation YourCustomClass
- (void)viewDidLoad {
    [super viewDidLoad];
    [[OTPublishersHeadlessSDK shared] addEventListener:self];
}

@end

@interface SceneDelegate : UIResponder <UIWindowSceneDelegate, OTEventListener> {
  - (void)onHideBanner {}
  - (void)onShowBanner {}
  - (void)onBannerClickedAcceptAll {}
  - (void)onBannerClickedRejectAll {}
  - (void)onShowPreferenceCenter {}
  - (void)onHidePreferenceCenter{}
  - (void)onPreferenceCenterPurposeConsentChangedWithPurposeId:(NSString *)purposeId consentStatus:(int8_t)consentStatus {}
  - (void)onPreferenceCenterAcceptAll {}
  - (void)onPreferenceCenterRejectAll {}
  - (void)onPreferenceCenterConfirmChoices {}
  - (void)onPreferenceCenterPurposeLegitimateInterestChangedWithPurposeId:(NSString *)purposeId legitInterest:(int8_t)legitInterest {}
  - (void)onShowVendorList {}
  - (void)onHideVendorList {}
  - (void)onVendorConfirmChoices {}
  - (void)onVendorListVendorConsentChangedWithVendorId:(NSString *)vendorId consentStatus:(int8_t)consentStatus {}
  - (void)onVendorListVendorLegitimateInterestChangedWithVendorId:(NSString *)vendorId legitInterest:(int8_t)legitInterest {}
  - (void)allSDKViewsDismissed:(ConsentInteractionType)interactionType {}
}