# Step 3: Advanced Integration

***

## How to use appConsent object ?

### **Specify a dedicated endpoint at init**

{% tabs %}
{% tab title="Swift" %}

```swift
let appConsent = ACNotice(withAppKey: "YOUR_APP_KEY", dedicatedEndpointURL: "YOUR_BACKEND_ENDPOINT")
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
 self.appConsent = [[ACNotice alloc] initWithAppKey:@"YOUR_APP_KEY" dedicatedEndpointURL:@"YOUR_BACKEND_ENDPOINT"];
```

{% endtab %}
{% endtabs %}

### **Redirecting user to their Privacy Settings**

This screen displays the user consent details and allows granular control, enabling users to provide consent for each individual item. User can also modify existing consent in that settings page.

{% tabs %}
{% tab title="Swift" %}

```swift
appConsent.presentSettings(viewController: self)
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
[self.appConsent presentSettingsWithViewController:self];
```

{% endtab %}
{% endtabs %}

### **Check if user gave consent**

{% tabs %}
{% tab title="Swift" %}

```swift
appConsent.consentGiven()
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
BOOL consentStatus = [appConsent consentGiven];
```

{% endtab %}
{% endtabs %}

Return `true` if consent is given, `false` otherwise.

{% hint style="danger" %}
**WARNING**

Please note that we are only talking about whether the user has confirmed a **choice** and not whether he has **accepted** or **refused** consent.
{% endhint %}

### **Implement delegates related to user consent**

When the user has completed the consent process and given their consent, this delegate informs you whether our CMP did finish successfully or did fail. Depending on these delegate you can trigger some action on your end depending on your business logic

{% tabs %}
{% tab title="UIKit (Swift)" %}
{% hint style="info" %}
**INFO**

In the example below, we start with the previous basic example found at [step-2-basic-integration](https://docs.sfbx.io/configuration/step-3-notice-implementation-web-app-tv/ios/appconsent-unified-sdk/step-2-basic-integration "mention")
{% endhint %}

Assign ACNotice delegate to self

```swift
  self.appConsent.delegate = self
```

Add an extension to your ViewController that conform to that Delegate&#x20;

```swift
extension ExampleViewController: AppConsentDelegate {
    
    func appConsentDidFinish() {
       // Below you can place your own business logic, for example grab the general consent status
        print("🔥 AppConsentUnified Delegate: did finish")
        
        let consentStatus = appConsent.consentStatus()
        print("🔥 AppConsentUnified Delegate: consent status => \(consentStatus.description)")
    }
    
    func appConsentDidFail(_ error: Error?) {
        print("🔥 AppConsentUnified Delegate: did fail, \(error?.localizedDescription ?? "No error details")")
    }
    
    func appConsentDidAppear() {
        print("🔥 AppConsentUnified Delegate: did appear")
    }
    
    func appConsentDidDisappear() {
        print("🔥 AppConsentUnified Delegate: did disappear")
    }
}
```

Full View Controller implementation:&#x20;

```swift
import AppConsentUnified

class ExampleViewController: UIViewController {

   // Notice Object
    private(set) var notice: ACNotice!
    
    override func viewDidLoad() {
        super.viewDidLoad()
       
        self.appConsent = ACNotice(withAppKey: "YOUR_APP_KEY")
        
        // Delegate is used to get some callbacks when CMP finishes its execution
        self.appConsent.delegate = self
        
        // Present CMP when you need it (it can after some internal logic on your end not necessarely here as the example shows)
        self.notice.presentNotice(viewController: self)
    }
}

fileprivate extension ExampleViewController: AppConsentDelegate {
    
    func appConsentDidFinish() {
       // Below you can place your own business logic, for example grab the general consent status
        print("🔥 AppConsentUnified Delegate: did finish")
        
        let consentStatus = notice.consentStatus()
        print("🔥 AppConsentUnified Delegate: consent status => \(consentStatus.description)")
    }
    
    func appConsentDidFail(_ error: Error?) {
        print("🔥 AppConsentUnified Delegate: did fail, \(error?.localizedDescription ?? "No error details")")
    }
    
    func appConsentDidAppear() {
        print("🔥 AppConsentUnified Delegate: did appear")
    }
    
    func appConsentDidDisappear() {
        print("🔥 AppConsentUnified Delegate: did disappear")
    }
}
   
```

{% endtab %}

{% tab title="UIKit (Objective-C)" %}
{% hint style="info" %}
**INFO**\
\
In the example below, we start with the previous basic example found at [step-2-basic-integration](https://docs.sfbx.io/configuration/step-3-notice-implementation-web-app-tv/ios/appconsent-unified-sdk/step-2-basic-integration "mention")
{% endhint %}

\
Implement AppConsentDelegate in your header ile (.h)

```objectivec
#import <UIKit/UIKit.h>
#import <AppConsentUnified/ACNotice.h>
#import <AppConsentUnified/AppConsentUnified-Swift.h>

NS_ASSUME_NONNULL_BEGIN
@interface ExampleObjcViewController : UIViewController <AppConsentDelegate>
@end
NS_ASSUME_NONNULL_END
```

Assign ACNotice delegate to self&#x20;

```objectivec
[self.appConsent setDelegate:self];
```

Then implement the delegate methods in your implementation file (.m) as per below

```objectivec
- (void)appConsentDidFail:(NSError * _Nullable)error {
   NSLog(@"🔥 AppConsentUnified Delegate: did fail %@", error.localizedDescription);
}

- (void)appConsentDidFinish {
    NSLog(@"🔥 AppConsentUnified Delegate: did finish");
    
    // Here you can place your own business logic, for example grab the general consent status
    ACConsentStatus consentStatus = [self.appConsent consentStatus];
    
    switch (consentStatus) {
        case ACConsentStatusAllowed:
            NSLog(@"🔥 AppConsentUnified Delegate: consent status Allowed");
            break;
        case ACConsentStatusDenied:
            NSLog(@"🔥 AppConsentUnified Delegate: consent status Denied");
        case ACConsentStatusMixed:
            NSLog(@"🔥 AppConsentUnified Delegate: consent status Mixed. Need to verify per purposes");
        default:
            break;
    }
}

-(void)appConsentDidAppear {
    NSLog(@"🔥 AppConsentUnified Delegate: did appear");
}

- (void)appConsentDidDisappear {
    NSLog(@"🔥 AppConsentUnified Delegate: did disappear");
}
```

**Full implementation ViewController implementation**

`ExampleObjcViewController.h`

```objectivec
#import <UIKit/UIKit.h>
#import <AppConsentUnified/ACNotice.h>
#import <AppConsentUnified/AppConsentUnified-Swift.h>

NS_ASSUME_NONNULL_BEGIN

@interface ExampleObjcViewController : UIViewController <AppConsentDelegate>
@end

NS_ASSUME_NONNULL_END

```

**ExampleObjcViewController.m**

```objectivec
#import "ExampleObjcViewController.h"

@interface ExampleObjcViewController ()
@property(nonatomic, strong) ACNotice *appConsent;
@end

@implementation ExampleObjcViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // initialise notice
    self.appConsent = [[ACNotice alloc] initWithAppKey:@"YOUR_APP_KEY"];
     // Set Delegate
     [self.appConsent setDelegate:self];
    // Present Notice
    [self.appConsent presentNoticeWithViewController:self];
}

- (void)appConsentDidFail:(NSError * _Nullable)error {
   NSLog(@"🔥 AppConsentUnified Delegate: did fail %@", error.localizedDescription);
}

- (void)appConsentDidFinish {
    NSLog(@"🔥 AppConsentUnified Delegate: did finish");
    
    // Here you can place your own business logic, 
    // An example here: get the general consent status
    ACConsentStatus consentStatus = [self.appConsent consentStatus];
    
    switch (consentStatus) {
        case ACConsentStatusAllowed:
            NSLog(@"🔥 AppConsentUnified Delegate: consent status Allowed");
            break;
        case ACConsentStatusDenied:
            NSLog(@"🔥 AppConsentUnified Delegate: consent status Denied");
        case ACConsentStatusMixed:
            NSLog(@"🔥 AppConsentUnified Delegate: consent status Mixed. Need to verify per purposes");
        default:
            break;
    }
}

-(void)appConsentDidAppear {
    NSLog(@"🔥 AppConsentUnified Delegate: did appear");
}

- (void)appConsentDidDisappear {
    NSLog(@"🔥 AppConsentUnified Delegate: did disappear");
}
@end

```

{% endtab %}

{% tab title="SwiftUI" %}
{% hint style="info" %}
**INFO**\
\
In the example below, we start with the previous basic example found at [step-2-basic-integration](https://docs.sfbx.io/configuration/step-3-notice-implementation-web-app-tv/ios/appconsent-unified-sdk/step-2-basic-integration "mention")
{% endhint %}

Conform your ViewModel to `AppConsentDelegate` as per below

```swift

// AppConsent Delegate
fileprivate extension AppConsentViewModel: AppConsentDelegate {    
    func appConsentDidFinish() {
        print("🔥 AppConsentUnified Delegate: did finish")
        noticeCompleted = true
    }
    func appConsentDidFail(_ error: Error?) {
        print("🔥 AppConsentUnified Delegate: did fail, \(error?.localizedDescription ?? "No error details")")
        noticeError = error
    }
    
    func appConsentDidAppear() {
        print("🔥 AppConsentUnified Delegate: did appear")
    }
    
    func appConsentDidDisappear() {
        print("🔥 AppConsentUnified Delegate: did disappear")
    }
}
```

Add 2 published properties on your ViewModel in order to react on delegates&#x20;

```swift
final class AppConsentViewModel: ObservableObject {
    
    private(set) var appConsent: ACNotice
    @Published var noticeCompleted = false
    @Published var noticeError: Error?
    
    init(ac: ACNotice) {
        self.appConsent = ac
    }
    
    func presentNotice() {
        if let rootVC = UIApplication.shared.keyWindow?.rootViewController {
            // Set delegate
            appConsent.delegate = self
            // Present Notice
            appConsent.presentNotice(viewController: rootVC)
        } else {
            noticeError = NSError(domain: "your_bundle_id", 
            code: 999, // Choose your internal code if needed
            userInfo: [
            NSLocalizedFailureReasonErrorKey: 
            "Unable to present notice, keyWindow is nil"
            ])
        }
    }
}
```

Full View Model implementation\ <br>

```swift
final class AppConsentViewModel: ObservableObject {
    private(set) var appConsent: ACNotice
    
    @Published var noticeCompleted = false
    @Published var noticeError: Error?
    
    init(notice: ACNotice) {
        self.appConsent = notice
    }
        
    func presentNotice() {
        if let rootVC = UIApplication.shared.keyWindow?.rootViewController {
            appConsent.delegate = self
            appConsent.presentNotice(viewController: rootVC)
        } else {
            noticeError = NSError(domain: "your_bundle_id", code: 999, userInfo: [NSLocalizedFailureReasonErrorKey: "Unable to present notice, keyWindow is nil"])
        }
    }
}

// AppConsent Delegate
extension AppConsentViewModel: AppConsentDelegate {
    
    func appConsentDidFinish() {
        print("🔥 AppConsentUnified Delegate: did finish")
        noticeCompleted = true
    }
    
    func appConsentDidFail(_ error: Error?) {
        print("🔥 AppConsentUnified Delegate: did fail, \(error?.localizedDescription ?? "No error details")")
        noticeError = error
    }
    
    func appConsentDidAppear() {
        print("🔥 AppConsentUnified Delegate: did appear")
    }
    
    func appConsentDidDisappear() {
        print("🔥 AppConsentUnified Delegate: did disappear")
    }
}
```

SwiftUI View implementation `AppConsentViewModel`  to receive delegates events

```swift
import SwiftUI
import AppConsentUnified

struct ContentView: View {
    @StateObject private var appConsentViewModel: AppConsentViewModel
    
    init(appConsentViewModel: AppConsentViewModel) {
        self._appConsentViewModel = StateObject(wrappedValue: appConsentViewModel)
    }
    var body: some View {
        VStack {
            // YOUR VIEW ELEMENTS
            Text("My View")
        }.onAppear {
            let appConsent = ACNotice(withAppKey: "YOUR_APP_KEY")
            // present notice
            appConsentViewModel.presentNotice()
        }.onReceive(appConsentViewModel.$noticeCompleted) { success in
            // Here you can place your own business logic, for example grab the general consent status
            let consentStatus = appConsentViewModel.appConsent.consentStatus()
            print("🔥 AppConsentUnified Delegate: did finish consent status => \(consentStatus.description)")
        }.onReceive(appConsentViewModel.$noticeError) { error in
            // Here you can place your own business logic for error handling
        }
    }
}
```

{% endtab %}
{% endtabs %}

### **Check for update**

This method allows you to check from our servers whether your Notice has been updated since it was last displayed on your user's device.

{% hint style="info" %}
**INFO**

The method will return true if you have modified the Source and/or Notice from your dashboard and, if and **only if**, you have configured your Notice to update for all your users.
{% endhint %}

<figure><img src="https://4229351976-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkyFlZKFaKP4MUM0zILOg%2Fuploads%2Fr0pByhnZyUtDmk5qVLRD%2Fcheck_for_update_notice.png?alt=media&#x26;token=37298ec4-ac21-4c66-8914-69911b1c43ae" alt=""><figcaption></figcaption></figure>

\
Our latest SDK supports both traditional callback-based APIs and the modern Swift concurrency approach using async/await for most methods. \
\
**Check for update - callback-based**

{% tabs %}
{% tab title="Swift" %}

```swift
  appConsent.checkForUpdate { [weak self] needUpdate in
             if needUpdate {
                // Your Notice has been updated, you must represent the CMP to your users
                // You can call presentNotice as per the below example
                 guard let self else { return }
                 appConsent.presentNotice(viewController: self)
            }
        }
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
    __weak typeof(self) weakSelf = self;
    
       [self.notice checkForUpdate:^(BOOL needUpdate) {
        if (needUpdate) {
            __strong typeof(self) strongSelf = weakSelf;
            if (!strongSelf) return;
            // Your Notice has been updated, you must represent the CMP to your users
           // You can call presentNotice as per the below example
            [self.notice presentNoticeWithViewController:strongSelf];
        }
    }];
```

{% endtab %}
{% endtabs %}

**Check for update - Modern concurrency**

{% tabs %}
{% tab title="Swift" %}

```swift
await appConsent.checkForUpdate()
```

{% endtab %}

{% tab title="Objective-C" %}
Not available
{% endtab %}
{% endtabs %}

### **GCM Status**

{% hint style="info" %}
**INFO**

This method shows the **current** status of GCMv2 (Google Consent Mode V2).

Before calling up this method, it's best to make sure that the user has **already given his consent** and that it's up to date, and that the CMP doesn't need to be redisplayed.

Otherwise :

* either the saved value of the **old consent** will be returned
* or the **default values** of your FirebaseAnalytics Info.plist configuration file will be returned

[Set the default consent state from google documentation](https://developers.google.com/tag-platform/security/guides/app-consent?consentmode=advanced\&platform=ios\&hl=fr#default-consent)
{% endhint %}

:information\_source: As some annotations are not compatible with Objective-C, we do have separate method for Objective-C and Swift.

{% tabs %}
{% tab title="Swift" %}

```swift
appConsent.gcmStatus()
```

Example:&#x20;

```swift
let gcmStatus: GCMStatus = appConsent.gcmStatus()
```

Return `GCMStatus`
{% endtab %}

{% tab title="Objective-C" %}

```objectivec
[self.appConsent objcGcmStatus];
```

Example:&#x20;

```objectivec
GCMObjCStatus* gcmStatus = [self.appConsent objcGcmStatus];
```

Return `GCMObjCStatus`
{% endtab %}
{% endtabs %}

<details>

<summary>Data model representing the state of GCMv2 (Google Consent Mode v2)</summary>

This will allow you to define consent from your Firebase Analytics &#x20;

1. Set the following key in your Info.plist file:
   * `GOOGLE_ANALYTICS_DEFAULT_ALLOW_ANALYTICS_STORAGE`
   * `GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_STORAGE`
   * `GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_USER_DATA`
   * `GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_PERSONALIZATION_SIGNALS`

For example, to set all grant consent for all parameters by default:

```
<key>GOOGLE_ANALYTICS_DEFAULT_ALLOW_ANALYTICS_STORAGE</key> <true/>
<key>GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_STORAGE</key> <true/>
<key>GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_USER_DATA</key> <true/>
<key>GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_PERSONALIZATION_SIGNALS</key> <true/>
```

</details>
