Info
Content

ConsentManager GDPR/CCPA SDK for iOS

The ConsentManager SDK for iOS apps implements and provides functionality to inform the user about data protection and ask and collect consent from the user. It enables app-developers to easily integrate the ConsentManager service into their app.

Supported Standards

The ConsentManager GDPR/CCPA SDK for Android supports the following industry standards:

  • IAB TCF v1
  • IAB TCF v2
  • IAB USPrivacy v1
  • ConsentManager custom vendors/purposes
  • Google Additional Consent Mode (Google AC String)

Cmp-Sdk-Screen-Shot---home.pngCmp-Sdk-Screen-Shot---settings.png

How it works

  1. Integrate the SDK into the app and configure the SDK settings
  2. Once the SDK is intergated into an app, the SDK will provide functions for the app developer in order to retrieve consent data
  3. As soon as the app starts, the SDK will automatically retrieve information from the ConsentManager servers in order to prepare the SDK for its usage.
  4. It is recommended, that on startup of the app, the app creates an instance of class CMPConsentTool. Once the this is created, the SDK will automatically show the consent screen if necessary.
  5. When the app wants to process personal data, it should "ask" the SDK if consent was given for the specific purpose and vendor.

Installation via Cocoapod

Add Library with Cocoapod

You can install the consentmanager SDK by adding consentmanager to your Podfile as explained in the example below:

target 'YourProject' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  pod 'consentmanager'

  target 'YourProjectTests' do
    inherit! :search_paths
     # Pods for testing
  end
  
...
      
end

Once this is done, you need to run pod install in your project directory to install the consentmanager SDK. After this, please open the *.xcworkspace and build. 

After you have followed all the steps, your dependency should be installed, and you can proceed and use it in your project.

Changelog

Changelog can be found here in our repository.

Manual Installation

We strongly recommend installing and using the library with Cocoapod. Without it, it will be harder to maintain for the user as well as for the developer. This way, updates need to be integrated manually, and there are some version control issues. Therefore, we are planning to stop the active service for this library. 

Download the SDK

Please download the latest version of the SDK here:

XCFramework: https://bitbucket.org/consentmanager/consentmanager-xcframework/src/master/

The SDK is configured for iOS Version 10 and higher.

Integration

In order to integrate the SDK into your existing project, please follow these steps:

  1. Pull the files from the folder ConsentManager.framework into the main folder of your app:



  2. Click on your project and go to tab General and expand the part under Frameworks, Libraries, and Embedded Content:

     

  3. If the module is not embedded yet, click on + (Plus) > Add Other > Add Files ...:

  4. Select the ConsentManager.framework folder from this project and click on Open:

  5. You should now see the Framework as "Embed & Sign" in the list:

  6. Navigate to your Main View Controller of your app and import the framework by using:
    #import <ConsentManager/CmpConsentTool.h>

Initiate the SDK

With the app-start (usually your viewDidAppear function) you must create an instance of class CMPConsentTool.  This will automatically fetch the necessary data from our server and determine if the consent screen needs to be shown or not. If so, the SDK will automatically show the consent screen at this point, collect the data and provide the data to the app. The instance can then be used in order to get consent details from the SDK in order to use it in the app.

#import "ViewController.h"
#import <ConsentManager/CMPConsentTool.h>

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *GDPRConsentStringLabel;
@end

@implementation ViewController
static CMPConsentTool *cmpConsentTool = nil;

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)viewDidAppear:(BOOL)animated {
    cmpConsentTool = [[CMPConsentTool alloc] init:@"consentmanager.mgr.consensu.org" addId:@"123456" addAppName:@"my%20Test%20App" addLanguage:@"DE" addViewController:self];
}

- (IBAction)showGDPRConsentTool:(id)sender {
    [cmpConsentTool openCmpConsentToolView];
}
@end

Example for Swift:

cmpConsentTool = CMPConsentTool.init("consentmanager.mgr.consensu.org", addId: "123456", addAppName: "my%20test%20app", addLanguage: "DE", add: self)

Please note that is is important to initialize the SDK in the didAppear Method. Otherwise the view may not be ready to use and the SDK may fail.

Please ensure to use the correct configuration data. The configuration data can be found in your ConsentManager account at Menu > Get Code.

Using the SDK

In order to check whether a vendor or purpose have consent, you can use the two methods:

if(consentTool!.hasPurposeConsent("52", purposeIsV1orV2: false))
{
    if(consentTool!.hasVendorConsent("s26", purposeIsV1orV2: false))
    {
        //do something with data
    }
}

Both methods hasPurposeConsent and hasVendorConsent require two parameter:

  • id - String of the vendor or purpose ID. Please note that vendor IDs can have different formats ("123", "s123" and "c123"), please double-check with Menu > Vendors and Menu > Purposes in your ConsentManager account.
  • isIABVendor / isIABPurpose - If the vendor or purpose is a vendor/purpose that follows the IAB TCF standard, you will need to set a true, otherwise a false.

Remember: All vendor that do not belong to the IAB have IDs starting with a "s" or "c" (e.g. "s123"); vendors that belong to the IAB have IDs not starting with a "s" or "c".

Re-Opening the Consent Screen

In order to allow the user to change the choices, you can simply call openCmpConsentToolView():

consentTool.openCmpConsentToolView();

Swift:

cmpConsentTool!.openView()

In some cases an native app might contain webviews in order to display certain things like advertising oder content. In order to transmit the consent information from the SDK to the webview, please use the function:

consentData = CMPStorageConsentManager.exportCMPData(this);

This will export the consent information and all further data that is needed by the CMP. You can then pass this information to the CMP that is in your webview by adding it to the URL that is called in the webview:

myWebView.loadURL("https://mywebsite.com/....#cmpimport=" + consentData);

Dynamic content blocking with placeholder UIView

The placeholder viewObject can be implemented to get the functionality of dynamic content blocking here.You can create the view with the following method: 

class ViewController: UIViewController, CmpPlaceholderAcceptedDelegate {
//...
  
@objc func createPlaceholderView{
	let params : CmpPlaceholderParams = CmpPlaceholderParams.init(vendorId: "123");
	let placeholder : CmpPlaceholderView = (cmpConsentTool?.createPlaceholder(CGRect.init(x: 0, y: 300, width: view.frame.size.width, height: 				view.frame.size.height), params))!;
	placeholder.vendorDelegate = self;
	view.addSubview(placeholder);	
}



func vendorAccepted(_ placeholderView: CmpPlaceholderView!) {
	//... actions to do when the consent is accepted
  	// Like showing youtube video view
}
// ...
}

With the Wrapper Object CMPPlaceholderParams you can also pass optional parameters like custom texts or an optional preview image. you can add custom Texts like shown below: 

params.buttonText = "Click me";

The required business Logic, when you want to show the view and when not need to be applied by the developer. To get information when the user is interacting with the placeholder, you can use the prepared delegate CmpPlaceholderAcceptedDelegate. With the delegate you will need to implement vendorAccepted function where you can control additional logic when the user accepted the consent. 

Integration with Apple Tracking Transparency (ATT)

Since iOS 14 Apple introduced the Apple Tracking Transparency framework, which requires that every app needs to expose which tracking data it uses. The ATT framework on its own is not compliant with the IAB TCF/GDPR, etc. and is only an apple specific version for asking user consent for tracking data. To enable the user a better experience we support a solution to synchronise the consents between the CMP SDK and the ATT interface . The SDK offers two different solutions for this. 

1. The developer integrates the ATT Framework on it's own and then pass the resulting information to the CMP SDK. Apples documentation can be found here

We're recommending this integration. You're still able to get full control of the ATT interface and implement your customised process depending of the user.  

The integration could look like this. 

       func requestPermission() {
           if #available(iOS 14, *) {
               ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
                   switch status {
                   case .authorized:
                       // Tracking authorization dialog was shown and accepted
                       // TODO custom code here:
                   case .denied:
                       // Tracking authorization dialog was shown and permission is denied
                       // TODO custom code here:
                   case .notDetermined:
                       // Tracking authorization dialog has not been shown
                       // TODO custom code here:
                   case .restricted:
                       // Tracking authorization dialog has not been shown app is restricted for tracking
                       // TODO custom code here:
                   }
                   // After determination of the att status, pass the information to the cmp sdk                                                           
                   CmpConfig.setAppleTrackingStatus(status.rawValue);
               })
           }
       }

The permission request could look like this. The important line of code is 19 where the information is passed to the CMP SDK. Depending on the ATT Status the CMP SDK sets predefined consent information. 

 

2. The developer activates the the automatic apple tracking. The CMP SDK handles the request with a default protocol. The status then will be handled by the CMP SDK. Afterwards it's possible to get the ATT status by the developer custom actions should be nevertheless handled on request like in option 1. You can activate the automatic ATT request with:

CmpConfig.setAutoAppleTracking(true);

Make sure to activate this function before instantiation of the CMP SDK. 

Custom Event Listeners

To add additional process logic you can make use of Event Listeners. Following Event Listeners are available:

Name

Occurrs

 

onCMPOpenedListener

Listener for Event when CMP opened

onCMPClosedListener

Listener for Event when CMP is closed

onCMPNotOpenedListener

Listener for Event when CMP doesn't need to be opened

networkErrorListener

Listener for Event when CMP has network problems

serverErrorListener

Listener for Event when CMP can not reach the Consentmanager server

customOpenListener

Listener for Event when CMP opens

Import/Export Consent

To import or export the consent you can use the function exportCMPData() and importCMPData(String cmpData). Check the example below: 

// Instanstiate CMPConsentTool()
cmpConsentTool = CMPConsentTool.init(...)

// Importing consent data if you like
cmpConsentTool.importCMPData("${your consentString}");

// ... Your code here ...


// Exporting Consent data 
let consentString : String = CMPConsentTool.exportCMPData()

The consentString you need to pass should be base64 encoded.

Compiling / Upload to AppStore

In order to compile the SDK for the AppStore you might want to use the following script in order to clean the working directory:

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
FRAMEWORK_NAME="ConsentManager.framework"
# Check if Framework is present.
FRAMEWORK_LOCATION=$(find "$APP_PATH" -name "$FRAMEWORK_NAME" -type d)
if [ -z $FRAMEWORK_LOCATION ]; then
echo "Couldn't find ConsentManager.framework in $APP_PATH. Make sure 'Embed Frameworks' build phase is listed before the 'Strip Unused Architectures' build phase."
exit 1
fi
# This script strips unused architectures
find "$APP_PATH" -name "$FRAMEWORK_NAME" -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done

NSUserDefaults preferences

The SDK will set NSUserDefaults values for IAB TCF v1, IAB TCF v2, IAB USPrivacy and Google AC String.

The following keys are defined:

IAB TCF v1  
IABConsent_CMPPresent Boolean: Set to true if a CMP implementing this specification is present in the application. Ideally set by the Publisher as soon as possible but can also be set by the CMP alternatively.
IABConsent_SubjectToGDPR String 1 - (subject to GDPR), 0 - (not subject to GDPR), Nil - undetermined (default before initialization). Aligns with IAB OpenRTB GDPR Advisory. Decided to be String, to have the uninitialized status.
IABConsent_ConsentString String: Consent string
IABConsent_ParsedPurposeConsents String (of "0" and "1") where the character in position N indicates the consent status to purpose ID N as defined in the Global Vendor List. String of consent given to enable simple checking. First character from the left being Purpose 1, ...
IABConsent_ParsedVendorConsents String (of "0" and "1") where the character in position N indicates the consent status to vendor ID N as defined in the Global Vendor List. String of consent given to enable simple checking. First character from the left being Vendor 1, ... 
IAB TCF v2  
IABTCF_CmpSdkID Number: The unsigned integer ID of CMP SDK
IABTCF_CmpSdkVersion Number: The unsigned integer version number of CMP SDK
IABTCF_PolicyVersion Number: The unsigned integer representing the version of the TCF that these consents adhere to.
IABTCF_gdprApplies Number:

1 GDPR applies in current context

0 - GDPR does not apply in current context

Unset - undetermined (default before initialization)

IABTCF_PublisherCC String: Two-letter ISO 3166-1 alpha-2 code – Default: AA (unknown)
IABTCF_PurposeOneTreatment Number:

0 - no special treatment of purpose one

1 - purpose one not disclosed

Unset default - 0

Vendors can use this value to determine whether consent for purpose one is required.

IABTCF_UseNonStandardStacks Number:

1 - CMP used a non-standard stack

0 - CMP did not use a non-standard stack

IABTCF_TCString String: Full encoded TC string
IABTCF_VendorConsents Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the consent status for Vendor ID n+1; false and true respectively. eg. '1' at index 0 is consent true for vendor ID 1
IABTCF_VendorLegitimateInterests Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the legitimate interest status for Vendor ID n+1; false and true respectively. eg. '1' at index 0 is legitimate interest established true for vendor ID 1
IABTCF_PurposeConsents Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the consent status for purpose ID n+1; false and true respectively. eg. '1' at index 0 is consent true for purpose ID 1
IABTCF_PurposeLegitimateInterests Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the legitimate interest status for purpose ID n+1; false and true respectively. eg. '1' at index 0 is legitimate interest established true for purpose ID 1
IABTCF_SpecialFeaturesOptIns Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the opt-in status for special feature ID n+1; false and true respectively. eg. '1' at index 0 is opt-in true for special feature ID 1
IABTCF_PublisherRestrictions{ID} String ['0','1', or '2']: The value at position n – where n's indexing begins at 0 – indicates the publisher restriction type (0-2) for vendor n+1; (see Publisher Restrictions Types). eg. '2' at index 0 is restrictionType 2 for vendor ID 1. {ID} refers to the purpose ID.
IABTCF_PublisherConsent Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the purpose consent status for purpose ID n+1 for the publisher as they correspond to the Global Vendor List Purposes; false and true respectively. eg. '1' at index 0 is consent true for purpose ID 1
IABTCF_PublisherLegitimateInterests Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the purpose legitimate interest status for purpose ID n+1 for the publisher as they correspond to the Global Vendor List Purposes; false and true respectively. eg. '1' at index 0 is legitimate interest established true for purpose ID 1
IABTCF_PublisherCustomPurposesConsents Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the purpose consent status for the publisher's custom purpose ID n+1 for the publisher; false and true respectively. eg. '1' at index 0 is consent true for custom purpose ID 1
IABTCF_PublisherCustomPurposesLegitimateInterests Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the purpose legitimate interest status for the publisher's custom purpose ID n+1 for the publisher; false and true respectively. eg. '1' at index 0 is legitimate interest established true for custom purpose ID 1
IAB USPrivacy  
IABUSPrivacy_String String: Aligns with IAB OpenRTB CCPA Advisory. The String encodes all choices and information.
Google AC String  
IABTCF_AddtlConsent

String: Aligns with Google’s Additional Consent Mode technical specification. 

API Overview

- (void)openCmpConsentToolView; Displays a modal view with the consent web view, without asking the server, if a new consent is needed. When the Webview is opened the openListener will be called. If the Compliance is accepted or rejected, a close function will be called. You can set these functions by your own and either pass them by or after the initalisation. If you want to add a closeListener just for this call of this method, you can overload this function with an additional closeListener function.
- (void)openCmpConsentToolView: (void(^)(void))closeListener; Displays a modal view with the consent web view, without asking the server, if a new consent is needed. When the Webview is opened the openListener will be called. If the Compliance is accepted or rejected, a close function will be called. You can set these functions by your own and either pass them by or after the initalisation. If you want to add a closeListener just for this call of this method, you can overload this function with an additional closeListener function. The closeListener is a function called with no parameter and returns no values. It will be called asynchronous.
- (NSString*)getVendorsString;  If the consentScreen is closed, an extended version of ConsentString is returned by the logic of consentmanager. The additional Vendor String contains all vendors which are not mentioned by the CMPString. This String will be returned. Each Vendor is separated by a “_” and will have a “_” before itself. “_c23_” would be a valid VendorsString generated by ConsentManager. An empty VendorsString will be either null, “” or “__”.
- (NSString*)getPurposesString; If the consentScreen is closed, an extended version of ConsentString is returned by the logic of consentmanager. The additional Purposes String contains all purposes which are not mentioned by the CMPString. This String will be returned. Each Purpose is separated by a “_” and will have a “_” before itself. “_p23_” would be a valid PurposeString generated by ConsentManager. An empty PurposeString will be either null, “” or “__”.
- (NSString*)getUSPrivacyString;  Returns the US Privacy String, that was returned by the users consent in the CMP ConsentScreen.
- (BOOL)hasVendorConsent:(NSString *)vendorId vendorIsV1orV2:(BOOL)isIABVendor; Returns if a given Vendor has the rights to set cookies. The parameter vendorIsV1orV2 claims, if the vendor is mentioned by the regular IABString, or if it Is contained in the vendorString generated by consentmanager.
- (BOOL)hasPurposeConsent:(NSString *)purposeId purposeIsV1orV2:(BOOL)isIABPurpose; Returns if a given Purposeis accepted. The parameter purposeIsV1orV2 claims, if the purpose is mentioned by the regular IABString, or if it Is contained in the purposeString generated by consentmanager.
- (BOOL)hasPurposeConsent:(int)purposeId forVendor:(int) vendorId;

Returns, if the Consent for a purpose for a specific vendor was given. This Method will only give a valid answer, if the Consent was given in the version V2.

- (id)init:(NSString *)domain addId:(NSString *)userId addAppName:(NSString *)appName addLanguage:(NSString *)language addViewController:(UIViewController *)viewController;

- (id)init:(NSString *)domain addId:(NSString *)userId addAppName:(NSString *)appName addLanguage:(NSString *)language addViewController:(UIViewController *)viewController addOpenListener:(void(^)(void))openListener;

- (id)init:(NSString *)domain addId:(NSString *)userId addAppName:(NSString *)appName addLanguage:(NSString *)language addViewController:(UIViewController *)viewController addCloseListener:(void(^)(void))closeListener;

- (id)init:(NSString *)domain addId:(NSString *)userId addAppName:(NSString *)appName addLanguage:(NSString *)language addViewController:(UIViewController *)viewController addOpenListener:(void(^)(void))openListener addCloseListener:(void(^)(void))closeListener;

- (id)init:(NSString *)domain addId:(NSString *)userId addAppName:(NSString *)appName addLanguage:(NSString *)language addViewController:(UIViewController *)viewController autoupdate:(BOOL)autoupdate;

- (id)init:(NSString *)domain addId:(NSString *)userId addAppName:(NSString *)appName addLanguage:(NSString *)language addViewController:(UIViewController *)viewController autoupdate:(BOOL)autoupdate addOpenListener:(void(^)(void))openListener;

- (id)init:(NSString *)domain addId:(NSString *)userId addAppName:(NSString *)appName addLanguage:(NSString *)language addViewController:(UIViewController *)viewController autoupdate:(BOOL)autoupdate addCloseListener:(void(^)(void))closeListener;

- (id)init:(NSString *)domain addId:(NSString *)userId addAppName:(NSString *)appName addLanguage:(NSString *)language addViewController:(UIViewController *)viewController autoupdate:(BOOL)autoupdate addOpenListener:(void(^)(void))openListener addCloseListener:(void(^)(void))closeListener;

- (id)init:(CMPConfig *)config withViewController:(UIViewController*)viewController;

- (id)init:(CMPConfig *)config withViewController:(UIViewController *)viewController addOpenListener:(void(^)(void))openListener;

- (id)init:(CMPConfig *)config withViewController:(UIViewController *)viewController addCloseListener:(void(^)(void))closeListener;

- (id)init:(CMPConfig *)config withViewController:(UIViewController *)viewController addOpenListener:(void(^)(void))openListener addCloseListener:(void(^)(void))closeListener;

- (id)init:(CMPConfig *)config withViewController:(UIViewController *)viewController autoupdate:(BOOL)autoupdate;

- (id)init:(CMPConfig *)config withViewController:(UIViewController *)viewController autoupdate:(BOOL)autoupdate addOpenListener:(void(^)(void))openListener;

- (id)init:(CMPConfig *)config withViewController:(UIViewController *)viewController autoupdate:(BOOL)autoupdate addCloseListener:(void(^)(void))closeListener;

- (id)init:(CMPConfig *)config withViewController:(UIViewController *)viewController autoupdate:(BOOL)autoupdate addOpenListener:(void(^)(void))openListener addCloseListener:(void(^)(void))closeListener;

Creates a new instance of this CMPConsentTool.

@ param domain = The domain URL of consentmanager eg.: “www.consentmanager.net

@ param userId =  The ID of your Account from consentmanagers webste eg,: 123

@ param appName = The Name of your App eg.: “My Test App”

@param language = The Language the consent should be shown in eg: “de”

@param viewController = The App Main ViewController instance

@param autoupdate = If set the App will check by itself, if a new consent is needed, if the app will be opened from the background.

@param openListener = This Listener given as a function will be called asynchronious shortly before the CMP Consent Screen will be opened.

@param closeListener = This Listener will be called asynchronious, if a consent was given by the user and the CMPConsentScreen was closed. This Listener is NOT called, if the User closes the app, without giving a consent.

@param config = The Parameters domain, userId, appName, language in an Object of Type CMPConfig.

You can overload the initialization function, as you can see in the following constructors:

+(NSString*)exportCMPData; Exports the current CMPData String. You can easily import this String at any other device with the function importCMPData.
+ (BOOL)importCMPData:(NSString *)cmpData; Imports the given CMPData String. You can easily export this String at any other device with the function exportCMPData.
-(BOOL)calledThisDay;  returns, whether the CMPConsent Manager Server was requested today, or the consentmanager server was already asked, if the CMP Consent Screen needs to be shown again.
-(BOOL)needsAcceptance;  returns, whether the user needs to give a consent, cause he didn't do so in the past, or because the consent Server returned, that a new consent is required.
+(void)reset; resets all data set by the consentCMPTool in the shared Preferences.

 

Back to top