# Third-party SDKs

## IAB Vendor

#### Transparency and Consent Framework (TCF)

The Didomi SDK shares the user consent status with vendors through the [IAB GDPR Consent framework](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework).

For vendors that support the framework ([see the list here](https://iabeurope.eu/vendor-list-tcf/)), the only thing you have to do is declare them in the list of vendors that your app uses (see the [Getting Started](https://developers.didomi.io/cmp/mobile-sdk/consent-notice/getting-started) section for more information on how to do that) and they will adapt their data processing to respect the user consent.

#### Global Privacy Platform (GPP)

{% hint style="warning" %}
Please note: to use GPP on Android, the minimum required Android API version is 21. Make sure your app support version 21 or above.
{% endhint %}

The [Global Privacy Platform (GPP) ](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Core)string encapsulates user privacy preferences across multiple jurisdictions and frameworks. To learn more about Didomi's GPP integration read our [help center documentation](https://support.didomi.io/what-is-iab-gpp-framework).

The pre-parsed data as well as the full GPP string are generated and stored by Didomi Mobile SDK in your app storage in [NSUserDefaults](https://developer.apple.com/documentation/foundation/nsuserdefaults#1664798?language=objc) (iOS) or [SharedPreferences](https://developer.android.com/training/data-storage/shared-preferences) (Android).

| Key name                                           | Data type         | Description                                                                                                                                                                                                                                                         |
| -------------------------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `IABGPP_HDR_Version`                               | String            | GPP Version                                                                                                                                                                                                                                                         |
| `IABGPP_HDR_Sections`                              | String            | List of Section IDs                                                                                                                                                                                                                                                 |
| `IABGPP_HDR_GppString`                             | String            | Full consent string in its encoded form                                                                                                                                                                                                                             |
| `IABGPP_GppSID`                                    | String            | Section ID(s) considered to be in force. Multiple IDs are separated by underscore, e.g. “2\_3”                                                                                                                                                                      |
| `IABGPP_[SectionID]_String`                        | String            | String representation of each section. E.g. IAB TCF EU v2 String will be found at IABGPP\_2\_String                                                                                                                                                                 |
| pre-parsed data from the applicable string section | String or integer | The key names are a combination of the “IABGPP\_” prefix followed by the section prefix followed by an underline and then followed by the name of the value as specified [here](https://www.notion.so/GPP-privacy-signals-2df4951e1d29491ba4519709e3f7a02a?pvs=21). |

## Non-IAB Vendor

For other vendors, that do not implement the IAB specification, you will need to share the consent status with their SDK if they have an API to do so or prevent their SDK from loading until the user has given consent for the vendor and its purposes. This has to be done manually for every vendor.

### Vendor with custom API

Some vendors will offer a custom (non-IAB) API to tell their SDK what the user consent status is. In that case, check the user consent status for the vendor and pass it to the SDK:

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

```java
public void loadVendor() {
    boolean vendorHasConsent = Didomi.getInstance().getUserStatus()
        .getVendors().getGlobalConsent().getEnabled().contains("vendor-id");

    if (vendorHasConsent) {
        // We have consent for the vendor
        // Initialize the vendor SDK and pass the positive consent status
    } else {
        // We do not have consent information yet
        // Wait until we get the user information
        Didomi.getInstance().addEventListener(new EventListener() {
            @Override
            public void consentChanged(@NotNull ConsentChangedEvent event) {
                loadVendor();
                Didomi.getInstance().removeEventListener(this);
            }
        });
    }
}

Didomi.getInstance().onReady(() -> {
    loadVendor();
});
```

{% endtab %}

{% tab title="Kotlin" %}

<pre class="language-kotlin"><code class="lang-kotlin">fun loadVendor() {
<strong>    val didomi = Didomi.getInstance()
</strong>    val vendorHasConsent = didomi.userStatus
        .vendors.globalConsent.enabled.contains("vendor-id")

    if (vendorHasConsent) {
        // We have consent for the vendor
        // Initialize the vendor SDK and pass the positive consent status
    } else {
        // We do not have consent information yet
        // Wait until we get the user information
        didomi.addEventListener(object : EventListener() {
            override fun consentChanged(event: ConsentChangedEvent) {
                loadVendor()
                didomi.removeEventListener(this)
            }
        })
    }
}

Didomi.getInstance().onReady { loadVendor() }
</code></pre>

{% endtab %}

{% tab title="Swift" %}

```swift
func loadVendor() {
    let didomi: Didomi = Didomi.shared
    let vendorHasConsent = didomi.getUserStatus().vendors.globalConsent.enabled.contains("vendor-id")
    
    if vendorHasConsent {
        // We have consent for the vendor
        // Initialize the vendor SDK and pass the positive consent status
    } else {
        let didomiEventListener = EventListener()
        didomiEventListener.onConsentChanged = { [unowned self] event in
            self.loadVendor()
            didomi.removeEventListener(listener: didomiEventListener)
        }
        didomi.addEventListener(listener: didomiEventListener)
    }
}

Didomi.shared.onReady {
    self.loadVendor()
}
```

{% endtab %}

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

```objectivec
- (void)viewDidLoad {
    [super viewDidLoad];
    
    Didomi *didomi = [Didomi shared];
    [didomi onReadyWithCallback:^{
        [self loadVendor];
    }];
}

- (void)loadVendor {
    Didomi *didomi = [Didomi shared];
    NSSet<NSString *>* enabledVendorsConsent = [[[[didomi getUserStatus] vendors] globalConsent] enabled];
    
    if ([enabledVendorsConsent containsObject:@"vendor-id"]) {
        // We have consent for the vendor
        // Initialize the vendor SDK and pass the positive consent status
    } else {
        DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
        __weak DDMEventListener *wDidomiEventListener = didomiEventListener;
        [didomiEventListener setOnConsentChanged:^(enum DDMEventType event) {
            [self loadVendor];
            [didomi removeEventListenerWithListener: wDidomiEventListener];
        }];
        [didomi addEventListenerWithListener:didomiEventListener];
    }
}
```

{% endtab %}

{% tab title="C# (Unity)" %}

<pre class="language-csharp"><code class="lang-csharp">public void LoadVendor()
{
    ISet&#x3C;String> enabledVendors = Didomi.GetInstance().GetUserStatus().GetVendors().GetGlobalConsent().GetEnabled();
    bool vendorHasConsent = enabledVendors.Contains("vendor-id");

    if (vendorHasConsent)
    {
<strong>        // We have consent for the vendor
</strong><strong>        // Initialize the vendor SDK and pass the positive consent status
</strong>    }
    else
    {
        // We do not have consent information yet
        // Wait until we get the user information
        DidomiEventListener eventListener = new DidomiEventListener();
        eventListener.ConsentChanged += EventListener_ConsentChanged;

        Didomi.GetInstance().AddEventListener(eventListener);
    }
}

private void EventListener_ConsentChanged(object sender, ConsentChangedEvent e)
{
    LoadVendor();
}

Didomi.GetInstance().OnReady( () =>  LoadVendor() );
</code></pre>

{% endtab %}

{% tab title="React-native" %}

```typescript
async function loadVendor() {
  let vendorHasConsent = (await Didomi.getUserStatus()).vendors.global_consent.enabled.includes("vendor-id");
  if (vendorHasConsent) {
    // We have consent for the vendor
    // Initialize the vendor SDK and pass the positive consent status
  } else {
    let consentListener = (data: any) => {
      loadVendor();
      Didomi.removeEventListener(DidomiEventType.CONSENT_CHANGED, consentListener);
    };
    Didomi.addEventListener(DidomiEventType.CONSENT_CHANGED, consentListener);
  }
}

Didomi.onReady().then(() => {
  loadVendor();
});
```

{% endtab %}

{% tab title="Flutter" %}

```dart
void requestLoadVendor() {
  final consentListener = EventListener();
  consentListener.onConsentChanged = () {
    loadVendorIfConsent(consentListener);
    consentListener.onConsentChanged = () {};
  };
  DidomiSdk.addEventListener(consentListener);

  loadVendorIfConsent(consentListener);
}

void loadVendorIfConsent(EventListener consentListener) async {
  final hasVendorStatus = (await DidomiSdk.userStatus).vendors?.globalConsent?.enabled?.contains("vendor-id") == true;
  if (hasVendorStatus) {
    // We have consent for the vendor
    // Initialize the vendor SDK and pass the positive consent status
    consentListener.onConsentChanged = () {};
  }
}

DidomiSdk.onReady(() => { requestLoadVendor() });
```

{% endtab %}
{% endtabs %}

### Vendor without a custom API

For vendors that do not offer a custom API to share the user consent status, your only option is to not load their SDK until the user has given consent. Use the following snippet of code to get started:

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

```java
public void loadVendor() {
    boolean vendorHasConsent = Didomi.getInstance().getUserStatus()
        .getVendors().getGlobalConsent().getEnabled().contains("vendor-id");

    if (vendorHasConsent) {
        // We have consent for the vendor
        // Initialize the vendor SDK
    } else {
        // We do not have consent information yet
        // Wait until we get the user information
        Didomi.getInstance().addEventListener(new EventListener() {
            @Override
            public void consentChanged(@NotNull ConsentChangedEvent event) {
                loadVendor();
                Didomi.getInstance().removeEventListener(this);
            }
        });
    }
}

Didomi.getInstance().onReady(() -> {
    loadVendor();
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
fun loadVendor() {
    val didomi = Didomi.getInstance()
    val vendorHasConsent = didomi.userStatus
        .vendors.globalConsent.enabled.contains("vendor-id")

    if (vendorHasConsent) {
        // We have consent for the vendor
        // Initialize the vendor SDK
    } else {
        // We do not have consent information yet
        // Wait until we get the user information
        didomi.addEventListener(object : EventListener() {
            override fun consentChanged(event: ConsentChangedEvent) {
                loadVendor()
                didomi.removeEventListener(this)
            }
        })
    }
}

Didomi.getInstance().onReady { loadVendor() }
```

{% endtab %}

{% tab title="Swift" %}

```swift
func loadVendor() {
    let didomi: Didomi = Didomi.shared
    let vendorHasConsent = didomi.getUserStatus().vendors.globalConsent.enabled.contains("vendor-id")
    
    if vendorHasConsent {
        // We have consent for the vendor
        // Initialize the vendor SDK
    } else {
        let didomiEventListener = EventListener()
        didomiEventListener.onConsentChanged = { [unowned self] event in
            self.loadVendor()
            didomi.removeEventListener(listener: didomiEventListener)
        }
        didomi.addEventListener(listener: didomiEventListener)
    }
}

Didomi.shared.onReady {
    self.loadVendor()
}
```

{% endtab %}

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

```objectivec
- (void)viewDidLoad {
    [super viewDidLoad];
    
    Didomi *didomi = [Didomi shared];
    [didomi onReadyWithCallback:^{
        [self loadVendor];
    }];
}

- (void)loadVendor {
    Didomi *didomi = [Didomi shared];
    NSSet<NSString *>* enabledVendorsConsent = [[[[didomi getUserStatus] vendors] globalConsent] enabled];
    
    if ([enabledVendorsConsent containsObject:@"vendor-id"]) {
        // We have consent for the vendor
        // Initialize the vendor SDK
    } else {
        DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
        __weak DDMEventListener *wDidomiEventListener = didomiEventListener;
        [didomiEventListener setOnConsentChanged:^(enum DDMEventType event) {
            [self loadVendor];
            [didomi removeEventListenerWithListener: wDidomiEventListener];
        }];
        [didomi addEventListenerWithListener:didomiEventListener];
    }
}
```

{% endtab %}

{% tab title="C# (Unity)" %}

```csharp
public void LoadVendor()
{
    ISet<String> enabledVendors = Didomi.GetInstance().GetUserStatus().GetVendors().GetGlobalConsent().GetEnabled();
    bool vendorHasConsent = enabledVendors.Contains("vendor-id");

    if (vendorHasConsent)
    {
        // We have consent for the vendor
        // Initialize the vendor SDK and pass the positive consent status
    }
    else
    {
        // We do not have consent information yet
        // Wait until we get the user information
        DidomiEventListener eventListener = new DidomiEventListener();
        eventListener.ConsentChanged += EventListener_ConsentChanged;

        Didomi.GetInstance().AddEventListener(eventListener);
    }
}

private void EventListener_ConsentChanged(object sender, ConsentChangedEvent e)
{
    LoadVendor();
}

Didomi.GetInstance().OnReady( () =>  LoadVendor() );
```

{% endtab %}

{% tab title="React-native" %}

```typescript
async function loadVendor() {
  let vendorHasConsent = (await Didomi.getUserStatus()).vendors.global_consent.enabled.includes("vendor-id");
  if (vendorHasConsent) {
    // We have consent for the vendor
    // Initialize the vendor SDK
  } else {
    let consentListener = (data: any) => {
      loadVendor();
      Didomi.removeEventListener(DidomiEventType.CONSENT_CHANGED, consentListener);
    };
    Didomi.addEventListener(DidomiEventType.CONSENT_CHANGED, consentListener);
  }
}

Didomi.onReady().then(() => {
  loadVendor();
});
```

{% endtab %}

{% tab title="Flutter" %}

```dart
void requestLoadVendor() {
  final consentListener = EventListener();
  consentListener.onConsentChanged = () {
    loadVendorIfConsent(consentListener);
    consentListener.onConsentChanged = () {};
  };
  DidomiSdk.addEventListener(consentListener);

  loadVendorIfConsent(consentListener);
}

void loadVendorIfConsent(EventListener consentListener) async {
  final hasVendorStatus = (await DidomiSdk.userStatus).vendors?.globalConsent?.enabled?.contains("vendor-id") == true;
  if (hasVendorStatus) {
    // We have consent for the vendor
    // Initialize the vendor SDK
    consentListener.onConsentChanged = () {};
  }
}

DidomiSdk.onReady(() => { requestLoadVendor() });
```

{% endtab %}
{% endtabs %}

## Google Additional Consent Mode

The mobile SDK supports Google Additional Consent Mode, as described in [Google's additional consent mode](https://developers.didomi.io/web-sdk/third-parties/direct-integrations/google-ad-manager-adsense/google-dfp-adsense-adx/share-consent-and-refresh#googles-additional-consent-mode-iab-tcf).

To handle it, the values for positive and negative additional consent string have to be set in the custom JSON:

```json
{
  "app": {
    "vendors": {
      "google": {
        "additionalConsent": {
          "positive": "positive-additional-consent",
          "negative": ""
        }
      }
    }
  }
}
```
