Swift Module: Consent Manager

Swift Module: Consent Manager

by ‎07-18-2018 02:32 PM - edited ‎07-27-2018 09:25 AM (1,315 Views)

This module provides a convenient implementation of the Tealium Consent Manager, which can help your app to comply with legal obligations, such as GDPR. Once implemented, your user will be able to easily consent to or decline tracking, and the Tealium SDK will store and respect their choice from that point on.

In this article:

Overview

How It Works

The Consent Manager module is enabled by default. In its default state, before any consent preferences have been set, it will queue* all events received prior to the initial consent being granted by the user (the "unknown" state). It will continue doing this until such point as the user consents, or revokes their consent. At the point where the app user makes a selection, the following will happen:

(*To deactivate this functionality, so that tracking calls are not queued prior to consent being granted, use the "setInitialUserConsentStatus(.notConsented)" on the config object. If this is implemented, tracking calls sent prior to opt-in will be discarded, including Lifecycle hits).

If the user consents to tracking

  • All previously-queued tracking calls will be sent
  • The user's consent state will be stored permanently, and will be checked each time a new tracking call is made
  • If the user has set customized preferences, and consented only to specific categories, these categories will be respected when tags or connectors are fired in Tealium iQ and EventStream respectively
  • If Consent Logging is enabled, a single tracking call will be sent to UDH, to keep track of the user's consent preferences for auditing purposes only.

If the user grants partial consent (selected categories)

  • If Consent Logging is enabled, a single tracking call will be sent to UDH, to keep track of the user's consent preferences for auditing purposes only

If the user declines tracking

  • All previously-queued tracking calls will be purged from the queue
  • All future tracking calls will be canceled
  • No events will be sent to the UDH. Declined consent state cannot be tracked in the UDH.

Supported Platforms

iOS, tvOS, watchOS, macOS

External Dependencies

Foundation

Recommended Usage

Usage of this module is recommended.

It is automatically included and enabled in Carthage and CocoaPods framework builds.

Disabling Consent Manager

If you do not need to use Consent Manager, it can be disabled by including it in the list of disabled modules on the TealiumConfig object at initialization time.

Included Variables

The following variables will be transmitted with each tracking call while the module is enabled:

Variable Name Description Example Value
policy The policy under which consent was collected gdpr (default value)
consent_status The user's current consent status consented/notConsented
consent_categories An array of the user's selected consent categories ["analytics", "cdp"]

Public API

consentManager

class MyClass {
    var tealium: Tealium?
	
    public init () {
        let config = TealiumConfig(account: "<youraccount>",
                                   profile: "demo",
                                   environment: "dev",
                                   datasource: "abc123",
                                   optionalData: nil)
		
		self.tealium = Tealium(config) { 
			// Note: this is inside the completion block after initialization
		
			// self.tealium is guaranteed to be initialized inside the completion block
			self.tealium?.consentManager()?.#### // where #### is any public API method on the consentManager object	
		}
	}
}

This code shows how to access the consent manager.

addConsentDelegate

tealium?.consentManager()?.addConsentDelegate(self)

Registers a specific class conforming to the TealiumConsentDelegate protocol.

Parameters Description
delegate A class conforming to TealiumConsentDelegate

removeAllConsentDelegates

tealium?.consentManager()?.removeAllConsentDelegates()

Removes all consent delegates added by you. Retains the built-in delegate created by the TealiumConsentManagerModule class.

setUserConsentStatus

tealium?.consentManager()?.setUserConsentStatus(.consented)

Sets the user's consent status. Designed to be called from your consent management preferences screen in your app when the user enables or disables tracking.

Will always set the list of consented categories to include ALL available consent categories, if the status is .consented. Does not allow categories to be set selectively.

Parameters Description Example Value
status A value from TealiumConsentStatus enum .consented/.notConsented

setUserConsentCategories

tealium?.consentManager()?.setUserConsentCategories([.analytics,.bigData])

Sets the user's consent categories. Designed to be called from your consent management preferences screen in your app.

Will always set consent status to .consented.

Parameters Description Example Value
categories An array of values from the TealiumConsentCategories enum [.analytics,.bigData]

setUserConsentStatusWithCategories

tealium?.consentManager()?.setUserConsentStatusWithCategories(status: .consented, categories: [.analytics])

Sets consent status and categories in a single call.

Parameters Description Example Value
status A value from TealiumConsentStatus enum .consented/.notConsented
categories An array of values from the TealiumConsentCategories enum [.analytics]

getUserConsentStatus

let consentStatus: TealiumConsentStatus? = tealium?.consentManager()?.getUserConsentStatus()

Returns the current consent status.

getUserConsentCategories

let consentCategories: [TealiumConsentCategories]? = self.tealium?.consentManager()?.getUserConsentCategories()

Returns the current consent categories.

getUserConsentPreferences

let prefs: TealiumConsentUserPreferences? = tealium?.consentManager()?.getUserConsentPreferences()

Returns the TealiumConsentUserPreferences object (by value -> struct).

resetUserConsentPreferences

tealium?.consentManager()?.resetUserConsentPreferences()

Clears all currently stored consent preferences. Reverts to "unknown" consent state, with no categories.

TealiumConfig Methods

setConsentLoggingEnabled

let config = TealiumConfig(...)
config.setConsentLoggingEnabled(true)

Enables the Consent Logging feature, which sends all consent status changes to UDH for auditing purposes.

Parameters Description Example Value
enabled Bool true (default: false)

isConsentLoggingEnabled

let config = TealiumConfig(...)
let isEnabled = config.isConsentLoggingEnabled()

Returns the current state of the consent logging feature.

setInitialUserConsentStatus

let config = TealiumConfig(...)
config.setInitialUserConsentStatus(.notConsented)

Sets the initial consent status for the user when the library starts up for the first time. If there are saved preferences, these will override any preferences passed in the config object.

Will always set the list of consented categories to include ALL available consent categories, if the status is .consented. Does not allow categories to be set selectively.

Parameters Description Example Value
status A value from TealiumConsentStatus enum .consented/.notConsented

setInitialUserConsentCategories

let config = TealiumConfig(...)
config.setInitialUserConsentCategories([.analytics])

Sets the user's initial consent categories when the library starts up for the first time. If there are saved preferences, these will override any preferences passed in the config object.

Will always set consent status to .consented.

Parameters Description Example Value
categories An array of values from the TealiumConsentCategories enum [.analytics,.bigData]

getInitialUserConsentStatus

let config = TealiumConfig(...)
let status: TealiumConsentStatus? = config.getInitialConsentStatus()

Getter for the consent status currently set on the config object.

May not match the consent status set in the consentManager if the user has changed their preferences since the library launched.

getInitialUserConsentCategories

let config = TealiumConfig(...)
let categories: [TealiumConsentCategories]? = config.getInitialConsentCategories()

Getter for the consent categories currently set on the config object.

May not match the consent categories set in the consentManager if the user has changed their preferences since the library launched.

setOverrideConsentPolicy

let config = TealiumConfig(...)
config.setOverrideConsentPolicy("mycustompolicy")

Overrides the default policy parameter. Default is gdpr.

Parameters Description Example Value
policy A string value describing the policy to set for consent logging purposes "mycustompolicy"

getOverrideConsentPolicy

let config = TealiumConfig(...)
let currentPolicy = config.getOverrideConsentPolicy()

Returns the current consent policy override, if applicable. Optional.

Delegate Methods (TealiumConsentManagerDelegate)

willDropTrackingCall

func willDropTrackingCall(_ request: TealiumTrackRequest) {
        print("**** Tracking call DROPPED ******")
        print(request.data)
    }

This method is called whenever the consent manager is going to drop a tracking call (i.e. the user has declined tracking consent).

willQueueTrackingCall

func willQueueTrackingCall(_ request: TealiumTrackRequest) {
        print("**** Tracking call Queued ******")
        print(request.data)
    }

This method is called whenever the consent manager is in the "unknown" state, and tracking calls are being queued locally until the user grants or declines consent.

willSendTrackingCall

func willSendTrackingCall(_ request: TealiumTrackRequest) {
        print("**** Tracking call Sent")
        print(request.data)
    }

This method is called whenever the user has consented to tracking, and a tracking call is about to pass through the consent manager without being blocked.

consentStatusChanged

func consentStatusChanged(_ state: TealiumConsentStatus) {
    print(state)
}

This method is called whenver the consent state has been successfully updated.

userConsentedToTracking

func userConsentedToTracking() {
        print("User Consented")
    }

This method is called whenever the consent state is changed to .consented.

userOptedOutOfTracking

func userOptedOutOfTracking() {
        print("User Declined Tracking")
    }

This method is called whenever the user declines/revokes consent (consent status: .notConsented).

userChangedConsentCategories

func userChangedConsentCategories(categories: [TealiumConsentCategories]) {
        print("Categories Changed")
    }

This method is called whenever the user updates their consent categories preferences.

Enums and Constants

TealiumConsentCategories

Enum Values

.analytics
.affiliates
.displayAds
.email
.personalization
.search
.social
.bigData
.mobile
.engagement
.monitoring
.cdm
.cdp
.cookiematch
.misc

This enum contains the complete list of supported consent categories.

all

let allCategories: [TealiumConsentCategories] = TealiumConsentCategories.all()

Returns the complete list of supported consent categories.

consentCategoriesStringArrayToEnum

let selectCategories: [TealiumConsentCategories] = TealiumConsentCategories.consentCategoriesStringArrayToEnum(["analytics","bigData"])

Converts an array of strings containing valid consent categories to an array of enum values. Invalid string values will be omitted from the resulting array.

Parameters Description Example Value
[String] An array of strings to convert into an array of TealiumConsentCategories ["analytics", "bigData"]

TealiumConsentStatus

unknown

let status: TealiumConsentStatus = .unknown

The unknown status is the default setting for the consent manager. In this state, the consent manager will queue events locally until an affirmative consented/notConsented status is provided.

consented

let status: TealiumConsentStatus = .consented

The consented status is set when the user has consented to tracking. In this state, the consent manager allow all tracking calls to continue as normal.

notConsented

let status: TealiumConsentStatus = .notConsented

The notConsented status is set when the user has declined tracking. In this state, the consent manager will drop all tracking calls and halt further processing by the SDK.

TealiumConsentConstants (Internal)

public enum TealiumConsentConstants {
    static let consentCategoriesKey = "consent_categories"
    static let trackingConsentedKey = "tracking_consented"
    static let consentGrantedEventName = "grant_full_consent"
    static let consentDeclinedEventName = "decline_consent"
    static let consentPartialEventName = "grant_partial_consent"
    static let updateConsentCookieEventName = "update_consent_cookie"
    static let moduleName = "consentmanager"
    static let consentLoggingEnabled = "consent_manager_enabled"
    static let consentStatus = "consent_status"
    static let policyKey = "policy"
    static let defaultPolicy = "gdpr"
}

This enum is used internally by the SDK to provide a central place to configure static key names.

 

Implemented Code Examples

Please see GitHub for latest sample apps

Use Case 1: Simple Opt-in

    func setConsentStatusSimple(_ consented: Bool) {
        let status: TealiumConsentStatus = consented ? .consented: .notConsented 
        self.tealium?.consentManager()?.setUserConsentStatus(status)
    }

This example shows you how to give your users a simple "Opt-in/Opt-out" option. If the user consents, they will be automatically opted-in to all tracking categories. If they revoke their consent, no categories will be active, and no tracking calls will be sent.

Define and call the following method in your Tealium Helper class when your app user consents to or declines tracking. If the user consents to tracking, the Consent Manager will automatically opt them in to all tracking categories.

Simple Consent

Use Case 2: Grouped Opt-in

func updateConsentPreferences(_ dict: [String: Any]) {
    if let status = dict["consentStatus"] as? String {
        var tealiumConsentCategories = [TealiumConsentCategories]()
        let tealiumConsentStatus = (status == "consented") ? TealiumConsentStatus.consented : TealiumConsentStatus.notConsented
        if let categories = dict["consentCategories"] as? [String] {
            tealiumConsentCategories = TealiumConsentCategories.consentCategoriesStringArrayToEnum(categories)
        }
        self.tealium?.consentManager()?.setUserConsentStatusWithCategories(status: tealiumConsentStatus, categories: tealiumConsentCategories)
    }
}

// example function to define groups of categories, and set the consent preferences in the consentManager API. Should be called when the user saves their preferences

func setUserConsentPreferences(){
	// define a dictionary containing grouped categories
	let consentGroups = ["Off" : [],
	        "Performance": ["analytics", "monitoring", "big_data", "mobile", "crm"],
	        "Marketing": ["analytics", "monitoring", "big_data", "mobile", "crm", "affiliates", "email", "search", "engagement", "cdp"],
	        "Personalized Advertising": ["analytics", "monitoring", "big_data", "mobile", "crm", "affiliates", "email", "search", "engagement", "cdp", "display_ads", "personalization", "social", "cookiematch", "misc"]]
	        
	// this is the user's selected preferences level. Would usually be dynamic in a real app
	let userSelection = "Marketing"
	
	if let userList = consentGroups[userSelection] {
	  let settingsDict: [String: Any] = ["consentStatus": "consented", "consentCategories": userList]
	  
	  updateConsentPreferences(settingsDict)
	}
}

This example shows a category-based consent model, where tracking categories are grouped into a smaller number of higher-level categories, defined by you. For example, you may choose to group the Tealium consent categories "big_data", "analytics", and "monitoring" under a single category called "performance". This may be easier for the user than selecting from the full list of categories. You may choose to represent this in a slider interface, ranging from least-permissive to most-permissive (all categories).

grouped-gif.gif

Use Case 3: Category-based Opt-in

// helper method to call Tealium consentManager API
func updateConsentPreferences(_ dict: [String: Any]) {
    if let status = dict["consentStatus"] as? String {
        var tealiumConsentCategories = [TealiumConsentCategories]()
        let tealiumConsentStatus = (status == "consented") ? TealiumConsentStatus.consented : TealiumConsentStatus.notConsented
        if let categories = dict["consentCategories"] as? [String] {
            tealiumConsentCategories = TealiumConsentCategories.consentCategoriesStringArrayToEnum(categories)
        }
        self.tealium?.consentManager()?.setUserConsentStatusWithCategories(status: tealiumConsentStatus, categories: tealiumConsentCategories)
    }
}

// example function to take a list of categories and pass to the Tealium consentManager API

func setUserConsentPreferences(_ categories: [String]){

	let settingsDict: [String: Any] = ["consentStatus": "consented", "consentCategories": categories]  
	updateConsentPreferences(settingsDict)
}

This example shows a category-based consent model where the user must explicitly select each category from the full list of categories. The default state is "Unknown", which will queue hits until the user provides their consent. If the user consents to any category, events are de-queued, and the consented category data is appended to each tracking call.

Category-based

Video

Please see this video for an implemented example.

Future Improvements

  • Remote configuration options via Tealium iQ

Change Log

Build 1

  • Initial release