# OneTrust Consent Management for iOS


The {{< legacy-tooltip "ios-objc" >}} lets you specify the user's consent during initialization.

This guide lists the steps to develop a consent interceptor for the [iOS (Obj-C) SDK]({{< ref "sources/event-streams/sdks/rudderstack-ios-sdk/" >}}) and use the interceptor to initialize the SDK **after** the user gives their consent.

{{< warning >}}
**The iOS (Swift) SDK does not have a dedicated OneTrust consent management integration**

The new [iOS (Swift) SDK]({{< ref "sources/event-streams/sdks/swift-sdk/" >}}) does not have a dedicated integration for OneTrust consent management. To implement OneTrust consent-based event filtering for cloud mode destinations, add the `consentManagement` object within the [context of your event payload]({{< ref "data-governance/consent-management/passing-consent.md" >}}).

See [Consent Management Support Matrix]({{< ref "data-governance/consent-management/support-matrix.md" >}}) for more information.
{{< /warning >}}

## Overview

The consent management is designed to be a filter for the event destinations and the natively added factories. Since the SDK initializes the native integration factories during the startup, **you must first capture** the user's consent to the cookie categories.

{{< info >}}
Note that:

- The iOS (Obj-C) SDK supports the OneTrust consent management feature only in v1.10.0 and above.
- You can add only one consent filter to the iOS (Obj-C) SDK.
{{< /info >}}

For filtering, RudderStack uses the `getConsentStatus(forCategory categoryId: String)` method of the OneTrust SDK.

## Install OneTrust consent

This setup assumes the [iOS (Obj-C) SDK]({{< ref "sources/event-streams/sdks/rudderstack-ios-sdk/#installing-the-rudderstack-ios-sdk" >}}) and the [OneTrust SDK](https://developer.onetrust.com/onetrust/docs/ios-tvos) are already added to your application.

1. Install `RudderOneTrustConsentFilter` by adding the following line to your `Podfile`:

```ruby
pod 'RudderOneTrustConsentFilter', '~> 1.0.0'
```

2. Import the iOS (Obj-C) SDK:

{{< tabs tabTotal="2">}}
{{% tab tabName="Objective-C" %}}

```objectivec
@import RudderOneTrustConsentFilter;
```

{{% /tab %}}
{{% tab tabName="Swift" %}}

```swift
import RudderOneTrustConsentFilter
```

{{% /tab %}}
{{< /tabs >}}

3. Add the imports to your `AppDelegate` file under the `didFinishLaunchingWithOptions` method, as shown:

{{< tabs tabTotal="2">}}
{{% tab tabName="Objective-C" %}}

```objectivec
@interface AppDelegate ()<OTEventListener>

@end

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[OTPublishersHeadlessSDK shared] startSDKWithStorageLocation:STORAGE_LOCATION domainIdentifier:DOMAIN_IDENTIFIER languageCode:@"en" params:nil loadOffline:NO completionHandler:^(OTResponse *response) {
        if (response.status) {
        
        }
    }];
    
    [[OTPublishersHeadlessSDK shared] addEventListener:self];
}

- (void)initializeRudderSDK {
    RSConfigBuilder *builder = [[RSConfigBuilder alloc] init];
    [builder withLoglevel:RSLogLevelDebug];
    [builder withDataPlaneUrl:DATA_PLANE_URL];
    [builder withConsentFilter:[[RudderOneTrustConsentFilter alloc] init]];

    [RSClient getInstance:rudderConfig.WRITE_KEY config:builder.build];
}

- (void)onPreferenceCenterConfirmChoices {
    [self initializeRudderSDK];
}
```

{{% /tab %}}
{{% tab tabName="Swift" %}}

```swift
class AppDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        OTPublishersHeadlessSDK.shared.startSDK(
            storageLocation: STORAGE_LOCATION,
            domainIdentifier: DOMAIN_IDENTIFIER,
            languageCode: "en"
        ) { response in
            if response.status {
        
            }
        }
        
        OTPublishersHeadlessSDK.shared.addEventListener(self)
    }
    
    func initializeRudderSDK() {
        let builder: RSConfigBuilder = RSConfigBuilder()
            .withLoglevel(RSLogLevelDebug)
            .withDataPlaneUrl(DATA_PLANE_URL)
            .withConsentFilter(RudderOneTrustConsentFilter())

        RSClient.getInstance(rudderConfig.WRITE_KEY, config: builder.build())
    }
}

extension AppDelegate: OTEventListener {
    func onPreferenceCenterConfirmChoices() {
        initializeRudderSDK()
    }
}
```

{{% /tab %}}
{{< /tabs >}}

{{< warning >}}
Make sure you load the SDK only if the user provides their consent.
{{< /warning >}}

## Create custom consent filter

{{< tabs tabTotal="2">}}
{{% tab tabName="Objective-C" %}}
1. Create a `CustomConsentIFilter.h` file by extending `RSConsentFilter`:

```objectivec
#import <Foundation/Foundation.h>
#import <Rudder/Rudder.h>
NS_ASSUME_NONNULL_BEGIN
@interface CustomConsentFilter : NSObject<RSConsentFilter>
@end
NS_ASSUME_NONNULL_END
```

2. Create a `CustomConsentFilter.m` file.

```objectivec
#import "CustomConsentFilter.h"

@implementation CustomConsentFilter

- (NSDictionary <NSString *, NSNumber *> * __nullable)filterConsentedDestinations:(NSArray <RSServerDestination *> *)destinations {
    NSDictionary <NSString *, NSNumber *> *filteredConsentedDestinations;
    // Do someting
    return filteredConsentedDestinations;
}

@end
```
{{% /tab %}}
{{% tab tabName="Swift" %}}

1. Create a `CustomConsentFilter` file by extending `RSConsentFilter`.

```swift
@objc
open class OneTrustInterceptor: NSObject, RSConsentFilter {
    @objc
    public override init() {
        super.init()
    }

    public func filterConsentedDestinations(_ destinations: [RSServerDestination]) -> [String: NSNumber]? {
        let filteredConsentedDestinations: [String: NSNumber]
        // Your code
        return filteredConsentedDestinations
    }
}
```

{{% /tab %}}
{{< /tabs >}}

### Register consent filter with iOS (Obj-C) SDK

You can register `CustomConsentFilter` with the iOS (Obj-C) SDK during its initialization, as shown:

{{< tabs tabTotal="2">}}
{{% tab tabName="Objective-C" %}}

```objectivec
RSConfigBuilder *builder = [[RSConfigBuilder alloc] init];
[builder withLoglevel:RSLogLevelDebug];
[builder withDataPlaneUrl:DATA_PLANE_URL];
[builder withConsentInterceptor:[[CustomConsentFilter alloc] init]];
[RSClient getInstance:WRITE_KEY config:builder.build];
```

{{% /tab %}}
{{% tab tabName="Swift" %}}

```swift
let builder: RSConfigBuilder = RSConfigBuilder()
    .withLoglevel(RSLogLevelDebug)
    .withDataPlaneUrl(DATA_PLANE_URL)
    .withConsentFilter(CustomConsentFilter())
RSClient.getInstance(rudderConfig.WRITE_KEY, config: builder.build())
```

{{% /tab %}}
{{< /tabs >}}

## Additional settings for cloud mode

{{< info >}}
RudderStack supports OneTrust integration in cloud mode from iOS (Obj-C) SDK v1.12.0 and above, and `RudderOneTrustConsentFilter` 1.1.0.
{{< /info >}}

You can specify your OneTrust cookie categories when sending events from your iOS (Obj-C) source in the [cloud mode]({{< ref "destinations/rudderstack-connection-modes.md#cloud-mode" >}}).

1. Set up your iOS (Obj-C) source in the RudderStack dashboard.
2. Connect it to a destination.
3. In the destination settings, enter the OneTrust category IDs in the **Enter consent category IDs** field. You can specify multiple consent category IDs by pressing the **Enter** key after each ID.

{{< info >}}
You can find the category IDs in your OneTrust dashboard under  **Preference & Consent Management** > **Cookie Compliance** > **Categorizations** > **Categories**.
{{< /info >}}

{{< image src="images/data-governance/consent-management/ios-onetrust.webp" alt="OneTrust category ID in consent settings" >}}

Note that the settings for specifying multiple consent IDs vary slightly for some destinations. Click **Add more** after specifying each consent category ID.

{{< image src="images/data-governance/consent-management/multiple-consent-ui.webp" >}}

<br />
