Swiftpack.co - Package - SourcePointUSA/ios-cmp-app
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.

Swift

How to install

CocoaPods

In your Podfile add the following line to your app target:

pod 'ConsentViewController', '5.3.3'

Carthage

We also support Carthage. It requires a couple more steps to install so we dedicated a whole wiki page for it. Let us know if we missed any step.

Swift Package Manager

We also support Swift Package Manager. It is a tool for automating the distribution of Swift code and is integrated into the swift compiler. It is in early development, but SourcePoint does support its use on iOS platform.

To add our SDK package as dependency to your Xcode project, In Xcode select File > Swift Packages > Add Package Dependency and enter our SDK repository URL.

https://github.com/SourcePointUSA/ios-cmp-app.git

How to use it

It's pretty simple, here are 5 easy steps for you:

  1. implement the GDPRConsentDelegate protocol
  2. instantiate the GDPRConsentViewController with your Account ID, property id, property, privacy manager id, campaign environment, a flag to show the privacy manager directly or not and the consent delegate
  3. call .loadMessage()
  4. present the controller when the message is ready to be displayed
  5. profit!

Swift

import ConsentViewController

class ViewController: UIViewController {
    lazy var consentViewController: GDPRConsentViewController = { return GDPRConsentViewController(
        accountId: 22,
        propertyId: 7639,
        propertyName: try! GDPRPropertyName("tcfv2.mobile.webview"),
        PMId: "122058",
        campaignEnv: .Public,
        consentDelegate: self
    )}()

    @IBAction func onPrivacySettingsTap(_ sender: Any) {
        consentViewController.loadPrivacyManager()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        consentViewController.loadMessage()
    }
}

extension ViewController: GDPRConsentDelegate {
    func gdprConsentUIWillShow() {
        present(consentViewController, animated: true, completion: nil)
    }

    func consentUIDidDisappear() {
        dismiss(animated: true, completion: nil)
    }

    func onConsentReady(gdprUUID: GDPRUUID, userConsent: GDPRUserConsent) {
        print("ConsentUUID: \(gdprUUID)")
        userConsent.acceptedVendors.forEach { vendorId in print("Vendor: \(vendorId)") }
        userConsent.acceptedCategories.forEach { purposeId in print("Purpose: \(purposeId)") }

        // IAB Related Data
        print(UserDefaults.standard.dictionaryWithValues(forKeys: userConsent.tcfData.dictionaryValue?.keys.sorted() ?? []))
    }

    func onError(error: GDPRConsentViewControllerError?) {
        print("Error: \(error.debugDescription)")
    }
}

Objective-C


#import "ViewController.h"
@import ConsentViewController;

@interface ViewController ()<GDPRConsentDelegate> {
    GDPRConsentViewController *cvc;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    GDPRPropertyName *propertyName = [[GDPRPropertyName alloc] init:@"tcfv2.mobile.webview" error:NULL];

    cvc = [[GDPRConsentViewController alloc]
           initWithAccountId: 22
           propertyId: 7639
           propertyName: propertyName
           PMId: @"122058"
           campaignEnv: GDPRCampaignEnvPublic
           consentDelegate: self];

    [cvc loadMessage];
}

- (void)onConsentReadyWithGdprUUID:(NSString *)gdprUUID userConsent:(GDPRUserConsent *)userConsent {
    NSLog(@"ConsentUUID: %@", gdprUUID);
    NSLog(@"ConsentString: %@", userConsent.euconsent);
    for (id vendorId in userConsent.acceptedVendors) {
        NSLog(@"Consented to Vendor(id: %@)", vendorId);
    }
    for (id purposeId in userConsent.acceptedCategories) {
        NSLog(@"Consented to Purpose(id: %@)", purposeId);
    }
}

- (void)gdprConsentUIWillShow {
    [self presentViewController:cvc animated:true completion:NULL];
}

- (void)consentUIDidDisappear {
    [self dismissViewControllerAnimated:true completion:nil];
}
@end

Programatically consenting an user

It's possible to programatically consent the current user to a list of custom vendors, categories and legitimate interest caregories with the method:

func customConsentTo(
        vendors: [String],
        categories: [String],
        legIntCategories: [String],
        completionHandler: @escaping (GDPRUserConsent) -> Void)

The ids passed will be appended to the list of already accepted vendors, categories and leg. int. categories. The method is asynchronous so you must pass a completion handler that will receive back an instance of GDPRUserConsent in case of success or it'll call the delegate method onError in case of failure.

It's important to notice, this method is intended to be used for custom vendors and purposes only. For IAB vendors and purposes, it's still required to get consent via the consent message or privacy manager.

Authenticated Consent

In order to use the authenticated consent all you need to do is replace .loadMessage() with .loadMessage(forAuthId: String). Example:

  consentViewController.loadMessage(forAuthId: "JohnDoe")

In Obj-C that'd be:

  [consentViewController loadMessage forAuthId: @"JohnDoe"]

This way, if we already have consent for that token ("JohDoe") we'll bring the consent profile from the server, overwriting whatever was stored in the device. More about the authId below.

Sharing consent with a WKWebView

let webview = WKWebView()
webview.setConsentFor(authId: String)
webview.load(URLRequest)

The authId:

This feature makes use of what we call Authenticated Consent. In a nutshell, you provide an identifier for the current user (username, user id, uuid or any unique string) and we'll take care of associating the consent profile to that identifier. The authId will then assume 1 of the 3 values below:

  1. User is authenticated and have an id: In that case the authId is going to be that user id.
  2. User is not authenticated and I'm only interested in using consent in this app. We recommend using a randomly generated UUID as authId. Make sure to persist this authId and always call the .loadMessage(forAuthId: String)
  3. User is not authenticated and I want the consent to be shared across apps I controll. In this case, you'll need an identifier that is guaranteed to be the same across apps you control. That's exactly what the IDFV (Identifier for Vendor) is for. You don't need to store this id as it remains the same across app launches.

Example

// let authId = // my user id
// let authId = // stored uuid || UUID().uuidString
let authId = UIDevice().identifierForVendor
consentViewController.loadMessage(forAuthId: myAuthId)

// after the `onConsentReady` is called
myWebView.setConsentFor(authId: authid)
myWebView.load(urlRequest)

A few remarks:

  1. The web content being loaded (web property) needs to share the same vendor list as the app.
  2. The vendor list's consent scope needs to be set to Shared Site instead of Single Site

Overwriting default language

By default, the SDK will instruct the message to render itself using the locale defined by the WKWebView. If you wish to overwrite this behaviour and force a message to be displayed in a certain language, you need to set the .messageLanguage attribute of the GDPRConsentViewController before calling .loadMessage() / .loadPrivacyManager().

consentViewController.messageLanguage = .German
consentViewController.loadMessage()

It's important to notice that if any of the components of the message doesn't have a translation for that language, the component will be rendered in english as a fallback.

Setting Targeting Parameters

In order to set a targeting param all you need to do is passing targetingParams:[string:string] as a parametter in the ConsentViewController constructor. Example:

lazy var consentViewController: GDPRConsentViewController = { return GDPRConsentViewController(
       //other parametters here...
        targetingParams:["language":"fr"]
    )}()

In this example a key/value pair "language":"fr" is passed to the sp scenario and can be useded, wiht the proper scenario setup, to show a french message instead of a english one.

Configuring the Message/Consents timeout

Before calling .loadMessage or .loadPrivacyManager, set the .messageTimeoutInSeconds attribute to a time interval that makes most sense for your own application. By default, we set it to 30 seconds.

In case of a timeout error, the onError callback will be called and the consent flow will stop there.

pubData

When the user takes an action within the consent UI, it's possible to attach an arbitrary payload to the action data an have it sent to our endpoints. For more information on how to do that check our wiki: Sending arbitrary data when the user takes an action

Rendering the message natively

Have a look at this neat wiki we put together.

Frequently Asked Questions

1. How big is the SDK?

The SDK is pretty slim, there are no assets, no dependencies, just pure code. Since we use Swift, its size will vary depending on the configuration of your project but it should not exceed 2 MB.

2. What's the lowest iOS version supported?

Although our SDK can be technically added to projects targeting iOS 9, we support iOS >= 10 only.

We'll update this list over time, if you have any questions feel free to open an issue or concact your SourcePoint account manager.

Github

link
Stars: 6

Releases

5.3.3 - 2020-12-01T10:05:58

5.3.2 (Nov, 23, 2020)

  • Fixed a regression that'd prevent the SDK from running on projects using Swift Package Manager #266

5.3.2 - 2020-11-23T15:38:27

  • Fixed a regression with the sharing consent with the webview feature

5.3.1 - 2020-11-23T10:05:49

5.3.1 (Nov, 23, 2020)

  • Fixed an issue that would prevent the consentLanguage field from the consent string to always be set to EN. #260
  • Added a feature to ease sharing consent between native and webviews. Check how to use it in this section of the README. #263
  • Fixed an issue that prevented the property .userConsents from the GDPRConsentViewController to be outdated after calling the .customConsentTo method. #264
  • Updated the README and the AuthExample app.

5.3.0 - 2020-10-19T14:58:12

  • Added support to Swift Package Manager(SPM)

5.2.10 - 2020-10-15T13:14:36

  • improve error handling on MessageWebView #247

5.2.9 - 2020-10-13T16:04:26

  • Fixed compatibility with Xcode 12.x

5.2.8 - 2020-08-21T13:43:52

  • improved the error handling code of our WebMessageViewController. #229 (thank you @ivanlisovyi)

5.2.6 - 2020-08-11T12:00:53

  • fixed an issue that'd, in some cases, prevent authenticated consent from being stored #224
  • disabled "back and forward" gestures in the WebView, to prevent users from skipping the consent message when no dismiss button is present. #221
  • we are now getting the privacy manager id from the consent message when the user taps on Show PM instead of using the one provided to the SDK via constructor. #201
  • fixed an issue that'd prevent GDPRMessageJson from having all its fields encoded #218 (thank you @ivanlisovyi)
  • considerably increase UI test coverage for both Native and Web messages.

5.2.5 - 2020-07-03T09:04:25

  • fixed an issue that'd prevent the consent message from showing up on iOS 10

5.2.4 - 2020-06-25T14:56:32

  • fixed an issue preventing the vendorGrants from being filled in when calling customConsentTo.
  • cache the user's consent in the UserDefaults
  • we now make sure the onConsentReady is always called (except when returning from the PM to the consent message).
  • increase test and code coverage

5.2.3 - 2020-06-09T10:17:03

Fixed an issue that'd prevent the user from interacting with the app when the PMId passed to the SDK was wrong. We now encapsulate that in a WebViewError and call the onError callback on the ConsentDelegate.

5.2.2 - 2020-06-04T15:42:08

  • Add vendorGrants attribute to GDPRUserConsent class. The vendorGrants attribute, simply put, is an dictionary representing the consent state (on a legal basis) of all vendors and its purposes for the current user. For example:
[
  "vendorId1": VendorGrant(
    vendorGrant: Bool,
    purposeGrants: [
      "purposeId1": Bool,
      "purposeId2": Bool,
      // more purposes here
    ]
  )
  // more vendors here
]

The vendorGrant attribute is derived from purposeGrants and will be true if all purposes are also true.

  • Removed the bounce effect from the MessageWebView to improve on the UX while interacting with the consent message or the Privacy Manager.

5.2.1 - 2020-05-27T15:14:04

5.2.1 (May, 27, 2020)

  • Introduce the configurable timeout. You now can configure a timeout in which either the consent message must be shown or the consent data should be returned to the app (onConsentReady) by setting the attribute .messageTimeoutInSeconds: TimeInterval. Just make sure to set it before calling loadMessage or loadPrivacyManager. #145
  • Fixed an issue that would in some cases show the consent message for logged in users. #144

5.2.0 - 2020-05-15T08:58:47

5.2.0 (May, 15, 2020)

  • Added the method customConsentTo to GDPRConsentViewController. It's now possible to programatically consent the current user to a list of vendors, categories and legitimate interest caregories. The ids passed will be appended to the list of already accepted vendors, categories and leg. int. categories. The method is asynchronous so you must pass a completion handler that will receive back an instance of GDPRUserConsent in case of success or it'll call the delegate method onError in case of failure. It's important to notice, this method is intended to be used for custom vendors and purposes only. For IAB vendors and purposes it's still required to get consent via the consent message or privacy manager. #139
  • Fix an issue preventing consent data from being completely removed when calling clearAllData #141
  • Removed one (and hopfeully the last one) retaining cycle from our SDK #136

5.1.0 (April, 16, 2020) - 2020-04-16T17:14:16

5.1.0 (April, 16, 2020)

This is big one. We're moving more and more towards a stable API, so bare with us.

  • Fixed an issue that'd prevent the user to save consents from the privacy manager with the action Save & Exit #118
  • Added legitimateInterestCategories: [String] to GDPRUserConsent class #121
  • Added specialFeatures: [String] to GDPRUserConsent class #121
  • Updated the AuthExample app to use SDKv5 #116
  • Disabled zooming and pinch zooming actions on the message webview #114
  • Changed the delegate method from onAction(_ action: GDPRAction, consents: PMConsents?) to onAction(_ action: GDPRAction). The consents is now part of GDPRAction and it's encoded into Data. 462e9b6
  • GDPRUserConsent.tcfData has changed types from [String: StringOrInt] to SPGDPRArbitraryJson. It can be used as a dictionary by calling its .dictionaryValue -> [String: Any]? property.

5.0.3 - 2020-04-03T10:08:21

5.0.3 (April, 03, 2020)

  • Storing IAB consent data ealier by persisting it at the very first http call #109
  • Added Swiftlint pod and to GitHub workflow #107
  • Fixed a ton of lint issues including one forced unwrap #107
  • Fixed an issue that was causing the Example app to crash on iPad 75e5472

5.0.2 - 2020-03-26T16:07:30

4.1.4 - 2020-03-17T10:10:17

4.1.3 - 2020-03-16T18:10:28

4.1.2 - 2020-02-13T16:04:09

4.1.1 - 2020-02-11T14:58:11

Identity Feature - 2019-06-27T14:11:04

This release includes the very awaited Identity feature.

Just call ConsentViewController.loadMessage(forAuthId: String) passing a unique token belonging to your user and if we find privacy settings for him/her, we'll load those into the SDK.

Updated ReachabilitySwift version to '4.3.1' - 2019-05-06T12:51:59

Updated ReachabilitySwift version to '4.3.1'

Moved the API calls on secondary thread to keep main thread independent and free for UI operation. - 2019-04-20T16:00:36

2.2.4: Moved the below API calls on secondary thread to keep main thread independent and free for UI operation.

  1. getSiteId
  2. getGdprStatus
  3. getCustomConsents