# Introduction

Didomi provides a Consent Management Platform (CMP) that you can integrate across various platforms such as websites, mobile applications, and internal apps. This platform facilitates user consent collection and preference settings before the use of personal data, empowering enforcement of user choices within all your tools like CRM, emailing, etc.

Ready-to-use UI elements such as banners and pop-ins allow you to collect consents on your existing websites and apps. Alternatively, you can leverage Didomi's API to create custom workflows based on consent. The platform ensures smooth integration with third-party services to synchronize consent precisely and facilitate enforcement of user choices, no matter which tools you use.

Besides CMP, Didomi also offers a Preference Management Platform (PMP). This platform allows you to target users' preferences in areas such as communication, marketing, advertising, or interests. It empowers users to share their preferences with you and maintain control over them.

Moreover, Didomi features an Automated Privacy Requests Management module. This module enables you to collect privacy requests from your end-users and manage them efficiently. By using this module, you can design forms for your customers to conveniently submit data subject access requests.

This guide takes you through the structure and API of the Didomi platform, including products like the SDKs.


# Introduction

SDKs provide customizable UI elements that can be used to collect user consent on your websites and apps. They allow you to easily deploy consent collection workflows without re-building every element of the user interface.

We offer SDKs for the following platforms:

* [Web (desktop and mobile)](/cmp/web-sdk/getting-started)
* [Mobile (Android and iOS) and TV (Android TV and tvOS)](/cmp/mobile-sdk)
* [AMP](/cmp/amp)


# Web SDK

This section will guide you through the required steps to setup the Didomi SDK for your websites.

We are assuming that you have a Didomi account and an API key. If not, please go to our [website](https://www.didomi.io) and sign up for an account.


# Getting started

## Load the SDK

### Script

We offer the Didomi SDK as a hosted JavaScript library that you can directly include on your website with a `<script>` tag.

Create a Consent Notice in the [Didomi Console](https://console.didomi.io/) and get the script tag from the "3. Publish" section. Paste the tag at the top of the `<head>` section of your HTML pages, before any other script tag.

**Important**: We recommend that you integrate the tags in the following order:

1. Conditioned vendors tags (header)
2. Didomi SDK (header)
3. Non conditioned vendors tags

Make sure to add the tag as close to the opening `<head>` tag on your page as possible, before any other tag gets embedded

Keep in mind that the role of our JavaScript SDK is to share consent information with all the other scripts on the page. In order to do so, it **MUST** be placed before any other tag or the tags from your vendors will not be able to collect consent information from us. Put it as close as possible to the opening `<head>` tag. If our SDK gets included after the other tags then the consent information will not be correctly shared and you will not be compliant with the GDPR requirements.

{% hint style="info" %}
If you are using [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) for whitelisting content source domains, you have to make sure that you whitelist <https://sdk.privacy-center.org/> and <https://api.privacy-center.org/> to allow the Didomi SDK to operate normally.
{% endhint %}

**Hybrid Apps:** If you are embedding our tag as part of your hybrid app (Electron, Cordova, etc), make sure to [set a custom domain](/cmp/web-sdk/consent-notice/custom-domains-for-events) as part of the configuration object.

#### Using a Custom Nonce (CSP)

If your website uses **Content Security Policy (CSP)** with nonces to authorize inline styles, the Didomi SDK can automatically apply your nonce to the styles it injects.

To enable this, define `window.didomiConfig` **before the SDK is loaded**, and provide your nonce value:

```javascript
<script>
  window.didomiConfig = {
    app: {
      nonce: 'YOUR_NONCE_VALUE',
    },
  };
</script>
```

Place this configuration snippet **above the Didomi SDK script tag** in the `<head>`.

When configured, the SDK will automatically add the corresponding `nonce` attribute to any styles it creates, ensuring compatibility with your CSP settings.

### React

{% hint style="info" %}
You can skip this section if you don't have a React application.
{% endhint %}

We also provide a React component to simplify the integration of our SDK with React applications. To use it, please follow the steps below or go directly to our React component documentation: <https://github.com/didomi/react>

1. Install the library using npm.

```bash
npm install --save @didomi/react
```

2\. Import the module into your app.

```javascript
import { DidomiSDK } from '@didomi/react';
```

We recommend instantiating the component as soon as possible: the sooner you instantiate the component, the faster the banner will be displayed or the faster consents will be shared with your partners and the ads displayed.

3\. Instantiate the component in your app

```javascript
<DidomiSDK
  iabVersion={2}
  gdprAppliesGlobally={true}
  onReady={didomi => console.log('Didomi SDK is loaded and ready', didomi)}
  onConsentChanged={cwtToken => console.log('A consent has been given/withdrawn', cwtToken)}
  onNoticeShown={() => console.log('Didomi Notice Shown')}
  onNoticeHidden={() => console.log('Didomi Notice Hidden')}
/>
```

The SDK will automatically pull the notice configuration from the Didomi Console.

For more information, please check our documentation: <https://github.com/didomi/react>

{% hint style="info" %}
**Testing from outside the EU**

If your banner is configured to not display to non EU visitors, it might be tricky to configure and test if you are not located in the EU. You can use the `notice.ignoreCountry: true` option if you are testing the banner from the US and force it to be shown to make sure it is working properly.

Another option is to add `#didomi:notice.ignoreCountry=true` to the URL in your address bar to force the SDK to ignore the country on the page. Example: if your website is `https://www.mywebsite.com`, go to `https://www.mywebsite.com/#didomi:notice.ignoreCountry=true` and the notice should be displayed even if you are not in the EU.
{% endhint %}

### Web based CTV application

{% hint style="info" %}
Make sure that the notice that you will set up has been marked as CTV type (rather than Web) on the Console. See [this article](https://docs.didomi.io/consent-management-platform-cmp/consent-notices/create-consent-notice-ctv) for more information.

<img src="/files/VhkrDwLnxxCU4W1HN4Hq" alt="" data-size="original">
{% endhint %}

Add the following code to your Web based CTV app. We recommend embedding it directly in the source of your HTML pages as adding it through a tag manager would slow down the loading of the notice.

```html
<script type="text/javascript">(function(){function r(e){if(!window.frames[e]){if(document.body&&document.body.firstChild){var t=document.body;var n=document.createElement("iframe");n.style.display="none";n.name=e;n.title=e;t.insertBefore(n,t.firstChild)}else{setTimeout(function(){r(e)},5)}}}function e(n,a,o,c,d){function e(e,t,n,r){if(typeof n!=="function"){return}if(!window[a]){window[a]=[]}var i=false;if(d){i=d(e,r,n)}if(!i){window[a].push({command:e,version:t,callback:n,parameter:r})}}e.stub=true;e.stubVersion=2;function t(r){if(!window[n]||window[n].stub!==true){return}if(!r.data){return}var i=typeof r.data==="string";var e;try{e=i?JSON.parse(r.data):r.data}catch(t){return}if(e[o]){var a=e[o];window[n](a.command,a.version,function(e,t){var n={};n[c]={returnValue:e,success:t,callId:a.callId};if(r.source){r.source.postMessage(i?JSON.stringify(n):n,"*")}},a.parameter)}}if(typeof window[n]!=="function"){window[n]=e;if(window.addEventListener){window.addEventListener("message",t,false)}else{window.attachEvent("onmessage",t)}}}e("__tcfapi","__tcfapiBuffer","__tcfapiCall","__tcfapiReturn");r("__tcfapiLocator");(function(e,t){var n=document.createElement("link");n.rel="preconnect";n.as="script";var r=document.createElement("link");r.rel="dns-prefetch";r.as="script";var i=document.createElement("script");i.id="spcloader";i.type="text/javascript";i["async"]=true;i.charset="utf-8";var a="{{SDK-URL}}"+e+"/loader.js?platform=ctv&target_type=notice&target="+t;if(window.didomiConfig&&window.didomiConfig.user){var o=window.didomiConfig.user;var c=o.country;var d=o.region;if(c){a=a+"&country="+c;if(d){a=a+"&region="+d}}}n.href="{{SDK-URL}}";r.href="{{SDK-URL}}";i.src=a;var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(n,s);s.parentNode.insertBefore(r,s);s.parentNode.insertBefore(i,s)})("{{Your-API-Key}}","{{Notice-ID}}")})();</script>
```

{% hint style="info" %}
You will need to replace `{{SDK-URL}}` with our default SDK URL: [`https://sdk.privacy-center.org/`](https://sdk.privacy-center.org/) or [use your own domain](https://developers.didomi.io/cmp/web-sdk/serve-didomi-assets-from-your-domain).\
\
You will also have to replace the `{{Your-API-Key}}` and `{{Notice-ID}}` parameters with your API key and your notice ID respectively.
{% endhint %}

Your website will automatically pull the latest configuration based on the notice ID provided.

**Supported Web based CTV devices**

{% hint style="info" %}
Devices not included in the supported list are likely compatible. If you encounter any issues with notice rendering on an unsupported device, please contact our support team for assistance.
{% endhint %}

Below is the list of supported devices:

* Tizen OS 3.0 and above
* HbbTV 1.5 and above
* webOS 4 and above

## Configure and interact with the SDK <a href="#configure-and-interact-with-the-sdk" id="configure-and-interact-with-the-sdk"></a>

Once the SDK has loaded, you can call other functions on it to do consent management, send analytics events, etc. To make sure that you use the SDK when it is ready, you can register a global *didomiOnReady* array of functions that will get called when the SDK is done loading:

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
<script type="text/javascript">
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) { 
    // Call other functions on the SDK
});
</script>
```

{% endtab %}

{% tab title="React" %}

```javascript
onDidomiReady(didomi) {
  console.log('Didomi Ready');
  // Call other functions on the SDK
}

...

<DidomiSDK
    ...
    onReady={this.onDidomiReady.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

The SDK exposes other events and functions to allow you to interact programmatically with the CMP. Read our [Reference](/cmp/web-sdk/reference) section for more information:

{% content-ref url="/pages/-LDh8hewhP9wNmXUW\_-D" %}
[Reference](/cmp/web-sdk/reference)
{% endcontent-ref %}

## Didomi Host Element <a href="#didomi-host-element" id="didomi-host-element"></a>

The Didomi SDK automatically creates a `<div>` element with the ID `didomi-host`, where the SDK will render its content. By default, this element is appended at the end of the `<body>` element of your webpage.

### **Customization Options**

Although we recommend using the default setup, you can optionally create and manage the `didomi-host` element yourself if your project requires additional control over its configuration. For instance, you may want to adjust the text direction, add custom CSS classes, or modify attributes for accessibility or SEO purposes.

Here is an example of how to manually define the host element:

```html
<body>
    <div id="didomi-host" class="custom-class"></div>
</body>
```

**Note:** Even if you manage the `didomi-host` element yourself, the SDK will control the following properties to ensure functionality and compliance:

* **`data-nosnippet`**: Prevents Google from using the CMP UI in search results.
* **`aria-hidden`**: Ensures the Didomi notice is correctly highlighted for screen readers, improving accessibility.

#### **Best Practices**

* If you customize the `didomi-host` element, ensure it is properly styled and positioned to avoid display issues.
* Avoid removing or overriding the SDK-managed attributes (`data-nosnippet` and `aria-hidden`) to maintain compliance with SEO and accessibility guidelines.

## Configure vendors and purposes

As per GDPR, the consent notice collects consents for a specific set of vendors and purposes. You must configure the notice to let it know what vendors are used on your website and it will automatically determine what purposes are required. This can be done from the [Didomi Console](https://console.didomi.io).

While we interoperate with a lot of vendors through the IAB framework or direct integrations, vendors that do not fall into either of these buckets must be configured through our tag manager or your existing tag manager. Failure to do so will result in vendors not being correctly blocked as needed and you will not be compliant with data privacy regulations.

Read our dedicated section to [learn how to configure your vendors](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/cmp/web-sdk/broken-reference/README.md).

## Add a link for the user to manage their preferences

After the user has given consent or closed the banner, you must give them an easy access to their choices so that they can update them.

You can use the function `Didomi.preferences.show()` to open the preferences manager and let the user update their choices. Example:

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
<a href="javascript:Didomi.preferences.show()">Consent preferences</a>
```

{% endtab %}

{% tab title="React" %}

```javascript
onDidomiReady(didomi) {
    this.didomiObject = didomi;
}

...

<DidomiSDK
    ...
    onReady={this.onDidomiReady.bind(this)}
/>
<button onClick={() => this.didomiObject.preferences.show()}>Consent preferences</button>
```

{% endtab %}
{% endtabs %}

We suggest adding this link to your privacy policy or in a header or footer menu on all of your pages.

## IAB frameworks <a href="#cmp-api-iab-gdpr-framework" id="cmp-api-iab-gdpr-framework"></a>

Didomi supports the IAB Transparency and Consent Framework as well as the IAB CCPA frameworks. Read more in our documentation:

{% content-ref url="/pages/-LyZ7klke2bEZ06CeXFx" %}
[IAB frameworks](/cmp/web-sdk/third-parties/iab-frameworks)
{% endcontent-ref %}


# Tags and vendors management

Managing tags and vendors on your website is a key aspect of integrating the Didomi CMP.\
You need to ensure that vendors that require consent are only loaded if consent is available so that they do not collect personal data or set cookies without the user consent.

## IAB vendors (TCF and CCPA)

The Didomi SDK automatically shares the user consent status with vendors through the [IAB GDPR Consent framework](https://iabeurope.eu/tcf-2-0/) and the [IAB CCPA Compliance framework](https://www.iab.com/guidelines/ccpa-framework/).

For vendors that support the framework, the only thing you have to do is declare them in the list of vendors that your website uses and they will adapt their data processing to respect the user consent.

## Non-IAB vendors with direct integrations

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

Didomi has built the following direct integrations:

* [Google Ad Manager / DFP](/cmp/web-sdk/third-parties/direct-integrations/google-ad-manager-adsense/google-dfp-adsense-adx)
* [Google Consent Mode](/cmp/web-sdk/third-parties/direct-integrations/google-consent-mode)
* [Kameleoon](/cmp/web-sdk/third-parties/direct-integrations/kameleoon)
* [Piano Analytics (AT Internet)](/cmp/web-sdk/third-parties/direct-integrations/at-internet)
* [Prebid](/cmp/web-sdk/third-parties/direct-integrations/prebid/prebid)
* [Salesforce DMP (Krux)](/cmp/web-sdk/third-parties/direct-integrations/salesforce-dmp-krux)

## Non-IAB vendors without a direct integration

For other non-IAB vendors that Didomi does not have a direct integration with, we support the following integration modes:

| **Mode**                                                                  | Use case                                                       |
| ------------------------------------------------------------------------- | -------------------------------------------------------------- |
| [Custom Didomi \<script> tags](/cmp/web-sdk/third-parties/no-tag-manager) | Hard-coded tags and vendors on your website as `<script>` tags |
| [Programmatic API](/cmp/web-sdk/third-parties/programmatic-api)           | Tags and vendors managed from your own JavaScript code         |
| [Tag managers](/cmp/web-sdk/third-parties/tags-management/tag-managers)   | Tags and vendors managed through your tag manager              |


# Tags management


# Events & Variables

Events are pushed by the Didomi Web SDK to your **tag management system**. Events provide variables that contain the user status on vendors and purposes.

You can then setup your rules based on events and variables to decide whether a tag can be loaded or not directly from your tag manager.

## Events

* `didomi-ready`: This event is pushed exactly once when the page is loaded and can be used for any tag that you want to fire exactly once on the page. The status of the user at the time of this event might be unknown.
* `didomi-consent-changed`: This event is pushed every time the user status changes as the result of a user interacting with the Didomi consent notices or preferences.
* `didomi-consent`: This event is pushed once when the page is loaded and then every time the user status changes as the result of a user interacting with the Didomi consent notices or preferences. Because this event does not distinguish between a page load and a subsequent status change, it can be fired multiple times on the page and is not suited for tags that must be fired at most once. You will usually want to use a combination of the `didomi-ready` and `didomi-consent-changed` events instead for these cases.

## Variables

### Vendors

These variables provide the user status for the vendors configured in your notice.

The user status reported for vendors automatically includes the status for their required purposes. You usually do not have to create a trigger that uses both vendors AND purposes variables: a trigger on vendors is enough.

Example: the vendor ID `google` is only included in the list of enabled vendors, if the user has enabled `google` and every purpose required by that vendor.

<table><thead><tr><th width="298">Variable</th><th>Description</th></tr></thead><tbody><tr><td><code>didomiVendorsEnabled</code></td><td><ul><li>Contains IDs of vendors that are 1) enabled for all their legal bases AND 2) all the defined purposes for the vendor are enabled for all their legal bases.</li><li><code>didomiVendorsEnabled</code> also contains any vendor defined with essential purposes only.</li><li>When no regulation applies to the user, <code>didomiVendorsEnabled</code> contains all vendors defined in your notice configuration.</li></ul></td></tr><tr><td><code>didomiVendorsDisabled</code></td><td><ul><li>Contains IDs of vendors that are either directly disabled by the user OR at least one of their defined purposes is disabled for any legal basis.</li><li>When no regulation applies to the user, <code>didomiVendorsDisabled</code> is empty.</li></ul></td></tr><tr><td><code>didomiVendorsUnknown</code></td><td><ul><li>Contains IDs of vendors that are neither enabled nor disabled (i.e: user has not made a choice and there is no default status for the legal basis).</li><li>When no regulation applies to the current user, <code>didomiVendorsUnknown</code> is empty.</li></ul></td></tr></tbody></table>

**Vendor IDs**

* All variables have the same format: a comma-separated list of vendor IDs terminated by a final comma.
* To find your vendor ID, navigate to the Didomi Console -> Consent notices -> Open your notice -> Regulation -> Edit vendors and Purposes: Use the API ID.
* Vendor IDs are unique and are the same across all regulations and notices.

<figure><img src="/files/rzArfbsk2g40tYqpnidh" alt=""><figcaption></figcaption></figure>

***

### Purposes

These variables contain the user status for the purposes configured in your notice.

You usually do not need to use these variables directly and want to use the vendors variables instead.

All variables have the same format: a comma-separated list of purpose IDs terminated by a final comma. Example: `cookies,analytics,`

<table data-header-hidden><thead><tr><th width="364">Variable</th><th>Description</th></tr></thead><tbody><tr><td>Variable</td><td>Description</td></tr><tr><td><code>didomiPurposesEnabled</code></td><td><ul><li>List of purposes that are enabled in all the legal bases for which they are defined.</li><li><code>didomiPurposesEnabled</code> also contains any purpose defined as essential on your consent notice.</li><li>When no regulation applies to the user, <code>didomiPurposesEnabled</code> contains all purposes defined in your notice configuration.</li></ul></td></tr><tr><td><code>didomiPurposesDisabled</code></td><td><ul><li>List of purposes that are disabled in any of the legal bases for which they were defined.</li><li>When no regulation applies to the current user, <code>didomiPurposesDisabled</code> is empty.</li></ul></td></tr></tbody></table>

***

### AB tests

We expose variables that contain the status of the AB test running (if any). That allows you to track your AB tests results through your own analytics solution.

| Variable                    | Description                           | Values / Example                                                                                                                                                                                                           |
| --------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `didomiExperimentId`        | ID of the AB test running.            | The value of the `experiment.id` property in your SDK configuration. An empty string is provided if there is no test configured.                                                                                           |
| `didomiExperimentUserGroup` | The group that the user is a part of. | <p><code>control</code> if the user is part of the control group</p><p><code>test</code> if the user is part of the user group</p><p>An empty string is provided if the user is not part of the control or test group.</p> |

***

### GDPR & IAB

| Variable            | Description                                                                                                                                                                                                                                                                                                                             | Values / Example                                    |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `didomiGDPRApplies` | Define whether the GDPR applies to the current user (ie the user is located in the EU or your website is configured to enforce GDPR for all users).                                                                                                                                                                                     | `0` (GDPR does not apply) and `1` (GDPR does apply) |
| `didomiIABConsent`  | The IAB consent string as defined in the [Consent String and Vendor List Format specification](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework). It encodes the consent information for every vendor and purpose as well as few other pieces of information on the CMP that created the string. | `BOMi0lyOMi0lyAHABBENAC-AAAAB4AQABaA`               |


# Deprecated

{% hint style="warning" %}
This page documents variables that were deprecated and that should not be used anymore.

If you are using Didomi variables for the first time, please directly refer to [this page](/cmp/web-sdk/third-parties/tags-management/events-and-variables).
{% endhint %}

## Deprecated vendor IDs

The Didomi Web SDK used to format vendor IDs with a prefix ( `prefix:ID,`).

The prefix that were supported:

* `iab:` for IAB vendors.
* `didomi:` for Didomi vendors.
* `c:` for custom vendors.

When non-GDPR regulations were introduced in the Didomi platform, a new and simpler vendor ID format was introduced and the prefix was removed.

To remain backward compatible, the variables listed on this page are still supported and continue to use the prefixed vendor IDs. **However, if your consent notices use multiple regulations, you must switch to the** [**new variables**](/cmp/web-sdk/third-parties/tags-management/events-and-variables#variables)**.**

* Example with prefix vendor IDs: `iab:628,didomi:google,c:custom,`
* Example with non-prefixed vendor IDs: `tappx-jjy49eFA,google,custom,`

## Deprecated events

<table><thead><tr><th width="211">Event</th><th>Description</th></tr></thead><tbody><tr><td><code>didomi-cookies-consent</code></td><td>An event sent to the dataLayer for Google Tag Manager</td></tr></tbody></table>

## Deprecated variables

### Vendors

<table><thead><tr><th width="335">Variable</th><th>Description</th></tr></thead><tbody><tr><td><code>didomiVendorsConsent</code></td><td>A comma-separated list of vendors that the user has given consent to. We use the list of purposes declared for the vendor to make sure that it has consent for all of them.</td></tr><tr><td><code>didomiVendorsConsentUnknown</code></td><td>A comma-separated list of vendors that the user has not yet given/denied consent to.</td></tr><tr><td><code>didomiVendorsConsentDenied</code></td><td>A comma-separated list of vendors that the user has denied consent to.</td></tr><tr><td><code>didomiVendorsRawConsent</code></td><td>A comma-separated list of vendors that the user has given consent to.<br>This list includes the raw consent status to vendors and does not take into account the required purposes per vendor. Only use this value if you are sure of what you are doing. Most likely, <code>didomiVendorsConsent</code> is the one you are looking for.</td></tr><tr><td><code>didomiVendorsRawConsentUnknown</code></td><td>A comma-separated list of vendors that the user has not yet given/denied consent to.<br>This list includes the raw consent status and does not take into account the required purposes per vendor. Only use this value if you are sure of what you are doing. Most likely, <code>didomiVendorsConsentUnknown</code> is the one you are looking for.</td></tr><tr><td><code>didomiVendorsRawConsentDenied</code></td><td>A comma-separated list of vendors that the user has denied consent to.<br>This list includes the raw consent status to vendors and does not take into account the required purposes per vendor. Only use this value if you are sure of what you are doing. Most likely, <code>didomiVendorsConsentDenied</code> is the one you are looking for.</td></tr></tbody></table>

### Purposes

<table data-header-hidden><thead><tr><th width="310">Variable</th><th>Description</th></tr></thead><tbody><tr><td><code>didomiPurposesConsent</code></td><td>List of purposes that are enabled based on consent only (legitimate interest is not considered).</td></tr><tr><td><code>didomiPurposesConsentDenied</code></td><td>List of purposes that are disabled based on consent only (legitimate interest is not considered).</td></tr><tr><td><code>didomiPurposesConsentUnknown</code></td><td>A comma-separated list of purposes that the user has not yet given/denied consent to.</td></tr><tr><td><code>didomiCookiesConsent</code></td><td>Contained end-user choices per cookie category (essential, analytics, marketing, social). Targeted at pre-GDPR concerns surrounding the ePrivacy directive.</td></tr></tbody></table>


# Custom events

If you have your own custom events that you use as triggers for tags and also want to add an additional condition on the consent status of the user, you need to make sure that your custom events only fire after the Didomi event that you are using (so that the Didomi variables have already been populated). You have two options to do so.

### Option 1: Wrap your custom events

In your JavaScript code that is pushing your custom events onto the data layer, wrap all your custom events to only fire them after the Didomi SDK has initialized and the `didomi-ready` event has been sent:

```javascript
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) {
  // Fire your custom event(s)
  dataLayer.push({'event': 'custom_event'});
});
```

You can use as many `didomiOnReady` functions and put them anywhere in your code. Custom events that are not used as triggers for a tag that you want to condition on consent do not need to be wrapped.

{% hint style="danger" %}
If you do not wait until the Didomi SDK is ready before firing your custom events, the order of the events will end up being random and you have no guarantee that the consent is correctly enforced for the tags using custom events triggers.
{% endhint %}

### Option 2: Condition your custom events

The second option is to only fire your custom events when you have consent. In that case, you do not need to add a consent condition in GTM and the mere fact that the event gets fired implies that consent was given

It is not ideal because is pushes the consent condition into your JavaScript code but can be useful sometimes.

```javascript
function fireCustomEvents(consentGiven) {
    if (consentGiven === true) {
      // Fire your custom event(s) because the user has given consent
      dataLayer.push({'event': 'custom_event'});
    }
  }
  
  window.didomiOnReady = window.didomiOnReady || [];
  window.didomiOnReady.push(function (Didomi) {
    // The SDK is done loading, check the user status for a given vendor
    const consentGiven = Didomi.getCurrentUserStatus().vendors['vendor-id']?.enabled;
  
    if (consentGiven === true) {
      // The user has enabled that vendor, fire the custom events
      fireCustomEvents(consentGiven);
    } else {
      // Subscribe to the consent.changed event to get notified when the consent status changes
      Didomi.on('consent.changed', function () {
        // The consent status of the user has changed, check again
        fireCustomEvents(Didomi.getCurrentUserStatus().vendors['vendor-id']?.enabled);
      });
    }
  });
```


# Tag managers

Didomi has direct integrations with key tag managers, and documentation for integrating with other tag managers that we do not have a direct integration with yet:

* [Adobe Launch/DTM](/cmp/web-sdk/third-parties/tags-management/tag-managers/adobe-launch-dtm)
* CommandersAct: Reach out to <support@didomi.io> for documentation.
* [Eulerian](/cmp/web-sdk/third-parties/tags-management/tag-managers/eulerian)
* [Google Tag Manager](/cmp/web-sdk/third-parties/tags-management/tag-managers/google-tag-manager)
* [Other tag managers](/cmp/web-sdk/third-parties/tags-management/tag-managers/other-tag-managers)
* [Tealium](/cmp/web-sdk/third-parties/tags-management/tag-managers/tealium)


# Adobe Launch/DTM

{% hint style="info" %}
Events and variables used by Adobe Launch/DTM integration are detailed in [this documentation.](/cmp/web-sdk/third-parties/tags-management/events-and-variables)
{% endhint %}

This section describe how to control what tags are embedded on your website when using Adobe Launch or DTM for managing tags.

The key idea of the integration is that Didomi pushes GDPR consent information into Adobe as variables of the data layer ([`_satellite.setVar`](https://experienceleague.adobe.com/en/docs/experience-platform/collection/tags/setvar)) and fires events/direct calls ([`_satellite.track`](https://experienceleague.adobe.com/en/docs/experience-platform/collection/tags/track)) to indicate when tags that require consent can be loaded. You should then configure Adobe to only fire tags after consent has been collected for each vendor.

On your side, the integration relies on adding rules, events and conditions to all the tags from vendors that do not support the IAB framework to make them fire on a custom event from the data layer. The Didomi SDK will then fire an event with the list of vendors that the user has given consent to, which will ensure that Adobe only loads the tags matching the user consent.

For instance, after a user gives consent to the vendor `google`, the SDK will push the direct call `didomi-consent-changed` and the variable `didomiVendorsEnabled` with the value `google,`. The tags setup in Adobe can then be fired through a rule on the event `didomi-consent-changed`.

{% hint style="warning" %}
**Make sure that our SDK is setup**

Before continuing, please read our section on [setting up our SDK](/cmp/web-sdk/getting-started) to learn how to do the initial setup of your tag. It is particularly important that our tag gets embedded before all the other tags on your page.
{% endhint %}

## Configure the Didomi / Adobe integration

### Step 1 - Enable the Adobe integration

Enable the `Adobe DTM and Launch` integration in the Integrations tab of your consent notice:

<figure><img src="/files/Ija1TZ3XgONrp7lW0YOT" alt=""><figcaption><p>Adobe DTM and Launch integration in the Didomi Console</p></figcaption></figure>

Make sure to publish your notice after enabling the integration.

{% hint style="danger" %}
**Embedding the Didomi SDK through Adobe**

We recommend not embedding the Didomi SDK through Adobe. By being directly on your pages, the Didomi SDK can load faster and also ensures that IAB vendors can detect a CMP on the page as soon as possible.

Embedding the Didomi SDK through Adobe will result in less consents being passed to vendors and a lower consent rate from their perspective.
{% endhint %}

### Step 2 - Create rules

You need to create rules that will be used to decide when to load each tag in Adobe DTM or Launch. Vendors that do not require consent need not be updated. [IAB vendors](https://vendor-list.consensu.org/v3/vendor-list.json) do not need to be conditioned either as they will automatically collect the consent status from Didomi through the IAB TCF API.

For every vendor tag that you need to condition on the user consent status, create or update a rule with the following configuration:

#### **Events**

Configure an event of type `Direct Call` with identifier `didomi-ready`:

![Didomi ready event configuration](/files/-LqDTbj8PMCYQRamQAT0)

With this event configured, your tag will be fired when the page loads AND consent has been given on a previous page. If you also want the tag to fire when consent is given on the current page, also add an event with identifier `didomi-consent-changed`:

![Didomi consent changed event](/files/-LqDU-NbozbSjcz8vpk8)

You should end up with one or two events configured:

![](/files/-LqDUKrmpxhfsWM91di6)

#### Conditions

Add a condition to your rule so that it only triggers if consent has been given to the vendor.\
The condition should be created on the `didomiVendorsEnabled` data element (noted as `%didomiVendorsEnabled%`) to validate that it contains the ID of the vendor that the tags belongs to.

<figure><img src="/files/cwk1CTu2xHGyM04ODmda" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
When matching vendors by IDs in variables, use the full ID of the vendor with an additional comma (`,`) at the end to ensure IDs do not get mixed and matched.\
Example: Use `google,` to match the vendor with ID `google` and not the vendor with ID `googleana-4TXnJigR`.
{% endhint %}

See [Variables / Vendors](/cmp/web-sdk/third-parties/tags-management/events-and-variables#vendors) for more information on `didomiVendorsEnabled` and other variables available to condition your tags.

## Custom events and consent

If you have your own custom events that you use as triggers for tags and also want to add an additional condition on the consent status of the user, check [this page](/cmp/web-sdk/third-parties/tags-management/events-and-variables/custom-events) for more details.


# Eulerian

This section describes how to control what tags are embedded on your website when using Eulerian for managing tags.

{% hint style="info" %}
Events and variables used by Eulerian are detailed in [this documentation.](/cmp/web-sdk/third-parties/tags-management/events-and-variables)
{% endhint %}

{% hint style="warning" %}
Please note that Eulerian can only be used for the GDPR regulation. You can contact us at <support@didomi.io> if you have a specific query to use Eulerian for other regulations.
{% endhint %}

## Overview

The key idea of the integration is that Didomi pushes consent information into Eulerian by firing calls to indicate when tags that require consent for a specific category/vendor can be loaded. You should then configure Eulerian to only fire tags after consent has been collected for each category/vendor.

{% hint style="info" %}
Categories in Eulerian are linked to Didomi vendors. When we speak about categories, we speak about Didomi vendors, which correspond to an Eulerian category.
{% endhint %}

On your side, the integration relies on linking your tags to categories for vendors that do not support the IAB framework to make them fire only once consent is collected. Tags that do not require consent must be linked to a `noconsent` category that will be triggered on every page load automatically.

For instance, after a user gives consent to the vendor `google`, the SDK will push the category `google` to Eulerian with the status `allowed`. The tags setup in Eulerian and linked to the `google` category can then be fired.

{% hint style="warning" %}
**Make sure that our SDK is setup**

Before continuing, please read our section on [setting up our SDK](/cmp/web-sdk/getting-started) to learn how to do the initial setup of your tag. It is particularly important that our tag gets embedded before all the other tags on your page.
{% endhint %}

## Configure the Didomi / Eulerian integration

### Step 1 - Enable the slave mode for the Consent Management Platform

First, contact Eulerian's support and request them to enable the slave mode for the Consent Management Platform. This will allow Didomi to interact with Eulerian for sharing the consent status fo the user.

To know more, please read the section 'ACTIVATE THE MASTER/SLAVE MODE OF THE EULERIAN CMP' of their documentation: <https://eulerian.wiki/doku.php?id=en:modules:collect:gdpr:master-slave_cmp>

### Step 2 - Enable the Eulerian integration

Enable the Eulerian integration in the Integrations tab of your consent notice.

<figure><img src="/files/8Z0gG1uK9qJA9a5Oz8xf" alt=""><figcaption><p>Eulerian integration in the Didomi Console</p></figcaption></figure>

{% hint style="danger" %}
**Embedding the Didomi SDK through Eulerian**

We recommend not embedding the Didomi SDK through Eulerian. By being directly on your pages, the Didomi SDK can load faster and also ensures that IAB vendors can detect a CMP on the page as soon as possible.

Embedding the Didomi SDK through Eulerian will result in less consents being passed to vendors and a lower consent rate from their perspective.
{% endhint %}

### Step 3 - Add the Eulerian collector script into your page

Didomi uses the Eulerian collector to send data. The collector script is not included by default in Eulerian. To access it you need to copy and paste the collector script in your page.

To access this script, go to your Eulerian dashboard into **Collection > Configuration > Site-centric > First-party data > EA\_collector configuration** and copy the asynchronous version from the Eulerian website. Add the EA\_collector script onto your website.

![](/files/-M8qcL5f9GSVgqIxt-qC)

### Step 4 - Add the categories into Eulerian

You need to create categories that will be linked to a vendor and used to decide when to load each tag in Eulerian. Vendors that do not require consent need to use a specific category called `noconsent` (More information below).

To create a category, go to **Activation > Consent Manager > Show list of consent managers**.

![](/files/-M8qBY1jD-R8r9F5Bi5h)

Add a category with the name corresponding to the vendor you want to condition. To know more about the name to use, please read [this section](#vendors).

![](/files/-M8qAu3qWgvT7ND4p4Nb)

You need to create a category for every vendor tag that you need to condition on the user consent status.

For instance, to load a Google vendor tag, create a category with the following condition:

* `name` equals `didomi:google`
* Link your Google vendor tag to this category

With this category configured, your tag will be fired when the page loads AND consent has been given on a previous page for the vendor Google or when the user gives consent to Google in the banner.

#### Vendors

The vendor name is only pushed in the list of categories if the user has given consent to it and to every purpose required by that vendor.

{% hint style="info" %}
**Vendor IDs are prefixed**

* `iab:` for IAB vendors (ex: `iab:1`)
* `didomi:` for Didomi vendors (ex: `didomi:google`)
* `c:` for custom vendors (ex: `c:vendor-id`)

Make sure to include the prefix in your Eulerian category.
{% endhint %}

**How to find your vendor ID?**

To find your vendor ID, in your Didomi account, go to Consent notices -> Open your notice -> Regulation -> Edit vendors and Purposes: copy the SDK ID.

<figure><img src="/files/e4AaT59Alk0c2qCGady5" alt=""><figcaption><p>Copy the SDK ID to have your vendor ID</p></figcaption></figure>

#### Create a category for tags that do not require consents

Vendors/tags that do not require consent need to have the `noconsent` option (last row) activated. [IAB vendors ](https://iabeurope.eu/vendor-list/)need to have this option activated as well as they will automatically collect the consent status from Didomi through the IAB TCF API.

![](/files/-MB4mJ4QLUBVLIOVaOVr)

### Step 5 - Link your categories to your tags

Once you have all your categories created. You can create and link your tags to the categories/vendors.

To create a tag, go to **Activation > TMS > Tag Management System**.

![](/files/-M942kEVy2zdacQN6MLG)

When you create your tag, link this tag to the category related.

![](/files/-M942m8-BJjNJNl6Bznn)

{% hint style="info" %}
Don't forget to activate your tag once it is created
{% endhint %}

### Step 6 - Activate the slave mode of the Consent Manager

To activate the slave mode, go to your Eulerian dashboard in **Activation > Consent Manager > Show list of consent managers**

![](/files/-M8qcpIiakeyJyG2gZ-n)

Once you are on the page, create a new consent manager (slave/asservi) and use **didomi\_eulerian** as cookie name. Make sure this consent manager is enabled and is the only one enabled.

![](/files/-M8qdTWX51RYE761uQPj)

{% hint style="info" %}
Be aware that this step will activate the slave mode and block by default, all the categories. Make sure to test in your staging environment first.
{% endhint %}


# Google Tag Manager

There are currently two ways for Didomi Web SDK to interact with Google Tag Manager.

* Configuring the Didomi/GTM custom integration. Google and non-google vendors are currently supported.
* Didomi's GTM template - A more native way to enable Google Consent Mode. It currently supports GCM statuses only (Google Analytics and Google Ads).


# Configure the Didomi / GTM integration

{% hint style="info" %}
Events and variables used by GTM are detailed in [this documentation.](/cmp/web-sdk/third-parties/tags-management/events-and-variables)
{% endhint %}

{% hint style="danger" %}
To avoid overriding our variables in the dataLayer in the case where Didomi is loaded before the dataLayer initialization, we recommend to instantiate it with this syntax : `window.dataLayer=window.dataLayer || [];` instead of `window.dataLayer=[];`
{% endhint %}

This section describes how to control what tags are embedded on your website when using Google Tag Manager for managing tags.

The key idea of the integration is that Didomi pushes consent information into Google Tag Manager as variables of the data layer. You should then configure GTM to only fire tags after consent has been collected for every vendor.

The integration relies on adding a trigger to all the tags from vendors that do not support the IAB framework to make them fire on a custom event from the data layer. The Didomi SDK will then fire an event with the list of vendors that the user has given consent to, which will ensure that Google Tag Manager only loads the tags matching the user consent.

For instance, if the user gives consent to the vendor `google`, the SDK will push the event `didomi-consent` and the variable `didomiVendorsEnabled` with the value `google,`. The tags setup in Google Tag Manager and with a trigger `"didomiVendorsEnabled" contains "google,"` will then be loaded by Google Tag Manager and other tags with triggers for a different vendor ID will not be loaded.

{% hint style="warning" %}
**Make sure that our SDK is setup**

Before continuing, please read our section on [setting up our SDK](/cmp/web-sdk/getting-started) to learn how to do the initial setup of your tag. It is particularly important that our tag gets embedded before all the other tags on your page.
{% endhint %}

### Step 1 - Enable our GTM integration

Enable the GTM integration in the Integrations tab of your consent notice by selecting this box:

<figure><img src="/files/ARRpgGfncpG2Khn6G6ov" alt=""><figcaption><p>GTM integration in the Didomi Console</p></figcaption></figure>

By default, Didomi uses the name “dataLayer” as the variable name for your [GTM data layer](https://support.google.com/tagmanager/answer/6164391?hl=en).

If you are using [another name for your data layer](https://developers.google.com/tag-manager/devguide#renaming), you can instruct Didomi to use this name instead, by typing it in the “DATA LAYER NAME” field.

If you are configuring Didomi through the Console, you can now go to the next step (2 - Create the variables in GTM).

{% hint style="danger" %}
**Embedding the Didomi SDK through GTM**

We recommend not embedding the Didomi SDK through GTM. By being directly on your pages, the Didomi SDK can load faster and also ensures that IAB vendors can detect a CMP on the page as soon as possible.

Embedding the Didomi SDK through GTM will result in fewer consents being passed to vendors and a lower consent rate from their perspective.
{% endhint %}

### Step 2 - Create the variables in GTM

The Didomi SDK will automatically push variables and events to GTM that contain the user consent status. You can then use these custom variables and events to decide when to load a vendor tag on your website.

First, you need to create a data layer variable that maps to the `didomiVendorsEnabled` variable for example, that will be pushed by the SDK onto the data layer.

1\) Go to the "Folders" section of your Google Tag Manager workspace:

![GTM folders](/files/-LDh8jbIiLL0-DcBDbs6)

2\) Create a new folder named "Didomi"

3\) Click on “add new variable”

4\) Create new user-defined variables, using the following configuration:

* Name: Didomi Vendors Consent
* Variable type: Data Layer Variable
* Data layer variable name: didomiVendorsEnabled

<figure><img src="/files/q3czKctCEf3an4majsDe" alt=""><figcaption><p>GTM Didomi variable</p></figcaption></figure>

Note: We recommend keeping Didomi's variables and triggers in a dedicated "Didomi" folder but you are free to structure resources differently.

Please read [this documentation](/cmp/web-sdk/third-parties/tags-management/events-and-variables#variables) for the list of all variables that are pushed to GTM by the Didomi SDK.

### Step 3 - Create triggers

You need to create triggers that will be used to decide when to load each tag in Google Tag Manager.

For every vendor tag that you need to control, in the "Folders" section of the manager, add a new trigger to the Didomi folder:

And use the following configuration:

* Trigger name: "{name of the Vendor} – {id of the vendor}" for example (see “how to find your vendor ID” further down in the article)
* Trigger type: Custom event
* Event name: one of the [events pushed by Didomi ](/cmp/web-sdk/third-parties/tags-management/events-and-variables#events)(`didomi-consent`, `didomi-ready` or `didomi-consent-changed`). We recommend using didomi-consent, because this event is merging didomi-consent-changed and didomi-ready. As a result, it will take care of a change of consent and a simple page load.
* “This trigger fires on “: Some Custom Events
* “Fire this trigger when an Event occurs and all of these conditions are true” :`Didomi Vendors Enabled` contains `{id of the vendor},`. Use the full ID of the vendor with an additional comma (`,`) at the end.
* Save.

<figure><img src="/files/VIZw0vEeT5hAAdvb0SIp" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
When matching vendors by IDs in variables, use the full ID of the vendor with an additional comma (`,`) at the end to ensure IDs do not get mixed and matched.\
Example: Use `google,` to match the vendor with ID `google` and not the vendor with ID `googleana-4TXnJigR`.
{% endhint %}

**Repeat this process for every non-IAB vendor that you have.** You need to create one trigger **per** non-IAB vendor.

Then, if your existing trigger is a custom trigger, you will need to create [a Trigger group](https://support.google.com/tagmanager/answer/9164222?hl=en), so that the tag triggers when condition 1 (already existing condition) **AND** condition 2 (related to consent) are both met.

Otherwise, if you just add another firing trigger related to consent to a tag with an already existing condition, the tag will trigger when condition 1 OR condition 2 are met. But not necessarily both at the same time, and this will not be compliant.

In the "Folders" section of the manager, add a new trigger to the Didomi folder, using the following configuration :

* Trigger group name : Trigger Group - Consent + {other condition} - {name of the Vendor} – {id of the vendor}
* Trigger type: “Trigger Group”.
* Select the existing trigger of your tag.
* Also select the Didomi trigger for this vendor, that you created in step 3.
* Save

{% hint style="info" %}
**Note**: Please note that trigger groups are triggered once per page only, which can be an issue when using dynamic websites. In that case, you can use our [functions](/cmp/web-sdk/reference/api) and [events](/cmp/web-sdk/third-parties/tags-management/events-and-variables). And in the specific context of a SPA, you can refer to our dedicated [GitHub page](https://github.com/didomi/samples/tree/main/how-to-track-SPA-with-GTM-and-Didomi).
{% endhint %}

**How to find your vendor ID?**

To find your vendor ID, in your Didomi account, go to Consent notices -> Open your notice -> Regulation -> Edit vendors and Purposes: copy the API ID. Learn more about variables in [this documentation.](/cmp/web-sdk/third-parties/tags-management/events-and-variables#variables)

<figure><img src="/files/rzArfbsk2g40tYqpnidh" alt=""><figcaption></figcaption></figure>

This trigger (or trigger group) can now be used to define tags that fire only when the user has given consent for that vendor.

{% hint style="danger" %}
Following these instructions while also enabling Google Consent Mode, will result in negatively impacting the Consent Mode functionality by blocking the Google tags from firing until consent is granted.
{% endhint %}

If enabling Google Consent Mode via our [GCM direct integration](https://docs.didomi.io/consent-management-platform-cmp/frameworks-regulations/google-consent-mode-v2), make sure that no consent-aware tags are configured for Google tags (vendors `google` , `googleana-4TXnJigR`).

To make sure Google Consent Mode is working, you will have to remove any consent-aware event and only use the didomi-ready event.

![](/files/LmTIw1IGkmNvQv2iFbqI)

Google Consent Mode only supports GDPR. For multi-regulation notices, you may want to duplicate your tags and condition them according to the applicable regulation. To do this, you can use the variable `didomiRegulationName`.

Alternatively, you could use two GTM containers, one for GDPR, one for the other regulations, and load one or the other based on the applicable regulation.

### Step 4 - Classify your tags

You now need to classify your tags and define what user consent is required for firing each of them. This last step is very important.

In the "Tags" section of your Google Tag Manager, edit **EACH** of your existing tag concerning non-IAB vendors and add the trigger or the trigger group (created at step 3) corresponding to the vendor that owns the tag instead of what was previously used.

Remember to condition the tags of **all your containers.**

![GTM didomi tag](/files/-LDh8jcgWN33A34qdvf8)

Moving forward, every time you add a new tag that does not implement the IAB specification and that requires GDPR consent, you must categorise it by adding the adequate trigger.

### Custom events and consent

If you have your own custom events that you use as triggers for tags and also want to add an additional condition on the consent status of the user, check [this page](/cmp/web-sdk/third-parties/tags-management/events-and-variables/custom-events) for more details.


# Didomi's GTM template

This section describes how to enable and configure Didomi's GTM custom template. The template is part of [Google's Community Template Gallery.](https://tagmanager.google.com/gallery/)

There are a few reasons why you might want to make use of this template:

* Enabling this template on your site automatically enables [Google Consent Mode](https://developers.didomi.io/cmp/web-sdk/third-parties/direct-integrations/google-consent-mode#configuring-google-tags) support.
* Templates are a native way to integrate with GTM.
* Any time a template is updated you will have the chance to automatically update it via the GTM console.
* No custom events or triggers are needed to handle Google consent mode statuses. *The template currently supports GCM statuses only (Google Ads and Google Analytics).*

### How to enable and configure Didomi's GTM template?

{% hint style="info" %}
When using the template, please disable the Google Consent Mode integration in the console to prevent conflicts.\
Also remember to enable the GTM integration within the Didomi's console
{% endhint %}

<figure><img src="/files/r8NLJZBcvT9ZFZezA4Hu" alt=""><figcaption></figcaption></figure>

In order to use this GTM template (Didomi CMP), you will need to create a new tag and associate the template with at least one trigger.

#### **Creating a new tag**

After accessing your Google Tag Manager account and select your workspace of choice.

* Click the "New Tag" button as shown here,

![New tag - option 1](https://user-images.githubusercontent.com/30706016/128257772-25becf03-3933-452a-8f1d-812b27cc8fcb.png)

Or navigate to the "Tags" tab, and click on the "New" button at the top right side of the tags table.

![New tag - option 2](https://user-images.githubusercontent.com/30706016/128257780-83929c88-0006-4c0d-a111-14fb1d301670.png)

* Use a relevant name for the new tag ("Didomi CMP" was used for this example) and hit the "Tag Configuration" card.

![](https://user-images.githubusercontent.com/30706016/128257793-23fb07a4-1457-4196-9aab-0121880e7d7e.png)

* From that screen you should have access to all the templates in the Community Template Gallery, including the "Didomi CMP" one. Look for it and load it.

![Didomi GTM template in the Community Gallery](https://user-images.githubusercontent.com/30706016/128257687-d36f0833-9814-4592-8c74-79a8ccf5ef9a.png)

At this point, you should have access to the template UI

<figure><img src="/files/O4tI5yqyG5Gc4K1gjirC" alt=""><figcaption></figcaption></figure>

#### **Associating a trigger to a tag**

We want our tag to be fired on all pages and make sure that it is fired before any other tags. In order to achieve that,

* Click on the "Triggering" card to choose a trigger so that the tag fires.

![Associating a trigger to the template](https://user-images.githubusercontent.com/30706016/128259753-938464b6-fe65-4b43-90c3-1dba7f754865.png)

* Select the "Consent Initialization" trigger.
* Save the tag. This is where you will choose the default values for the consent mode parameters.

### Setting Default Consent Values by Region

The Didomi GTM template allows you to configure default consent states for different regions, ensuring compliance with various privacy regulations while optimizing user experience.

**Regional Default Behavior**

The template includes pre-configured regional settings that align with Didomi's regulation logic:

* GDPR regions are set to denied by default, including:
  * EU countries: AT, BE, BG, CY, CZ, DE, DK, EE, ES, FI, FR, GR, HR, HU, IE, IT, LT, LU, LV, MT, NL, PL, PT, RO, SE, SI, SK
  * Other GDPR-regulated territories: AD, BR, GB, GF, GG, GI, GP, IS, JE, LI, MC, MF, MQ, NO, RE, SM, VA, YT
* Non-GDPR regions: Default behavior depends on the global configuration option

**Global Configuration Option**

Use the "Set all GCM purposes to GRANTED by default - for all regions except EU" checkbox to control the default consent behavior:

* When enabled:
  * GDPR regions are denied by default
  * Non-GDPR regions are granted by default.
* When disabled: All regions are denied by default (legacy behavior)

**Custom Regional Overrides**

For more granular control, you can override default settings for specific regions using the parameter table:

1. Region field: Enter ISO 3166-2 region codes (e.g., "US-CA, US-CO" for California and Colorado)
2. Leave blank: To apply settings to all regions not covered by other entries
3. Consent types: Set individual consent states for each Google Consent Mode purpose

The template processes these overrides in order, with later entries taking precedence over earlier ones.

<figure><img src="/files/x1pQUmpuKvJyh40Zd1zk" alt=""><figcaption></figcaption></figure>

### Embedding the Didomi Web SDK from the GTM template

The template's UI will give you the option of embedding the Didomi Web SDK from within the template:

<figure><img src="/files/Lr7yflsAsJYAen5EONkX" alt=""><figcaption><p>Embedding Didomi's SDK via the GTM template</p></figcaption></figure>

While the template can embed the SDK directly on your website, we do not recommend this setup in production as it delays loading the Web SDK and subsequent tags that depend on it like advertising, analytics, etc. We are leaving the option available for testing purposes. Embedding the Didomi SDK through GTM will result in fewer consents being passed to vendors and a lower consent rate from their perspective.

We recommend embedding the Web SDK directly into the source code of your website for the best performance. By being directly in the source code of your website, the Didomi Web SDK can load faster and also ensures that IAB vendors can detect a CMP on the page as soon as possible.

{% hint style="danger" %}
When embedding the Didomi Web SDK directly in the code of your website, make sure that the "Embed the Didomi Web SDK" option on the template is disabled.
{% endhint %}

#### Embedding the Web SDK configuration

Once you have enabled the "Embed the Didomi Web SDK" option, the UI will change as follows.

\
A quick note on the fields,

<figure><img src="/files/9CSdBweEdeuXr3ZdJnTo" alt=""><figcaption></figcaption></figure>

* **Public API key:** Required field. It must be a valid UUID value.
* **Notice ID:** Optional field. Setting its value would be the equivalent to configuring "Manual Targeting" in the Didomi console. Leaving it blank would be the equivalent to "Domain Targeting" in the Didomi console.
* **Enable IAB TCF support:** Enable this option if the IAB TCF is enabled for your consent notice in the Didomi Console. See [here](https://docs.didomi.io/consent-management-platform-cmp/frameworks-regulations/iab-tcf) for more information.

### Preview

In order to test the tag on a website, you can make use of the "Preview" feature of the GTM platform. You can find a "Preview" button at the top right of the GTM navbar menu.

![](/files/-Mi2_bqe-gJThiaP1Blb)

You will be prompted by the following screen where you can set up the URL of your website.

![This example uses https://sandbox.didomi.io/gtm.html](https://user-images.githubusercontent.com/30706016/128261167-d8dc858c-5502-4583-83c3-cdd2a4d04945.png)

Clicking continue opens the "Tag Assistant" website. This assistant is a live tool that can help tremendously with debugging your tags and/or templates.

You can see that the tag being previewed is in fact being fired during the initial load of the site.

![Didomi CMP Test is the name of the tag used in this example](https://user-images.githubusercontent.com/30706016/128379448-39b95cfe-8334-4715-aae3-da03badd94b8.png)

### Submit

Once the testing/previewing process has been successful, you can "Submit" a tag to a website so that it goes live.

In this case, click on the "Submit" button at the top right of the GTM nav bar menu (to the right of the "Preview" button).

### Debugging

You can check whether "hits" are being correctly transmitted to Google or not. To do so, go to the DevTools/Network tab, filter by "collect" and look for the `gcs` parameter (as shown in the image below).

![](/files/-Mi2SNHexPCvxelWBMdx)

You will find a value for the parameter (G111 in this case). It can be understood as follows:

* G1: This initial value is always the same.
* The following digit (0 or 1) refers to `ad_storage`.
* The third number (0 or 1) refers to `analytics_storage`.

For both cases 0 means **“denied”** and 1 means **“granted”**.

In our case, **G111** means that marketing and statistics cookies have both received consent.

{% hint style="danger" %}
If you're previewing and/or have submitted our GTM template to your site and the `gcs` parameter values don't match, please make sure to enable the following vendor IDs via the DIDOMI console: `google`, `googleana-4TXnJigR`
{% endhint %}


# Tealium

This section describe how to control what tags are embedded on your website when using Tealium for managing tags.

{% hint style="info" %}
Events and variables used by Tealium are detailed in [this documentation.](/cmp/web-sdk/third-parties/tags-management/events-and-variables)
{% endhint %}

## Overview

The key idea of the integration is that Didomi pushes user actions and consent information into Tealium by firing events/direct calls ([`utag.link`](https://docs.tealium.com/platforms/javascript/track/#utag-link)) to indicate when tags that require consent can be loaded. You should then configure load rules in Tealium to only fire tags after consent has been collected for each vendor.

On your side, the integration relies on adding rules, events and conditions to all the tags from vendors that do not support the IAB framework to make them fire on a custom event from the data layer. The Didomi SDK will then fire an event with the list of vendors that the user has given consent to, which will ensure that Tealium only loads the tags matching the user consent.

For instance, after a user gives consent to the vendor `google`, the SDK will push the direct call `didomi-consent-changed` and the variable `didomiVendorsEnabled` with the value `google,`. The tags setup in Tealium can then be fired through a load rule on the event `didomi-consent-changed`.

{% hint style="warning" %}
**Make sure that our SDK is setup**

Before continuing, please read our section on [setting up our SDK](/cmp/web-sdk/getting-started) to learn how to do the initial setup of your tag. It is particularly important that our tag gets embedded before all the other tags on your page.
{% endhint %}

## Configure the Didomi / Tealium integration

### Step 1 - Enable the Tealium integration

If you are configuring Didomi through the Console, enable the Tealium integration in you Consent notice -> Cutomization -> Integrations:

<figure><img src="/files/if4xRVQgKzgCgAPIbXCC" alt=""><figcaption><p>Tealium integration in the Didomi Console</p></figcaption></figure>

{% hint style="danger" %}
**Embedding the Didomi SDK through Tealium**

We recommend not embedding the Didomi SDK through Tealium. By being directly on your pages, the Didomi SDK can load faster and also ensures that IAB vendors can detect a CMP on the page as soon as possible.

Embedding the Didomi SDK through Tealium will result in less consents being passed to vendors and a lower consent rate from their perspective.
{% endhint %}

### Step 2 - Add the Events extension

Didomi pushes the user consent status through Tealium events and you will use the `tealium_event` variable to condition your tags.

Enable the Events extension in Tealium to ensure that the `tealium_event` variable is available in the data layer and can be used in load rules:

* [Tealium - Events Extension](https://docs.tealium.com/iq-tag-management/extensions/extensions-list/tealium-events-extension/)
* [Tealium - Add an extension](https://docs.tealium.com/iq-tag-management/extensions/manage/)

### Step 3 - Create load rules

You need to create load rules that will be used to decide when to load each tag in Tealium. Vendors that do not require consent do not need to be updated. [IAB vendors](https://vendor-list.consensu.org/v3/vendor-list.json) do not need to be conditioned either as they will automatically collect the consent status from Didomi through the IAB TCF API.

For every vendor tag that you need to condition on the user consent status, create or update a load rule that loads the tag when consent is collected and consent has been given for the vendor.

For instance, to load a Google vendor tag, create a rule with the following conditions:

* `tealium_event` equals `didomi-ready`
* AND `didomiVendorsEnabled` contains `google,`

{% hint style="warning" %}
When matching vendors by IDs in variables, use the full ID of the vendor with an additional comma (`,`) at the end to ensure IDs do not get mixed and matched.\
Example: Use `google,` to match the vendor with ID `google` and not the vendor with ID `googleana-4TXnJigR`.
{% endhint %}

With this load rule configured, your tag will be fired when the page loads AND consent has been given on a previous page for the vendor Google. If you also want the tag to fire when consent is given on the current page, also add a rule when `tealium_events` equals `didomi-consent-changed`.

For more information on the events and variables available for your load rules:

* See [Events](/cmp/web-sdk/third-parties/tags-management/events-and-variables#events) for more information on the values of `tealium_event`.
* See [Variables / Vendors](/cmp/web-sdk/third-parties/tags-management/events-and-variables#vendors) for more information on `didomiVendorsEnabled` and other variables available to condition your tags.

**How to find your vendor ID?**

To find your vendor ID, go to the *Vendors and Purposes* section of your Didomi account and copy the API ID. Learn more about variables in [this documentation.](/cmp/web-sdk/third-parties/tags-management/events-and-variables#variables)

<figure><img src="/files/fkC4sjqZUKNC0SPqPaxA" alt=""><figcaption></figcaption></figure>

### Custom events and consent

If you have your own custom events that you use as rules for tags and also want to add an additional condition on the consent status of the user, you need to make sure that your custom events only fire after the Didomi event that you are using (so that the Didomi variables have already been populated). You have two options to do so.

Check [this page](/cmp/web-sdk/third-parties/tags-management/events-and-variables/custom-events) for more details on custom events.


# Other tag managers

This section explains how to integrate Didomi with any tag manager that we do not have a direct integration with. This allows you to to use consent information in rules when deciding whether a tag can be loaded or not directly from your tag manager.

{% hint style="info" %}
Events and variables are detailed in [this documentation.](/cmp/web-sdk/third-parties/tags-management/events-and-variables)
{% endhint %}

## Overview

Didomi stores variables on the `window.didomiState` object with the consent information from the user. A custom tag manager integration requires passing that consent information to the data layer of the tag manager, to be able to create tag-loading rules based on the user consent status.

With this guide, you will:

* Pass consent information from Didomi to the data layer of your tag manager
* Create rules in your tag manager to only load tags when consent is granted
* Delay loading of your tag manager and/or tags that require consent

## Configure the integration

### Step 1 - Website configuration

#### Option A - Dynamic data layer - Update the data layer on your website

If your tag manager supports dynamically passing variables to the data layer after page load, this is the best option to leverage as you will not need to delay your tag manager initialization.

The Didomi SDK stores a copy of the user consent status in variables on the `window.didomiState` object. To get started, update the data layer on your website to pass variables from Didomi to your tag manager after the Didomi SDK is ready:

```javascript
<script type="text/javascript">
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) {
    window.updateDataLayer({      
      // Didomi variables  
      didomiRegulationName: window.didomiState.didomiRegulationName,
      didomiVendorsEnabled: window.didomiState.didomiVendorsEnabled,
      didomiVendorsDisabled: window.didomiState.didomiVendorsDisabled,
      didomiVendorsUnknown: window.didomiState.didomiVendorsUnknown,
      didomiPurposesEnabled: window.didomiState.didomiPurposesEnabled,
      didomiPurposesDisabled: window.didomiState.didomiPurposesDisabled,
      didomiExperimentId: window.didomiState.didomiExperimentId,
      didomiExperimentUserGroup: window.didomiState.didomiExperimentUserGroup,
      didomiGDPRApplies: window.didomiState.didomiGDPRApplies,
      didomiIABConsent: window.didomiState.didomiIABConsent,
      
    };
});
</script>
```

`updateDataLayer` is an example function name. Your tag manager will have its own way of passing custom variables to the data layer dynamically.

Notice how the data layer is updated in a `didomiOnReady` handler. This guarantees that the Didomi consent status is available in the `didomi*` variables when the data layer for your tag manager gets updated.

#### Option 2 - Static data layer - Update the data layer on your website

Some tag managers load variables into the data layer only on page load and do not have an option to dynamically pass variables later in the page lifecycle. As a result, you will need to update your website configuration to delay loading the tag manager and set the `dataLayer` variable only after Didomi is loaded on the page.

The Didomi SDK stores a copy of the user consent status in variables on the `window.didomiState` object. To get started, update your `dataLayer` JavaScript on your website to pass variables from Didomi to your tag manager after the Didomi SDK is ready:

```javascript
<script type="text/javascript">
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) {
    window.dataLayer = {
      // Keep your existing variables here
      firstVariable: 'content',
      secondVariable: 'content',
      ...
      
      // Add Didomi variables
      didomiRegulationName: window.didomiState.didomiRegulationName,
      didomiVendorsEnabled: window.didomiState.didomiVendorsEnabled,
      didomiVendorsDisabled: window.didomiState.didomiVendorsDisabled,
      didomiVendorsUnknown: window.didomiState.didomiVendorsUnknown,
      didomiPurposesEnabled: window.didomiState.didomiPurposesEnabled,
      didomiPurposesDisabled: window.didomiState.didomiPurposesDisabled,
      didomiExperimentId: window.didomiState.didomiExperimentId,
      didomiExperimentUserGroup: window.didomiState.didomiExperimentUserGroup,
      didomiGDPRApplies: window.didomiState.didomiGDPRApplies,
      didomiIABConsent: window.didomiState.didomiIABConsent,
    };
});
</script>
```

`dataLayer` is an example variable name. Your tag manager will have its own naming for data layer variables.

Notice how the `dataLayer` variable is defined in a `didomiOnReady` handler. This guarantees that the Didomi consent status is available in the `didomi*` variables when the external variables for your tag manager get registered.

### Step 2 - Delay initializing your tag manager

{% hint style="warning" %}
**If you are using a static data layer**, you will need to delay the initialization of your tag manager to make sure that the user consent status is available in the data layer when tags get evaluated and loaded.

**If you are using a dynamic data layer**, you usually do not need to implemented this step.
{% endhint %}

Didomi creates the `window.didomi*` variable when the SDK is done loading. You must delay your tag manager until Didomi is ready or the variables holding the consent status will be undefined.

To delay your tag manager, update your `<script>` tags that load your tag manager to execute after Didomi is loaded. For instance:

```javascript
<script type="text/javascript" src="/path/to/tagmanager.js"></script>
```

becomes:

```javascript
<script type="didomi/javascript" src="/path/to/tc_script.js"></script>
```

Notice how we replaced the script type `text/javascript` with `didomi/javascript`. This will ensure that your tag manager only gets included after Didomi is ready.

[Read our documentation](/cmp/web-sdk/third-parties/no-tag-manager#add-didomi-less-than-script-greater-than-tags-to-your-page) for more information on this feature.

### Step 3 - Create rules in your tag manager

Now that your data layer is setup, you are able to access the user consent status collected by Didomi in your tag manager.

You need to create rules on your tags that require consent to only load after consent is given by the user. How to do that depends on your tag manager and we can only provide a generic outline of the setup.

Generally, you will create rules that depend on the `didomiVendorsEnabled` and that constrain a tag to be loaded only if that variables contains a specific value indicating that the user has given consent for that vendor.

For instance, if you want to load Google Ads only if the user has given consent to the vendor Google, you will create a rule that only embeds ads into the page if the `didomiVendorsEnabled` data layer variable contains "google,".


# Custom Didomi \<script> tags

Didomi `<script>` tags can be used to conditionally load JavaScript tags or other HTML elements on your page.

In this method, you replace your `<script type="text/javascript">` tags or any HTML element with `<script type="didomi/javascript">` or `<script type="didomi/html">` tags and add `data-*` attributes determining when the tags should be loaded based on consent given to vendors and/or purposes.

When the Didomi SDK is loaded on a page or when the user gives consent, the tags will be scanned and replaced as follows:

| Tag                                             | Replacement                                   |
| ----------------------------------------------- | --------------------------------------------- |
| `<script type="didomi/javascript">...</script>` | `<script type="text/javascript">...</script>` |
| `<script type="didomi/html">...</script>`       | `<div>...</div>`                              |

The Didomi SDK keeps all the original attributes (including the `data-*` attributes) and content from the `<script type="didomi/javascript|html">` tags when doing the replacement so no other change than the HTML element is required.

## Consent to vendors

The `data-vendor` attribute accepts a single vendor ID and conditionally loads a tag when the user enables a vendor and all the purposes required by that vendor.

The `data-vendor-raw` attribute accepts a single vendor ID and conditionally loads a tag when the user enables a vendor (does not include its purposes).

Note that enabling purposes with legal basis "Legitimate interest" is not required before loading a tag for a vendor. Read the [Consent to purposes](#consent-to-purposes) section to required consent for specific purposes irrespective of the vendor's legal bases configuration.

**Examples**

{% tabs %}
{% tab title="JavaScript tag" %}
Google Analytics tag:

```markup
<script type="text/javascript">
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
```

becomes

```markup
<script type="didomi/javascript" data-vendor="custom-vendor-id">
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
```

The Google Analytics tag is only loaded onto the page when the user gives consent to the vendor Google and all its associated purposes.
{% endtab %}

{% tab title="HTML element" %}
Facebook like button:

```markup
<!-- Load Facebook SDK for JavaScript -->
<div id="fb-root"></div>
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.0"></script>

<!-- Your like button code -->
<div class="fb-like" 
  data-href="https://www.your-domain.com/your-page.html" 
  data-layout="standard" 
  data-action="like" 
  data-show-faces="true">
```

becomes

```markup
<script type="didomi/html" data-vendor="facebook">
	<div id="fb-root"></div>
	<div class="fb-like" 
	data-href="https://www.your-domain.com/your-page.html" 
	data-layout="standard" 
	data-action="like" 
	data-show-faces="true">
</script>

<script type="didomi/javascript" data-vendor="facebook" async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.0"></script>
```

The Facebook Like button is only loaded onto the page when the user gives consent to the vendor Facebook and all its associated purposes.
{% endtab %}
{% endtabs %}

#### **How to find your vendor ID?**

* To find your vendor ID, navigate to the Didomi Console -> Consent notices -> Open your notice -> Regulation -> Edit vendors and Purposes: Use the API ID.
* Vendor IDs are unique and are the same across all regulations and notices.

<figure><img src="/files/fkC4sjqZUKNC0SPqPaxA" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The Didomi Web SDK used to format vendor IDs with a prefix ( `prefix:ID,`).

The prefix that were supported:

* `iab:` for IAB vendors.
* `didomi:` for Didomi vendors.
* `c:` for custom vendors.

To keep backward compatibility, the `data-vendor and data-vendor-raw` continue to support prefixed vendor IDs. However it is mandatory to switch to the non-prefixed vendor IDs (i.e API ID) if you are willing to use multiple regulations.
{% endhint %}

{% hint style="warning" %}
The `didomi/javascript` and `didomi/html` tags must be placed before the Didomi SDK tag on the page.

If they are not, the Didomi SDK might sometimes miss them if it gets executed before the HTML page is fully parsed.
{% endhint %}

{% hint style="danger" %}
Didomi `<script>` tags cannot be used through Google Tag Manager

Because GTM removes custom tag `data-*` attributes when it adds them to the page, you cannot add Didomi `<script>` tags in GTM.
{% endhint %}

## Consent to purposes

The `data-purposes` attribute accepts a comma-separated list of purpose IDs and conditionally loads a tag when the user enables all the specified purposes.

`data-vendor` is the recommended way of conditionally loading a tag as you need the user to enable a specific vendor and its associated purposes. It can be combined with `data-purposes` if you want to force consent for specific purposes on top of the vendor's associated purposes. It can be because the vendor has chosen legitimate interest as a legal basis for one or more purposes or because a purpose is not associated with the vendor.

**Examples**

{% tabs %}
{% tab title="JavaScript tag" %}
Google Analytics tag:

```markup
<script type="text/javascript">
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
```

becomes

```markup
<script type="didomi/javascript" data-vendor="custom-vendor-id" data-purposes="measure_ad_performance,improve_products">
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
```

The Google Analytics tag is only loaded onto the page when the user gives consent to the vendor Google, all its required purposes, and the purposes `cookies` (Information storage and access) and `analytics` (Measurement).
{% endtab %}

{% tab title="HTML element" %}
Facebook like button:

```markup
<!-- Load Facebook SDK for JavaScript -->
<div id="fb-root"></div>
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.0"></script>

<!-- Your like button code -->
<div class="fb-like" 
  data-href="https://www.your-domain.com/your-page.html" 
  data-layout="standard" 
  data-action="like" 
  data-show-faces="true">
```

becomes

```markup
<script type="didomi/html" data-vendor="facebook" data-purposes="measure_ad_performance,improve_products">
<!-- Load Facebook SDK for JavaScript -->
<div id="fb-root"></div>
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.0"></script>

<!-- Your like button code -->
<div class="fb-like" 
  data-href="https://www.your-domain.com/your-page.html" 
  data-layout="standard" 
  data-action="like" 
  data-show-faces="true">
</script>
```

The Facebook Like button is only loaded onto the page when the user gives consent to the vendor Facebook, all its required purposes, and the purposes `measure_ad_performance` and `improve_products`.
{% endtab %}
{% endtabs %}

{% hint style="warning" %}
The `didomi/javascript` and `didomi/html` tags must be placed before the Didomi SDK tag on the page.

If they are not, the Didomi SDK might sometimes miss them if it gets executed before the HTML page is fully parsed.
{% endhint %}

{% hint style="danger" %}
Didomi `<script>` tags cannot be used through Google Tag Manager

Because GTM removes custom tag `data-*` attributes when it adds them to the page, you cannot add Didomi `<script>` tags in GTM.
{% endhint %}

## Macros

A macro is a string that will be replaced into a certain value once the script is loaded. It can be used to share consent information with partners embedded in `didomi/javascript` and `didomi/html` scripts.

The available macros are:

| Name                              | Value   | Description                                                                                                                                                                                                                                           |
| --------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| regulation\_name                  | string  | <p>The name of the regulation that applies for the current user.</p><p><br>Possible values: <code>gdpr</code>, <code>cpra</code>..<br><br>When no regulation applies to the current user <code>regulation\_name</code> returns <code>none</code>.</p> |
| `gdpr`                            | 0 or 1  | Whether GDPR applies to the current request or not                                                                                                                                                                                                    |
| `gdpr_consent`                    | string  | IAB consent string                                                                                                                                                                                                                                    |
| `gdpr_consent_vendor`             | 0 or 1  | Does the vendor specified in `data-vendor` have consent?                                                                                                                                                                                              |
| `gdpr_consent_vendor_boolean`     | boolean | Does the vendor specified in `data-vendor` have consent?                                                                                                                                                                                              |
| `gdpr_consent_vendor_raw`         | 0 or 1  | Does the vendor specified in `data-vendor-raw` have consent?                                                                                                                                                                                          |
| `gdpr_consent_vendor_boolean_raw` | boolean | Does the vendor specified in `data-vendor-raw` have consent?                                                                                                                                                                                          |

```javascript
<script data-vendor="8" type="didomi/javascript">
  console.log(`
    Which regulation applies: {regulation_name} // Will be replaced with gdpr or cpra..
    // Or: Does GDPR apply: {gdpr} // Will be replaced with 0 or 1.
    GDPR consent string: {gdpr_consent} // Will be replaced with the consent string
    Does the data-vendor (IAB vendor 8) have the consent: 
    {gdpr_consent_vendor} // Will be replaced with 0 or 1
    or {gdpr_consent_vendor_boolean} // Will be replaced with true or false
  `)
</script>

//  Output if GDPR applies, IAB vendor 8 has consent and the consent string is EXAMPLE_OF_CONSENT_STRING: 
//    Which regulation applies: gdpr
//    // Or: Does GDPR apply: 1
//    GDPR consent string: EXAMPLE_OF_CONSENT_STRING
//    Does the data-vendor (IAB vendor 8) have consent: 
//    1 
//    or true
```

## Immediate loading

By default, custom Didomi `<script>` tags are loaded on the page after the user gives consent (be it on the same page or on a previous page).

If you want to load these tags on the page immediately, irrespective of the user consent status, add a `data-loading` attribute with the value `immediate`.\
This supports use cases like always loading a tag on a page and passing the current user consent status to it.

{% hint style="danger" %}
Immediate loading should only be used in conjunction with macros in your tags as it allows you to load a tag on page load and get the user consent status through a macro, whether the consent status is positive or negative.

If you are not using macros and enable immediate loading for a tag, the result is the same as keeping a regular `<script type="text/javascript">` tag or HTML element on your page as it will always be loaded on the page without conditions.
{% endhint %}


# Third-party integrations


# Google Ad Manager / AdSense


# GDPR via Non-Personalized Ads

{% hint style="danger" %}
We recommend using the IAB TCF for integrating with Google Ad Manager or AdSense for GDPR. Please review our Google Ad Manager implementation recommendation [here](https://docs.didomi.io/integrations/google/configure-google-ad-manager-and-additional-consent-mode).

Our direct integration with Google Ad Manager which relies on passing an NPA parameter to ad requests is still available in the Didomi Console for backward compatibility but has been deprecated.
{% endhint %}

Didomi supports sharing consent with Google Ad Manager (ex DFP), AdSense and Ad Exchange asynchronous ad tags. When the user gives consent, the Google tags are configured to fetch personalized ads.

For this integration to work, you need to make sure that you are delaying the loading of Google ads until Didomi has shared the consent information with Google.

The Didomi SDK offers two different configurations:

* [Share consent and refresh ads](/cmp/web-sdk/third-parties/direct-integrations/google-ad-manager-adsense/google-dfp-adsense-adx/share-consent-and-refresh): In this setup, the Didomi SDK is in charge of both sharing the consent status with Google Ad Manager/AdSense but also takes care of the initial loading and refreshing of ads when needed. Use this configuration if you only use Ad Manager and no other script (Prebid, IAS, etc.) is in charge of loading/refreshing ads or needs to be synchronized with Ad Manager.
* [Share consent without ads refresh](/cmp/web-sdk/third-parties/direct-integrations/google-ad-manager-adsense/google-dfp-adsense-adx/share-consent-without-ads-refresh): In this setup, the Didomi SDK shares the consent status with Google Ad Manager/AdSense but does not load or refresh ads at all. You must synchronize with the SDK through an event listener to make sure that any ads refresh in your code or in third-party code (Prebid, IAS, etc.) happens after the Didomi SDK has passed consent to Google. Use this integration if you use Ad Manager to include auction results from Prebid, for instance.

Make sure to read the documentation dedicated to the setup that is appropriate for your website configuration. Feel free to reach out to our support team if you have any question.


# Share consent and load/refresh ads

{% hint style="danger" %}
Our integration with Google Ad Manager which relies on passing an NPA parameter to ad requests is still available in the Didomi Console. But we do not advise using it.\
Please review our Google Ad Manager implementation recommendation [here](https://docs.didomi.io/integrations/google/configure-google-ad-manager-and-additional-consent-mode).\
\
This module does not support automatically passing CCPA Do Not Sell Status to Google products yet.\
See <https://support.google.com/adsense/answer/9598414> for more information.
{% endhint %}

Didomi supports sharing consent with Google Ad Manager, AdSense and Ad Exchange asynchronous ad tags. When the user gives consent, the Google tags are configured to fetch personalized ads.

For this integration to work, you need to make sure that you are delaying the loading of Google ads until Didomi has shared the consent information with Google.

With this integration, Didomi will do two operations for you:

* Share the consent status with Google
* Refresh/load the ads on the page

Didomi must be in control of the initial loading of ads on the page to guarantee that consent has been passed to Google before the ads are loaded.\
You must not refresh the ads yourself or have any other tag refresh ads on the page or you will see the ads refreshed multiple times.

The Didomi SDK only synchronizes with Ad Manager. If you need to wait for other scripts to complete before loading or refreshing Ad Manager ads (for instance, wait for auction results from Prebid to integrate them into your Ad Manager ad slot), [use our Ad Manager integration and control the ads yourself](/cmp/web-sdk/third-parties/direct-integrations/google-ad-manager-adsense/google-dfp-adsense-adx/share-consent-without-ads-refresh).

## Configure the Didomi tag

{% hint style="info" %}
If you are using the Didomi Console to manage your consent notices, you can manage the Google integration from there and can skip this tag configuration section.
{% endhint %}

You must ensure that the Didomi tag gets embedded first on your pages and configure it to communicate with the Google tag.

### Enable the Didomi / Google integration

Make sure that you add the following vendors to your tag (in the `app.vendors` property):

* `google`as a Didomi vendor (`app.vendors.didomi` property)
* All the "ad technology providers" enabled in your Google account (see the [Google Ad Manager documentation](https://support.google.com/dfp_premium/answer/7673898) or the [Google AdSense documentation](https://support.google.com/adsense/answer/7670013)). They can be added as IAB vendors (recommended if they are in the list), Didomi or custom vendors, and must appear in the list for the consent to be valid.

You also need to enable the specific integration with Google with the property `integrations`:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>',
    vendors: {
      iab: {
        include: [
          ..., // All the vendors that you have enabled as ad technology providers in your Google account
        ]
      },
      didomi: [
        // Ask Didomi to collect consent for Google
        'google'
      ]
    }
  },

  integrations: {
    vendors: {
      // Setup the integration with Google (ask Didomi to share consent with Google tags)
      google: {
        enable: true,
        eprivacy: true
      }
    },
    refreshOnConsent: true // by default, ads are reloaded after consent is given
  }
};
</script>
```

This configuration will tell the Didomi tag to automatically share consent with Google and resume ad loading as soon as possible by calling `window.googletag.pubads().refresh()` . If you are already doing manual ads refresh, you must remove them to avoid the ads from being refreshed multiple times.

{% hint style="info" %}
You can disable the reload of the ads after consent is given by setting `refreshOnConsent` to `false.` In that scenario, Didomi will not refresh ads after consent is collected but will refresh ads on subsequent page loads.
{% endhint %}

{% hint style="info" %}
`integrations.google` **is required**

It is used to tell the Didomi SDK to enable the integration with the Google tag. If you do not add that object, consent will be collected for Google but will not be shared with their tag.
{% endhint %}

### Display ads before collecting consent

According to [Google's documentation](https://support.google.com/dfp_premium/answer/7678538?hl=en) and to be compliant with the ePrivacy directive from 2002/2009, even when configured to serve non-personalized, their tags still use cookies for "frequency capping, aggregated ad reporting, and to combat fraud and abuse".

As a result, no ad request should be sent to Google (and no ad displayed) until the user has given consent for the cookies purpose. This is the default and recommended behavior. If you do not want to apply the ePrivacy directive, you can turn the `eprivacy` parameter to `false` and non-personalized ads will be served when there is no consent.

Example:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>',
    vendors: {
      iab: {
        include: [
          ..., // All the vendors that you have enabled as ad technology providers in your Google account
        ]
      },
      didomi: [
        // Ask Didomi to collect consent for Google
        'google'
      ]
    }
  },

  integrations: {
    vendors: {
      // Setup the integration with Google (ask Didomi to share consent with Google tags)
      google: {
        enable: true,
        eprivacy: false // Serve non-personalized ads to users before collecting consent
      }
    },
    refreshOnConsent: true // by default, ads are reloaded after consent is given
  }
};
</script>
```

### Single-page applications

The Didomi SDK has been tested with single-page applications (Angular and React) without any issue.

One important note regarding the Ad Manager integration for SPAs is that the Didomi SDK will only refresh ads once when the page/app is loaded in the browser. If you are using a custom routing logic and not actually loading new pages when the user is navigating, you must continue refreshing the Ad Manager ads yourself as you (most likely) already do.

In that case, you only want to refresh after Didomi has collected consent. You can do so by using the [getUserConsentStatusForVendor](https://developers.didomi.io/privacy-management/sdk-and-api/sdk/reference#getuserconsentstatusforvendor-vendor) function to check if Didomi already has consent or not.

Run the following snippet of code when the user navigates to another route:

```javascript
// Wrap your existing Ad Manager refresh logic on user navigation
if (Didomi) {
  const userStatus = Didomi.getCurrentUserStatus();

  if (
    userStatus.vendors.hasOwnProperty("google") &&
    userStatus.vendors["google"].enabled
  ) {
    // Didomi is loaded and has collected consent (either positive or negative)
    // Refresh Ad Manager ads
  }
}
```

### Google's additional consent mode (IAB TCF)

The Didomi SDK supports [Google's additional consent mode](https://support.google.com/admanager/answer/9681920).

It allows collecting consents for Google Ad vendors which are currently not part of the IAB TCF but are part of Google's Ad Tech Providers list (ATP).

By default, the Didomi SDK uses a predefined list of Google's Ad Tech Providers when generating positive and negative additional consent values.

If you would like to specify a custom positive or negative additional consent parameter, you can do so by specifying `additionalConsent.positive` and `additionalConsent.negative` fields in the `google` section of the Didomi's vendors configuration. Additionally, you must set the `fullATP` field to `false:`

```javascript
<script type="text/javascript">
  window.didomiConfig = {
    app: {
      vendors: {
        iab: {
          version: 2
        },
        didomi: ['google'],
        google: {
          fullATP: false
          additionalConsent: {
            positive: 'positive-additional-consent',
            negative: ''
          }
        }
      }
    }
  };
</script>
```

`app.vendors.google.additionalConsent.positive` is the exact AC string to pass to Google when the user has given consent to the vendor Google and all its required purposes based on consent.

`app.vendors.google.additionalConsent.negative` is the exact AC string to pass to Google when the user has denied consent to the vendor Google or any of its required purposes based on consent.

If the positive/negative additional consent strings are missing from the configuration, the Didomi SDK uses the predefined ATP list.

**Additional consent string** **format**

The additional consent string contains 3 parts:

* A **specification version** number, such as "1"
* A **separator symbol** "\~"
* A dot-separated **list of user-consented Google Ad Tech Providers**

For example, the additional consent string `1~7.11.12` means that the user has consented to ATPs with IDs `7`, `11`, and `12`, and the string is created using the format defined in the v1.0 specification.

You can find the latest Google's Ad Tech Providers (ATP) list [here](https://storage.googleapis.com/tcfac/additional-consent-providers.csv).

## Configure your Google account

Whether you are using Ad Manager or AdSense, your need to configure your account to allow personalized ads.

### Ad Manager account configuration

Sign into Google Ad Manager, go to **Admin** ![and then](https://lh3.googleusercontent.com/nHFGZ_9xjCh-mP83zMzXQVJF5VYf2n6kwoBIxB2zv3V4VPT4gNTtBye8lYznogLqLPY=w13-h18) **EU user consent** and ensure that your account is setup for serving personalized ads (see instructions from Google on <https://support.google.com/dfp_premium/answer/7673898>).

The Didomi CMP will take care of enabling personalized or non-personalized ads on a per-request basis but your account must be configured to allow serving personalized ads. Otherwise, only non-personalized ads will be served no matter what the consent status of the user is.

Also note that you must identify all the vendors used by Google for serving ads and add them to your Didomi tag configuration to make sure that consent is collected for everyone of them.

### AdSense account configuration

Sign into Google AdSense, go to **Allow & block ads** ![and then](https://lh3.googleusercontent.com/nHFGZ_9xjCh-mP83zMzXQVJF5VYf2n6kwoBIxB2zv3V4VPT4gNTtBye8lYznogLqLPY=w13-h18) **Content** ![and then](https://lh3.googleusercontent.com/nHFGZ_9xjCh-mP83zMzXQVJF5VYf2n6kwoBIxB2zv3V4VPT4gNTtBye8lYznogLqLPY=w13-h18) **All my sites** ![and then](https://lh3.googleusercontent.com/nHFGZ_9xjCh-mP83zMzXQVJF5VYf2n6kwoBIxB2zv3V4VPT4gNTtBye8lYznogLqLPY=w13-h18) **EU user consent** and ensure that your account is setup for serving personalized ads (see instructions from Google on <https://support.google.com/adsense/answer/7670013>).

The Didomi CMP will take care of enabling personalized or non-personalized ads on a per-request basis but your account must be configured to allow serving personalized ads. Otherwise, only non-personalized ads will be served no matter what the consent status of the user is.

Also note that you must identify all the vendors used by Google for serving ads and add them to your Didomi tag configuration to make sure that consent is collected for everyone of them.

## Configure Google tags

Google offers multiple SDKs and tags to load ads on your website. Each tag type has to be integrated slightly differently. The following instructions go through every tag type that we currently support.

You must ensure that ads do not get loaded before Didomi has shared the consent information with Google.

{% hint style="info" %}
**Fast loading of ads outside of the EU (if you are not an EU company)**

If the end user is not in the EU and you are not an EU-based company, Didomi will immediately resume loading ads as no consent is required.

If you want to optimize your ad delivery, you can decide not to delay the loading of ads when the user is outside of the EU and not rely on Didomi for that. If your company is based in the EU then you must apply GDPR to all visitors and cannot leverage this option.
{% endhint %}

### Ad Manager GPT tag

Update your existing Ad Manager GPT tag to [disable the initial loading of ads](https://developers.google.com/doubleclick-gpt/reference#googletag.PubAdsService_disableInitialLoad) and setup async rendering. Also remove any call to [`googletag.pubads().refresh()`](https://developers.google.com/doubleclick-gpt/reference#googletag.PubAdsService_refresh) in your code as the Didomi tag will now take care of refreshing ads when needed.

Example:

```javascript
googletag.cmd.push(function() {
    googletag.defineSlot(...);
    googletag.pubads().disableInitialLoad();
    googletag.pubads().enableAsyncRendering();
    googletag.pubads().enableSingleRequest();
    googletag.enableServices();
});
```

The Didomi tag will automatically call [`googletag.pubads().refresh()`](https://developers.google.com/doubleclick-gpt/reference#googletag.PubAdsService_refresh) when consent information becomes available to trigger the rendering of the ads.\
The SDK will only call that function after [`googletag.enableServices()`](https://developers.google.com/doubleclick-gpt/reference#googletag.enableServices) has been called so that there is no race condition if the SDK loads faster than Google's tag.

{% hint style="info" %}
If you have a complex Ad Manager setup or want to control the refreshing of the ads, you can disable the integration by removing the integrations.google part of your Didomi configuration. Keep `google` as a vendor to make sure consent is collected for Google.

You then need to make sure you are enabling personalized ads and refreshing ads with the Ad Manager API. See <https://support.google.com/adsense/answer/7670312> for more information.
{% endhint %}

### AdSense / Ad Exchange tag

Make sure that you use the async ad tag and disable the initial loading of ads before you embed Google's tag:

```javascript
(adsbygoogle = window.adsbygoogle || []).pauseAdRequests = 1;
```

The Didomi tag will automatically set `window.adsbygoogle.pauseAdRequest=0` to resume ad loading when consent information becomes available to trigger the rendering of the ads.

{% hint style="danger" %}
**The order of execution matters**

You must set `pauseAdRequests` to `1` before the tags from Google and Didomi get loaded. Because the Didomi SDK will set the value back to `0`, there could be a race condition where you would pause ad requests after the SDK enables them if the order is not right. If that happens, ads will sometimes not be displayed on a page even if you have consent.

One way to make sure it behaves as expected is to pause requests before the SDK configuration (`window.didomiConfig`) and before the Didomi and Google `<script>` tags are embedded in the page.
{% endhint %}

### Google Interactive Media Ads HTML5 SDK (for Video)

When using the Google IMA SDK, you must provide the consent status to your ad tag URL by setting the `npa` query-string parameter. A value of `0` will display personalized ads and requires consent while a value of `1` will display non-personalized ads and might not require consent.

Google does not offer an API for the Didomi SDK to push that information automatically (like with the GPT or AdSense tag) but you can pass that information from the Didomi SDK API:

```javascript
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) {
    // Determine if we should display non-personalized or personalized ads
    var nonPersonalizedAds = 1;

    const userStatus = Didomi.getCurrentUserStatus();
    if (
      !Didomi.isConsentRequired() ||
      (userStatus.vendors.hasOwnProperty("google") &&
        userStatus.vendors["google"].enabled)
    ) {
      // No consent required or consent has been given, enable personalized ads
      nonPersonalizedAds = 0;
    }

    // Build the ad tag URL to request personalized ads if possible
    var adTagUrl =
      "https://pubads.g.doubleclick.net/gampad/ads?" +
      "sz=640x480&iu=/124319096/external/single_ad_samples&ciu_szs=300x250&" +
      "impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&" +
      "cust_params=deployment%3Ddevsite%26sample_ct%3Dlinear&correlator=&npa=" +
      nonPersonalizedAds;

    // Initialize the IMA SDK and request ads as needed (your existing code)
    var adsRequest = new google.ima.AdsRequest();
    adsRequest.adTagUrl = adTagUrl;

    [...]
});
```

You can read more in the [Google IMA SDK documentation on consent](https://developers.google.com/interactive-media-ads/docs/sdks/html5/consent).

## Ad Manager macros

Didomi can pass the IAB consent string and the GDPR status to Ad Manager as [page-level custom targeting variables](https://support.google.com/admanager/answer/188092). These variables can be used in creative snippets with [pattern match macros](https://support.google.com/admanager/answer/2376981?hl=en) to pass the IAB consent string to creatives/vendors served through Ad Manager creatives.

### Configuration

#### Console

If you manage your consent notices through the Didomi Console, make sure to enable the "Pass IAB consent string and GDPR status as targeting variables to creatives" option for the Google Ad Manager integration.

#### Tag

If you manage the Didomi tags yourself, set the `integrations.vendors.google.passTargetingVariables` to `true` to configure the SDK to pass targeting variables to Ad Manager.

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>',
    vendors: {
      iab: {
        include: [
          ..., // All the vendors that you have enabled as ad technology providers in your Google account
        ]
      },
      didomi: [
        // Ask Didomi to collect consent for Google
        'google'
      ]
    }
  },

  integrations: {
    vendors: {
      // Setup the integration with Google (ask Didomi to share consent with Google tags)
      google: {
        enable: true,
        eprivacy: true,
        passTargetingVariables: true
      }
    },
  }
};
</script>
```

### Variables

The Didomi SDK pushes the following variables:

| Variable name      | Description                                                     | Macro                          |
| ------------------ | --------------------------------------------------------------- | ------------------------------ |
| `iabconsentstring` | Current IAB consent string of the user                          | `%%PATTERN:iabconsentstring%%` |
| `iabgdprapplies`   | Whether the GDPR applies to the current user (0 = No / 1 = Yes) | `%%PATTERN:iabgdprapplies%%`   |

### Macros in creatives

You can use [pattern match macros](https://support.google.com/admanager/answer/2376981?hl=en) to pass the IAB consent string and GDPR status to a creative.

**Example:**

The creative code

```
https://vendor.com/creative?gdpr_consentstring=%%PATTERN:iabconsentstring%%&gdpr_status=%%PATTERN:iabgdprapplies%%
```

will be rendered as the following code when the creative gets served

```
https://vendor.com/creative?gdpr_consentstring=SWFtYWNvbnNlbnRzdHJpbmc=gdpr_status=1
```


# Share consent without loading or refreshing ads

{% hint style="danger" %}
Our integration with Google Ad Manager which relies on passing an NPA parameter to ad requests is still available in the Didomi Console. But we do not advise using it.\
Please review our Google Ad Manager implementation recommendation [here](https://docs.didomi.io/integrations/google/configure-google-ad-manager-and-additional-consent-mode).\
\
This module does not support automatically passing CCPA Do Not Sell Status to Google products yet.\
See <https://support.google.com/adsense/answer/9598414> for more information.
{% endhint %}

Didomi supports sharing consent with Google Ad Manager, AdSense and Ad Exchange asynchronous ad tags. When the user gives consent, the Google tags are configured to fetch personalized ads.

With this integration, Didomi shares consent with Google Ad Manager/AdSense but does not load or refresh ads. This allows you to fully control the ad workflow on your pages and build more complex use cases like include Prebid auction results into your Ad Manager ad slots, for instance.

For this integration to work, you need to make sure that you are delaying the loading of Google ads until Didomi has shared the consent information with Google. You must also synchronize the ad calls to ensure that consent is passed before the ads are loaded on the page.

## Configure the Didomi tag

{% hint style="info" %}
If you are using the Didomi Console to manage your consent notices, you can manage the Google integration from there and can skip this tag configuration section.
{% endhint %}

You must ensure that the Didomi tag gets embedded first on your pages and configure it to communicate with the Google tag.

### Enable the Didomi / Google integration

Make sure that you add the following vendors to your tag (in the `app.vendors` property):

* `google`as a Didomi vendor (`app.vendors.didomi` property)
* All the "ad technology providers" enabled in your Google account (see the [Google Ad Manager documentation](https://support.google.com/dfp_premium/answer/7673898) or the [Google AdSense documentation](https://support.google.com/adsense/answer/7670013)). They can be added as IAB vendors (recommended if they are in the list), Didomi or custom vendors, and must appear in the list for the consent to be valid.

You also need to enable the specific integration with Google with the property `integrations`:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>',
    vendors: {
      iab: {
        include: [
          ..., // All the vendors that you have enabled as ad technology providers in your Google account
        ]
      },
      didomi: [
        // Ask Didomi to collect consent for Google
        'google'
      ]
    }
  },
  
  integrations: {
    vendors: {
      // Setup the integration with Google (ask Didomi to share consent with Google tags)
      google: {
        enable: true,
        refresh: false // Tell the SDK to never load/refresh ads and only share consent with Google
      }
    }
  }
};
</script>
```

This configuration will tell the Didomi tag to automatically share consent with Google and never load or refresh ads (ie the Didomi SDK will never call `window.googletag.pubads().refresh()` ).

{% hint style="info" %}
`integrations.google` **is required**

It is used to tell the Didomi SDK to enable the integration with the Google tag. If you do not add that object, consent will be collected for Google but will not be shared with their tag.
{% endhint %}

### Display ads before collecting consent

According to [Google's documentation](https://support.google.com/dfp_premium/answer/7678538?hl=en) and to be compliant with the ePrivacy directive from 2002/2009, even when configured to serve non-personalized, their tags still use cookies for "frequency capping, aggregated ad reporting, and to combat fraud and abuse".

As a result, no ad request should be sent to Google (and no ad displayed) until the user has given consent for the cookies purpose. This is the recommended behavior.\
\
The Didomi SDK will always share the consent status with Google and you are in charge of deciding when ads should actually be displayed.

### Google's additional consent mode (IAB TCF)

The Didomi SDK supports [Google's additional consent mode](https://support.google.com/admanager/answer/9681920).

It allows collecting consents for Google Ad vendors which are currently not part of the IAB TCF but are part of Google's Ad Tech Providers list (ATP).

**Additional consent string** **format**

The additional consent string contains 4 parts:

* A **specification version** number, such as "2"
* A **separator symbol** "\~"
* A dot-separated **list of user-consented Google Ad Tech Provider (ATP)** IDs. *Example: "`1.35.41.101`"*
* A separator symbol "`~`"
* "dv." followed by a dot-separated list of disclosed Google Ad Tech Provider (ATP) IDs. *Example: "`dv.9.21.81`"*

For example, the AC string `2~1.35.41.101~dv.9.21.81` means that the user has consented to ATPs with IDs `1`, `35`, `41` and `101`, ATPs with IDs `9`, `21`, and `81` have been disclosed to the user and the string is created using the format defined in the v2 specification.

You can find the latest Google's Ad Tech Providers (ATP) list [here](https://storage.googleapis.com/tcfac/additional-consent-providers.csv).

## Configure your Google account

Whether you are using Ad Manager or AdSense, your need to configure your account to allow personalized ads.

### Ad Manager account configuration

Sign into Google Ad Manager, go to **Admin** ![and then](https://lh3.googleusercontent.com/nHFGZ_9xjCh-mP83zMzXQVJF5VYf2n6kwoBIxB2zv3V4VPT4gNTtBye8lYznogLqLPY=w13-h18) **EU user consent** and ensure that your account is setup for serving personalized ads (see instructions from Google on <https://support.google.com/dfp_premium/answer/7673898>).

The Didomi CMP will take care of enabling personalized or non-personalized ads on a per-request basis but your account must be configured to allow serving personalized ads. Otherwise, only non-personalized ads will be served no matter what the consent status of the user is.

Also not that you must identify all the vendors used by Google for serving ads and add them to your Didomi tag configuration to make sure that consent is collected for everyone of them.

### AdSense account configuration

Sign into Google AdSense, go to **Allow & block ads** ![and then](https://lh3.googleusercontent.com/nHFGZ_9xjCh-mP83zMzXQVJF5VYf2n6kwoBIxB2zv3V4VPT4gNTtBye8lYznogLqLPY=w13-h18) **Content** ![and then](https://lh3.googleusercontent.com/nHFGZ_9xjCh-mP83zMzXQVJF5VYf2n6kwoBIxB2zv3V4VPT4gNTtBye8lYznogLqLPY=w13-h18) **All my sites** ![and then](https://lh3.googleusercontent.com/nHFGZ_9xjCh-mP83zMzXQVJF5VYf2n6kwoBIxB2zv3V4VPT4gNTtBye8lYznogLqLPY=w13-h18) **EU user consent** and ensure that your account is setup for serving personalized ads (see instructions from Google on <https://support.google.com/adsense/answer/7670013>).

The Didomi CMP will take care of enabling personalized or non-personalized ads on a per-request basis but your account must be configured to allow serving personalized ads. Otherwise, only non-personalized ads will be served no matter what the consent status of the user is.

Also not that you must identify all the vendors used by Google for serving ads and add them to your Didomi tag configuration to make sure that consent is collected for everyone of them.

## Configure Google tags for loading and refreshing ads

The Didomi SDK will automatically share the user consent status with Google and you must ensure that ads do not get loaded before Didomi has done so.

The SDK exposes the event `integrations.consentpassedtodfp` to be notified when the user consent status has been shared with Google. Once that is done, you can resume your ad operations and load or refresh your ads as needed:

```javascript
/**
 * Add an event listener to get notified once Didomi has passed
 * the user consent status to Google
 * Important: this must be placed before the Didomi SDK gets embedded on your
 * website to guarantee that you do not miss any event
 */
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'integrations.consentpassedtodfp',
  listener: function (data) {
    // Consent has been passed to Google
    // Load or refresh ads as needed with Ad Manager, Prebid, etc.
    // `data.consentStatus` contains the current consent status of the user (true/false/undefined)
    // `data.index` contains the index of the event (integer)
    if (data.index === 0) {
      // This is the very first event on the page that gets triggered on page load
    } else {
      // This is an event that happens later on the page, after a user action (user giving consent or changing their preferences)
    }
  }
});
```

The `integrations.consentpassedtodfp` event is triggered every time the user consent status changes and can be called multiple times on a single page. For instance, the very first time a user visits your website, this event will be called twice on the page: once with an `undefined` consent status (and index 0) and a second time, after the user has given consent, with a `true` consent status (and index 1).

The `data` object provided to your listener contains the current user consent status for Google as well as the index of the event so that you can decide to only react to some consent statuses.\
The index is the number of the event on the page. There is always a first event that gets triggered with index 0 on page load. More events can be triggered if the user changes their consent preferences on the page and the index gets incremented by 1 for every event triggered.

The cases that commonly need to be taken into account when deciding to load or refresh ads are the following:

| Consent status   | Index | Case                                                                                                                             |
| ---------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------- |
| `true` / `false` | 0     | User visits a page and has already made a consent choice on a previous page so that the consent status is immediately available. |
| `undefined`      | 0     | User visits your website for the first time and has not made a consent choice yet.                                               |
| `true` / `false` | >0    | User is on the page and has made a new consent choice.                                                                           |

{% hint style="info" %}
**Fast loading of ads outside of the EU (if you are not an EU company)**

If you want to optimize your ad delivery, you can decide not to delay the loading of ads when the user is outside of the EU and not rely on Didomi for that. If your company is based in the EU then you must apply GDPR to all visitors and cannot leverage this option.
{% endhint %}

## Ad Manager macros

Didomi can pass the IAB consent string and the GDPR status to Ad Manager as [page-level custom targeting variables](https://support.google.com/admanager/answer/188092). These variables can be used in creative snippets with [pattern match macros](https://support.google.com/admanager/answer/2376981?hl=en) to pass the IAB consent string to creatives/vendors served through Ad Manager creatives.

### Configuration

#### Console

If you manage your consent notices through the Didomi Console, make sure to enable the "Pass IAB consent string and GDPR status as targeting variables to creatives" option for the Google Ad Manager integration.

#### Tag

If you manage the Didomi tags yourself, set the `integrations.vendors.google.passTargetingVariables` to `true` to configure the SDK to pass targeting variables to Ad Manager.

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>',
    vendors: {
      iab: {
        include: [
          ..., // All the vendors that you have enabled as ad technology providers in your Google account
        ]
      },
      didomi: [
        // Ask Didomi to collect consent for Google
        'google'
      ]
    }
  },
  
  integrations: {
    vendors: {
      // Setup the integration with Google (ask Didomi to share consent with Google tags)
      google: {
        enable: true,
        eprivacy: true,
        passTargetingVariables: true
      }
    },
  }
};
</script>
```

### Variables

The Didomi SDK pushes the following variables:

| Variable name      | Description                                                     | Macro                          |
| ------------------ | --------------------------------------------------------------- | ------------------------------ |
| `iabconsentstring` | Current IAB consent string of the user                          | `%%PATTERN:iabconsentstring%%` |
| `iabgdprapplies`   | Whether the GDPR applies to the current user (0 = No / 1 = Yes) | `%%PATTERN:iabgdprapplies%%`   |

### Macros in creatives

You can use [pattern match macros](https://support.google.com/admanager/answer/2376981?hl=en) to pass the IAB consent string and GDPR status to a creative.

**Example:**

The creative code

```
https://vendor.com/creative?gdpr_consentstring=%%PATTERN:iabconsentstring%%&gdpr_status=%%PATTERN:iabgdprapplies%%
```

will be rendered as the following code when the creative gets served

```
https://vendor.com/creative?gdpr_consentstring=SWFtYWNvbnNlbnRzdHJpbmc=gdpr_status=1
```

###


# US states laws

For US states laws, we recommend enabling [restricted data processing in ad requests](https://support.google.com/admanager/answer/9598414) to Google Ad Manager / AdSense when a user has opted out of personal data processing (selling, sharing, etc.).

This can be implemented by adding code on your website with the following logic:

* [Disable initial ad loading](https://developers.google.com/publisher-tag/reference#googletag.PubAdsService_disableInitialLoad) on the page until [Didomi is ready](https://developers.didomi.io/cmp/web-sdk/reference/api#didomi-ready).
* Check if the regulation that applies is a US regulation and if the user has opted out via the Didomi API. [Enable restricted data processing](https://support.google.com/admanager/answer/9598414) in that case.
* [Load ads on the page](https://developers.google.com/publisher-tag/reference#googletag.PubAdsService_refresh).

### Code sample

{% hint style="danger" %}
The following code disables GPT automatic ad loading on page load and refreshes ads after Didomi is ready on the page.

This will interact with your existing GPT ad code and must be thoroughly tested on your website to confirm that the ads behave as expected in all regulations.
{% endhint %}

```javascript
window.googletag = window.googletag || { cmd: [] };

googletag.cmd.push(() => {
    // Disable initial load.
    // This prevents GPT from automatically fetching ads when display is called until Didomi is ready on the page
    googletag.pubads().disableInitialLoad();
    googletag.enableServices();
});

window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) {
    const userStatus = window.Didomi.getCurrentUserStatus();

    if (
        userStatus.regulation == 'cpra'
        || userStatus.regulation == 'cpa'
        || userStatus.regulation == 'ucpa'
        || userStatus.regulation == 'ctdpa'
        || userStatus.regulation == 'vcdpa'
    ) {
        if (
            !!Object
                .values(userStatus.purposes)
                .find(purpose => purpose.enabled === false)
        ) {
            googletag.cmd.push(() => {
                // Enable restricted data processing
                googletag.pubads().setPrivacySettings({
                    'restrictDataProcessing': true
                });
            });
        }
    }

    // Refresh ads
    googletag.cmd.push(() => {
        googletag.pubads().refresh();
    });
});
```


# Google Consent Mode V2

{% hint style="warning" %}
Google Consent Mode is only supported by the GDPR regulation.
{% endhint %}

Please refer to our [Help Center Documentation](https://docs.didomi.io/consent-management-platform-cmp/frameworks-regulations/google-consent-mode-v2) for Google Consent Mode.


# Kameleoon

Kameleoon is an A/B test and web personalization tool. Although the vendor is part of the IAB's Transparency and Consent Framework, they also allow you to use their features without the TCF.

### Configure your Didomi notice

In Didomi, you will need to create two Kameleoon vendors and two associated purposes. This will allow Kameloon to get the user consent value directly from the CMP.

#### Create your purposes

To do so, browse to your Didomi console and go to **Settings > Purposes** to create the following purposes:

* AB testing
* Personalization

![Purpose creation in the console](/files/-MRyQSdn72GDiUIvQhmZ)

#### Create your vendors

You will also have to create two Kameleoon vendors by going to **Settings > Vendors**. The name and custom ID of these vendors will be :

* Kameleoon experiment (SDK ID: c:kameleoon-experiment)
* Kameleoon personalization (SDK ID: c:kameleoon-personalization)

The custom SDK ID is important as Kameleoon will use these two values to get the user consent from Didomi.

![Vendor creation with Custom SDK ID](/files/-MRz7EbNgQYp78Gv0DRw)

#### **Configure your notice**

Once these vendors are created you can browse to your notice configuration and go to the **Vendors & Purposes** section.

Select the two vendors you previously created and make sure the SDK ID matches the Kameleeon vendors you created in the previous step.

![](/files/-MRzBa8oFMfqWGaa06D0)

### Configure your website

Your notice is now ready to be used with Kameleoon. Get the embed code in the "3. Publish" section of the notice configuration and place it on the top of your \<head> tag.

Thanks to the custom vendor ID you set when you created your vendors, Kameleoon will be able to get the user consent directly from the notice.

### Configure a test

If you need to configure a test notice, you will have to browse through the documentation to create a `window.didomiConfig` which will change the banner format.


# Piano Analytics (AT Internet)

Piano Analytics (AT Internet) is an analytics solution authorized by the French Data Protection Authority (CNIL) to provide analytics services without user consent. Piano Analytics supports three modes:

* Essential (CNIL exemption)
* Opt-in (Full analytics tracking)
* Opt-out (Complete deactivation)

Didomi will support the essential and the opt-in mode while the opt-out mode will have to be added on one of your websites pages.

{% hint style="danger" %}
Other Data Protection Authorities in Europe may not allow analytics with Piano Analytics if consent is not given by the user.
{% endhint %}

This guide will help you activate the Piano Analytics hybrid measure to use the CNIL essential mode.

The Piano Analytics prerequisites for the use of this feature are:

* The use of their [piano analytics tag](https://developers.atinternet-solutions.com/piano-analytics/data-collection/sdks/javascript)
* Activating and configuring a [default consent mode](https://developers.atinternet-solutions.com/piano-analytics/data-collection/how-to-send-events/consent#configure-the-default-consent-mode)

## Configure Didomi

If you are using the Piano Analytics essential mode, you will have to add some information to the text displayed in the preference view and add the Piano Analytics vendor in your notice.

### Change the Preferences - Purposes text

{% hint style="danger" %}
When using the Piano Analytics hybrid measure feature, you will also have to add a link redirecting to one of your website pages. This page will have to allow your users to completely disable Piano Analytics (opt-out mode).
{% endhint %}

In the console browse to the **Consent Notices** section and select the notice related to the use of Piano Analytics.

Select the **Content editor** section of your notice in **Customization** and go to the **Purposes** specific subsection to change the content of the text displayed at the top of the Preferences view.

Add the following mention to the existing text in French:

> Nous utilisons également des traceurs exemptés du recueil de consentement pour le dépôt des cookies de mesure d'audience. Vous pouvez utiliser une fonction d'opt-out via notre `<a href="<https://www.example.com/opt-out-link">politique de confidentialité</a>`.

You can change it to fit your needs if you want to. Also, don't forget to change the link `https://www.example.com/opt-out-link` to the one you want to use. If the link is the same as the one you are using for your Privacy Policy, you can use the `{privacyPolicyURL}` macro.

![Exemple of Preferences - Purposes text](/files/yFnbHWUzmaXn6jMXjPXF)

### Select the vendor in the consent notice

Then, select the **Vendors & Purposes** section in **Regulations** to add the **Piano (Hybrid Analytics)** vendor with the ID `pianohybr-R3VKC2r4`.

![](/files/NniJAHscF2NOfk7o06uS)

Click on the **Save & Publish** button on the top left of the page.

## Enable the correct Piano Analytics mode on your website

### 1. Opt-in or essential mode

Once everything is configured in the Didomi console, you have to add the following code to your website along with the Didomi embed code:

```javascript
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) {
  // Check the consent status for the Piano Analytics vendor
  const userStatus = Didomi.getCurrentUserStatus();
  const defaultStatus =
    userStatus.vendors.hasOwnProperty("pianohybr-R3VKC2r4") &&
    userStatus.vendors["pianohybr-R3VKC2r4"].enabled;

  if (defaultStatus) {
    // If the consent status is true, activate the opt-in visitor mode
    pa.consent.setByPurpose("AM", "opt-in");
  } else {
    // Else, if the visitor mode is not "opt-out", then activate the essential mode
    if (
      pa.consent.getByPurpose().AM.mode == null ||
      pa.consent.getByPurpose().AM.mode !== "opt-out"
    ) {
      pa.consent.setByPurpose("AM", "essential");
    }
  }
});
```

### 2. Opt-out mode

Piano Analytics also suggests that you add a way for the user to completely deactivate the audience measurement.

Using Didomi and Piano Analytics, you will have to adapt your code to disable the vendor and the purpose along with the audience measurement feature. To do so, you will have to use `openCurrentUserStatusTransaction()`.

Below is an example using a button with an ID `#optout-piano`.

```javascript
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) {
  const button = document.getElementById("optout-piano");
  // Add event handler
  button.addEventListener("click", function () {
    // Open Didomi Transaction
    const transaction = Didomi.openCurrentUserStatusTransaction();
    // Disable a purpose
    transaction.disablePurpose("audiencem-hJxaeGrR");
    // Disable a vendor
    transaction.disableVendor("pianohybr-R3VKC2r4");
    // Save user choices
    transaction.commit();

    pa.consent.setByPurpose("AM", "opt-out");
  });
});
```

`pa.consent.setByPurpose` is the method exposed by Piano Analytics to set their consent mode by purpose. Their documentation is available [here](https://developers.atinternet-solutions.com/piano-analytics/data-collection/how-to-send-events/consent#set-consent-mode-by-purpose).

### Deploy the opt-out button

If you want to use the button mentioned above, you will be able to deploy this by using the following text and code.

> *« Les cookies Piano Analytics (AT Internet) sont exemptés de la nécessité d'obtenir le consentement, comme indiqué dans l’Arrêt CNIL n°2020-091, dans la mesure où ils sont strictement nécessaires au bon fonctionnement du site. Vous pouvez refuser le traitement de vos données personnelles de navigation en activant cette option. Veuillez noter qu’en cliquant sur le bouton suivant, nous ne pourrons plus mesurer et améliorer nos sites de manière optimale. »*

```html
<button id="optout-piano">Opt Out</button>
```

The link between Didomi and Piano Analytics is now done.


# Prebid

Prebid can be integrated with Didomi to configure ad requests based on the user status:

* [GDPR via IAB TCF](/cmp/web-sdk/third-parties/direct-integrations/prebid/prebid)
* [US states laws](/cmp/web-sdk/third-parties/direct-integrations/prebid/us-states-laws)


# GDPR via IAB TCF

[Prebid](https://prebid.org) is able to use the consent information collected by IAB TCF-compliant CMPs through the standard IAB TCF API. The consent information is then passed down to the bidders/vendors that support those APIs.

To enable Prebid support for CMPs and have it work with Didomi, follow the steps listed on this page.

## Add the consent management module to Prebid

Make sure that the `consentManagement` module is being added to your Prebid build: \\

<https://docs.prebid.org/dev-docs/modules/consentManagementTcf.html#page-integration>

## Configure Prebid

Configure your Prebid deployment to enable consent management with an `iab` CMP by adding a `consentManagement.gdpr` configuration option:

```javascript
var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];
pbjs.que.push(function() {
  pbjs.setConfig({
    consentManagement: {
      gdpr: {
        cmpApi: 'iab',
        timeout: 8000,
        allowAuctionWithoutConsent: false
      }
    }
  });

  pbjs.addAdUnits(adUnits);
});
```

The complete documentation from Prebid is available here:\
<https://docs.prebid.org/dev-docs/modules/consentManagementTcf.html>

#### Enable IAB TCF vendors

If you do not collect consent for all IAB vendors, make sure to enable the IAB vendor IDs corresponding to all the bidders/adapters that you are working with in Prebid.


# US states laws

For US states laws, we recommend disabling Prebid when a user has opted out of personal data processing (selling, sharing, etc.).

This can be implemented by adding code on your website to only request bids when the user has not opted out.

### Code sample

```javascript
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) {
    const userStatus = window.Didomi.getCurrentUserStatus();

    if (
        userStatus.regulation == 'cpra'
        || userStatus.regulation == 'cpa'
        || userStatus.regulation == 'ucpa'
        || userStatus.regulation == 'ctdpa'
        || userStatus.regulation == 'vcdpa'
    ) {
        if (
            !!Object
                .values(userStatus.purposes)
                .find(purpose => purpose.enabled === false)
        ) {
            // User has opted out, do not load prebid ads
            // Load non-prebid ads via GAM or another ad server
        } else {
            // User has not opted out, load prebid ads and your usual ad logic without restriction
        }
    }
});
```


# Salesforce DMP (Krux)

The Didomi CMP can automatically share the consent status of the user with the Salesforce DMP (Krux) tag. When the integration is enabled, the SDK will call `Krux('consent:set', { ...consent information })` as needed.

See the following articles from the Salesforce DMP documentation for more information on what the SDK does:

* <https://konsole.zendesk.com/hc/en-us/articles/360000754674-JavaScript-Consent-Tag-Spec>
* <https://konsole.zendesk.com/hc/en-us/articles/360000486853>
* <https://konsole.zendesk.com/hc/en-us/articles/360001614194-DMP-Implementation-Best-Practices-for-GDPR>

To enable the integration, you must add the `salesforce` vendor to your tag configuration and also add a dedicated section for the integration:

```javascript
window.didomiConfig = {
    app: {
      vendors: {
        didomi: [
          'salesforce',
        ],
      }
    },

    integrations: {
      vendors: {
        'salesforce-dmp': {
          enable: true,
          namespace: 'namespace', // Optional ; set to null if you do not use a namespace
        },
      },
    },
};
```

The `namespace` property is optional and allows you to specify what namespace you are using in the Salesforce DMP.


# Simple Analytics

Simple Analytics is a privacy-first analytics platform that avoids storing personally identifiable information (PII), making it ideal for organizations that need simple, compliant analytics without cookies.

This document explains how to integrate Didomi with Simple Analytics to send user consent status as events.

To illustrate the possibilities with Simple Analytics, we will present two use cases (you may include one, the other, or both):

1. **Opt-in and Opt-out**: The user either accepts at least one vendor or denies all vendors (with none enabled).
2. **Selective Opt-in or Opt-out**: The user grants or denies consent to a specific vendor (e.g., Google).

### How the integration works

To integrate Didomi with Simple Analytics, you must ensure that:

* The Simple Analytics script tag is set before the Didomi SDK.
* The Didomi SDK is ready when sending the first "before" consent status to Simple Analytics.
* Consent updates are sent to Simple Analytics using the Didomi `consent.changed` event.

To achieve the first two items, we use a condition to verify whether user consent should be collected. When that condition is met, a “before” event is sent to the Simple Analytics dashboard. This helps you monitor users who see the consent notice before making a choice.

Then, to assess each consent decision and send it to Simple Analytics, we use the `consent.changed` event. This event allows us to send a dedicated `consent_update` event to Simple Analytics whenever the user's choices change.

{% hint style="info" %}
You can also use the consent values metadata in multiple ways in Simple Analytics, such as in *Goals* or the *Events explorer*. To explore the possibilities further, please refer directly to the associated [Simple Analytics metadata documentation](https://docs.simpleanalytics.com/metadata).
{% endhint %}

### Scenarios

{% hint style="warning" %}
Since you are relying on `didomiEventListeners`, please paste the following script **before** the Didomi embed code on your site.
{% endhint %}

#### Prerequisites (required for both use cases)

* A [Simple Analytics](https://simpleanalytics.com/) account.
* The Didomi Web SDK is properly integrated into the page (see the [getting started guide](https://developers.didomi.io/cmp/web-sdk/getting-started)).

#### Use case 1: Opt-ins and Opt-outs

***When to Use***

Use this when you need to collect Simple Analytics metadata on:

* **Opt-ins**: At least one vendor enabled.
* **Opt-outs**: At least one vendor disabled and no vendor enabled.
* **Mixed**: At least one vendor enabled and at least one vendor disabled.

***Implementation code***

```html
<script>
  window.didomiEventListeners = window.didomiEventListeners || [];
  window.didomiEventListeners.push({
    event: "consent.changed",
    listener: () => {
      const userStatus = Didomi.getCurrentUserStatus();
      const vendors = userStatus.vendors || {};

      const enabledVendors = Object.values(vendors).filter((v) => v.enabled === true);
      const disabledVendors = Object.values(vendors).filter((v) => v.enabled === false);

      const hasEnabledVendors = enabledVendors.length > 0;
      const hasDisabledVendors = disabledVendors.length > 0;

      // We will use below the same calculation methods defined in our SDK and detailed here: https://support.didomi.io/cmp-notice-metrics-indicators

      // ✅ Opt-in: At least one vendor enabled
      const isOptIn = hasEnabledVendors;

      // ❌ Opt-out: At least one vendor disabled AND none enabled
      const isOptOut = hasDisabledVendors && !hasEnabledVendors;

      // ⚠️ Mixed: At least one vendor enabled AND at least one vendor disabled
      const isMixed = hasEnabledVendors && hasDisabledVendors;

      if (isMixed) {
        consentStatus = "mixed";
      } else if (isOptIn) {
        consentStatus = "approved";
      } else if (isOptOut) {
        consentStatus = "denied";
      }

      if (!window.sa_loaded) {
        // If the Simple Analytics script is not loaded, no action is taken.
        console.warn("Simple Analytics script is not loaded.");
        return;
      }

      if (window.sa_event) {
        sa_event("consent_update", { consent_status: consentStatus }); // We change the event name to `consent_update`
      }
    },
  });

  window.didomiOnReady = window.didomiOnReady || [];
  window.didomiOnReady.push(function (Didomi) {
    let consentStatus = "before";

    /**
     * This function allows detecting the number of times consent should be collected, to compare with the actual consent given
     * It will only return "before" if consent collection is still required for this user.
     *
     * ⚠️ Note: If this causes "before" to be sent too frequently (e.g., due to new vendors being added),
     * you can alternatively use: `Didomi?.notice?.isVisible?.()` to gate it based on the banner actually being shown.
     */
    if (!window.sa_loaded) {
      // If the Simple Analytics script is not loaded, no action is taken.
      console.warn("Simple Analytics script is not loaded.");
      return;
    }

    if (window.sa_event && Didomi?.shouldUserStatusBeCollected?.()) {
      sa_event("consent_init", { consent_status: consentStatus }); // We first define the event name to `consent_init`
    }
  });
</script>

// You must declare this tag before the Didomi SDK, otherwise you won't be able to collect "before" events
<script type="text/javascript" data-collect-dnt="true" async src="https://scripts.simpleanalyticscdn.com/latest.js"></script>
```

{% hint style="info" %}
We have used `consent_init` and `consent_update` as event names in the example above, but you can, of course, choose any other names that make more sense to you.
{% endhint %}

#### Use case 2: Selective Opt-in/Opt-out (only Google is enabled or disabled)

***When to Use***

Use this if you need to track consent for a specific vendor, such as Google, whether it is enabled or disabled.

***Implementation code***

```html
<script>
  window.didomiEventListeners = window.didomiEventListeners || [];
  window.didomiEventListeners.push({
    event: "consent.changed",
    listener: () => {
      const userStatus = Didomi.getCurrentUserStatus();
      const vendorId = "google";

      // ✅ Check if Google is enabled
      const hasConsent = userStatus.vendors && userStatus.vendors.hasOwnProperty(vendorId) && userStatus.vendors[vendorId].enabled;

      consentStatus = hasConsent ? "approved" : "denied";

      if (!window.sa_loaded) {
        // If the Simple Analytics script is not loaded, no action is taken.
        console.warn("Simple Analytics script is not loaded.");
        return;
      }

      if (window.sa_event) {
        sa_event("consent_update", { consent_status: consentStatus }); // We change the event name to `consent_update`
      }
    },
  });

  window.didomiOnReady = window.didomiOnReady || [];
  window.didomiOnReady.push(function (Didomi) {
    let consentStatus = "before";

    /**
     * This function allows detecting the number of times consent should be collected, to compare with the actual consent given
     * It will only return "before" if consent collection is still required for this user.
     *
     * ⚠️ Note: If this causes "before" to be sent too frequently (e.g., due to new vendors being added),
     * you can alternatively use: `Didomi?.notice?.isVisible?.()` to gate it based on the banner actually being shown.
     */
    if (!window.sa_loaded) {
      // If the Simple Analytics script is not loaded, no action is taken.
      console.warn("Simple Analytics script is not loaded.");
      return;
    }

    if (window.sa_event && Didomi?.shouldUserStatusBeCollected?.()) {
      sa_event("consent_init", { consent_status: consentStatus }); // We first define the event name to `consent_init`
    }
  });
</script>

// You must declare this tag before the Didomi SDK, otherwise you won't be able to collect "before" events
<script type="text/javascript" data-collect-dnt="true" async src="https://scripts.simpleanalyticscdn.com/latest.js"></script>
```

### Additional notes

You can extend this guide with additional vendor-specific or purpose-based events using the same structure.

Example use cases:

* Consent tracking per purpose (e.g., marketing)
* Custom event segmentation based on combined vendor states

### Resources

* [Simple Analytics Docs](https://docs.simpleanalytics.com/)


# IAB frameworks

### Transparency and Consent Framework

Didomi is a registered CMP (ID 7) with the IAB Europe. We fully support the CMP API and your vendors will automatically use the `__tcfapi` function that we expose to collect user consent.

For this integration to behave properly, make sure that you include the IAB CMP stub at the top of your page:

```javascript
(function(){function r(e){if(!window.frames[e]){if(document.body&&document.body.firstChild){var t=document.body;var n=document.createElement("iframe");n.style.display="none";n.name=e;n.title=e;t.insertBefore(n,t.firstChild)}else{setTimeout(function(){r(e)},5)}}}function e(n,o,a,c,d){function e(e,t,n,r){if(typeof n!=="function"){return}if(!window[o]){window[o]=[]}var i=false;if(d){i=d(e,r,n)}if(!i){window[o].push({command:e,version:t,callback:n,parameter:r})}}e.stub=true;e.stubVersion=2;function t(r){if(!window[n]||window[n].stub!==true){return}if(!r.data){return}var i=typeof r.data==="string";var e;try{e=i?JSON.parse(r.data):r.data}catch(t){return}if(e[a]){var o=e[a];window[n](o.command,o.version,function(e,t){var n={};n[c]={returnValue:e,success:t,callId:o.callId};if(r.source){r.source.postMessage(i?JSON.stringify(n):n,"*")}},o.parameter)}}if(typeof window[n]!=="function"){window[n]=e;if(window.addEventListener){window.addEventListener("message",t,false)}else{window.attachEvent("onmessage",t)}}}e("__tcfapi","__tcfapiBuffer","__tcfapiCall","__tcfapiReturn");r("__tcfapiLocator");(function(e){var t=document.createElement("link");t.rel="preconnect";t.as="script";var n=document.createElement("link");n.rel="dns-prefetch";n.as="script";var r=document.createElement("script");r.id="spcloader";r.type="text/javascript";r["async"]=true;r.charset="utf-8";var i="{{SDK-URL}}"+e+"/loader.js?target="+document.location.hostname;if(window.didomiConfig&&window.didomiConfig.user){var o=window.didomiConfig.user;var a=o.country;var c=o.region;if(a){i=i+"&country="+a;if(c){i=i+"&region="+c}}}t.href="{{SDK-URL}}";n.href="{{SDK-URL}}";r.src=i;var d=document.getElementsByTagName("script")[0];d.parentNode.insertBefore(t,d);d.parentNode.insertBefore(n,d);d.parentNode.insertBefore(r,d)})("{{Your-API-Key}}")})();
```

{% hint style="info" %}
This stub is automatically added to your Embed code available in the [Didomi Console](https://console.didomi.io/).
{% endhint %}

For the stub to behave properly, it should be added at the top of the `<head>` section, before any other script. Improperly placing the stub on your pages will reduce the effective consent rate seen by your IAB vendors and can impact your ad revenue negatively.

​[Read more in the IAB documentation](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#how-does-the-cmp-provide-the-api)

### Global Privacy Platform (GPP)

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://docs.didomi.io/consent-management-platform-cmp/frameworks-regulations/iab-global-privacy-protocol-gpp).

By decoding the GPP string, you will have access to detailed information about user preferences across regulations, including:

* Applicable strings (e.g. TCF, USCA, USNAT, etc.)
* User's preferences related to the applicable data processing per regulation.

Similar to the TCF framework, ensure that the [GPP stub](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Core/CMP%20API%20Specification.md#using-the-cmp-api) is included at the top of your webpage. This stub is automatically added to your Embed code available in the [Didomi Console](https://console.didomi.io/).

#### Fetching GPP string

* Using IAB's [\_\_gpp function](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Core/CMP%20API%20Specification.md).
* You can also retrieve the GPP string directly through the Didomi SDK using the following method:

```javascript
Didomi.getCurrentUserStatus().gpp_string
```

Here is an example of GPP string: `DBABBg~BqoIAAKU.QA`

#### Decoding GPP string

Decode and interpret the GPP string using the [IAB GPP Decoder](https://iabgpp.com/#DBABBg~BqoIAAKU.QA).\
![](/files/wMOPhfsyH8eYnSLk7rlA)


# Programmatic API

If you need more control over when and how tags are loaded, the Didomi SDK exposes a function to get an observable on the consent status for a given vendor. This allows you to listen to changes to the consent status and react to them to decide when to enable a vendor.

Here are a few use cases and how to implement them with the [getObservableOnUserConsentStatusForVendor](/cmp/web-sdk/reference#getobservableonuserconsentstatusforvendor-vendorid) function. You can find more examples and documentation on the function in the [Reference](/cmp/web-sdk/reference#getobservableonuserconsentstatusforvendor-vendorid).

## Enable a vendor when the user has allowed it

With this structure, your function gets called exactly once and only when the user has given consent to the vendor specifically. It could be immediately if the user has already given consent or later on after the user gives consent.

```javascript
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) {
    if (Didomi.isConsentRequired()) {
        // Consent is required: your visitor is from the EU or you are an EU company
        // Only enable the vendor when consent is given
        Didomi.getObservableOnUserConsentStatusForVendor('vendor-id')
            .filter(function(status) { return status === true; }) // Filter out updates where status is not true
            .first() // Only get the first consent status update
            .subscribe(function (consentStatusForVendor) {
                // The user has given consent to the vendor
                // Enable it
            });
    } else {
        // Consent is not required, enable your vendor immediately
    }
});
```

{% hint style="info" %}
If your tag is configured to only collect consent for visitors from the EU, you can enable all your tags for other visitors without waiting for the consent. Use the [isConsentRequired()](/cmp/web-sdk/reference#isconsentrequired) function to check if consent is required or not for the current visitor on the page.
{% endhint %}

## Get notified when the consent status for a vendor changes

With this structure, your function gets called every single time the consent status for the vendor changes. If the user has not given consent information yet, your function is called immediately with `undefined` as the consent status. If the consent status of the user changes multiple times on the page, the function will be called multiple times.

```javascript
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) { 
    if (Didomi.isConsentRequired()) {
        // Consent is required: your visitor is from the EU or you are an EU company
        // Only enable the vendor when consent is given
        Didomi.getObservableOnUserConsentStatusForVendor('vendor-id')
            .subscribe(function (consentStatusForVendor) {
                // The consent status for the vendor has changed
                if (consentStatusForVendor === true) {
                    // The vendor has consent
                } else if (consentStatusForVendor === false) {
                    // The vendor does not have consent
                } else if (consentStatusForVendor === undefined) {
                    // The consent status for the vendor is unknown
                }
            });
    } else {
        // Consent is not required, enable your vendor immediately
    }
});
```

{% hint style="info" %}
If your tag is configured to only collect consent for visitors from the EU, you can enable all your tags for other visitors without waiting for the consent. Use the [isConsentRequired()](/cmp/web-sdk/reference#isconsentrequired) function to check if consent is required or not for the current visitor on the page.
{% endhint %}


# Configuration

{% hint style="danger" %}
This section describes how to configure the Didomi consent notice through its programmatic API and the `window.didomiConfig` object.

Most configuration options are available through the [Didomi Console](https://console.didomi.io/) and this documentation only applies to edge cases or custom implementations that require it.
{% endhint %}

The notice is required by the EU legislation on cookies and other tracking technologies and is also used for informing the user on other GDPR data processing and collecting consent. Before collecting data or processing it, you must let your users know that your website is using such tools and why, as well as give them options to opt out.

**Topics**

* [Customize the notice](/cmp/web-sdk/consent-notice/notice)
* [Customize the preferences popup](/cmp/web-sdk/consent-notice/preferences)
* [Customize the theme](/cmp/web-sdk/consent-notice/customize-theme)


# Bots (SEO & Performance tools)

In most cases, bots that visit your website for indexing (such as Google, Bing, etc.) or performance evaluation (like Google PageSpeed Insights, GTmetrix, etc.) do **not** need to see the consent collection UI. In fact, displaying a consent notice to bots can negatively impact your SEO ranking or performance score, as bots cannot interact with consent banners and might index them as part of your site content.

The **Didomi Web SDK** includes built-in options to control how it behaves when a bot visits your website. You can configure it to **bypass consent collection entirely** and act “as if” consent had been given — for example, by loading all third-party vendors. This is recommended since bots are not human visitors and do not provide consent.

#### Default behavior: robots.txt blocks all bots

By default, Didomi serves a `robots.txt` file on **sdk.privacy-center.org** that completely prevents bots from crawling or loading any SDK files:

```
User-agent: *
Disallow: /
```

This configuration tells all compliant crawlers (for example: Googlebot, Bingbot, DuckDuckBot, YandexBot, Baiduspider, Twitterbot, LinkedInBot, Slackbot, FacebookExternalHit, AhrefsBot, SemrushBot, MJ12bot, DotBot, CensysInspect, PetalBot, Archive.org\_bot, CommonCrawlBot) **not to crawl or load any resources from the SDK domain**.

As a result, **the Didomi SDK is not loaded at all for bots that respect this file**.

The configuration described below only applies to **non-compliant or synthetic clients**, such as **headless browsers (Puppeteer, Playwright)** or **monitoring tools** that do not follow `robots.txt`.

#### Allowing bots to load the SDK under a custom domain

If you want the configuration below to apply to **all bots**, including compliant ones, you can set up a **custom domain** for serving the Didomi SDK and configure that domain to allow bots in its own `robots.txt`.\
This can be done through the **Didomi Console** or via our **API**.

## Bypass consent collection for bots

To indicate that consent should not be collected for bots, set the `user.bots.consentRequired` property to `false` in your SDK configuration:

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

```javascript
<script type="text/javascript">
window.didomiConfig = {
  user: {
    bots: {
      /**
       * Indicate whether consent is required for bots.
       * Defaults to false when configuring the consent notice from
       * the Didomi console. Defaults to true otherwise.
       */
      consentRequired: false,
      
      /**
       * Predefined types of bots to identify
       * Defaults to all types supported by the SDK
       * (Optional)
       */
      types: ['crawlers', 'performance'],
    }
  }
};
</script>
```

{% endtab %}

{% tab title="Custom JSON" %}

```python
{
  "user": {
    "bots": {
      "consentRequired": false,
      "types": ["crawlers", "performance"]
    }
  }
}
```

{% endtab %}
{% endtabs %}

The `user.bots.types` and `user.bots.extraUserAgents` properties give you extra control on what user agents are identified as bots. The Didomi SDK can automatically identify all the most common search engine bots and performance tools.

{% hint style="warning" %}
When configuring the consent notice from the Didomi console, consent is not collected for bots by default (consentRequired is set to false). This is usually the expected behavior, and it is thus unnecessary to use the above code.
{% endhint %}

#### Example using extraUserAgents

{% hint style="info" %}
The SDK internally uses the `RegExp` object constructor to generate the needed regular expressions out of the provided `extraUserAgents` array list. Normal string escape rules apply, i.e, preceding special characters with the \ character, [reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#flags_in_constructor).
{% endhint %}

The following is a valid example using the `extraUserAgents` property:

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

```javascript
<script type="text/javascript">
window.didomiConfig = {
  user: {
    bots: {
      /**
       * List of additional regular expressions to match
       * against the User Agent of the visitor.
       * When one of the regular expressions matches, the user
       * is considered to be a bot.
       * This allows you to identify extra bots that the SDK does not
       * know about.
       * Regular expressions must be specified as strings and correctly
       * escaped.
       * (Optional)
       */
      extraUserAgents: [
        "Mozilla\\/5.0 \\(Windows NT 10.0; Win64; x64; rv:88.0\\) Gecko\\/20100101 Firefox\\/88.0 \\(compatible; MonetoringBot\\/2.1\\)",
        "Mozilla\\/5.0 \\(compatible; SiteAnalyzerBot\\/5.0; \\+https:\\/\\/www.site-analyzer.com\\/\\)"
      ],
    }
  }
};
</script>
```

{% endtab %}

{% tab title="Custom JSON" %}

```json
{
  "user": {
    "bots": {
      "extraUserAgents": [
        "Mozilla\\/5.0 \\(Windows NT 10.0; Win64; x64; rv:88.0\\) Gecko\\/20100101 Firefox\\/88.0 \\(compatible; MonetoringBot\\/2.1\\)",
        "Mozilla\\/5.0 \\(compatible; SiteAnalyzerBot\\/5.0; \\+https:\\/\\/www.site-analyzer.com\\/\\)"
      ]
    }
  }
}
```

{% endtab %}
{% endtabs %}

## Bots categories

By default and if you configure the SDK to not collect consent from bots, all bots are impacted.\
If you want to control what categories of bots require consent more specifically, the Didomi SDK categorizes bots in the following categories and allows you to enable only some of them:

| ID            | Category          | Description                                                                                  |
| ------------- | ----------------- | -------------------------------------------------------------------------------------------- |
| `crawlers`    | Crawlers          | Bots that index your websites for Search Engines (Google, Bing, etc.)                        |
| `performance` | Performance Tools | Bots that visit your websites for performance reports (Google Page Insights, GTmetrix, etc.) |


# Configuration by URL

{% hint style="danger" %}
This section describes how to override the configuration of the Didomi Web SDK through query-string parameters in the URL.

Configuration options should be done through the [Didomi Console](https://console.didomi.io/) or through local configuration variables/files. Configuration by URL should only be used in [specific cases like testing/previewing AB tests or disabling a notice in a WebView](#use-cases).
{% endhint %}

Didomi allows some configuration properties to be passed via query-string parameters in the URL if you want to test or preview changes on the fly. The configuration passed in the query string is merged into the remote configuration (from the Console) and the local configuration (from `window.didomiConfig`).

## Allowed properties to be passed by URL

For security reasons, we currently only allow the properties below:

* `notice.enable`
* `notice.showDataProcessing`
* `experiment.group`
* `app.vendors.iab.version`

{% hint style="warning" %}
**Note**: If your organization encounters an issue with the `token` query parameter in your URL, your organization can configure the Didomi web SDK to process a different token name. [Click here](/api-and-platform/consents/tokens#configure-consent-token-name) for more information.
{% endhint %}

## Query-string parameters

You can either pass a full Didomi configuration object via a `didomiConfig` parameter or a specific attribute via `didomiConfig.*`.

### Full configuration

To override more than one attribute, we suggest to use the `didomiConfig` parameter. It allows you to provide a full Didomi configuration object encoded as JSON. The format and content of the object is the same as the `window.didomiConfig` object added to a webpage so any option that can be passed there can be passed in the query string.

First, encode your configuration object as url-encoded JSON so that it can be read properly by the browser. You can use [this online encoder](https://www.urlencoder.org/) to convert your JSON object into a readable query-string parameter.

For example, `{ "notice": { "enable": false } }` will become `%7B%20%22notice%22%3A%20%7B%20%22enable%22%3A%20false%20%7D%20%7D` and the URL will be:

```http
{{YOUR_WEBSITE_URL}}?didomiConfig=%7B%20%22notice%22%3A%20%7B%20%22enable%22%3A%20false%20%7D%20%7D
```

### Specific configuration

If you want to override only one attribute, it may be faster and easier to use the `didomiConfig.*` parameter. It allows you to edit a specific attribute via a dot notation.

Use a **dot notation** to go deeper into the configuration tree. For example, `{ "notice": { "enable": false } }` will be written as `didomiConfig.notice.enable=false` and the URL will be:

```http
{{YOUR_WEBSITE_URL}}?didomiConfig.notice.enable=false
```

## Use cases

Configuration should never be passed via URL except for specific cases for temporary preview or testing. Here are a few cases where configuration via URL can be useful:

### Force group test for AB tests

If you run AB test, it can be difficult to see how it looks on production, especially if the size of your test is small. To avoid you from clearing your cache and refreshing the page until you see the test configuration, you can force the test group to `test` or `control`.

Force your website to display the test group configuration :

```http
{{YOUR_WEBSITE_URL}}?didomiConfig.experiment.group=test
```

### Disable notice in a WebView (Mobile Apps)

If you are opening WebViews in your mobile apps, you can [share the consent status of the user from the app to the WebViews](/cmp/mobile-sdk/share-consent-with-webviews). This allows you to not re-collect consent on the web pages.

In some cases, the notice might be displayed for a short time before being hidden in the WebView as the consent gets passed. To avoid that visual glitch, you can disable the notice in your WebView to make sure that it never shows:

```http
{{YOUR_WEBSITE_URL}}?didomiConfig.notice.enable=false
```

### Force the Transparency and Consent Framework (TCF) version

If you want to transitioned to the TCF v2 and would like to have a preview on how it will impact your website, you can force the version via URL. The authorized values are `1` et `2`.

Force your website to display the notice with a specific version of the TCF :

```http
{{YOUR_WEBSITE_URL}}?didomiConfig.app.vendors.iab.version=2
```

### Display the data processing list in your notice

If you want to have a preview on how the data processing list will impact the UI of your notice, you can display it by switching `showDataProcessing` to `true`.

Force the data processing list to be displayed in the notice :

```http
{{YOUR_WEBSITE_URL}}?didomiConfig.notice.showDataProcessing=true
```


# Cookies and storage

By default, the Didomi CMP uses first-party cookies to store consent information. Consent is stored in the base domain and shared across all the subdomains of the base domain where the SDK is deployed.

**Example:** If you install Didomi on `www.domain.com`, consents will be stored in a cookie on `.domain.com` and all sub-domains of `domain.com` will have access to the same consent information.

## Store consent on a different domain (subdomain)

If you want to store the first-party cookie on a specific sub-domain, you can add this option into the configuration.

Consents will be shared only to pages with this specific sub-domain.

```javascript
window.didomiConfig = {
  cookies: {
    local: {
      customDomain: 'privacy.your-domain.com'
    }
  }
};
```

## Cookie name

The Didomi SDK uses up to three cookies and local storage items for storing user consent:

* `didomi_token` for vendors and purposes in the token format (JSON format)
* `didomi_dcs` for vendors and purposes stored in the Didomi Consent String format (binary encoded)
* `euconsent-v2` for IAB TCF vendors and purposes (only for the GDPR regulation)

The name of the `didomi_token` , `didomi_dcs` and `euconsent-v2` cookies can be modified if you want to use a different name by setting the `cookies` property:

```javascript
window.didomiConfig = {
  cookies: {
    didomiTokenCookieName: 'custom_cookie_name', // didomi_token custom name
    iabCookieName: 'custom_iab_cookie_name', // euconsent-v2 custom name
    didomiConsentStringCookieName: 'custom_dcs_cookie_name' // didomi_dcs custom name
  }
};
```

Keep in mind that modifying the cookie name on a website that already had the Didomi SDK installed will re-collect consent. We recommend using a short cookie name.

## **Enable consent collection for different pages**

There may be a case where some pages on your website(s) do not belong to the same legal entity, but you want to collect consent on different pages, for example, displaying multiple notices on the website, with different vendors configuration, and local regulations, and save them "locally" and not at the domain level.

If you would like to separate consent between different sub-domains or pages inside the domain you can use custom cookie names to store the end-user consent status in different cookies / storage items. Custom cookie names should be configured in the `didomiConfig.cookies` property for a given page.

Defining the custom cookie names used to store end-user consent will depend on whether your organization utilizes `didomi_token` or `didomi_dcs` ([Didomi Consent String](/cmp/didomi-consent-string)). Refer to the tabs for more information:

{% tabs %}
{% tab title="Didomi token" %}
If the web property utilizes the Didomi token (`didomi_token`) to store end-user consents your organization will need to define the custom cookie names for `didomiTokenCookieName` and `iabCookieName` for each web property.

{% code overflow="wrap" %}

```javascript
window.didomiConfig = {
  cookies: {
    didomiTokenCookieName: 'custom_cookie_name', // didomi_token custom name
    iabCookieName: 'custom_iab_cookie_name', // euconsent-v2 custom name
  }
};
```

{% endcode %}
{% endtab %}

{% tab title="Didomi Consent String" %}
If the web property utilizes the Didomi Consent String (`didomi_dcs`) to store end-user consents your organization will need to define the custom cookie names for `didomiConsentStringCookieName` and `iabCookieName` for each web property.

{% code overflow="wrap" %}

```javascript
window.didomiConfig = {
  cookies: {
    iabCookieName: 'custom_iab_cookie_name', // euconsent-v2 custom name
    didomiConsentStringCookieName: 'custom_dcs_cookie_name' // didomi_dcs custom name
  }
};
```

{% endcode %}
{% endtab %}
{% endtabs %}

Please have a look at the [Didomi Sandbox for Collecting Consent on Different Pages](https://sandbox.didomi.io/page-consent/index.html) to see how it works.

## Storage sources for user information

By default, the Web SDK stores user information and choices in both cookies and local storage. You can configure where user information and choices should be stored and use only cookies or local storage if you want to.

Set `cookies.storageSources.cookies` to `false` to disable storing data in cookies.\
Similarly, set `cookies.storageSources.localStorage` to `false` to disable storing data in local storage.

For instance, to configure the Web SDK to use local storage only:

```javascript
window.didomiConfig = {
  cookies: {
    storageSources: {
      cookies: false,
      localStorage: true
    }
  }
};
```


# Custom domains for events

{% hint style="danger" %}
This section describes how to configure the Didomi consent notice through its programmatic API and the `window.didomiConfig` object.

Most configuration options are available through the [Didomi Console](https://console.didomi.io/), and this documentation only applies to edge cases or custom implementations that require it.
{% endhint %}

In some hybrid apps (Electron, Cordova, etc.), the `location.host` value used by the Web SDK is not defined. This can cause the following issue in analytics data and events:

* Your organization has a lot of page views with no consent rate.

A custom domain can be set as part of the `didomiConfig` object to ensure that some domain is associated with API events for those applications.

You can add a `customDomain` property to the `app` object in the configuration:

```javascript
window.didomiConfig = {
  app: {
    customDomain: "custom.app.domain",
  },
};
```

{% hint style="warning" %}
Please ensure that you specify a valid domain in one of the following formats:

* A valid DNS name

  **Example:** `sandbox.domain.io`, `www.domain.io`
* A valid iOS bundle ID or Android package ID

  **Example:** `com.example.app`, `com.example.app.ios`, `com.example.app.macos`

Otherwise, it will be filtered out and not included in your analytics event data.
{% endhint %}

This configuration option is also available in the [Didomi Console](https://console.didomi.io/) as part of the Custom JSON field in the `Customization` tab.


# Notice

{% hint style="danger" %}
This section describes how to configure the Didomi consent notice through its programmatic API and the `window.didomiConfig` object.

Most configuration options are available through the [Didomi Console](https://console.didomi.io/) and this documentation only applies to edge cases or custom implementations that require it.
{% endhint %}

The notice is the first banner or pop-in that gets displayed on your website to ask the user to give consent. It is a short version of the full Preferences pop-in that has all the details on the purposes and vendors that you are collecting consent for.

The notice is highly customizable to match the look and feel of your website: it can be displayed as a banner, a popup, a floating panel, etc. and you can change all the colors and content.

This section presents the main customization options that are available. If you need even more, you can use CSS to further customize the visual aspect of the notice.

{% content-ref url="/pages/-M-kpC9xJIoeZDHf8wwx" %}
[Behavior](/cmp/web-sdk/consent-notice/notice/behavior)
{% endcontent-ref %}

{% content-ref url="/pages/-M-kZCwUTUzsJx57Gz6l" %}
[Interactions](/cmp/web-sdk/consent-notice/notice/interactions)
{% endcontent-ref %}

{% content-ref url="/pages/-M-kiKyfYmFLvaSG80zw" %}
[Look and feel](/cmp/web-sdk/consent-notice/notice/look-and-feel)
{% endcontent-ref %}


# Behavior

## Window for recollecting consent

By default, consent is automatically re-collected and the notice is displayed again in three cases:

* After 13 months (maximum acceptable cookie lifetime)
* When the user clears they browser cookies
* When a new vendor is added in your tag configuration or in the IAB vendors list (if you choose the option `all`)

The third case (a new vendor is added) can happen pretty often so you have the option to choose a number of days during which the notice will not be displayed even though there are new vendors to collect consent for. By default, the number is zero and the notice will be displayed automatically if a new vendor is added. If you create notices through the Didomi Console, the default value is 30 days.

During that consent recollection window:

* New users will be asked for consent for the new vendor immediately.
* Previous users that had already given consent within the window (ie less than X days ago) will not be asked again until the expiration of the window. The new vendor will not have vendor during that time.
* Previous users that had already given consent outside of the window (ie more than X days ago) will be asked again immediately.

```javascript
<script type="text/javascript">
window.didomiConfig = {
  notice: {
    daysBeforeShowingAgain: 5 // Number of days. Default is 0
  }
};
</script>
```

{% hint style="info" %}
If you choose that option and because the notice is not shown again, the user consent status will be partial and some vendors will not have consent information. The function `Didomi.isUserStatusPartial()` can return `true` in these cases.
{% endhint %}

{% hint style="info" %}
Be aware that when recollecting consent until it is given to a vendor (`true` or `false`), consent status is reset to `undefined.`
{% endhint %}

## Recollect consent after a certain date

In some cases, you might want to force recollect consent for all users after a certain date, irrespective of their choices and the configured window for recollecting consent.

This can be achieved by setting an ISO8601 date in the `user.ignoreConsentBefore` property:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  user: {
    ignoreConsentBefore: "2020-09-09T00:00:00Z"
  }
};
</script>
```

When the user has given consent before the provided date, consent will be automatically recollected. Dates in the future are ignored until they become current so you can schedule a consent recollection for a specific date in the future.

## Consent expiration

Didomi CMP allows you to customize the lifetime of the consent so that it expires after a specific time.

You can use `app.consentDuration` configuration option to specify custom consent duration:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    consentDuration: 100 // Custom consent duration in seconds
  }
};
</script>
```

The `app.consentDuration` configuration option accepts custom consent duration value in seconds.

Consent expires after 12 months by default if custom consent duration is not specified.

The lifetime of the cookies is set to the value specified in the consent duration configuration option. If the custom consent duration is not specified, the lifetime of the cookies will be set to 12 months by default.

### Expiration for denied consent

It is possible to apply a specific consent expiration when the user denies consent for all purposes and vendors. This can be done by using the `app.deniedConsentDuration` configuration option:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    deniedConsentDuration: 100 // Denied consent duration in seconds
  }
};
</script>
```

If this configuration option is used and the user disagrees to all vendors and purposes on the consent legal basis, the consent will expire after the specified denied consent expiration and the consent will be recollected. The user choices on the legitimate interest legal basis are not taken into account when applying this configuration option.

{% hint style="info" %}
The denied consent duration value should be smaller than the generic consent duration value, otherwise, the denied consent expiration will be ignored.
{% endhint %}

The `app.deniedConsentDuration` configuration option accepts a custom consent duration value in seconds.

If no value is set for the denied consent duration, the generic consent duration will still be applied for the denied consents.

## Vendors and purposes

You must configure the vendors for which consent is collected by our consent notice and displayed in the preferences popup.

## Notice country

If you want to specify the country which determines the policy, you can use the `app.country` configuration option:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    country: 'fr' // Two-letter country code
  }
};
</script>
```

The `app.country` configuration option receives a string which is an [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code.

{% hint style="info" %}
The value specified in the **`app.country`** configuration option is used for the IAB TCF v2 consent string and for the IAB TCF v2 \*\*`__tcfapi`\*\*method.

You can read more about it in our [Reference](/cmp/web-sdk/reference/api#__tcfapi-command-version-callback-parameter) section.
{% endhint %}

## Configuration by user country

By default, we will serve the notice with the appropriate regulation based on the location of the user's geolocation as determined by IP address resolution to country and region values. That is, if you have a notice configured to display GDPR within the EU (the default) and you have also added the CPRA regulation to display in California, a visitor from California will receive the CPRA banner and the same visitor traveling to France would see the GDPR version of the notice. For more details on multi-regulation notices, read more [here](https://developers.didomi.io/api/widgets/consent-notices/multi-reg-configurations#specifying-where-to-show-a-specific-regulation-geo-locations).

If you want to override what our servers are detecting in terms of the geolocation of your visitors, you can override the user [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) `country` code and the [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) `region` code directly via your local SDK config object by setting the `window.didomiConfig.user.country` and `window.didomiConfig.user.region` properties to have their values equal to valid country and region codes. For example, if you want a user to appear to be visiting from California:

```javascript
window.didomiConfig = {
    user: {
        country: "US",
        region: "CA"
    }
}
```

It is likely that you would be setting these properties dynamically via server-side code. Some things to be aware of when explicitly overriding the country and region codes when overriding the SDK's default behavior for serving notice configurations based on user geolocation detected by our servers:

* If the values are null/undefined, we will ignore them and serve the notice using our standard behavior, i.e. what our servers have detected based on the incoming request's geolocation.
* Because you are overriding our default behavior and we do not validate whether or not the country and region codes you are sending us are actual ISO codes, it is your responsibility to send valid country and region ISO codes. An invalid codes would result in a failure to match in our lookup for a related notice configuration. It is your responsibility to ensure valid codes are sent to us to resolve.
* We are not changing our logic about how we serve notices, we are only allowing you to override the country and region codes. Therefore, what happens is determined on the notice settings in the country and region configuration in the console for the notice. That is, if you have configured GDPR to apply to only certain countries, the GDPR notice will only show up in those cases. In all other cases, there is no notice displayed.

#### Country-specific configuration settings

If you want to apply a different configuration depending on the country that the user is from, you can add country-specific properties in a `configByCountry` property where each key is an [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code in uppercase (the country code is case-sensitive). This allows you to replace part or all of the configuration for some countries.

Example to force the language based on the user country instead of the user browser configuration, and modify vendors:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  // Visitors from countries other than FR or US will get this configuration
  languages: {
    enabled: ['fr', 'en'], // Enable both French and English for all users
  },
  app: {
    name: 'My Website',
    vendors: {
      iab: {
        all: true,
        exclude: [9],
      }
    }
  },
  configByCountry: {
    // Visitors from France will get the global configuration + these changes applied to it
    FR: {
      languages: {
        enabled: ['fr'] // Force French for visitors from France
      },
      app: {
        vendors: {
          iab: {
            all: false,
            include: [9],
            exclude: [] // It's important to override "exclude" here otherwise it would be kept as [9]
          }
        }
      }
    },
    // Visitors from the US will get the global configuration + these changes applied to it
    US: {
      languages: {
        enabled: ['en'] // Force English for visitors from the US
      }
      // Vendors are not specified here so the global vendors will apply (all IAB)
    }
  }
};
</script>
```

The properties defined in `configByCountry` are merged with the rest of the configuration when the user comes from the matching country. The properties from the country configuration override the properties defined globally and are merged recursively so make sure to fully override objects when necessary. Arrays are replaced and not merged or concatenated.


# Interactions

{% hint style="info" %}
These features are available exclusively under GDPR. However, we don’t recommend their use. Many European Data Protection Authorities, including those in France, Germany, and Belgium, along with the EDPB, do not recognise consent obtained through scrolling or clicking as clear, unambiguous, and affirmative action. Therefore, consent collected with such methods are considered invalid.
{% endhint %}

Consent can be collected on various user interactions with the website (scroll, navigation, etc.).

These options are disabled by default as, under GDPR and ePrivacy, collecting consent when the user interacts with a website (apart from an explicit `Agree` button), is usually not considered a valid consent. Local exceptions might apply so these options can be enabled if your legal department considers them to be valid for your operations.

## Scroll

Our banner supports the option of collecting consent when the user scrolls down a page.\
That means that, when the user scrolls down a certain amount of the page, the banner gets closed and the user consent is registered. The banner will not be shown again on the following pages.

You can enable or disable that option with the `notice.closeOnScroll` option.

**To enable consent on scroll:**

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    closeOnScroll: true
  }
};
</script>
```

**To disable consent on scroll:**

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    closeOnScroll: false
  }
};
</script>
```

### Thresholds

By default, consent is collected after the user scrolls more than 30% of the page. This can be configured in two ways:

* Collect consent after the user scrolls more than X% of a page (percent-based)
* Collect consent after the user scrolls more than X pixels on a page (absolute)

#### Percent-based scroll threshold

To collect consent after the user scrolls a certain percentage of the page:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    closeOnScroll: true,
    closeOnScrollThresholdType: 'percent',
    closeOnScrollThreshold: 30,
  }
};
</script>
```

#### Absolute scroll threshold

To collect consent after the user scrolls a certain number of pixels on the page:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    closeOnScroll: true,
    closeOnScrollThresholdType: 'absolute',
    closeOnScrollThreshold: 300,
  }
};
</script>
```

## Navigation

Our banner supports the option of collecting consent when the user navigates to another page of your website.\
That means that, when the user clicks on a link to another page, the banner get closed and the user consent is registered. The banner will not be shown again on the following pages.

You can enable or disable that option with the `notice.closeOnClick` option.

**To enable consent on navigation:**

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    closeOnClick: true
  }
};
</script>
```

**To disable consent on navigation:**

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    closeOnClick: false
  }
};
</script>
```

### Delay

This option allows you to set a delay that will be applied when consent is collected after the user navigates to another page of your website. That delay will allow your vendors to execute on the first page before the user is redirected to the page he was meant to navigate to. It helps not losing data that would only be available on the first page that the user gets on (for analytics and attribution, for instance).

With this option, the chain of events becomes:

1. User clicks on a link to navigate to another page of your website
2. Consent is collected
3. Vendors' tags are fired on the page
4. Delay of X milliseconds
5. User navigates to the other page

If the user has already given consent by another mean, no delay will be applied.

To enable this option, set your delay in milliseconds in the `notice.closeOnClickNavigationDelay` property:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    closeOnClick: true,
    closeOnClickNavigationDelay: 500 // Delay of 500 milliseconds
  }
};
</script>
```

This option is disabled by default and no delay is applied.

## Backdrop click

Our banner supports the option of collecting consent when the user clicks on the backdrop when the popup notice is open. By default, this option is disabled but you can enable it with the `notice.closeOnClickBackdrop` option.

{% hint style="info" %}
This feature only applies to the "popup" notice.
{% endhint %}

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    closeOnClickBackdrop: true
  }
};
</script>
```


# Look and feel

## Languages

Our SDK supports multiple languages out-of-the-box with translations for all our standard messages. See below if your website uses other languages.\
English is the default language: if a visitor does not use a supported language, the banner and popups will be displayed in English.

You do not need to do anything to use Didomi's languages. However, you can choose to enable only certain languages and set up a different default language.\
Set the `languages.enabled` property to your list of supported languages and `languages.default` property as the default language in case the customer language is not supported:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  languages: {
    enabled: ['en', 'es', 'fr'], // List of languages that visitors can use (must be a subset of the languages that we support)
    default: 'fr' // Default language to use if the visitor uses a language that is not enabled
  }
};
</script>
```

By default, `enabled` is the list of supported languages by Didomi and `default` is `en`. You can support different languages by changing the English texts and setting English as the only enabled language.

{% hint style="info" %}
We currently support [this list of languages](/api-and-platform/introduction/translations#languages-supported).
{% endhint %}

### **Language direction**

The Didomi SDK adapts to the text direction of your website by default, inheriting the `dir` attribute from its parent elements, typically the `<html>` or `<body>` tag. This ensures compatibility with the overall layout of your site.

To understand more about the HTML `dir` attribute please refer to <https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir>

#### **Overriding language direction**

If you need the Didomi notice to have a different text direction from the rest of your website, you can override it with custom CSS.

The Didomi notice is rendered in a `div` element with ID `didomi-host` that contains:

* a `lang` attribute to identify the language on the notice
* a `data-lang-dir` attribute with the suggested direction to use for the language applied

Example of HTML generated by the Didomi SDK for a notice in Arabic:

```html
<div id="didomi-host" lang="ar" data-lang-dir="rtl">...</div>
```

With these attributes you can apply CSS rules like:

```css
/* Target a single language */
#didomi-host[lang="ar"] {
  direction: rtl;
}

/* Target all languages that are suggested as RTL */
#didomi-host[data-lang-dir="rtl"] {
  direction: rtl;
}
```

## Theme

The SDK supports theming by providing a color that will be used across the interfaces (consent notice, popups, etc.) to make sure that our UIs match your brand colors.

The color that you provide should be the main color of your website, the one that appears most frequently.

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  theme: {
    color: '#3F51B5'
  }
};
</script>
```

## Position

The notice can be displayed as a popup, a regular banner (top or bottom), a smaller banner or as a floating panel and can be positioned at different locations on the screen.

The `position` configuration parameter lets you define the position of the notice. The possible values are:

| Values                                                                                                                                  | Description                                                                                                             |
| --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `popup`                                                                                                                                 | Display the notice as a full-screen popup. Also set your website logo and name to make sure the popup is personnalized. |
| <p><code>panel-top-left</code><br><code>panel-top-right</code><br><code>panel-bottom-left</code><br><code>panel-bottom-right</code></p> | Display the notice as a small panel in one of the corners of the screen. `panel-bottom-right` is the default value.     |
| <p><code>top</code><br><code>bottom</code></p>                                                                                          | Display a banner notice at the top or the bottom of the screen                                                          |
| <p><code>top-left</code><br><code>top-right</code><br><code>bottom-left</code><br><code>bottom-right</code></p>                         | Display a floating panel in a corner of the screen                                                                      |

Examples:

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

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    position: 'bottom'
  }
};
</script>
```

{% endtab %}

{% tab title="Corner banner" %}

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    position: 'panel-bottom-right'
  }
};
</script>
```

{% endtab %}

{% tab title="Popup" %}

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    position: 'popup'
  }
};
</script>
```

{% endtab %}

{% tab title="Floating panel" %}

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    position: 'top-left'
  }
};
</script>
```

{% endtab %}
{% endtabs %}

## **"Disagree and close" button**

By default, our notices display `Agree and close` and `Learn More` buttons. These allow users to give consent or get more information on the purposes and vendors that your website works with.

We also support displaying `Agree and close` and `Disagree and close` buttons directly in the notice:

![](/files/-MRzIS11NqPdHQgUkYoU)

To display those buttons, set the `notice.denyOptions.button` of your notice to `primary`

```javascript
window.didomiConfig = {
  notice: {
    denyOptions: {
      button: 'primary',
    }
  }
};
```

This is supported for both banners (`bottom` or `top` positions) or pop-ins (`popup` position).

### Style of the "Disagree and close" button

In the example above the `Disagree and close` button is a primary button. To make it a secondary button, you can set the `notice.denyOptions.button` configuration option `secondary`:

```javascript
window.didomiConfig = {
  notice: {
    denyOptions: {
      button: 'secondary',
    }
  }
};
```

To hide the `Disagree and close` button in the notice you can set `notice.denyOptions.button` to `none`.

{% hint style="danger" %}
Please note that the `denyAsPrimary` parameter is deprecated and should not be used for the styling of the "Disagree and close" button.
{% endhint %}

### "Continue without agreeing" link

A "Continue without agreeing" link can be displayed instead of the "Disagree and close" button in the `optin` notice type:

![](/files/-MSXTdLx5T-drcXUckNZ)

To show the "Continue without agreeing" link, set the `notice.denyOptions.link` value to `true`:

```javascript
window.didomiConfig = {
  notice: {
    denyOptions: {
      button: 'secondary',
      link: true,
    }
  }
};
```

The "Continue without agreeing" link behaves the same way as the "Disagree and close" button.

Please note that if `notice.denyOptions.link` is `true` then `notice.denyOptions.button` options will be ignored and only a link will be shown in the notice.

{% hint style="danger" %}
Please note that the `denyAsLink` parameter is deprecated and should not be used for the "Continue without agreeing" link configuration.
{% endhint %}

### **Cross button**

To comply with Italian regulation, you should add a cross button to the notice. To make the cross button appear in the notice set the `notice.denyOptions.cross` parameter value to `true`:

```javascript
window.didomiConfig = {
  notice: {
    denyOptions: {
     cross: true,
     link: true,
    }
  }
};
```

![Italian Regulation example](/files/2GukUmEHbuAIZr8RSVTo)

Please note that you can have both the “Disagree and close button” and the cross button in the same notice, for example:

```javascript
window.didomiConfig = {
  notice: {
    denyOptions: {
     button: 'primary',
     link: true,
    }
  }
};
```

![Italian Regulation Example](/files/m6FFPgIK8RU7h1uwE6X1)

### Configuring legitimate interest legal basis status

After clicking on the "Disagree and close" button or "Continue without agreeing" link in the optin notice, all purposes' and vendors' consents are disabled, and all purposes' and vendors' legitimate interests are enabled by default.

To disable legitimate interests as well after clicking on the "Disagree and close" button or "Continue without agreeing" link, `notice.denyAppliesToLI` should be set to `true` in the Didomi configuration object:

```javascript
window.didomiConfig = {
  notice: {
    type: 'optin',
    denyAppliesToLI: true
  }
};
```

## Text alignment

You can change the alignment of the text inside the notice. The options are `left`, `right`, `center` and `justify`. By default, the text is aligned to the `left`.

Example:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  notice: {
    textAlignment: 'left'
  }
};
</script>
```

## Logo alignment

You can change the alignment of the logo inside the notice. The options are the one available for the CSS property [align-self](https://www.w3schools.com/cssref/css3_pr_align-self.asp). So for example to align it to the left, the value would be `flex-start` and to the right `flex-end`. By default, the logo is aligned to the `center`.

Example:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  notice: {
    logoAlignment: 'center'
  }
};
</script>
```

## Buttons

### Order

You can change the order of the buttons inside the notice. By default `learnMorePosition` is `null` and the "learn more" button is displayed before the "agree" button on the regular notice and after on the popup notice.

The options are `before` and `after`.

Example:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  notice: {
    learnMorePosition: null
  }
};
</script>
```

### Margins

You can set the margins of the "learn more" button on the popup notice.

The options are based on the CSS `margin` property.

Example:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  notice: {
    learnMoreMargin: '20px 0 5px 0'
  }
};
</script>
```

## Texts

You can change some of the texts of the consent notice:

| Configuration Key             | Description                                                                                                                            |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `notice.content.dismiss`      | "Agree & Close" button                                                                                                                 |
| `notice.content.deny`         | "Decline" button                                                                                                                       |
| `notice.content.learnMore`    | "Learn More" button                                                                                                                    |
| `notice.content.subTextPopup` | Message below the "Learn more" button in the popup. This is only used if you are using a popup and not for banners or floating panels. |

Example:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  notice: {
    content: {
      dismiss: {
        en: 'Agree & Close',
        fr: 'Accepter et fermer'
      },
      learnMore: {
        en: 'Learn More',
        fr: 'En savoir plus'
      }
    }
  }
};
</script>
```

Note that you should provide translations for all the languages that your website supports. We provide translations for all our standard messages.

#### Move the vendors link in your banner to your custom text

If you want to move the vendor link to your custom text `notice.content.notice` instead of having a separate link, you can use the function `Didomi.preferences.show('vendors')` to open the preference popup. The original link will be automatically replaced.

```markup
<a href="javascript:Didomi.preferences.show('vendors')">View partners</a>
```


# Preferences

{% hint style="danger" %}
This section describes how to configure the Didomi consent notice through its programmatic API and the `window.didomiConfig` object.

Most configuration options are available through the [Didomi Console](https://console.didomi.io/) and this documentation only applies to edge cases or custom implementations that require it.
{% endhint %}

## Introduction

![Preferences popup that opens when the user clicks on "Learn more"](/files/-LMZ9oBks-hOLhkvAmGq)

The "Preferences" pop-in allows the user to manage his or her preferences in terms of consent given by purpose and by vendor. By default, it is shown when the user clicks on "Learn more" in the notice (banner or popin) and we recommend adding a link on your website to open it.

## Open the popup

By default, the popup can be open from the banner if the user wants to get more information.

We recommend that you also add a link to your website (in the menu or in the privacy policy) to let the user update his or her preferences.

You can do so by calling the `Didomi.preferences.show()` function.

Example with a link:

```markup
<a href="javascript:Didomi.preferences.show()">Manage my privacy preferences</a>
```

## Privacy Policy

Our default text includes a link to your privacy policy. You can set that URL with the `app.privacyPolicyURL` property.

Example:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>',
    privacyPolicyURL: 'https://privacy.didomi.io/'
  }
};
</script>
```

## Text & Macros

You can change the content of the popup by setting properties on `preferences.content`.

| Configuration Key                     | Description                                                |
| ------------------------------------- | ---------------------------------------------------------- |
| `preferences.content.text`            | Main content of the popup                                  |
| `preferences.content.title`           | Title of the popup (Welcome to ...)                        |
| `preferences.content.disagreeToAll`   | 'Disagree to all' button                                   |
| `preferences.content.agreeToAll`      | 'Agree to all' button                                      |
| `preferences.content.save`            | 'Save' button                                              |
| `preferences.content.subText`         | Text between the 'View all partners' button and the footer |
| `preferences.content.viewAllPartners` | 'View all partners' button                                 |
| `preferences.content.agree`           | 'Agree' buttons                                            |
| `preferences.content.disagree`        | 'Disagree' buttons                                         |

Example:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API key>'
  },
  preferences: {
    content: {
      text: {
        en: 'We and our partners place cookies, access and use non-sensible information from your device to improve our products and personalize ads and other contents throughout this website. [...]',
        fr: 'Nos partenaires et nous déposons des cookies et utilisons des informations non sensibles de votre appareil pour améliorer nos produits et afficher des publicités et contenus personnalisés. Vous pouvez accepter ou refuser ces différentes opérations. [...]'
      },
      title: {
        en: 'Welcome to our website',
        fr: 'Bienvenue sur notre site'
      },
      disagreeToAll: {
        en: 'Disagree to all',
        fr: 'Refuser tout'
      },
      agreeToAll: {
        en: 'Agree to all',
        fr: 'Accepter tout'
      },
      save: {
        en: 'Save',
        fr: 'Sauvegarder'
      },
      viewAllPartners: {
        en: 'View all partners',
        fr: 'Voir nos partenaires'
      },
      agree: {
        en: 'Agree',
        fr: 'Accepter'
      },
      disagree: {
        en: 'Disagree',
        fr: 'Refuser'
      }
    }
  }
};
</script>
```

Note that you should provide translations for all the languages that your website supports. We provide translations for all our standard messages.

### Macros

You can use macros that will get replaced with the actual value configured when the text gets rendered.

| Macro                      | Value                  | Description                                                                        |
| -------------------------- | ---------------------- | ---------------------------------------------------------------------------------- |
| `{privacyPolicyURL}`       | `app.privacyPolicyURL` | Privacy Policy URL                                                                 |
| `{websiteName}`            | `app.name`             | Name of your website                                                               |
| `{numberOfPartners}`       |                        | A dynamic value that displays a numeric count of all vendors                       |
| `{numberOfIABPartners}`    |                        | A dynamic value that displays a numeric count of IAB vendors                       |
| `{numberOfNonIABPartners}` |                        | A dynamic value that displays a numeric count of all vendors excluding IAB vendors |

## Disable Agree/Disagree to all buttons

By default, we display "Agree to all" and "Disagree to all" buttons at the bottom of the list of purposes to allow the user to agree or disagree in a single click:

![](/files/-LZuRDo5nu5ahpDmgmNk)

You can disable these buttons and only display the Save button to force the user to make individual choices by purpose by switching `enableAllButtons` to `false` . In that case, the user will have to manually agree/disagree to each purposes:

![](/files/-LZuRJ45RzyP7Fk2QJfV)

Example:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  preferences: {
    enableAllButtons: true,
  }
};
</script>
```

### Disagree and Agree to all buttons at the top of the purposes list

We can enable "Agree to all" and "Disagree to all" buttons at the top of the list of purposes by setting `enableBulkActionOnPurposes` to `true` in the `notice` object.

Example:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  notice: {
    enableBulkActionOnPurposes: true,
  }
};
</script>
```

![Disagree to all / Agree to all buttons at the top of the puproses list](/files/Y39mDvWmfjUntjAts5RQ)

When "Disagree to all" and "Agree to all" buttons are visible all other purposes buttons will be adjusted in width to be aligned with bulk action buttons. There are number of changes in the styling for bulk action buttons and purposes buttons that the WEB SDK applies in this case:

| Bulk buttons     | `font-size`  | `12px !important` |
| ---------------- | ------------ | ----------------- |
|                  | `box-sizing` | `border-box`      |
|                  |              |                   |
| Purposes buttons | `box-sizing` | `border-box`      |
|                  |              |                   |

{% hint style="danger" %}
A custom CSS that changes the `didomi-components-radio__option` class could break buttons alignment and places buttons outside of the notice
{% endhint %}

## Configuring legitimate interest legal basis status

After clicking on the `Disagree to all` button in the purposes screen, all purposes' and vendors' consents and legitimate interests are disabled by default.

To keep legitimate interests enabled after clicking on the `Disagree to all` button, `preferences.denyAppliesToLI` should be set to `false` in the Didomi configuration object:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  preferences: {
    denyAppliesToLI: false
  }
};
</script>
```

## Purposes

### Order of purposes

You can control the order in which purposes should be displayed.

This can be done by adding an array of purposes in the `preferences.categories` property in the `didomiConfig` object. The order in which items are added to this array will be the same order in which purposes will be displayed in based on their `purposeId`.

Purposes that are required by some vendors and that are not included in the list will be appended to the end of the list in alphabetical order to make sure that all required purposes are displayed and that consent is correctly collected.

{% code title="didomi\_config.json" %}

```javascript
<script type="text/javascript">
window.didomiConfig = {
  preferences: {
    categories: [
      {
        type: 'purpose',
        purposeId: 'cookies'
      },
      {
        type: 'purpose',
        purposeId: 'advertising_personalization'
      },
      {
        type: 'purpose',
        purposeId: 'ad_delivery'
      }
    ]
  }
};
</script>
```

{% endcode %}

| Configuration Key                         | Type   | Description                                                                                                                                                                                                                          |
| ----------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `preferences.categories[index].type`      | String | Type of the entity to be displayed. If you are specifying a purpose, this key should have `purpose` value.                                                                                                                           |
| `preferences.categories[index].purposeId` | String | Purpose ID to be displayed in that position. See [Vendors and purposes](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/cmp/web-sdk/consent-notice/broken-reference/README.md) for a list of available purposes. |

### Categories of purposes

Purposes having a similar functionality can be optionally grouped into categories. This could be useful for better clarity of the purposes screen.

To group purposes into categories, the `preferences.categories` configuration option in the Didomi configuration can be used:

```javascript
<script type="text/javascript">
window.didomiConfig = {
  preferences: {
    categories: [
      {
        id: 'category-id',
        type: 'category',
        name: {
          en: 'Category name'
        },
        description: {
          en: 'Category description'
        },
        children: [
          {
            type: 'purpose',
            purposeId: 'cookies'
          }
        ]
      }
    ]
  }
};
</script>
```

Purposes that are required by some vendors and that are not included in one of the specified categories will be appended to the end of the purposes list in alphabetical order so that all required purposes are displayed and that consent is correctly collected for them.

Each category has the following configuration keys:

| Configuration Key      | Type   | Description                                                                                                   |
| ---------------------- | ------ | ------------------------------------------------------------------------------------------------------------- |
| `category.id`          | String | Unique category identifier                                                                                    |
| `category.name`        | Object | An object containing language ISO code as keys and the localized category name as values                      |
| `category.description` | Object | An object containing language ISO code as keys and the localized category description as values               |
| `category.children`    | Array  | An array of purposes and/or categories which are included in the specified category                           |
| `category.type`        | String | Type of the entity to be displayed. If you are specifying the category, this key should have `category` value |

If the user has agreed to the whole category, the`preferences.clickcategoryagree` Didomi event will be dispatched. Similarly, if the user has disagreed with the whole category, the `preferences.clickcategorydisagree` Didomi event will be dispatched.

Read our [Events](/cmp/web-sdk/reference/events) section for more information:

{% content-ref url="/pages/-Lg5AbN1GiZKfQRmPpn5" %}
[Events](/cmp/web-sdk/reference/events)
{% endcontent-ref %}

## Information screen

You can embed an intermediate information screen that shows when the user clicks on "Learn More" in the consent notice. That information screen will be displayed before the Preferences screen where the user can give consent per purpose. Example:

![Information screen](/files/-LDh8mWScw5IQ5MeK_lE)

To enable the information screen with a custom message as well as a custom text for the buttons per language :

```javascript
<script type="text/javascript">
window.didomiConfig = {
  preferences: {
    information: {
      enable: true,

      content: {
        text: {
          en: 'Information in English',
          fr: 'Information en français'
        },
        learnMore: {
          en: 'Learn More',
          fr: 'En savoir plus'
        },
        agreeAndClose: {
          en: 'Agree and Close',
          fr: 'Accepter et Fermer'
        }
      }
    }
  }
};
</script>
```

There is no default text for the information screen so you must specify one or the screen will be empty.

## Vendors screen

![Vendors screen](/files/-LMZ9u9igAgrS04sh5hf)

By clicking on the `View our partners` button, you will access this screen where you can block certain vendors.

### Text

You can change the content of the popup by setting properties on `preferences.content`.

| Configuration Key                      | Description                                     |
| -------------------------------------- | ----------------------------------------------- |
| `preferences.content.textVendors`      | Main content of the popup                       |
| `preferences.content.subTextVendors`   | Text between the list of vendors and the footer |
| `preferences.content.authorizeVendors` | Authorize buttons                               |
| `preferences.content.blockVendors`     | Block buttons                                   |

## Display when consent is missing

If you want to bypass the notice and display the Preferences popup directly when consent is missing, you can set the property `preferences.showWhenConsentIsMissing` to true. When that is configured, you also need to disable the regular notice to ensure that it will not be displayed by setting `notice.enable` to false.

{% code title="" %}

```javascript
<script type="text/javascript">
window.didomiConfig = {
  notice: {
    enable: false
  },
  preferences: {
    showWhenConsentIsMissing: true
  }
};
</script>
```

{% endcode %}

## Prevent the popup from being closed when consent is missing

By default, the Preferences popup can be closed at any time, even if the user has not made a choice for some purposes. You can choose to hide the "X" icon and disallow closing the popup until the user has expressed a choice for every purpose by setting `canCloseWhenConsentIsMissing` to `false`.

{% code title="" %}

```javascript
<script type="text/javascript">
window.didomiConfig = {
  preferences: {
    canCloseWhenConsentIsMissing: true
  }
};
</script>
```

{% endcode %}

## Vendors and purposes

You must configure the vendors for which consent is collected by our consent notice and displayed in the preferences popup.

[Read our detailed section](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/cmp/web-sdk/consent-notice/broken-reference/README.md) to see how they can be configured.


# Theme

{% hint style="danger" %}
This section describes how to configure the Didomi consent notice through its programmatic API and the `window.didomiConfig` object.

Most configuration options are available through the [Didomi Console](https://console.didomi.io/) and this documentation only applies to edge cases or custom implementations that require it.
{% endhint %}

## Introduction

We have options to easily customize your notice and popups via the Didomi tag configuration. Our current implementation includes the customization of the theme color, the font and the buttons and other parts can be customized via CSS.

Our consent management flow includes 3 different screens:

1. The notice which is the first screen displayed when a user arrives on your website. It can be a banner attached to a side of the screen, a floating panel or a popup.
2. The information popup which can be enabled or disabled depending on your configuration.
3. The preferences popup that allows users to choose what purpose or vendor they want to allow.

Our theming options will change the style globally, which means that if you change the font or the color of the buttons, it will be changed on every screen. If you need more specific styling or style other parts of the workflow, you can always use your own CSS on top of ours.

## Tag configuration

We expose three attributes in the `theme` section of the Didomi tag configuration: `color`, `font` and `buttons`.

### **Color**

The `color` attribute controls the entire theme color like the popup borders and the highlighted buttons. It is used throughout the workflow UI to make it match your main brand color automatically.

The `linkColor` attribute controls the color of all the links in the banner/popup.

### **Font**

The `font` attribute determines the font used in the consent UIs, from the banner to the popups. You only need to set it once to have it applied globally.

### **Buttons**

We use two different types of buttons:

* Regular buttons (`regularButtons`): our basic button used throughout the consent workflow (Learn More, Disagree, etc.). Those buttons are grey by default.
* Highlighted buttons (`highlightButtons`): used when we want to emphasize an action. Those buttons use the theme color by default.

Here is an example of a regular button (on the left) and a highlighted button (on the right)<img src="/files/-LIM41HMcDIHkUy7Pb-G" alt="" data-size="original"> .

```javascript
<script type="text/javascript">
window.didomiConfig = {
  theme: {
    color: '#3F51B5', // Principal color used by the SDK
    linkColor: '#3F51B5',
    font: 'Arial', // Font used by the SDK
    buttons: {
      regularButtons: { // Learn more/disagree/disagree to all buttons.
        backgroundColor: '#eeeeee',
        textColor: '#999999',
        borderColor: 'rgba(34, 34, 34, 0.2)',
        borderWidth: '1px',
        borderRadius: '0px'
      },
      highlightButtons: { // Agree/save/agree to all buttons.
        backgroundColor: 'rgb(194, 39, 45)',
        textColor: '#ffffff',
        borderColor: 'rgba(194, 39, 45, 0.3)',
        borderWidth: '1px',
        borderRadius: '0px'
      }
    }
  }
};
</script>
```

## Customize with your own CSS

You can use CSS classes and IDs to go even deeper into the customization of the notice and popups. Here is an example of customization that adds a shadow to the highlighted button of the notice. If you want to override a property already used in our style, you may have to add `!important` or use a more precise selector.

```css
#didomi-host .didomi-notice-banner .didomi-buttons .didomi-button-highlight {
  box-shadow: 7px 10px 28px -12px rgba(0,0,0,0.75);
}
```

As you can see, the top-most parent selector is `#didomi-host` . All our elements live in that parent div and you should always use it as your base selector to limit your CSS to our SDK.

### Font

If you prefer to use CSS to change the font globally, you can do it.

```css
#didomi-host {
  font-family: 'Trebuchet MS' !important;
}
```

### Buttons

You can also modify the style of the buttons by using your own CSS.

```css
/* How to change all the buttons on all the screens */
#didomi-host .didomi-buttons .didomi-button {
  box-shadow: 7px 10px 12px -12px rgba(0,0,0,0.75);
}

/* How to change all the buttons for one specific screen (here the preferences popup) */
#didomi-host #didomi-consent-popup .didomi-consent-popup-preferences .didomi-buttons .didomi-button {
  box-shadow: 7px 10px 12px -12px rgba(0,0,0,0.75);
}

/* How to change the standard buttons on all the screens */
#didomi-host .didomi-buttons .didomi-button.didomi-button-standard {
  box-shadow: 7px 10px 12px -12px rgba(0,0,0,0.75);
}
```

| Sections           | Selector(s)                |
| ------------------ | -------------------------- |
| Buttons container  | `.didomi-buttons`          |
| Buttons            | `.didomi-button`           |
| Regular Button     | `.didomi-button-standard`  |
| Highlighted Button | `.didomi-button-highlight` |

### Screens Selectors

If you want to change one screen in particular, you will have to specify the selector. Here is the list of the different screens you can customize and their selectors.

| **Screens**                       | **Selector(s)**                                           |
| --------------------------------- | --------------------------------------------------------- |
| Backdrop (for popups)             | `.didomi-popup-backdrop`                                  |
| Notice (as a banner)              | `.didomi-notice-banner`                                   |
| Notice (as a popup)               | `.didomi-notice-popup`                                    |
| Information and Preferences popup | `#didomi-consent-popup`                                   |
| Content of the Information popup  | `#didomi-consent-popup .didomi-consent-popup-information` |
| Content of the Preferences popup  | `#didomi-consent-popup .didomi-consent-popup-preferences` |

### Popup

There are 3 different popups. The notice popup, the information and the preference popups.

| Sections                     | Selectors                 |
| ---------------------------- | ------------------------- |
| Exterior border of the popup | `.didomi-exterior-border` |
| Popup container              | `.didomi-popup-container` |

#### Information and preference popups only :

| Sections              | Selectors              |
| --------------------- | ---------------------- |
| Text container (body) | `.didomi-popup-body`   |
| Footer                | `.didomi-popup-footer` |

### Notice

#### Banner selectors

Don't forget to prefix those selectors with `#didomi-host .didomi-notice-banner` if you only want to change this screen.

| **Sections**         | **Selectors**         |
| -------------------- | --------------------- |
| Border of the notice | `.didomi-border`      |
| Text                 | `.didomi-notice-text` |

### Information and preferences

#### Information and preferences popup selectors

Don't forget to prefix those selectors with `#didomi-host #didomi-consent-popup` if you only want to change this screen.

| **Sections** | **Selectors**                              |
| ------------ | ------------------------------------------ |
| Header       | `.didomi-popup-header`                     |
| Header title | `.didomi-popup-header .didomi-popup-title` |

#### Information content selectors

Don't forget to prefix those selectors with `#didomi-host #didomi-consent-popup .didomi-consent-popup-information` if you only want to change this screen.

#### Preferences content selectors

Don't forget to prefix those selectors with `#didomi-host #didomi-consent-popup .didomi-consent-popup-preferences` if you only want to change this screen.

| **Sections**     | **Selectors**                      |
| ---------------- | ---------------------------------- |
| Purposes buttons | `.didomi-components-radio__option` |

{% hint style="warning" %}
Please only use those documented classes and IDs. The undocumented ones that exist in our HTML may be removed or modified and may break your style.
{% endhint %}

### Custom CSS

Custom CSS can be specified as part of the theme configuration object to further customize the look and feel of the consent notice.

You can do so by specifying the `theme.css` property in the Didomi configuration object.

The `theme.css` property is a stringified value with the CSS rules you want to apply to the consent notice:

```javascript
window.didomiConfig = {
  theme: {
    css: `
        #didomi-consent-popup .didomi-popup-header {
          text-align: center;
        }
    `,
  },
};
```

With the `theme.css` configuration, you can also specify media queries (to override the default UI for different breakpoints) and target pseudo-elements for the consent notice (e.g. `::before` and `::after` pseudo-elements).

{% hint style="warning" %}
Only use the documented classes and IDs. The undocumented ones that exist in our HTML may be removed or modified at any time and may break your style.
{% endhint %}

## Some examples

### Example 1 - Popup with shadow, black backdrop and round buttons

![Example 1 - Popup with shadow, black backdrop and round buttons](/files/-LIIbkO6C7sXgmqm_1wh)

#### CSS file

```css
#didomi-host .didomi-popup-backdrop {
  background-color: hsla(0,0%,10%,.8) !important;
}

#didomi-host .didomi-exterior-border {
  box-shadow: 7px 10px 28px -12px rgba(0,0,0,0.75);
  border: 1px solid rgba(0,0,0,0.1) !important;
}
#didomi-host .didomi-popup-container {
  border: 0 !important;
}

#didomi-host .didomi-popup-header {
  text-align: center;
}

#didomi-host .didomi-popup-title {
  width: 100%;
}

#didomi-host .didomi-buttons .didomi-button {
  box-shadow: 7px 10px 12px -12px rgba(0,0,0,0.75);
}

#didomi-host .didomi-popup-footer {
  border-top: 1px solid rgba(139,185,212,0.4);
}

#didomi-host .didomi-components-radio__option {
  border: 2px solid rgba(139,185,212,0.6) !important;
  border-radius: 5px;
  box-shadow: 0px 0px !important;
}
```

{% hint style="info" %}
We use global styles that apply to all screens in that example. Screen-specific selectors are therefore not used.
{% endhint %}

#### Tag configuration

```javascript
<script type="text/javascript">
window.didomiConfig = {
  theme: {
    buttons: {
      regularButtons: {
        backgroundColor: 'white',
        borderColor: 'rgba(0,0,0,0.1)',
        borderWidth: '1px',
        borderRadius: '10px'
      },
      highlightButtons: {
        backgroundColor: '#8BB9D4',
        textColor: 'white',
        borderColor: 'rgba(139,185,212,0.2)',
        borderWidth: '2px',
        borderRadius: '10px'
      }
    }
  }
};
</script>
```

### Example 2 - Banner notice with colored background and buttons

![](/files/-LIMvlewMw7nJrsVF6R7)

#### CSS file

```css
#didomi-host .didomi-notice-banner {
  background-color: #ECC193 !important;
  color: white !important;
  border-top: 2px solid rgba(236, 193, 147, 0.3) !important;
  box-shadow: 1px 7px 17px 3px rgba(0,0,0,0.75);
}

#didomi-host .didomi-notice-banner .didomi-notice-text {
  font-size: 14px;
  font-weight: 700;
}

#didomi-host .didomi-notice-banner .didomi-buttons .didomi-button-standard {
  padding: 8px 10px !important;
  min-width: 100px !important;
}

#didomi-host .didomi-notice-banner .didomi-buttons .didomi-button-highlight {
  text-decoration: none !important;
  min-width: 100px !important;
  padding: 8px 10px !important;
}
```

#### Tag configuration

```javascript
<script type="text/javascript">
window.didomiConfig = {
  theme: {
    font: "Trebuchet MS",
    buttons: {
      regularButtons: {
        backgroundColor: '#DA7F6D',
        textColor: 'white',
        borderWidth: '0px',
        borderRadius: '15px'
      },
      highlightButtons: {
        backgroundColor: '#FBE394',
        textColor: '#B56A44',
        borderWidth: '0px',
        borderRadius: '15px'
      }
    }
  }
};
</script>
```

{% hint style="info" %}
Note that with that configuration, the style provided to the configuration related to the font and the buttons will be global. If you only want the buttons of the banner notice to be styled, please use the CSS selectors explained above.
{% endhint %}


# AB tests

The Didomi SDK allows you to run AB tests to compare the consent rates and other metrics of two groups of populations. We support running AB tests through your preferred vendor or through the Didomi platform.

{% hint style="danger" %}
AB tests cannot be run with standard texts at the moment. Standard texts will not be displayed in your test version.
{% endhint %}

## Run AB tests with Didomi

The Didomi SDK allows you to test the performance of a variant of your configuration (notice format, content, etc.). To do so, our SDK will separate your users into two groups:

* **Control** group (A): control users will be shown your normal consent notices and the current configuration of your SDK will be applied.
* **Test** group (B): test users will be shown the variant of your SDK configuration that you want to test.

To validate whether the outcome of your AB test is positive or negative, you will observe the metrics (consent rate, bounce rate, etc.) of your **test** group and compare them with the metrics of your **control** group. If your test group performs better than your control group then your AB test will be positive and indicate that the configuration applied to your test group is more efficient than the one applied to your control group.

{% hint style="info" %}
**How about multivariate tests?**

Multivariate tests allow you to create **multiple test groups** to analyze the performance of multiple variants at once. Didomi does not support multivariate tests at the moment. Consider using an AB testing vendor to create these types of tests.
{% endhint %}

### Configuration

To setup your AB test, you need to add an `experiment` property in your `didomiConfig` variable. Keep in mind that all properties outside of that `experiment` property will be applied to your control group as usual. That is the baseline that you will be comparing your **test** group results against.

The `experiment` property allows you to configure three variables of your test:

| Property    | Description                                                                                                                                                                                                                                                                                                                                                     | Example                                                |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| `id`        | A unique ID for your test. That will be used to distinguish the results between multiple tests that you would be running over time. Use a lowercase string with no spaces and only `-` (dash) as a special character (`[a-z-]`).                                                                                                                                | `first-test`, `test-variation-1`                       |
| `size`      | The size of your **test** group as a percentage between 0 and 1. Your **control** group size will be `1 - size`. We recommend keeping this value between 0.1 (10%) and 0.5 (50%) so that you **control** group will include 50% to 90% of your users.                                                                                                           | `0.2` for a test group that includes 20% of your users |
| `config`    | The extra configuration parameters to apply to the **test** group users. The configuration parameters will be merged into your regular configuration (the one applied to your **control** group) to allow you to only test a small number of variables at once. Any configuration parameter that is valid for the SDK can be used here.                         | See below                                              |
| `startDate` | <p>Start date of the test as an ISO 8601 string. When provided, only users that are asked for consent after that start date will be included in the test.</p><p>While this is not required, it is strongly recommended to include a start date to make sure that your test and control groups only include new users that have not seen the consent UI yet.</p> | 2019-03-06T23:38:50Z                                   |

{% hint style="warning" %}
**Keep your test focused**

It is important to not test too many variations at once as you wil**l** not be able to attribute the performance results of your test group to a specific variable.

For instance, if you change both the notice content and format of your **test** group (compared to your **control** group) and see a consent rate increase of 10% in your **test** group, you will not be able to determine if the consent rate increase comes from the different notice content or format. You will only be able to conclude that changing both the notice content and format had a joint positive effect.
{% endhint %}

#### Example - Test a different format for your consent notice (banner vs pop-in)

```markup
<script type="text/javascript">
window.didomiConfig = {
  app: {
    apiKey: '<Your API Key>',
    name: 'My website',
    vendors: {      
      iab: {
        all: true
      }  
    }
  },
  notice: {
    // Users in your control group will see the consent banner at the bottom of their screen
    position: 'bottom'
  },
  experiment: {
    id: 'test-notice-format', // Unique ID for your test
    size: 0.2, // Test group will include 20% of your users
    startDate: '2019-03-06T23:38:50Z',
    config: {
      // Every property in this config object will be merged into window.didomiConfig for users in your test group
      notice: {
        // Users in your test group will see the consent popup instead of the banner
        position: 'popup'
      }
    }
  }
};
</script>
```

Keep in mind that users in your **test** group will see the default configuration for your tag PLUS the specific configuration for them (that will replace the default configuration for properties that appear in both)\
For instance, they will see all the IAB vendors and the pop-in consent notice. Users in your **control** group will see all the IAB vendors and the banner consent notice.

## Run AB tests with your preferred vendor

If you already work with an AB testing solution, you can use it to deploy different variants of the Didomi tag configuration and automatically measure the difference in consent rates.

You create, configure and analyze your AB test entirely in your AB testing solution. You will create the variants that you want to test using the standard process of your vendor and will use your testing solution to collect and analyze the result of your tests.

Example for comparing two different messages in your consent notice:

* Create an AB test with two groups: **control** and **test**
* Configure the **test** group to show a different notice message
* Add an event to count the number of clicks on the "I agree" button of the consent notice
* Use the event counter as your AB test objective

### Test complex cases

Some variants might be complicated to create with your AB testing solution. For instance, comparing notice formats (banner vs pop-in) can be complex to configure.

In that case, you can use your AB testing solution to serve two different versions of the `didomiConfig` configuration object: one specific to your **control** group and another one specific to your **test** group. With that setup, you can create variations of any option supported by the Didomi SDK without being limited by your testing solution.

### Measure and analyze your test results

You need to define and measure the metric(s) that you will use to analyze your tests results and compare the performance of your test groups. Your AB testing solution should allow you to define what metric(s) you want to use (number of clicks on the "I agree" button, number of page views with consent, etc.) and measure them for you, potentially with the help of your analytics solution.

If that is not possible or if you want to be able to have access to all the analytics provided by Didomi for your AB tests, we can setup a custom dashboard to help you track the results of your tests.\
Reach out to <support@didomi.io> for more information.


# Custom domain

A custom domain can be used for:

* Sharing consents across domains
* Serving the Web SDK and API requests from your own domain by redirecting all requests to your domain instead of the domain used by Didomi (`privacy-center.org`). This ensures that Didomi does not appear as a third-party on your websites.
* Preventing adblockers from blocking the Didomi SDK.

Once configured, a domain can be used for some or all those purposes listed above.

We offer two solutions for setting up your custom domain:

* [A delegated custom domain relying on Didomi's infrastructure](/api-and-platform/domains/domain-delegation)
* [A reverse proxy relying on your own infrastructure](broken://pages/-M9dcWO0ZnCie1tpVb8q)


# Share consents between domains

By default, the Didomi CMP uses first-party cookies to store consent information. Consent is therefore shared across all the sub-domains of the base domain where the SDK is deployed but is not shared across domains.

**Example:** If you install Didomi on `www.domain.com`, consents will be stored in a cookie on `.domain.com` and all sub-domains of `domain.com` will have access to the same consent information.\
Other domain names (`www.other-domain.com`) will NOT have access to that consent information.

With group cookies, consent is stored on a sub-domain that you own and delegate to Didomi (like `privacy.your-domain.com`) and can be shared across all your websites.

Consents will be shared only between the domains that have activated the group cookies feature with the same specific sub-domain. It allows you to have private consents between your different websites without exposing them to third-parties.

## Limits and obligations

Before enabling this feature, please keep in mind the following limits and obligations.

### Storage in cookies must be enabled

The cross-domain feature requires cookies to be enabled as a storage method. By default, Didomi already enables cookies as a storage method.

If your organization has deactivated this feature (i.e. set `cookies.storageSources.cookies` to `false` ) you will need to remove that setting and utilize the default in order to utilize the cross-domain feature.

{% hint style="info" %}
Since Didomi enables cookies as a storage method by default your organization does not need to explicitly set `cookies.storageSources.cookies` to `true`.
{% endhint %}

### User information

If you are enabling this feature, you must update your notice and popup content to correctly inform the user that their consent will be shared across multiple websites for the collected consents to be valid. Include a list of websites and legal entities that will be sharing consent.

### Third-party cookies limitations

This feature depends on browsers accepting third-party cookies. By default, more browsers are blocking the use of third-party cookies. Therefore, users browsing with default settings on Safari, Firefox, or Chrome on iOS, or users who have blocked third-party cookies, will not be able to store third-party cookies in their browser. Didomi will fall back to using first-party cookies when third-party cookies are not available.

### Switch from first-party cookies

If you are already using Didomi with first-party cookies (the default behavior) and decide to switch to third-party cookies, please be advised that all your previous consents will be lost. The consent notice will be displayed to all visitors again to recollect consent.

### Load time

Sharing consent between domains increases the load time of the SDK as it involves additional asynchronous operations for reading and writing consent from a different domain. [Read more in our FAQ.](/cmp/web-sdk/performance#how-to-optimize-the-load-time-of-the-consent-notice-and-third-party-scripts-including-advertising)

## Setup a custom domain

Configure your domain to use for sharing consents by following our [Custom domain guide](/cmp/web-sdk/custom-domain).

## Configure your consent notice

Update your SDK configuration on all the websites that need to share consent (this can be done via the Didomi Console):

```javascript
window.didomiConfig = {
  cookies: {
    group: {
      enabled: true,
      customDomain: 'privacy.your-domain.com'
    }
  }
};
```

After that setup is done, the Didomi SDK will start using `privacy.your-domain.com` for storing consent cookies. You must use the same `customDomain` configuration on all the websites that you want to share consents between.


# Share consents across devices

{% hint style="success" %}
Sharing consents across devices (i.e. cross-device consent sync) is a premium feature. Contact your Didomi representative to enable the feature for your organization.
{% endhint %}

The Didomi cross-device consent feature enables your organization to sync an end-user's consent selections across multiple devices and environments. Consent can be shared between all environments that have syncing enabled within the same organization: multiple websites, multiple apps (same or multiple devices), multiple websites and apps together, etc...

* [Prerequisites](#prerequisites)
* [Cross-device consent sync overview](#cross-device-consent-sync-overview)
* [Configure user authentication](#configure-user-authentication)
* [Enable cross-device consent sync](#enable-cross-device-consent-sync)
* [Confirmation notice](#confirmation-notice)

{% hint style="warning" %}
**Note**: Didomi does not support cross-device consent sync for AMP sites due to its s[ingle consent status limitation](/cmp/amp#amp-limitations).
{% endhint %}

***

### Prerequisites

Ensure your organization meets the following criteria before continuing:

* Premium feature cross-device consent sync is enabled for your organization's Didomi account
* Websites and apps that will share consent utilize a unique identifier to identify an individual end-user in your organization's system (e.g. email, phone number, CRM ID, etc.)

### Cross-device consent sync overview

Once cross-device consent sync is successfully configured, syncing end-user consent selections will be managed via the Didomi Consents API. For each website, device, or app where syncing is enabled and the end-user's organization user ID is available in the Didomi server:

* If the end-user is visiting the website, device, or app for the first time and a sync has not taken place, Didomi will load the previously stored end-user's consent (identified from their organization user ID) via the Consents API and apply them locally.
* If the end-user already has consent data from the sync stored locally, the local data will be updated from the server via Consents API once the time configured for the sync frequency has lapsed relative to the last completed sync
* If the sync request duration exceeds the configured timeout setting, Didomi will use the locally stored consent and will attempt a sync with Didomi servers once the window for sync frequency has elapsed.

<figure><img src="/files/9EetiHNOP62MzOHS2x9k" alt="" width="563"><figcaption></figcaption></figure>

### Configure user authentication

In order to successfully sync an end-user's consent from the Didomi server with a website, app, device, Didomi needs to be able to identify the end-user.

When an end-user is identified by your organization (e.g. via a login process or other authentication method), this unique user ID should be shared with the Didomi SDK in the `window.didomiConfig` object via the `user.organizationUserId` property. This must be set before the Didomi Web SDK is embedded onto the page.

```javascript
window.didomiConfig = {
  user: {
    organizationUserId: 'organization_user_id',
  }
};
```

{% hint style="info" %}
The `organizationUserId` shared on the website will be used in the Didomi [Consents API](/api-and-platform/consents/users). If you are accessing the end-user status or event from the API, you will need to specify the same `organizationUserId` as what is shared on the website, including any form of anonymization or hashing method in place.\
\
The `organizationUserId` must be consistent across your organization and all the other Didomi products you are using (APIs, Privacy Center, etc.).
{% endhint %}

While the `organizationUserID` value can be any string (e.g. email, phone number, etc...), Didomi recommends sending a hashed version of this value to avoid exposing any potential sensitive data on page or to Didomi.

The same unique user ID will need to be shared in other environments like mobile apps. If you are sending a hashed ID, make sure that you will be able to send exactly the same ID across all environments.

In addition to configuring the end-user's `organizationUserId`, your organization will also need to configure a hash digest.

* [Authentication with a hash digest](#authentication-with-a-hash-digest)
* [Supported hashing methods](#supported-hashing-methods)
* [Salting](#salting)
* [Information expiry](#information-expiry)
* [Hashing/encrypting rules](#hashing-rules)

#### Authentication with a hash digest

{% hint style="warning" %}
**Note**: Sending authentication with a hash digest is required to share an end-user's consent across devices.
{% endhint %}

Since the `organizationUserId` is provided in a public environment (on a webpage), we need to authenticate the value to guarantee that users cannot freely read and write consents for any `organizationUserId`.

In order to authenticate the `organizationUserId` and prove that it was authorized by the website, your organization will need to include the following hash digest in the `user` object. This digest must be computed directly by your server in an authenticated context and not on the client-side.

{% hint style="danger" %}
Using a hash digest does not guarantee the confidentiality of the `organizationUserId` passed to Didomi as it is exposed in clear text on the page.
{% endhint %}

<table><thead><tr><th width="317.5">Property</th><th>Description</th></tr></thead><tbody><tr><td><pre><code>organizationUserIdAuthDigest
</code></pre></td><td><p>Computed hash digest of the ID concatenated with a secret. Secrets can be managed through the Didomi API to obtain an actual secret and its associated ID. <a href="/pages/-M29CkuzI0FBVr2ypyzM">Click here</a> to learn more about secrets.</p><div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p><strong>Note</strong>: The hash digest is computed on the concatenation of the <code>organization_user_id</code> and the <code>secret</code>, without any extra space added. Example: <code>organization_user_idsecret</code>.</p><p>Review <a href="#hashing-rules">Didomi hashing/encrypting rules</a> for more information on hash digest.</p></div></td></tr><tr><td><pre><code>organizationUserIdAuthSid
</code></pre></td><td>ID of the secret. Secrets can be managed through the Didomi API to obtain an actual secret and its associated ID. <a href="/pages/-M29CkuzI0FBVr2ypyzM">Click here</a> to learn more about secrets.</td></tr><tr><td><pre><code>organizationUserIdAuthAlgorithm
</code></pre></td><td>ID of the hashing algorithm used to generate the hash digest. <a href="#supported-hashing-methods">Click here</a> for more information on supported hashing methods</td></tr></tbody></table>

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

```javascript
<script type="text/javascript">
window.didomiConfig = {
  user: {
    organizationUserId: 'organization_user_id',
    organizationUserIdAuthDigest: MD5('organization_user_id' + 'secret'),
    organizationUserIdAuthSid: 'secret_id',
    organizationUserIdAuthAlgorithm: 'hash-md5'
  }
};
</script>
```

{% endtab %}
{% endtabs %}

When Didomi receives a request, we will re-compute the digest with the secret and ensure that it matches the digest that your organization has provided.

#### Supported hashing methods

Didomi supports the following methods for computing a digest:

<table><thead><tr><th width="181">Algorithm</th><th width="154">ID</th><th>Description</th></tr></thead><tbody><tr><td>Hash MD5</td><td><code>hash-md5</code></td><td>Hexadecimal digest computed with the MD5 algorithm</td></tr><tr><td>Hash SHA1</td><td><code>hash-sha1</code></td><td>Hexadecimal digest computed with the SHA1 algorithm</td></tr><tr><td>Hash SHA256</td><td><code>hash-sha256</code></td><td>Hexadecimal digest computed with the SHA256 algorithm</td></tr><tr><td>HMAC SHA1</td><td><code>hmac-sha1</code></td><td>Hexadecimal representation of a HMAC computed with the SHA1 algorithm</td></tr><tr><td>HMAC SHA256</td><td><code>hmac-sha256</code></td><td>Hexadecimal representation of a HMAC computed with the SHA256 algorithm</td></tr></tbody></table>

#### Salting

Salting is the optional practice of adding a value (the "salt") to a value before computing the hash digest to increase security. If your organization utilizes salting when computing its hash digest then include the salt in `user.organizationUserIdAuthSalt`.

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

```javascript
<script type="text/javascript">
window.didomiConfig = {
  user: {
    organizationUserId: 'organization_user_id',
    organizationUserIdAuthDigest: MD5('organization_user_id' + 'secret'),
    organizationUserIdAuthSid: 'secret_id',
    organizationUserIdAuthAlgorithm: 'hash-md5',
    organizationUserIdAuthSalt: 'salt'
  }
};
</script>
```

{% endtab %}
{% endtabs %}

#### Information expiry

Authentication methods guarantee the integrity of the information sent to Didomi (i.e. the information originates from the client and cannot be modified by a third-party) but does not guarantee that the information cannot be reused.

In order to prevent the reuse of an encrypted end-user identifier, Didomi allows your organization to provide an optional expiry so that the identifier can no longer be used after a certain date. If your organization wishes to set an expiration date on an end-user identifier, include a valid Unix timestamp in `user.organizationUserIdExp`.

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

```javascript
<script type="text/javascript">
window.didomiConfig = {
  user: {
    organizationUserId: 'organization_user_id',
    organizationUserIdAuthDigest: MD5('organization_user_id' + 'secret' + 'salt' + 'expiration'),
    organizationUserIdAuthSid: 'secret_id',
    organizationUserIdAuthAlgorithm: 'hash-md5',
    organizationUserIdAuthSalt: 'salt',
    organizationUserIdExp: 1628714229
  }
};
</script>
```

{% endtab %}
{% endtabs %}

#### Hashing/encrypting rules

Review the table below for more information on hashing/encrypting rules:

<table><thead><tr><th width="188">Algorithm</th><th>Digest</th></tr></thead><tbody><tr><td>Hash algorithm</td><td><p>Computed as: <code>hash('organization_user_id' + 'secret' + 'salt' + expiration)</code></p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><code>salt</code> and <code>expiration</code> are optional values.</p></div></td></tr><tr><td>HMAC algorithm</td><td><p>Computed as <code>hmac('organization_user_id' + 'salt' + expiration, 'secret')</code><br></p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><code>salt</code> and <code>expiration</code> are optional values. The <code>secret</code> is not part of the digest although it is used in the HMAC process.</p></div></td></tr></tbody></table>

### Enable cross-device consent sync

Once the `user` object is appropriately configured, enable cross-device consent sync by setting `sync.enabled` to `true` in the `window.didomiConfig` object.

{% code overflow="wrap" %}

```javascript
<script type="text/javascript">
	window.didomiConfig = {
		user: {
			organizationUserId: 'organization_user_id',
			organizationUserIdAuthDigest: MD5('organization_user_id' + 'secret'),
			organizationUserIdAuthSid: 'secret_id',
			organizationUserIdAuthAlgorithm: 'hash-md5'
		},
		sync: {
			enabled: true
		}
	};
</script>
```

{% endcode %}

In the sections below we will cover different behaviors that your organization can configure for cross-device consent sync:

* [Frequency](#frequency-1)
* [Sync timeout](#sync-timeout)
* [Consent notice delay](#consent-notice-delay)

#### Frequency

The `sync.frequency` property enables your organization to configure how often (in seconds) the sync process will run on the website. By default, the sync process is performed every 24 hours (86,400 seconds).

<table><thead><tr><th width="104.5"></th><th width="192">Frequency</th><th>Comments</th></tr></thead><tbody><tr><td><strong>Default</strong></td><td>24 hrs (86,400 secs)</td><td>Didomi recommends leaving the frequency at 24 hrs. More frequent syncs (e.g. every 8 hours) can negatively impact the end-user experience of your website since page load times would be impacted by frequent unnecessary syncs.</td></tr><tr><td><strong>Minimum</strong></td><td>6 hrs (21,600 secs)</td><td>Any frequency interval set to lower than 6 hours will be overridden to the minimum threshold of 6 hours.</td></tr></tbody></table>

{% code overflow="wrap" %}

```javascript
<script type="text/javascript">
	window.didomiConfig = {
		user: {
			organizationUserId: 'organization_user_id',
			organizationUserIdAuthDigest: MD5('organization_user_id' + 'secret'),
			organizationUserIdAuthSid: 'secret_id',
			organizationUserIdAuthAlgorithm: 'hash-md5'
		},
		sync: {
			enabled: true,
			frequency: 86400
		}
	};
</script>
```

{% endcode %}

#### Sync timeout

The `sync.timeout` property enables your organization to configure the maximum time allowed (in milliseconds) for the syncing process to be completed. If the syncing process takes longer than the configured time then the initialization continues as if there was no data to sync.

{% hint style="warning" %}
**Note**: By default, `sync.timeout` is set to 3 seconds (3,000 milliseconds). Didomi believes it should not be necessary to increase this threshold.
{% endhint %}

{% code overflow="wrap" %}

```javascript
<script type="text/javascript">
	window.didomiConfig = {
		user: {
			organizationUserId: 'organization_user_id',
			organizationUserIdAuthDigest: MD5('organization_user_id' + 'secret'),
			organizationUserIdAuthSid: 'secret_id',
			organizationUserIdAuthAlgorithm: 'hash-md5'
		},
		sync: {
			enabled: true,
			frequency: 86400,
			timeout: 3000
		}
	};
</script>
```

{% endcode %}

#### Consent notice delay

{% hint style="warning" %}
**Note**: `sync.delayNotice` is set to `true` by default. Omitting the property will still delay the consent notice from displaying until the sync process is complete.
{% endhint %}

The `sync.delayNotice` property enables your organization to delay the consent notice from displaying until the sync process is complete. By delaying the consent notice display you can ensure that the end-user will not see a consent notice if the sync process successfully retrieves their consent selections from Didomi servers.

{% code overflow="wrap" %}

```javascript
<script type="text/javascript">
	window.didomiConfig = {
		user: {
			organizationUserId: 'organization_user_id',
			organizationUserIdAuthDigest: MD5('organization_user_id' + 'secret'),
			organizationUserIdAuthSid: 'secret_id',
			organizationUserIdAuthAlgorithm: 'hash-md5'
		},
		sync: {
			enabled: true,
			frequency: 86400,
			timeout: 3000,
			delayNotice: true
		}
	};
</script>
```

{% endcode %}

### Confirmation notice

{% hint style="info" %}
The design and interaction of the confirmation notice is developed and implemented by your organization.
{% endhint %}

A confirmation notice is an optional configuration your organization can implement to communicate to end-users that their local consent has been synced from the Didomi servers.

Refer to the tabs below for how to implement your confirmation notice for single page applications and non-single page applications, respectively:

{% tabs %}
{% tab title="SPA" %}
When implementing a confirmation notice for a single page application, your organization should look at the `statusApplied` property returned from [`syncUser()`](https://developers.didomi.io/cmp/web-sdk/reference/api#syncuser) . When `statusApplied` is `true` then the end-user's local consent was synced from Didomi servers and the confirmation should be displayed.

```javascript
const syncResult = await Didomi.syncUser();

// The end-user status actually changed from syncing
if (syncResult.statusApplied) {
  // Show your reassurance notice

  // Report the reassurance notice was shown to Didomi after dismiss
  syncResult.syncAcknowledged();
}
```

{% endtab %}

{% tab title="non-SPA" %}
When implementing a confirmation notice for a non-single page application, your organization should listen for the [`sync.ready`](https://developers.didomi.io/cmp/web-sdk/reference/events#sync.ready) event and check the `statusApplied` property. When the `statusApplied` property is `true` then the end-user's local consent was synced from Didomi servers and the confirmation notice should be shown.

{% hint style="warning" %}
**Note**: In the example below the `sync-modal` HTML and CSS is already included on the page.
{% endhint %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];

window.didomiEventListeners.push({
  event: "sync.ready",
  listener: function ({ statusApplied, syncAcknowledged, syncError }) {
    // Only proceed if status was applied from remote backend
    if (!statusApplied) {
      return;
    }

    // Optional: handle sync error case
    if (syncError) {
      console.error("Didomi sync error:", syncError);
    }

    // Show modal; you should use your own HTML/CSS elements
    var modal = document.getElementById("sync-modal");
    var closeBtn = document.getElementById("sync-modal-close");
    if (!modal || !closeBtn) {
      console.warn("Sync modal elements not found");
      // Still acknowledge to avoid blocking tracking
      syncAcknowledged();
      return;
    }

    modal.style.display = "block";

    // When user confirms, hide modal and acknowledge sync
    var onClose = function () {
      modal.style.display = "none";
      closeBtn.removeEventListener("click", onClose);
      // Notify Didomi that the sync has been communicated to the user
      var result = syncAcknowledged();
      console.log("syncAcknowledged result:", result);
    };

    closeBtn.addEventListener("click", onClose);
  },
});
```

{% endtab %}
{% endtabs %}


# Pass user choices in query string

It's possible to pass user choices through query-string parameters, allowing the sharing of information across different pages or domains.

Here's a high-level overview of how this is done:

* Generate a JSON-encoded format of the user choices.
* Append the URL-encoded JSON user choices to a link on the page.
* Configure the Didomi Web SDK to retrieve the user choices from the URL.

When passing user choices from one page to another in a query string, the purposes and vendors configured for the receiving page must be a subset of the purposes and vendors configured for the origin page that is collecting user choices. This will ensure that the receiver page gets all the user choices it requires and it will not need to re-collect user choices and show a consent notice again.

## Setup

This section will guide you on how to set up an origin page (where users' choices are collected) and a receiver page (where these choices are read from the query-string parameters).

<figure><img src="/files/8RtVvtwXSZeb9pP2td9Q" alt="Sequence diagram showing flow of data between origin and receiver page when passing purposes and vendors from one to the other"><figcaption></figcaption></figure>

### Step 1 - Creation of the query-string parameter

On the origin page, encode the subset of consent values you need to pass in JSON format:

```javascript
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) {
  // Build the value for the query string parameter with a subset of the consent values
  const userStatusForQueryString = encodeURIComponent(
    JSON.stringify({
      purposes: {
        consent: {
          enabled: ["cookies", "select_basic_ads"],
          disabled: [],
        },
        legitimate_interest: { enabled: [], disabled: [] },
      },
      vendors: {
        consent: {
          enabled: ["google", "c:googleana-4TXnJigR"], // SDK ID
          disabled: [],
        },
        legitimate_interest: { enabled: [], disabled: [] },
      },
    }),
  );
});
```

The above code needs to run after the SDK is ready which is done by using the [`window.didomiOnReady` array](https://developers.didomi.io/cmp/web-sdk/reference/api#didomi-ready).

### Step 2 - Append the query-string parameter to the URL of the receiver page

Append the `userStatusForQueryString` variable created in step 1 to the receiver page's URL in a query-string parameter named `didomiConfig.user.externalConsent.value`.

For instance, if your receiver page URL is `https://receiver.com/page.html`, the updated URL should appear like `https://receiver.com/page.html?didomiConfig.user.externalConsent.value=%7B...%7D`.

### Step 3 - Configure the Didomi Web SDK on the receiver page

For the Web SDK to read user choices from the query string, it must be appropriately configured since this behavior is disabled by default.

One way to do this is via the [Didomi Console](https://console.didomi.io/). Update the custom JSON of the consent notice embedded on the receiver page:

```json
{
  "user": {
    "externalConsent": {
      "enabled": true
    }
  }
}
```

Alternatively, you can configure this setting directly on your receiver page by assigning `window.didomiConfig`:

```js
window.didomiConfig = {
  "user": {
    "externalConsent": {
      "enabled": true
    }
  }
};
```


# Reference

This section is a comprehensive reference of the methods and events exposed by the SDK and that you can leverage in your application:

* [API](/cmp/web-sdk/reference/api)
* [Events](/cmp/web-sdk/reference/events)


# API

## Usage

The Didomi Web SDK exposes a complete API on the page via JavaScript for interacting with the Didomi platform. This allows your scripts to programmatically interact with the Didomi SDK. You can check the user consent status, register consents that you would collect yourself, and show/hide the Didomi UI.

### Didomi ready

The API is exposed on the `window.Didomi` object. All calls to the Didomi API (except for the standard IAB `__cmp` function) must be enclosed within a `window.didomiOnReady` callback to ensure that the SDK is ready before calling it:

{% tabs %}
{% tab title="Plain Javascript" %}

```javascript
<script type="text/javascript">
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function (Didomi) { 
    // Call other functions on the SDK
});
</script>
```

{% endtab %}

{% tab title="React" %}

```javascript
onDidomiReady(didomi) {
  console.log('Didomi Ready');
  // Call other functions on the SDK
}

...

<DidomiSDK
    ...
    onReady={this.onDidomiReady.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

The `window.didomiOnReady` callbacks are called after the SDK is initialized and has loaded its configuration.

{% hint style="warning" %}
Setting `window.didomiConfig` in a `window.didomiOnReady` callback has no effect as the SDK is already initialized at that point. `window.didomiConfig` must be set at the root of the page and outside of any callback.
{% endhint %}

### postMessage API

If your JavaScript is not directly present on the page where the Didomi Web SDK is embedded but is present within an iframe on that page, you can communicate with the Didomi Web SDK through the `postMessage` API of the browser.

#### Available functions

Currently only `getCurrentUserStatus` is exposed via this API to allow reading the consent status of the user. To better understand its usage, you can refer to its [definition](#getcurrentuserstatus).

#### Messages structure

The Didomi API is exposed with the same structure as the [IAB CMP API](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/CMP%20JS%20API%20v1.1%20Final.md#without-safeframes-using-postmessage-).

The message to send should have the below form where:

* `command` is the name of the function on the `window.Didomi` object to call
* `parameter` is an array of parameters passed to the function called on the `window.Didomi` object
* `callId` is a unique value that will be sent back with the response from Didomi, allowing you to identify what call the response is for

```javascript
window.parent.postMessage({
  __cmpCall: 
    {
      command: "*command*", 
      parameter: [param1, param2, ...], 
      callId: *uniqueId*
    }
}, "*");
```

The Didomi Web SDK will send back the message below to your frame with the `postMessage` API containing a response for your command where:

* `returnValue` is the value returned by the API function called
* `success` is a boolean flag indicating whether the call was successful or not
* `callId` is the unique value provided as `callId` in your original message

```javascript
{
  __cmpReturn: 
    {
      returnValue: *returnValue*, 
      success: *boolean*, 
      callId: *uniqueId*
    }
}
```

#### Usage example

Here is a complete example of how to call one of the available functions of the postMessage API (`getCurrentUserStatus`) and collect its response:

```javascript
window.addEventListener(
  "message",
  function (event) {
    try {
      var data = typeof event.data === "string" ? JSON.parse(event.data) : event.data;

      if (data && data.__cmpReturn) {
        // data.__cmpReturn contains the response from the CMP
        if (data.__cmpReturn.callId === "get-current-user-status") {
          // This is the response to our call for getting the user status
          // The status is in data.__cmpReturn.returnValue
          // Do something
        }
      }
    } catch (e) {
      // An error happened when decoding the message data
      // Most likely, the message wasn't related to the CMP so do nothing
    }
  },
  false
);

window.parent.postMessage(
  {
    __cmpCall: {
      command: "getCurrentUserStatus",
      parameter: [],
      callId: "get-current-user-status",
    },
  },
  "*",
);
```

#### Determining the frame containing the Didomi CMP

The frame to send the `postMessage` to can be determined by the ancestor with a `.frames["__tcfapiLocator"]` child iframe present.

If your code runs in a direct iframe of the page containing the `window.Didomi` object then you can simply use window\.parent as the reference to send messages to.

If your code might run multiple levels removed from the frame containing the `window.Didomi` object, you can search for the correct frame to send a message to with the following code:

```javascript
var f = window;
var cmpFrame;

while (!cmpFrame) {
  try {
    if (f.frames["__tcfapiLocator"]) cmpFrame = f;
  } catch (e) {}

  if (f === window.top) break;

  f = f.parent;
}
```

***

## Didomi Consent String (DCS)

The Didomi Consent String (DCS) - `didomi_dcs` - is a binary format that replaces the traditional `didomi_token`, typically stored in cookies or local storage. [Click here](/cmp/didomi-consent-string) for more information.

{% hint style="warning" %}
**Note**: For consent notices utilizing a GDPR regulation with the IAB TCF framework, the TC String remains the source of truth and the Didomi Web SDK will work with both strings to create a unified view of consent choices that are reflected in the public API functions for the SDK.
{% endhint %}

The Didomi Consent String stores end-user choices for custom and Google ATP vendors, and custom and global purposes across all regulations. These vendors and purposes are assigned numeric IDs that are encoded in the Didomi Consent String and are used to identify the vendor or purpose, respectively.

Each time a notice is published, Didomi generates the numeric IDs for these vendors and purposes contained in the consent notice (if they do not already have numeric IDs). Numeric IDs can be accessed with the following API functions:

### getVendorNumericId()

Retrieve the numeric ID of a custom or Google ATP vendor for a consent notice.

**Parameters**

<table><thead><tr><th width="163">Name</th><th width="121">Type</th><th>Description</th></tr></thead><tbody><tr><td>Vendor SDK ID</td><td><code>string</code></td><td>The SDK ID belonging to the vendor for which you are retrieving the numeric ID</td></tr></tbody></table>

**Returns**

Numeric ID of the vendor.

**Example**

<details>

<summary><code>Didomi.getVendorNumericId("c:mycompany-AbCD1234")</code></summary>

```javascript
40512
```

</details>

### getVendorByNumericId()

Retrieve the vendor object for the specified numeric ID

**Parameters**

<table><thead><tr><th width="163">Name</th><th width="121">Type</th><th>Description</th></tr></thead><tbody><tr><td>Vendor numeric ID</td><td><code>number</code></td><td>The numeric ID belonging to the vendor for which you are retrieving the vendor object</td></tr></tbody></table>

**Returns**

Properties returned for a vendor object dependent on vendor class and declarations.

<table><thead><tr><th width="230">Property</th><th width="174">Data Type</th><th>Description</th></tr></thead><tbody><tr><td>didomiId</td><td><code>string</code></td><td>Didomi assigned vendor ID</td></tr><tr><td>id</td><td><code>string</code></td><td>Didomi SDK ID</td></tr><tr><td>namespace</td><td><code>string</code></td><td>Defines the vendor class</td></tr><tr><td>purposeIds</td><td><code>array</code></td><td>Opt-in purposes declared by a custom vendor (requires end-user consent)</td></tr><tr><td>deviceStorageDisclosureUrl</td><td><code>string</code></td><td>URL disclosing details for web or app storage</td></tr><tr><td>cookieMaxAgeSeconds</td><td><code>number</code></td><td>The longest lifespan of a cookie (in seconds)</td></tr><tr><td>lang_urls</td><td><code>array</code></td><td>Url objects representing language, policy url and legitimate interest url</td></tr><tr><td>name</td><td><code>string</code></td><td>Name of the vendor</td></tr><tr><td>namespaces</td><td><code>object</code></td><td><p>Can contain:</p><ul><li>Namespace objects with additional IDs for the vendor</li><li><code>num</code>: Didomi Consent String encoding/decoding numeric ID</li></ul></td></tr><tr><td>policyUrl</td><td><code>string</code></td><td>URL of the vendor's privacy policy</td></tr><tr><td>type</td><td><code>string</code></td><td>Whether vendor is 1st_party or 3rd_party</td></tr><tr><td>usesNonCookieAccess</td><td><code>boolean</code></td><td><p>Indicates the vendor’s use of non-cookie storage and access to information already stored on an end-user’s device.</p><ul><li><strong>True</strong>: non-cookie access is used.</li><li><strong>False:</strong> non-cookie storage and access to information already stored on an end-user's device is not used</li></ul></td></tr></tbody></table>

**Example**

<details>

<summary><code>Didomi.getVendorByNumericId(40512)</code></summary>

```javascript
{
    didomiId: "tomgccvvv-1234Cm3G",
    id: "c:tomgccvvv-MXUaCm3G",
    lang_urls: [],
    legIntPurposeIds: ['market_research', 'improve_products'],
    name: "Custom Vendor Example",
    namespace: "custom",
    namespaces: {
        num: 12345
    },
    policyUrl: "https://demoprivacypolicy.com",
    purposeIds: ["advertising", "select_basic_ads", "create_ads_profile"],
    type: "3rd_party",
    usesNonCookieAccess: true
}
```

</details>

### getPurposeNumericId()

Retrieve the numeric ID of a custom or global purpose for a consent notice.

**Parameters**

<table><thead><tr><th width="163">Name</th><th width="121">Type</th><th>Description</th></tr></thead><tbody><tr><td>Purpose numeric ID</td><td><code>string</code></td><td>The SDK ID belonging to the purpose for which you are retrieving the numeric ID</td></tr></tbody></table>

**Returns**

Numeric ID of the purpose

**Example**

<details>

<summary><code>Didomi.getPurposeNumericId("analytics_tracking")</code></summary>

```javascript
16819
```

</details>

### getPurposeByNumericId()

Retrieve the purpose object for the specified numeric ID

**Parameters**

<table><thead><tr><th width="163">Name</th><th width="121">Type</th><th>Description</th></tr></thead><tbody><tr><td>Purpose SDK ID</td><td><code>number</code></td><td>The numeric ID belonging to the purpose for which you are retrieving the purpose object</td></tr></tbody></table>

**Returns**

<table><thead><tr><th width="180">Property</th><th width="162">Data Type</th><th>Description</th></tr></thead><tbody><tr><td>description</td><td><code>object</code></td><td>Translations of the purpose description</td></tr><tr><td>id</td><td><code>string</code></td><td>Didomi SDK ID</td></tr><tr><td>name</td><td><code>object</code></td><td>Translations of the purpose name</td></tr><tr><td>namespace</td><td><code>string</code></td><td>Defines the purpose class</td></tr><tr><td>namespaces</td><td><code>object</code></td><td><p>Can contain:</p><ul><li>Namespace objects with additional IDs for the purpose</li><li><code>num</code>: Didomi Consent String encoding/decoding numeric ID</li></ul></td></tr></tbody></table>

**Example**

<details>

<summary><code>Didomi.getPurposeByNumericId(16819)</code></summary>

```javascript
{
  description: {
    en: "Marketing communication delivered to end-user",
    fr: "Communication marketing délivrée à l'utilisateur final"
  },
  id: "marketing-kKRJyAND",
  name: {
    en: "Marketing communication",
    fr: "Communication marketing"
  },
  namespace: "custom",
  namespaces: {
    num: 16951
  }
}
```

</details>

***

## Notice config

### getExperiment()

Get the currently configured [AB test (experiment)](/cmp/web-sdk/ab-tests) and the user information for that test.

**Parameters**

No parameter.

**Returns**

An object with the following properties:

| Name      | Type     | Description                                                                                                                                                                                                                                                      |
| --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id        | `string` | ID of the experiment as configured in your tag                                                                                                                                                                                                                   |
| group     | `string` | <p>Group that the user is assigned to for the experiment</p><p><code>control</code> if the user is part of the control group</p><p><code>test</code> if the user is part of the test group</p><p><code>null</code> if the user is not part of the experiment</p> |
| size      | `number` | Size of the test group (number between 0 and 1)                                                                                                                                                                                                                  |
| startDate | `string` | Start date of the test as ISO 8601 with millisecond precision                                                                                                                                                                                                    |

**Example**

```javascript
{
    "id": "experiment-id",
    "group": "control",
    "size": 0.1,
    "startDate": "2019-03-06T23:38:50.000Z"
}
```

### isRegulationApplied(regulation)

Check if a given regulation applies to the current user.

**Parameters**

| Name       | Type     | Description                                                        |
| ---------- | -------- | ------------------------------------------------------------------ |
| regulation | `string` | <p><code>gdpr</code> for GDPR</p><p><code>ccpa</code> for CCPA</p> |

**Returns**

A `boolean` indicating whether the user is subject to the regulation and support for the regulation is enabled for the website.

**Example**

```javascript
if (Didomi.isRegulationApplied('gdpr')) {
  // The user is subject to GDPR, do something
}

if (Didomi.isRegulationApplied('ccpa')) {
  // the user is subject to CCPA, do something
}
```

### navigate(button)

Simulate a user input by indicating to the SDK that the user has pressed a button on an input device like a keyboard or a TV remote control. This function is usually called when mapping TV remote control inputs to the Didomi SDK.

This function is only available if the TV mode of the SDK is enabled by adding the following `didomiConfig` to your page:

```javascript
window.didomiConfig = {
  mode: 'tv' // Enable TV mode
};
```

{% hint style="info" %}
`window.didomiConfig` must be set outside of any callback like `window.didomiOnReady` to be effective.
{% endhint %}

If no UI view is displayed from the Didomi SDK (notice, purposes, or vendors), this function has no effect and will log an error message that can be ignored.

**Parameters**

| **Name** | Type     | Description                                                                                      |
| -------- | -------- | ------------------------------------------------------------------------------------------------ |
| button   | `string` | The button that was pressed by the user. See below for the acceptable values for this parameter. |

The `button` parameter can take one of the following values:

| Value     | Description                                                                                                                                                                                                                                                              |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `confirm` | When the user presses a confirmation button (like OK or Enter). This input validates the user choice when pressed on UI buttons like Agree or Disagree.                                                                                                                  |
| `cancel`  | When the user presses a cancellation button (like Return or Exit). This input cancels the current action and, usually, closes the current UI view.                                                                                                                       |
| `up`      | When the user presses a button to move up (like an Up arrow). This input moves the focus to the closest action button located above the current focused element. If no such input exists, the focus is moved to the last element of the current UI view.                 |
| `right`   | When the user presses a button to move right (like a Right arrow). This input moves the focus to the closest action button located to the right of the current focused element. If no such input exists, the focus is moved to the next element of the current UI view.  |
| `down`    | When the user presses a button to move down (like a Down arrow). This input moves the focus to the closest action button located below the current focused element. If no such input exists, the focus is moved to the first element of the current UI view.             |
| `left`    | When the user presses a button to move left (like a Left arrow). This input moves the focus to the closest action button located to the left of the current focused element. If no such input exists, the focus is moved to the previous element of the current UI view. |

**Returns**

No return value.

**Example**

```javascript
Didomi.navigate('down');
Didomi.navigate('confirm');
```

### notice.isVisible()

Check if the consent notice is currently displayed.

**Parameters**

No parameter.

**Returns**

`Boolean`

**Example**

```javascript
Didomi.notice.isVisible();
```

### preferences.show(view)

Show the preferences manager. This can be used to allow the user to update their consent choices after the notice has been closed. We suggest adding a link with this function call somewhere on your website.

**Parameters**

| Name | Type     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ---- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| view | `string` | <p>The view you want to open.</p><p>Possible options for GDPR: <code>information, purposes</code> and <code>vendors</code>. (<code>information</code> will only work if you <a href="/pages/-LDh8hfA2ctE-QMXVkkY#information-screen">enabled the information view</a>).<br>For CCPA, the Do Not Sell view is always open.<br></p><p>This parameter is optional. If it is not provided, it will display the <code>purposes</code> view or the <code>information</code> view if information is enabled for GDPR.</p> |

**Returns**

Nothing

**Example**

```javascript
Didomi.preferences.show('purposes');
```

***

## User status

### addVendorStatusListener

#### Definition

Listens to the user’s status for a given vendor and returns a callback when the status changes.

#### Parameters

| Parameter | Type       | Description                                                                                                                                                                                   |
| --------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Vendor ID | `string`   | <ul><li>The ID of the vendor for which the changes will be tracked by the function.</li><li>This ID must be the Didomi API ID, with no prefixes (for example: <code>google</code>).</li></ul> |
| callback  | `function` | Callback that will be executed whenever changes are detected on the specified vendor.                                                                                                         |

#### **Returns**

Numeric value indicating the index position of the listener (zero-based indexing) in the list of registered listeners.

#### Example

```javascript
Didomi.addVendorStatusListener("google",(status) => console.log("Google: listener 1: status", status))
```

### clearUser()

Clear the user configuration details set via `setUser` or `window.didomiConfig.user` in a single-page application. This function does not clear the local user status (use `reset()` for that).

{% hint style="info" %}
If your website is not a single-page application, do not use this function and stop setting the user configuration details via `window.didomiConfig.user` on page load instead.
{% endhint %}

**Parameters**

No parameter.

**Returns**

`Promise<void>`

**Example**

```javascript
await Didomi.clearUser();
```

### getCurrentUserStatus()

#### Definition

Exposes the user status for the current regulation that applies.

#### Parameters

No parameters.

#### Returns

The user status containing the computed global status for Vendors and purposes:

* A vendor's global status is enabled, if and only if:
  * the vendor is enabled directly in the vendors layer in all legal basis
  * **AND** all its related purposes are enabled or essential.
* A purpose's global status is enabled in one of the two conditions:
  * the purpose is enabled for all the legal basis that it is configured for.
  * **OR** when the purpose is essential.

| Parameter       | Type     | Description                                                                                                                                                                                                                                                                                              |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendors         | `object` | <ul><li>Object that maps the ID of a vendor to an object representing its status.</li><li>Vendors with undefined user status are included in the response with <code>enabled: false.</code></li><li>Vendors with ONLY essential purposes are automatically set with <code>enabled: true</code></li></ul> |
| purposes        | `object` | <ul><li>Object that maps the ID of a purpose to an object representing its status.</li><li>Purposes with undefined user status are included in the response with <code>enabled: false.</code></li><li>Essential purposes are automatically set with <code>enabled: true</code></li></ul>                 |
| regulation      | `string` | <ul><li>Representation of the current regulation as a <code>Regulation</code> enum value, such as <code>GDPR</code>, <code>CCPA</code>, <code>CPRA</code>, or <code>NONE</code>.</li><li>Note that some regulations present as enum values are not available yet.</li></ul>                              |
| user\_id        | `string` | Didomi user id.                                                                                                                                                                                                                                                                                          |
| created         | `string` | User choices creation date.                                                                                                                                                                                                                                                                              |
| updated         | `string` | User choices update date.                                                                                                                                                                                                                                                                                |
| consent\_string | `string` | TCF consent as string                                                                                                                                                                                                                                                                                    |
| gpp\_string     | `string` | GPP string                                                                                                                                                                                                                                                                                               |
| addtl\_consent  | `string` | Additional consent.                                                                                                                                                                                                                                                                                      |

#### Example

```javascript
Didomi.getCurrentUserStatus();
```

### getRequiredPurposeIds()

Get the list of purpose IDs that are configured for the consent notice and that consent is collected for.

**Parameters**

No parameter.

**Returns**

An array of purpose IDs.

**Example**

```javascript
// Returns ['cookies']
Didomi.getRequiredPurposeIds();
```

### getRequiredVendors()

Get list of vendors that are configured for the consent notice for which consent is collected.

**Parameters**

<table><thead><tr><th width="229">Parameter</th><th width="176">Data Type</th><th>Description</th></tr></thead><tbody><tr><td>namespace</td><td><code>string</code></td><td>Filter the result by vendor class (e.g. <code>custom</code> | <code>didomi</code> | <code>iab</code> )</td></tr></tbody></table>

**Returns**

An array of vendor objects. Properties returned for each vendor object dependent on vendor class and declarations.

<table><thead><tr><th width="230">Property</th><th width="174">Data Type</th><th>Description</th></tr></thead><tbody><tr><td>didomiId</td><td><code>string</code></td><td>Didomi assigned vendor ID</td></tr><tr><td>featureIds</td><td><code>array</code></td><td>IAB features declared by the vendor</td></tr><tr><td>flexiblePurposeIds</td><td><code>array</code></td><td>Purpose IDs where vendor has registered flexible legal bases (consent or legitimate interest) with the IAB</td></tr><tr><td>id</td><td><code>number | string</code></td><td>IAB assigned ID | Didomi SDK ID</td></tr><tr><td>legIntPurposeIds</td><td><code>array</code></td><td>Opt-out purposes declared by a vendor (based on legitimate interest)</td></tr><tr><td>namespace</td><td><code>string</code></td><td>Defines the vendor class</td></tr><tr><td>purposeIds</td><td><code>array</code></td><td>Opt-in purposes declared by a custom vendor (requires end-user consent)</td></tr><tr><td>specialFeatureIds</td><td><code>array</code></td><td>IAB special features declared by a vendor</td></tr><tr><td>specialPurposeIds</td><td><code>array</code></td><td>IAB special purposes declared by a vendor</td></tr><tr><td>tmpDeletedDate</td><td><code>undefined | string</code></td><td>Vendor is considered deleted after this date/time</td></tr><tr><td>deviceStorageDisclosureUrl</td><td><code>string</code></td><td>URL disclosing details for web or app storage</td></tr><tr><td>cookieMaxAgeSeconds</td><td><code>number</code></td><td>The longest lifespan of a cookie (in seconds)</td></tr><tr><td>lang_urls</td><td><code>array</code></td><td>Url objects representing language, policy url and legitimate interest url</td></tr><tr><td>name</td><td><code>string</code></td><td>Name of the vendor</td></tr><tr><td>namespaces</td><td><code>object</code></td><td><p>Can contain:</p><ul><li>Namespace objects with additional IDs for the vendor</li><li><code>num</code>: Didomi Consent String encoding/decoding numeric ID</li></ul></td></tr><tr><td>policyUrl</td><td><code>string</code></td><td>URL of the vendor's privacy policy</td></tr><tr><td>type</td><td><code>string</code></td><td>Whether vendor is 1st_party or 3rd_party</td></tr><tr><td>usesNonCookieAccess</td><td><code>boolean</code></td><td><p>Indicates the vendor’s use of non-cookie storage and access to information already stored on an end-user’s device.</p><ul><li><strong>True</strong>: non-cookie access is used.</li><li><strong>False:</strong> non-cookie storage and access to information already stored on a end-user's device is not used</li></ul></td></tr></tbody></table>

**Example**

<details>

<summary><code>Didomi.getRequiredVendors();</code></summary>

```javascript
[
    {
        didomiId: "tomgdprv-1234Cm3G",
        id: "c:tomgdprv-MXUaCm3G",
        lang_urls: [],
        legIntPurposeIds: ["analytics_tracking"],
        name: "Custom Vendor Example",
        namespace: "custom",
        namespaces: {
            num: 12345
        },
        policyUrl: "https://demoprivacypolicy.com",
        purposeIds: ["advertising", "select_basic_ads", "create_ads_profile"],
        type: "3rd_party",
        usesNonCookieAccess: true
    }
]
```

</details>

### isUserStatusPartial()

This function assesses whether the user has made choices regarding all the vendors and data processing tasks specified by the regulation. It returns `true` if there are any vendors or data processing activities for which the user has yet to express a preference.

Requires SDK to be initialized.

**Parameters**

No parameter.

**Returns**

`Boolean`

\
The function returns `true` when the following conditions are all met:

1. A relevant regulation applies to the current user, meaning the regulation is not classified as `none`.
2. There is at least one vendor configured. Without any configured vendors, the function defaults to `false` since there are no statuses to evaluate.
3. There is a lack of user status for certain vendors or for specific purposes.

In all other scenarios, the function will return `false`.

For example, when the regulation is set to `none`, indicating that no specific regulation is applicable to the end-user, the function will yield `false`.

An important edge case to consider is when a new vendor is introduced to the system and their status has not yet been collected. In such instances, the function will return `true` until the user updates their preferences through the notice banner.

**Example**

```javascript
Didomi.isUserStatusPartial();
```

### openCurrentUserStatusTransaction

Create an instance of the `CurrentUserStatusTransaction` object.

This object provides mechanisms to stage updates to the user status regarding purposes and vendors, allowing for batch operations.

Updates made through its methods are queued and applied simultaneously to the user status only once the `commit` method of the returned object is called.

Additional notes:

* The status of vendors and purposes whose IDs are not specified through the methods provided by `CurrentUserStatusTransaction` are kept unchanged.
* Essential purposes are always set to enabled and can’t be updated by the methods provided by `CurrentUserStatusTransaction`.
* When the regulation applied for a user is `none`, the methods provided by `CurrentUserStatusTransaction` should not update the status of any vendor or purpose which will always remain as enabled. When the `commit` method is called it will return `false`.
* If the IDs that are passed through the methods provided by `CurrentUserStatusTransaction` don’t correspond to vendors or purposes required by the Notice Config, they will be ignored.

#### Parameters

No parameter.

**Returns**

An instance of the `CurrentUserStatusTransaction` object.

<table><thead><tr><th width="207">Method</th><th width="233">Parameters</th><th>Returns</th><th>Description</th></tr></thead><tbody><tr><td><code>enablePurpose</code></td><td><code>id</code> (<code>string</code>): ID of the purpose to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single purpose based on its ID.</td></tr><tr><td><code>enablePurposes</code></td><td><code>ids</code> ([<code>string]</code>): IDs of the purposes to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple purposes based on their IDs.</td></tr><tr><td><code>disablePurpose</code></td><td><code>id</code> (<code>string</code>): ID of the purpose to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single purpose based on its ID.</td></tr><tr><td><code>disablePurposes</code></td><td><code>ids</code> ([<code>string]</code>): IDs of the purposes to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple purposes based on their IDs.</td></tr><tr><td><code>enableVendor</code></td><td><code>id</code> (<code>string</code>): Didomi ID of the vendor to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single vendor based on its Didomi ID.</td></tr><tr><td><code>enableVendors</code></td><td><code>ids</code> ([<code>string]</code>): Didomi IDs of the vendors to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>disableVendor</code></td><td><code>id</code> (<code>string</code>): Didomi ID of the vendor to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single vendor based on its Didomi ID.</td></tr><tr><td><code>disableVendors</code></td><td><code>ids</code> ([<code>string]</code>): Didomi IDs of the vendors to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>commit</code></td><td>No parameters.</td><td><code>true</code> if user status has been updated, <code>false</code> otherwise.</td><td>Commit the changes that have been made through other methods.</td></tr></tbody></table>

#### Examples

```javascript
const transaction = didomi.openCurrentUserStatusTransaction();

// enable a purpose
transaction.enablePurpose("cookies");
// enable purposes
transaction.enablePurposes(["cookies", "analytics"]);
// disable a purpose
transaction.disablePurpose("analytics");
// disable purposes
transaction.disablePurposes(["cookies", "analytics"]);
// enable a vendor
transaction.enableVendor("vendor-1");
// enable vendors
transaction.enableVendors(["vendor-1", "vendor-2"]);
// disable a vendor
transaction.disableVendor("vendor-1");
// disable vendors
transaction.disableVendors(["vendor-1", "vendor-1"]);

// chain multiple calls
transaction.enablePurpose("cookies").disablePurpose("analytics");

// save user choices
transaction.commit();
```

#### Error handling

Invalid purposes or vendors will be ignored, errors will be logged in the browser's console

<pre class="language-javascript"><code class="lang-javascript">const transaction = Didomi.openCurrentUserStatusTransaction();
// enable purposes
transaction.enablePurposes(['cookies', 'invalid_ID']);
transaction.commit();

// Console output:
<strong>'Didomi SDK - disablePurpose ignored due to invalid purpose: invalid_ID'
</strong>true
</code></pre>

### reset()

Reset all the consent information for the current user and assign a new user ID. This will remove all cookies created by Didomi and will trigger re-collection of consent. The consent notice will be displayed again.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

```javascript
Didomi.reset();
```

### setUser(userConfiguration)

Update the user configuration details in a single-page application. You can provide the user configuration options as part of the `userConfiguration` parameter.

{% hint style="info" %}
If your website is not a single-page application, do not call this function and set the user configuration details via `window.didomiConfig.user` on page load instead.
{% endhint %}

{% hint style="info" %}
The `setUser` function will update all the provided properties and set the others to `undefined`. If a property is omitted, it will be set to `undefined`.
{% endhint %}

**Parameters**

| Name              | Type     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ----------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| userConfiguration | `object` | <p>An object containing any of the following properties:<br><br><code>organizationUserId</code>: Organization User ID to associate with the user<br><code>organizationUserIdAuthAlgorithm</code>: Algorithm used for computing the digest<br><code>organizationUserIdAuthSid</code>: ID of the secret used for computing the digest<br><code>organizationUserIdAuthSalt</code>: Salt used for computing the digest<br><code>organizationUserIdAuthDigest</code>: Digest of the organization user ID and secret<br><code>organizationUserIdExp</code>: Unix timestamp<br><code>organizationUserIdIv</code>: If encryption is used and an IV was used for encrypting the message</p> |

**Returns**

Nothing

**Example**

```javascript
Didomi.setUser({ organizationUserId: 'organizationUserID' });
```

### setUserAgreeToAll()

Report that the user has enabled consents and legitimate interests for all purposes and vendors configured for your website.

This function will log the user choice on our platform and close the notice.

{% hint style="info" %}
Consent statuses for essential purposes are not stored as they are designed to always be enabled and are injected at read time
{% endhint %}

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

```javascript
Didomi.setUserAgreeToAll();
```

### setUserDisagreeToAll()

Report that the user has disabled consents and legitimate interests for all purposes and vendors configured for your website.

This function will log the user choice on our platform and close the notice.

{% hint style="info" %}
Consent statuses for essential purposes are not stored as they are designed to always be enabled and are injected at read time
{% endhint %}

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

```javascript
Didomi.setUserDisagreeToAll();
```

### setCurrentUserStatus(parameters)

#### Definition

Set the user status for purposes and vendors. This function will trigger events and API calls every time it is called (and the user status changes) so make sure to push all user choices at once and not one by one.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

#### Parameters

Add the desired global status for each vendor and each purpose:

* the vendor status specified in this function will be reflected on the vendor’s layer.
  * vendor enabled : true → means the vendor is enabled in all the legal basis that this vendor uses.
  * vendor enabled : false → means the vendor is disabled in all the legal basis that this vendor uses
* the purposes status specified in this function will be reflected on the preferences layer.
  * purpose enabled : true → means the purpose is enabled in all the legal basis in which it’s defined.
  * purpose enabled : false → means the purpose is disabled in all the legal basis in which it’s defined.

#### Returns

`boolean`

`true` if the user's choices have changed (i.e. the user had made different choices before this function got called).

#### Example

```javascript
Didomi.setCurrentUserStatus({
  purposes: {
    purpose1: {
      id: "purpose1",
      enabled: true,
    },
    purpose2: {
      id: "purpose2",
      enabled: false
    }
  },
  vendors: {
    vendor1: {
      id: "vendor1",
      enabled: true
    },
    vendor2: {
      id: "vendor2",
      enabled: false
    }
  }
});
```

### setWidgetLocale()

{% hint style="info" %}
This function is only supported by [Privacy widgets](/api-and-platform/widgets/privacy-widgets).
{% endhint %}

#### **Definition**

Set the language for a widget.

#### **Parameters**

| Name      | Type   | Description                                                                                                                                                                                   |
| --------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Widget ID | String | The identifier for the widget.                                                                                                                                                                |
| Locale    | String | The language code for the display language. View the list of available languages [here](https://chat.openai.com/g/g-q7kFlQPHr-documentation-reviewer/c/0544af67-ff28-4d60-be4b-7e5741bd4c55). |

#### Example

<pre class="language-javascript"><code class="lang-javascript"><strong>const widget = await Didomi.getContainerById("WIDGET_ID")
</strong>
widget.setWidgetLocale('fr')
</code></pre>

### shouldUserStatusBeCollected()

Determine if user status (consent) should be collected for the visitor. Returns `true` if user status is required for the current user and one of the following two conditions is met:

* User status has never been collected for this visitor yet
* New user status should be collected (as new vendors have been added) AND the configured number of days before recollecting consent has been exceeded
* The [ignoreConsentBefore](https://developers.didomi.io/cmp/web-sdk/consent-notice/notice/behavior#recollect-consent-after-a-certain-date) flag has been set with a date that applies to force consent renewal

If none of these conditions is met, the function returns `false`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

**Parameters**

No parameter.

**Returns**

`Boolean`

**Example**

```javascript
Didomi.shouldUserStatusBeCollected();
```

### syncUser()

Update the local user status from the server in a single-page application if the server has a more recent user status than the local one.

{% hint style="info" %}
If your website is not a single-page application, do not call this function as syncing will be done automatically when the user configuration details are set via `window.didomiConfig.user` on page load.
{% endhint %}

{% hint style="info" %}
The synchronization only runs if the following conditions are met: synchronization is enabled in the configuration, an organization user ID has been provided for the user, the user is not a bot, and the sync frequency has not been exceeded.
{% endhint %}

**Parameters**

No parameter.

**Returns**

A promise that resolves when the user status has been synced with the server:

```javascript
Promise<SyncReadyEvent>
```

A `SyncReadyEvent` is provided as the return value of the function with the following properties:

| Property         | Type                  | Description                                                                                                                                                                                          |
| ---------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| statusApplied    | `boolean`             | Indicates if the user status has been applied locally from the remote Didomi backend. `true` if the user status was applied from the remote, `false` otherwise.                                      |
| syncAcknowledged | `Function`            | Callback that can be used to communicate to the Didomi servers that the synchronization has been communicated to the user. Returns `true` if the API event was successfully sent, `false` otherwise. |
| syncError        | `undefined \| string` | An error message if the sync failed                                                                                                                                                                  |

**Example 1 - Simple sync**

```javascript
await Didomi.syncUser();
```

**Example 2 - Reassurance notice**

```javascript
const syncResult = await Didomi.syncUser();

if (syncResult.statusApplied) {
    // The user status actually changed from syncing
    
    // Show your reassurance notice
    
    // Report the reassurance notice as shown
    syncResult.syncAcknowledged();
}
```

### getRemoteConsentsFromAPI()

Fetch the current user’s remote consents from the Consents API via the Web SDK, instead of calling the HTTP endpoint directly. Typical use case: retrieve an existing consent state to condition UI (for example, hide a widget if an opt-in already exists).

{% hint style="info" %}
Prerequisite: you must create a Consent Token for the end-user first, this method only works when the SDK holds a valid consent token. See Consents & Preferences → Tokens for how to create a token.
{% endhint %}

**Returns**

```
Promise<RemoteConsents | null>
```

* Resolves with the normalized remote consents payload (or `null` when the user is not authenticated with a consent token).
* Also emits SDK events to signal loading/auth status.

**Limitations**

* Consent Token required. This method only works when the SDK has a valid Consent Token; it does not accept `org_id` or `org_user_id` parameters directly. See [Tokens docs](/api-and-platform/consents/tokens) for token creation flows.
* Subset of Consents API parameters. Only the `$merge_users` behavior is exposed via the `mergeUsers` option. Other Consents API query parameters are not supported here, use the HTTP API directly if you need full flexibility. See Consents & Preferences → Users to learn about the `/consents/users` endpoint.

**Notes**

* A `404` from the Consents API when calling this method does not imply an invalid token, but rather that no user exists yet for the given `organization_user_id`. Authentication will still be marked as `true`.
* This method always calls the API with `mergeUsers = false`, and this behavior

  cannot currently be changed via parameters.
* On success, the SDK normalizes the consents object and updates internal state; an “authenticated” event is emitted.

**Example 1 - Basic fetch**

```javascript
window.didomiOnReady = window.didomiOnReady || [];

window.didomiOnReady.push(async function (Didomi) {
  // Assumes you already created and set a Consent Token for this user.
  const data = await Didomi.getRemoteConsentsFromAPI();
  
  if (data?.consents) {
    console.log('Remote consents:', data.consents);
  }
});
```

**Example 2 - Conditionally hide a widget if opt-in already exists**

```javascript
window.didomiOnReady = window.didomiOnReady || [];

window.didomiOnReady.push(async function (Didomi) {
  const data = await Didomi.getRemoteConsentsFromAPI();
  const hasMarketingOptIn = !!data?.consents?.purposes?.marketing?.enabled;

  if (hasMarketingOptIn) {
    // End-user already opted in → don't render the signup widget.
    document.querySelector('#marketing-widget')?.remove();
  } else {
    // No opt-in yet → show your widget.
    document.querySelector('#marketing-widget')?.classList.remove('hidden');
  }
});
```

***

## GDPR

### \_\_tcfapi(command, version, callback, parameter)

Didomi is fully compliant with the CMP API from the [IAB Transparency and Consent framework version 2](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#how-does-the-cmp-provide-the-api).\
We expose a `__tcfapi` function and listen to `postMessage` events as per the specification.

Example (getting the IAB consent string):

```javascript
__tcfapi('getTCData', null, function (result) {
  // The IAB consent string is available in the `tcString` property of the object
  console.log(result.tcString);
});
```

[Read more in the IAB documentation](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#how-does-the-cmp-provide-the-api)


# Deprecated

## User Status

### getRequired**Vendor**Ids

Get the list of vendor IDs that are configured for the consent notice and that consent is collected for.

**Parameters**

No parameter.

**Returns**

An array of vendor IDs.

**Example**

```javascript
// Returns ['google']
Didomi.getRequiredVendorIds();
```

## GDPR

### \_\_cmp(command, parameter, callback)

Didomi is fully compliant with the CMP API from the [IAB Transparency and Consent framework version 1](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/CMP%20JS%20API%20v1.1%20Final.md#what-api-will-need-to-be-provided-by-the-cmp-).\
We expose a `__cmp` function and listen to `postMessage` events as per the specification.

Example (getting the IAB consent string):

```javascript
__cmp("getConsentData", null, function (result) {
  // The IAB consent string is available in the `consentData` property of the object
  console.log(result.consentData);
});
```

[Read more in the IAB documentation](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/CMP%20JS%20API%20v1.1%20Final.md#what-api-will-need-to-be-provided-by-the-cmp-)

{% hint style="warning" %}
The **\_\_cmp** function belongs to the IAB Transparency and Consent framework version 1, which is officially deprecated since **8/15/2020.**
{% endhint %}

### getObservableOnUserConsentStatusForVendor(vendorId)

**Deprecated**, use [addVendorStatusListener](/cmp/web-sdk/reference/api#addvendorstatuslistener) instead.

Get an observable on the consent status for a given vendor. By subscribing to the observable, you can define a function that gets called whenever the consent status of a given vendor changes.

We use the list of purposes declared for the vendor to make sure that it has consent for all of them. The required purposes are automatically setup for IAB or Didomi vendors and you must specify the required purposes for your custom vendors when configuring the tag.

It also allows you to filter for specific types of updates so that you can react to certain events only. It is an alternative to listening to the `consent.changed` event that helps in dealing with vendor-specific operations.

This is commonly used to observe the consent status for a vendor to decide when to load/enable the vendor on a page.

**Parameters**

| Name   | Type     | Description                                                                                                                                                               |
| ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendor | `string` | The ID of vendor that to check the user consent for. If you are checking an IAB vendor, use an integer instead of a string. Custom vendor IDs must be prefixed with `c:`. |

**Returns**

`Observable` on the consent status of the vendor.

{% hint style="warning" %}
The observable is not a real RxJS observable and only supports the following operators: distinctUntilChanged, filter and first. These operators behave the same as in RxJS.
{% endhint %}

**Examples:**

**Example 1 - Get all updates to the consent status for a vendor**

With this structure, your function gets called when the user gets on the page and every time the consent status of the user changes.

```javascript
Didomi.getObservableOnUserConsentStatusForVendor("vendor-id").subscribe(
  function (consentStatus) {
    if (consentStatus === undefined) {
      // The consent status for the vendor is unknown
    } else if (consentStatus === true) {
      // The user has given consent to the vendor
    } else if (consentStatus === false) {
      // The user has denied consent to the vendor
    }
  },
);
```

**Example 2 - Get updates when the consent status is true or false**

With this structure, your function only gets called after the user has given consent information. It could be on page load if the user had already given consent on a previous page or every time the user interacts with the Didomi widgets to change their consent information. When the consent status is unknown, your function does not get called.

```javascript
Didomi.getObservableOnUserConsentStatusForVendor("vendor-id")
  .filter(function (status) {
    return status !== undefined;
  })
  .subscribe(function (consentStatus) {
    if (consentStatus === undefined) {
      // The consent status for the vendor is unknown
    } else if (consentStatus === true) {
      // The user has given consent to the vendor
    } else if (consentStatus === false) {
      // The user has denied consent to the vendor
    }
  });
```

**Example 3 - Get the first update to the consent status of the vendor**

With this structure, your function gets called exactly once with the first available consent status. If the user has not given consent yet, your function will get called with `undefined`. If the user has already given consent, your function will get called with the consent status from the user.

```javascript
Didomi.getObservableOnUserConsentStatusForVendor("vendor-id")
  .first()
  .subscribe(function (consentStatus) {
    if (consentStatus === undefined) {
      // The consent status for the vendor is unknown
    } else if (consentStatus === true) {
      // The user has given consent to the vendor
    } else if (consentStatus === false) {
      // The user has denied consent to the vendor
    }
  });
```

**Example 4 - Get the first true or false update to the consent status of the vendor**

With this structure, your function gets called exactly once when the consent status becomes available. If the user has not given consent yet, your function will only be called after the user has given consent. If the user has already given consent, your function will immediately get called with the consent status from the user. Your function will never get called with `undefined`.

```javascript
Didomi.getObservableOnUserConsentStatusForVendor("vendor-id")
  .first()
  .filter(function (status) {
    return status !== undefined;
  })
  .subscribe(function (consentStatus) {
    if (consentStatus === true) {
      // The user has given consent to the vendor
    } else if (consentStatus === false) {
      // The user has denied consent to the vendor
    }
  });
```

### getUserConsentStatus(purpose, vendor)

**Deprecated**, use [getCurrentUserStatus](/cmp/web-sdk/reference/api#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the purpose in `getCurrentUserStatus().purposes` or the vendor in `getCurrentUserStatus().vendors`.
{% endhint %}

Check if the current user has given consent for a specific purpose and vendor.

**Parameters**

<table data-header-hidden><thead><tr><th width="249.33333333333331">Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Type</td><td>Description</td></tr><tr><td>purpose</td><td><code>string</code></td><td>The purpose that we are checking the user consent for (example: <code>cookies</code>)</td></tr><tr><td>vendor</td><td><code>string</code></td><td>The ID of vendor whose user consent is being checked for. If you are checking an IAB vendor, use an integer instead of a string. Custom vendor IDs must be prefixed with <code>"c:"</code>.</td></tr></tbody></table>

**Returns**

A `boolean` that indicates if the user has given consent or not.

The method always returns `true` if the specified purpose is an essential purpose and if the specified vendor has consent.

**Example**

```javascript
// IAB vendors
Didomi.getUserConsentStatus(Didomi.Purposes.Cookies, "1");

// Didomi vendors
Didomi.getUserConsentStatus(Didomi.Purposes.Cookies, "vendor-id");

// Custom vendors
Didomi.getUserConsentStatus(Didomi.Purposes.Cookies, "c:custom-vendor-id");
```

### getUserConsentStatusForPurpose(purposeId)

**Deprecated**, use [getCurrentUserStatus](/cmp/web-sdk/reference/api#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the purposeId in `getCurrentUserStatus().purposes`
{% endhint %}

Get the user consent status for a given purpose.

**Parameters**

| Name      | Type     | Description                                           |
| --------- | -------- | ----------------------------------------------------- |
| purposeId | `string` | The ID of purpose that to check the user consent for. |

**Returns**

A `boolean` that indicates if the user has given consent or not to the specific purpose.

`undefined` is returned if the consent status is not known yet. From a GDPR perspective, you'll want to treat `undefined` as `false` (ie no consent given) but it is helpful to know that the user has not interacted with the consent UI yet so that you can subscribe to events and wait for consent information to be collected.

The method always returns `true` if the specified purpose is an essential purpose.

**Example**

```javascript
Didomi.getUserConsentStatusForPurpose("cookies");
```

### getUserConsentStatusForVendor(vendor)

**Deprecated**, use [getCurrentUserStatus](/cmp/web-sdk/reference/api#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the vendorId in `getCurrentUserStatus().vendors`.
{% endhint %}

\
Get the user consent status for a given vendor. We use the list of purposes declared for the vendor to make sure that it has consent for all of them. The required purposes are automatically setup for IAB or Didomi vendors and you must specify the required purposes for your custom vendors when configuring the tag.

When determining user consent status for a given vendor, the method will treat essential purposes as purposes with given consent.

**Parameters**

| Name   | Type     | Description                                                                                                                                                                        |
| ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendor | `string` | The ID of the vendor whose user consent is being checked for. If you are checking an IAB vendor, use an integer instead of a string. Custom vendor IDs must be prefixed with `c:`. |

**Returns**

A `boolean` that indicates if the user has given consent or not to the specific vendor and all the purposes that require consent for that vendor.

`undefined` is returned if the consent status is not known yet. From a GDPR perspective, you'll want to treat `undefined` as `false` (ie no consent given) but it is helpful to know that the user has not interacted with the consent UI yet so that you can subscribe to events and wait for consent information to be collected.

**Example**

```javascript
// IAB vendors
Didomi.getUserConsentStatusForVendor("1");

// Didomi vendors
Didomi.getUserConsentStatusForVendor("vendor-id");

// Custom vendors
Didomi.getUserConsentStatusForVendor("c:custom-vendor-id");
```

### getUserStatus()

**Deprecated**, use [getCurrentUserStatus](/cmp/web-sdk/reference/api#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the purposes in `getCurrentUserStatus().purposes` or the vendors in `getCurrentUserStatus().vendors`.
{% endhint %}

Get the user consent and legitimate interest status for all the purposes and vendors.

**Parameters**

No parameter.

**Returns**

An object with the consent and legitimate interest status of the user for every purpose and vendor. The response also contains the user ID from Didomi (`user_id`), the TCF consent string (`consent_string`), additional consent string from [Google's additional consent mode](https://support.google.com/admanager/answer/9681920) (`addtl_consent`) and the dates of the user choices (`created` and `updated` ISO8061 dates).

It returns an object with the following information:

* Consent and LI status for purposes
* Consent and LI status for vendors
* Computed global status for vendors (based on the required purposes for that vendor)
* User ID
* TCF consent string
* Additional consent string
* User creation date
* User update date
* User sync date

```javascript
{
  purposes: {
      global: {
        enabled: ['purpose1'], // IDs of the purposes that are essential OR enabled as consent OR enabled as LI
        disabled: ['purpose2'] // All other purposes
      },
      consent: {
          enabled: ['purpose1'], // IDs of the purposes with consent enabled
          disabled: ['purpose2'] // IDs of the purposes with consent disabled
      },
      legitimate_interest: {
          enabled: ['purpose1'], // IDs of the purposes with legitimate interest enabled
          disabled: ['purpose2'] // IDs of the purposes with legitimate interest disabled
      },
      essential: ['purposexxx'], // IDs of the purposes that are defined as essential
  },
  vendors: {
      consent: {
          enabled: ['vendor1'], // IDs of the vendors with consent enabled
          disabled: ['vendor2'] // IDs of the vendors with consent disabled
      },
      legitimate_interest: {
          enabled: ['vendor1'], // IDs of the vendors with legitimate interest enabled
          disabled: ['vendor2'] // IDs of the vendors with legitimate interest disabled
      },
      global: {
          enabled: ['vendor1'], // IDs of the vendors that have been marked as enabled by the user based on consent/LI. When computing this property, required purposes are taken into account and essential purposes are considered as enabled.
          disabled: ['vendor2'] // All other vendors
      },
      global_consent: {
          enabled: ['vendor1'], // IDs of the vendors that have been marked as enabled by the user based on consent. When computing this property, required purposes are taken into account and essential purposes are considered as enabled.
          disabled: ['vendor2'] // All other vendors
      },
      global_li: {
          enabled: ['vendor1'], // IDs of the vendors that have been marked as enabled by the user based on LI. When computing this property, required purposes are taken into account and essential purposes are considered as enabled.
          disabled: ['vendor2'] // All other vendors
      }
  },
  user_id: 'user_id_from_token', // Didomi user ID
  created: 'ISO8061 creation date from token', // User choices creation date
  updated: 'ISO8061 update date from token', // User choices update date
  consent_string: '...' // TCF consent string,
  addtl_consent: '...' // Additional consent string
}
```

**Example**

```javascript
Didomi.getUserStatus();
```

### isConsentRequired()

**Deprecated**, use [getCurrentUserStatus().regulation](/cmp/web-sdk/reference/api#getcurrentuserstatus)

Determine if consent is required for the user based on two rules:

* You are an EU company and collect consent for all visitors. In that case, consent is always required.
* You are not an EU company and you only need to collect consent for EU visitors (see [Country and GDPR](/cmp/web-sdk/consent-notice/notice#country-and-gdpr) for more information). In this case, we use the geolocation of the user to determine whether GDPR applies or not. For instance, a user in France or Germany will require consent (under the GDPR) whereas a user in the United States will not.

{% hint style="info" %}
If you do not apply GDPR to all your visitors, you should call this function to determine whether you need to condition the loading of vendors or not.
{% endhint %}

**Parameters**

No parameter.

**Returns**

`Boolean`

**Example**

```javascript
Didomi.isConsentRequired();
```

### isUserConsentStatusPartial()

**Deprecated**, use [isUserStatusPartial](/cmp/web-sdk/reference/api#isuserstatuspartial) instead.

Determine if all consent information is available for the user.

This function returns `true` if and only if:

* Consent is required for the user (ie the user is in the EU or your tag is configured to apply GDPR to all users)
* At least one vendor is configured (if there is no vendor configured, this function always returns `false` as there is no consent to collect)
* We are missing consent information for at least one vendor or purpose.
* The consent re-collection window as configured in your tag has expired.

If there is at least one piece of consent information missing for a single vendor/purpose, this function will return `true`. The consent notice is usually displayed when this function returns `true` although there is no guarantee of the direct mapping between the two.

An important edge case is when you add new vendors or if configured vendors ask for new purposes: the consent notice will be displayed again and this function will return `true` until the user has given or denied consent. Vendors that already had consent before will still operate normally as we only recollect consent for additional vendors/purposes.

**Parameters**

No parameter.

**Returns**

`Boolean`

**Example**

```javascript
Didomi.isUserConsentStatusPartial();
```

### openTransaction()

**Deprecated**, use [openCurrentUserTransaction](/cmp/web-sdk/reference/api#opencurrentuserstatustransaction) instead.

Allow you to easily enable/disable a purpose/vendor from the existing consents.

**Parameters**

No parameter.

**Returns**

a `Transaction` object that contain the current consents. You can then modify them with the functions below.

**Example**

<pre class="language-javascript"><code class="lang-javascript"><strong>const transaction = Didomi.openTransaction();
</strong>// enable a purpose
transaction.enablePurpose('cookies');
// enable purposes
transaction.enablePurposes('cookies', 'analytics');
// disable a purpose
transaction.disablePurpose('analytics');
// disable purposes
transaction.disablePurposes('cookies', 'analytics');
// enable a vendor
transaction.enableVendor(1);
// enable vendors
transaction.enableVendors(2, 3);
// disable a vendor
transaction.disableVendor(2);
// disable vendors
transaction.disableVendors(2, 3);
// Save and set the token/cookie with the new values
transaction.commit();
</code></pre>

### **setUserStatus**(parameters)

**Deprecated**, use [setCurrentUserStatus](/cmp/web-sdk/reference/api#setcurrentuserstatus) instead.

Sets the user consent and legitimate interest statuses for vendors and purposes. You must pass the full list of enabled/disabled purposes/vendors as it will override the previous consent and legitimate interest statuses. To get the current user status, you can use `Didomi.getCurrentUserStatus()`

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

Parameters is an object with the following structure:

| Name                                    | Type           | Description                                                                          |
| --------------------------------------- | -------------- | ------------------------------------------------------------------------------------ |
| `purposes.consent.enabled`              | `array`        | The list of IDs of purposes enabled for the consent legal basis                      |
| `purposes.consent.disabled`             | `array`        | The list of IDs of purposes disabled for the consent legal basis                     |
| `purposes.legitimate_interest.enabled`  | `array`        | The list of IDs of purposes enabled for the legitimate interest legal basis          |
| `purposes.legitimate_interest.disabled` | `array`        | The list of IDs of purposes disabled for the legitimate interest legal basis         |
| `vendors.consent.enabled`               | `array`        | The list of IDs of vendors enabled for the consent legal basis                       |
| `vendors.consent.disabled`              | `array`        | The list of IDs of vendors disabled for the consent legal basis                      |
| `vendors.legitimate_interest.enabled`   | `array`        | The list of IDs of vendors enabled for the legitimate interest legal basis           |
| `vendors.legitimate_interest.disabled`  | `array`        | The list of IDs of vendors disabled for the legitimate interest legal basis          |
| `created`                               | `ISO8601 date` | An optional ISO8601 date which represents the date when the consent was created      |
| `updated`                               | `ISO8601 date` | An optional ISO8601 date which represents the date when the consent was last updated |
| `action`                                | `string`       | Action which triggered user status change                                            |

**Returns**

Nothing

**Example**

```javascript
Didomi.setUserStatus({
  purposes: {
    consent: {
      enabled: ["purpose1"], // IDs of the purposes with consent enabled
      disabled: ["purpose2"], // IDs of the purposes with consent disabled
    },
    legitimate_interest: {
      enabled: ["purpose1"], // IDs of the purposes with legitimate interest enabled
      disabled: ["purpose2"], // IDs of the purposes with legitimate interest disabled
    },
  },
  vendors: {
    consent: {
      enabled: ["vendor1"], // IDs of the vendors with consent enabled
      disabled: ["vendor2"], // IDs of the vendors with consent disabled
    },
    legitimate_interest: {
      enabled: ["vendor1"], // IDs of the vendors with legitimate interest enabled
      disabled: ["vendor2"], // IDs of the vendors with legitimate interest disabled
    },
  },
});
```

### setUserStatusForAll(params)

**Deprecated**, use [setCurrentUserStatus](/cmp/web-sdk/reference/api#setcurrentuserstatus) instead.

Sets the user consent and legitimate interest statuses for all vendors and purposes. This method overrides the previous consent and legitimate interest statuses. To get the current user status, you can use `Didomi.getCurrentUserStatus()`

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

Parameters is an object with the following structure:

| Name                    | Type           | Description                                                                                       |
| ----------------------- | -------------- | ------------------------------------------------------------------------------------------------- |
| `purposesConsentStatus` | `boolean`      | Boolean value specifying whether all purposes' consents should be enabled or disabled             |
| `purposesLIStatus`      | `boolean`      | Boolean value specifying whether all purposes' legitimate interests should be enabled or disabled |
| `vendorsConsentStatus`  | `boolean`      | Boolean value specifying whether all vendors' consents should be enabled or disabled              |
| `vendorsLIStatus`       | `boolean`      | Boolean value specifying whether all vendors' legitimate interests should be enabled or disabled  |
| `created`               | `ISO8601 date` | An optional ISO8601 date which represents the date when the consent was created                   |
| `updated`               | `ISO8601 date` | An optional ISO8601 date which represents the date when the consent was last updated              |
| `action`                | `string`       | Action which triggered user status change                                                         |

**Returns**

Nothing

**Example**

```javascript
Didomi.setUserStatusForAll({
  purposesConsentStatus: true,
  purposesLIStatus: true,
  vendorsConsentStatus: true,
  vendorsLIStatus: true,
  action: "click",
});
```

### shouldConsentBeCollected()

**Deprecated**, use [shouldUserStatusBeCollected](/cmp/web-sdk/reference/api#shoulduserstatusbecollected) instead.

Determine if consent should be collected for the visitor. Returns `true` if consent is required for the current user and one of following two conditions is met:

* Consent has never been collected for this visitor yet
* New consents should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `false`.\
This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

**Parameters**

No parameter.

**Returns**

`Boolean`

**Example**

```javascript
Didomi.shouldConsentBeCollected();
```

***

## CCPA

### setDoNotSellStatus(status)

Set the Do Not Sell status of the user.

**Parameters**

| Name   | Type      | Description                                                                                                                                           |
| ------ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| status | `boolean` | <p><code>true</code> if the user has opted out of data sharing.</p><p><code>false</code> if the user has not opted out of data sharing (default).</p> |

**Returns**

Nothing

**Example**

```javascript
Didomi.CCPA.setDoNotSellStatus(true);
```

### getDoNotSellStatus()

Get the Do Not Sell status of the user.

**Parameters**

No parameter.

**Returns**

`Boolean`

**Example**

```javascript
Didomi.CCPA.getDoNotSellStatus();
```


# Events

The Didomi SDK triggers various events to notify you that the user has taken some action (changed their consent status, opened the preferences pop-in, etc.) or that an important event has happened.

This section describes what events are available and how to subscribe to them.

## Event listeners

The Didomi SDK supports three methods for registering event listeners:

### didomiEventListeners (Recommended)

You can register events by adding them to the special `window.didomiEventListeners` array:

```markup
<script type="text/javascript">
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'event.type',
  listener: function () {
    // Your event listener
  }
});

window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function () {
  // Your initialization code (if any)
});
</script>

...

// Embed the Didomi SDK on the page
<script type="text/javascript" src="https://sdk.privacy-center.org/loader.js" async="true"></script>
```

When the SDK initializes, it collects event listeners from that array and registers them.\
You must add your event listeners to that array before the SDK gets embedded on the page and before it is ready to guarantee that you do not miss an event.\
You can also add event listeners to that array after the SDK is loaded and the SDK will automatically pick them up but you will miss events that happen during the SDK initialization.

This is the preferred method of registering event listeners as it guarantees that you do not miss events.

{% hint style="warning" %}
Registering your event listeners should be done outside of the `window.didomiOnReady` callback to ensure that you receive all events.

If you register events within the `window.didomiOnReady` callback, you will miss some events like the very first `notice.shown` that is sent before the `window.didomiOnReady` callback gets fired.
{% endhint %}

### Didomi.on

The SDK also allows you to register event listeners with the `Didomi.on` method exposed in its API:

```javascript
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function () {
  Didomi.on('event.type', function () {
    // Your event listener
  });
});
```

### Didomi.once

Additionally, the SDK provides the `Didomi.once` method to register single-use event listeners:

```javascript
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function () {
  Didomi.once('event.type', function () {
    // Your event listener, executed only once
  });
});
```

While these methods are perfectly valid, their main drawback is that your event listeners only get registered once the SDK is ready, meaning you will miss events fired during the SDK initialization. We recommend using the `didomiEventListeners` method instead.

### Didomi.off

The SDK provides the `Didomi.off` method to unsubscribe from events that were previously registered either through the `didomiEventListeners` array or using the `Didomi.on` method.

```javascript
const callback = () => {
  console.log('Event triggered');
};

// Register via didomiEventListeners
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'event.type',
  listener: callback
});


// Or register via Didomi.on
window.didomiOnReady = window.didomiOnReady || [];
window.didomiOnReady.push(function () {
  Didomi.on('event.type', callback);
});

// Later, unsubscribe
Didomi.off('event.type', callback);
```

### React

If you are using our React plugin, event listeners can be passed as props to the DidomiSDK component:

```javascript
consentHasChanged() {
    // Do something when the consent from the user has changed
}

preferencesClickPurposeAgree(purposeId) {
    // Do something when user agrees on a purpose
}

...

<DidomiSDK
    ...
    onConsentChanged={this.consentHasChanged.bind(this)}
    onPreferencesClickPurposeAgree={this.preferencesClickPurposeAgree.bind(this)}
/>
```

## Event types

This section presents a comprehensive list of the event types exposed by the Didomi SDK and usage examples.

### api.error

Triggered when an error happens while sending an HTTP request to our API for collecting consents, events, metrics, etc.

**Listener parameters**

`context` object that contains the following properties:

| Key    | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| reason | <p>The reason for the request error.</p><p><br>Possible values:<br>- <code>request.failure</code> when the request fails to be sent for any reason (timeout, no connection, blocked by an extension, etc.)<br>- <code>response.error</code> when we received an error response from the server based on the HTTP response code (>= 400)</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| id     | <p>An ID identifying the request that failed.<br><br>Possible values:<br>- <code>createEventPageview</code>: HTTP request to collect an event after a page view</p><p>- <code>createEventConsentAsked</code>: HTTP request to collect an event after consent was asked</p><p>- <code>createEventConsentGiven</code>: HTTP request to collect an event after consent was given</p><p>- <code>createEventUIAction</code>: HTTP request to collect an event after a interaction with the UI</p><p>- <code>createEventSyncAcknowledged</code>: HTTP request to collect an event after sync is acknowledged</p><p>- <code>getRemoteConsentUser</code>: HTTP request to get the remote consent</p><p>- <code>requestAuthentication</code>: HTTP request to request authentication</p><p>- <code>sendMessage</code>: HTTP request to send a login message (remote consent flow)</p><p>- <code>verifyOtpCode</code>: HTTP request to send and verify an OTP verification code<br>- <code>createSignature</code>: HTTP request to sign a Didomi Consent String<br>- <code>getSyncData</code>: HTTP request to get user choices from the backend (sync)</p> |

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'api.error',
  listener: function ({ id, reason }) {
    // An API error happened
  }
});
```

{% endtab %}
{% endtabs %}

### consent.changed

Triggered when the user consent status changes either as the result of a user action or an API call.

**Listener parameters**

`context` object that contains the following properties:

| Key    | Description                                                                                                                                                                                                    |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| action | The user action that triggered the consent change. Possible values: `click` (explicit click on the buttons), `navigate` (click to navigate to another page) or `external` (external call to setUserAgreeToAll) |

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'consent.changed',
  listener: function (context) {
    // The user consent status has changed
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
consentHasChanged() {
    // The user consent status has changed
}

...

<DidomiSDK
    ...
    onConsentChanged={this.consentHasChanged.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### consent.pendingchanged (Currently only used for preference center)

Triggered when a pending content is added or removed from the queue through the method `Didomi.setPendingConsentForEntityById` or cleared through `Didomi.savePendingConsents`.

**Listener parameters**

| Key             | Description                  |
| --------------- | ---------------------------- |
| pendingConsents | The list of pending consents |

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'consent.pendingchanged',
  listener: function ({ pendingConsents }) {
    // The number of pending consent has changed
  }
});
```

{% endtab %}
{% endtabs %}

### integrations.consentpassedtodfp

Triggered when the user consent status has been passed to Google DFP / AdSense / AdExchange. This is only triggered when the [Google DFP / AdSense / AdExchange integration](/cmp/web-sdk/third-parties/direct-integrations/google-ad-manager-adsense/google-dfp-adsense-adx) is enabled on your website.\
Visit that section for more information.

**Listener parameters**

The listener is provided with a single `data` object that has the following properties:

| Property        | Type    | Description                                                                                                                                                                                                                                                                                 |
| --------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `consentStatus` | boolean | <p>Consent status of the user for the vendor Google.</p><p><code>true</code> if the user has given consent.</p><p><code>false</code> if the user has denied consent.</p><p><code>undefined</code> if the user has not made a choice yet.</p>                                                |
| `index`         | number  | <p>The index is the number of the event on the page.<br>There is always a first event that gets triggered with index 0 on page load. More events can be triggered if the user changes their consent preferences on the page. The index gets incremented by 1 for every event triggered.</p> |

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'integrations.consentpassedtodfp',
  listener: function (data) {
    // Consent has been passed to Google
    // Load or refresh ads as needed with DFP, Prebid, etc.
    // `data.consentStatus` contains the current consent status of the user (true/false/undefined)
    // `data.index` contains the index of the event (integer)
    if (data.index === 0) {
      // This is the very first event on the page that gets triggered on page load
    } else {
      // This is an event that happens later on the page, after a user action (user giving consent or changing their preferences)
    }
  }
});
```

{% endtab %}

{% tab title="React" %}
Not available in React yet.
{% endtab %}
{% endtabs %}

### notice.backdropclick

{% hint style="info" %}
Only triggers when GDPR is active with a pop-in notice
{% endhint %}

Triggered when the user has clicked on the backdrop of a pop-in notice. This event only gets fired when a consent notice of type pop-in is displayed.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'notice.backdropclick',
  listener: function () {
    // Your event listener
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
noticeBackdropClicked() {
    // The user has clicked on the backdrop
}

...

<DidomiSDK
    ...
    onNoticeBackdropclick={this.noticeBackdropClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### notice.clickagree

Triggered when the user has clicked on the `Agree and close` button of a consent notice.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'notice.clickagree',
  listener: function () {
    // The user has clicked on the "Agree and close" button
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
noticeAgreeClicked() {
    // The user has clicked on the "Agree and close" button
}

...

<DidomiSDK
    ...
    onNoticeClickAgree={this.noticeAgreeClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### notice.clickclose

Triggered when the user has clicked on the Close icon of a consent notice with format Popup.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'notice.clickclose',
  listener: function () {
    // The user has clicked on the Close button
  }
});
```

{% endtab %}
{% endtabs %}

### notice.clickdisagree

Triggered when the user has clicked on the `Decline` button of a consent notice.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'notice.clickdisagree',
  listener: function () {
    // The user has clicked on the "Decline" button
  }
});
```

{% endtab %}
{% endtabs %}

### notice.clickmoreinfo

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has clicked on the `More information` link of a consent notice.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'notice.clickmoreinfo',
  listener: function () {
    // The user has clicked on the "More information" link
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
noticeMoreInfoClicked() {
    // The user has clicked on the "More information" link
}

...

<DidomiSDK
    ...
    onNoticeClickMoreInfo={this.noticeMoreInfoClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### notice.clickviewvendors

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has clicked on the `View our partners` link of a consent notice.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'notice.clickviewvendors',
  listener: function () {
    // The user has clicked on the "View our partners" link
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
noticeViewVendorsClicked() {
    // The user has clicked on the "View our partners" link
}

...

<DidomiSDK
    ...
    onNoticeClickViewVendors={this.noticeViewVendorsClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### notice.hidden

Triggered when the user closes the consent notice.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'notice.hidden',
  listener: function () {
    // The notice has been hidden
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
noticeHidden() {
    // The notice has been hidden
}

...

<DidomiSDK
    ...
    onNoticeHidden={this.noticeHidden.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### notice.shown

Triggered when the consent notice gets shown to the user.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'notice.shown',
  listener: function () {
    // The notice has been shown
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
noticeShown() {
    // The notice has been shown
}

...

<DidomiSDK
    ...
    onNoticeShown={this.noticeShown.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### preferences.clickagreetoall

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has clicked on the `Agree to all` button of the Preferences pop-in.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.clickagreetoall',
  listener: function () {
    // The user has clicked on the "Agree to all" button 
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
preferencesAgreeToAllClicked() {
    // The user has clicked on the "Agree to all" button 
}

...

<DidomiSDK
    ...
    onPreferencesClickAgreeToAll={this.preferencesAgreeToAllClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### preferences.clickclose

Triggered when the user has clicked on the Close icon of the Preferences pop-in.

![](/files/-LlGgkB8teRMwGMdumWY)

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.clickclose',
  listener: function () {
    // The user has clicked on the "Close" icon
  }
});
```

{% endtab %}
{% endtabs %}

### preferences.clickdisagreetoall

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has clicked on the `Disagree to all` button of the Preferences pop-in.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.clickdisagreetoall',
  listener: function () {
    // The user has clicked on the "Disagree to all" button
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
preferencesDisagreeToAllClicked() {
    // The user has clicked on the "Disagree to all" button
}

...

<DidomiSDK
    ...
    onPreferencesClickDisagreeToAll={this.preferencesDisagreeToAllClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### preferences.clickpurposeagree

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has enabled a specific purpose or category on the Preferences pop-in.

**Listener parameters**

The listener is provided with a single `data` object that has the following properties:

| Property    | Type    | Description                                  |
| ----------- | ------- | -------------------------------------------- |
| `purposeId` | string  | Unique ID of the purpose that was enabled    |
| `category`  | boolean | `true` if the purpose clicked was a category |

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.clickpurposeagree',
  listener: function (data) {
    // The user has enabled a specific purpose
    // `data.purposeId` contains the ID of the purpose
    // `data.category` contains a boolean to identify if the purpose was category
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
preferencesPurposeAgreeClicked(data) {
    // The user has enabled a specific purpose
    // `data.purposeId` contains the ID of the purpose
    // `data.category` contains a boolean to identify if the purpose was category
}

...

<DidomiSDK
    ...
    onPreferencesClickPurposeAgree={this.preferencesPurposeAgreeClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### preferences.clickpurposedisagree

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has disabled a specific purpose or category on the Preferences pop-in.

**Listener parameters**

The listener is provided with a single `data` object that has the following properties:

| Property    | Type    | Description                                  |
| ----------- | ------- | -------------------------------------------- |
| `purposeId` | string  | Unique ID of the purpose that was disabled   |
| `category`  | boolean | `true` if the purpose clicked was a category |

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.clickpurposedisagree',
  listener: function (data) {
    // The user has disabled a specific purpose
    // `data.purposeId` contains the ID of the purpose
    // `data.category` contains a boolean to identify if the purpose was category
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
preferencesPurposeDisagreeClicked(data) {
    // The user has disabled a specific purpose
    // `data.purposeId` contains the ID of the purpose
    // `data.category` contains a boolean to identify if the purpose was category
}

...

<DidomiSDK
    ...
    onPreferencesClickPurposeDisagree={this.preferencesPurposeDisagreeClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### preferences.clicksavechoices

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has clicked on the `Save` button on the Preferences pop-in (Purposes view).

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.clicksavechoices',
  listener: function () {
    // The user has clicked on the "Save" button
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
preferencesSaveChoicesClicked() {
    // The user has clicked on the "Save" button
}

...

<DidomiSDK
    ...
    onPreferencesClickSaveChoices={this.preferencesSaveChoicesClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### preferences.clickvendoragree

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has enabled a specific vendor on the Preferences pop-in.

**Listener parameters**

The listener is provided with a single `data` object that has the following properties:

| Property   | Type   | Description                              |
| ---------- | ------ | ---------------------------------------- |
| `vendorId` | string | Unique ID of the vendor that was enabled |

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.clickvendoragree',
  listener: function (data) {
    // The user has enabled a specific vendor
    // `data.vendorId` contains the ID of the vendor
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
preferencesVendorAgreeClicked(data) {
    // The user has enabled a specific vendor
    // `data.vendorId` contains the ID of the vendor
}

...

<DidomiSDK
    ...
    onPreferencesClickVendorAgree={this.preferencesVendorAgreeClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### preferences.clickvendordisagree

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has disabled a specific vendor on the Preferences pop-in.

**Listener parameters**

The listener is provided with a single `data` object that has the following properties:

| Property   | Type   | Description                               |
| ---------- | ------ | ----------------------------------------- |
| `vendorId` | string | Unique ID of the vendor that was disabled |

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.clickvendordisagree',
  listener: function (data) {
    // The user has disabled a specific vendor
    // `data.vendorId` contains the ID of the vendor
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
preferencesVendorDisagreeClicked(data) {
    // The user has disabled a specific vendor
    // `data.vendorId` contains the ID of the vendor
}

...

<DidomiSDK
    ...
    onPreferencesClickVendorDisagree={this.preferencesVendorDisagreeClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### preferences.clickvendorsavechoices

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has clicked on the `Save` button of the Preferences pop-in (Vendors view).

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.clickvendorsavechoices',
  listener: function () {
    // The user has clicked on the "Save" button
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
preferencesVendorSaveChoicesClicked() {
    // The user has clicked on the "Save" button
}

...

<DidomiSDK
    ...
    onPreferencesClickVendorSaveChoices={this.preferencesVendorSaveChoicesClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### preferences.clickviewvendors

{% hint style="info" %}
Does not trigger for CCPA
{% endhint %}

Triggered when the user has clicked on the `View vendors` link of the Preferences pop-in to open the Vendors view.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.clickviewvendors',
  listener: function () {
    // The user has clicked on the "View vendors" link
  }
});
```

{% endtab %}

{% tab title="React" %}

```javascript
preferencesViewVendorsClicked() {
    // The user has clicked on the "View vendors" link
}

...

<DidomiSDK
    ...
    onPreferencesClickViewVendors={this.preferencesViewVendorsClicked.bind(this)}
/>
```

{% endtab %}
{% endtabs %}

### preferences.hidden

Triggered when the user closes the Preferences pop-in.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.hidden',
  listener: function () {
    // The Preferences pop-in has been hidden
  }
});
```

{% endtab %}
{% endtabs %}

### preferences.shown

Triggered when the Preferences pop-in gets shown to the user.

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'preferences.shown',
  listener: function () {
    // The Preferences pop-in has been shown
  }
});
```

{% endtab %}
{% endtabs %}

### remoteconsent.changed

Triggered after the SDK refreshes remote consents, i.e. when consents are successfully saved remotely (the SDK re-fetches after saving).

{% hint style="warning" %}
**Note**: This event fires whenever remote consents are refreshed, even if the values are unchanged. Use it to react to end-user consent updates in a PMP context (preference widgets), where `consent.changed` is not available. For CMP notices, keep listening to `consent.changed`, which remains the preferred event for when consent changes.
{% endhint %}

**Listener parameters**

None

**Example**

{% tabs %}
{% tab title="Plain Javascript" %}
{% code overflow="wrap" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'remoteconsent.changed',
  listener: function () {
    // Remote consents have been re-fetched and the local consent state has been refreshed
  }
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

### sync.ready

Triggered when the syncing process is done on the page and the SDK is ready.

This event is meant to be a replacement to `window.didomiOnReady` when you need to wait for the sync process to be complete and for the SDK to be ready on the page.

It is fired in every case:

* When syncing is disabled
* When syncing is enabled but not required (ie the user information is recent enough)
* When syncing is enabled and has happened (including in error cases)

**Listener parameters**

`SyncReadyEvent` object

| Property         | Type                  | Description                                                                                                                                                                                          |
| ---------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| statusApplied    | `boolean`             | Indicates if the user status has been applied locally from the remote Didomi backend. `true` if the user status was applied from the remote, `false` otherwise.                                      |
| syncAcknowledged | `Function`            | Callback that can be used to communicate to the Didomi servers that the synchronization has been communicated to the user. Returns `true` if the API event was successfully sent, `false` otherwise. |
| syncError        | `undefined \| string` | An error message if the sync failed                                                                                                                                                                  |

**Example**

{% tabs %}
{% tab title="Plain JavaScript" %}

```javascript
window.didomiEventListeners = window.didomiEventListeners || [];
window.didomiEventListeners.push({
  event: 'sync.ready',
  listener: function () {
    // The SDK is ready and syncing is done
  }
});
```

{% endtab %}
{% endtabs %}


# Versions

## 1.5.2

### Patch Changes

* CTV: Fix notice and preferences failing to render correctly on HbbTV apps served as XHTML (`application/vnd.hbbtv.xhtml+xml`), which left the preferences buttons unclickable.
* CTV: Fix Next and Previous navigation arrow icons rendering bold and misaligned on older TV models.
* CTV: Fix Accept, Reject, and Save buttons also activating the focused background element once the consent screen closed, using the remote control.
* CTV: Sort categories and purposes alphabetically in the preferences view.
* GPP: Add `gpp_string` to the `user` object in API event payloads when a GPP string is available on the device.
* GPP: Fix a first-load race where the `tcfeuv2` section was encoded from an empty consent string (all-false defaults) while `__tcfapi` already reflected the user's choice. The initial GPP update now waits for the TC string to settle before pushing to the CMP API.
* Let explicit consent choice override GPC opt-out.
* Fix user location so the region is preserved for all countries instead of only the US.
* Fix `didomiOnReady` callbacks never running when no notice UI module applies to the current configuration

## 1.5.1

### Patch Changes

* GPP: Fix `cmpDisplayStatus` reporting `visible` when no CMP UI is displayed on sites with `notice.enable: false`.
* GPP: Fix the `Gpc` field always reporting `false` in encoded GPP sections (`usnat`, `usca`, ...) by reflecting the browser Global Privacy Control signal (`navigator.globalPrivacyControl`).
* CTV: Fix missing GPP string in consent status and a console error on GPP-enabled notices.
* CTV: Fix the SDK failing to load on notices with GPP enabled (console error, notice not rendering, GPP string missing from the consent status).
* IAB TCF: Hide the "IAB TCF" mention for IAB vendors and purposes when a non-GDPR regulation applies; the mention is still shown under GDPR.

## 1.5.0

### Minor Changes

* GPC: Add territories and purposes configuration options.
* GPP: Fix `applicableSections` returning `[]` instead of the in-force section IDs for users under an active regulation.
* Add GCM (Google Consent Mode) direct integration support for mixed regulations.

### Patch Changes

* CTV: Discard unsaved changes when the preferences screen is closed.
* Expose `isLoggedIn` and `ageGroup` on `Didomi.setUser`.

## 1.4.0

### Minor Changes

* CCPA: Remove support for the deprecated regulation.

### Patch Changes

* Include the public API key (`key` query parameter) on `/sign` and `/sync` API requests to allow access logs to be attributed to the originating organization.

## 1.3.1

### Patch Changes

* IAB TCF: Load vendor details server-side instead of bundling them in the SDK.
* Fix consent choices not being saved properly under US regulations when GPC is enabled, which caused the notice to reappear after clicking "Accept all".
* Fix `window.didomiState` misclassifying purpose-disabled vendors as enabled or unknown for GTM and other tag managers, aligning with `currentUserStatus` vendor lists.
* IAB TCF: Apply cache control for vendor device storage disclosures.

## 1.3.0

### Minor Changes

* Fix GPP `signalStatus` when the CMP is already loaded and operational.

### Patch Changes

* CTV: Fix embed loader to always use the legacy SDK path for CTV notices.

## 1.2.0

### Minor Changes

* IAB TCF: Apply April 2026 updates including SDK items and new `specialPurposes` and `optOut` fields for cookie disclosures.

### Patch Changes

* A11Y: Fix button `aria-label` to start with visible button text and include description for WCAG 2.5.3 compliance.
* Fix X (Twitter) in-app browser incorrectly detected as a bot.

## 1.1.2

### Patch Changes

* A11Y: Replace `aria-pressed` with `aria-checked` on radio buttons.

## 1.1.1

### Patch Changes

* Fix Didomi custom tag setup - use `textContext` instead of `setHTML`.
* Emit `notice.clickviewvendors` for embedded partner links.

## 1.1.0

### Minor Changes

* IAB TCF: Fix `tcData` structure by exposing `disclosedVendors` under `vendor.disclosedVendors` instead of `outOfBand.disclosedVendors` to comply with the TCF 2.3 specification.
* Fix `addVendorStatusListener` callback not triggered under CPRA (USCA).

### Patch Changes

* Add missing colon to data processing translation key in locales.
* Fix Legitimate Interest purpose consideration with `isVendorEnabled` for vendor consent status.
* Fix CPRA consent-only vendors shown as enabled in `didomiState` before user interaction.
* Fix bulk action toggle not working with first-party vendor.

## 1.0.4

### Patch Changes

* Propagate CSP nonce to all dynamic style and script injections.
* CTV: Remove double scrollbars.
* Fix user choices not reflected on third layer.
* Fix bulk toggle for categories.

## 1.0.3

### Patch Changes

* Fix horizontal scrolling and cut-off CTAs on mobile devices.
* Fix action param set to external when status is set using `setCurrentUserStatus()` and `setUserStatus()` methods.
* A11Y: Add `role` and `aria-level` attributes for accessibility compliance.

## 1.0.2

### Patch Changes

* Fix the reset function behaviour for cross-domain hostnames configuration.
* CTV: Remove clickable link from Didomi logo in notice footer to prevent unintended navigation when using remote controls.
* Fix automatically enabling vendors with only essential purposes (consent or legitimate interest) when using setUserStatus API.
* Fix vendor handling (optin/optout) on mixed regulations and prevent notice from reappearing on every refresh of the page.

## 1.0.1

### Patch Changes

* A11Y: Add missing ID for bulk purposes `aria-describedby` attribute.
* Add configurable token query parameter name via `user.auth.tokenName` to prevent conflicts with third-party services using the same parameter name.
* CTV: Fix active border style to apply only to direct child paragraph element, preventing unintended styling of nested paragraphs.
* A11Y: Change text for voice over on third layer purposes.
* Hide notice for bots.
* Add regional subdomains for Canada.
* A11Y: Add translated `alt` attribute for Didomi logo.
* Adjust auto spacing for link continue without agreeing.
* Fix the reset API function for DCS enabled configuration.
* A11Y: Add `aria-hidden` attribute to Continue without agreeing link.
* CTV: Fix notice legal text font size enlargement when navigating back from preferences.
* CTV: Add `padStart` polyfill needed for some CTV models when the organization has the DCS feature enabled.
* A11Y: Adjust category heading level for accessibility.

## 1.0.0

### Major Changes

* CTV: **Multiregulations support** - CTV notices now support multiple regulations including GPP (Global Privacy Platform) functionalities.
* CTV: Moving forward, the "Enable the 'agree to all' and 'disagree to all' buttons" option must be explicitly enabled from the console to show agree/disagree/close buttons in the second layer for all CTV notices (including existing GDPR notices).

### Minor Changes

* IAB TCF: Add v2.3 support.
* IAB TCF: Refactor service to improve website performance.
* CTV: Categories with mixed legal bases (consent and legitimate interest) now update correctly.
* CTV: Second layer CTA buttons ordering logic is now fixed.

### Patch Changes

* Prevent unintended validation of Accept / Reject when users drag and release the mouse unintentionally outside the notice.
* CTV: Fix UI rendering failure on devices where style element was undefined during initialization.
* Transpile monorepo packages (metrics, utils, consent-string) in modern build to prevent ES2021 syntax errors in legacy browsers with external polyfills.
* CTV: Improve HbbTV compatibility by fixing CSS syntax issues and element type detection on Smart TV platforms.
* CTV: Fix notice text overflow on older TV models by removing scrollbars and enabling dynamic text resizing.
* A11Y: Use localized key for aria-label on close dialog popup icon.
* A11Y: Remove block-level elements from buttons for compliance.
* CTV: Fix consent status overflow outside buttons in preferences. The data-processing component had a layout issue causing overflow regardless of text length, while the purpose-row component overflowed when purpose names were too long.
* A11Y: Add attributes to allow for tab navigation on all supported browsers.
* Add support for setting the logo height and width in the CMP banner.
* A11Y: Fix purpose button selection when dragging the mouse during click.
* A11Y: Include arrow in "continue without agreeing" link text for tab navigation purposes.
* Fix Firefox tab key navigation for vendors list.

## 0.0.1

### Patch Changes

* Initial release of the versioned SDK


# Performance

At Didomi, we understand the critical importance of maintaining optimal web performance while ensuring compliance with data privacy regulations through our Consent Management Platform (CMP).

CMPs, while essential, can introduce additional JavaScript and network requests that may impact Core Web Vitals—key metrics for assessing web performance and user experience. Specifically, these additional elements can affect Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS).

To address these concerns, the Didomi Web SDK is engineered to be lightweight and highly efficient, minimizing its impact on these vital metrics. This section of the documentation provides insights and best practices for integrating the Didomi CMP without compromising on performance, ensuring both compliance and an excellent user experience.

## Load time

The Didomi Web SDK needs to be loaded and ready before the notice is displayed or third-party scripts like ads are loaded. Depending on how your website is built, this might add a delay.

There are 2 main elements that can slow down the SDK loading process:

1. **Your website is loading a lot of resources and scripts.** Didomi needs the DOM to be loaded for the `loader` script (the one included from the Console) to append our SDK in the `head` of the page. If your DOM is loaded after 5 seconds, our SDK will start to load after 5 seconds. Even if you add the `loader` at the top of the `head`, the progression will be stuck until the DOM is loaded. It is important for you to make sure the DOM is ready as fast as possible and that no scripts are blocking the thread and slowing down the loading process. If your website loads a lot of resources like scripts and CSS, the SDK will be placed at the end of the queue and wait until the others are loaded.
2. **You are using shared consent via a custom domain.** When using shared consent, the Didomi SDK uses an iframe on your designated domain to read and write cookies from that domain. This involves asynchronous operations for loading the iframe and communicating with it that will slow down the execution of the SDK. If load time is key, we recommend not sharing consent across domains.

To optimize the load time of the SDK, you can explore the following options:

* Make sure the DOM is loaded as fast as possible and no other scripts are blocking the DOM from being ready. You can read more about the use of `defer` or `async` , for example.
* Make sure the Didomi script is placed first, at the `head` of the page. Adding our `loader` in an external Javascript file or in the footer will delay its execution.
* Reduce the number of calls or scripts loaded by your page and/or move them to the `body` section of the page.

## Core Web Vitals

#### Largest Contentful Paint (LCP)

LCP measures the loading performance of the largest visible element in the viewport. A slow LCP can result from heavy JavaScript, large images, or slow server response times.

**Recommendations:**

* Ensure that the CMP script is loaded asynchronously.
* Lazy load non-essential elements.
* Optimize images and other large assets for faster loading.
* Use efficient caching strategies to speed up server response times.

#### Interaction to Next Paint (INP)

INP evaluates the responsiveness of the page to user interactions by measuring the delay between user input and the next frame rendered.

**Recommendations:**

* Efficient Code in Callbacks:
  * Ensure that the code within these callbacks is performant and yields at appropriate points (more information about yielding on <https://web.dev/articles/optimize-inp#yield_to_the_main_thread_often>) to prevent lengthy tasks:
    * **TCF API callbacks**
    * **Didomi events callbacks** (e.g., `consent.changed`, `notice.hidden`)
    * **Integrations and Tag Managers** (e.g., `dataLayer.push`)
* Vendor and Purpose Limitation:
  * Limit the number of vendors and purposes in the consent notice to only those necessary. Avoid including all IAB vendors if not required.
* Deferred Loading of Third-Party Scripts:
  * Avoid loading third-party scripts immediately, as they can burden the main thread and impact performance.
* Custom UI Implementations:
  * If using custom UI elements, adhere to [INP best practices](https://web.dev/articles/optimize-inp) for buttons, links, or any interactive components to ensure smooth user interactions.

#### Cumulative Layout Shift (CLS)

CLS quantifies the visual stability of a page by measuring unexpected layout shifts. High CLS can occur if the Didomi CMP dynamically inserts elements without reserving space in advance.

**Recommendations:**

* Pre-allocate space for the CMP elements.
* Use CSS to minimize layout shifts during loading.
* Avoid inserting elements above existing content.
* Implement placeholder elements to maintain layout stability.

#### Total Blocking Time (TBT)

TBT measures the total time that a page is blocked from responding to user input due to long-running tasks.

**Recommendations:**

* Break up long tasks into smaller chunks.
* Defer non-critical JavaScript.
* Leverage web workers where possible.
* Optimize the CMP script for minimal blocking and quick execution.

By implementing these strategies, you can significantly improve the load time and performance impact of the Didomi SDK and ensure a better user experience on your website.


# Mobile and TV SDKs

![Consent collection in-app](/files/lgPrvNyUeQ8XsSkcTbxJ)

This section will guide you through the required steps to setup the Didomi SDK for your mobile and TV applications.

We are assuming that you have a Didomi account and an API key. If not, please go to our [website](https://www.didomi.io) and sign up for an account.

To collect and manage consents in your mobile and TV applications, we offer SDKs for the Android, iOS, and TV platforms:

* [Android / Android TV SDK](/cmp/mobile-sdk/android/setup)
* [iOS / tvOS SDK](/cmp/mobile-sdk/ios/setup)

If you’re looking for guidance on getting started with mobile development with our SDKs, feel free to explore our sample apps repositories:

* [Android Sample App (Java)](https://github.com/didomi/sample-app-android-java)
* [Android Sample App (Jetpack Compose)](https://github.com/didomi/sample-app-android-compose)
* [Android Sample App (Kotlin)](https://github.com/didomi/sample-app-android-kotlin)
* [iOS Sample App (Objective-C)](https://github.com/didomi/sample-app-ios-objective-c)
* [iOS Sample App (Swift)](https://github.com/didomi/sample-app-ios-swift-storyboard)
* [iOS Sample App (SwiftUI)](https://github.com/didomi/sample-app-ios-swift-swiftui)
* [Android / iOS Sample App (React Native)](https://github.com/didomi/sample-app-react-native)


# Android and Android TV

The Didomi SDK for Android and Android TV (including Amazon Fire TV) enables apps to collect user consent through a native experience.

Read on for more information:

* [Setup](/cmp/mobile-sdk/android/setup): How to configure the SDK
* [Logging](/cmp/mobile-sdk/android/logging): Log formats and levels
* [Reference](/cmp/mobile-sdk/android/reference/api): API functions exposed
* [Versions](/cmp/mobile-sdk/android/versions): History of versions


# Setup

Follow these steps to set up the Didomi Android and Android TV SDK:

* [Requirements](#requirements)
* [Add the SDK to your project](#add-the-sdk-to-your-project)
* [Initialize the SDK](#initialize-the-sdk)
* [Set up the SDK UI](#setup-the-sdk-ui)
* [Configure the SDK](#configure-the-sdk)

## Requirements

We offer our SDK as a pre-compiled package that you can add to your application. We support SDK versions >= 21 (`minSdkVersion(21)`) and the target/compile version must meet the [minimum required for Google Play](https://developer.android.com/distribute/best-practices/develop/target-sdk).

## Add the SDK to your project

The package is distributed through the mavenCentral repository. Make sure it is added to your repositories in your project `build.gradle` file:

{% tabs %}
{% tab title="build.gradle" %}

```groovy
buildscript {
    repositories {
        mavenCentral()
    }
}
```

{% endtab %}
{% endtabs %}

Add our SDK to your dependencies:

{% tabs %}
{% tab title="build.gradle" %}

```
dependencies {
    implementation 'io.didomi.sdk:android:2.47.0'
}
```

{% endtab %}
{% endtabs %}

Our SDK requires permissions to use the internet connection and check its status. As a result, the following permissions will be merged to your `AndroidManifest` file:

{% tabs %}
{% tab title="AndroidManifest.xml" %}

```markup
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.my.app">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
```

{% endtab %}
{% endtabs %}

## Initialize the SDK

Once our SDK has been added to your project, you need to initialize it. The initialization process will run in a background thread and prepare the SDK for interactions with the user and your application. It is important to launch the SDK initialization as soon as possible.

In the `onCreate` function of your main `Application` class, call the `Didomi.getInstance().initialize` function and pass a reference to your `Application` instance and your API key:

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

```java
package com.my.app;

import android.app.MultiDexApplication;
import android.util.Log;

import io.didomi.sdk.Didomi;

public class SampleApplication extends MultiDexApplication {
    @Override
    public void onCreate() {
        super.onCreate();

        try {
            Didomi.getInstance().initialize(
                this,
                new DidomiInitializeParameters(
                    /*apiKey*/ "<Your API key>",
                    /*localConfigurationPath*/ "<Your local config path>",
                    /*remoteConfigurationURL*/ "<Your remote config url>",
                    /*providerID*/ "<Your provider ID>",
                    /*disableDidomiRemoteConfig*/ true|false,
                    /*languageCode*/ "<Your language code>",
                    /*noticeID*/ "<Your notice ID>",
                    /*tvNoticeId*/ "<Your TV notice ID>",
                    /*androidTvEnabled*/ true|false
                )
            );
            
            // Do not use the Didomi.getInstance() object here for anything else than registering your ready listener
            // The SDK might not be ready yet
            
            Didomi.getInstance().onReady(() -> {
                // The SDK is ready, you can now interact with it
            });
        } catch(Exception e) {
            Log.e("App", "Error while initializing the Didomi SDK", e);
        }
    }
}


```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
package com.my.app

import android.util.Log
import androidx.multidex.MultiDexApplication
import io.didomi.sdk.Didomi
import io.didomi.sdk.DidomiInitializeParameters

class SampleApplication : MultiDexApplication() {

    override fun onCreate() {
        super.onCreate()
        try {
            Didomi.getInstance().initialize(
                this,
                DidomiInitializeParameters(
                    apiKey = "<Your API key>",
                    localConfigurationPath = "<Your local config path>",
                    remoteConfigurationURL = "<Your remote config url>",
                    providerID = "<Your provider ID>",
                    disableDidomiRemoteConfig = true|false,
                    languageCode = "<Your language code>",
                    noticeID = "<Your notice ID>",
                    tvNoticeId = "<Your TV notice ID>",
                    androidTvEnabled = true|false
                )
            )
            
            // Do not use the Didomi.getInstance() object here for anything else than registering your ready listener
            // The SDK might not be ready yet
            
            Didomi.getInstance().onReady {
                // The SDK is ready, you can now interact with it
            }
        } catch (e: Exception) {
            Log.e("SampleApp", "Error while initializing the Didomi SDK", e)
        }
    }
}
```

{% endtab %}
{% endtabs %}

It is a good idea to have a try/catch block around the Didomi initialization code and log any error that might happen.

Keep in mind that the SDK initialization is an asynchronous process so you must avoid interacting with the `Didomi` object until it is actually ready to handle your requests. Use the `onReady` function to register a listener for the ready event.

## Set up the SDK UI

{% hint style="info" %}
Note: the setupUI method should be called only from your main/entry `Activities` which in most cases should be once per app launch.

You do not need to call `onReady`, `isReady`, or `shouldConsentBeCollected` before calling `setupUI` because they are called internally. Therefore, by calling this method the consent notice and preference views will only be displayed if it is required and only once the SDK is ready.
{% endhint %}

In order for the SDK to be able to display UI elements and interact with the user, you must provide a reference to your main activity. Call the `setupUI` function of the SDK in the `onCreate` lifecycle event of your main activity:

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

```java
package io.didomi.sample;

import android.os.Bundle;
import androidx.fragment.app.FragmentActivity;
import io.didomi.sdk.Didomi;

public class SampleActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Didomi.getInstance().setupUI(this);
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
package io.didomi.sample

import android.os.Bundle
import androidx.fragment.app.FragmentActivity
import io.didomi.sdk.Didomi

class SampleActivity : FragmentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        Didomi.getInstance().setupUI(this)
    }
}
```

{% endtab %}
{% endtabs %}

We use the activity to get the fragment manager and register our own lifecycle events. We do not keep a reference to the activity outside of the `setupUI` function call to avoid leaks.

{% hint style="warning" %}
For Jetpack compose, you will need to extend `FragmentActivity` instead of `ComponentActivity.`
{% endhint %}

### Deep links

If you are using deep links or have multiple main activities in your app, make sure that the `setupUI` function is called on every activity that the user can launch the app on.\
\
This will ensure that consent is always collected as needed and there is no path where the user can launch the app without consent being collected. If `setupUI` is missing at some entry points, you will see lower consent rates as users will be using the app without giving consent.

## Configure the SDK

We support three options for configuring the UI and the behavior of the SDK:

* [Didomi Console](#from-the-console-recommended): the SDK is configured remotely from the Didomi Console
* [Local file](#local-file): the SDK is configured from a `didomi_config.json` file embedded in your app package
* [Remote file](#remote-file): the SDK is configured from a remote `didomi_config.json` file

{% hint style="info" %}
On Android TV / Fire TV, only Didomi Console option is enabled. Local and remote files configuration will be ignored.
{% endhint %}

### From the Console (Recommended)

You can configure the consent notice in your app by creating a notice in your Didomi console. It will automatically be linked to your app through your API key and notice ID. Values for the API key and notice ID can be retrieved directly from the [Didomi console](https://console.didomi.io/).

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

```java
Didomi.getInstance().initialize(
    this,
    new DidomiInitializeParameters(
        /*apiKey*/ "<Your API key>",
        /*localConfigurationPath*/ null,
        /*remoteConfigurationURL*/ null,
        /*providerId*/ null,
        /*disableDidomiRemoteConfig*/ false,
        /*noticeID*/ "<Your notice ID>"
    )
);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().initialize(
    this,
    DidomiInitializeParameters(
        apiKey = "<Your API key>",
        localConfigurationPath = null,
        remoteConfigurationURL = null,
        providerId = null,
        disableDidomiRemoteConfig = false,
        noticeID = "<Your notice ID>"
    )
)
```

{% endtab %}
{% endtabs %}

The SDK will automatically use the remote configuration hosted by Didomi and cache it locally. The cached version is refreshed every 60 minutes.

### Local file (deprecated)

{% hint style="danger" %}
Using a local file automatically disables the TCF integration.\
If your app uses the TCF, you must use a configuration from the Didomi Console.
{% endhint %}

{% hint style="warning" %}
Using a local file will prevent you from supporting multiple regulations.
{% endhint %}

In this option, you create your own SDK configuration file and embed it in your app package.

The SDK behavior is configured in a `didomi_config.json` file that must be placed at the root of your `assets/` folder. Create a file with the following content to get started:

{% tabs %}
{% tab title="assets/didomi\_config.json" %}

```javascript
{
    "app": {
        "name": "My App Name",
        "privacyPolicyURL": "http://www.website.com/privacy",
        "vendors": {
            "iab": {
                "all": true
            }
        },
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    }
}
```

{% endtab %}
{% endtabs %}

You also need to disable loading the remote configuration to ensure that only the local file is loaded and that no HTTP request is sent. Update your [`initialize`](/cmp/mobile-sdk/android/reference/api#initialize) call to set the `disableDidomiRemoteConfig` parameter to `true`:

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

```java
Didomi.getInstance().initialize(
    this,
    new DidomiInitializeParameters(
        /*apiKey*/ "<Your API key>",
        /*localConfigurationPath*/ null,
        /*remoteConfigurationURL*/ null,
        /*providerId*/ null,
        /*disableDidomiRemoteConfig*/ true
    )
);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().initialize(
    this,
    DidomiInitializeParameters(
        apiKey = "<API key>",
        localConfigurationPath = null,
        remoteConfigurationURL = null,
        providerId = null,
        disableDidomiRemoteConfig = true
    )
)
```

{% endtab %}
{% endtabs %}

Your SDK is now set up. [Read the Getting started section](/cmp/mobile-sdk/consent-notice/getting-started) to learn more about how to configure it to match your app UI and requirements.

### Remote file

{% hint style="danger" %}
Using your own remote file automatically disables the TCF integration.\
If your app uses the TCF, you must use a configuration from the Didomi Console.
{% endhint %}

{% hint style="info" %}
Enabling this option will prevent the configuration from being loaded from the Didomi Console.
{% endhint %}

You can provide a remote URL for the SDK to download the `didomi_config.json` configuration file from. That allows you to update the SDK configuration without having to re-publish your mobile application.

When that configuration is enabled, the SDK will automatically use the remote configuration and cache it locally. The cached version is refreshed every 60 minutes. If there is no connection available to download the remote file and no locally cached version, the SDK will try to use the local `assets/didomi_config.json` as a fallback.

To enable that option, change your call to [initialize](/cmp/mobile-sdk/android/reference/api#initialize) to provide the remote file URL:

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

```java
Didomi.getInstance().initialize(
    this,
    new DidomiInitializeParameters(
        /*apiKey*/ "<Your API key>",
        /*localConfigurationPath*/ null,
        /*remoteConfigurationURL*/ "https://www.website.com/didomi_config.json",
        /*providerId*/ null,
        /*disableDidomiRemoteConfig*/ false
    )
);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().initialize(
    this,
    DidomiInitializeParameters(
        apiKey = "<Your API key>",
        localConfigurationPath = null,
        remoteConfigurationURL = "https://www.website.com/didomi_config.json",
        providerId = null,
        disableDidomiRemoteConfig = false
    )
)
```

{% endtab %}
{% endtabs %}

Also see the [reference documentation of the initialize function](/cmp/mobile-sdk/android/reference/api#initialize) for more information.

### Download Global Vendor List (GVL)

Since version `1.28.0`, the GVL will be downloaded by default from our API before the SDK is initialized. If you want to stop this behavior, provide the `app.vendors.iab.requireUpdatedGVL` flag set to `false` in the Custom JSON section when editing your notice on the Console app (or in your local `didomi_config.json` file if that's the case).

```
{
    "app": {
        "vendors": {
            "iab": {
                "requireUpdatedGVL": false
            }
        }
    }
}
```

A timeout can also be provided to specify a maximum timeout for the download of the GVL. This can be done by providing the `app.vendors.iab.updateGVLTimeout` property (in seconds).

```
{
    "app": {
        "vendors": {
            "iab": {
                "updateGVLTimeout": 10
            }
        }
    }
}
```


# ProGuard/R8 rules

Proguard (and its successor, R8) is a code-shrinking and obfuscation tool used by Android when building release apps. Without the necessary rules in place, Proguard might strip or rename classes that an SDK needs at runtime that causes app crashes.

The Didomi Android SDK includes ProGuard rules in its Android Archive (AAR) that is automatically applied to any Android application that integrates the SDK. Your organization does not need to copy or references these rules manually as they will take effect at build time. In this article, we provide an overview of the different ProGuard/R8 rules that are packaged with the Didomi Android SDK:

* [Core Didomi SDK classes rules](#core-didomi-sdk-classes-rules)
* [Defensive/housekeeping rules](#defensive-housekeeping-rules)
* [Gson rules](#gson-rules)
* [Firebase rules](#firebase-rules)

{% hint style="info" %}
If your organization has a custom ProGuard configuration that conflicts (e.g. aggresive `-keep` or `-obfuscate` overrides) it my need to verify that these rules are not being overridden.
{% endhint %}

### Core Didomi SDK classes rules

The following rules tell ProGuard to leave Didomi SDK classes untouched (they should not be removed nor renamed):

```
-keep class io.didomi.iabtcf.** { *; }
-keep class io.didomi.sdk.** { *; }
```

### Defensive/housekeeping rules

<table><thead><tr><th width="401.06658935546875">Rule</th><th>Description</th></tr></thead><tbody><tr><td><pre data-overflow="wrap"><code>-keep,allowshrinking,allowobfuscation enum io.didomi.iabtcf.decoder.v2.RestrictionType
</code></pre></td><td>Preserves a specific enum used in TCF v2 decoding to work around a known bug in certain ProGuard versions</td></tr><tr><td><pre data-overflow="wrap"><code>-dontwarn com.eclipsesource.v8.V8
</code></pre></td><td>Suppresses a build warning about <code>V8</code> (a JavaScript engine). The SDK no longer depends on <code>V8</code> at runtime, but a reference may linger in the dependency tree.</td></tr><tr><td><pre data-overflow="wrap"><code>-dontwarn kotlinx.parcelize.Parcelize
</code></pre></td><td>Suppresses a warning about Kotlin's <code>@Parcelize</code> annotation plugin in certain build configurations.</td></tr></tbody></table>

### Gson rules

The following rules are used to handle Gson:

<table><thead><tr><th>Rule</th><th>Description</th></tr></thead><tbody><tr><td><pre data-overflow="wrap"><code>-keepattributes Signature
</code></pre></td><td>Preserves generic type information Gson needs to read JSON into typed objects</td></tr><tr><td><pre data-overflow="wrap"><code>-keepattributes *Annotation*
</code></pre></td><td>Keeps <code>@Expose</code> and other Gson annotations</td></tr><tr><td><pre data-overflow="wrap"><code>-dontwarn sun.misc.**
</code></pre></td><td>Suppresses a known harmless warning from Gson internals</td></tr><tr><td><pre data-overflow="wrap"><code>-keep class * extends com.google.gson.TypeAdapter
</code></pre></td><td>Protects custom JSON adapters from being stripped</td></tr><tr><td><pre data-overflow="wrap"><code>-keep class * implements com.google.gson.TypeAdapterFactory
</code></pre></td><td>Protects custom JSON adapter factories from being stripped</td></tr><tr><td><pre data-overflow="wrap"><code>-keep class * implements com.google.gson.JsonSerializer/Deserializer
</code></pre></td><td>Protects custom serializer/deserializer implementations</td></tr><tr><td><pre data-overflow="wrap"><code>-keepclassmembers … @SerializedName
</code></pre></td><td>Prevents R8 from nullifying fields mapped from JSON using the <code>@SerializedName</code> annotation</td></tr><tr><td><pre data-overflow="wrap"><code>-keep class com.google.gson.reflect.TypeToken
</code></pre></td><td>Required for R8 v3.0+ to correctly handle generic type tokens</td></tr></tbody></table>

### Firebase rules

The following rules apply to Android applications that use the Didomi Android SDK and Firebase Analytics with Google Consent Mode v2 enabled. Together, these rules protect Firebase Analytics classes that the Didomi Android SDK's Google Consent Mode v2 integration calls via reflection.

{% hint style="info" %}
Reflection is a technique where code calls another class's methods by name at runtime rather than at compile time. This technique requires explicit ProGuard protection.
{% endhint %}

{% code overflow="wrap" %}

```
-dontwarn com.google.firebase.analytics.FirebaseAnalytics
-keep class com.google.firebase.analytics.FirebaseAnalytics$ConsentType { *; }
-keep class com.google.firebase.analytics.FirebaseAnalytics$ConsentStatus { *; }
-keepclassmembers class com.google.firebase.analytics.FirebaseAnalytics {
    public void setConsent(java.util.Map);
}
```

{% endcode %}


# Advanced setup & troubleshooting

### Multidex

If your project already uses several libraries, it is possible that by adding Didomi it reaches the limit of 64K references. In this case, it is necessary to enable multidex in your project: <https://developer.android.com/studio/build/multidex#groovy>

Example of error that can be caused by reaching the 64K limit:

```log
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':launcher:transformClassesWithDexBuilderForRelease'.
> com.android.build.api.transform.TransformException: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException
```

{% tabs %}
{% tab title="build.gradle" %}

```
android {    
    defaultConfig {
        multiDexEnabled = true
    }
}
```

{% endtab %}
{% endtabs %}

### Languages

Didomi SDK supports the following [languages](/api-and-platform/introduction/translations#languages-supported)

Restricting the supported languages can reduce your application size.

{% tabs %}
{% tab title="build.gradle" %}

```groovy
android {
    defaultConfig {
        resourceConfigurations += ["en", "de", "fr", "es"]
    }
}
```

{% endtab %}

{% tab title="build.gradle.kts" %}

```kts
android {
    defaultConfig {
        resourceConfigurations += listOf("en", "de", "fr", "es")
    }
}
```

{% endtab %}
{% endtabs %}

Note that the Hebrew (`he`) language code is rewritten as `iw`, Indonesian (`id`) as `in`, and Yiddish (`yi`) as `ji` (see <https://developer.android.com/reference/java/util/Locale.html#legacy-language-codes> for more information).

For example: to add Hebrew language to the filtered list of language, you need to use `iw`.

{% hint style="warning" %}
**App bundles**

The Didomi SDK can be configured to restrict the languages it supports. If the user device language is not in the supported languages list, and app is distributed with Android App Bundles on the play store, it is possible that texts are removed from the downloaded app. In this case, all the texts will be displayed in english, except the custom texts.

To avoid this behavior, it is possible to either

* disable the splitting by language in App Bundle configuration.
* dynamically retrieve missing languages from Play Store through Install Manager, as described in Android developer doc: <https://developer.android.com/guide/playcore/feature-delivery/on-demand?hl=fr#lang_resources>
  {% endhint %}

#### Disable splitting by language

{% tabs %}
{% tab title="build.gradle" %}

```groovy
android {
    bundle {
        language {
            enableSplit = false
        }
    }
}
```

{% endtab %}
{% endtabs %}

#### Get missing language through Install Manager

{% tabs %}
{% tab title="SomeActivity.kt" %}

```kotlin
private lateinit var splitInstallManager: SplitInstallManager

override fun attachBaseContext(newBase: Context) {
    super.attachBaseContext(newBase)
    splitInstallManager = SplitInstallManagerFactory.create(newBase)
    SplitCompat.installActivity(this)
}

private fun onLanguageChanged(languageCode) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !splitInstallManager.installedLanguages.contains(languageCode)) {
        // Creates a request to download and install additional language resources.
        val request = SplitInstallRequest.newBuilder()
            // Uses the addLanguage() method to include needed language resources in the request.
            .addLanguage(Locale.forLanguageTag(languageCode))
            .build()

        // Submits the request to install the additional language resources.
        splitInstallManager
            .startInstall(request)
            .addOnFailureListener { (...) }
            .addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    (...)
                    // Recreate activity so new language is available
                    recreate()
                }
            }
        return
    }
}
```

{% endtab %}
{% endtabs %}

### Zipline library

Didomi SDK uses the Zipline library (<https://github.com/cashapp/zipline>) to interpret local javascript code. Currently the Zipline dependency version is `1.18.0`.

Since Didomi SDK version `2.36.0`, it is possible to exclude this library from the dependencies,. In this case the Didomi SDK will use a WebView instance to evaluate javascript.

You can exclude Zipline in the `build.gradle` file, when adding the Didomi dependency:

```
dependencies {
    implementation("io.didomi.sdk:android:X.XX.X") {
        exclude(group = "app.cash.zipline", module = "zipline")
    } 
}
```

At the moment, Didomi uses javascript for the following features:

* Didomi Consent String
* GPP
* GCM privacy signals

{% hint style="info" %}
Didomi SDK does not interpret remote javascript. All the javascript code is embedded with the SDK release.
{% endhint %}

#### Drawbacks

{% hint style="warning" %}
Excluding Zipline reduces the size of the Didomi SDK, however javascript operations will be less performant.
{% endhint %}

{% hint style="warning" %}
To support the Didomi javascript features, the device WebView version must be ≥ version 61.
{% endhint %}

{% hint style="warning" %}
Other uses of WebView from a different process in the same app can result in a crash. This can happen when a WebView is used in a Service or when using specific libraries.

More information about this crash and possible solutions can be found here: <https://stackoverflow.com/a/65423323>.
{% endhint %}


# Logging

The Didomi SDK on Android will log various informational and error messages.\
We use the [standard android.util.Log mechanism](https://developer.android.com/reference/android/util/Log) to log messages.

## Format

Messages logged by the SDK use the tag `Didomi` to indicate their origin.

Example:

![](/files/-M9VJm8i0PRF6c8jEtij)

## Levels

We use the [standard log levels supported by android.util.Log](https://developer.android.com/reference/android/util/Log#constants_1): `DEBUG`, `ERROR`, `INFO`, `VERBOSE`, and `WARN`.

You can decide what level of messages should be logged by the SDK by calling the `setLogLevel` function before `initialize`

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

```java
Didomi.getInstance().setLogLevel(android.util.Log.INFO);
Didomi.getInstance().initialize(...);
```

{% endtab %}

{% tab title="Kotlin" %}

```
Didomi.getInstance().setLogLevel(android.util.Log.INFO)
Didomi.getInstance().initialize(...)
```

{% endtab %}
{% endtabs %}

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

```java
Didomi.getInstance().setLogLevel(android.util.Log.INFO);
Didomi.getInstance().initialize(...);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().setLogLevel(android.util.Log.INFO)
Didomi.getInstance().initialize(...)
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}
Make sure that the call to `setLogLevel` is done before the call to `initialize` or some messages will be logged at the wrong level.
{% endhint %}


# Reference

This section is a comprehensive reference of the methods and events exposed by the SDK and that you can leverage in your application:

* [API](/cmp/mobile-sdk/android/reference/api)
* [Events](/cmp/mobile-sdk/android/reference/events)


# API

## Usage

The Didomi Android SDK exposes a complete API through the `io.diomi.sdk.Didomi` class. This allows your app to programmatically interact with the Didomi SDK. You can check the user consent status, register consents that you would collect yourself, and show/hide the Didomi UI.

Always use `Didomi.getInstance()` to get a reference to the Didomi SDK. Also make sure to always call the SDK after it is fully initialized (see [onReady](#onready)).

### addEventListener

Add an event listener to catch events triggered by the SDK. [See the dedicated section for more details](/cmp/mobile-sdk/android/reference/events)

### removeEventListener

Remove a previously add event listener.

**Parameters**

| Name          | Type            | Description                   |
| ------------- | --------------- | ----------------------------- |
| eventListener | `EventListener` | The event listener to remove. |

**Returns**

Nothing

**Example**

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

```java
Didomi.getInstance().removeEventListener(currentEventListener);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().removeEventListener(currentEventListener)
```

{% endtab %}
{% endtabs %}

### getDeviceType

Get the device determined by Didomi SDK (mobile or TV).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type         | Description                                                                                                                                                               |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DeviceType` | A value of type `DeviceType` reflecting the device type determined at SDK initialization. Can be either `Mobile` (phone or tablet) or `ConnectedTv` (Android TV, Fire TV) |

**Example**

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

```java
Didomi.getInstance().getDeviceType();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().deviceType
```

{% endtab %}
{% endtabs %}

### getJavaScriptForWebView

Get JavaScript to embed into a WebView to pass the consent status from the app to the Didomi Web SDK embedded into the WebView.

Inject the returned tag into a WebView with `evaluateJavaScript`.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type     | Description                           |
| -------- | ------------------------------------- |
| `String` | JavaScript code to embed in a WebView |

**Example**

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

```java
Didomi.getInstance().getJavaScriptForWebView();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().getJavaScriptForWebView()
```

{% endtab %}
{% endtabs %}

### getQueryStringForWebView

Get a query string parameter to append to the URL of a WebView to pass the consent status from the app to the Didomi Web SDK embedded into the WebView.

Read our article on [sharing consent with WebViews](/cmp/mobile-sdk/share-consent-with-webviews) for more information.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type     | Description                                                                                                                                                                            |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `String` | Query string parameter with the format `didomiConfig.user.externalConsent.value=...`. It can be appended to your URL after a `?` or a `&` if your URL already contains a query string. |

**Example**

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

```java
Didomi.getInstance().getQueryStringForWebView();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().queryStringForWebView
```

{% endtab %}
{% endtabs %}

### hideNotice

Hide the consent notice.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

Nothing

**Example**

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

```javascript
Didomi.getInstance().hideNotice();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().hideNotice()
```

{% endtab %}
{% endtabs %}

### hidePreferences

Hide the preferences popup.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

Nothing

**Example**

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

```javascript
Didomi.getInstance().hidePreferences();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().hidePreferences()
```

{% endtab %}
{% endtabs %}

### initialize

Initialize the SDK. The initialization runs on a background thread to avoid blocking your UI. Use the [onReady](#onready) function to know when the initialization is done and the SDK is ready to be used.

**Parameter:**

<table data-header-hidden><thead><tr><th width="319">Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Type</td><td>Description</td></tr><tr><td>application</td><td>Application</td><td>A reference to your Application.</td></tr><tr><td>parameters</td><td>DidomiInitializationParameters</td><td>Object containing the application parameters, see below</td></tr></tbody></table>

The **DidomiInitializationParameters** object contains all the information needed to initialize the SDK.

{% hint style="warning" %}
The parameter `disableDidomiRemoteConfig` is deprecated, we strongly suggest you to create your notice from the console (see [Setup from the Console](/cmp/mobile-sdk/android/setup#from-the-console-recommended) for more information).
{% endhint %}

| Parameter                              | Type    | Nullable | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| -------------------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| apiKey                                 | String  | No       | Your API key                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| localConfigurationPath                 | String  | Yes      | The path to your local config file in your `assets/` folder. Defaults to `didomi_config.json` if null.                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| remoteConfigurationPath                | String  | Yes      | The URL to a remote configuration file to load during initialization. When provided, the file at the URL will be downloaded and cached to be used instead of the local `assets/didomi_config.json`. If there is no Internet connection available and no previously cached file, the local file will be used as fallback.                                                                                                                                                                                                                                                 |
| providerId                             | String  | Yes      | Your provider ID (if any). A provider ID is assigned when you work with Didomi through a third-party. If are not sure if you have one, set this to `null`.                                                                                                                                                                                                                                                                                                                                                                                                               |
| disableDidomiRemoteConfig (deprecated) | Boolean | No       | <p>Prevent the SDK from loading a remote configuration from the Didomi Console. Defaults to <code>false</code> (allows loading of remote config).</p><p>Set this parameter to <code>false</code> to use a remote consent notice configuration loaded from the Didomi Console.</p><p>Set this parameter to <code>true</code> to disable loading configurations from the Didomi Console.</p>                                                                                                                                                                               |
| languageCode                           | String  | Yes      | Language in which the consent UI should be displayed. By default, the consent UI is displayed in the language configured in the device settings. This property allows you to override the default setting and specify a language to display the UI in. String containing the language code or the local code e.g.: `"es"`, `"fr"`, `"en-US"`*,* `"zh-HK"`, etc.                                                                                                                                                                                                          |
| noticeId                               | String  | Yes      | Notice ID to load the configuration from. If provided, the SDK bypasses the app ID targeting and directly loads the configuration from the notice ID.                                                                                                                                                                                                                                                                                                                                                                                                                    |
| tvNoticeId                             | String  | Yes      | TV notice ID to load the configuration from. If provided and SDK is initialized on TV, the SDK bypasses the app ID targeting and directly loads the configuration from the notice ID.                                                                                                                                                                                                                                                                                                                                                                                    |
| androidTvEnabled                       | Boolean | No       | <p>Enable the Android TV SDK. Defaults to <code>false</code> (Android TV is not enabled).</p><p>This parameter will be checked if sdk is initialized from a TV device.</p><p>If set to <code>false</code>, the sdk initialization will fail with an error.</p><p>If set to <code>true</code>, the sdk will try to initialize in TV mode, using the API key and the optional <code>tvNoticeId</code> parameter.</p><p>Please note that the TV notice option must be enabled on Didomi side. Please reach out to your dedicated customer success manager to know more.</p> |
| countryCode                            | String  | Yes      | <p>Override user country code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user country.</p>                                                                                                                                                                                                                                                                                                                                                                                                       |
| regionCode                             | String  | Yes      | <p>Override user region code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user region.</p><p>Ignored if <code>countryCode</code> is not set.</p>                                                                                                                                                                                                                                                                                                                                                   |
| isUnderage                             | Boolean | Yes      | Whether the user is underage or not. This parameters can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).                                                                                                                                                                                                                                                                                                                                                                                               |

{% hint style="info" %}
The `initialize` methods with parameters arguments are removed since version 2.0.0, please use `DidomiInitializeParameters` object instead.
{% endhint %}

**Returns**

Nothing

**Example**

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

```java
Didomi.getInstance().initialize(
    this,
    new DidomiInitializeParameters(
        "<Your API key>",
        null,
        null,
        null,
        false,
        null,
        "<Your notice id>",
        "<Your TV notice id>",
        true
    )
);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
didomi.initialize(
    this,
    DidomiInitializeParameters(
        "<Your API key>",
        noticeId = "<Your notice id>",
        tvNoticeId = "<Your TV notice id>",
        androidTvEnabled = true)
    )
)
```

{% endtab %}
{% endtabs %}

### isNoticeVisible

Check if the consent notice is currently displayed.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

`boolean`

**Example**

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

```javascript
Didomi.getInstance().isNoticeVisible();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().isNoticeVisible
```

{% endtab %}
{% endtabs %}

### isPreferencesVisible

Check if the preferences popup is currently displayed.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

`boolean`

**Example**

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

```javascript
Didomi.getInstance().isPreferencesVisible();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().isPreferencesVisible
```

{% endtab %}
{% endtabs %}

### isError

Check if the SDK has encountered an error

**Parameters**

No parameters

**Returns**

`boolean`

**Example**

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

```java
Didomi.getInstance().isError();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().isError
```

{% endtab %}
{% endtabs %}

### isReady

Check if the SDK is ready.

**Parameters**

No parameter.

**Returns**

`boolean`

**Example**

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

```javascript
Didomi.getInstance().isReady();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().isReady
```

{% endtab %}
{% endtabs %}

### onError

Add an event listener that will be called when the SDK initialization encounters an error. If the event listener is added after the SDK initialization already failed, the listener will be called immediately.

If this listener is called, the SDK initialization will not complete and onReady will not be called.

**Parameters**

| **Name** | Type       | Description                                                                    |
| -------- | ---------- | ------------------------------------------------------------------------------ |
| callback | `Runnable` | An instance of Runnable to run when the SDK initialization encounters an error |

**Returns**

Nothing

**Example**

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

```java
Didomi.getInstance().onError(() -> {
    // The SDK has encountered an error
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().onError {
    // The SDK has encountered an error
}
```

{% endtab %}
{% endtabs %}

### onReady

Add an event listener that will be called when the SDK is ready (ie fully initialized). If the event listener is added after the SDK initialization, the listener will be called immediately.

All calls to other functions of this API must only be made in a listener to the ready event to make sure that the SDK is initialized before it is used.

**Parameters**

| Name     | Type       | Description                                          |
| -------- | ---------- | ---------------------------------------------------- |
| callback | `Runnable` | An instance of Runnable to run when the SDK is ready |

**Returns**

Nothing

**Example**

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

```javascript
Didomi.getInstance().onReady(() -> {
    // The SDK is ready
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().onReady {
    // The SDK is ready
}
```

{% endtab %}
{% endtabs %}

### openCurrentUserStatusTransaction

**Definition**

Create an instance of the `CurrentUserStatusTransaction` class.

This class provides mechanisms to stage updates to the user status regarding purposes and vendors, allowing for batch operations.

Updates made through its methods are queued and applied simultaneously to the user status only once the `commit` method of the returned object is called.

Additional details:

* The status of vendors and purposes whose IDs are not not specified through the methods provided by `CurrentUserStatusTransaction` are kept unchanged.
* Essential purposes are always set to enabled and can’t be updated by the methods provided by `CurrentUserStatusTransaction`.
* When the regulation applied for a user is `none`, the methods provided by `CurrentUserStatusTransaction` should not update the status of any vendor or purpose which will always remain as enabled. When the `commit` method is called it will return `false`.
* If the IDs that are passed through the methods provided by `CurrentUserStatusTransaction` don’t correspond to vendors or purposes required by the Notice Config, they will be ignored.

**Requires SDK to be initialized**

Yes.

#### Parameters

No parameter.

**Returns**

An instance of the `CurrentUserStatusTransaction` class.

**Description of the** `CurrentUserStatusTransaction` **class**

<table><thead><tr><th width="207">Method</th><th width="233">Parameters</th><th>Returns</th><th>Description</th></tr></thead><tbody><tr><td><code>enablePurpose</code></td><td><code>id</code> (<code>String</code>): ID of the purpose to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single purpose based on its ID.</td></tr><tr><td><code>enablePurposes</code></td><td><code>ids</code> (<code>Array&#x3C;String></code>): IDs of the purposes to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple purposes based on their IDs.</td></tr><tr><td><code>disablePurpose</code></td><td><code>id</code> (<code>String</code>): ID of the purpose to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single purpose based on its ID.</td></tr><tr><td><code>disablePurposes</code></td><td><code>ids</code> (<code>Array&#x3C;String></code>): IDs of the purposes to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple purposes based on their IDs.</td></tr><tr><td><code>enableVendor</code></td><td><code>id</code> (<code>String</code>): Didomi ID of the vendor to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single vendor based on its Didomi ID.</td></tr><tr><td><code>enableVendors</code></td><td><code>ids</code> (<code>Array&#x3C;String></code>): Didomi IDs of the vendors to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>disableVendor</code></td><td><code>id</code> (<code>String</code>): Didomi ID of the vendor to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single vendor based on its Didomi ID.</td></tr><tr><td><code>disableVendors</code></td><td><code>ids</code> (<code>Array&#x3C;String></code>): Didomi IDs of the vendors to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>commit</code></td><td>No parameters.</td><td><code>Boolean</code>: <code>true</code> if user status has been updated, <code>false</code> otherwise.</td><td>Commit the changes that have been made through other methods.</td></tr></tbody></table>

#### Examples

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

<pre class="language-kotlin"><code class="lang-kotlin"><strong>val didomi = Didomi.getInstance()
</strong>val transaction = didomi.openCurrentUserStatusTransaction()

// Enable a purpose
transaction.enablePurpose("cookies")
// Enable purposes
transaction.enablePurposes("cookies", "analytics")
// Disable a purpose
transaction.disablePurpose("analytics")
// Disable purposes
transaction.disablePurposes("cookies", "analytics")
// Enable a vendor
transaction.enableVendor("vendor-1")
// Enable vendors
transaction.enableVendors("vendor-1", "vendor-2")
// Disable a vendor
transaction.disableVendor("vendor-1")
// Disable vendors
transaction.disableVendors("vendor-1", "vendor-2")

// Chain multiple calls
transaction.enablePurpose("cookies").disablePurpose("analytics")

// Save user choices
val updated = transaction.commit()
</code></pre>

{% endtab %}

{% tab title="Java" %}

```java
Didomi didomi = Didomi.getInstance();
CurrentUserStatusTransaction transaction = didomi.openCurrentUserStatusTransaction();

// Enable a purpose
transaction.enablePurpose("cookies");
// Enable purposes
transaction.enablePurposes(Arrays.asList("cookies", "analytics"));
// Disable a purpose
transaction.disablePurpose("analytics");
// Disable purposes
transaction.disablePurposes(Arrays.asList("cookies", "analytics"));
// Enable a vendor
transaction.enableVendor("vendor-1");
// Enable vendors
transaction.enableVendors(Arrays.asList("vendor-1", "vendor-2"));
// Disable a vendor
transaction.disableVendor("vendor-1");
// Disable vendors
transaction.disableVendors(Arrays.asList("vendor-1", "vendor-2"));

// Chain multiple calls
transaction.enablePurpose("cookies").disablePurpose("analytics");

// Save user choices
boolean updated = transaction.commit();
```

{% endtab %}
{% endtabs %}

### setLogLevel

Set the minimum level of messages to log. The SDK will not log messages under that level.\
See [Logging](/cmp/mobile-sdk/android/logging) for more information.

**Parameters**

| Name     | Type  | Description                       |
| -------- | ----- | --------------------------------- |
| minLevel | `int` | Minimum level of messages to log. |

**Returns**

Nothing

**Example**

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

```javascript
Didomi.getInstance().setLogLevel(android.util.Log.INFO);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().setLogLevel(android.util.Log.INFO)
```

{% endtab %}
{% endtabs %}

### setupUI

Setup the SDK UI. By calling this method, the consent notice will be displayed once the SDK is ready and if consent should be collected. It does not show any view if consent was already collected or is not required.\
This method should be called in the `onCreate` function of your activities and should be called in every activity where consent can be collected.

**Parameters**

| Name     | Type               | Description                                                                      |
| -------- | ------------------ | -------------------------------------------------------------------------------- |
| activity | `FragmentActivity` | Activity used to get the Support Fragment Manager to display the consent notice. |

**Returns**

Nothing

**Example**

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

```javascript
Didomi.getInstance().setupUI(this);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().setupUI(this)
```

{% endtab %}
{% endtabs %}

### showNotice

{% hint style="info" %}
In most cases this method should be called if the notice should be displayed in response to a user action (e.g.: select the privacy settings section within your app). By calling the setupUI method, the notice will be automatically displayed if required.
{% endhint %}

Show the consent notice. The consent notice actually only gets shown if needed (consent is required and we are missing consent information for some vendor or purpose).

**Parameters**

| Type             |                                                                                    |
| ---------------- | ---------------------------------------------------------------------------------- |
| FragmentActivity | Activity used to get the Support Fragment Manager to display the Preferences view. |

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

Nothing

**Example**

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

```javascript
Didomi.getInstance().showNotice();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().showNotice()
```

{% endtab %}
{% endtabs %}

### showPreferences

{% hint style="info" %}
In most cases this method should be called if you want to show the Preferences screen in response to a user action (the user pressing a "Consent Preferences" button in your app menu, for instance).
{% endhint %}

Show the Preferences view to the user. This method can be used to allow the user to update their preferences after the banner has been closed. We suggest adding a link/button/item that calls this method somewhere in your app, for example from your settings menu. By default, the Purposes view is displayed first. By calling this method, users will have the opportunity to modify the choices previously made.

**Parameters**

| Type              |                                                                                                                                                                                                                                                                                                                                             |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| FragmentActivity  | Activity used to get the Support Fragment Manager to display the Preferences view.                                                                                                                                                                                                                                                          |
| String (Optional) | Defines which view is displayed to the user first between the purposes view or the vendors view. We expose the values to provide on the Didomi class as `VIEW_PURPOSES`, `VIEW_VENDORS` and `VIEW_SENSITIVE_PERSONAL_INFORMATION`. If this parameter is not defined or contains an unexpected string, the purposes' view will be displayed. |

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

Nothing

**Example**

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

```javascript
// We pass "this" as a parameter as this method is called from an Activity.
Didomi.getInstance().showPreferences(this);
Didomi.getInstance().showPreferences(this, Didomi.VIEW_PURPOSES);
Didomi.getInstance().showPreferences(this, Didomi.VIEW_VENDORS);
Didomi.getInstance().showPreferences(this, Didomi.VIEW_SENSITIVE_PERSONAL_INFORMATION);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
// We pass "this" as a parameter as this method is called from an Activity.
Didomi.getInstance().showPreferences(activity = this)
Didomi.getInstance().showPreferences(activity = this, view = Didomi.VIEW_PURPOSES)
Didomi.getInstance().showPreferences(activity = this, view = Didomi.VIEW_VENDORS)
Didomi.getInstance().showPreferences(activity = this, view = Didomi.VIEW_SENSITIVE_PERSONAL_INFORMATION)
```

{% endtab %}
{% endtabs %}

### updateSelectedLanguage

Method used to update the selected language of the Didomi SDK and any property that depends on it.

In most cases this method doesn't need to be called. It would only be required for those apps that allow language change on-the-fly, i.e.: from within the app rather than from the device settings.

If your configuration involves country code (`en-US`), you can provide a locale code to change the regional configuration as well. If only language code (`en`) is provided and your configuration requires a country code, the country from the device location will be used (and will fallback to the default country if required).

In order to update the language of the views displayed by the Didomi SDK, this method needs to be called before these views are displayed.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name         | Type     | Description                                                                                                        |
| ------------ | -------- | ------------------------------------------------------------------------------------------------------------------ |
| languageCode | `String` | string containing the 2-letter language code or 5-letter locale code e.g. `en`, `es`, `fr`, `en-US`, `zh-HK`, etc. |

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

Nothing

**Example**

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

```java
Didomi.getInstance().onReady(() -> {
    Didomi.getInstance().updateSelectedLanguage("fr");
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().onReady {
    Didomi.getInstance().updateSelectedLanguage("fr")
}
```

{% endtab %}
{% endtabs %}

***

## Notice Config

### getPurpose

Get a purpose based on its ID.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name      | Type     | Description                       |
| --------- | -------- | --------------------------------- |
| purposeId | `String` | ID of the purpose we want to get. |

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type      | Description                                                              |
| --------- | ------------------------------------------------------------------------ |
| `Purpose` | A `Purpose` with ID `purposeId` found in the array of required purposes. |

**Example**

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

```java
Didomi.getInstance().getPurpose("purpose-id");
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().getPurpose("purpose-id")
```

{% endtab %}
{% endtabs %}

### getRequiredPurposes

Get the list of purpose that are required (automatically determined from the list of required vendors).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type           | Description                                               |
| -------------- | --------------------------------------------------------- |
| `Set<Purpose>` | A set of type `Purpose` containing the required purposes. |

**Example**

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

```java
Didomi.getInstance().getRequiredPurposes();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().requiredPurposes
```

{% endtab %}
{% endtabs %}

### getRequiredVendors

Get the list of vendors that are required (determined from the configuration).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type          | Description                                             |
| ------------- | ------------------------------------------------------- |
| `Set<Vendor>` | A set of type `Vendor` containing the required vendors. |

**Example**

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

```java
Didomi.getInstance().getRequiredVendors();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().requiredVendors
```

{% endtab %}
{% endtabs %}

### getText

Method used to get a dictionary/map based on the key being passed. These keys and texts are extracted from the notice content, preferences content and the `texts` property specified in the `didomi_config.json` file as described here <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme#translatable-texts-for-custom-notices>.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name | Type   | Description                                           |
| ---- | ------ | ----------------------------------------------------- |
| key  | String | key associated to the dictionary that we want to get. |

**Throws**

<table data-header-hidden><thead><tr><th width="495">Type</th><th>Description</th></tr></thead><tbody><tr><td><strong>Type</strong></td><td>Description</td></tr><tr><td>DidomiNotReadyException</td><td>Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the <code>onReady</code> method.</td></tr></tbody></table>

**Returns**

| Type           | Description                                                                                                                                                 |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Dictionary/map | Dictionary/map containing the translations for an specific key in different languages, with the form { "en:" "text in English", "fr": "texte en Français" } |

**Example**

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

```java
Didomi.getInstance().getText("key");
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().getText("key")
```

{% endtab %}
{% endtabs %}

### getTranslatedText

Method used to get a translated text based on the key being passed.

The language and the source of this translated text will depend on the availability of the translation for the specific key.

The language being used will be either the selected language of the SDK (based on device Locale and other parameters) or the language specified by app developers as the default language being used by the SDK. The source can be either the `didomi_config.json` file, which can be either local or remote, or a file that is bundled within the SDK.

These are the attempts performed by the SDK to try to find a translation for the specific key:

* Get translated value in user locale (selected language) from `didomi_config.json` (either local or remote).
* Get translated value in default locale (from the config) from `didomi_config.json` (either local or remote).
* Get translated value in user locale (selected language) from the Didomi-provided translations (bundled within the Didomi SDK).
* Get translated value in default locale (from the config) from the Didomi-provided translations (bundled within the Didomi SDK).

If no translation can be found after these 4 attempts, the key will be returned.

App developers can provide these translated texts through the `didomi_config.json` file (locally or remotely) in 3 different ways:

* Custom texts for the consent notice: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-notice#texts>
* Custom texts for the preferences: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#text>
* Custom texts for custom notices: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/build-your-own-custom-notice#translatable-texts-for-custom-notices>

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name | Type   | Description                                                |
| ---- | ------ | ---------------------------------------------------------- |
| key  | String | key associated to the text that we want to get translated. |

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

Translated text.

**Example**

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

```java
Didomi.getInstance().getTranslatedText("key");
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().getTranslatedText("key")
```

{% endtab %}
{% endtabs %}

### getVendor

Get a vendor based on its ID.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name     | Type     | Description                      |
| -------- | -------- | -------------------------------- |
| vendorId | `String` | ID of the vendor we want to get. |

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type     | Description                                                           |
| -------- | --------------------------------------------------------------------- |
| `Vendor` | A `Vendor` with ID `vendorId` found in the array of required vendors. |

**Example**

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

```java
Didomi.getInstance().getVendor("vendor-id");
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().getVendor("vendor-id")
```

{% endtab %}
{% endtabs %}

### getTotalVendorCount

Get the count of required vendors.

**Requires SDK to be initialized**

Yes.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type  | Description            |
| ----- | ---------------------- |
| `Int` | The total vendor count |

**Example**

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

```java
Didomi.getInstance().getTotalVendorCount();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().getTotalVendorCount()
```

{% endtab %}
{% endtabs %}

### getIabVendorCount

Get the count of required IAB vendors.

**Requires SDK to be initialized**

Yes.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type  | Description          |
| ----- | -------------------- |
| `Int` | The IAB vendor count |

**Example**

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

```java
Didomi.getInstance().getIabVendorCount();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().getIabVendorCount()
```

{% endtab %}
{% endtabs %}

### getNonIabVendorCount

Get the count of required vendors which are not part of the IAB.

**Requires SDK to be initialized**

Yes.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type  | Description              |
| ----- | ------------------------ |
| `Int` | The non-IAB vendor count |

**Example**

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

```java
Didomi.getInstance().getNonIabVendorCount();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().getNonIabVendorCount()
```

{% endtab %}
{% endtabs %}

***

## User Status

### applicableRegulation

Get the applicable regulation.

**Requires SDK to be initialized**

**yes.**

**Returns**

| Type     | Description                                                                                                                                                                                                                                                      |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `String` | <p>Representation of the current regulation as a <code>Regulation</code> String value, such as <code>GDPR</code>, <code>CCPA</code>, <code>CPRA</code>, or <code>NONE</code>.</p><p>Note that some regulations present as enum values are not available yet.</p> |

**Example**

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

```java
String regulation = Didomi.getInstance().getApplicableRegulation();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val regulation = Didomi.getInstance().applicableRegulation
```

{% endtab %}
{% endtabs %}

### addVendorStatusListener

Listen for changes on the user status linked to a specific vendor.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type                                                 | Description                                                                                                                                                          |
| -------- | ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id       | `String`                                             | <p>The ID of the vendor for which we want to start listening for changes.</p><p><br>This ID should be the ID provided by Didomi, which doesn't contain prefixes.</p> |
| callback | callback: `(CurrentUserStatus.VendorStatus) -> Unit` | Callback that will be executed whenever changes are detected on the specified vendor.                                                                                |

**Returns**

Nothing

**Example**

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

```java
Didomi.getInstance().addVendorStatusListener("vendor-id", (newStatus) -> {
    System.out.println("Vendor Status changed. New status: " + newStatus);
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addVendorStatusListener("vendor-id") { newStatus ->
    println("Vendor Status changed. New status: $newStatus")
}
```

{% endtab %}
{% endtabs %}

### removeVendorStatusListener

Stop listening for changes on the user status linked to a specific vendor.

**Requires SDK to be initialized**

No.

**Parameters**

| Name | Type     | Description                                                                                                                                                     |
| ---- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id   | `String` | <p>The ID of the vendor for which we want to stop listening for changes.</p><p>This ID should be the ID provided by Didomi, which doesn't contain prefixes.</p> |

**Returns**

Nothing

**Example**

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

```java
Didomi.getInstance().removeVendorStatusListener("vendor-id");
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().removeVendorStatusListener("vendor-id")
```

{% endtab %}
{% endtabs %}

### getCurrentUserStatus

#### Definition

Exposes the user status for the current regulation that applies.

#### Parameters

No parameters.

#### Returns

The user status containing the computed global status for Vendors and purposes:

* A vendor's global status is enabled, if and only if:
  * the vendor is enabled directly in the vendors layer in all legal basis
  * **AND** all its related purposes are enabled or essential.
* A purpose's global status is enabled in one of the two conditions:
  * the purpose is enabled for all the legal basis that it is configured for.
  * **OR** when the purpose is essential.

| Parameter                     | Type     | Description                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ----------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| didomi\_dcs                   | `string` | Didomi Consent String that stores end-user choices for custom and Google ATP vendors, and custom and global purposes across all regulations. [Click here](/cmp/didomi-consent-string) for more information.                                                                                                                                                                                                                             |
| vendors                       | `object` | <ul><li>Dictionary that maps the ID of a vendor to an object representing its status.</li><li>The IDs used in this dictionary correspond to the Didomi IDs i.e.: without the <code>c:</code> or any other prefix.</li><li>Vendors with undefined user status are included in the response with <code>enabled: false.</code></li><li>Vendors with ONLY essential purposes are automatically set with <code>enable: true</code></li></ul> |
| purposes                      | `object` | <ul><li>Dictionary that maps the ID of a purpose to an object representing its status.</li><li>Purposes with undefined user status are included in the response with <code>enabled: false.</code></li><li>Essential purposes are automatically set with <code>enable: true</code></li></ul>                                                                                                                                             |
| regulation                    | `String` | <ul><li>Representation of the current regulation as a <code>Regulation</code> enum value, such as <code>GDPR</code>, <code>CCPA</code>, <code>CPRA</code>, or <code>NONE</code>.</li><li>Note that some regulations present as enum values are not available yet.</li></ul>                                                                                                                                                             |
| userId                        | `String` | Didomi user id.                                                                                                                                                                                                                                                                                                                                                                                                                         |
| created                       | `String` | User choices creation date.                                                                                                                                                                                                                                                                                                                                                                                                             |
| updated                       | `String` | User choices update date.                                                                                                                                                                                                                                                                                                                                                                                                               |
| consentString                 | `String` | TCF consent as string                                                                                                                                                                                                                                                                                                                                                                                                                   |
| additionalConsent             | `String` | Additional consent.                                                                                                                                                                                                                                                                                                                                                                                                                     |
| gppString                     | `String` | GPP string.                                                                                                                                                                                                                                                                                                                                                                                                                             |
| shouldUserStatusBeCollected() | `Bool`   | Determine if the User Status (consent) should be collected or not, based on regulation, expiration date, and user status at the time of the call to `Didomi#getCurrentUserStatus()`. This method is only valid for objects returned by Didomi after a call to `getCurrentUserStatus()`.                                                                                                                                                 |

#### **Throws**

<table data-header-hidden><thead><tr><th width="334">Type</th><th>Description</th></tr></thead><tbody><tr><td><strong>Type</strong></td><td>Description</td></tr><tr><td>DidomiNotReadyException</td><td>Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the <code>onReady</code> method.</td></tr></tbody></table>

#### Examples

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

```java
CurrentUserStatus currentUserStatus = Didomi.getInstance().getCurrentUserStatus();

// Example: get consent status for vendor `google`
VendorStatus vendorStatus = currentUserStatus.vendors["google"];
bool isVendorEnabled = vendorStatus.enabled;

// Example: get consent status for custom vendor
// with ID `custom-vendor-id` (without `c:` prefix).
VendorStatus customVendorStatus = currentUserStatus.vendors["custom-vendor-id"];
bool isCustomVendorEnabled = customVendorStatus.enabled;
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val currentUserStatus = Didomi.getInstance().currentUserStatus

// Example: get consent status for vendor `google`
val vendorStatus = currentUserStatus.vendors["google"]
val isVendorEnabled = vendorStatus.enabled
```

{% endtab %}
{% endtabs %}

### isUserStatusPartial

#### Definition

Determine if the user has provided a choice for all vendors selected for the regulation and linked data processing.

This function returns `true` if the user has not expressed a choice for all the required vendors and data processing.

Requires SDK to be initialized.

#### Parameters

No parameters.

#### Returns

`boolean`

* This function returns true if the following conditions are all met
  * A regulation apply for the current user (i.e: regulation is not NONE)
  * At least one vendor is configured (if there is no vendor configured, this function always returns false as there is no status to collect)
  * We miss user status for some vendors or purposes
* Otherwise, it will return false.
  * e.g: If regulation = none (i.e no regulation apply to the end user) → This function returns false
* Edge cases: a new vendor is added to the notice and status is not collected yet for that vendor. In this case the function will return true until the user update their choice on the consent banner.

#### Throws (Android and Flutter only)

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

#### Examples

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

```java
Didomi.getInstance().isUserStatusPartial();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().isUserStatusPartial
```

{% endtab %}
{% endtabs %}

### setCurrentUserStatus

#### Definition

Set the user status for purposes and vendors. This function will trigger events and API calls every time it is called (and the user status changes) so make sure to push all user choices at once and not one by one.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

#### Parameters

Add the desired global status for each vendor and each purpose:

* the vendor status specified in this function will be reflected on the vendor’s layer.
  * vendor enabled : true → means the vendor is enabled in all the legal basis that this vendor uses.
  * vendor enabled : false → means the vendor is disabled in all the legal basis that this vendor uses
* the purposes status specified in this function will be reflected on the preferences layer.
  * purpose enabled : true → means the purpose is enabled in all the legal basis in which it’s defined.
  * purpose enabled : false → means the purpose is disabled in all the legal basis in which it’s defined.

#### Returns

`boolean`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

#### Throws (Android and Flutter only)

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

#### Examples

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

```java
Map<String, PurposeStatus> purposes = new HashMap<>();
purposes.put("purpose1", new PurposeStatus("purpose1", true));

Map<String, VendorStatus> vendors = new HashMap<>();
vendors.put("vendor1", new VendorStatus("vendor1", true));

CurrentUserStatus currentUserStatus = new CurrentUserStatus(purposes, vendors);
 
boolean updated = Didomi.getInstance().setCurrentUserStatus(currentUserStatus);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val currentUserStatus = CurrentUserStatus(
    purposes = mapOf("purpose1" to CurrentUserStatus.PurposeStatus(id = "purpose1", enabled = true)),
    vendors = mapOf("vendor1" to CurrentUserStatus.VendorStatus(id = "vendor1", enabled = true)),
)

val updated = Didomi.getInstance().setCurrentUserStatus(currentUserStatus)
```

{% endtab %}
{% endtabs %}

### reset

Reset all the consent information for the current user. This will remove all consent information stored on the device by Didomi and will trigger re-collection of consent. The consent notice will be displayed again when `setupUI` is called.

If the SDK is not initialized when this method is called, the reset will be performed during SDK initialization.

**Parameters**

No parameter.

**Throws**

Nothing

**Returns**

Nothing

**Example**

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

```java
Didomi.getInstance().reset();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().reset()
```

{% endtab %}
{% endtabs %}

### setUserAgreeToAll

Report that the user has enabled consents and legitimate interests for all purposes and vendors configured for your app.

This function will log the user choice on our platform and close the notice.

Consent statuses for essential purposes are not stored.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

`boolean`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```javascript
Didomi.getInstance().setUserAgreeToAll();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().setUserAgreeToAll()
```

{% endtab %}
{% endtabs %}

### setUserDisagreeToAll

Report that the user has disabled consents and legitimate interests for all purposes and vendors configured for your app.

This function will log the user choice on our platform and close the notice.

Consent statuses for essential purposes are not stored.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

`boolean`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```javascript
Didomi.getInstance().setUserDisagreeToAll();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().setUserDisagreeToAll()
```

{% endtab %}
{% endtabs %}

### shouldUserStatusBeCollected

#### Definition

Determine if user status (consent) should be collected for the visitor. Returns `true` if user status is required for the current user and one of following two conditions is met:

* User status has never been collected for this visitor yet
* New user status should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `false`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

Requires SDK to be initialized.

#### **Parameters**

No parameter.

#### **Returns**

`boolean`

#### Throws (Android and Flutter only)

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

#### Examples

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

```java
Didomi.getInstance().shouldUserStatusBeCollected();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().shouldUserStatusBeCollected()
```

{% endtab %}
{% endtabs %}

### setUser

The `setUser` function is used to configure settings specific to the user currently navigating the mobile app. It can be used in various scenarios, such as:

* Authenticating the user.
* Enabling cross-device functionality. For detailed information, see [documentation](/cmp/mobile-sdk/share-consents-across-devices).
* Setting user-specific attributes, like identifying the user as underage.

**Parameter:**

<table><thead><tr><th width="198">Name</th><th width="254">Type</th><th>Description</th></tr></thead><tbody><tr><td>parameters</td><td><code>DidomiUserParameters</code></td><td>Object containing properties required to set a user.</td></tr></tbody></table>

***Description for*** `DidomiUserParameters`***:***

<table><thead><tr><th width="193">Name</th><th width="219">Type</th><th>Description</th></tr></thead><tbody><tr><td>userAuth</td><td><code>UserAuth</code></td><td>User authentication object. Can be either <code>UserAuthWithoutParams</code>, <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.</td></tr><tr><td>dcsUserAuth</td><td><code>UserAuthParams?</code></td><td>Optional. Dedicated user with encryption or hash used for Didomi Consent String signature. Can be either <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.<br>This parameter can only be used if you are using the Didomi Consent String feature (This feature is currently in beta version)</td></tr><tr><td>activity</td><td><code>FragmentActivity?</code></td><td>Optional. Activity of the application if the notice should be displayed when the consent expired or the user is new.</td></tr><tr><td>isUnderage</td><td><code>Boolean?</code></td><td>Optional. Whether the user is underage or not. This parameters can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).</td></tr></tbody></table>

Parameters for `UserAuthWithoutParams` :

<table><thead><tr><th width="204">Name</th><th width="228">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr></tbody></table>

Parameters for `UserAuthWithEncryptionParams` :

<table><thead><tr><th width="211">Name</th><th width="202">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>String</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>String</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>initializationVector</td><td><code>String</code></td><td>Initialization Vector used for encrypting the message.</td></tr><tr><td>expiration</td><td><code>Long?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0).</td></tr></tbody></table>

Parameters for `UserAuthWithHashParams` :

<table><thead><tr><th width="212">Name</th><th width="205">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>String</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>String</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>digest</td><td><code>String</code></td><td>Digest used for representing the user ID</td></tr><tr><td>salt</td><td><code>String?</code></td><td>Optional. Salt used for computing the user ID.</td></tr><tr><td>expiration</td><td><code>Long?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0)</td></tr></tbody></table>

**Returns**

Nothing

**Example**

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

```java
Didomi.getInstance().setUser(new DidomiUserParameters(
            new UserAuthWithoutParams(
                        "e3222031-7c45-4f4a-8851-ffd57dbf0a2a"
            ), // user ID
            new UserAuthWithEncryptionParams(
                        "e3222031-7c45-4f4a-8851-ffd57dbf0a2b",
                        "algorithm",
                        "secret_id",
                        "initialization_vector",
                        10000L // or null
            ), // optional DCS user authentication
            activity, // optional activity
            true // optional underage flag
));

Didomi.getInstance().setUser(new DidomiUserParameters(
            new UserAuthWithEncryptionParams(
                        "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
                        "algorithm",
                        "secret_id",
                        "initialization_vector",
                        10000L // or null
            ), // user authentication
            new UserAuthWithEncryptionParams(
                        "e3222031-7c45-4f4a-8851-ffd57dbf0a2b",
                        "algorithm",
                        "secret_id",
                        "initialization_vector",
                        10000L // or null
            ), // optional DCS user authentication
            activity, // optional activity
            true // optional underage flag
));

Didomi.getInstance().setUser(new DidomiUserParameters(
            new UserAuthWithHashParams(
                        "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
                        "algorithm",
                        "secret_id",
                        "digest",
                        "salt", // or null
                        10000L // or null
            ), // user authentication
            new UserAuthWithHashParams(
                        "e3222031-7c45-4f4a-8851-ffd57dbf0a2b",
                        "algorithm",
                        "secret_id",
                        "digest",
                        "salt", // or null
                        10000L // or null
            ), // optional DCS user authentication
            activity, // optional activity
            true // optional underage flag
));
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().setUser(DidomiUserParameters(
    userAuth = UserAuthWithoutParams(
        "e3222031-7c45-4f4a-8851-ffd57dbf0a2a"
    ), // user ID
    dcsUserAuth = UserAuthWithEncryptionParams(
        id = "e3222031-7c45-4f4a-8851-ffd57dbf0a2b",
        algorithm = "algorithm",
        secretId = "secret_id",
        initializationVector = "initialization_vector",
        expiration = 10000L // or null
    ), // optional DCS user authentication
    activity = activity, // optional activity
    isUnderage = true, // optional underage flag
))

Didomi.getInstance().setUser(DidomiUserParameters(
    userAuth = UserAuthWithEncryptionParams(
        id = "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
        algorithm = "algorithm",
        secretId = "secret_id",
        initializationVector = "initialization_vector",
        expiration = 10000L // or null
    ), // user authentication
    dcsUserAuth = UserAuthWithEncryptionParams(
        id = "e3222031-7c45-4f4a-8851-ffd57dbf0a2b",
        algorithm = "algorithm",
        secretId = "secret_id",
        initializationVector = "initialization_vector",
        expiration = 10000L // or null
    ), // optional DCS user authentication
    activity = activity, // optional activity
    isUnderage = true, // optional underage flag
))

Didomi.getInstance().setUser(DidomiUserParameters(
    userAuth = UserAuthWithHashParams(
        id = "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
        algorithm = "algorithm",
        secretId = "secret_id",
        digest = "digest",
        salt = "salt", // or null
        expiration = 10000L // or null
    ), // user authentication
    dcsUserAuth = UserAuthWithHashParams(
        id = "e3222031-7c45-4f4a-8851-ffd57dbf0a2b",
        algorithm = "algorithm",
        secretId = "secret_id",
        digest = "digest",
        salt = "salt", // or null
        expiration = 10000L // or null
    ), // optional DCS user authentication
    activity = activity, // optional activity
    isUnderage = true, // optional underage flag
))
```

{% endtab %}
{% endtabs %}

### clearUser

Remove the user information from organization. This will also reset the Didomi User ID.

**Throws**

| **Type**                  | Description                                                                                                                                                                                                       |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DidomiNotReadyException` | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

Nothing

**Example**

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

```java
Didomi.getInstance().clearUser();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().clearUser()
```

{% endtab %}
{% endtabs %}


# Deprecated

## Notice Config

### getDisabledPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getDisabledPurposeIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getDisabledVendors

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getDisabledVendorIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getEnabledPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getEnabledPurposeIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getEnabledVendors

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getEnabledVendorIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getRequiredPurposeIds

**Removed since version 2.0.0**, use [getRequiredPurposes](/cmp/mobile-sdk/android/reference/api#getrequiredpurposes) instead.

Get the list of purpose IDs that are required (automatically determined from the list of required vendors).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type          | Description                                                     |
| ------------- | --------------------------------------------------------------- |
| `Set<String>` | A set of type `String` containing the IDs of required purposes. |

**Example**

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

```java
Didomi.getInstance().getRequiredPurposeIds();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().requiredPurposeIds
```

{% endtab %}
{% endtabs %}

### getRequiredVendorIds

**Removed since version 2.0.0**, use [getRequiredVendors](/cmp/mobile-sdk/android/reference/api#getrequiredvendors) instead.

Get the list of vendor IDs that are required (determined from the configuration).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

| Type          | Description                                                    |
| ------------- | -------------------------------------------------------------- |
| `Set<String>` | A set of type `String` containing the IDs of required vendors. |

**Example**

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

```java
Didomi.getInstance().getRequiredVendorIds();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().requiredVendorIds
```

{% endtab %}
{% endtabs %}

***

## User Status

### getUserConsentStatusForPurpose

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getUserConsentStatusForVendor

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getUserConsentStatusForVendorAndRequiredPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getUserLegitimateInterestStatusForPurpose

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getUserLegitimateInterestForVendor

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getUserLegitimateInterestStatusForVendorAndRequiredPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### getUserStatus

**Deprecated**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

Get all the user consent status.

**Throws**

<table data-header-hidden><thead><tr><th width="334">Type</th><th>Description</th></tr></thead><tbody><tr><td><strong>Type</strong></td><td>Description</td></tr><tr><td>DidomiNotReadyException</td><td>Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the <code>onReady</code> method.</td></tr></tbody></table>

**Returns**

A `UserStatus` object describing all the available and computed user information.

<table data-header-hidden><thead><tr><th width="249.33333333333331">Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td>purposes.global.disabled</td><td>Set&#x3C;String></td><td>Computed sets/lists of disabled IDs of purposes that have been chosen by the user regarding the consent or legitimate interest Legal Basis.</td></tr><tr><td>purposes.global.enabled</td><td>Set&#x3C;String></td><td>Computed sets/lists of enabled IDs of purposes that have been chosen by the user regarding the consent or legitimate interest Legal Basis. Purposes considered as essential will be part of the enabled IDs.</td></tr><tr><td>purposes.consent.disabled</td><td>Set&#x3C;String></td><td>Disabled IDs of purposes that have been explicitly chosen by the user regarding the consent Legal Basis.</td></tr><tr><td>purposes.consent.enabled</td><td>Set&#x3C;String></td><td>Enabled IDs of purposes that have been explicitly chosen by the user regarding the consent Legal Basis.</td></tr><tr><td>purposes.legitimateInterest.disabled</td><td>Set&#x3C;String></td><td>Disabled IDs of purposes that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.</td></tr><tr><td>purposes.legitimateInterest.enabled</td><td>Set&#x3C;String></td><td>Enabled IDs of purposes that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.</td></tr><tr><td>purposes.essential</td><td>Set&#x3C;String></td><td>IDs of purposes that are considered essential.</td></tr><tr><td>vendors.global.disabled</td><td>Set&#x3C;String></td><td>Computed sets/lists of disabled IDs of vendors that have been chosen by the user regarding the consent or legitimate interest Legal Basis. This takes into account the consent and legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.</td></tr><tr><td>vendors.global.enabled</td><td>Set&#x3C;String></td><td>Computed sets/lists of enabled IDs of vendors that have been chosen by the user regarding the consent or legitimate interest Legal Basis. This takes into account the consent and legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.</td></tr><tr><td>vendors.globalConsent.disabled</td><td>Set&#x3C;String></td><td>Computed sets/lists of disabled IDs of vendors that have been chosen by the user regarding the consent Legal Basis. This takes into account the consent required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.</td></tr><tr><td>vendors.globalConsent.enabled</td><td>Set&#x3C;String></td><td>Computed sets/lists of enabled IDs of vendors that have been chosen by the user regarding the consent Legal Basis. This takes into account the consent required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.</td></tr><tr><td>vendors.globalLegitimateInterest.disabled</td><td>Set&#x3C;String></td><td>Computed sets/lists of disabled IDs of vendors that have been chosen by the user regarding the legitimate interest Legal Basis. This takes into account the legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.</td></tr><tr><td>vendors.globalLegitimateInterest.enabled</td><td>Set&#x3C;String></td><td>Computed sets/lists of enabled IDs of vendors that have been chosen by the user regarding the legitimate interest Legal Basis. This takes into account the legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.</td></tr><tr><td>vendors.consent.disabled</td><td>Set&#x3C;String></td><td>Disabled IDs of vendors that have been explicitly chosen by the user regarding the consent Legal Basis.</td></tr><tr><td>vendors.consent.enabled</td><td>Set&#x3C;String></td><td>Enabled IDs of vendors that have been explicitly chosen by the user regarding the consent Legal Basis.</td></tr><tr><td>vendors.legitimateInterest.disabled</td><td>Set&#x3C;String></td><td>Disabled IDs of vendors that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.</td></tr><tr><td>vendors.legitimateInterest.enabled</td><td>Set&#x3C;String></td><td>Enabled IDs of vendors that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.</td></tr><tr><td>userId</td><td>String</td><td>Didomi user id.</td></tr><tr><td>created</td><td>String</td><td>User choices creation date.</td></tr><tr><td>updated</td><td>String</td><td>User choices update date.</td></tr><tr><td>consentString</td><td>String</td><td>TFC consent as string.</td></tr><tr><td>additionalConsent</td><td>String</td><td>Additional consent for <a href="/pages/-LMZcLWpf6K_p4r_pMax#google-additional-consent-mode">Google Additional Consent Mode</a>.</td></tr><tr><td>regulation</td><td><code>Regulation</code></td><td>Representation of the current regulation as a <code>Regulation</code> enum value, such as <code>GDPR</code>, <code>CCPA</code>, <code>CPRA</code>, or <code>NONE</code>. Note that some regulations present as enum values are not available yet.</td></tr></tbody></table>

**Example**

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

```java
UserStatus userStatus = Didomi.getInstance().getUserStatus();

// Enabled consent ids for vendors
Set<String> enabledVendorsConsentIds = userStatus.getVendors().getConsent().getEnabled();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val userStatus = Didomi.getInstance().userStatus

// Enabled consent ids for vendors
val enabledVendorsConsentIds = userStatus.vendors.consent.enabled
```

{% endtab %}
{% endtabs %}

### getUserStatusForVendor

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) instead.

### isConsentRequired

**Deprecated**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) and check that the field `regulation`is not `Regulation.NONE`.

Determine if consent is required for the user. This takes into account the location of the user and the configuration of the SDK:

* If your app is configured to apply GDPR to all users then this function always returns `true`.
* If your app is configured to apply GDPR to EU users only then this function returns `true` only if the user in the EU.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

`boolean`

**Example**

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

```javascript
Didomi.getInstance().isConsentRequired();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().isConsentRequired
```

{% endtab %}
{% endtabs %}

### isUserConsentStatusPartial

**Deprecated**, use [isUserStatusPartial](/cmp/mobile-sdk/android/reference/api#isuserstatuspartial) instead.

Determine if all consent information is available for the user.

This function returns `true` if and only if:

* Consent is required for the user (ie the user is in the EU or your tag is configured to apply GDPR to all users)
* At least one vendor is configured (if there is no vendor configured, this function always returns `false` as there is no consent to collect)
* We miss consent information for some vendors or purposes

If there is at least one piece of consent information missing for a single vendor/purpose, this function will return `true`. The consent notice is usually displayed when this function returns `true` although there is no guarantee of the direct mapping between the two.

An important edge case is when you add new vendors or if configured vendors ask for new purposes: the consent notice will be displayed again and this function will return `true` until the user has given or denied consent. Vendors that already had consent before will still operate normally as we only recollect consent for additional vendors/purposes.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

`boolean`

**Example**

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

```javascript
Didomi.getInstance().isUserConsentStatusPartial();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().isUserConsentStatusPartial
```

{% endtab %}
{% endtabs %}

### isUserLegitimateInterestStatusPartial

**Deprecated**, use [isUserStatusPartial](/cmp/mobile-sdk/android/reference/api#isuserstatuspartial) instead.

Determine if all Legitimate Interest information is available for the user.

This function returns `true` if and only if:

* Legitimate Interest is required for the user (ie the user is in the EU or your tag is configured to apply GDPR to all users)
* At least one vendor is configured (if there is no vendor configured, this function always returns `false` as there is no Legitimate Interest to collect)
* We miss Legitimate Interest information for some vendors or purposes

If there is at least one piece of Legitimate Interest information missing for a single vendor/purpose, this function will return `true`. The consent notice is usually displayed when this function returns `true` although there is no guarantee of the direct mapping between the two.

An important edge case is when you add new vendors or if configured vendors ask for new purposes: the consent notice will be displayed again and this function will return `true` until the user has given or denied consent. Vendors that already had Legitimate Interest before will still operate normally as we only recollect Legitimate Interest for additional vendors/purposes.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

`boolean`

**Example**

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

```java
Didomi.getInstance().isUserLegitimateInterestStatusPartial();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().isUserLegitimateInterestStatusPartial
```

{% endtab %}
{% endtabs %}

### setUserConsentStatus

**Deprecated**, use [setCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#setcurrentuserstatus) instead.

### setUserStatus

**Removed since version 2.0.0**, use [setCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#setcurrentuserstatus) instead.

Set the user status for purposes and vendors. This function will trigger events and API calls every time it is called (and the user status changes) so make sure to push all user choices at once and not one by one.

Please read [our article ](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics)on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

**Global method:**

Define a global status for consent purposes, legitimate interest purposes, consent vendors, legitimate interest vendors

| Name                  | Type      | Description                                                                                             |
| --------------------- | --------- | ------------------------------------------------------------------------------------------------------- |
| purposesConsentStatus | `boolean` | `true` if purposes on a consent basis should be enabled, `false` if they should be disabled             |
| purposesLIStatus      | `boolean` | `true` if purposes on a legitimate interest basis should be enabled, `false` if they should be disabled |
| vendorsConsentStatus  | `boolean` | `true` if vendors on a consent basis should be enabled, `false` if they should be disabled              |
| vendorsLIStatus       | `boolean` | `true` if vendors on a legitimate interest basis should be enabled, `false` if they should be disabled  |

**Example**

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

```javascript
// Disable everything except vendors legitimate interest
Didomi.getInstance().setUserStatus(
    false, true, false, true
);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
// Disable everything except vendors legitimate interest
Didomi.getInstance().setUserStatus(
    purposesConsentStatus = false,
    purposesLIStatus = true,
    vendorsConsentStatus = false,
    vendorsLIStatus = true
)
```

{% endtab %}
{% endtabs %}

**Individual purposes/vendors method:**

Allows to define precisely which purposes and vendors are enabled / disabled

| Name                      | Type          | Description                                                                                                                                |
| ------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| enabledConsentPurposeIds  | `Set<String>` | Set of purpose IDs that the user has given consent to                                                                                      |
| disabledConsentPurposeIds | `Set<String>` | Set of purpose IDs that the user has not given consent to                                                                                  |
| enabledLIPurposeIds       | `Set<String>` | Set of purpose IDs that the user has allowed legitimate interest processing to                                                             |
| disabledLIPurposeIds      | `Set<String>` | Set of purpose IDs that the user has disallowed legitimate interest processing to                                                          |
| enabledConsentVendorIds   | `Set<String>` | <p>Set of vendor IDs that the user has given consent to.</p><p>Prefix custom vendor IDs with <code>c:</code>.</p>                          |
| disabledConsentVendorIds  | `Set<String>` | Set of vendor IDs that the user has not given consent to                                                                                   |
| enabledLIVendorIds        | `Set<String>` | <p>Set of vendor IDs that the user has allowed legitimate interest processing to.</p><p>Prefix custom vendor IDs with <code>c:</code>.</p> |
| disabledLIVendorIds       | `Set<String>` | Set of vendor IDs that the user has not allowed legitimate interest processing to                                                          |

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

`boolean`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

<pre class="language-javascript"><code class="lang-javascript">Didomi.getInstance().setUserStatus(
    new HashSet&#x3C;String>(Arrays.asList("cookies", "ad_delivery")),
    new HashSet&#x3C;String>(Arrays.asList("market_research")),
    new HashSet&#x3C;String>(Arrays.asList("cookies", "market_research"),
<strong>    new HashSet&#x3C;String>(Arrays.asList("ad_delivery"),
</strong><strong>    new HashSet&#x3C;String>(Arrays.asList("123", "c:custom-vendor-id")),
</strong>    new HashSet&#x3C;String>(Arrays.asList("125")),
    new HashSet&#x3C;String>(Arrays.asList("123", "125", "c:custom-vendor-id")),
    new HashSet&#x3C;String>()
);
</code></pre>

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().setUserStatus(
    enabledConsentPurposeIds = setOf("cookies", "ad_delivery"),
    disabledConsentPurposeIds = setOf("market_research"),
    enabledLIPurposeIds = setOf("cookies", "market_research"),
    disabledLIPurposeIds = setOf("ad_delivery"),
    enabledConsentVendorIds = setOf("123", "c:custom-vendor-id"),
    disabledConsentVendorIds = setOf("125"),
    enabledLIVendorIds = setOf("123", "125", "c:custom-vendor-id"),
    disabledConsentVendorIds = emptySet()
);
```

{% endtab %}
{% endtabs %}

### shouldConsentBeCollected

**Deprecated**, use [shouldUserStatusBeCollected](/cmp/mobile-sdk/android/reference/api#shoulduserstatusbecollected) instead.

Determine if consent should be collected for the visitor. Returns `true` if consent is required for the current user and one of following two conditions is met:

* Consent has never been collected for this visitor yet
* New consents should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `false`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

**Parameters**

No parameter.

**Throws**

| **Type**                | Description                                                                                                                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DidomiNotReadyException | Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the `onReady` method. |

**Returns**

`boolean`

**Example**

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

```java
Didomi.getInstance().shouldConsentBeCollected();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().shouldConsentBeCollected()
```

{% endtab %}
{% endtabs %}

### setUser

**Deprecated**, use [setUser](/cmp/mobile-sdk/android/reference/api#setuser) with `DidomiUserParameters` instead.

Set user information from organization for cross device functionality. For detailed information, see [documentation](/cmp/mobile-sdk/share-consents-across-devices).

**Parameters**

***Method without authentication:***

| Name               | Type               | Description                                                                                 |
| ------------------ | ------------------ | ------------------------------------------------------------------------------------------- |
| organizationUserId | `String`           | Organization ID to associate with the user                                                  |
| activity           | `FragmentActivity` | Optional. When present, notice will be displayed if synchronized user has partial consents. |

***Method with Encrypted authentication:***

| Name           | Type                           | Description                                                                                 |
| -------------- | ------------------------------ | ------------------------------------------------------------------------------------------- |
| userAuthParams | `UserAuthWithEncryptionParams` | User authentication with encryption                                                         |
| activity       | `FragmentActivity`             | Optional. When present, notice will be displayed if synchronized user has partial consents. |

Parameters for `UserAuthWithEncryptionParams` :

| Name                 | Type     | Description                                                |
| -------------------- | -------- | ---------------------------------------------------------- |
| id                   | `String` | Organization ID to associate with the user                 |
| algorithm            | `String` | Algorithm used for computing the user ID                   |
| secretId             | `String` | ID of the secret used for the computing the user ID        |
| initializationVector | `String` | Initialization Vector used for encrypting the message      |
| expiration           | `Long`   | Expiration time as UNIX timestamp (optional - must be > 0) |

***Method with Hash authentication:***

| Name           | Type                     | Description                         |
| -------------- | ------------------------ | ----------------------------------- |
| userAuthParams | `UserAuthWithHashParams` | User authentication with encryption |

Parameters for `UserAuthWithHashParams` :

| Name       | Type     | Description                                                |
| ---------- | -------- | ---------------------------------------------------------- |
| id         | `String` | Organization ID to associate with the user                 |
| algorithm  | `String` | Algorithm used for computing the user ID                   |
| secretId   | `String` | ID of the secret used for the computing the user ID        |
| digest     | `String` | Digest used for representing the user ID                   |
| salt       | `String` | Salt used for computing the user ID (optional)             |
| expiration | `Long`   | Expiration time as UNIX timestamp (optional - must be > 0) |

**Returns**

Nothing

**Example**

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

```javascript
Didomi.getInstance().setUser("e3222031-7c45-4f4a-8851-ffd57dbf0a2a");

Didomi.getInstance().setUser(new UserAuthWithEncryptionParams(
            "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
            "algorithm",
            "secret_id",
            "initialization_vector",
            10000L // or null
));

Didomi.getInstance().setUser(new UserAuthWithHashParams(
            "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
            "algorithm",
            "secret_id",
            "digest",
            "salt", // or null
            10000L // or null
));
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().setUser("e3222031-7c45-4f4a-8851-ffd57dbf0a2a")

Didomi.getInstance().setUser(
    UserAuthWithEncryptionParams(
        id = "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
        algorithm = "algorithm",
        secretId = "secret_id",
        initializationVector = "initialization_vector",
        expiration = 10000L // or null
    )
)

Didomi.getInstance().setUser(
    UserAuthWithHashParams(
        id = "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
        algorithm = "algorithm",
        secretId = "secret_id",
        digest = "digest",
        salt = "salt", // or null
        expiration = 10000L // or null
    )
)
```

{% endtab %}
{% endtabs %}


# Events

The Didomi SDK triggers various events to notify you that the user has taken some action (changed their consent status, opened the preferences screen, etc.) or that an important event has happened.

This section describes what events are available and how to subscribe to them.

## addEventListener

This method adds an event listener to catch events triggered by the SDK. Events listeners allow you to react to different events of interest. This function is safe to call before the `ready` event has been triggered.

**Parameters**

| Name          | Type            | Description                                                                           |
| ------------- | --------------- | ------------------------------------------------------------------------------------- |
| eventListener | `EventListener` | The event listener. An instance of a subclass of `io.didomi.sdk.events.EventListener` |

**Returns**

Nothing

**Example**

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

```java
import io.didomi.sdk.events.EventListener;
import io.didomi.sdk.events.ConsentChangedEvent;

Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void consentChanged(ConsentChangedEvent event) {
        // React to consent changed
    }
    
    @Override
    public void showNotice(ShowNoticeEvent event) {
        // React to notice being shown
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
import io.didomi.sdk.events.EventListener
import io.didomi.sdk.events.ConsentChangedEvent

Didomi.getInstance().addEventListener(object : EventListener() {
    override fun consentChanged(event: ConsentChangedEvent) {
        // React to consent changed
    }

    override fun showNotice(event: ShowNoticeEvent) {
        // React to notice being shown
    }
})
```

{% endtab %}
{% endtabs %}

## Event types

This section presents a comprehensive list of the event types exposed by the Didomi SDK and usage examples.

### consentChanged

Triggered when the user consent status changes, either as the result of a user action or an API call.

**Listener parameters**

`ConsentChangedEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void consentChanged(ConsentChangedEvent event) {
        // The consent status of the user has changed
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun consentChanged(event: ConsentChangedEvent) {
        // The consent status of the user has changed
    }
})
```

{% endtab %}
{% endtabs %}

### error

Triggered when an unexpected situation occurs, for example an error during the initialization process.

#### **Listener parameters**

`ErrorEvent` object with the following properties:

| Name           | Type               | Description                                                                                                                                                                                                                                             |
| -------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `errorMessage` | `String`           | String describing the reason of the error.                                                                                                                                                                                                              |
| `errorType`    | `ErrorType` (enum) | <p>One of the following values:</p><p><code>NULL\_PROPERTY</code>, <code>CONFIG\_FILE\_ERROR</code>, <code>INVALID\_API\_KEY</code>, <code>INITIALIZATION\_ERROR</code>, <code>WEB\_SDK\_ERROR</code> or <code>ERROR\_LOADING\_UI\_RESOURCE</code>.</p> |

#### **Example**

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void error(ErrorEvent event) {
        // An error occurred with message `event.errorMessage`
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
  override fun error(event: ErrorEvent) {
    // An error occurred with message `event.errorMessage`
  }
})
```

{% endtab %}
{% endtabs %}

### hideNotice

Triggered when the user closes the consent notice. If you have disabled our default consent notice to replace it with your own, you need to hide your custom notice when this event gets triggered.

**Listener parameters**

`HideNoticeEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void hideNotice(HideNoticeEvent event) {
        // The notice is being hidden
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun hideNotice(event: HideNoticeEvent) {
        // The notice is being hidden
    }
})
```

{% endtab %}
{% endtabs %}

### showNotice

Triggered when the consent notice gets shown to the user. If you have disabled our default consent notices to replace them with your own, you need to show your custom notice when this event gets triggered.

**Listener parameters**

`ShowNoticeEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void showNotice(ShowNoticeEvent event) {
        // The notice is being shown
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun showNotice(event: ShowNoticeEvent) {
        // The notice is being shown
    }
})
```

{% endtab %}
{% endtabs %}

### noticeClickAgree

Triggered when the user clicks on the `Agree and close` button of a consent notice.

**Listener parameters**

`NoticeClickAgreeEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void noticeClickAgree(NoticeClickAgreeEvent event) {
        // Click on agree on notice
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun noticeClickAgree(event: NoticeClickAgreeEvent) {
        // Click on agree on notice
    }
})
```

{% endtab %}
{% endtabs %}

### noticeClickDisagree

Triggered when the user clicks on the `Decline` button of a consent notice.

**Listener parameters**

`NoticeClickDisagreeEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void noticeClickDisagree(NoticeClickDisagreeEvent event) {
        // Click on disagree on the notice
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun noticeClickDisagree(event: NoticeClickDisagreeEvent) {
        // Click on disagree on the notice
    }
})
```

{% endtab %}
{% endtabs %}

### noticeClickMoreInfo

Triggered when the user clicks on the `Learn More` button of a consent notice.

**Listener parameters**

`NoticeClickMoreInfoEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void noticeClickMoreInfo(NoticeClickMoreInfoEvent event) {
        // Click on learn more on notice
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun noticeClickMoreInfo(event: NoticeClickMoreInfoEvent) {
        // Click on learn more on notice
    }
})
```

{% endtab %}
{% endtabs %}

### noticeClickViewVendors

Triggered when the user clicks on the partners link/button of a consent notice.

**Listener parameters**

`NoticeClickViewVendorsEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void noticeClickViewVendors(NoticeClickViewVendorsEvent event) { 
        // Click on partners link/button from the notice
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun noticeClickViewVendors(event: NoticeClickViewVendorsEvent) { 
        // Click on partners link/button from the notice
    }
})
```

{% endtab %}
{% endtabs %}

### noticeClickViewSPIPurposes

Triggered when the user clicks on the Sensitive Personal Information button of a consent notice.

**Listener parameters**

`NoticeClickViewSPIPurposesEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void noticeClickViewSPIPurposes(NoticeClickViewSPIPurposesEvent event) { 
        // Click on Sensitive personal information button from the notice
    }
});
```

{% endtab %}

{% tab title="Koltin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun noticeClickViewSPIPurposes(event: NoticeClickViewSPIPurposesEvent) { 
        // Click on Sensitive personal information button from the notice
    }
})
```

{% endtab %}
{% endtabs %}

### noticeClickPrivacyPolicy

Triggered when the user clicks on the privacy policy button of a consent notice (available on TV only)

**Listener parameters**

`NoticeClickPrivacyPolicyEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void noticeClickPrivacyPolicy(NoticeClickPrivacyPolicyEvent event) { 
        // Click on privacy policy on the TV notice
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun noticeClickPrivacyPolicy(event: NoticeClickPrivacyPolicyEvent) {
        // Click on privacy policy on the TV notice
    }
})
```

{% endtab %}
{% endtabs %}

### hidePreferences

Triggered when the preferences screen becomes hidden, for example when the user closed it or saved their consent.

**Listener parameters**

`HidePreferencesEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void hidePreferences(HidePreferencesEvent event) {
        // The preferences screen is being hidden
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun hidePreferences(event: HidePreferencesEvent) {
        // The preferences screen is being hidden
    }
})
```

{% endtab %}
{% endtabs %}

### showPreferences

Triggered when the preferences screen gets displayed.

**Listener parameters**

`ShowPreferencesEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void showPreferences(ShowPreferencesEvent event) {
        // The preferences screen is being shown
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun showPreferences(event: ShowPreferencesEvent) {
        // The preferences screen is being shown
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickAgreeToAll

Triggered when the user clicks on the `Agree to all` button of the preferences screen.

**Listener parameters**

`PreferencesClickAgreeToAllEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickAgreeToAll(PreferencesClickAgreeToAllEvent event) {
        // Click on agree to all on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickAgreeToAll(event: PreferencesClickAgreeToAllEvent) {
        // Click on agree to all on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickDisagreeToAll

Triggered when the user clicks on the `Disagree to all` button of the preferences screen.

**Listener parameters**

`PreferencesClickDisagreeToAllEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickDisagreeToAll(PreferencesClickDisagreeToAllEvent event) {
        // Click on disagree to all on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickDisagreeToAll(event: PreferencesClickDisagreeToAllEvent) {
        // Click on disagree to all on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickSaveChoices

Triggered when the user clicks on the `Save` button of the preferences screen.

**Listener parameters**

`PreferencesClickSaveChoicesEvent` object (contains no properties)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickSaveChoices(PreferencesClickSaveChoicesEvent event) {
        // Click on save on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickSaveChoices(event: PreferencesClickSaveChoicesEvent) {
        // Click on save on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickPurposeAgree

Triggered when the user agrees to an individual purpose on the preferences screen.

**Listener parameters**

`PreferencesClickPurposeAgreeEvent` object with the following property:

<table data-header-hidden><thead><tr><th>Method</th><th width="171.33333333333331">Type</th><th>Description</th></tr></thead><tbody><tr><td>Method</td><td>Type</td><td>Description</td></tr><tr><td><code>purposeId</code></td><td>String</td><td>Unique ID of the purpose that was enabled</td></tr></tbody></table>

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickPurposeAgree(PreferencesClickPurposeAgreeEvent event) {
        String purposeId = event.getPurposeId();
        // Agree to a purpose on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickPurposeAgree(event: PreferencesClickPurposeAgreeEvent) {
        val purposeId = event.purposeId
        // Agree to a purpose on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickPurposeDisagree

Triggered when the user disagrees to an individual purpose on the preferences screen.

**Listener parameters**

`PreferencesClickPurposeDisagreeEvent` object with the following property:

| Method      | Type   | Description                                |
| ----------- | ------ | ------------------------------------------ |
| `purposeId` | String | Unique ID of the purpose that was disabled |

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickPurposeDisagree(PreferencesClickPurposeDisagreeEvent event) {
        String purposeId = event.getPurposeId();
        // Disagree to a purpose on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickPurposeDisagree(event: PreferencesClickPurposeDisagreeEvent) {
        val purposeId = event.purposeId
        // Disagree to a purpose on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickCategoryAgree

Triggered when the user agrees to a purposes category on the preferences screen.

**Listener parameters**

`PreferencesClickCategoryAgreeEvent` object with the following property:

| Method       | Type   | Description                                |
| ------------ | ------ | ------------------------------------------ |
| `categoryId` | String | Unique ID of the category that was enabled |

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickCategoryAgree(PreferencesClickCategoryAgreeEvent event) {
        String categoryId = event.getCategoryId();
        // Agree to a category on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickCategoryAgree(event: PreferencesClickCategoryAgreeEvent) {
        val categoryId = event.categoryId
        // Agree to a category on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickCategoryDisagree

Triggered when the user disagrees to a purposes category on the preferences screen.

**Listener parameters**

`PreferencesClickCategoryDisagreeEvent` object with the following property:

| Method       | Type   | Description                                 |
| ------------ | ------ | ------------------------------------------- |
| `categoryId` | String | Unique ID of the category that was disabled |

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickCategoryDisagree(PreferencesClickCategoryDisagreeEvent event) {
        String categoryId = event.getCategoryId();
        // Disagree to a category on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickCategoryDisagree(event: PreferencesClickCategoryDisagreeEvent) {
        val categoryId = event.categoryId
        // Disagree to a category on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickViewVendors

Triggered when the user clicks on `View Vendors` buttons on the preferences screen.

**Listener parameters**

`PreferencesClickViewVendorsEvent` object (contains no properties)

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickViewVendors(PreferencesClickViewVendorsEvent event) {
        // Click view vendors on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickViewVendors(event: PreferencesClickViewVendorsEvent) {
        // Click view vendors on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickViewSPIPurposes

Triggered when the user clicks on `Sensitive Personal Information` button from preferences screen.

**Listener parameters**

`PreferencesClickViewSPIPurposesEvent` object (contains no property)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickViewSPIPurposes(PreferencesClickViewSPIPurposesEvent event) { 
        // Click on view Sensitive Personal Information from the preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickViewSPIPurposes(event: PreferencesClickViewSPIPurposesEvent) { 
        // Click on view Sensitive Personal Information from the preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickVendorAgree

Triggered when the user agrees to an individual vendor on the preferences screen.

**Listener parameters**

`PreferencesClickVendorAgreeEvent` object with the following property:

| Method     | Type   | Description                              |
| ---------- | ------ | ---------------------------------------- |
| `vendorId` | String | Unique ID of the vendor that was enabled |

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickVendorAgree(PreferencesClickVendorAgreeEvent event) {
        String vendorId = event.getVendorId();
        // Agree to a vendor on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickVendorAgree(event: PreferencesClickVendorAgreeEvent) {
        val vendorId = event.vendorId
        // Agree to a vendor on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickVendorDisagree

Triggered when the user disagrees to an individual vendor on the preferences screen.

**Listener parameters**

`PreferencesClickVendorDisagreeEvent` object with the following property:

| Method     | Type   | Description                               |
| ---------- | ------ | ----------------------------------------- |
| `vendorId` | String | Unique ID of the vendor that was disabled |

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickVendorDisagree(PreferencesClickVendorAgreeEvent event) {
        String vendorId = event.getVendorId();
        // Disagree to a vendor on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickVendorDisagree(event: PreferencesClickVendorAgreeEvent) {
        val vendorId = event.vendorId
        // Disagree to a vendor on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickAgreeToAllVendors

Triggered when the user agrees to all the vendors through the global switch on the preferences screen.

**Listener parameters**

`PreferencesClickAgreeToAllVendorsEvent` object (contains no property)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickAgreeToAllVendors(PreferencesClickAgreeToAllVendorsEvent event) {
        // Flip ON all vendors switch on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickAgreeToAllVendors(event: PreferencesClickAgreeToAllVendorsEvent) {
        // Flip ON all vendors switch on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickDisagreeToAllVendors

Triggered when the user disagrees to all the vendors through the global switch on the preferences screen.

**Listener parameters**

`PreferencesClickDisagreeToAllVendorsEvent` object (contains no property)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickDisagreeToAllVendors(PreferencesClickDisagreeToAllVendorsEvent event) {
        // Flip OFF all vendors switch on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickDisagreeToAllVendors(PreferencesClickDisagreeToAllVendorsEvent event) {
        // Flip OFF all vendors switch on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickVendorSaveChoices

Triggered when the user clicks on `Save` button on the vendors view on preferences screen.

**Listener parameters**

`PreferencesClickVendorSaveChoicesEvent` object (contains no property)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickVendorSaveChoices(PreferencesClickVendorSaveChoicesEvent event) {
        // Click on save on the vendors view on preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickVendorSaveChoices(event: PreferencesClickVendorSaveChoicesEvent) {
        // Click on save on the vendors view on preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickViewPurposes

Triggered when the user clicks on `View Purpose` button from preferences screen (available only on TV).

**Listener parameters**

`PreferencesClickViewPurposesEvent` object (contains no property)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickViewPurposes(PreferencesClickViewPurposesEvent event) { 
        // Click on view purposes on the TV preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickViewPurposes(event: PreferencesClickViewPurposesEvent) { 
        // Click on view purposes on the TV preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickAgreeToAllPurposes

Triggered when the user agrees to all the purposes through the global switch on the preferences screen.

**Listener parameters**

`PreferencesClickAgreeToAllPurposesEvent` object (contains no property)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickAgreeToAllPurposes(PreferencesClickAgreeToAllPurposesEvent event) { 
        // Flip ON all purposes switch on the preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickAgreeToAllPurposes(event: PreferencesClickAgreeToAllPurposesEvent) {
        // Flip ON all purposes switch on the preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickDisagreeToAllPurposes

Triggered when the user disagrees to all the purposes through the global switch on the preferences screen.

**Listener parameters**

`PreferencesClickDisagreeToAllPurposesEvent` object (contains no property)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickDisagreeToAllPurposes(PreferencesClickAgreeToAllPurposesEvent event) { 
        // Flip OFF all purposes switch on the preferences popup
    }
});
```

{% endtab %}
{% endtabs %}

### preferencesClickSPIPurposeAgree

Triggered when the user agrees to an individual Personal Data purpose from the preferences screen.

**Listener parameters**

`PreferencesClickSPIPurposeAgreeEvent` object with the following property:

<table data-header-hidden><thead><tr><th>Method</th><th width="171.33333333333331">Type</th><th>Description</th></tr></thead><tbody><tr><td>Method</td><td>Type</td><td>Description</td></tr><tr><td><code>purposeId</code></td><td>String</td><td>Unique ID of the purpose that was enabled</td></tr></tbody></table>

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickSPIPurposeAgree(PreferencesClickSPIPurposeAgreeEvent event) {
        String purposeId = event.getPurposeId();
        // Agree to a Personal Data purpose from preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickSPIPurposeAgree(event: PreferencesClickSPIPurposeAgreeEvent) {
        val purposeId = event.purposeId
        // Agree to a Personal Data purpose from preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickSPIPurposeDisagree

Triggered when the user disagrees to an individual Personal Data purpose from the preferences screen.

**Listener parameters**

`PreferencesClickSPIPurposeDisagreeEvent` object with the following property:

| Method      | Type   | Description                                |
| ----------- | ------ | ------------------------------------------ |
| `purposeId` | String | Unique ID of the purpose that was disabled |

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickSPIPurposeDisagree(PreferencesClickSPIPurposeDisagreeEvent event) {
        String purposeId = event.getPurposeId();
        // Disagree to a Personal Data purpose from preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickSPIPurposeDisagree(event: PreferencesClickSPIPurposeDisagreeEvent) {
        val purposeId = event.purposeId
        // Disagree to a Personal Data purpose from preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickSPICategoryAgree

Triggered when the user agrees to a Personal Data category from the preferences screen.

**Listener parameters**

`PreferencesClickSPICategoryAgreeEvent` object with the following property:

| Method       | Type   | Description                                |
| ------------ | ------ | ------------------------------------------ |
| `categoryId` | String | Unique ID of the category that was enabled |

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickSPICategoryAgree(PreferencesClickSPICategoryAgreeEvent event) {
        String categoryId = event.getCategoryId();
        // Agree to a Personal Data category from preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickSPICategoryAgree(event: PreferencesClickSPICategoryAgreeEvent) {
        val categoryId = event.categoryId
        // Agree to a Personal Data category from preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickSPICategoryDisagree

Triggered when the user disagrees to a Personal Data category from the preferences screen.

**Listener parameters**

`PreferencesClickSPICategoryDisagreeEvent` object with the following property:

| Method       | Type   | Description                                 |
| ------------ | ------ | ------------------------------------------- |
| `categoryId` | String | Unique ID of the category that was disabled |

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickSPICategoryDisagree(PreferencesClickSPICategoryDisagreeEvent event) {
        String categoryId = event.getCategoryId();
        // Disagree to a Personal Data category from preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickSPICategoryDisagree(event: PreferencesClickSPICategoryDisagreeEvent) {
        val categoryId = event.categoryId
        // Disagree to a Personal Data category from preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### preferencesClickSPIPurposeSaveChoices

Triggered when the user clicks on `Save` button from the Sensitive Personal Information view from preferences screen.

**Listener parameters**

`PreferencesClickSPIPurposeSaveChoicesEvent` object (contains no property)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void preferencesClickSPIPurposeSaveChoices(PreferencesClickSPIPurposeSaveChoicesEvent event) {
        // Click on save on the Sensitive Personal Information view from preferences popup
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun preferencesClickSPIPurposeSaveChoices(event: PreferencesClickSPIPurposeSaveChoicesEvent) {
        // Click on save on the Sensitive Personal Information view from preferences popup
    }
})
```

{% endtab %}
{% endtabs %}

### syncUserChanged

Triggered when the user is changed from [setUser](/cmp/mobile-sdk/react-native/reference#setuser) function only if sync is enabled.

**Listener parameters**

`SyncUserChangedEvent` object with the following property:

<table data-header-hidden><thead><tr><th>Method</th><th width="171.33333333333331">Type</th><th>Description</th></tr></thead><tbody><tr><td>Method</td><td>Type</td><td>Description</td></tr><tr><td><code>userAuth</code></td><td>UserAuth</td><td>The new user as <code>UserAuthWithoutParams</code>, <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code></td></tr></tbody></table>

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void syncUserChanged(SyncUserChangedEvent event) { 
        UserAuth userAuth = event.userAuth
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun syncUserChanged(event: SyncUserChangedEvent) {
        val userAuth = event.userAuth
    }
})
```

{% endtab %}
{% endtabs %}

### syncDone

{% hint style="warning" %}
This event has been deprecated. Use [syncReady](#syncready) instead.
{% endhint %}

Triggered when the consent synchronization is successful (Cross-device).

**Listener parameters**

`SyncDoneEvent` object (contains no property)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void syncDone(SyncDoneEvent event) { 
        // Synchronization success
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun syncDone(event: SyncDoneEvent) {
        // Synchronization success
    }
})
```

{% endtab %}
{% endtabs %}

### syncError

Triggered when the consent synchronization has failed (Cross-device).

**Listener parameters**

`SyncErrorEvent` object (contains no property)

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void syncError(SyncErrorEvent event) { 
        // Synchronization failure
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun syncError(event: SyncErrorEvent) {
        // Synchronization failure
    }
})
```

{% endtab %}
{% endtabs %}

### **syncReady**

Triggered when the user status synchronization is ready (cross-device).

**Listener parameters**

`SyncReadyEvent` object

| Property           | Type              | Description                                                                                                                                                                                          |
| ------------------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| organizationUserId | String            | The organization user ID (OUID) used for the sync.                                                                                                                                                   |
| statusApplied      | Boolean           | Indicates if the user status has been applied locally from the remote Didomi backend. `true` if the user status was applied from the remote, `false` otherwise.                                      |
| syncAcknowledged   | Lambda expression | Callback that can be used to communicate to the Didomi servers that the synchronization has been communicated to the user. Returns `true` if the API event was successfully sent, `false` otherwise. |

**Example**

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void syncReady(SyncReadyEvent event) { 
        // User status synchronization was successful.
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun syncReady(event: SyncReadyEvent) {
        // User status synchronization was successful.
    }
})
```

{% endtab %}
{% endtabs %}

### languageUpdated

Triggered when SDK language has been successfully changed.

**Listener parameters**

`LanguageUpdatedEvent` object with the following property:

<table data-header-hidden><thead><tr><th>Method</th><th width="171.33333333333331">Type</th><th>Description</th></tr></thead><tbody><tr><td>Method</td><td>Type</td><td>Description</td></tr><tr><td><code>languageCode</code></td><td>String</td><td>The language code applied</td></tr></tbody></table>

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void languageUpdated(LanguageUpdatedEvent event) { 
        // Language has been changed
        String languageCode = event.languageCode;
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun languageUpdated(event: LanguageUpdatedEvent) {
        // Language has been changed
        val languageCode = event.languageCode
    }
})
```

{% endtab %}
{% endtabs %}

### languageUpdateFailed

Triggered when SDK language update has failed.

**Listener parameters**

`LanguageUpdateFailedEvent` object with the following property:

<table data-header-hidden><thead><tr><th>Method</th><th width="171.33333333333331">Type</th><th>Description</th></tr></thead><tbody><tr><td>Method</td><td>Type</td><td>Description</td></tr><tr><td><code>reason</code></td><td>String</td><td>The reason of the failure</td></tr></tbody></table>

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void languageUpdateFailed(LanguageUpdateFailedEvent event) { 
        // Language update failure
        String reason = event.reason;
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun languageUpdateFailed(event: LanguageUpdateFailedEvent) {
        // Language update failure
        val reason = event.reason
    }
})
```

{% endtab %}
{% endtabs %}

### integrationError

Triggered when an integration with an external SDK is not working as expected. The currently supported external SDKs are **Firebase**, **Airbridge**, **AppsFlyer**, and **Branch** (see related documentation [here](/cmp/mobile-sdk/google-consent-mode#how-does-it-work-on-apps)). This event indicates that Didomi was not able to update the privacy signals for the specified SDK.

**Listener parameters**

`IntegrationErrorEvent` object with the following properties:

<table data-header-hidden><thead><tr><th>Method</th><th width="171.33333333333331">Type</th><th>Description</th></tr></thead><tbody><tr><td>Method</td><td>Type</td><td>Description</td></tr><tr><td><code>integrationName</code></td><td>String</td><td>Name of the failing SDK integration, such as <code>Firebase SDK</code>, <code>Airbridge SDK</code>...</td></tr><tr><td><code>reason</code></td><td>String</td><td>Technical reason of the failure</td></tr></tbody></table>

#### Example

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

```java
Didomi.getInstance().addEventListener(new EventListener() {
    @Override
    public void integrationError(IntegrationErrorEvent event) { 
        // An external SDK integration is not working properly
        Log.w(event.integrationName + " : Integration error - " + event.reason);
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
Didomi.getInstance().addEventListener(object : EventListener() {
    override fun integrationError(event: IntegrationErrorEvent) {
        // An external SDK integration is not working properly
        Log.w("${event.integrationName} : Integration error - ${event.reason}")
    }
})
```

{% endtab %}
{% endtabs %}


# Versions

### 2.47.0 (August 3, 2026)

**Features:**

* Update translations and embedded GVL version.

**Fixes:**

* Forward `sdkPath` and `apiPath` to the Web SDK so notices displayed in a WebView load their static files and reach the API through the custom domain.
* Fix network connectivity detection when the device is connected through a VPN.

### 2.46.0 (July 21, 2026)

**Features:**

* Update translations and embedded GVL version.

**Fixes:**

* Stop resetting `userId` during `clearUser()`.

### 2.45.0 (July 6, 2026)

**Features:**

* App V2 (WebView): Fix user ID mismatch between native and web components.
* Add `sdkPath` and `apiPath` parameters to `DidomiInitializeParameters` to override the base URLs used for static files and API requests respectively.

### 2.44.0 (June 16, 2026)

**Features:**

* Add `frameworks` field to user payload in API events.
* Add API events to monitor deprecated `Didomi` methods usage.
* Add API events to monitor UI rendering time.

**Fixes:**

* Include the public API key (`key` query parameter) on `/sign`, `/sync` and `/batch-sign` API requests to allow access logs to be attributed to the originating organization.

### 2.43.0 (May 25, 2026)

**Features:**

* Add default obfuscation requirement for Firebase Consent Mode.
* Add error `cause` in `ErrorEvent`.
* Add API events to monitor some `Didomi` methods usage.

**Fixes:**

* Handle predictive Back feature for 'targetSdk' version 36+.
* Android TV: Make Read More button reachable on Vendor data processing details screen.
* Memory leak: Prevent `Didomi` callbacks from retaining `Activity` references.
* Prevent merging custom vendors with Didomi vendors when configuration does not request it.
* Gracefully handle invalid vendor ids in GVL.

### 2.42.0 (May 4, 2026)

**Features:**

* Update translations and embedded GVL version.

### 2.41.1 (April 21, 2026)

**Fixes:**

* Fix IllegalStateException / BadTokenException when showing Consent Dialog.

### 2.41.0 (April 20, 2026)

**Features:**

* IAB TCF: Apply April 2026 updates including SDK items and new `specialPurposes` and `optOut` fields for cookie disclosures.
* IAB TCF: Apply cache control for vendor device storage disclosures.
* Update GPP library to use `@iabgpp/cmpapi` version `3.1.8` which adds support for `UsMn` section.

**Fixes:**

* Reset ready state so `isReady()` returns false during re-initialization.

### 2.40.0 (April 7, 2026)

**Features:**

* Add API events to monitor SDK initialization performance.

**Fixes:**

* GPP: Improve handling of GPP fields when user regulation changes.

### 2.39.0 (March 23, 2026)

**Features:**

* Update translations and embedded GVL version.
* GCM: Update privacy signals transmitted to `Firebase`, `AppsFlyer` and `Branch` integrations.

### 2.38.0 (March 9, 2026)

**Features:**

* Update translations and embedded GVL version.

**Fixes:**

* DCS and App V2: Improve status handling for vendors defined by Didomi.
* Android TV: Improve focus navigation from Preferences screens without accessibility enabled.
* App V2: Use legacy Web SDK when device WebView version does not support modern JavaScript features. Note: If GPP is enabled, these devices will fallback to App V1 UI.

### 2.37.0 (February 23, 2026)

**Features:**

* Update translations and embedded GVL version.

**Fixes:**

* Android TV: Wrong text-to-speech element focus on back from purpose or partner details.

### 2.36.2 (February 9, 2026)

**Fixes:**

* Prevent triggering onConsentChanged event after a call to `clearUser()`.
* Load bundle logo image from App v2 (WebView)

### 2.36.1 (January 28, 2026)

**Fixes:**

* Address conflicting use cases between `TCF 2.2` and `TCF 2.3`.

### 2.36.0 (January 26, 2026)

**Features:**

* TCF 2.3: Add value `IABTCF_DisclosedVendors` to shared preferences.
* Allow to safely exclude Zipline library when adding Didomi dependency. More information can be found in [Advanced setup & troubleshooting](/cmp/mobile-sdk/android/setup/advanced-setup-and-troubleshooting#zipline-library) page.

**Fixes:**

* Android TV - Accessibility: Update default focus from secondary screen for easier key event interception.

### 2.35.0 (January 12, 2026)

**Features:**

* Android TV: Make sure content can be scrolled when it is too big in some screens:
  * Purpose details
  * Additional data processing
  * Device storage disclosure
  * User information

**Fixes:**

* GCM: Make sure external SDKs are updated even when consent types are not specified in the configuration.
* Android TV: Fix focus on Purpose details screen.

### 2.34.0 (December 1, 2025)

**Features:**

* Android TV: Add support for the `preferences.enableAllButtons` configuration parameter.
* Add support for the `preferences.vendorsLayer.enabled` configuration parameter.
* GCM: Improve accuracy of privacy signals transmitted to `Firebase`, `AppsFlyer` and `Branch` integrations.

**Fixes:**

* Add the missing footer on the Additional Data Processing Details screen.
* Improve consent recollection behavior after GVL updates.
* Correct an issue affecting notices with DCS enabled, where IAB TCF String did not contain the purposes status.
* Android TV: Revert focus catcher on notice initialization when screen reader is enabled but notice. Description message will still be spelled first.

### 2.33.0 (November 6, 2025)

**Features:**

* Android TV: Improve navigation / focus management.
* Android TV: Accessibility improvements.

**Fixes:**

* GPP values were not correctly saved in SharedPreferences and were not returned in `CurrentUserStatus`.
* Android TV: Fix additional cases of incorrect padding rendering on preferences screens.

### 2.32.1 (January 28, 2026)

{% hint style="info" %}
This is the minimum required SDK version to fully support IAB TCF v2.3 consent notices on Android and Android TV.
{% endhint %}

**Fixes:**

* Address conflicting use cases between `TCF 2.2` and `TCF 2.3`.

### 2.32.0 (October 24, 2025)

**Features:**

* Handle new requirements for TCF 2.3 in the TC String:
  * TC String now contains the Disclosed Vendors segment.
  * When consent and legitimate interest purposes are all disabled, Vendors with consent or legitimate interest purposes are marked as disabled even if they present special purposes.
* Update GPP library version.

**Fixes:**

* AndroidTV: In some cases, padding was not rendered correctly on CTV preferences screens.

### 2.31.1 (October 7, 2025)

**Fixes:**

* Fix obfuscation issue for GCM integration event handler introduced in [2.31.0](#id-2.31.0-october-3-2025).
* Android TV: apply fix to prevent `lateinit property bindingPrimary has not been initialized`.

### 2.31.0 (October 3, 2025)

{% hint style="danger" %}
To use this SDK version, your app must target min API 21 or above.
{% endhint %}

**Features:**

* Remove support for min APIs 19 and 20.
* Improve accessibility descriptions for Android TV.
* Add alphabetical headers to the list of vendors.
* Add event handlers to GCM integrations.
* Support new US regulations:
  * Minnesota Consumer Data Privacy Act (`MCDPA`).
  * Maryland Online Data Privacy Act (`MODPA`).
  * Rhode Island Data Transparency and Privacy Protection Act (`RIDTPPA`).
  * Indiana Consumer Data Protection Act (`INCDPA`).
  * Kentucky Consumer Data Protection Act (`KCDPA`).
  * Nebraska Data Privacy Act (`NDPA`).
  * Tennessee Information Protection Act (`TIPA`).

**Fixes:**

* Android TV: Remove the focus transitions to prevent performances issues on some devices.
* Android TV: Focus was lost when exiting Privacy Policy Screen from the Notice.

### 2.30.0 (September 17, 2025)

{% hint style="warning" %}
To use this SDK version, your app must target at least Android API version 35.

Note: targeting API 35 is required to publish apps on the Play Store since August 31, 2025.
{% endhint %}

**Features:**

* Android TV: improve accessibility on `Notice`, `Purposes` and `Vendors` screens.
* Upgrade target and compile SDK versions to 35.

**Fixes:**

* Make sure Activity is resumed before trying to display Notice or Preferences to prevent crashes.
* Apply fix to prevent `kotlin.UninitializedPropertyAccessException: lateinit property component has not been initialized` on Android TV and App V2 (Webview)

### 2.29.0 (August 12, 2025)

**Features:**

* Android TV: update behaviour of toggles.

**Fixes:**

* App v2 (WebView): apply fix to prevent `UninitializedPropertyAccessException: lateinit property uiProvider has not been initialized`.

### 2.28.0 (August 1, 2025)

**Feature:**

* Add new `GCM` integration: Appsflyer.

**Fixes:**

* Accessibility: re-structured `Vendor Details` screen.
* Android TV: applied fix to prevent `IllegalStateException` in some specific focus change use cases.

### 2.27.0 (July 17, 2025)

**Features:**

* Add `GCM` support for `Firebase`, `AirBridge`, `Branch` and `Kochava`.
* Update dependencies:
  * Dagger from `2.55` to `2.56`.
  * Gson from `2.12.1` to `2.13.1`.

**Fixes:**

* The order of the Purposes list is now respected when a `Purpose` is declared as `Purpose Category`.
* Accessibility: Fix screen reader focus management from the *Storage Disclosures* screen.
* Remove embedded configurations for deprecated `TCF v2.1` .
* AndroidTV: Address crash report from `IllegalStateException` when requesting the activity from the fragments.

### 2.26.0 (June 20, 2025)

{% hint style="info" %}
This version includes support for App v2 (WebView) mode. You can enable this feature from the Console. More information is available [here](https://docs.didomi.io/consent-management-platform-cmp/consent-notices/mobile-app-v2-webview).
{% endhint %}

**Features:**

* Add support for App v2 (WebView) mode.
* Accessibility: added missing heading roles in multiple screens.
* Accessibility: re-structured `User Information` screen.
* Accessibility: improved navigation on the `Device Storage Disclosure` screen within vendor details.

**Fixes:**

* In `CurrentUserStatus` object, `shouldUserStatusBeCollected()` method was not publicly accessible

### 2.25.1 (May 28, 2025)

**Features:**

* Add new languages support (Belarus, Bosnian, Basque, English Canada, Galician, Georgian, Maltese, Albanian, Tagalog, Welsh)

{% hint style="info" %}
New languages must be enabled from the Console once they are available.
{% endhint %}

**Fixes:**

* Update properties of the Facebook vendor provided by Didomi

### 2.24.1 (April 30, 2025)

Fixes:

* Revert serialized names for `CurrentUserStatus` object.

### 2.24.0 (April 25, 2025)

**Features:**

* Add boolean field to identify if `preferences.purposechanged` API event is triggered from a Purpose Category screen or not.

**Fixes:**

* Android TV: prevent Save button from updating vendor statuses.

### 2.23.0 (April 16, 2025)

**Features:**

* Update accessibility descriptions for Preferences screens.
* Update `Didomi Consent String` computation (*beta*).

Fixes:

* Add missing Header (logo or App name) from the Storage of your choices screen.
* Prevent navigation button to overlap if the label is too long from the Device Storage Disclosures screen.

### 2.22.0 (April 3, 2025)

**Features:**

* Update accessibility description for Preferences screens.
* When a vendor is not associated with legitimate interest purposes but has special purposes, always include it in IAB TCF Consent String legitimate interest vendors section (IAB TCF update).
* Trigger `SyncReady` event even when `Cross-Device` feature is disabled.
* Additional focus customization option for Android TV.
* Add new screen to display `User Information` for Android TV in order to match with mobile SDK.

### 2.21.0 (March 18, 2025)

**Features:**

* Add new features to `CurrentUserStatus` returned by [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus):
  * `gppString` field (*beta*).
  * Utility method `shouldUserStatusBeCollected()` .
* Modify the layout of the bottom bar buttons on the Preferences screen.
* Handle configuration parameter `preferences.enableAllButtons` .

### 2.20.0 (March 4, 2025)

**Features:**

* Replace checkboxes with switches for legitimate interest-based purposes on AndroidTV.
* Update status labels for buttons and switches from the Preferences screen on AndroidTV.
* Update GPP library version (*beta*).

Fixes:

* Set AndroidTV activities `exported` flag to `false` in manifest.

### 2.19.1 (February 11, 2025)

**Fixes:**

* Cross-device: Make sure remote consent expiration is checked before applying consent synchronization.

### 2.19.0 (January 30, 2025)

**Features:**

* Create new `setUser` function that accepts an instance of the new `DidomiUserParameters` (more information [here](/cmp/mobile-sdk/android/reference/api#setuser)).
* Deprecate the other `setUser` functions (more information [here](/cmp/mobile-sdk/android/reference/api/deprecated#setuser)).

**Fixes:**

* Make sure the Purpose view is not shown before the Vendor view when the user requests the Vendor view from the Notice.
* Stop forcing capital letters from the Notice's action button.

### 2.18.0 (January 9, 2025)

**Features:**

* Use Java 11 to build the SDK (more information [here](/cmp/mobile-sdk/android/setup#add-the-sdk-to-your-project)).
* Created new applicableRegulation public API that provides a string value (`CPRA`, `GDPR`, `NONE`, etc.) containing the regulation being applied (more information [here](/cmp/mobile-sdk/android/reference/api#applicableregulation)).

**Fixes:**

* Optimize performance when updating the consent from the cross-device response.
* The Purpose list's bulk action subtitle was always the same despite being enabled or not from Android TV preferences.

### 2.17.1 (December 13, 2024)

**Features:**

* Add US regulation support for Utah: `ucpa`.

### 2.17.0 (December 11, 2024)

**Features:**

* Add support for `syncUserChanged` callback. See reference [here](/cmp/mobile-sdk/android/reference/events#syncuserchanged) for more information.
* Accessibility: Increase contrast in toggle buttons icons.
* Stop displaying Sensitive Personal Information in a separate screen.

**Fixes:**

* Fix `ConcurrentModificationException` related to SDK events.

### 2.16.2 (November 29, 2024)

**Fixes:**

* Fix a `ConcurrentModificationException` occurring sometimes when consent status is updated while `setUser` is called or status is retrieved asynchronously.
* Accessibility: Sticky notice buttons were not always enabled when using only TalkBack to read the notice text.

### 2.16.1 (November 19, 2024)

**Fixes:**

* Update translations and embedded GVL version.

### 2.16.0 (November 8, 2024)

{% hint style="info" %}
`DidomiEventListener` interface implementations need to override 2 new callbacks: `dcsSignatureReady` / `dcsSignatureError`. These callbacks implementation can be left empty as they should not be active in this SDK version.
{% endhint %}

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

```kotlin
@UiThread
override fun dcsSignatureError(event: DcsSignatureErrorEvent) = Unit

@UiThread
override fun dcsSignatureReady(event: DcsSignatureReadyEvent) = Unit
```

{% endtab %}

{% tab title="Java" %}

```java
@Override
public void dcsSignatureReady(@NonNull DcsSignatureReadyEvent event) {}

@Override
public void dcsSignatureError(@NonNull DcsSignatureErrorEvent event) {}
```

{% endtab %}
{% endtabs %}

**Fixes:**

* When overriding IAB vendors with custom vendors, prevent overriding vendor id with custom id.
* Prevent `ConcurrentModificationException` when setting and getting user status.

### 2.15.0 (October 24, 2024)

**Features:**

* Add new `organizationUserId` parameter for `SyncReady` event (see [documentation](/cmp/mobile-sdk/android/reference/events#syncready)).

**Fixes:**

* Get consent from server when `setUser` is called. If the user is new, you will need to call `setupUI` to display the notice. In order to display the notice automatically, you can call `setUser` and provide the `activity` (see [documentation](/cmp/mobile-sdk/share-consents-across-devices#multi-account)).
* Hide privacy policy button from AndroidTV's notice when the link is blank.
* Trim translations before displaying the purpose list.

### 2.14.0 (October 10, 2024)

**Features:**

* Update translations and embedded GVL version.

### 2.13.1 (October 8, 2024)

**Fixes:**

* Update embedded `QuickJS` library in order to support 16 KB page sizes (see [here](https://developer.android.com/guide/practices/page-sizes) for more information).
* Fix notice's description display when the text contains link and justification is enabled.
* Update Kotlin dependencies from `1.9.20` to `1.9.23`.
* Update Kotlin coroutines dependency from `1.8.1` to `1.9.0`.

### 2.13.0 (October 1, 2024)

**Fixes:**

* Update translations and embedded GVL version.

### 2.12.0 (September 13, 2024)

**Features:**

* Support Serbian latin language script
* Rename `IDPL` regulation to `ICDPA`

### 2.11.0 (August 22, 2024)

**Features:**

* Use **API 34** for compiling our SDK and update dependencies:
  * **Dagger** plugin and dependencies from `2.51.1` to `2.52`.
  * **Kotlin** plugin from `1.8.20` to `1.9.20`.
  * `com.google.code.gson:gson` from `2.10.1` to `2.11.0`.
  * `com.google.android.material:material` from `1.6.1` to `1.12.0`.

{% hint style="warning" %}
Your application **must target API 34** starting this version (required from Google Play Store starting August 31, 2024).
{% endhint %}

### 2.10.1 (August 20, 2024)

**Fixes:**

* Make sure `DidomiToggle` is not obfuscated.
* Make sure sticky buttons behave correctly when scrolling the content of the notice.

### 2.10.0 (July 30, 2024)

**Features:**

* Implement First Party Vendors support.
* Support Publisher TC segment from the Consent String.

**Fixes:**

* Merge duplicated Vendors declared from different sources (IAB, Didomi, Custom).

### 2.9.0 (July 15, 2024)

**Features:**

* Add support for TCF v2.2 amendments (implement new `Storage Disclosure` button and screen).

### 2.8.0 (June 21, 2024)

**Features:**

* Add support for new regulations: `dpdpa`, `fdbr`, `idpl`, `mcdpa`, `nhpa`, `njdpa`, `ocpa` and `tdpsa`.
* Set a minimum frequency for user synchronization process.
* Only rely on configuration obtained from Didomi to determine the user regulation.

{% hint style="warning" %}
From this version, local configuration fields `gdprAppliesGlobally` and `gdprAppliesWhenUnknown` are ignored. To adapt notice behavior to user country, it is now mandatory to use remote configuration. See [here](/cmp/mobile-sdk/android/setup#from-the-console-recommended) for more information.
{% endhint %}

* Mark obsolete methods as `Deprecated`:

  * `isConsentRequired`
  * `isUserConsentStatusPartial`
  * `isUserLegitimateInterestStatusPartial`
  * `getUserStatus`

  See the complete list of currently deprecated methods [here](/cmp/mobile-sdk/android/reference/api/deprecated).
* Support for `IABTCF_EnabledAdvertiserConsentMode` for Google Consent Mode, through the configuration flag `integrations.vendors.gcm.enableTCFAdvertiserConsentMode`. See the [related documentation](/cmp/mobile-sdk/google-consent-mode#enabling-consent-modes-tcf-integration) for more information.

**Fixes:**

* Prevent SDK translations to be removed from compiled app when `shrinkMode` option is set to `strict`.
* On Android TV, bulk action buttons state was not consistent after scrolling.
* IAB purposes 1 or 2 could incorrectly appear in notice and consent string when using vendors with Special Features.
* Make sure a fallback is provided in case a translation is missing for an IAB element.
* Prevent thread safety issues when SDK listens to connectivity status.

### 2.7.0 (June 6, 2024)

**Features:**

* Update logic around setting the vendors' status based on purposes' status.

**Fixes:**

* Modify package name of IAB TCF encoder/decoder fork from `com.iabtcf.*` to `io.didomi.iabtcf.*` to prevent duplicate classes issue.

### 2.6.1 (May 30, 2024)

**Fixes:**

* Prevent external link icon to be stretched depending on the font size.
* Increase the margin between title and toggle from the Sensitive Personal Information item.
* Make the Sensitive Personal Information section title bold.

### 2.6.0 (May 10, 2024)

**Features:**

* Display an icon indicating when a link targets a page outside of the application.
* Add field `isIAB` in `Vendor` object to indicate if vendor is from the IAB Global Vendor List.

**Fixes:**

* Do not obfuscate parameters class of `setUser(...)` method.

### 2.5.1 (April 26, 2024)

**Features:**

* Add new parameters to `DidomiInitializeParameters` to override the user location determined by the SDK when getting the notice configuration:
  * `countryCode`: Force the user country used to get the notice configuration.
  * `regionCode` : Force the user region used to get the notice configuration.
* Add support for new `SyncReady` event. See the [event documentation](/cmp/mobile-sdk/android/reference/events#syncready) for more information.
* Deprecate `SyncDone` event.

### 2.5.0 (April 26, 2024)

{% hint style="warning" %}
This version has obfuscation issues and should not be used.
{% endhint %}

### 2.4.0 (April 10, 2024)

**Features:**

* Make sure that vendors removed from the GVL are not present in the notice or in the IAB Consent String when the IAB TCF framework is enabled.
* Increase contrast for secondary texts to improve readability.

**Fixes:**

* Add a proguard rule regarding `kotlinx.parcelize.Parcelize` to avoid issues in some projects configurations.

### 2.3.1 (March 28, 2024)

**Fixes:**

* Vendors status updates were ignored when using `openCurrentUserStatusTransaction` method.

### 2.3.0 (March 27, 2024)

**Features:**

* Deprecate CCPA regulation.
* Set values for `IABTCF_CmpSdkID`, `IABTCF_CmpSdkVersion`, `IABTCF_PolicyVersion` and `IABTCF_gdprApplies` even when GDPR does not apply.

**Fixes:**

* Rename incorrect `openCurrentUserTransaction` method to `openCurrentUserStatusTransaction`.

### 2.2.0 (March 18, 2024)

**Features:**

* Create new `openCurrentUserStatusTransaction` method which returns an instance of `CurrentUserStatusTransaction`. This class can be used to asynchronously enable and disable specific vendors and purposes. For more information, see the [documentation](https://developers.didomi.io/cmp/mobile-sdk/android/reference/api#opencurrentuserstatustransaction).
* Display Purpose Categories for Android TV.
* Update dependencies:
  * `com.google.zxing:core` from `3.5.2` to `3.5.3`
  * `org.jetbrains.kotlinx:kotlinx-coroutines-jdk8` from `1.7.3` to `1.8.0`
  * Dagger dependencies from `2.50` to `2.51`

**Fixes:**

* Stop exposing `GSON` library as a transitive dependency.
* Stop Exposing `IAB TCF Decoder` library as a transitive dependency.
* Update the `getCurrentUserStatus` method so it marks as enabled those purposes that are enabled by default on the UI when the regulation applied is opt-out or mixed (e.g.: CPRA) and the user hasn’t expressed any choices yet.

### 2.1.0 (March 6, 2024)

**Features:**

* Create new `addVendorStatusListener` and `removeVendorStatusListener` methods to observe changes in the status of individual Vendors (For more information, see the [documentation](/cmp/mobile-sdk/android/reference/api#addvendorstatuslistener)).

**Fixes:**

* Sort Device Storage Disclosure list by `identifier` and `type` in order to prevent random order from the Vendor details screen.
* Align the `Privacy Policy` link to the left of the Vendor details screen.

### 2.0.1 (February 23, 2024)

**Fixes:**

* Make sure public inner classes `Vendor.Namespaces` and `Vendor.Url` are not obfuscated in the released SDK.
* Prevent unwanted line breaks in the notice text when using Bold font and Justified alignment.

### 2.0.0 (February 15, 2024)

{% hint style="danger" %}
**Major update of the SDK**

This release will contain some breaking changes, described below.

**Migration steps:**

1. Update ***Didomi SDK*** to version `1.90.0` if it is not already the case.
2. Replace any deprecated usages that might appear with the alternatives suggested by *Android Studio* (lint). If *Android Studio* does not suggest any updates, it means no deprecated methods are being used.
3. Update ***Didomi SDK*** to version `2.0.0`.
   {% endhint %}

{% hint style="danger" %}
The `Purpose` class returned by `getPurpose` and `getRequiredPurposes`, and the `Vendor` class returned by `getVendor` and `getRequiredVendors` were modified. If you encounter an issue with these changes (such as a removed field), please reach out to **<support@didomi.io>**.

Important notes:

* `Vendor.id` is now the ID provided by Didomi, without prefix
* `Purpose.description` is deprecated and should be replaced by `Purpose.descriptionText`
  {% endhint %}

**Features:**

* Set the minimum supported API version (`minSdk`) to `19`.
* Remove deprecated functions listed below:

  *Deprecated as of v1.31.0*

  * `setUserConsentStatus`
  * `setUserConsentStatusFromObjects`

  [`setUserStatus`](/cmp/mobile-sdk/android/reference/api#setuserstatus) or [`setCurrentUserStatus`](/cmp/mobile-sdk/android/reference/api#setcurrentuserstatus) should be used instead.

  *Deprecated as of v1.42.0*

  * `(get)disabledPurposeIds`
  * `(get)disabledPurposes`
  * `(get)disabledVendorIds`
  * `(get)disabledVendors`
  * `(get)enabledPurposeIds`
  * `(get)enabledPurposes`
  * `(get)enabledVendorIds`
  * `(get)enabledVendors`

  [`(get)userStatus`](/cmp/mobile-sdk/android/reference/api#getuserstatus) or [`(get)currentUserStatus`](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) should be used instead.

  * `initialize` (without `DidomiInitializeParameters`)

  *Deprecated as of v1.43.0*

  * `setUser` (with authentication parameters instead of `UserAuthParams`)

  *Deprecated as of v1.43.1*

  * `getUserConsentStatusForPurpose`
  * `getUserConsentStatusForVendor`
  * `getUserConsentStatusForVendorAndRequiredPurposes`
  * `getUserLegitimateInterestStatusForPurpose`
  * `getUserLegitimateInterestStatusForVendor`
  * `getUserLegitimateInterestStatusForVendorAndRequiredPurposes`
  * `getUserStatusForVendor`

  [`(get)userStatus`](/cmp/mobile-sdk/android/reference/api#getuserstatus) or [`(get)currentUserStatus`](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) should be used instead.

  *Deprecated as of v1.45.0*

  * `setUserStatus` (with `sendAPIEvent` parameter)
  * `setUserStatusFromObjects`

  [`setUserStatus`](/cmp/mobile-sdk/android/reference/api#setuserstatus) or [`setCurrentUserStatus`](/cmp/mobile-sdk/android/reference/api#setcurrentuserstatus) should be used instead.
* Update dependencies (`com.google.code.gson:gson` from `2.9.1` to `2.10.1` and `androidx.recyclerview:recyclerview` from `1.3.1` to `1.3.2`).
* Update Didomi brand logo for AndroidTV notices.
* Update `showPreferences` parameter for **Sensitive Personal Information** screen (see [showPreferences](/cmp/mobile-sdk/android/reference/api#showpreferences)) and prevent displaying this screen if there is no such purpose to display.
* Modified `Purpose` class returned by methods `getPurpose` and `getRequiredPurposes`. See details below:
  * `id` (*String*) the Purpose ID.
  * `name` (*String*) the Purpose name.
  * `descriptionText` (*String*) the Purpose description. This property replaces the previous `description` property.
  * Removed properties:
    * `iabId` (*String?*)
    * `descriptionLegal` (*String?*)
    * `illustrations` (*List\<String>?*)
    * `isConsent` (*Boolean*)
    * `isEssential` (*Boolean*)
    * `isLegitimateInterest` (*Boolean*)
    * `isSpecialFeature` (*Boolean*)
    * `type` (*String?*)
    * `iabConsentRequired` (*Boolean*)
    * `iabLiRequired` (*Boolean*)
    * `category` (*PurposeCategory?*)
    * `isConsentNotEssential()` (*Boolean*)
    * `isLegitimateInterestNotEssential()` (*Boolean*)
    * `isLegitimateInterestOnly()` (*Boolean*)
* Modified `Vendor` class returned by methods `getVendor` and `getRequiredVendors`. See details below:
  * `id` (*String*) the Vendor ID provided by Didomi without any prefix.
  * `name` (*String*) the Vendor name.
  * `namespaces` (*Namespaces?*) the Namespaces of the vendor (*IAB*, *num*) and their corresponding ids.
  * `policyUrl` (*String*) the privacy policy URL (replace `privacyPolicyUrl`).
  * `purposeIds` (*List\<String>*) the Purpose list with legal basis "consent".
  * `legIntPurposeIds` (*List\<String>*) the Purpose list with legal basis "legitimate interest".
  * `featureIds` (*List\<String>*) the ID list that represent features.
  * `flexiblePurposeIds` (*List\<String>*) the ID list that represent flexible purposes.
  * `specialFeatureIds` (*List\<String>*) the ID list that represent Special Features.
  * `specialPurposeIds` (*List\<String>*) the ID list that represent Special Purposes.
  * `urls` (*List\<Url>?*) the localized Privacy policy and LI disclaimer urls introduced in TCF v2.2.
  * Removed properties:
    * `namespace` (*String*)
    * `iabId` (*String?*)
    * `cookieMaxAgeSeconds` (*Long?*)
    * `usesNonCookieAccess` (*Boolean*)
    * `deviceStorageDisclosureUrl` (*String?*)
    * `dataDeclaration` (*Set\<String>*)
    * `dataRetention` (*DataRetention?*)
    * `didomiId` (*String?*)
    * `isIABVendor` (*Boolean*)
    * `isIabVendor` (*Boolean*)
    * `essentialPurposeIds` (*List\<String>*)
    * `deviceStorageDisclosures` (*DeviceStorageDisclosures?*)
    * `isDeviceStorageDisclosureComplete` (*Boolean*)
    * `hasLegIntClaim` (*Boolean*)

**Fixes:**

* Ensure that the focus cannot go back to the `SELECT` title from AndroidTV notice for APIs 27 and below.
* Stop filtering vendors if they don't have any purposes but data declaration.

### 1.90.0 (February 8, 2024)

**Features:**

* Hide `Sensitive Personal Information` button from the Notice and Preferences screens if there is no such purpose to display.
* Ensure that regulation `NONE` will behave as expected (no consent required, notice and preferences screens can't be displayed and all vendors and purposes are enabled).

### 1.89.0 (January 22, 2024)

**Features:**

* Use default country code then default language when custom translations are missing for selected language.
* Create new public function `setCurrentUserStatus()` (See [setCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#setcurrentuserstatus) for more information).
* Create new public function `getCurrentUserStatus()` (See [getCurrentUserStatus](/cmp/mobile-sdk/android/reference/api#getcurrentuserstatus) for more information).

**Fixes:**

* Fix typo in TCF 2.2 notice for Spanish translation.

### 1.88.0 (January 11, 2024)

**Features:**

* Update Didomi brand logo for preferences screens.
* Create new public function `isUserStatusPartial()` (See [isUserStatusPartial](/cmp/mobile-sdk/android/reference/api#isuserstatuspartial) for more information).
* Create new public function `shouldUserStatusBeCollected()` (See [shouldUserStatusBeCollected](/cmp/mobile-sdk/android/reference/api#shoulduserstatusbecollected) for more information).

**Fixes:**

* Serbian translation was containing some Latin labels instead of Cyrillic.
* The consent stored after the first launch of an application could contain some discrepancies.
* Wrong padding for the Purpose's Vendor list screen for some devices.

### 1.87.0 (December 12, 2023)

**Features:**

* Set TCF version 2.2 as default version (current TCF 2.1 notices will be treated as TCF 2.2 notices).

### 1.86.3 (December 6, 2023)

**Fixes:**

* Temporarily disable internal use of WebView component.

### 1.86.2 (December 4, 2023)

**Fixes:**

* Fix Hebrew and Indonesian translations not displayed correctly on some devices.
* Fix to ignore purposes and special features coming from Custom Vendors when creating the TCF Consent String.

### 1.86.1 (November 23, 2023)

**Fixes:**

* Setup Notice logo constraints. Maximum height is now set to `150dp`.
* Publisher restrictions now applies to `Facebook` vendor.
* Fix Polish translation for Partners count label on Notice screen.

### 1.86.0 (November 17, 2023)

**Features:**

* Update IAB policy links URLs to <https://iabeurope.eu/iab-europe-transparency-consent-framework-policies/>.
* Add support for new language regions: Arabic (Jordan), Dutch (Belgium), English (New Zealand), English (United Kingdom), French (Belgium), French (Canada), German (Austria), German (Switzerland).
* Handle Regulation field (`user.regs`) in synchronization requests and API events.
* Specify "non-IAB partners" instead of just "partners" when presenting count of partners associated to a purpose.
* Update list of purposes associated to Facebook vendor.
* Handle `notice.enableBulkActionOnPurpose` config parameter, to allow to hide the `enable / disable all purposes` switch on preferences screen.
* Use Kotlin 1.8.20.

### 1.85.1 (November 7, 2023)

**Fixes:**

* Remove dependencies `androidx.javascriptengine:javascriptengine` and `com.google.guava:guava` to prevent compatibility issues.

### 1.85.0 (November 6, 2023)

{% hint style="info" %}
This is the minimum required sdk version to fully handle TCF v2.2 notices on Android and Android TV.
{% endhint %}

**Features:**

* Add methods to get vendors count: [`getTotalVendorCount()`](/cmp/mobile-sdk/android/reference/api#gettotalvendorcount), [`getIabVendorCount()`](/cmp/mobile-sdk/android/reference/api#getiabvendorcount), [`getNonIabVendorCount()`](/cmp/mobile-sdk/android/reference/api#getnoniabvendorcount)
* Enable non-transitive R class in the SDK (Didomi resources will not be present anymore in application `R` class, only in `io.didomi.sdk.R`)
* Deprecate `Vendor.isIABVendor` and add `Vendor.isIabVendor` to use instead

**Fixes:**

* Support IAB purpose 11 from TCF 2.2 (`Use limited data to select content`)
* Remove unwanted dependency `com.google.firebase:firebase-crashlytics-buildtools:2.9.9`
* Update exported proguard rules for `gson` as advised in R8 documentation.

### 1.84.1 (October 20, 2023)

**Fixes:**

* Handle translation of TCF v2.2 purposes even when there is no internet connection.
* Improve performance on vendors screen.
* Update proguard rules for `gson` as advised in R8 documentation.

### 1.84.0 (October 17, 2023)

{% hint style="info" %}
This version added support for TCF v2.2 notices on AndroidTV. However it does not correctly handle purpose 11 (`Use limited data to select content`), sdk version 1.85.0 or higher should be used instead.
{% endhint %}

**Features:**

* Full TCF v2.2 support for AndroidTV.
* Change label of "View our partners" notice button to "Manage our partners" .

**Fixes:**

* Improve loading time to display the list of vendors associated to a purpose.
* Incorrect UI layout for purposes illustrations, vendor details and the list of vendors associated to a purpose on tablet.

### 1.83.1 (October 5, 2023)

**Fixes:**

* Revert dependency `com.google.android.material:material` to version `1.6.1` to allow use of gradle versions < `7.3.3` (required for Unity).
* Trim names of some IAB vendors containing additional trailing space.

### 1.83.0 (October 4, 2023)

{% hint style="info" %}
This version added support for TCF v2.2 notices on Android devices. However it does not correctly handle purpose 11 (`Use limited data to select content`), sdk version 1.85.0 or higher should be used instead.
{% endhint %}

**Features:**

* TCF v2.2 support.
* Revert the design and label of the partners button displayed on the notice (underlined / "View our partners").
* Update Target SDK from 31 to 33.
* Add support for new macros (`numberOfPartners`, `numberOfIABPartners` and `numberOfNonIABPartners`) from the Preferences screens, see the full list [here](/cmp/web-sdk/consent-notice/preferences#macros).
* Remove support of `notice.content.viewOurPartners` configuration parameter from AndroidTV Notice (the same default label as mobile will be used).

**Fixes:**

* Prevent crash from notice when calling the `setUser` function multiple times.

### 1.82.0 (September 19, 2023)

**Features:**

* Better layouts (fonts, margins, etc...) for `Additional Data Processing`, `Purposes` and `Vendors` detail screens.

**Fixes:**

* Add missing IAB tag on `Vendor` detail screen.
* Prevent duplicated screens when user is clicking multiple times.
* Manage empty privacy policy url from `Custom Vendor` detail screen.

### 1.81.1 (August 17, 2023)

**Fixes:**

* Prevent crash if `Android System WebView` is not available.

### 1.81.0 (July 18, 2023)

**Features:**

* Change the "Learn More" link into button.

### 1.80.0 (July 7, 2023)

**Features:**

* In notice, modify design of "Manage our partners" and "Learn more" links
* In vendor details screen, move links to IAB and privacy policy outside of privacy policy disclaimer (improves accessibility)
* Mark `disableDidomiRemoteConfig` initialization parameter as deprecated.

{% hint style="info" %}
Didomi SDK configuration should be done through the console. In the future, local configuration file will no longer be supported.
{% endhint %}

**Fixes:**

* GDPR was not correctly applied for additional countries set in console.

### 1.79.1 (June 15, 2023)

**Fixes:**

* Modify code related to `synchronized` and `try` / `catch` to avoid `VerifyError` during initialization when using JaCoCo plugin (see error description [here](https://salesforce.stackexchange.com/a/402982))

### 1.79.0 (June 14, 2023)

{% hint style="info" %}
This version has build issues in some configurations, it should not be used.
{% endhint %}

### 1.78.1 (May 4, 2023)

**Fixes:**

* Fix crash with Android < 21.
* Compute opposite color from 3 digits color code (for Button theme).
* Prevent blank `Sensitive Personal Information` button from Preferences (*Purposes*) if the label is not provided by the configuration.

### 1.78.0 (April 20, 2023)

**Features:**

* Display message on Sensitive Personal Information screen when no Personal Data is present.
* Display IAB TCF tag for IAB Vendors on AndroidTV vendor screens.

### 1.77.0 (April 3, 2023)

**Features:**

* Enable **`CPRA`** regulation support.
* Create new `Sensitive Personal Information` screens.
* Create new Internal events for `Sensitive Personal Information` interactions (see [Events](/cmp/mobile-sdk/android/reference/events)).
* Update `Additional Data Processing` list from `Purpose` screen in order to improve accessibility.

**Fixes:**

* Notice underlined buttons were not underlined on APIs below 26.
* Fix padding issue for multiline label from Preferences screens `Save` / `Save and close` button.

### 1.76.0 (March 20, 2023)

**Features:**

* Add a link to `privacyPolicyURL` on preferences (Purpose) screen when the link is not present in text description.
* Remove link to `privacyPolicyURL` in embedded default preferences (Purpose) screen description.

**Fixes:**

* Throw exception when `clearUser()` is called before SDK initialization.
* Fix conflicting color resources.

### 1.75.2 (March 8, 2023)

**Fixes:**

* Improve accessibility description of Vendor bulk action.

### 1.75.1 (February 28, 2023)

**Fixes:**

* Fix line break from Notice description and Vendor header description.
* Update proguard consumer rules in order to prevent obfuscation of Didomi classes.

### 1.75.0 (February 22, 2023)

**Features:**

* Accessibility improvements in Purposes and Vendors screen.
* Call `onError` callback when invalid API key is passed to `Didomi.initialize`.

**Fixes:**

* Prevent duplicated publisher restriction from configuration.
* Fix accessibility description for Essential Purposes.

### 1.74.0 (February 8, 2023)

**Features:**

* Accessibility improvements in
  * Partners button on main notice
  * Purposes screen
  * Purpose details buttons
  * Vendors screen
  * Vendor details buttons
* New User Information button from the Vendor screen.

### 1.73.0 (January 25, 2023)

**Features:**

* Accessibility improvements on the Notice screen.
* Accessibility improvements on the Purpose screen.
* Update proguard consumer rules in order to keep class member only for the Didomi package.

**Fixes:**

* Add missing subtitle "*Select partners*" for Vendor screen.
* Some large title could overlap the close button in Preferences screens (Purpose and Vendor).
* Some configurations allowed the Purpose screen to be closed even when the parameter `preferences.canCloseWhenConsentIsMissing` was *false*.

### 1.72.1 (December 15, 2022)

**Fixes:**

* Rendering issue when preferences screen header text contained html lists.

### 1.72.0 (December 14, 2022)

**Features:**

* Allow font family to be applied to all UI elements on the screen (see [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#custom-font-family) for more details).
* Cross-device: do not reset Didomi User ID by default, unless `clearUser` is called (see [Share consents across devices](/cmp/mobile-sdk/share-consents-across-devices#multi-account) for more details).

### 1.71.0 (November 17, 2022)

**Features:**

* Remove TCF v1 support.
* Supporting url and resource name from `logoUrl` configuration parameter.

### 1.70.2 (October 27, 2022)

**Fixes:**

* SetupUI was not working properly with specific Android project configurations, throwing an exception.

```
AndroidJavaException: java.lang.AbstractMethodError: abstract method "void androidx.lifecycle.DefaultLifecycleObserver.onStart(androidx.lifecycle.LifecycleOwner)"
```

### 1.70.1 (October 21, 2022)

**Fixes:**

* Fix Toggle colors not changing for older APIs (< 24).
* Fix Toggle state not updated on click when the view holder is recycled for older APIs (< 27).

### 1.70.0 (October 19, 2022)

**Features:**

* Optimize display of Purpose legal description.
* Update `kotlin` plugin from 1.5.31 to 1.7.20.
* Update `appcompat` library from 1.3.1 to 1.4.2.
* Update `material` library from 1.4.0 to 1.6.1.
* Improve AndroidTV performance.

**Fixes:**

* Prevent crash when Application is brought back from background and the Didomi SDK is not initialized from the Application class.
* Fix device language not correctly handled for Hebrew and Indonesian.

### 1.69.0 (September 16, 2022)

**Features:**

* Add ability to enable sticky buttons on the notice (see [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#sticky-buttons)).
* Disable location query from device GPS when the location permissions are granted (we now rely only on our API to get the user location and to provide the matching regulation).

**Fixes:**

* Update link to IAB TCF v2 from the vendor detail page.
* Prevent CCPA "Sell my data" toggle neutral state.

### 1.68.0 (September 13, 2022)

**Features**:

* Add support for [CCPA regulation](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/cmp/mobile-sdk/android/broken-reference/README.md)

{% hint style="info" %}
CCPA support is still in beta, please contact <support@didomi.io> if you are interested to participate
{% endhint %}

### 1.67.0 (September 8, 2022)

**Features:**

* Accessibility improvements on the vendors list
* Improved accessibility on buttons displayed on the notice.

**Fixes:**

* Consent asked events was using all required purposes as both consent and legitimate interest.
* Fix toggle buttons behaviour when using purpose categories

### 1.66.0 (August 26, 2022)

**Features:**

* Improve accessibility of close buttons and headings on Preferences screens.

**Fixes:**

* Fix missing button padding on some devices for AndroidTV.
* Fix a lifecycle issue causing not initialized properties errors (e.g. `Fatal Exception: kotlin.UninitializedPropertyAccessExceptionlateinit property themeProvider has not been initialized`).

### 1.65.0 (August 8, 2022)

**Features:**

* Add ability to enable fullscreen mode (see [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#fullscreen-mode) for more details).
* Handle device storage disclosure as link (instead of json) from IAB vendor list.
* Improve accessibility of Preferences screen.

**Fixes:**

* Add missing bottom bar for Vendor details page.
* Fix crash when displaying details of vendor with an incorrect device storage disclosure URL (`java.lang.NullPointerException: Attempt to invoke virtual method 'boolean io.didomi.sdk.models.DeviceStorageDisclosure.isValid()' on a null object reference`)

### 1.64.0 (July 21, 2022)

**Features:**

* Query purposes for current language in order to always provide up-to-date translations.
* Add new events for language change (see [Events](/cmp/mobile-sdk/android/reference/events#languageupdated) and [Events](/cmp/mobile-sdk/android/reference/events#languageupdatedfailed) for more details).

{% hint style="info" %}
`updateSelectedLanguage` is now asynchronous.
{% endhint %}

{% hint style="info" %}
`setUser(null)` is no more available. The correct call is `clearUser()` (see [API](/cmp/mobile-sdk/android/reference/api#clearuser) for more details).
{% endhint %}

**Fixes:**

* Fix layout on additional data processing page.
* Disable neutral state when controlled value is legitimate interest.

### 1.63.0 (June 27, 2022)

**Features:**

* Handle mutli-account for Cross-device feature (see [Share consents across devices](/cmp/mobile-sdk/share-consents-across-devices#multi-account) for more details).
* Allow to customize font family of title and description in notice and preferences screen (see [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#custom-font-family) for more details).
* Hide bulk action in purposes and vendors screens when there is only one item in the list.
* Allow to call `reset()` method while SDK is not initialized.

### 1.62.0 (June 10, 2022)

**Features:**

* Add an optional title field in notice (see [Customize the notice](/cmp/mobile-sdk/consent-notice/customize-the-notice#texts) for more details)
* Allow to customize font size, color and alignment of title and description in notice and preferences screen (see[Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#notice), [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#preferences) for more details)

**Fixes:**

* Prevent notice text scrolling outside of pop-up window

### 1.61.1 (May 30, 2022)

**Fixes:**

* Fix possible crash when app and notice were restored after staying a very long time in the background.

### 1.61.0 (May 17, 2022)

**Features:**

* Handle custom background color (see [Customize the theme & UI](https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme#color) for more detail).

**Fixes:**

* When notice was displayed to the user but no choice was made yet, the IAB consent string contained an incorrect list of enabled legitimate interest purposes.
* Vendor device storage disclosure list was not displayed on devices below API 21.

### 1.60.0 (April 27, 2022)

**Features:**

* Update design for tablets.
* Add new languages support (Norwegian, Brazilian, Azerbaijani, Bengali, Filipino/Tagalog, Hebrew, Hindi, Indonesian, Macedonian, Swahili).

{% hint style="info" %}
New languages must be enabled from the Console once they are available.
{% endhint %}

**Bug fixes:**

* Remove Purpose and Vendor bulk action when only essential/required purposes are used.
* Incorrect toggles animation while scrolling
* Fix issues when legitimate interest purposes are set as essential
* Fix a crash on Android TV preferences screen when using essential purposes

### 1.59.1 (April 4, 2022)

**Features:**

* Migrate `Didomi` class to Kotlin
* Improve banner notice layout
* Add a default background color for secondary buttons

**Fixes:**

* Fix dependencies conflict with some libraries, producing the error `java.lang.VerifyError: Verifier rejected class`

### 1.59.0 (April 4, 2022)

{% hint style="info" %}
This version can produce crashes and should not be used
{% endhint %}

### 1.58.0 (March 18, 2022)

**Features:**

* Improve accessibility of User Information screen
* Update ConstraintLayout dependency from 2.1.2 to 2.1.3

**Fixes:**

* Prevent glitch during Preferences screen animation for tablets
* Revert toggle change animation for purposes screen
* Prevent invisible toggle track for some application themes

### 1.57.0 (March 11, 2022)

**Features:**

* Allow multiple initializations of the SDK.
* Use Support Library for vector drawables (no more bitmaps generated for older APIs).
* Toggle and Switch components were migrated to Kotlin.

**Fixes:**

* Keep white background for the notice on Dark Mode.
* Remove empty space on the top of the notice with some themes (disable Dialog Title).

### 1.56.0 (March 4, 2022)

**Features:**

* Remove unnecessary permission `ACCESS_WIFI_STATE`.
* Improve accessibility for purposes and partners screens.
* Layout optimisation for CTV Vendors detail screens (layout simplification, use selector for components colors).
* Improve alignment in purposes list with optional icon.

### 1.55.0 (February 7, 2022)

{% hint style="info" %}
From this version, the Didomi SDK does no longer require `jcenter()` in the project repositories list.
{% endhint %}

**Features:**

* `Vendor` model class was migrated to Kotlin
* Embed a library which was hosted on deprecated JCenter repository, so JCenter is no longer required for building app

**Fixes:**

* Added the `didomi_` prefix before all Didomi SDK resource ids (layouts, drawables, colors, dimensions...) to prevent conflicts with app or other libraries resources
* Fix possible crash related to application lifecycle (`lateinit property model has not been initialized`)

### 1.54.0 (January 2022)

**Features:**

* Support new IAB rules regarding timestamp: the timestamp stored in the GDPR consent string has now only day-level granularity. See <https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/pull/306/files#diff-99d4d9da93e17e584b04a239a04503a776d54503b0e2db52fc157b77fc950bbbR65>
* `Purpose` model class was migrated to Kotlin

**Bug fixes:**

* The user consent update date was not correctly updated
* `syncDone` event was not called if last synchronization was still recent

### 1.53.0 (January 2022)

**Features:**

* Improve accessibility for the notice and purposes screens
* Migrate Didomi event classes to Kotlin

**Bug fixes:**

* Code javadoc was not published with the release

### 1.52.0 (December 2021)

**Features:**

* Optimize focus management on Android TV

**Bug fixes:**

* Apply “save”, “agree to all”, “disagree to all” to Vendors on Android TV preferences screen
* Saving Consent without any action will keep the current state of Vendors and Purposes on Android TV
* Fix Notice and Preferences layouts to prevent cropped text on Android TV
* Update displayed user status when reopening preferences screen on Android TV

### 1.51.2 (December 2021)

**Bug fixes:**

* Keep package name for obfuscated classes in order to prevent conflicts with other obfuscated libraries.

### 1.51.1 (December 2021)

{% hint style="info" %}
This release may cause conflicts with other obfuscated libraries. Please update to 15.1.2.
{% endhint %}

**Bug fixes:**

* Add missing @Keep annotation and avoid obfuscation of some parameters name that are exposed to host app.

### 1.51.0 (December 2021)

{% hint style="info" %}
This release may cause conflicts with other obfuscated libraries. Please update to 15.1.2.
{% endhint %}

**Features:**

* Update fallback data for IAB TCF global vendors list.
* Use `@Keep` annotation for obfuscation (no need for proguard rules anymore).
* Layouts optimization for performance.

### 1.50.0 (November 2021)

**Features:**

* Implement `showPreferences` / `hidePreferences` events when the preferences screen is opened and closed.

**Bug fixes:**

* Allow to modify the save button label in the vendors view through `preferences.content.save` property.
* Convert bitmap resources to vectorized resources.
* The common screen header had a few wrong margins.

### 1.49.0 (November 2021)

**Features:**

* Added Legitimate Interest in TCF Consent String by default once the notice has been shown.

**Bug fixes:**

* User Info screen was not displaying in fullscreen mode.
* Avoid random ConcurrentModificationException while synchronizing after several calls to Didomi#setUser
* The Purposes screen had a few wrong margins.

### 1.48.0 (October 2021)

#### **Bug fixes:**

* Simultaneous API event calls were sometimes skipped.

### 1.47.1 (October 2021)

**Bug fixes:**

* Get content from the remote if the cache date is valid but the file is corrupted or missing.

### 1.47.0 (October 2021)

**Features:**

* Handle deny option as a cross in notice

**Bug fixes:**

* Disabled vendors with only legitimate interest purposes were not present in `getUserStatus().vendors.global.disabled`
* Vendors with no associated consent or legitimate interest purposes were not present in `getUserStatus().vendors.global.enabled`
* In vendors screen, in some situations, a switch was displayed next to vendors with no associated consent or legitimate interest purposes

### 1.46.2 (September 2021)

**Bug fixes:**

* Consent String retrieved by the sdk was not correctly updated after consent changes

### 1.46.1 (September 2021)

**Bug fixes:**

* Fix incorrect serialization of `UserStatus` object when using Gson library

### 1.46.0 (September 2021)

**Features:**

* Add salesforce vendor to global configuration
* Update dependencies: Kotlin from `1.5.21` to `1.5.30`, Gson from `2.8.6` to `2.8.8`, Coroutines from `1.4.X` to `1.5.2`.

**Bug fixes:**

* Better focus management on vendors detail page for CTV

### 1.45.0 (September 2021)

**Features:**

* Add a parameter to determine if user consent choice was set from Didomi UI or from a call to `Didomi.setUserStatus`.
* Handle non-TCF purposes in device storage disclosures.
* When publisher restrictions applies to all vendors, apply it to non-IAB vendors as well.

**Bug fixes:**

* Vendor device storage disclosures were not displayed in some configurations.

### 1.44.0 (August 2021)

**Features:**

* Change the default focus on CTV notice according to CNIL guidelines.

### 1.43.2 (July 2021)

**Bug fixes:**

* Fix `getUserStatus()` method by correcting `vendors.globalLegitimateInterest` and `vendors.globalConsent` values.
* Fix Vendors bulk action for some configurations. The `All` toggle behavior was not working properly.
* Update french translation for `required`.

### 1.43.1 (July 2021)

{% hint style="info" %}
This version fixes an issue which prevented generation of the IAB-TCF consent string in some cases
{% endhint %}

**Bug fixes:**

* Update IAB-TCF encoding library to fix invalid consent string for some configurations.\
  Issue: <https://github.com/InteractiveAdvertisingBureau/iabtcf-java/pull/126/commits/a80bc4ce0bfb38120aaf8984091f2c512743f713>
* Fix User Info screen by adding scrollbars and fixing a crash after clipboard action on older devices.
* Update dependencies: Kotlin from `1.5.10` to `1.5.21` and Android Material from `1.3.0` to `1.4.0`.

### 1.43.0 (July 2021)

**Features:**

* Refactor dependency management that which will allow improving the performance of the SDK.

### 1.42.0 (July 2021)

{% hint style="info" %}
Important changes for Android TV apps:

* By default, the sdk is now disabled when running on Android TV. To enable it, you have to use the new `initialize` method with `DidomiInitializeParameters` , and set `androidTvEnabled` to `true`(see [reference](/cmp/mobile-sdk/android/reference/api#initialize))
* To use a specific notice configuration, you must set the parameter `tvNoticeId` instead of `noticeId`.
  {% endhint %}

**Features:**

* Add a `getUserStatus` method, replacing the previous methods to get user consent status. See the [reference](/cmp/mobile-sdk/android/reference/api#getuserstatus) for more information.
* Add a new initialization method with a `DidomiInitializeParameters` parameters object. This is the recommended way to initialize the sdk, the previous methods are now deprecated. See the [reference](/cmp/mobile-sdk/android/reference/api#initialize) for more information.
* Disable Android TV SDK by default, and add `androidTvEnabled` parameter to enable it. If you need to use the Android TV SDK, please reach out to your dedicated customer success manager.
* Add `tvNoticeId` parameter for Android TV SDK specific notice id.
* Ensure configuration is only loaded from Didomi on Android TV SDK.
* Add getDeviceType method to check the device determined by the SDK (see [reference](/cmp/mobile-sdk/android/reference/api#getdevicetype))
* Update androidx.appcompat dependency: `1.3.0`

**Bug fixes:**

* Fix Android TV preferences screen closing unexpectedly when switching from partners tab
* Fix material shadow under preferences screens buttons

### 1.41.3 (June 2021)

**Bug fixes:**

* `getRequiredVendorIds` method was only returning vendors with consent-based data processing instead of all the required vendors
* When reopening the preferences screen after setting user consent status programmatically (`setUserAgreeToAll` / `setUserDisagreeToAll` / `setUserStatus` methods), the displayed consent state was not correct

### 1.41.2 (June 2021)

**Features:**

* Removed separate internal vendors implementations, and turned `Vendor` interface into a class instead
* Prepare support for displaying device storage information for custom vendors

**Bug fixes:**

* Fix `hidePreferences` command when main preferences screen is not displayed
* Use density-independent pixels (dp) instead of raw pixels for theme buttons border and corner radius sizes. **In order to preserve existing configurations, this fix is under a feature flag**: set `sizesInDp` to `true` to use it (see [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#buttons) for more information)
* Fix material shadow under notice "Agree" button

  �

### 1.41.1 (May 2021)

**Bug fixes:**

* Manage languages with specific script code from device
* Handle vendor with no consent or LI in `getUserStatusForVendor`

### 1.41.0 (May 2021)

**Features:**

* Add new languages support, see <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-notice#supported-languages>
* Improve public methods documentation

### 1.40.2 (May 2021)

**Bug fixes:**

* Prevent incorrect buttons colors when using a non-Bridge `Theme.MaterialComponents.*` app theme

### 1.40.1 (May 2021)

**Features:**

* Improved header's layout and made bulk action sticky on the Vendors view

**Bug fixes:**

* Remove Lifecycle Observer after onResume was reached in setupUI

### 1.40.0 (April 2021)

**Features:**

* Allow to use Didomi SDK with simple `FragmentActivity` instead of `AppCompatActivity`
* Improve internal handling of Didomi fragments
* Remove internal use of some deprecated Android Framework features
* Added support for `app.deploymentId`.

**Bug fixes:**

* Fix a glitch of the "Agree to all" button in preferences screen

### 1.39.0 (April 2021)

{% hint style="warning" %}
We now use AndroidX instead of the support library. This means that your project must [enable AndroidX](https://developer.android.com/jetpack/androidx) to use this version.
{% endhint %}

{% hint style="warning" %}
Please note that this release replaces the Advertising ID provided by Google Ads Services for a random custom identifier.
{% endhint %}

**Features :**

* Allow users to see and copy their information (Consent Token and User Id)
* Remove ADID usage
* Use AndroidX (allowing you to disable jetifier in your project)

### 1.38.1 (April 2021)

**Features:**

* Support for denied consent duration (`app.deniedConsentDuration`)

**Bug fixes:**

* Fix possible crash when using some colors in configuration
* Choice buttons incorrectly displayed in essential purposes details screen
* Handle essentials purposes associated to vendor's legitimate interests

### 1.37.0 (March 2021)

**Features:**

* Support for Categories
* Change notice buttons order

**Bug fixes:**

* Fix Vendors with essential purposes that are disabled even when the user accepts all

### 1.36.0 (March 2021)

**Features:**

* Support for Android TV

**Bug fixes:**

* Do not raise Exception when calling `Didomi.updateSelectedLanguage` with an unavailable language code
* Fix custom purpose translations issues when language is not the default

### 1.35.1 (March 2021)

**Features:**

* Updated behaviour of `setUserDisagreeToAll` to be consistent with other platforms.
* Added support for the `denyAppliesToLI` feature in notice and preferences screen.
* Check if SDK is ready before using features `Didomi.updateSelectedLanguage`, `Didomi.getText`, `Didomi.getTranslatedText`.
* Sync user choices for cross-device. (This feature is currently in private beta. Please reach out to our Support team if you want to use it)

**Bugs fixes:**

* Rename conflicting `state` and `enabled` attributes.
* Fix custom essential purposes not displayed after language change.
* Modify SDK initialization logs from `info` to `verbose`.
* Prevent crash if the TCF Consent String is not present when syncing user choices with the Didomi API.

### 1.34.0 (March 2021)

{% hint style="info" %}
The Android Didomi SDK is now distributed through mavenCentral instead of deprecated JCenter. Make sure to update your build scripts: [Setup](/cmp/mobile-sdk/android/setup#add-the-sdk-to-your-project)
{% endhint %}

**Features:**

* Support for consent maximum duration (`app.consentDuration` , default is 12 months / 31,622,400 seconds)
* Distribute SDK through mavenCentral

**Fixes:**

* Fix an issue with some API events sample rate
* Prevent SDK from removing Camera permission
* Fix possible crash in vendor details screen

### 1.33.0 (February 2021)

**Features:**

* Added support to include Publisher Country Code into Consent String

**Bug fixes:**

* Fix vendor details screen behavior on scroll

### 1.32.0 (February 2021)

**Features:**

* Added ability to display "Continue without agreeing" link on the notice (`notice.denyAsLink = true`).

### 1.31.0 (January 2021)

**Features :**

* Show a Disagree button on consent notice by setting `notice.type = "optin"`
* Use primary button style for the disagree button by setting `notice.denyAsPrimary = true`
* Evolution of UI design
* Add new method `setUserStatus(purposesConsentStatus, purposesLIStatus, vendorsConsentStatus, vendorsLIStatus)` to set status globally
* Deprecate old method `setUserConsentStatus(enabledPurposeIds, disabledPurposeIds, enabledLegitimatePurposeIds, disabledLegitimatePurposeIds, enabledVendorIds, disabledVendorIds, enabledLegIntVendorIds, disabledLegIntVendorIds)` and replace it with a new method `setUserStatus` with the same signature

**Bug fixes :**

* Fix consent notice pop-up width too small on some devices

### 1.30.0 (January 2021)

**Features :**

* Indicate platform and SDK version when downloading notice configuration
* Added support for TCF v2.1

### 1.29.1 (January 2021)

**Bug fixes :**

* Fallback to English resources if requested locale was stripped by app bundles
* Fix incorrect or missing Google vendor after language change
* Prevent a crash when requesting notice display directly

### 1.29.0 (December 2020)

**Features :**

* Device storage usage information in the detailed view for each vendor
* Update texts provided by IAB

### 1.28.0 (December 2020)

{% hint style="warning" %}
Please note that this release includes the ability to download the GVL (Global Vendor List) file. If you don't want the SDK initialization to wait for this step, set the `app.vendors.iab.requireUpdatedGVL` flag to false as explained here : <https://developers.didomi.io/cmp/mobile-sdk/android/setup#download-global-vendor-list-gvl>
{% endhint %}

**Features :**

* Essential/Required purposes section in the detailed view for each vendor
* Download the GVL (Global Vendor List)

### 1.27.0 (November 2020)

**Features :**

* Send TCF and Additional Consent information in API events
* Optimize publisher restrictions encoding in Consent String
* Modify additional data processing links color in purposes screen

**Bug fixes :**

* Fix daysBeforeShowingAgain parameter preventing consents recollection unexpectedly

### 1.26.2 (November 2020)

**Bug fixes :**

* Fix pageview API event sent when app is still in background
* Update embedded proguard rules

### 1.26.1 (October 2020)

**Features :**

* GVL update
* Detailed additional data processing information
* Remove TCFv1 storage keys when TCFv2 is enabled

**Bug fixes :**

* Ensure that the legitimate interest status is correctly passed to Webviews in `getJavaScriptForWebView`

### 1.25.0 (October 2020)

**Features :**

* Support for publisher restrictions
* Improve SDK initialization time
* Update notice default texts
* Allow disabling TCF from config
* Export javadoc

**Bug fixes :**

* Dynamic buttons size in Preferences screen
* Potential crash in purpose details screen

### 1.24.2 (September 2020)

**Bug fixes :**

* After modifying purposes consent manually, it was not possible to save if a purpose was only available under legitimate interest.

### 1.24.0 (September 2020)

**Features :**

* Support for `user.ignoreConsentBefore` parameter in config file, to force recollecting consent after a certain date
* Added status accessors in `Didomi` class : `getUserLegitimateInterestStatusForVendor`, `getUserLegitimateInterestStatusForPurpose`, `getUserLegitimateInterestStatusForVendorAndRequiredPurposes`, `getUserStatusForVendor`

### 1.23.0 (September 2020)

**Features :**

* Support for organization user ID: `Didomi#setUser()`
* TCF v2: Do not display toggle for vendors with no consent or legitimate interest purpose
* Do not display vendors with no associated purpose

**Bug fixes :**

* Fix callback events `PreferencesClickPurposeAgreeEvent`, `PreferencesClickPurposeDisagreeEvent`, `PreferencesClickVendorAgreeEvent`, `PreferencesClickVendorDisagreeEvent` triggered several times when modifying purpose or vendor choices
* Increase notice pop-up width
* Do not display notice pop-up "Learn more" and "Accept" buttons on the same line if there is not enough space
* Fix notice bottom banner "Accept" button not displayed correctly

### 1.22.2 (September 2020)

**Bug fixes :**

* Prevent `ConcurrentModificationException` occurring from time to time when adding an EventListener

### 1.22.1 (September 2020)

**Bug fixes :**

* Impossible to modify consent choices in Preferences screen when essential purposes are defined

### 1.22.0 (August 2020)

**Features:**

* Updated IAB vendors list to 52.

### 1.21.1 (August 2020)

**Bug fixes :**

* Fix consent string and other properties not stored in Shared Preferences on devices running an Android version lower than 7.0

### 1.21.0 (August 2020)

**Features :**

* Added support for Google as a TCF vendor

**Bug fixes :**

* Fixed alignment of the banner notice buttons

### 1.20.3 (August 2020)

**Bug fixes :**

* Incorrect display of the notice buttons when texts are too long
* Preferences screen validation buttons enabled too soon
* Preferences screen "close" button displayed despite config parameters

### 1.20.2 (August 2020)

**Bug fixes :**

* Fix value for SharedPreference `"IABTCF_PolicyVersion"`

### 1.20.1 (July 2020)

**Bug fixes :**

* `getUserConsentStatusForVendorAndRequiredPurposes` was not returning the right status for `google` and other custom vendors.
* Add missing purposes for custom vendors

### 1.20.0 (July 2020)

**Features:**

* Additional data processing in Preferences

### 1.19.2 (July 2020)

**Features :**

* Link to open vendors page from notice

**Bug fixes :**

* Fix crash when using latest versions of play-services-ads
* Prevent memory leak in onReady / onError functions

### 1.19.1 (July 2020)

**Features :**

* "IAB TCF" tag on vendors list

**Bug fixes :**

* Export Proguard rules with library
* Consents were not sent in TCF v1 for vendors with only legitimate interest purposes

### 1.19.0 (July 2020)

**Features:**

* Notice configuration by ID

### 1.18.0 (July 2020)

**Features:**

* IAB TCF v2 initial support

### 1.17.1 (July 2020)

**Bug fixes:**

* Fix interface issue at build time with RMSwitch dependency

### 1.17.0 (June 2020)

**Features:**

* Pass consent to Webviews or Chrome Custom Tabs via query-string

### 1.16.0 (June 2020)

**Features:**

* Do not pre-check vendors in Preferences

### 1.15.0 (June 2020)

**Features:**

* Allow setting the log level through `setLogLevel`

### 1.14.1 (June 2020)

**Features:**

* `showPreferences` has been improved, requiring an AppCompactActivity and allowing to select which view should open (purposes or vendors)

### 1.13.0 (May 2020)

**Bug fixes:**

* Ensure that the SDK is never initialized more than once even if `Didomi.getInstance().initialize()` is called multiple times.
* Fixed a crash caused by a race condition that could happen when an activity is destroyed with `finishActivity` or `finishAffinity` and `setupUI` is called before the activity is fully destroyed by Android

### 1.12.1 (May 2020)

**Features:**

* Improved compatibility with dark themes.

### 1.11.0 (March 2020)

**Features:**

* Updated Global Vendor List to version 192.

### 1.10.11 (February 2020)

**Bug fixes:**

* Better protect Didomi SDK against null Fragment Managers

### 1.10.10 (February 2020)

**Bug fixes:**

* Background was displayed in a dark color on some views when device and app had dark mode enabled which made it difficult to read dark text.

### 1.10.9 (February 2020)

**Features:**

* Added `Didomi.notice.hide();` to the JavaScript code that gets returned by method `getJavaScriptForWebView`. This means that the notice view on the web app that's loaded on the native app will be hidden automatically when injecting the JavaScript code returned by this method.

### 1.10.7 (January 2020)

**Bug fixes:**

* The privacy policy link for each vendor on the Vendors view was picking up the color from the app theme which in some cases could result in white text displayed on a white background.

### 1.10.5 (January 2020)

**Features:**

* Updated Spanish and Lithuanian translations.

**Bug fixes:**

* The `Learn more` button did not have the right padding.
* The description texts for each purpose and vendor were picking up the color from the app theme which in some cases could result in white text displayed on a white background.

### 1.10.1 (Dec 2019)

**Features:**

* Updated `getTranslatedText` method to get translated text from multiple sources <https://developers.didomi.io/cmp/mobile-sdk/reference-android#gettranslatedtext>
* Created new method `updateSelectedLanguage` method that allows app developers to change the language of the Didomi SDK.
* Added the ability to pass a language code when calling the `initialize` method. This language code will be used to set the selected language.

**Bug fixes:**

* The `save` button in the purposes view was not being enabled property in some cases when the user had previously saved their preferences using an old list of purposes.

### 1.9.0 (Nov 2019)

**Bug fixes:**

* LeakCanary was reporting a memory leak related to Fragment Managers which was potentially caused by a race condition between the Garbage Collector and LeakCanary (potentially a false positive).

### 1.8.12 (Nov 2019)

**Feature:**

* Updated the way API events are sampled to be based on user ID rather than on a random number.

### 1.8.11 (Oct 2019)

**Feature:**

* Introduced `ui.action` type for events sent to the API for tracking the interactions of the user with the consent UI. Actions added: `preferences.shownpurposes`, `preferences.shownvendors`, `preferences.purposechanged` and `preferences.vendorchanged`.

### 1.8.10 (Oct 2019)

**Bug fixes:**

* When displayed as a banner, the consent notice was hiding in landscape orientation. The user would have to swipe up to bring back the notice.

### 1.8.9 (Oct 2019)

**Bug fixes:**

* When the `colorControlHighlight` property was being set in the app theme, the purpose switches were taking that color as their background color.

### 1.8.8 (Oct 2019)

**Bug fixes:**

* When the notice was displayed as a banner and the text was long, the bottom buttons wouldn't display on small screens.

### 1.8.7 (Jul 2019)

**Bug fixes:**

* Some mapping keys related to the getText and getTranslatedText methods were not matching the JSON properties of the preferences and notice properties.

### 1.8.6 (Jul 2019)

**Features:**

* Updated IAB vendors list to 155.
* Added the ability to provide translatable texts through the `texts` property in the `didomi_config.json` file that can be used when creating a custom notice.

### 1.8.5 (Jul 2019)

**Features:**

* Added the ability to block/disable the `Agree to all` and `Disable to all` buttons by providing the `preferences.disableButtonsUntilScroll` flag and setting it to `true`.

### **1.8.4 (Jul 2019)**

**Bug fixes:**

* The consent notice was not behaving properly when the device was rotated.

### **1.8.3 (Jun 2019)**

**Bug fixes:**

* Event `HideNoticeEvent` was not triggered as required in some cases.

### **1.8.2 (Jun 2019)**

**Bug fixes:**

* The Console generates custom purpose IDs within `[A-Za-z0-9-_]` and SDKs only allowed `[a-z0-9-_]`

### **1.8.1 (May 2019)**

**Features:**

* Exposed `showPreferences(AppCompatActivity activity)` method to allow the display of the Preferences view from an activity other than the one used with the `setupUI` method.

### **1.8.0 (May 2019)**

{% hint style="danger" %}
**Breaking change**

This release adds an exception that will be thrown by those public methods that must be called only once the Didomi SDK is ready. The recommended way to handle this exception is by passing a lambda expression to the \`onReady\` method where the corresponding method is called.
{% endhint %}

**Features:**

* Added the `DidomiNotReadyException` to those methods that should only be called once the Didomi SDK is ready.

### **1.7.2 (May 2019)**

**Features:**

* Update IAB vendors list (version 146)

### **1.7.1 (May 2019)**

**Bug fixes:**

* Popup notice was being dismissed when the device back button was pressed.
* SDK was crashing the app when 1) an SDK fragment (notice, preferences, etc.) was left open and the app was sent to the background for long enough to be killed by the OS and 2) the app was resumed on that fragment.

### **1.7.0 (May 2019)**

**Features:**

* [Share consent status with WebViews](/cmp/mobile-sdk/share-consent-with-webviews)

### **1.6.0 (Apr 2019)**

**Features:**

* Add the possibility to get the configuration remotely from the Didomi console

{% hint style="warning" %}
If you are coming from a previous version and want to enable the remote Didomi configuration created from the console, please add `false` as a new parameter in your `initialize` function. [See documentation](/cmp/mobile-sdk/android/setup#initialize-the-sdk).
{% endhint %}

### **1.5.0 (Apr 2019)**

**Features:**

* Add Russian and Ukrainian languages
* [Add events to track user interaction](/cmp/mobile-sdk/android/reference/api#addeventlistener)

### 1.4.4 (Mar 2019)

**Bug fixes:**

* `java.util.ConcurrentModificationException` was thrown when adding event listeners inside the `onReady` callback.
* Not availability of `Advertising ID` was causing issues. Now we use a fallback identifier when `Advertising ID` is not available.

### 1.4.3 (Mar 2019)

**Bug fixes:**

* There was a race condition when registering SDK events that in some edge cases could potentially crash the app.
* The SDK was using the current activity on fragments instead of the fragments themselves to retain the view models which in some edge cases could potentially crash the app.

### 1.4.2 (Feb 2019)

**Features:**

* Exposing `shouldConsentBeCollected` method used to allow developers to check if consent should be collected or not.

### 1.4.1 (Feb 2019)

**Bug fixes:**

* App was crashing in some edge cases when user minimised the app right before the consent notice was displayed.

### 1.4.0 (Jan 2019)

**Features:**

* Customize buttons and links color <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme>.
* Details about purposes and vendors by expanding the list items.
* Purposes are listed under each vendor item on the vendors screen when they are expanded.
* Customize logo on the Purposes view <https://developers.didomi.io/cmp/mobile-sdk/getting-started#configure-your-app-name-and-logo>.
* Bypass notice and open Preferences pop-in directly <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#display-when-consent-is-missing>.
* Customize purposes order and icons by providing purpose categories <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#purposes>.
* Prevent the Preferences pop-in from being closed when consent is missing <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#prevent-the-popup-from-being-closed-when-consent-is-missing>.
* Remove "Number of Partners" on the Preferences view.
* Update content translations.

**Bug fixes:**

* Text scrolled in the middle on the Preferences pop-in.
* Preferences pop-in opens twice.
* Preferences pop-in closed when clicking on back button and the "X" button was disabled.
* Vendor switch color was not different from the switches on the Purposes view.

### 1.3.0 (Jan 2019)

**Features:**

* Supports the 24 European languages
* Number of days before recollecting consent option in the configuration tag

**Bug fixes:**

* Fixed some UI issues

### 1.2.2 (Dec 2018)

**Bug fixes:**

* Translate the "View Privacy Policy" link on the vendors list
* Fixed potential issue around macros and the way they get replaced in the content

### 1.2.1 (Nov 2018)

**Bug fixes:**

* Default texts format used different font size/weight across languages
* Remove `VendorRepository` and `ApiEventsRepository` from the public API
* Correctly load purposes and vendors statuses in the Preferences popup after consent has been given
* Show the `Save` button when the Preferences popup is open after consent has been given

### 1.2.0 (Nov 2018)

**Features:**

* Custom purposes
* Map custom vendor to IAB ID
* Expose `getUserConsentStatusForPurpose` and `getUserConsentStatusForVendorAndRequiredPurposes` in the public API
* Ability to customize texts in the preferences popup

**Bug fixes:**

* Translation issues on purposes and vendors
* Do not load cached config if remote config URL is null/empty

### 1.1.0 (Nov 2018)

**Features:**

* Load app config (`didomi_config.json`) from a remote URL
* `IABConsent_SubjectToGDPR` shared preferences key for the IAB spec to indicate whether the user is subject to GDPR or not

**Bug fixes:**

* Expandable info on vendors would not expand
* Remove the app name from the User-Agent and replace it with "Didomi SDK/\[SDK version]"

### 1.0.0 (Oct 2018)

Initial version.


# iOS and tvOS

The Didomi SDK for iOS and tvOS enables apps to collect user consent through a native experience.

Read on for more information:

* [Setup](/cmp/mobile-sdk/ios/setup): How to configure the SDK
* [Logging](/cmp/mobile-sdk/ios/logging): Log formats and levels
* [App Tracking Transparency (iOS 14+)](/cmp/mobile-sdk/ios/app-tracking-transparency-ios-14): How to integrate the Didomi SDK with the App Tracking Transparency framework
* [Reference](/cmp/mobile-sdk/ios/reference/api): API functions exposed
* [Versions](/cmp/mobile-sdk/ios/versions): History of versions


# Setup

Follow these steps to set up the Didomi iOS and tvOS SDK:

* [Requirements](#requirements)
* [Add the SDK to your project](#add-the-sdk-to-your-project)
* [Initialize the SDK](#initialize-the-sdk)
* [Set up the SDK UI](#setup-the-sdk-ui)
* [Configure the SDK](#configure-the-sdk)
* [SwiftUI](#swiftui)

## Requirements

We offer our SDK as a pre-compiled XCFramework that you can add to your application. We support iOS versions >= 10 and tvOS versions >= 11.

## Add the SDK to your project

The package can be added using CocoaPods or manually.

### Using CocoaPods

The package can be added using CocoaPods:

{% tabs %}
{% tab title="Xcode >= 26 (XCFramework)" %}
1\. If you haven't already, install the latest version of [CocoaPods](https://guides.cocoapods.org/using/getting-started.html).\
2\. Add this line to your `Podfile`:

```
pod 'Didomi-XCFramework', '2.47.0'
```

{% endtab %}
{% endtabs %}

### Using Swift Package Manager

The iOS SDK is available through Swift Package Manager as a binary library. In order to integrate it into your iOS or tvOS project, follow the instructions below:

* Open your Xcode project
* Select your project in the **navigator area**
* Select your project in the **PROJECT** section
* Select the **Package Dependencies**
* Click on the **+** button
* Copy the package URL <https://github.com/didomi/didomi-ios-sdk-spm> into the search bar
* Select the **didomi-ios-sdk-spm** package from the list
* Click on **Add Package**
* From the **Choose Package Products for the didomi-ios-sdk-spm** screen click on Add Package

Your setup should end up looking like this:

<figure><img src="/files/OciDLJH7VaF13SZUOXv8" alt=""><figcaption><p>Swift Package Manager setup</p></figcaption></figure>

### Manually

The package can also be added manually as explained below:

1. Download and unzip the latest version of our framework for Xcode >= 26: <https://sdk.didomi.io/ios/didomi-ios-sdk-X.Y.Z-xcframework.zip> where `X.Y.Z` corresponds to the version number that you want to add.
2. In Xcode, select your project.
3. Then, select your app target.
4. Click on the `General` tab.
5. Scroll down to the `Embedded binaries` section.
6. From Finder, drag the `Didomi.framework` file into the `Embedded binaries` section.
7. Make sure the `Copy items if needed` box is checked and click on `Finish`.
8. Your configuration should end up looking as follows:

![](/files/-LQG2ADr21LSQMjTL1Xd)

### Objective-C projects only

The iOS Didomi SDK is written in Swift so if your app is written in Objective-C, please make sure that the `Always Embed Swift Standard Libraries` flag is set to `YES` as shown in the image below:

![](/files/-LbcnIsQsXx1vLAu_pDs)

## Initialize the SDK

Once our SDK has been added to your project, you need to initialize it. The initialization process will prepare the SDK for interactions with the user and your application. It is important to launch the SDK initialization as soon as possible.

In the `AppDelegate`, make sure to import the `Didomi` module, then call the `initialize` method and pass your API key:

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

```swift
import UIKit
import Didomi

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        let parameters = DidomiInitializeParameters(
            apiKey: "<Your API key>",
            localConfigurationPath: "<Your local config path>",
            remoteConfigurationURL: "<Your remote config url>",
            providerID: "<Your provider ID>",
            disableDidomiRemoteConfig: true|false,
            languageCode: "<Your language code>",
            noticeID: "<Your notice ID>"
        )
        Didomi.shared.initialize(parameters)
        
        // Important: views should not wait for onReady to be called.
        // You might want to execute code here that needs the Didomi SDK
        // to be initialized such as: analytics and other non-IAB vendors.
        Didomi.shared.onReady {
            // The Didomi SDK is ready to go, you can call other functions on the SDK
        }
        
        return true
    }
}
```

{% endtab %}

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

```objectivec
#import <UIKit/UIKit.h>
#import <Didomi/Didomi.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end
```

```objectivec
#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    Didomi *didomi = [Didomi shared];
    DidomiInitializeParameters *parameters = [[DidomiInitializeParameters alloc] initWithApiKey: @"<Your API key>"
                                                                         localConfigurationPath: nil
                                                                         remoteConfigurationURL: nil
                                                                                     providerID: nil
                                                                      disableDidomiRemoteConfig: NO
                                                                                   languageCode: nil
                                                                                       noticeID: @"<Your notice ID>"];
    
    [didomi initialize: parameters];
    // Important: views should not wait for onReady to be called.
    // You might want to execute code here that needs the Didomi SDK
    // to be initialized such as: analytics and other non-IAB vendors.
    [didomi onReadyWithCallback:^{
        // The Didomi SDK is ready to go, you can call other functions on the SDK
    }];

    return YES;
}

@end
```

{% endtab %}
{% endtabs %}

Keep in mind that the SDK initialization is an asynchronous process so you must avoid interacting with the `Didomi` object until it is actually ready to handle your requests. Use the `onReady` closure in Swift or the `onReadyWithCallback` method in Objective-C to register a listener for the ready event.

## Set up the SDK UI

{% hint style="info" %}
Note: the `setupUI` method should be called only from your main/entry `UIViewController` which in most cases should be once per app launch.

You do not need to call `onReady`, `isReady` or `shouldConsentBeCollected` before calling `setupUI` because they are called internally. Therefore, by calling this method the consent notice and preference views will only be displayed if it is required and only once the SDK is ready.
{% endhint %}

In order for the SDK to be able to display UI elements and interact with the user, you must provide a reference to your main `UIViewController`. Make sure to import the `Didomi` module and call the `setupUI` method in Swift, `setupUIWithContainerController` in Objective-C, of the SDK in the `viewDidLoad` method of your main `UIViewController`:

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

```swift
import UIKit
import Didomi

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        Didomi.shared.setupUI(containerController: self)
    }
}
```

{% endtab %}

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

```objectivec
#import <UIKit/UIKit.h>
#import <Didomi/Didomi.h>

@interface ViewController : UIViewController

@end
```

```objectivec
#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Didomi *didomi = [Didomi shared];
    [didomi setupUIWithContainerController:self];
}

@end
```

{% endtab %}
{% endtabs %}

### Deep links

If you are using deep links or have multiple entry points in your app, make sure that the `setupUI` function is called on every entry point that the user can launch the app on.\
\
This will ensure that consent is always collected as needed and there is no path where the user can launch the app without consent being collected. If `setupUI` is missing at some entry points, you will see lower consent rates as users will be using the app without giving consent.

## Configure the SDK

We support three options for configuring the UI and the behavior of the SDK:

* [Didomi Console](#from-the-console-recommended): the SDK is configured remotely from the Didomi Console
* [Local file](#local-file): the SDK is configured from a `didomi_config.json` file embedded in your app package
* [Remote file](#remote-file): the SDK is configured from a remote didomi\_config.json file

### From the Console (Recommended)

You can configure the consent notice in your app by creating a notice in your Didomi console. It will automatically be linked to your app through your API key and notice ID. Values for the API key and notice ID can be retrieved directly from the [Didomi console](https://console.didomi.io/).

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

```swift
Didomi.shared.initialize(
    apiKey: "<Your API key>",
    localConfigurationPath: nil,
    remoteConfigurationURL: nil,
    providerId: nil,
    disableDidomiRemoteConfig: false,
    noticeID: "<Your notice ID>"
)
```

{% endtab %}

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

```objectivec
[didomi initializeWithApiKey:@"<Your API key>"
     localConfigurationPath:nil
    remoteConfigurationURL:nil
                 providerId:nil
  disableDidomiRemoteConfig:NO
               languageCode:nil
                   noticeID:@"<Your notice ID>"];
```

{% endtab %}
{% endtabs %}

The SDK will automatically use the remote configuration hosted by Didomi and cache it locally. The cached version is refreshed every 60 minutes.

### Local file (deprecated)

{% hint style="danger" %}
Using your own remote file automatically disables the TCF integration.\
If your app uses the TCF, you must use a configuration from the Didomi Console.
{% endhint %}

{% hint style="warning" %}
Using a local file will prevent you from supporting multiple regulations.
{% endhint %}

With this option, you create your own SDK configuration file and embed it in your app package.

The SDK behavior is configured in a `didomi_config.json` file that must be placed somewhere under your project folder (see the image below for reference). Create a file with the following content to get started:

{% tabs %}
{% tab title="didomi\_config.json" %}

```javascript
{
    "app": {
        "name": "My App Name",
        "privacyPolicyURL": "http://www.website.com/privacy",
        "vendors": {
            "iab": {
                "all": true
            }
        },
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    }
}
```

{% endtab %}
{% endtabs %}

![](/files/-LQFzYfWXIjbXbBXyqw4)

You also need to disable loading the remote configuration to ensure that only the local file is loaded and that no HTTP request is sent. Update your [`initialize`](/cmp/mobile-sdk/ios/reference/api#initialize) call to set the `disableDidomiRemoteConfig` parameter to `true`:

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

```swift
Didomi.shared.initialize(
    apiKey: "<Your API key>",
    localConfigurationPath: nil,
    remoteConfigurationURL: nil,
    providerId: nil,
    disableDidomiRemoteConfig: true
)
```

{% endtab %}

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

```objectivec
[didomi initializeWithApiKey:@"<Your API key>" localConfigurationPath:nil remoteConfigurationURL:nil providerId:nil disableDidomiRemoteConfig:YES languageCode:nil];
```

{% endtab %}
{% endtabs %}

Your SDK is now set up. [Read the Getting started section](/cmp/mobile-sdk/consent-notice/getting-started) to learn more about how to configure it to match your app UI and requirements.

### Remote file

{% hint style="danger" %}
Using your own remote file automatically disables the TCF integration.\
If your app uses the TCF, you must use a configuration from the Didomi Console.
{% endhint %}

{% hint style="info" %}
Enabling this option will prevent the configuration from being loaded from the Didomi Console.
{% endhint %}

You can provide a remote URL for the SDK to download the `didomi_config.json` configuration file from. That allows you to update the SDK configuration without having to re-publish your mobile application.

When that configuration is enabled, the SDK will automatically use the remote configuration and cache it locally. The cached version is refreshed every 60 minutes. If there is no connection available to download the remote file and no locally cached version, the SDK will try to use the local `didomi_config.json` (provided in the app bundle) as a fallback.

To enable that option, change your call to [initialize](/cmp/mobile-sdk/ios/reference/api#initialize) to provide the remote file URL:

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

```swift
Didomi.shared.initialize(
    apiKey: "<Your API key>",
    localConfigurationPath: nil,
    remoteConfigurationURL: "http://www.website.com/didomi_config.json",
    providerId: nil,
    disableDidomiRemoteConfig: false
)
```

{% endtab %}

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

```objectivec
[didomi initializeWithApiKey:@"<Your API key>" localConfigurationPath:nil remoteConfigurationURL:@"http://www.website.com/didomi_config.json" providerId:nil disableDidomiRemoteConfig:NO languageCode:nil];
```

{% endtab %}
{% endtabs %}

Also see the [reference documentation of the initialize function](/cmp/mobile-sdk/ios/reference/api#initialize) for more information.

### Download Global Vendor List (GVL)

Since version `1.40.1`, the GVL will be downloaded by default from our API before the SDK is initialized. If you want to stop this behavior, provide the `app.vendors.iab.requireUpdatedGVL` flag set to `false` in the Custom JSON section when editing your notice on the Console app (or in your local `didomi_config.json` file if that's the case).

```
{
    "app": {
        "vendors": {
            "iab": {
                "requireUpdatedGVL": false
            }
        }
    }
}
```

A timeout can also be provided to specify a maximum timeout for the download of the GVL. This can be done by providing the `app.vendors.iab.updateGVLTimeout` property (in seconds).

```
{
    "app": {
        "vendors": {
            "iab": {
                "updateGVLTimeout": 10
            }
        }
    }
}
```

## SwiftUI

When you create a new Apple app, among other things you need to choose if your app is going to use UIKit or SwiftUI. SwiftUI is Apple's new framework for creating user interfaces in a declarative way. In order to use the Didomi SDK in a SwiftUI app we suggest the following steps.

### Prepare UIViewController to call setupUI method

1. Create a new Swift file. You can name it for example `DidomiWrapper`.
2. Inside this new file, create a new class that extends `UIViewController`. We need this to make sure we call the `setupUI` method when the `viewDidLoad` method is called.
3. Inside the same file, create a struct that implements the `UIViewControllerRepresentable` protocol as shown below:

```swift
import SwiftUI
import Didomi

// If you have your own UIViewController you can use that instead.
class DidomiViewController: UIViewController {
    override func viewDidLoad() {
        // 2)
        Didomi.shared.setupUI(containerController: self)
    }
}

// 3)
struct DidomiWrapper: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
        let didomiViewController = DidomiViewController()
        
        return didomiViewController
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        // We don't need to implement this method
    }
}
```

### Prepare AppDelegate to call initialize method

When using SwiftUI, you might still want to use the `UIApplicationDelegate` functionality. Since we want to initialize the Didomi SDK as early as possible we recommend creating a class that implements the `UIApplicationDelegate`.

1. Create a new Swift file. You can name it for example `YourSwiftUIApp`.
2. Create a new class that extends the `UIApplicationDelegate` protocol. Inside the `applicationDidFinishLaunchingWithOptions` method, call the Didomi `initialize` method.
3. Create a new struct that implements the SwiftUI `App` protocol. Use the `UIApplicationDelegateAdaptor` property wrapper to connect this new struct with the `AppDelegate` class. Make sure this new struct uses the `main` annotation. Now you are ready to use the new `DidomiWrapper` struct that you created in the previous steps.

The snippet below shows the steps explained in the points above.

```swift
import SwiftUI
import Didomi

// 2)
class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        let parameters = DidomiInitializeParameters(
            apiKey: "<Your API key>",
            localConfigurationPath: "<Your local config path>",
            remoteConfigurationURL: "<Your remote config url>",
            providerID: "<Your provider ID>",
            disableDidomiRemoteConfig: true|false,
            languageCode: "<Your language code>",
            noticeID: "<Your notice ID>"
        )
        Didomi.shared.initialize(parameters)
        return true
    }
}

// 3)
@main
struct YourSwiftUIApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            DidomiWrapper()
        }
    }
}
```


# Logging

The Didomi SDK on iOS will log various informational and error messages.

As recommended by Apple, we use two mechanisms for logging:

* [NSLog](https://developer.apple.com/documentation/foundation/1395275-nslog) for iOS 9
* [os\_log](https://developer.apple.com/documentation/os/logging) for iOS 10+

## Formats

### iOS 9 - NSLog

Messages logged with `NSLog` use the format: `Didomi - {LEVEL} - {Message}`

Example: `Didomi - ERROR - Didomi SDK is not ready`

### iOS 10+ - os\_log

Messages logged with `os_log` use the type type to indicate the level and the following information:

* Subsystem: `Bundle.main.bundleIdentifier` or `io.didomi.sdk` if the bundler identifier is not available
* Category: `Didomi`

Example:

![](/files/-M9VFn0OOrecoG-yvCwI)

## Levels

We use the [standard log levels supported by os\_log](https://developer.apple.com/documentation/os/oslogtype): `debug`, `error`, `info`, and `fault`.

You can decide what level of logs should be displayed by the SDK by calling the setLogLevel function:

```swift
import os

...

Didomi.shared.setLogLevel(minLevel: OSLogType.debug.rawValue)
Didomi.shared.setLogLevel(minLevel: 2)
Didomi.shared.initialize(...)
```

{% hint style="danger" %}
Make sure that the call to `setLogLevel` is done before the call to `initialize` or some messages will be logged at the wrong level.
{% endhint %}

If your app supports iOS 9, use the actual value of the error level instead of `OSLogType`:

| Level   | Value |
| ------- | ----- |
| `info`  | 1     |
| `debug` | 2     |
| `error` | 16    |
| `fault` | 17    |


# App Tracking Transparency (iOS 14.5+)

Starting with iOS 14.5 (April 2021) and the [App Tracking Transparency](https://developer.apple.com/app-store/user-privacy-and-data-use/) (ATT) framework, Apple requires that your app provides transparency on the data that it uses and on the third parties that will track the user in your app.

Tracking and the use of the IDFA are subject to permission being obtained from the user. "Tracking refers to the act of linking user or device data collected from your app with user or device data collected from other companies’ apps, websites, or offline properties for targeted advertising or advertising measurement purposes. Tracking also refers to sharing user or device data with data brokers." (from [Apple's guidelines](https://developer.apple.com/app-store/user-privacy-and-data-use/)).

![Tracking permission on iOS 14](/files/-MGA096Up8fnho89AsI8)

## ATT tracking permission

At the moment, the Didomi SDK does not ask for the user permission for tracking in the ATT framework and it is the responsibility of the app to do so and to decide how the Didomi CMP and the ATT permission should coexist.

Your app must follow [Apple's guidelines](https://developer.apple.com/app-store/user-privacy-and-data-use/) for disclosing the data collected by your app and asking for the user's permission for tracking. Permission for tracking on iOS can be asked by calling the `ATTrackingManager.requestTrackingAuthorization` function in your app.

### When and how to ask for the ATT permission?

According to [Apple's guidelines](https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/accessing-user-data/), you must display the ATT tracking permission alert before trying to use the IDFA from the iOS device. If permission is not asked or if the user denies permission, the IDFA will not be available to your app and embedded third-party SDKs. Third-party SDKs might not be able to function properly in that case.

To be fully compliant with both Apple and GDPR requirements, you must ask for the user permission through ATT **AND** ask for user consent through the CMP.\
Apple's ATT is not compliant with the IAB TCF or with GDPR requirements at the moment so that it cannot be used as the only consent-collection mechanism and must be used in conjunction with the Didomi CMP.

#### Recommended solutions

We recommend two options to combine the CMP and ATT:

| Implementation                                                                                                    | Pros/Cons                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|                                                                                                                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| Ask permission via ATT then collect consent from the CMP **if and only if** the user has given permission via ATT | <p>This implementation allows the users to only be asked once if they do not give consent in ATT. It still requires users to be asked twice (ATT then CMP) for users who give consent but there is no way around this at the moment.</p><p>The main drawback of this solution is that a user who does not give consent to ATT is assumed to also not give consent to the CMP even though ATT and the CMP deal with different purposes and vendors. Your app would be extrapolating user choices from ATT (tracking via IDFA) to all other purposes. Whether that is acceptable or not is an app-specific choice.</p><p><strong>In our experience, this implementation is the one that is the most accepted by Apple. This is our recommended implementation.</strong></p> |
| Collect consent from the CMP then ask permission via ATT                                                          | The main advantage of this implementation is that it allows the user to make different choices between the ATT tracking and other CMP purposes and vendors. It still requires users to be asked twice (CMP then ATT) but there is no way around this at the moment.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

The ATT permission can also be collected at a later point in the user experience but your third-party vendors might not be able to operate if the IDFA is not available until the user has given permission.

#### Apple guidelines

Apple also provides some [guidelines on how the ATT permission should be integrated](https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/accessing-user-data/). The public guidelines lack specificity and we have seen Apple reject apps for various reasons. We recommend being careful about the following points:

* Do not show the CMP after a user denies an ATT permission request. Apple considers that the CMP is asking the user to reconsider their decision in the ATT permission request. Similarly, avoid showing any message asking the user to reconsider their decision even if it is not the Didomi CMP.
* If you show the ATT permission request after the CMP, always show the ATT permission irrespective of the user choice in the CMP. Apple consider the CMP as "custom messaging before the ATT alert" in that case and ATT must always be displayed. (See "Displaying Custom Messaging Before the Alert" on <https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/accessing-user-data/>)
* If you show the ATT permission request after the CMP, do not allow the CMP to be closed without the user agreeing or disagreeing. If the CMP is allowed to be closed, this would delay the permission request which Apple does not accept after showing a custom message before the alert.

Please read our section on [integrating the CMP notice and ATT permission](#integrate-the-cmp-notice-and-ios-permission) for code samples.

### Can I use only ATT or only the Didomi CMP?

To the user, the CMP notice and the iOS ATT permissions alert might look like the app asking for the same permission twice with a slightly different UI. This is confusing and disappointing.

However, that is not true from a legal perspective:

* ATT is Apple's specific solution to collecting the user permission for Apple's definition of tracking: "Tracking refers to the act of linking user or device data collected from your app with user or device data collected from other companies’ apps, websites, or offline properties for targeted advertising or advertising measurement purposes. Tracking also refers to sharing user or device data with data brokers." (from <https://developer.apple.com/app-store/user-privacy-and-data-use/>)
* The Didomi CMP covers the legal definition of collecting consent and helps with IAB TCF compliance as well.

Unfortunately, at the moment, these two definitions are not aligned. ATT's permission is not detailed enough to be considered legal under GDPR or compliant with the IAB TCF. As a result, the ATT's permission cannot be used alone without a CMP.\
For apps to be compliant with GDPR and Apple's guidelines, the app developers are forced to use disappointing combinations of consent notices / ATT permission which leads to increased user confusion and poor user experience.

Didomi is in discussions with Apple, the IAB, and European DPAs to try to find common grounds in the long term.

### Does the Didomi SDK use the IDFA and require ATT permission?

Since version 1.48.2 (<https://developers.didomi.io/cmp/mobile-sdk/ios/versions#1-48-2-april-2021>) of our SDK, the Didomi SDK does not use the IDFA in any way and does not require the ATT permission. We recommend updating to that SDK version as soon as possible.

Didomi uses its own random user ID that is specific to every app that the SDK is embedded in. This ID is not used for any user tracking and is only used for the purpose of consent management.

If an older version of the SDK is used on an iOS version that requires ATT then:

* Consent will still be collected as usual and will be TCF compliant
* Analytics in the Didomi Console will be correctly reported
* Individual proof of consent will not be available as some users will not have an individual user ID

### How does the ATT permission (or the lack thereof) impact third-party SDKs?

This depends on third-party SDKs. Third-party SDKs that rely on the IDFA (advertising or analytics SDKs, for instance), will require the IDFA and might stop working if the user denies consent in the ATT prompt.

Check with your third-party SDK providers how they behave in that case and what they expect from the app.

### Is ATT permission compliant with GDPR/CCPA/IAB TCF/CNIL/AEPD/BfDI/...?

ATT is an Apple-specific solution to collecting user consent to "tracking" with its own definition of what constitutes tracking and, more importantly, how consent should be collected and what valid consent is.

On its own, ATT is not compliant with the IAB TCF specifications and is unlikely to be considered a compliant way of collecting consent for data processing under GDPR or CCPA. It cannot be used as a replacement to a CMP for GDPR, CCPA, or IAB TCF compliance at the moment.

### **What happens if the customer gives consent in the Didomi CMP but rejects the ATT permission? (or the other way around)**

The two are independent.

If the user rejects ATT, the behavior of apps and third-party SDKs that rely on IDFA will be impacted. The impact depends on what those apps and third-party SDKs are doing and needs to be assessed directly by the app developer with the SDK providers.

### Why did Apple reject my app because of how I am asking for ATT permission?

We have seen Apple accept and reject apps for all combinations of ATT and CMP. We have also seen Apple accept and reject two apps with the same ATT/CMP configuration, or reject then accept a given app without any modifications.

It is hard to give definitive answers and guidelines at the moment as there is some unpredictability in Apple's validation process. It is likely that Apple is still fine-tuning its guidelines and acceptance criteria as ATT is a recent feature.

We have listed recommendations and guidelines from the Apple validation processes that our clients have been through in [When and how to ask for the ATT permission?](#when-and-how-to-ask-for-the-att-permission). Following the guidelines will strongly avoiding rejection.

We will keep updating this page with more recommendations on how to integrate ATT and CMP consent notices.

Feel free to reach out to our Support team at <support@didomi.io> to discuss your specific app if needed.

## Integrate the CMP notice and ATT permission

### Show the CMP notice then the ATT permission if the user gives consent in the CMP notice

This sample shows how to:

* Show the Didomi consent notice
* Show the ATT permission request if and only if:
  * The iOS version is >= 14
  * The user has not made an ATT permission choice before and the choice is not restricted (<https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/restricted>)
  * The user gave consent to at least one purpose in the Didomi consent notice

The CMP consent notice will always be displayed and the ATT permission will not show if the user denies consent to all purposes in the Didomi consent notice. The ATT status will remain `notDetermined`.

```swift
import UIKit
import AdSupport
import AppTrackingTransparency

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        let didomiEventListener = EventListener()
        didomiEventListener.onConsentChanged = { event in
            // The consent status of the user has changed
            if #available(iOS 14, *) {
                if ATTrackingManager.trackingAuthorizationStatus == .notDetermined && Didomi.shared.getCurrentUserStatus().purposes.values.first(where: { $0.enabled }) != nil {
                    // Show the ATT permission request if the user has not made an ATT choice before AND the user gave consent to at least one purpose in the Didomi CMP
                    ATTrackingManager.requestTrackingAuthorization { status in }
                }
            }
        }
        Didomi.shared.addEventListener(listener: didomiEventListener)
        
        // Show the Didomi notice
        Didomi.shared.setupUI(containerController: self)
    }
}
```

### Show the ATT permission then the CMP notice if the user accepts the ATT permission

This sample shows how to:

* Show the ATT permission request if iOS >= 14
* Show the Didomi consent notice if and only if:
  * The iOS version is < 14
  * The user accepted the ATT permission OR ATT is restricted (<https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/restricted>)

The ATT permission request will always be displayed if it is not restricted. The Didomi consent notice will only be displayed if the user accepts the ATT permission OR the ATT permission cannot be displayed for any reason (restricted or iOS < 14).

```swift
import UIKit
import AdSupport
import AppTrackingTransparency

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        if #available(iOS 14, *) {
            ATTrackingManager.requestTrackingAuthorization { status in
                switch status {
                    case .authorized:
                        // Show the Didomi CMP notice to collect consent from the user
                        Didomi.shared.setupUI(containerController: self)
                    case .denied:
                        // The user denied ATT permission, deny user consent for all purposes/vendors in the Didomi CMP as well
                        Didomi.shared.setUserDisagreeToAll()
                    case .restricted:
                        // ATT is restricted on the device so the user was not asked for a choice (https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/restricted)
                        // Show the Didomi CMP notice to collect consent from the user
                        Didomi.shared.setupUI(containerController: self)
                    case .notDetermined:
                        // This is not supposed to happen
                        // Show the Didomi CMP notice to collect consent from the user
                        Didomi.shared.setupUI(containerController: self)
                }
            }
        } else {
            // Show the Didomi CMP notice to collect consent from the user as iOS < 14 (no ATT available)
            Didomi.shared.setupUI(containerController: self)
        }
    }
}
```


# Reference

This section is a comprehensive reference of the methods and events exposed by the SDK and that you can leverage in your application:

* [API](/cmp/mobile-sdk/ios/reference/api)
* [Events](/cmp/mobile-sdk/ios/reference/events)


# API

This section is a comprehensive reference of the methods and events exposed by the iOS SDK that you can leverage in your application.

Always use `Didomi.shared` to get a reference to the Didomi SDK. Also make sure to always call the SDK after it is fully initialized (see [onReady](#onready)).

## Usage

### addEventListener

Add an event listener to catch events triggered by the SDK. [See the dedicated section for more details](https://developers.didomi.io/cmp/mobile-sdk/ios/reference/events)

### removeEventListener

Remove a previously added event listener.

**Requires SDK to be initialized**

No.

**Parameters**

| Name          | Type            | Description                   |
| ------------- | --------------- | ----------------------------- |
| eventListener | `EventListener` | The event listener to remove. |

**Returns**

Nothing

**Example**

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

```java
Didomi.shared.removeEventListener(listener: currentEventListener)
```

{% endtab %}
{% endtabs %}

### getJavaScriptForWebView

Get JavaScript to embed into a WebView to pass the consent status from the app to the Didomi Web SDK embedded into the WebView.

Inject the returned tag into a WebView with `evaluateJavaScript`.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type (Swift) | Type (Objective-C) | Description                           |
| ------------ | ------------------ | ------------------------------------- |
| `String`     | `NSString *`       | JavaScript code to embed in a WebView |

**Example**

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

```swift
Didomi.shared.getJavaScriptForWebView()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
NSString *javaScriptForWebView = [didomi getJavaScriptForWebView];
```

{% endtab %}
{% endtabs %}

### getQueryStringForWebView

Get a query string parameter to append to the URL of a WebView to pass the consent status from the app to the Didomi Web SDK embedded into the WebView.

Read our article on [sharing consent with WebViews](/cmp/mobile-sdk/share-consent-with-webviews) for more information.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type     | Description                                                                                                                                                                            |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `String` | Query string parameter with the format `didomiConfig.user.externalConsent.value=...`. It can be appended to your URL after a `?` or a `&` if your URL already contains a query string. |

**Example**

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

```java
Didomi.shared.getQueryStringForWebView()
```

{% endtab %}

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

```
Didomi *didomi = [Didomi shared];
NSString *queryStringForWebView = [didomi getQueryStringForWebView];
```

{% endtab %}
{% endtabs %}

### hideNotice

Hide the consent notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.hideNotice()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];

[didomi hideNotice];
```

{% endtab %}
{% endtabs %}

### hidePreferences

Hide the preferences popup.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.hidePreferences()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];

[didomi hidePreferences];
```

{% endtab %}
{% endtabs %}

### initialize

Initialize the SDK. The initialization runs on a background thread to avoid blocking your UI. Use the [onReady](#onready) function to know when the initialization is done and the SDK is ready to be used.

**Requires SDK to be initialized**

No.

**Parameter:**

|            |                            |
| ---------- | -------------------------- |
| **Name**   | Type                       |
| parameters | DidomiInitializeParameters |

**Description for `DidomiInitializeParameters`**

{% hint style="warning" %}
The parameter `disableDidomiRemoteConfig` is deprecated, we strongly suggest you to create your notice from the console (see [Setup fromThe Console](/cmp/mobile-sdk/ios/setup#from-the-console-recommended) for more information).
{% endhint %}

| Name                                   | Type    | Optional | Description                                                                                                                                                                                                                                                                                                                                                                         |
| -------------------------------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| apiKey                                 | String  | No       | Your API key                                                                                                                                                                                                                                                                                                                                                                        |
| localConfigurationPath                 | String  | Yes      | The path to your local config file in your `assets/` folder. Defaults to `didomi_config.json` if null.                                                                                                                                                                                                                                                                              |
| remoteConfigurationURL                 | String  | Yes      | The URL to a remote configuration file to load during initialization. When provided, the file at the URL will be downloaded and cached to be used instead of the local `assets/didomi_config.json`. If there is no Internet connection available and no previously cached file, the local file will be used as fallback.                                                            |
| providerID                             | String  | Yes      | Your provider ID (if any). A provider ID is assigned when you work with Didomi through a third-party. If are not sure if you have one, set this to `null`.                                                                                                                                                                                                                          |
| disableDidomiRemoteConfig (deprecated) | Boolean | Yes      | <p>Prevent the SDK from loading a remote configuration from the Didomi Console. Defaults to <code>true</code> (not loading remote config).</p><p>Set this parameter to <code>false</code> to use a remote consent notice configuration loaded from the Didomi Console.</p><p>Set this parameter to <code>true</code> to disable loading configurations from the Didomi Console.</p> |
| languageCode                           | String  | Yes      | Language in which the consent UI should be displayed. By default, the consent UI is displayed in the language configured in the device settings. This property allows you to override the default setting and specify a language to display the UI in. String containing the language code or the local code e.g.: `"es"`, `"fr"`, `"en_US"`*,* `"zh_HK"`, etc.                     |
| noticeID                               | String  | Yes      | Notice ID to load the configuration from. If provided, the SDK bypasses the app ID targeting and directly loads the configuration from the notice ID.                                                                                                                                                                                                                               |
| countryCode                            | String  | Yes      | <p>Override user country code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user country.</p>                                                                                                                                                                                                                  |
| regionCode                             | String  | Yes      | <p>Override user region code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user region.</p><p>Ignored if countryCode is not set.</p>                                                                                                                                                                           |
| isUnderage                             | Boolean | Yes      | Whether the user is underage or not. This parameters can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).                                                                                                                                                                                                          |

**Returns**

Nothing

**Example**

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

```swift
let parameters = DidomiInitializeParameters(
    apiKey: "<Your API key>",
    noticeID: "<Your notice ID>"
)
initialize(parameters)
```

{% endtab %}

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

```objectivec
DidomiInitializeParameters *parameters = [[DidomiInitializeParameters alloc] initWithApiKey: @"<Your API key>"
                                                                         localConfigurationPath: nil
                                                                         remoteConfigurationURL: nil
                                                                                     providerID: nil
                                                                      disableDidomiRemoteConfig: NO
                                                                                   languageCode: nil
                                                                                       noticeID: @"<Your Notice ID>"];
    
[didomi initialize: parameters];
```

{% endtab %}
{% endtabs %}

### isNoticeVisible

Check if the consent notice is currently displayed.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`Bool`

**Example**

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

```swift
Didomi.shared.isNoticeVisible()
```

{% endtab %}

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

```
Didomi *didomi = [Didomi shared];
BOOL isNoticeVisible = [didomi isNoticeVisible];
```

{% endtab %}
{% endtabs %}

### isPreferencesVisible

Check if the preferences popup is currently displayed.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`Bool`

**Example**

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

```swift
Didomi.shared.isPreferencesVisible()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
BOOL isPreferencesVisible = [didomi isPreferencesVisible];
```

{% endtab %}
{% endtabs %}

### isReady

Check if the SDK is ready.

**Requires SDK to be initialized**

No.

**Parameters**

No parameter.

**Returns**

`Bool`

**Example**

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

```swift
Didomi.shared.isReady()
```

{% endtab %}

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

```
Didomi *didomi = [Didomi shared];
BOOL isReady = [didomi isReady];
```

{% endtab %}
{% endtabs %}

### onError

Add a closure that will be executed if an unexpected situation occurs, for example an error during the initialization process.

**Requires SDK to be initialized**

**No**

**Parameters**

| **Name** | Type   | Description                                             |
| -------- | ------ | ------------------------------------------------------- |
| callback | `func` | A closure executed when an unexpected situation occurs. |

**Returns**

The method itself does not return a value but when the closure is executed an error object is passed to it which explains the reason of the unexpected situation.

We recommend calling this method before calling the `initialize` method.

**Example**

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

```swift
Didomi.shared.onError { errorEvent in
    // Closure executed
}
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi onErrorWithCallback:^(DDMErrorEvent * _Nonnull event) {
    NSLog(@"An unexpected situation occurred.");
}];
```

{% endtab %}
{% endtabs %}

### onReady

Add an event listener that will be called when the SDK is ready (ie fully initialized). If the event listener is added after the SDK initialization, the listener will be called immediately.

All calls to other functions of this API must only be made in a listener to the ready event to make sure that the SDK is initialized before it is used.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type   | Description                              |
| -------- | ------ | ---------------------------------------- |
| callback | `func` | A function to call when the SDK is ready |

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.onReady {
    // The SDK is ready
}
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi onReadyWithCallback:^{
    // The SDK is ready
}];
```

{% endtab %}
{% endtabs %}

### setLogLevel

Set the minimum level of messages to log. The SDK will not log messages under that level.\
See [Logging](/cmp/mobile-sdk/ios/logging) for more information.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type    | Description                       |
| -------- | ------- | --------------------------------- |
| minLevel | `UInt8` | Minimum level of messages to log. |

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.setLogLevel(minLevel: 2)
```

{% endtab %}
{% endtabs %}

### setupUI

{% hint style="info" %}
Internally, the setupUI method calls the `showNotice` method, which calls the `shouldConsentBeCollected` method. Therefore, by calling the `setupUI` method, the notice or preferences view will be displayed only if required.
{% endhint %}

Setup the SDK UI workflows. This method is used to pass a reference to a `UIViewController` to the SDK that will use it as needed. By calling this method the notice or the preferences views will be displayed only once the SDK is ready and if consent should be collected. This must be called once in your main `UIViewController`.

**Requires SDK to be initialized**

No.

**Parameters**

| Name                | Type               | Description                                     |
| ------------------- | ------------------ | ----------------------------------------------- |
| containerController | `UIViewController` | The controller to use for displaying the notice |

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.setupUI(containerController: this)
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi setupUIWithContainerController:self];
```

{% endtab %}
{% endtabs %}

### showNotice

{% hint style="info" %}
In most cases this method should be called if the notice should be displayed in response to a user action (e.g.: select the privacy settings section within your app). By calling the setupUI method, the notice will be displayed if required.
{% endhint %}

Show the consent notice. The consent notice actually only gets shown if needed (consent is required and we are missing consent information for some vendor or purpose).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.showNotice()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi showNotice];
```

{% endtab %}
{% endtabs %}

### showPreferences

{% hint style="info" %}
In most cases this method should be called if you want to show the Preferences screen in response to a user action (the user pressing a "Consent Preferences" button in your app menu, for instance).
{% endhint %}

Show the Preferences view to the user. This method can be used to allow the user to update their preferences after the notice has been closed. We suggest adding a link/button/item that calls this method somewhere in your app, for example from your settings menu. By default, the Purposes view is displayed first. By calling this method, users will have the opportunity to modify the choices previously made.

{% hint style="info" %}
We strongly advise you to always pass the `viewController` parameter unless you can be certain that `setupUI` has been called.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name       | Type               | Description                                          |
| ---------- | ------------------ | ---------------------------------------------------- |
| controller | `UIViewController` | The controller to use for displaying the Preferences |
| view       | `Didomi.Views`     | The view to show (`.purposes` or `.vendors`)         |

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.showPreferences()
Didomi.shared.showPreferences(viewController, .purposes) // Open the Purposes view
Didomi.shared.showPreferences(viewController, .vendors) // Open the Vendors view
Didomi.shared.showPreferences(viewController, .sensitivePersonalInformation) // Open the Sensitive Personal Information view
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
// We use `self` assuming this method is called from a `UIViewController`
[didomi showPreferencesWithController:self view:ViewsPurposes];
```

{% endtab %}
{% endtabs %}

### updateSelectedLanguage

Method used to update the selected language of the Didomi SDK and any property that depends on it.

In most cases this method doesn't need to be called. It would only be required for those apps that allow language change on-the-fly, i.e.: from within the app rather than from the device settings.

If your configuration involves country code (`en-US`), you can provide a locale code to change the regional configuration as well. If only language code (`en`) is provided and your configuration requires a country code, the country from the device location will be used (and will fallback to the default country if required).

In order to update the language of the views displayed by the Didomi SDK, this method needs to be called before these views are displayed.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name         | Type     | Description                                                                                                        |
| ------------ | -------- | ------------------------------------------------------------------------------------------------------------------ |
| languageCode | `String` | string containing the 2-letter language code or 5-letter locale code e.g. `en`, `es`, `fr`, `en_US`, `zh_HK`, etc. |

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.onReady {
    Didomi.shared.updateSelectedLanguage(languageCode: "en")
}
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi onReadyWithCallback:^{
    [didomi updateSelectedLanguageWithLanguageCode:@"en"];
}];
```

{% endtab %}
{% endtabs %}

***

## Notice Config

### getPurpose

Get a purpose based on its ID.

{% hint style="warning" %}
**Not available for Objective-C**

This function is only exposed to Swift apps and cannot be called from Objective-C.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name      | Type     | Description                       |
| --------- | -------- | --------------------------------- |
| purposeId | `String` | ID of the purpose we want to get. |

**Returns**

| Type      | Description                                                              |
| --------- | ------------------------------------------------------------------------ |
| `Purpose` | A `Purpose` with ID `purposeId` found in the array of required purposes. |

**Example**

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

```swift
Didomi.shared.getPurpose(purposeId: "purpose-id")
```

{% endtab %}
{% endtabs %}

### getRequiredPurposes

Get the list of purpose that are required (automatically determined from the list of required vendors).

{% hint style="warning" %}
**Not available for Objective-C**

This function is only exposed to Swift apps and cannot be called from Objective-C.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type        | Description                                                  |
| ----------- | ------------------------------------------------------------ |
| `[Purpose]` | An array of type `Purpose` containing the required purposes. |

**Example**

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

```swift
Didomi.shared.getRequiredPurposes()
```

{% endtab %}
{% endtabs %}

### getRequiredVendors

Get the list of vendors that are required (determined from the configuration).

{% hint style="warning" %}
**Not available for Objective-C**

This function is only exposed to Swift apps and cannot be called from Objective-C.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type       | Description                                                |
| ---------- | ---------------------------------------------------------- |
| `[Vendor]` | An array of type `Vendor` containing the required vendors. |

**Example**

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

```swift
Didomi.shared.getRequiredVendors()
```

{% endtab %}
{% endtabs %}

### getText

Method used to get a dictionary/map based on the key being passed. These keys and texts are extracted from the notice content, preferences content and the `texts` property specified in the `didomi_config.json` file as described here <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme#translatable-texts-for-custom-notices>.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name | Type   | Description                                           |
| ---- | ------ | ----------------------------------------------------- |
| key  | String | key associated to the dictionary that we want to get. |

**Returns**

| Type           | Description                                                                                                                                                 |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Dictionary/map | Dictionary/map containing the translations for an specific key in different languages, with the form { "en:" "text in English", "fr": "texte en Français" } |

**Example**

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

```swift
Didomi.shared.getText("key")
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
NSString *translatedText = [didomi getTextWithKey:@"key"];
```

{% endtab %}
{% endtabs %}

### getTranslatedText

Method used to get a translated text based on the key being passed.

The language and the source of this translated text will depend on the availability of the translation for the specific key.

The language being used will be either the selected language of the SDK (based on device Locale and other parameters) or the language specified by app developers as the default language being used by the SDK. The source can be either the `didomi_config.json` file, which can be either local or remote, or a file that is bundled within the SDK.

These are the attempts performed by the SDK to try to find a translation for the specific key:

* Get translated value in user locale (selected language) from `didomi_config.json` (either local or remote).
* Get translated value in default locale (from the config) from `didomi_config.json` (either local or remote).
* Get translated value in user locale (selected language) from the Didomi-provided translations (bundled within the Didomi SDK).
* Get translated value in default locale (from the config) from the Didomi-provided translations (bundled within the Didomi SDK).

If no translation can be found after these 4 attempts, the key will be returned.

App developers can provide these translated texts through the `didomi_config.json` file (locally or remotely) in 3 different ways:

* Custom texts for the consent notice: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-notice#texts>
* Custom texts for the preferences: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#text>
* Custom texts for custom notices: [https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme#translatable-texts-for-custom-notices](https://developers.didomi.io/cmp/mobile-sdk/consent-notice/build-your-own-custom-notice#translatable-texts-for-custom-notices)

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name | Type   | Description                                                |
| ---- | ------ | ---------------------------------------------------------- |
| key  | String | key associated to the text that we want to get translated. |

**Returns**

Translated text.

**Example**

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

```swift
Didomi.shared.getTranslatedText("key")
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
NSString *translatedText = [didomi getTranslatedTextWithKey:@"key"];
```

{% endtab %}
{% endtabs %}

### getVendor

Get a vendor based on its ID.

{% hint style="warning" %}
**Not available for Objective-C**

This function is only exposed to Swift apps and cannot be called from Objective-C.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name     | Type     | Description                      |
| -------- | -------- | -------------------------------- |
| vendorId | `String` | ID of the vendor we want to get. |

**Returns**

| Type     | Description                                                           |
| -------- | --------------------------------------------------------------------- |
| `Vendor` | A `Vendor` with ID `vendorId` found in the array of required vendors. |

**Example**

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

```swift
Didomi.shared.getVendor(vendorId: "vendor-id")
```

{% endtab %}
{% endtabs %}

### getTotalVendorCount

Get the total count of required vendors.

**Requires SDK to be initialized**

Yes.

**Returns**

| Type  | Description            |
| ----- | ---------------------- |
| `Int` | The total vendor count |

**Example**

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

```java
Didomi.shared.getTotalVendorCount();
```

{% endtab %}

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

```kotlin
Didomi *didomi = [Didomi shared];

[didomi getTotalVendorCount];
```

{% endtab %}
{% endtabs %}

### getIABVendorCount

Get the count of required IAB vendors.

**Requires SDK to be initialized**

Yes.

**Returns**

| Type  | Description          |
| ----- | -------------------- |
| `Int` | The IAB vendor count |

**Example**

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

```java
Didomi.shared.getIABVendorCount();
```

{% endtab %}

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

```kotlin
Didomi *didomi = [Didomi shared];

[didomi getIABVendorCount];
```

{% endtab %}
{% endtabs %}

### getNonIABVendorCount

Get the count of required vendors which are not part of the IAB.

**Requires SDK to be initialized**

Yes.

**Returns**

| Type  | Description              |
| ----- | ------------------------ |
| `Int` | The non-IAB vendor count |

**Example**

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

```swift
Didomi.shared.getNonIABVendorCount();
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];

[didomi getNonIABVendorCount];
```

{% endtab %}
{% endtabs %}

## User Status

### applicableRegulation

Get the applicable regulation.

**Requires SDK to be initialized**

**yes.**

**Returns**

| Type   | Description                                                                                                                                                                                                                                   |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Enum` | <p>Representation of the current regulation as a <code>Regulation</code> enum value, such as <code>.gdpr</code>, <code>.cpra</code> or <code>.none</code>.</p><p>Note that some regulations present as enum values are not available yet.</p> |

**Example**

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

```swift
let regulation = Didomi.shared.applicableRegulation
```

{% endtab %}

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

```objectivec
NSString *regulation = [Didomi.shared applicableRegulation];
```

{% endtab %}
{% endtabs %}

### addVendorStatusListener

Listen for changes on the user status linked to a specific vendor.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type                                                 | Description                                                                                                                                                                                   |
| -------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id       | `String`                                             | <p>The ID of the vendor for which we want to start listening for changes.</p><p><br>This ID should be the ID provided by Didomi, which doesn't contain prefixes.</p>                          |
| callback | callback: `(CurrentUserStatus.VendorStatus) -> Void` | <p>Callback that will be executed whenever changes are detected on the specified vendor.<br><br>When this callback is executed, the status linked to the specified vendor will be passed.</p> |

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.addVendorStatusListener(id: "vendor-id") { newStatus in
  print("Vendor Status changed. New status: \(newStatus)")
}
```

{% endtab %}

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

```objectivec
[[Didomi shared] addVendorStatusListenerWithId:@"vendor-id" :^(DDMCurrentUserStatusVendor *newStatus) {
  NSLog(@"Vendor Status changed. New status: %@", newStatus);
}];
```

{% endtab %}
{% endtabs %}

### removeVendorStatusListener

Stop listening for changes on the user status linked to a specific vendor.

**Requires SDK to be initialized**

No.

**Parameters**

| Name | Type     | Description                                                                                                                                                     |
| ---- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id   | `String` | <p>The ID of the vendor for which we want to stop listening for changes.</p><p>This ID should be the ID provided by Didomi, which doesn't contain prefixes.</p> |

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.removeVendorStatusListener(id: "vendor-id")
```

{% endtab %}

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

{% endtab %}
{% endtabs %}

### getCurrentUserStatus

#### Definition

Exposes the user status for the current regulation that applies.

#### Parameters

No parameters.

#### Returns

The user status containing the computed global status for Vendors and purposes:

* A vendor's global status is enabled, if and only if:
  * the vendor is enabled directly in the vendors layer in all legal basis
  * **AND** all its related purposes are enabled or essential.
* A purpose's global status is enabled in one of the two conditions:
  * the purpose is enabled for all the legal basis that it is configured for.
  * **OR** when the purpose is essential.

| Parameter                     | Type      | Description                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ----------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| didomi\_dcs                   | `string`  | Didomi Consent String that stores end-user choices for custom and Google ATP vendors, and custom and global purposes across all regulations. [Click here](/cmp/didomi-consent-string) for more information.                                                                                                                                                                                                                             |
| vendors                       | `object`  | <ul><li>Dictionary that maps the ID of a vendor to an object representing its status.</li><li>The IDs used in this dictionary correspond to the Didomi IDs i.e.: without the <code>c:</code> or any other prefix.</li><li>Vendors with undefined user status are included in the response with <code>enabled: false.</code></li><li>Vendors with ONLY essential purposes are automatically set with <code>enable: true</code></li></ul> |
| purposes                      | `object`  | <ul><li>Dictionary that maps the ID of a purpose to an object representing its status.</li><li>Purposes with undefined user status are included in the response with <code>enabled: false.</code></li><li>Essential purposes are automatically set with <code>enable: true</code></li></ul>                                                                                                                                             |
| regulation                    | `enum`    | <ul><li>Representation of the current regulation as a <code>Regulation</code> enum value, such as <code>.gdpr</code>, <code>.cpra</code> or <code>.none</code>.</li><li>Note that some regulations present as enum values are not available yet.</li></ul>                                                                                                                                                                              |
| user\_id                      | `string`  | Didomi user id.                                                                                                                                                                                                                                                                                                                                                                                                                         |
| created                       | `string`  | User choices creation date.                                                                                                                                                                                                                                                                                                                                                                                                             |
| updated                       | `string`  | User choices update date.                                                                                                                                                                                                                                                                                                                                                                                                               |
| consent\_string               | `string`  | TCF consent as string                                                                                                                                                                                                                                                                                                                                                                                                                   |
| addtl\_consent                | `string`  | Google additional consent to pass end-user consent to Google Ad Technology Providers (ATP).                                                                                                                                                                                                                                                                                                                                             |
| gpp\_string                   | `string`  | GPP string.                                                                                                                                                                                                                                                                                                                                                                                                                             |
| shouldUserStatusBeCollected() | `Boolean` | Determine if the User Status (consent) should be collected or not, based on regulation, expiration date, and user status at the time of the call to `Didomi#getCurrentUserStatus()`. This method is only valid for objects returned by Didomi after a call to `getCurrentUserStatus()`. Not available in Objective-C.                                                                                                                   |

#### Examples

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

```swift
let currentUserStatus = Didomi.shared.getCurrentUserStatus()

// Example: get consent status for vendor `google`
let vendorStatus = currentUserStatus.vendors["google"]
let isVendorEnabled = vendorStatus.enabled

// Example: get consent status for custom vendor
// with ID `custom-vendor-id` (without `c:` prefix).
let customVendorStatus = currentUserStatus.vendors["custom-vendor-id"]
let isCustomVendorEnabled = customVendorStatus.enabled
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
DDMCurrentUserStatus *currentUserStatus = [didomi getCurrentUserStatus];

// Example: get consent status for vendor `google`
DDMVendorStatus *vendorStatus = [currentUserStatus.vendors objectForKey:@"google"];
BOOL isVendorEnabled = [vendorStatus.enabled boolValue];
```

{% endtab %}
{% endtabs %}

### isUserStatusPartial

#### Definition

Determine if the user has provided a choice for all vendors selected for the regulation and linked data processing.

This function returns `true` if the user has not expressed a choice for all the required vendors and data processing.

Requires SDK to be initialized.

#### Parameters

No parameters.

#### Returns

`boolean`

* This function returns true if the following conditions are all met
  * A regulation apply for the current user (i.e: regulation is not NONE)
  * At least one vendor is configured (if there is no vendor configured, this function always returns false as there is no status to collect)
  * We miss user status for some vendors or purposes
* Otherwise, it will return false.
  * e.g: If regulation = none (i.e no regulation apply to the end user) → This function returns false
* Edge cases: a new vendor is added to the notice and status is not collected yet for that vendor. In this case the function will return true until the user update their choice on the consent banner.

#### Examples

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

```swift
Didomi.shared.isUserStatusPartial()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
BOOL isUserStatusPartial = [didomi isUserStatusPartial];
```

{% endtab %}
{% endtabs %}

### openCurrentUserStatusTransaction

**Definition**

Create an instance of the `CurrentUserStatusTransaction` class.

This class provides mechanisms to stage updates to the user status regarding purposes and vendors, allowing for batch operations.

Updates made through its methods are queued and applied simultaneously to the user status only once the `commit` method of the returned object is called.

Additional details:

* The status of vendors and purposes whose IDs are not not specified through the methods provided by `CurrentUserStatusTransaction` are kept unchanged.
* Essential purposes are always set to enabled and can’t be updated by the methods provided by `CurrentUserStatusTransaction`.
* When the regulation applied for a user is `none`, the methods provided by `CurrentUserStatusTransaction` should not update the status of any vendor or purpose which will always remain as enabled. When the `commit` method is called it will return `false`.
* If the IDs that are passed through the methods provided by `CurrentUserStatusTransaction` don’t correspond to vendors or purposes required by the Notice Config, they will be ignored.

**Requires SDK to be initialized**

Yes.

#### Parameters

No parameter.

**Returns**

An instance of the `CurrentUserStatusTransaction` class.

**Description of the** `CurrentUserStatusTransaction` **class**

<table><thead><tr><th width="207">Method</th><th width="233">Parameters</th><th>Returns</th><th>Description</th></tr></thead><tbody><tr><td><code>enablePurpose</code></td><td><code>id</code> (<code>String</code>): ID of the purpose to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single purpose based on its ID.</td></tr><tr><td><code>enablePurposes</code></td><td><code>ids</code> (<code>[String]</code>): IDs of the purposes to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple purposes based on their IDs.</td></tr><tr><td><code>disablePurpose</code></td><td><code>id</code> (<code>String</code>): ID of the purpose to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single purpose based on its ID.</td></tr><tr><td><code>disablePurposes</code></td><td><code>ids</code> (<code>[String]</code>): IDs of the purposes to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple purposes based on their IDs.</td></tr><tr><td><code>enableVendor</code></td><td><code>id</code> (<code>String</code>): Didomi ID of the vendor to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single vendor based on its Didomi ID.</td></tr><tr><td><code>enableVendors</code></td><td><code>ids</code> (<code>[String]</code>): Didomi IDs of the vendors to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>disableVendor</code></td><td><code>id</code> (<code>String</code>): Didomi ID of the vendor to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single vendor based on its Didomi ID.</td></tr><tr><td><code>disableVendors</code></td><td><code>ids</code> (<code>[String]</code>): Didomi IDs of the vendors to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>commit</code></td><td>No parameters.</td><td><code>Bool</code>: <code>true</code> if user status has been updated, <code>false</code> otherwise.</td><td>Commit the changes that have been made through other methods.</td></tr></tbody></table>

#### Examples

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomi = Didomi.shared
</strong>let transaction = didomi.openCurrentUserStatusTransaction()

// enable a purpose
transaction.enablePurpose("cookies")
// enable purposes
transaction.enablePurpose(["cookies", "analytics"])
// disable a purpose
transaction.enablePurpose("analytics")
// disable purposes
transaction.disablePurposes(["cookies", "analytics"])
// enable a vendor
transaction.enableVendor("vendor-1")
// enable vendors
transaction.enableVendors(["vendor-1","vendor-2"])
// disable a vendor
transaction.disableVendor("vendor-1")
// disable vendors
transaction.disableVendors(["vendor-1", "vendor-1"])

// Chain multiple calls
transaction.enablePurpose("cookies").disablePurpose("analytics")

// Save user choices
let updated = transaction.commit()
</code></pre>

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
CurrentUserStatusTransaction *transaction = [didomi openCurrentUserStatusTransaction];

// Enable a purpose
[transaction enablePurpose:@"cookies"];
// Enable purposes
[transaction enablePurposes:@[@"cookies", @"analytics"]];
// Disable a purpose
[transaction disablePurpose:@"analytics"];
// Disable purposes
[transaction disablePurposes:@[@"cookies", @"analytics"]];
// Enable a vendor
[transaction enableVendor:@"vendor-1"];
// Enable vendors
[transaction enableVendors:@[@"vendor-1", @"vendor-2"]];
// Disable a vendor
[transaction disableVendor:@"vendor-1"];
// Disable vendors
[transaction disableVendors:@[@"vendor-1", @"vendor-2"]];

// Chain multiple calls
[[transaction enablePurpose:@"cookies"] disablePurpose:@"analytics"];

// Save user choices
BOOL updated = [transaction commit];
```

{% endtab %}
{% endtabs %}

### reset

**Definition**

Reset all the consent information for the current user. This will remove all consent information stored on the device by Didomi and will trigger re-collection of consent. The consent notice will be displayed again when `setupUI` is called.

If the SDK is not initialized when this method is called, the reset will be performed during SDK initialization.

**Requires SDK to be initialized**

No.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.reset()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi reset];
```

{% endtab %}
{% endtabs %}

### setCurrentUserStatus

#### Definition

Set the user status for purposes and vendors. This function will trigger events and API calls every time it is called (and the user status changes) so make sure to push all user choices at once and not one by one.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

#### Parameters

Add the desired global status for each vendor and each purpose:

* the vendor status specified in this function will be reflected on the vendor’s layer.
  * vendor enabled : true → means the vendor is enabled in all the legal basis that this vendor uses.
  * vendor enabled : false → means the vendor is disabled in all the legal basis that this vendor uses
* the purposes status specified in this function will be reflected on the preferences layer.
  * purpose enabled : true → means the purpose is enabled in all the legal basis in which it’s defined.
  * purpose enabled : false → means the purpose is disabled in all the legal basis in which it’s defined.

#### Returns

`boolean`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

#### Examples

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

<pre class="language-swift"><code class="lang-swift">let currentUserStatus = CurrentUserStatus(
    purposes: ["purpose1": PurposeStatus(id: "purpose1", enabled: true)],
    vendors: ["vendor1": VendorStatus(id: "vendor1", enabled: true)]
)

<strong>let updated = Didomi.shared.setCurrentUserStatus(currentUserStatus)
</strong></code></pre>

{% endtab %}

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

```objectivec
DDMCurrentUserStatusPurpose *purposeStatus = [[DDMCurrentUserStatusPurpose alloc] initWithId:@"purpose1" enabled:true];
DDMCurrentUserStatusVendor *vendorStatus = [[DDMCurrentUserStatusVendor alloc] initWithId:@"vendor1" enabled:true];

NSDictionary<NSString *, DDMCurrentUserStatusPurpose *> *purposeStatuses = @{
    @"purpose1": purposeStatus
};

NSDictionary<NSString *, DDMCurrentUserStatusVendor *> *vendorStatuses = @{
    @"vendor1": vendorStatus
};

DDMCurrentUserStatus *currentUserStatus = [[DDMCurrentUserStatus alloc] initWithPurposes:purposeStatuses vendors:vendorStatuses];

Didomi *didomi = [Didomi shared];
bool updated = [didomi setCurrentUserStatusWithCurrentUserStatus:currentUserStatus];
```

{% endtab %}
{% endtabs %}

### setUserAgreeToAll

Report that the user has enabled consents and legitimate interests for all purposes and vendors configured for your app.

This function will log the user choice on our platform and close the notice.

Consent statuses for essential purposes are not stored.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`Bool`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```swift
Didomi.shared.setUserAgreeToAll()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi setUserAgreeToAll];
```

{% endtab %}
{% endtabs %}

### setUserDisagreeToAll

Report that the user has disabled consents and legitimate interests for all purposes and vendors configured for your app.

This function will log the user choice on our platform and close the notice.

Consent statuses for essential purposes are not stored.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Requires SDK to be initialized**

Yes.

**Returns**

`Bool`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```swift
Didomi.shared.setUserDisagreeToAll()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi setUserDisagreeToAll];
```

{% endtab %}
{% endtabs %}

### shouldUserStatusBeCollected

#### Definition

Determine if user status (consent) should be collected for the visitor. Returns `true` if user status is required for the current user and one of following two conditions is met:

* User status has never been collected for this visitor yet
* New user status should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `false`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

Requires SDK to be initialized.

#### **Parameters**

No parameter.

#### **Returns**

`boolean`

#### Examples

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

```swift
Didomi.shared.shouldUserStatusBeCollected()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi shouldUserStatusBeCollected];
```

{% endtab %}
{% endtabs %}

### setUser

The `setUser` function is used to configure settings specific to the user currently navigating the mobile app. It can be used in various scenarios, such as:

* Authenticating the user.
* Enabling cross-device functionality. For detailed information, see [documentation](/cmp/mobile-sdk/share-consents-across-devices).
* Setting user-specific attributes, like identifying the user as underage.

**Parameter:**

<table><thead><tr><th width="198">Name</th><th width="254">Type</th><th>Description</th></tr></thead><tbody><tr><td>parameters</td><td><code>DidomiUserParameters</code></td><td>Object containing properties required to set a user.</td></tr></tbody></table>

***Description for*** `DidomiUserParameters`***:***

<table><thead><tr><th width="193">Name</th><th width="219">Type</th><th>Description</th></tr></thead><tbody><tr><td>userAuth</td><td><code>UserAuth</code></td><td>User authentication object. Can be either <code>UserAuthWithoutParams</code>, <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.</td></tr><tr><td>dcsUserAuth</td><td><code>UserAuthParams?</code></td><td>Optional. Dedicated user with encryption or hash used for Didomi Consent String signature. Can be either <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.<br>This parameter can only be used if you are using the Didomi Consent String feature (This feature is currently in beta version)</td></tr><tr><td>containerController</td><td><code>UIViewController?</code></td><td>Optional. Activity of the application if the notice should be displayed when the consent expired or the user is new.</td></tr><tr><td>isUnderage</td><td><code>Boolean?</code></td><td>Optional. Whether the user is underage or not. This parameters can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).</td></tr></tbody></table>

Parameters for `UserAuthWithoutParams` :

<table><thead><tr><th width="204">Name</th><th width="228">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr></tbody></table>

Parameters for `UserAuthWithEncryptionParams` :

<table><thead><tr><th width="211">Name</th><th width="202">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>String</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>String</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>initializationVector</td><td><code>String</code></td><td>Initialization Vector used for encrypting the message.</td></tr><tr><td>expiration</td><td><code>TimeInterval?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0).</td></tr></tbody></table>

Parameters for `UserAuthWithHashParams` :

<table><thead><tr><th width="212">Name</th><th width="205">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>String</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>String</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>digest</td><td><code>String</code></td><td>Digest used for representing the user ID</td></tr><tr><td>salt</td><td><code>String?</code></td><td>Optional. Salt used for computing the user ID.</td></tr><tr><td>expiration</td><td><code>TimeInterval?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0)</td></tr></tbody></table>

**Returns**

Nothing

**Example**

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

```swift
Didomi.shared.setUser(DidomiUserParameters(
            userAuth: UserAuthWithoutParams(
                        id: "e3222031-7c45-4f4a-8851-ffd57dbf0a2a"
            ), // user ID
            dcsUserAuth: UserAuthWithEncryptionParams(
                        id: "e3222031-7c45-4f4a-8851-ffd57dbf0a2b",
                        algorithm: "algorithm",
                        secretID: "secret_id",
                        initialisationVector: "initialization_vector",
                        expiration: 10000 // or null
            ), // optional DCS user authentication
            containerController: viewController, // optional View Controller
            isUnderage: true // optional underage flag
));

Didomi.shared.setUser(DidomiUserParameters(
            userAuth: UserAuthWithEncryptionParams(
                        id: "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
                        algorithm: "algorithm",
                        secretID: "secret_id",
                        initialisationVector: "initialization_vector",
                        expiration: 10000 // or nil
            ), // user authentication
            dcsUserAuth: UserAuthWithEncryptionParams(
                        id: "e3222031-7c45-4f4a-8851-ffd57dbf0a2b",
                        algorithm: "algorithm",
                        secretID: "secret_id",
                        initialisationVector: "initialization_vector",
                        expiration: 10000 // or nil
            ), // optional DCS user authentication
            containerController: viewController, // optional View Controller
            isUnderage: true // optional underage flag
));

Didomi.shared.setUser(DidomiUserParameters(
            userAuth: UserAuthWithHashParams(
                        id: "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
                        algorithm: "algorithm",
                        secretID: "secret_id",
                        digest: "digest",
                        salt: "salt", // or nil
                        expiration: 10000 // or nil
            ), // user authentication
            dcsUserAuth: UserAuthWithHashParams(
                        id: "e3222031-7c45-4f4a-8851-ffd57dbf0a2b",
                        algorithm: "algorithm",
                        secretID: "secret_id",
                        digest: "digest",
                        salt: "salt", // or nil
                        expiration: 10000 // or nil
            ), // optional DCS user authentication
            containerController: viewController, // optional View Controller
            isUnderage: true // optional underage flag
));
```

{% endtab %}

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

```objectivec
DidomiUserParameters *params1 = [[DidomiUserParameters alloc] initWithUserAuth:
    [[UserAuthWithoutParams alloc] initWithId: @"e3222031-7c45-4f4a-8851-ffd57dbf0a2a"]
    dcsUserAuth:[[UserAuthWithEncryptionParams alloc] initWithId: @"e3222031-7c45-4f4a-8851-ffd57dbf0a2b"
                                                     algorithm: @"algorithm"
                                                     secretID: @"secret_id"
                                        initialisationVector: @"initialization_vector"
                                                   expiration: @10000]
    containerController: viewController
    isUnderage: @(YES)];
[[Didomi shared] setUser: params1];

DidomiUserParameters *params2 = [[DidomiUserParameters alloc] initWithUserAuth:
    [[UserAuthWithEncryptionParams alloc] initWithId: @"e3222031-7c45-4f4a-8851-ffd57dbf0a2a"
                                           algorithm: @"algorithm"
                                           secretID: @"secret_id"
                              initialisationVector: @"initialization_vector"
                                         expiration: @10000]
    dcsUserAuth:[[UserAuthWithEncryptionParams alloc] initWithId: @"e3222031-7c45-4f4a-8851-ffd57dbf0a2b"
                                                     algorithm: @"algorithm"
                                                     secretID: @"secret_id"
                                        initialisationVector: @"initialization_vector"
                                                   expiration: @10000]
    containerController: viewController
    isUnderage: @(YES)];
[[Didomi shared] setUser: params2];

DidomiUserParameters *params3 = [[DidomiUserParameters alloc] initWithUserAuth:
    [[UserAuthWithHashParams alloc] initWithId: @"e3222031-7c45-4f4a-8851-ffd57dbf0a2a"
                                     algorithm: @"algorithm"
                                     secretID: @"secret_id"
                                       digest: @"digest"
                                         salt: @"salt"
                                   expiration: @10000]
    dcsUserAuth:[[UserAuthWithHashParams alloc] initWithId: @"e3222031-7c45-4f4a-8851-ffd57dbf0a2b"
                                               algorithm: @"algorithm"
                                               secretID: @"secret_id"
                                                 digest: @"digest"
                                                   salt: @"salt"
                                             expiration: @10000]
    containerController: viewController
    isUnderage: @(YES)];
[[Didomi shared] setUser: params3];
```

{% endtab %}
{% endtabs %}

### clearUser

Remove custom user information from organization. This will also reset the Didomi User ID.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

Nothing

#### Examples

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

```swift
Didomi.shared.clearUser()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi clearUser];
```

{% endtab %}
{% endtabs %}


# Deprecated

## Notice Config

### getRequiredPurposeIds

**Removed since version 2.0.0**, use [getRequiredPurposes](/cmp/mobile-sdk/android/reference/api#getrequiredpurposes) instead.

Get the list of purpose IDs that are required (automatically determined from the list of required vendors).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type (Swift)  | Type (Objective-C)    | Description                                                     |
| ------------- | --------------------- | --------------------------------------------------------------- |
| `Set<String>` | `NSSet<NSString *> *` | A set of type `String` containing the IDs of required purposes. |

**Example**

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

```swift
Didomi.shared.getRequiredPurposeIds()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
NSSet<NSString *> *requiredPurposeIds = [didomi getRequiredPurposeIds];
```

{% endtab %}
{% endtabs %}

### getRequiredVendorIds

**Removed since version 2.0.0**, use [getRequiredVendors](/cmp/mobile-sdk/ios/reference/api#getrequiredvendors) instead.

Get the list of vendor IDs that are required (determined from the configuration).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type (Swift)  | Type (Objective-C)    | Description                                                    |
| ------------- | --------------------- | -------------------------------------------------------------- |
| `Set<String>` | `NSSet<NSString *> *` | A set of type `String` containing the IDs of required vendors. |

**Example**

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

```swift
Didomi.shared.getRequiredVendorIds()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
NSSet<NSString *> *requiredVendorIds = [didomi getRequiredVendorIds];
```

{% endtab %}
{% endtabs %}

## User Status

### getUserConsentStatusForPurpose

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getUserConsentStatusForVendor

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getUserConsentStatusForVendorAndRequiredPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getUserLegitimateInterestStatusForPurpose

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getUserLegitimateInterestForVendor

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getUserLegitimateInterestStatusForVendorAndRequiredPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getUserStatus

**Deprecated**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

Get all the user consent status.

**Returns**

A `UserStatus` object describing all the available and computed user information.

| Parameter                                 | Type         | Description                                                                                                                                                                                                                                                                                                                 |
| ----------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| purposes.global.disabled                  | Set\<String> | Computed sets/lists of disabled IDs of purposes that have been chosen by the user regarding the consent or legitimate interest Legal Basis.                                                                                                                                                                                 |
| purposes.global.enabled                   | Set\<String> | Computed sets/lists of enabled IDs of purposes that have been chosen by the user regarding the consent or legitimate interest Legal Basis. Purposes considered as essential will be part of the enabled IDs.                                                                                                                |
| purposes.consent.disabled                 | Set\<String> | Disabled IDs of purposes that have been explicitly chosen by the user regarding the consent Legal Basis.                                                                                                                                                                                                                    |
| purposes.consent.enabled                  | Set\<String> | Enabled IDs of purposes that have been explicitly chosen by the user regarding the consent Legal Basis.                                                                                                                                                                                                                     |
| purposes.legitimateInterest.disabled      | Set\<String> | Disabled IDs of purposes that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.                                                                                                                                                                                                        |
| purposes.legitimateInterest.enabled       | Set\<String> | Enabled IDs of purposes that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.                                                                                                                                                                                                         |
| purposes.essential                        | Set\<String> | IDs of purposes that are considered essential.                                                                                                                                                                                                                                                                              |
| vendors.global.disabled                   | Set\<String> | Computed sets/lists of disabled IDs of vendors that have been chosen by the user regarding the consent or legitimate interest Legal Basis. This takes into account the consent and legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled. |
| vendors.global.enabled                    | Set\<String> | Computed sets/lists of enabled IDs of vendors that have been chosen by the user regarding the consent or legitimate interest Legal Basis. This takes into account the consent and legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.  |
| vendors.globalConsent.disabled            | Set\<String> | Computed sets/lists of disabled IDs of vendors that have been chosen by the user regarding the consent Legal Basis. This takes into account the consent required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.                                                |
| vendors.globalConsent.enabled             | Set\<String> | Computed sets/lists of enabled IDs of vendors that have been chosen by the user regarding the consent Legal Basis. This takes into account the consent required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.                                                 |
| vendors.globalLegitimateInterest.disabled | Set\<String> | Computed sets/lists of disabled IDs of vendors that have been chosen by the user regarding the legitimate interest Legal Basis. This takes into account the legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.                        |
| vendors.globalLegitimateInterest.enabled  | Set\<String> | Computed sets/lists of enabled IDs of vendors that have been chosen by the user regarding the legitimate interest Legal Basis. This takes into account the legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.                         |
| vendors.consent.disabled                  | Set\<String> | Disabled IDs of vendors that have been explicitly chosen by the user regarding the consent Legal Basis.                                                                                                                                                                                                                     |
| vendors.consent.enabled                   | Set\<String> | Enabled IDs of vendors that have been explicitly chosen by the user regarding the consent Legal Basis.                                                                                                                                                                                                                      |
| vendors.legitimateInterest.disabled       | Set\<String> | Disabled IDs of vendors that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.                                                                                                                                                                                                         |
| vendors.legitimateInterest.enabled        | Set\<String> | Enabled IDs of vendors that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.                                                                                                                                                                                                          |
| userId                                    | String       | Didomi user id.                                                                                                                                                                                                                                                                                                             |
| created                                   | String       | User choices creation date.                                                                                                                                                                                                                                                                                                 |
| updated                                   | String       | User choices update date.                                                                                                                                                                                                                                                                                                   |
| consentString                             | String       | TFC consent as string.                                                                                                                                                                                                                                                                                                      |
| additionalConsent                         | String       | Additional consent for [Google Additional Consent Mode](/cmp/mobile-sdk/third-party-sdks#google-additional-consent-mode).                                                                                                                                                                                                   |
| regulation                                | `Regulation` | Representation of the current regulation as a `Regulation` enum value, such as `gdpr`, `ccpa`, `cpra`, or `none`. Note that some regulations present as enum values are not available yet.                                                                                                                                  |

**Example**

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

```swift
let userStatus = Didomi.shared.getUserStatus()

// Enabled consent ids for vendors
let enabledVendorsConsentIds = userStatus.vendors.consent.enabled
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
DDMUserStatus *userStatus = [didomi getUserStatus];

// Enabled consent ids for vendors
NSSet *enabledVendorsConsentIDs = [[[userStatus vendors] consent] enabled];
```

{% endtab %}
{% endtabs %}

### getUserStatusForVendor

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getDisabledPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

Get the list of purposes that have been disabled by the user.

{% hint style="warning" %}
**Not available for Objective-C**

This function is only exposed to Swift apps and cannot be called from Objective-C.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type        | Description                                                              |
| ----------- | ------------------------------------------------------------------------ |
| `[Purpose]` | An array of type `Purpose` containing the purposes disabled by the user. |

**Example**

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

```swift
Didomi.shared.getDisabledPurposes()
```

{% endtab %}
{% endtabs %}

### getDisabledPurposeIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

Get the list of purpose IDs that have been disabled by the user.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type (Swift)  | Type (Objective-C)    | Description                                                                 |
| ------------- | --------------------- | --------------------------------------------------------------------------- |
| `Set<String>` | `NSSet<NSString *> *` | A set of type `String` containing the IDs of purposes disabled by the user. |

**Example**

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

```swift
Didomi.shared.getDisabledPurposeIds()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
NSSet<NSString *> *disabledPurposeIds = [didomi getDisabledPurposeIds];
```

{% endtab %}
{% endtabs %}

### getDisabledVendors

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

Get the list of vendors that have been disabled by the user.

{% hint style="warning" %}
**Not available for Objective-C**

This function is only exposed to Swift apps and cannot be called from Objective-C.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type       | Description                                                            |
| ---------- | ---------------------------------------------------------------------- |
| `[Vendor]` | An array of type `Vendor` containing the vendors disabled by the user. |

**Example**

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

```swift
Didomi.shared.getDisabledVendors()
```

{% endtab %}
{% endtabs %}

### getDisabledVendorIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getEnabledPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getEnabledPurposeIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getEnabledVendors

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### getEnabledVendorIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) instead.

### isConsentRequired

**Deprecated**, use [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) and check that the field `regulation`is not `.none`

Determine if consent is required for the user. This takes into account the location of the user and the configuration of the SDK:

* If your app is configured to apply GDPR to all users then this function always returns `true`.
* If your app is configured to apply GDPR to EU users only then this function returns `true` only if the user in the EU.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`Bool`

**Example**

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

```swift
Didomi.shared.isConsentRequired()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
BOOL isConsentRequired = [didomi isConsentRequired];
```

{% endtab %}
{% endtabs %}

### isUserConsentStatusPartial

**Deprecated**, use [isUserStatusPartial](/cmp/mobile-sdk/ios/reference/api#isuserstatuspartial) instead.

Determine if all consent information is available for the user.

This function returns `true` if and only if:

* Consent is required for the user (ie the user is in the EU or your tag is configured to apply GDPR to all users)
* At least one vendor is configured (if there is no vendor configured, this function always returns `false` as there is no consent to collect)
* We miss consent information for some vendors or purposes

If there is at least one piece of consent information missing for a single vendor/purpose, this function will return `true`. The consent notice is usually displayed when this function returns `true` although there is no guarantee of the direct mapping between the two.

An important edge case is when you add new vendors or if configured vendors ask for new purposes: the consent notice will be displayed again and this function will return `true` until the user has given or denied consent. Vendors that already had consent before will still operate normally as we only recollect consent for additional vendors/purposes.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`Bool`

**Example**

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

```swift
Didomi.shared.isUserConsentStatusPartial()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
BOOL isUserConsentStatusPartial = [didomi isUserConsentStatusPartial];
```

{% endtab %}
{% endtabs %}

### isUserLegitimateInterestStatusPartial

**Deprecated**, use [isUserStatusPartial](/cmp/mobile-sdk/ios/reference/api#isuserstatuspartial) instead.

Determine if all Legitimate Interest information is available for the user.

This function returns `true` if and only if:

* Legitimate Interest is required for the user (ie the user is in the EU or your tag is configured to apply GDPR to all users)
* At least one vendor is configured (if there is no vendor configured, this function always returns `false` as there is no Legitimate Interest to collect)
* We miss Legitimate Interest information for some vendors or purposes

If there is at least one piece of Legitimate Interest information missing for a single vendor/purpose, this function will return `true`. The consent notice is usually displayed when this function returns `true` although there is no guarantee of the direct mapping between the two.

An important edge case is when you add new vendors or if configured vendors ask for new purposes: the consent notice will be displayed again and this function will return `true` until the user has given or denied consent. Vendors that already had Legitimate Interest before will still operate normally as we only recollect Legitimate Interest for additional vendors/purposes.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`Bool`

**Example**

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

```swift
Didomi.shared.isUserLegitimateInterestStatusPartial()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
BOOL isUserLegitimateInterestStatusPartial = [didomi isUserLegitimateInterestStatusPartial];
```

{% endtab %}
{% endtabs %}

### setUserConsentStatus

**Removed since version 2.0.0**, use [setCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#setcurrentuserstatus) instead.

Set the user consent status for purposes and vendors. This function will trigger events and API calls every time it is called (and the user status changes) so make sure to push all your consent information at once and not one by one.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name               | Type          | Description                                               |
| ------------------ | ------------- | --------------------------------------------------------- |
| enabledPurposeIds  | `Set<String>` | Set of purpose IDs that the user has given consent to     |
| disabledPurposeIds | `Set<String>` | Set of purpose IDs that the user has not given consent to |
| enabledVendorIds   | `Set<String>` | Set of vendor IDs that the user has given consent to      |
| disabledVendorIds  | `Set<String>` | Set of vendor IDs that the user has not given consent to  |

**Returns**

`Bool`

`true` if the user consent status has changed (i.e. the user had given different consent information before this function got called).

**Example**

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

```swift
let didomi = Didomi.shared
didomi.setUserConsentStatus(enabledPurposeIds: ["1", "2"],
                            disabledPurposeIds: ["3", "4"],
                            enabledVendorIds: ["1", "2"],
                            disabledVendorIds: ["3", "4"])
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi setUserConsentStatusWithEnabledPurposeIds:[NSSet setWithArray:@[@"1",@"2"]]
                               disabledPurposeIds:[NSSet setWithArray:@[@"3",@"4"]]
                                 enabledVendorIds:[NSSet setWithArray:@[@"1",@"2"]]
                                disabledVendorIds:[NSSet setWithArray:@[@"3",@"4"]]];
```

{% endtab %}
{% endtabs %}

### setUserStatus

**Removed since version 2.0.0**, use [setCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#setcurrentuserstatus) instead.

Set the user status for purposes and vendors. This function will trigger events and API calls every time it is called (and the user status changes) so make sure to push all user choices at once and not one by one.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

#### Global method :

Define a global status for consent purposes, legitimate interest purposes, consent vendors, legitimate interest vendors

| Name                  | Type      | Description                                                                                             |
| --------------------- | --------- | ------------------------------------------------------------------------------------------------------- |
| purposesConsentStatus | `boolean` | `true` if purposes on a consent basis should be enabled, `false` if they should be disabled             |
| purposesLIStatus      | `boolean` | `true` if purposes on a legitimate interest basis should be enabled, `false` if they should be disabled |
| vendorsConsentStatus  | `boolean` | `true` if vendors on a consent basis should be enabled, `false` if they should be disabled              |
| vendorsLIStatus       | `boolean` | `true` if vendors on a legitimate interest basis should be enabled, `false` if they should be disabled  |

**Example**

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

```swift
Didomi.shared.setUserStatus(
    purposesConsentStatus: false,
    purposesLIStatus: true,
    vendorsConsentStatus: false,
    vendorsLIStatus: true)
```

{% endtab %}

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

<pre class="language-objectivec"><code class="lang-objectivec">Didomi *didomi = [Didomi shared];
<strong>[didomi setUserStatusWithPurposesConsentStatus:false
</strong>                         purposesLIStatus:true
                         vendorsConsentStatus:false
                         vendorsLIStatus:true];
</code></pre>

{% endtab %}
{% endtabs %}

#### Individual purposes / vendors method :

Allows to define precisely which purposes and vendors are enabled / disabled

| Name                      | Type          | Description                                                                                                                                |
| ------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| enabledConsentPurposeIds  | `Set<String>` | Set of purpose IDs that the user has given consent to                                                                                      |
| disabledConsentPurposeIds | `Set<String>` | Set of purpose IDs that the user has not given consent to                                                                                  |
| enabledLIPurposeIds       | `Set<String>` | Set of purpose IDs that the user has allowed legitimate interest processing to                                                             |
| disabledLIPurposeIds      | `Set<String>` | Set of purpose IDs that the user has disallowed legitimate interest processing to                                                          |
| enabledConsentVendorIds   | `Set<String>` | <p>Set of vendor IDs that the user has given consent to.</p><p>Prefix custom vendor IDs with <code>c:</code>.</p>                          |
| disabledConsentVendorIds  | `Set<String>` | Set of vendor IDs that the user has not given consent to                                                                                   |
| enabledLIVendorIds        | `Set<String>` | <p>Set of vendor IDs that the user has allowed legitimate interest processing to.</p><p>Prefix custom vendor IDs with <code>c:</code>.</p> |
| disabledLIVendorIds       | `Set<String>` | Set of vendor IDs that the user has not allowed legitimate interest processing to                                                          |

**Example**

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

```swift
Didomi.shared.setUserStatus(
    enabledConsentPurposeIds: ["cookies", "ad_delivery"],
    disabledConsentPurposeIds: ["market_research"],
    enabledLIPurposeIds: ["cookies", "market_research"],
    disabledLIPurposeIds: ["ad_delivery"],
    enabledConsentVendorIds: ["123", "c:custom-vendor-id"],
    disabledConsentVendorIds: ["125"],
    enabledLIVendorIds: ["123", "125", "c:custom-vendor-id"],
    disabledLIVendorIds: []
)
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi setUserStatusWithEnabledConsentPurposeIds:[NSSet setWithArray:@[@"cookies", @"ad_delivery"]]
                         disabledConsentPurposeIds:[NSSet setWithArray:@[@"market_research"]]
                         enabledLIPurposeIds:[NSSet setWithArray:@[@"cookies, market_research"]]
                         disabledLIPurposeIds:[NSSet setWithArray:@[@"ad_delivery"]]
                         enabledConsentVendorIds:[NSSet setWithArray:@[@"123",  @"c:custom-vendor-id"]]
                         disabledConsentVendorIds:[NSSet setWithArray:@[@"125"]]
                         enabledLIVendorIds:[NSSet setWithArray:@[@"123", @"125", @"c:custom-vendor-id"]]
                         disabledLIVendorIds:[[NSSet alloc] init]];
```

{% endtab %}
{% endtabs %}

### shouldConsentBeCollected

**Deprecated**, use [shouldUserStatusBeCollected](/cmp/mobile-sdk/ios/reference/api#shoulduserstatusbecollected) instead.

Determine if consent should be collected for the visitor. Returns `true` if consent is required for the current user and one of following two conditions is met:

* Consent has never been collected for this visitor yet
* New consents should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `false`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`boolean`

**Example**

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

```swift
Didomi.shared.shouldConsentBeCollected()
```

{% endtab %}

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

```objectivec
Didomi *didomi = [Didomi shared];
[didomi shouldConsentBeCollected];
```

{% endtab %}
{% endtabs %}

### setUser

**Deprecated**, use [setUser](/cmp/mobile-sdk/ios/reference/api#setuser) with `DidomiUserParameters` instead.

Set custom user information from organization. For detailed information, see [documentation](/cmp/mobile-sdk/share-consents-across-devices).

**Parameters**

***Method without authentication:***

<table><thead><tr><th width="206.72727272727272">Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>organizationUserId</td><td><code>String</code></td><td>Organization ID to associate with the user</td></tr><tr><td>containerController</td><td><code>UIViewController</code></td><td>Optional. When present, notice will be displayed if synchronized user has partial consents.</td></tr></tbody></table>

***Method with Encrypted authentication:***

| Name                | Type                           | Description                                                                                 |
| ------------------- | ------------------------------ | ------------------------------------------------------------------------------------------- |
| userAuthParams      | `UserAuthWithEncryptionParams` | User authentication with encryption                                                         |
| containerController | `UIViewController`             | Optional. When present, notice will be displayed if synchronized user has partial consents. |

Parameters for `UserAuthWithEncryptionParams` :

| Name                 | Type            | Description                                                |
| -------------------- | --------------- | ---------------------------------------------------------- |
| id                   | `String`        | Organization ID to associate with the user                 |
| algorithm            | `String`        | Algorithm used for computing the user ID                   |
| secretID             | `String`        | ID of the secret used for the computing the user ID        |
| initializationVector | `String`        | Initialization Vector used for encrypting the message      |
| expiration           | `TimeInterval?` | Expiration time as UNIX timestamp (optional - must be > 0) |

***Method with Hash authentication:***

| Name                | Type                     | Description                                                                                 |
| ------------------- | ------------------------ | ------------------------------------------------------------------------------------------- |
| userAuthParams      | `UserAuthWithHashParams` | User authentication with encryption                                                         |
| containerController | `UIViewController`       | Optional. When present, notice will be displayed if synchronized user has partial consents. |

Parameters for `UserAuthWithHashParams` :

<table data-header-hidden><thead><tr><th width="160.66666666666666">Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Type</td><td>Description</td></tr><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user</td></tr><tr><td>algorithm</td><td><code>String</code></td><td>Algorithm used for computing the user ID</td></tr><tr><td>secretID</td><td><code>String</code></td><td>ID of the secret used for the computing the user ID</td></tr><tr><td>digest</td><td><code>String</code></td><td>Digest used for representing the user ID</td></tr><tr><td>salt</td><td><code>String?</code></td><td>Salt used for computing the user ID (optional)</td></tr><tr><td>expiration</td><td><code>TimeInterval?</code></td><td>Expiration time as UNIX timestamp (optional - must be > 0)</td></tr></tbody></table>

**Returns**

Nothing

**Example**

```swift
Didomi.shared.setUser(id: "e3222031-7c45-4f4a-8851-ffd57dbf0a2a")

Didomi.shared.setUser(userAuthParams: UserAuthWithEncryptionParams(
            id: "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
            algorithm: "algorithm",
            secretID: "secret_id",
            expiration: 10000, // or nil
            initialisationVector: "initialization_vector"
))

Didomi.shared.setUser(userAuthParams: UserAuthWithHashParams(
            id: "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
            algorithm: "algorithm",
            secretID: "secret_id",
            digest: "digest",
            salt: "salt", // or nil
            expiration: 10000 // or nil
))           
```


# Events

The Didomi SDK triggers various events to notify you that the user has taken some action (changed their consent status, open the preferences screen, etc.) or that an important event has happened.

This section describes what events are available and how to subscribe to them.

## addEventListener

Add an event listener to catch events triggered by the SDK. Events listeners allow you to react to different events of interest. This function is safe to call before the `ready` event has been triggered.

**Requires SDK to be initialized**

No.

**Parameters**

| Name          | Type            | Description                                                      |
| ------------- | --------------- | ---------------------------------------------------------------- |
| eventListener | `EventListener` | The event listener. An instance of a subclass of `EventListener` |

**Returns**

Nothing

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onConsentChanged = { event in
</strong>    // The consent status of the user has changed
}

didomiEventListener.onHideNotice = { event in
    // The notice is being hidden
}

didomiEventListener.onShowNotice = { event in
    // The notice is being shown
}

Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];

[didomiEventListener setOnConsentChanged:^(enum DDMEventType event) {
    // The consent status of the user has changed
}];

[didomiEventListener setOnHideNotice:^(enum DDMEventType event) {
    // The notice is being hidden
}];

[didomiEventListener setOnShowNotice:^(enum DDMEventType event) {
    // The notice is being shown
}];

[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

### Event types <a href="#event-types" id="event-types"></a>

This section presents a comprehensive list of the event types exposed by the Didomi SDK and usage examples.

#### **onConsentChanged**

Triggered when a consent is given or withdrawn by the user. It's only triggered when the consent status actually changes. For instance, if the user saves consents without adding/removing any consent then this does not get called.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onConsentChanged = { event in
</strong>    // The consent status of the user has changed
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnConsentChanged:^(enum DDMEventType event) {
    // The consent status of the user has changed
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onHideNotice**

Triggered when the consent notice is hidden. If you have disabled our default consent notice to replace it with your own, you need to hide your custom notice when this event gets triggered.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onHideNotice = { event in
</strong>    // The notice is being hidden
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnHideNotice:^(enum DDMEventType event) {
    // The notice is being hidden
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onShowNotice**

Triggered when the consent notice gets displayed. If you have disabled our default consent notices to replace them with your own, you need to show your custom notice when this event gets triggered.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onShowNotice = { event in
    // The notice is being shown
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnShowNotice:^(enum DDMEventType event) {
    // The notice is being shown
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onNoticeClickAgree**

Triggered when the user clicks on agree on the notice.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onNoticeClickAgree = { event in
    // Click on agree on notice
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnNoticeClickAgree:^(enum DDMEventType event) {
    // Click on agree on notice
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onNoticeClickMoreInfo**

Triggered when the user clicks on learn more on the notice.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onNoticeClickMoreInfo = { event in
    // Click on learn more on notice
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnNoticeClickMoreInfo:^(enum DDMEventType event) {
    // Click on learn more on notice
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onHidePreferences**

Triggered when the preferences screen becomes hidden, for example when the user closes it or saves their consent.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onHidePreferences = { event in
    // The preferences screen is being hidden
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnHidePreferences:^(enum DDMEventType event) {
    // The preferences screen is being hidden
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onShowPreferences**

Triggered when the preferences screen gets displayed.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onShowPreferences = { event in
    // The preferences screen is being shown
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnShowPreferences:^(enum DDMEventType event) {
    // The preferences screen is being shown
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickAgreeToAll**

Triggered when the user clicks on agree to all on the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickAgreeToAll = { event in
    // Click on agree to all on preferences popup
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickAgreeToAll:^(enum DDMEventType event) {
    // Click on agree to all on preferences popup
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickDisagreeToAll**

Triggered when the user clicks on disagree to all on the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickDisagreeToAll = { event in
    // Click on disagree to all on preferences popup
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickDisagreeToAll:^(enum DDMEventType event) {
    // Click on disagree to all on preferences popup
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickPurposeAgree**

Triggered when the user agrees to a purpose on the preferences popup.

**Listener parameters**

* event: EventType (enum)
* purposeId: String

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickPurposeAgree = { event, purposeId in
    // Click on agree to a purpose on preferences popup
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickPurposeAgree:^(enum DDMEventType event, purposeId) {
    // Click on agree to a purpose on preferences popup
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickPurposeDisagree**

Triggered when the user disagrees to a purpose on the preferences popup. (purposeId provided as a parameter)

**Listener parameters**

* event: EventType (enum)
* purposeId: String

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickPurposeDisagree = { event, purposeId in
    // Click on disagree to a purpose on preferences popup
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickPurposeDisagree:^(enum DDMEventType event, purposeId) {
    // Click on disagree to a purpose on preferences popup
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickViewVendors**

Triggered when the user clicks on view vendors on the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickViewVendors = { event in
    // Click view vendors on purposes view on preferences popup
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickViewVendors:^(enum DDMEventType event) {
    // Click view vendors on purposes view on preferences popup
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickViewSPIPurposes**

Triggered when the user clicks on view Sensitive Personal Information from the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onPreferencesClickViewSPIPurposes = { event in
</strong>    // User clicked on view Sensitive Personal Information from the preferences popup.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickViewSPIPurposes:^(enum DDMEventType event) {
    // User clicked on view Sensitive Personal Information from the preferences popup.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickSaveChoices**

Triggered when the user saves his choice on the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickSaveChoices = { event in
    // Click on save on the purposes view on preferences popup
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickSaveChoices:^(enum DDMEventType event) {
    // Click on save on the purposes view on preferences popup
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

**onPreferencesClickVendorAgree**

Triggered when the user agrees to a vendor on the preferences popup.

**Listener parameters**

* event: EventType (enum)
* vendorId: String

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickVendorAgree = { event, vendorId in
    // Click on agree to a vendor on preferences popup
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickVendorAgree:^(enum DDMEventType event, vendorId) {
    // Click on agree to a vendor on preferences popup
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

**onPreferencesClickVendorDisagree**

Triggered when the user disagrees to a vendor on the preferences popup.

**Listener parameters**

* event: EventType (enum)
* vendorId: String

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickVendorDisagree = { event, vendorId in
    // Click on disagree to a vendor on preferences popup
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickVendorDisagree:^(enum DDMEventType event, vendorId) {
    // Click on disagree to a vendor on preferences popup
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickVendorSaveChoices**

This happens when the user saves his choice on the vendors view on the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickVendorSaveChoices = { event in
    // Click on save on the vendors view on preferences popup
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickVendorSaveChoices:^(enum DDMEventType event) {
    // Click on save on the vendors view on preferences popup
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onNoticeClickDisagree**

Triggered when the user clicks on disagree on the notice.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onNoticeClickDisagree = { event in
    // Select disagree on the notice
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnNoticeClickDisagree:^(enum DDMEventType event) {
    // Select disagree on the notice
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onNoticeClickViewVendors**

Triggered when the user clicks on partners on the notice.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onNoticeClickViewVendors = { event in
    // Select Our Partners on the notice
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnNoticeClickViewVendors:^(enum DDMEventType event) {
    // Select Our Partners on the notice
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onNoticeClickViewSPIPurposes**

Triggered when the user clicks on Sensitive Personal Information from the notice.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onNoticeClickViewSPIPurposes = { event in
</strong>    // User clicked on Sensitive Personal Information from the notice.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnNoticeClickViewSPIPurposes:^(enum DDMEventType event) {
    // User clicked on Sensitive Personal Information from the notice.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onNoticeClickPrivacyPolicy**

Triggered when the user clicks on privacy policy on the notice (available on TV only).

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onNoticeClickPrivacyPolicy = { event in
    // Select Our Privacy Policy on the notice (tvOS only)
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnNoticeClickPrivacyPolicy:^(enum DDMEventType event) {
    // Select Our Privacy Policy on the notice (tvOS only)
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickAgreeToAllPurposes**

Triggered when the user flips ON all purposes switch on the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickAgreeToAllPurposes = { event in
    // Agree to all purposes using the bulk action button on the preferences screen
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickAgreeToAllPurposes:^(enum DDMEventType event) {
    // Agree to all purposes using the bulk action button on the preferences screen
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickDisagreeToAllPurposes**

Triggered when the user flips OFF all purposes switch on the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickDisagreeToAllPurposes = { event in
    // Disagree to all purposes using the bulk action button on the preferences screen
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickDisagreeToAllPurposes:^(enum DDMEventType event) {
    // Disagree to all purposes using the bulk action button on the preferences screen
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickAgreeToAllVendors**

Triggered when the user flips ON all vendors switch on the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickAgreeToAllVendors = { event in
    // Agree to all vendors using the bulk action button on the preferences screen
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickAgreeToAllVendors:^(enum DDMEventType event) {
    // Agree to all vendors using the bulk action button on the preferences screen
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickDisagreeToAllVendors**

Triggered when the user flips OFF all vendors switch on the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickDisagreeToAllVendors = { event in
    // Disagree to all vendors using the bulk action button on the preferences screen
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickDisagreeToAllVendors:^(enum DDMEventType event) {
    // Disagree to all vendors using the bulk action button on the preferences screen
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickViewPurposes**

Triggered when the user clicks on view purposes on the preferences popup.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
didomiEventListener.onPreferencesClickViewPurposes = { event in
    // Select displaying the purposes on the preferences screen
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickViewPurposes:^(enum DDMEventType event) {
    // Select displaying the purposes on the preferences screen
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickSPIPurposeAgree**

Triggered when the toggle linked to a Personal Data purpose is set to agree/enabled.

**Listener parameters**

* event: EventType (enum)
* purposeId: String (nullable/optional)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onPreferencesClickSPIPurposeAgree = { event, purposeId in
</strong>    // Toggle linked to a Personal Data purpose was set to agree/enabled.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickSPIPurposeAgree:^(enum DDMEventType event, NSString * _Nullable purposeId) {
    // Toggle linked to a Personal Data purpose was set to agree/enabled.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickSPIPurposeDisagree**

Triggered when the toggle linked to a Personal Data purpose is set to disagree/disabled.

**Listener parameters**

* event: EventType (enum)
* purposeId: String (nullable/optional)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onPreferencesClickSPIPurposeDisagree = { event, purposeId in
</strong>    // Toggle linked to a Personal Data purpose was set to disagree/disabled.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickSPIPurposeDisagree:^(enum DDMEventType event, NSString * _Nullable purposeId) {
    // Toggle linked to a Personal Data purpose was set to disagree/disabled.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickSPICategoryAgree**

Triggered when the toggle linked to a Personal Data category is set to agree/enabled.

**Listener parameters**

* event: EventType (enum)
* categoryId: String (nullable/optional)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onPreferencesClickSPICategoryAgree = { event, categoryId in
</strong>    // Toggle linked to a Personal Data category was set to agree/enabled.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickSPICategoryAgree:^(enum DDMEventType event, NSString * _Nullable categoryId) {
    // Toggle linked to a Personal Data category was set to agree/enabled.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickSPICategoryDisagree**

Triggered when the toggle linked to a Personal Data category is set to disagree/disabled.

**Listener parameters**

* event: EventType (enum)
* categoryId: String (nullable/optional)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onPreferencesClickSPICategoryDisagree = { event, categoryId in
</strong>    // Toggle linked to a Personal Data category was set to disagree/disabled.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickSPICategoryDisagree:^(enum DDMEventType event, NSString * _Nullable categoryId) {
    // Toggle linked to a Personal Data category was set to disagree/disabled.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onPreferencesClickSPIPurposeSaveChoices**

Triggered when the Save button from the Sensitive Personal Information screen is pressed.

**Listener parameters**

* event: EventType (enum)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onPreferencesClickSPIPurposeSaveChoices = { event in
</strong>    // Save button from the Sensitive Personal Information screen was pressed.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnPreferencesClickSPIPurposeSaveChoices:^(enum DDMEventType event) {
    // Save button from the Sensitive Personal Information screen was pressed.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onSyncUserChanged**

Triggered when the user is changed from [setUser](/cmp/mobile-sdk/ios/reference/api#setuser) function only if sync is enabled.

**Listener parameters**

* `SyncUserChangedEvent`: object

  | Property | Type     | Description                                                                                          |
  | -------- | -------- | ---------------------------------------------------------------------------------------------------- |
  | userAuth | UserAuth | The new user as `UserAuthWithoutParams`, `UserAuthWithEncryptionParams` or `UserAuthWithHashParams`. |

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onSyncUserChanged = { event in
</strong>    let userAuth = event.userAuth
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener onSyncUserChanged:^(DDMSyncUserChangedEvent event) {
    NSUserAuth *userAuth = event.userAuth;
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onSyncDone**

{% hint style="warning" %}
This event has been deprecated. Use [onSyncReady](#onsyncready) instead.
{% endhint %}

Triggered when the consent synchronization is successful (Cross-device).

**Listener parameters**

* event: EventType (enum)
* organizationUserId: String (nullable/optional)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onSyncDone = { event, organizationUserId in
</strong>    // The consent synchronization was successful.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnSyncDone:^(enum DDMEventType event, NSString * _Nullable organizationUserId) {
    // The consent synchronization was successful.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onSyncError**

Triggered when the consent synchronization has failed (Cross-device).

**Listener parameters**

* event: EventType (enum)
* error: String (nullable/optional)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onSyncError = { event, error in
</strong>    // The consent synchronization has failed.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnSyncError:^(enum DDMEventType event, NSString * _Nullable error) {
    // The consent synchronization has failed.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onSyncReady**

Triggered when the user status synchronization is ready (Cross-device).

**Listener parameters**

`SyncReadyEvent` object

| Property           | Type              | Description                                                                                                                                                                                          |
| ------------------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| organizationUserId | String            | The organization user ID (OUID) used for the sync.                                                                                                                                                   |
| statusApplied      | Boolean           | Indicates if the user status has been applied locally from the remote Didomi backend. `true` if the user status was applied from the remote, `false` otherwise.                                      |
| syncAcknowledged   | Lambda expression | Callback that can be used to communicate to the Didomi servers that the synchronization has been communicated to the user. Returns `true` if the API event was successfully sent, `false` otherwise. |

**Example**

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

```swift
let didomiEventListener = EventListener()

didomiEventListener.onSyncReady = { event in
    // User status synchronization was successful.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
```

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnSyncReady:^(DDMSyncReadyEvent* event) {
    // The consent synchronization was successful.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onLanguageUpdated**

Triggered when SDK language has been successfully changed.

**Listener parameters**

* event: EventType (enum)
* languageCode: String (nullable/optional)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onLanguageUpdated = { event, languageCode in
</strong>    // SDK language has been successfully changed.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnLanguageUpdated:^(enum DDMEventType event, NSString * _Nullable languageCode) {
    // SDK language has been successfully changed.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

#### **onLanguageUpdateFailed**

Triggered when SDK language update has failed. (reason provided as a parameter)

**Listener parameters**

* event: EventType (enum)
* reason: String (nullable/optional)

**Example**

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

<pre class="language-swift"><code class="lang-swift"><strong>let didomiEventListener = EventListener()
</strong>
<strong>didomiEventListener.onLanguageUpdateFailed = { event, reason in
</strong>    // SDK language update has failed.
}
Didomi.shared.addEventListener(listener: didomiEventListener)
</code></pre>

{% endtab %}

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

```objectivec
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnLanguageUpdateFailed:^(enum DDMEventType event, NSString * _Nullable reason) {
    // Event was triggered.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}

### onIntegrationError

Triggered when an integration with an external SDK is not working as expected. The currently supported external SDKs are **Firebase**, **Airbridge**, **AppsFlyer**, and **Branch** (see related documentation [here](/cmp/mobile-sdk/google-consent-mode#how-does-it-work-on-apps)). This event indicates that Didomi was not able to update the privacy signals for the specified SDK.

**Listener parameters**

`IntegrationErrorEvent` object with the following properties:

<table data-header-hidden><thead><tr><th>Method</th><th width="171.33333333333331">Type</th><th>Description</th></tr></thead><tbody><tr><td>Method</td><td>Type</td><td>Description</td></tr><tr><td><code>integrationName</code></td><td>String</td><td>Name of the failing SDK integration, such as <code>Firebase SDK</code>, <code>Airbridge SDK</code>...</td></tr><tr><td><code>reason</code></td><td>String</td><td>Technical reason of the failure</td></tr></tbody></table>

#### Example

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

```swift
let didomiEventListener: EventListener = EventListener()

didomiEventListener.onIntegrationError = { event in
    // An external SDK integration is not working properly
    print("\(event.integrationName) : Integration error - \(event.reason)")
}
        
Didomi.shared.addEventListener(listener: didomiEventListener)
```

{% endtab %}

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

```objective-c
DDMEventListener *didomiEventListener = [[DDMEventListener alloc] init];
[didomiEventListener setOnIntegrationError:^(DDMIntegrationErrorEvent* event) {
    // An external SDK integration is not working properly.
}];
[didomi addEventListenerWithListener:didomiEventListener];
```

{% endtab %}
{% endtabs %}


# Versions

### 2.47.0 (August 3, 2026)

**Features:**

* Update translations and embedded GVL version.

**Fixes:**

* Check the reachability connection instead of its description when determining network connectivity
* Forward `sdkPath` and `apiPath` to the Web SDK so notices displayed in a WebView load their static files and reach the API through the custom domain.

### 2.46.0 (July 21, 2026)

**Features:**

* Update translations and embedded GVL version.

**Fixes:**

* Stop resetting `userId` during `clearUser()`.

### 2.45.0 (July 6, 2026)

**Features:**

* App V2 (WebView): Fix user ID mismatch between native and web components.
* Add `sdkPath` and `apiPath` parameters to `DidomiInitializeParameters` to override the base URLs used for static files and API requests respectively.

### 2.44.0 (June 16, 2026)

**Features:**

* Add API events to monitor UI rendering time.
* Add API events to monitor deprecated `Didomi` methods usage.
* Add `frameworks` field to user payload in API events.

**Fixes:**

* CPRA: Fix 1st party vendor purposes not being enabled by default in the Web UI (App v2).
* Memory leak: Prevent retaining `WKWebView` instances when using AppV2.
* Include the public API key (`key` query parameter) on `/sign`, `/sync` and `/batch-sign` API requests to allow access logs to be attributed to the originating organization.

### 2.43.0 (May 25, 2026)

**Features:**

* Add API events to monitor some `Didomi` methods usage.

**Fixes:**

* Prevent merging custom vendors with Didomi vendors when configuration does not request it.

### 2.42.0 (May 4, 2026)

**Features:**

* Update translations and embedded GVL version.

### 2.41.0 (April 20, 2026)

**Features:**

* IAB TCF: Apply April 2026 updates including SDK items and new `specialPurposes` and `optOut` fields for cookie disclosures.
* IAB TCF: Apply cache control for vendor device storage disclosures.
* Update GPP library to use `@iabgpp/cmpapi` version `3.1.8` which adds support for `UsMn` section.

**Fixes:**

* Reset ready state so `isReady()` returns false during re-initialization.

### 2.40.0 (April 7, 2026)

**Features:**

* Add API events to monitor SDK initialization performance.

**Fixes:**

* GPP: Improve handling of GPP fields when user regulation changes.

### 2.39.0 (March 23, 2026)

**Features:**

* Update translations and embedded GVL version.
* GCM: Update privacy signals transmitted to `Firebase`, `AppsFlyer` and `Branch` integrations.

### 2.38.0 (March 9, 2026)

**Features:**

* Update translations and embedded GVL version.

**Fixes:**

* DCS and App V2: Improve status handling for vendors defined by Didomi.

### 2.37.0 (February 23, 2026)

**Features:**

* Update translations and embedded GVL versions.

**Fixes:**

* Set `SyncReadyEvent.statusApplied` to `true` only if consent status was changed by the user synchronization process.
* Improve performance of `Didomi.getCurrentUserStatus` method.

### 2.36.2 (February 9, 2026)

**Fixes:**

* Prevent triggering onConsentChanged event after a call to `clearUser()`.
* Load bundle logo image from App v2 (WebView)
* tvOS: Make sure disclosure arrows are shown when the label is too long

### 2.36.1 (January 28, 2026)

**Fixes:**

* Address conflicting use cases between `TCF 2.2` and `TCF 2.3`.

### 2.36.0 (January 26, 2026)

**Features:**

* TCF 2.3: Add value `IABTCF_DisclosedVendors` to user defaults.

### 2.35.0 (January 12, 2026)

{% hint style="info" %}
This release requires Xcode 26 which is also the minimum version required by Apple to upload apps to the App Store.
{% endhint %}

**Features:**

* Update translations and embedded GVL versions.

**Fixes:**

* Handle TC String for custom purposes overriding IAB purposes.
* GCM: Make sure external SDKs are updated even when consent types are not specified in the configuration.

### 2.34.0 (December 1, 2025)

**Features:**

* tvOS: Improve accessibility, adding hints to most UI elements.
* tvOS: Add support for the `preferences.enableAllButtons` configuration parameter.
* Add support for the `preferences.vendorsLayer.enabled` configuration parameter.
* GCM: Improve accuracy of privacy signals transmitted to `Firebase`, `AppsFlyer` and `Branch` integrations.

**Fixes:**

* Fix toggle size on iOS 26.1.
* Fix a decoding issue for User Status when fields are missing.
* Improve consent recollection behavior after GVL updates.
* Ensure SDK storage disclosure retention times display correctly.
* Prevent calls to unavailable methods when the Didomi SDK is not ready yet.

### 2.33.1 (November 25, 2025)

**Fixes:**

* Corrected an issue affecting App V2 notices where user status was not saved correctly for non-GDPR regulations.

### 2.33.0 (November 6, 2025)

**Features:**

* Update translations and embedded GVL versions.

### 2.32.1 (January 28, 2026)

{% hint style="info" %}
This is the minimum required SDK version to fully support IAB TCF v2.3 consent notices on iOS and tvOS.
{% endhint %}

**Fixes:**

* Address conflicting use cases between `TCF 2.2` and `TCF 2.3`.

### 2.32.0 (October 24, 2025)

**Features:**

* Handle new requirements for TCF 2.3 in the TC String:
  * TC String now contains the Disclosed Vendors segment.
  * When consent and legitimate interest purposes are all disabled, Vendors with consent or legitimate interest purposes are marked as disabled even if they present special purposes.
* Update GPP library version.

### 2.31.1 (October 9, 2025)

**Fixes:**

* Fix incorrect field name for new event `IntegrationErrorEvent`: `sdkName` is replaced by `integrationName`.
* `onIntegrationError` trigger was missing in some cases.

### 2.31.0 (October 3, 2025)

**Features:**

* Add alphabetical headers to the list of vendors.
* Add event handlers to GCM integrations..
* Support new US regulations:
  * Minnesota Consumer Data Privacy Act (`MCDPA`).
  * Maryland Online Data Privacy Act (`MODPA`).
  * Rhode Island Data Transparency and Privacy Protection Act (`RIDTPPA`).
  * Indiana Consumer Data Protection Act (`INCDPA`).
  * Kentucky Consumer Data Protection Act (`KCDPA`).
  * Nebraska Data Privacy Act (`NDPA`).
  * Tennessee Information Protection Act (`TIPA`).

**Fixes:**

* When using the web notice in popup format, the background color was white. It is now the same as the banner format (black + alpha).

### 2.30.0 (September 17, 2025)

**Features:**

* tvOS: improved accessibility by restructuring the `User Info` screen.

**Fixes:**

* Some UI elements were not updating correctly when language was updated asynchronously.
* List of vendors: ignore case sensitivity when sorting vendors.

### 2.29.1 (August 14, 2025)

**Fixes:**

* App v2 (WebView): `hidePreferences` event was not being triggered.

### 2.29.0 (August 12, 2025)

**Features:**

* tvOS: add missing `button` role for accessibility.
* App v2 (WebView): update background of `bottom` notice format.

### 2.28.0 (August 4, 2025)

**Features:**

* Add `GCM` support for `AppsFlyer`.

**Fixes:**

* Preferences: theme was not being applied correctly to buttons.

### 2.27.0 (July 29, 2025)

**Features:**

* Add `GCM` support for `Firebase`, `AirBridge`, `Branch` and `Kochava`.

**Fixes:**

* Purposes set as Legitimate Interest only were not enabled by default on mixed regulations (e.g.: CPRA) .
* App v2 (WebView):
  * Notice was not displayed on iOS 15/16 devices and a white screen was displayed instead.
  * Notice page was displayed 1 out of 2 times when Preferences page was resurfaced.
  * `configByCountry` Config field was not working.

### 2.26.3 (July 11, 2025)

**Fixes:**

* On tvOS, the Legitimate Interest status is now translated on the *Vendor Details* screen.
* Remove embedded configurations for deprecated `TCF v2.1`.

### 2.26.2 (July 7, 2025)

**Fixes:**

* Update translations and embedded GVL versions.

### 2.26.1 (June 23, 2025)

**Fixes:**

* Applied fix for upcoming feature. Most clients can continue using version 2.26.0 without needing to update to this version.

### 2.26.0 (June 20, 2025)

{% hint style="info" %}
This version includes support for App v2 (WebView) mode. You can enable this feature from the Console. More information is available [here](https://docs.didomi.io/consent-management-platform-cmp/consent-notices/mobile-app-v2-webview).
{% endhint %}

**Features:**

* Add support for App v2 (WebView) mode.
* Accessibility: added missing heading roles in multiple screens.
* Accessibility: re-structured `User Information` screen.
* Accessibility: improved physical keyboard navigation.
* Accessibility: improved navigation on the `Device Storage Disclosure` screen within vendor details.
* Accessibility: improved layout of links on the Purposes screen in order to adapt better when the font size of the device has been updated.

**Fixes:**

* `user.ignoreConsentBefore` was being ignored if the date contained milliseconds.

### 2.25.1 (May 28, 2025)

**Features:**

* Add new languages support (Belarus, Bosnian, Basque, English Canada, Galician, Georgian, Maltese, Albanian, Tagalog, Welsh)
* Add new screen to display `User Information` for tvOS in order to match with mobile SDK.

{% hint style="info" %}
New languages must be enabled from the Console once they are available.
{% endhint %}

**Fixes:**

* Update properties of the Facebook vendor provided by Didomi.

### 2.24.2 (May 2, 2025)

{% hint style="info" %}
This release requires Xcode 16 which is also the minimum version required by Apple to upload apps to the App Store.
{% endhint %}

**Fixes:**

* Under certain circumstances, apps configured for Swift 6 were crashing.

### 2.24.1 (April 30, 2025)

**Fixes:**

* Apply fix in preparation for upcoming feature.

### 2.24.0 (April 25, 2025)

**Features:**

* Add boolean field to identify if `preferences.purposechanged` API event is triggered from a Purpose Category screen or not.

**Fixes:**

* On tvOS, focus could become stuck on the notice depending on the configuration.
* On tvOS, make sure there is a link to the partners list from the notice when it is legally required.
* On tvOS 18.x, focus could be brought back to another item than the previous selected item when a sub-screen is closed.

### 2.23.0 (April 16, 2025)

**Features:**

* Update accessibility descriptions for Preferences screens.
* Update `Didomi Consent String` computation (*beta*).

### 2.22.0 (April 3, 2025)

**Features:**

* Update accessibility description for Preferences screens.
* When a vendor is not associated with legitimate interest purposes but has special purposes, always include it in IAB TCF Consent String legitimate interest vendors section (IAB TCF update).
* Additional focus customization option for tvOS.
* Trigger `SyncReady` event even when `Cross-Device` feature is disabled.

**Fixes:**

* HMTL lists were not displayed properly on iOS 18.x.
* Fix didomi logo position from the bottom bar for devices without notch.

### 2.21.1 (March 21, 2025)

**Fixes:**

* Replace checkboxes with switches for legitimate interest-based purposes on tvOS.

### 2.21.0 (March 18, 2025)

**Features:**

* Add new features to `CurrentUserStatus` returned by [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus):
  * `gppString` field (*beta*).
  * Utility method `shouldUserStatusBeCollected()` .
* Modify the layout of the bottom bar buttons on the Preferences screen.
* Handle configuration parameter `preferences.enableAllButtons` .

### 2.20.0 (March 5, 2025)

**Features**

* Update GPP library version (*beta*).

### 2.19.1 (February 11, 2025)

**Fixes:**

* Cross-device: Make sure remote consent expiration is checked before applying consent synchronization.

### 2.19.0 (January 30, 2025)

**Features:**

* Create new `setUser` function that accepts an instance of the new `DidomiUserParameters` (more information [here](/cmp/mobile-sdk/ios/reference/api#setuser)).
* Deprecate the other `setUser` functions (more information [here](/cmp/mobile-sdk/ios/reference/api/deprecated#setuser)).

**Fixes:**

* Scale custom logo loaded from URL with the screen density.
* Ignore new line characters (`\n`) around HTML line breaks (`<br>`) in custom texts from the Notice and Preferences screens.

### 2.18.0 (January 9, 2025)

**Features:**

* Created new applicableRegulation public API that provides an enum value (`.cpra`, `.gdpr`, `.none`, etc.) containing the regulation being applied (more information [here](/cmp/mobile-sdk/ios/reference/api#applicableregulation)).

**Fixes:**

* Optimize performance when updating the consent from the cross-device response.
* Improved accessibility of the vendors screen in order to allow the user to access the details of a vendor when using a physical keyboard.

### 2.17.1 (December 13, 2024)

**Features:**

* Add US regulation support for Utah: `ucpa`.

### 2.17.0 (December 11, 2024)

**Features:**

* Add support for `onSyncUserChanged` callback. See reference [here](/cmp/mobile-sdk/ios/reference/events#onsyncuserchanged) for more information.
* Accessibility: Increase contrast in toggle buttons icons.
* Stop displaying Sensitive Personal Information in a separate screen.

**Fixes:**

* Add missing icon to indicate that the "Our Privacy Policy" link targets a page outside of the application.

### 2.16.1 (December 6, 2024)

**Fixes:**

* Optimize the way in which the user choices are stored in UserDefaults to prevent crashes on tvOS.
* Allow Legitimate Interest purposes and vendors to be enabled by default on tvOS.
* In some cases when navigating using VoiceOver, buttons were not being enabled properly when scrolling the content of the notice.
* IAB TCF tag was not part of the vendor element when navigating with VoiceOver enabled.

### 2.16.0 (November 18, 2024)

**Features:**

* Update translations and embedded GVL version.

### 2.15.1 (October 31, 2024)

**Fixes:**

* Apply improvements regarding thread safety.

### 2.15.0 (October 25, 2024)

**Features:**

* Add new `organizationUserId` parameter for `SyncReady` event (see [documentation](/cmp/mobile-sdk/ios/reference/events#onsyncready)).

**Fixes:**

* Get consent from server when `setUser` is called. If the user is new, you will need to call `setupUI` to get the notice. In order to display the notice automatically, you can call `setUser` and provide the `containerController` (see [documentation](/cmp/mobile-sdk/share-consents-across-devices#multi-account)).

### 2.14.0 (October 10, 2024)

**Features:**

* Update translations and embedded GVL version.

### 2.13.1 (October 2, 2024)

**Fixes:**

* Update translations and embedded GVL versions.

### 2.13.0 (September 23, 2024)

**Fixes:**

* Handle purposes bulk action state when using First Party Vendors.
* Remove unneeded field from `Storage Disclosure` screen.

### 2.12.0 (September 13, 2024)

**Features:**

* Support Serbian latin language script.
* Rename `IDPL` regulation to `ICDPA`.

### 2.11.1 (August 20, 2024)

**Fixes:**

* Trigger `onError` callback when there's no Internet connection.
* Add improvements around recollection.
* Make sure sticky buttons behave correctly when scrolling the content of the notice.

### 2.11.0 (July 30, 2024)

**Features:**

* Implement First Party Vendors support.
* Support Publisher TC segment from the Consent String.

**Fixes:**

* Merge duplicated Vendors declared from different sources (IAB, Didomi, Custom).

### 2.10.0 (July 15, 2024)

**Features:**

* Add support for TCF v2.2 amendments (implement new `Storage Disclosure` button and screen).

### 2.9.2 (July 2, 2024)

**Fixes:**

* Applied various improvements to increase thread safety and improve memory management.

### 2.9.1 (June 24, 2024)

**Features:**

* Add support for new regulations: `dpdpa`, `fdbr`, `idpl`, `mcdpa`, `nhpa`, `njdpa`, `ocpa` and `tdpsa`.
* Set a minimum frequency for user synchronization process.
* Only rely on SDK configuration obtained from Didomi to determine the user regulation

  <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>From this version, local configuration fields <code>gdprAppliesGlobally</code> and <code>gdprAppliesWhenUnknown</code> are ignored. To adapt notice behavior to user country, it is now mandatory to use remote configuration. See <a href="/pages/-LKOtdup9v6C7sF6X24f#from-the-console-recommended">here</a> for more information.</p></div>
* Mark obsolete methods as `Deprecated`:

  * `isConsentRequired`
  * `isUserConsentStatusPartial`
  * `isUserLegitimateInterestStatusPartial`
  * `getUserStatus`

  See the complete list of deprecated methods [here](/cmp/mobile-sdk/ios/reference/api/deprecated).
* Support for `IABTCF_EnabledAdvertiserConsentMode` for Google Consent Mode, through the configuration flag `integrations.vendors.gcm.enableTCFAdvertiserConsentMode`. See the [related documentation](/cmp/mobile-sdk/google-consent-mode#enabling-consent-modes-tcf-integration) for more information.

**Fixes:**

* Allow the use of GVL v3 even if TCF is disabled in the SDK configuration.
* Make sure purpose and vendor toggles behave properly when bulk action is activated on Mac Catalyst.
* Make sure a fallback is provided in case a translation is missing for an IAB element.

### 2.8.0 (June 6, 2024)

**Features:**

* Updated logic around setting the vendors' status based on purposes' status.

### 2.7.1 (May 30, 2024)

**Fixes:**

* Disable sticky header for Sensitive Personal Information screen.
* Multiple UI improvements when font scaling is enabled from the device accessibility settings.

### 2.7.0 (May 23, 2024)

**Features:**

* Display an icon indicating when a link targets a page outside of the application.

**Fixes:**

* Make sure `onSyncReady` event is triggered each time the consent synchronization process occurs.
* On tvOS, adapt the font size of notice text when required to make sure it is fully displayed.
* On tvOS, distribute the notice buttons proportionally in order to display long privacy policy button.
* On tvOS, enable scrolling when displaying purposes list from a category.

### 2.6.0 (May 10, 2024)

**Features:**

* Add field `isIAB` in `Vendor` object to indicate if vendor is from the IAB Global Vendor List

### 2.5.0 (April 26, 2024)

**Features:**

* Add new parameters to `DidomiInitializeParameters` to override the user location determined by the SDK when getting the notice configuration:
  * `countryCode`: Force the user country used to get the notice configuration.
  * `regionCode` : Force the user region used to get the notice configuration.
* Add support for new `SyncReady` event. See the [event documentation](/cmp/mobile-sdk/ios/reference/events#onsyncready) for more information.
* Deprecate `SyncDone` event.

### 2.4.0 (April 10, 2024)

**Features:**

* Make sure that vendors removed from the GVL are not present in the notice or in the IAB Consent String when the IAB TCF framework is enabled.
* Increase contrast for secondary texts to improve readability.

**Fixes:**

* Do not display button to open Sensitive Personal Information screen, if there is no valid SPI purpose to display.

### 2.3.0 (March 27, 2024)

**Features:**

* Sign XCFramework bundle based on latest requirements from Apple.
* Deprecate CCPA regulation.
* Set values for `IABTCF_CmpSdkID`, `IABTCF_CmpSdkVersion`, `IABTCF_PolicyVersion` and `IABTCF_gdprApplies` even when GDPR does not apply.

### 2.2.0 (March 18, 2024)

**Features:**

* Create new `openCurrentUserStatusTransaction` method which returns an instance of `CurrentUserStatusTransaction`. This class can be used to asynchronously enable and disable specific vendors and purposes. For more information, see the [documentation](https://developers.didomi.io/cmp/mobile-sdk/ios/reference/api#opencurrentuserstatustransaction).
* Added Apple Privacy Manifest file.
* Display Purpose Categories for Apple TV.

**Fixes:**

* Update the `getCurrentUserStatus` method so it marks as enabled those purposes that are enabled by default on the UI when the regulation applied is opt-out or mixed (e.g.: CPRA) and the user hasn’t expressed any choices yet.

### 2.1.0 (March 6, 2024)

**Features:**

* Create new `addVendorStatusListener` and `removeVendorStatusListener` methods to observe changes in the status of individual Vendors (For more information, see the [documentation](/cmp/mobile-sdk/ios/reference/api#addvendorstatuslistener)).

### 2.0.2 (February 26, 2024)

**Fixes:**

* Expose the following methods to Objective-C: `getVendor`, `getPurpose`, `getRequiredVendors` and `getRequiredPurposes`.
* Sort Device Storage Disclosure list by `identifier` and `type` in order to prevent random order from the Vendor details screen.

### 2.0.1 (February 16, 2024)

**Fixes:**

* Make sure ***IAB Google Vendor*** details screen displays TCF 2.2 data such as localized Privacy Policy link, Data Declaration and Data Retention.

### 2.0.0 (February 15, 2024)

{% hint style="danger" %}
**Major update of the SDK**

This release will contain some breaking changes, described below.

**Migration steps:**

1. Update ***Didomi SDK*** to version `1.99.0` if it is not already the case.
2. Replace any deprecated usages that might appear with the alternatives suggested by *Xcode*. If *Xcode* does not suggest any updates, it means no deprecated methods are being used.
3. Update ***Didomi SDK*** to version `2.0.0`.
   {% endhint %}

{% hint style="danger" %}
The `Purpose` class returned by `getPurpose` and `getRequiredPurposes`, and the `Vendor` class returned by `getVendor` and `getRequiredVendors` were modified. If you encounter an issue with these changes (such as a removed field), please reach out to **<support@didomi.io>**.

Important notes:

* `Vendor.id` is now the ID provided by Didomi, without prefix
* `Purpose.description` is not related to Didomi anymore, as it is a reserved iOS field. The correct field to use is `Purpose.descriptionText`
  {% endhint %}

**Features:**

* Set the minimum supported version to `iOS 10`.
* Remove deprecated functions below:\
  \&#xNAN;*Deprecated as of v1.60.2*

  * `getDisabledPurposeIds`
  * `getDisabledPurposes`
  * `getDisabledVendorIds`
  * `getDisabledVendors`
  * `getEnabledPurposeIds`
  * `getEnabledPurposes`
  * `getEnabledVendorIds`
  * `getEnabledVendors`

  [`getUserStatus`](/cmp/mobile-sdk/ios/reference/api#getuserstatus) or [`getCurrentUserStatus`](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) should be used instead.

  * `initialize` (without `DidomiInitializeParameters`)

  *Deprecated as of v1.58.0*

  * `setUser` (with authentication parameters instead of `UserAuthParams`)

  *Deprecated as of v1.56.0*

  * `getUserConsentStatusForPurpose`
  * `getUserConsentStatusForVendor`
  * `getUserConsentStatusForVendorAndRequiredPurposes`
  * `getUserLegitimateInterestStatusForPurpose`
  * `getUserLegitimateInterestStatusForVendor`
  * `getUserLegitimateInterestStatusForVendorAndRequiredPurposes`
  * `getUserStatusForVendor`

  [`getUserStatus`](/cmp/mobile-sdk/ios/reference/api#getuserstatus) or [`getCurrentUserStatus`](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) should be used instead.
* Update Didomi brand logo for AppleTV notices.
* Prevent `showPreferences` to display **Sensitive Personal Information** screen (see [showPreferences](/cmp/mobile-sdk/ios/reference/api#showpreferences)) if there is no such purpose to display.
* Modified `Purpose` class returned by methods `getPurpose` and `getRequiredPurposes`. See details below:
  * `id` (*String*) the Purpose ID.
  * `name` (*String*) the Purpose name.
  * `descriptionText` (*String*) the Purpose description. This property replaces the previous `description` property.
  * Removed properties:
    * `iabId` (*String?*)
    * `descriptionLegal` (*String?*)
* Modified `Vendor` class returned by methods `getVendor` and `getRequiredVendors`. See details below:
  * `id` (*String*) the Vendor ID provided by Didomi without any prefix.
  * `name` (*String*) the Vendor name.
  * `namespaces` (*Namespaces?*) the Namespaces of the vendor (*IAB*, *num*) and their corresponding ids.
  * `policyUrl` (*String*) the privacy policy URL (replace `privacyPolicyUrl`).
  * `purposeIDs` (*Set\<String>*) the Purpose list with legal basis "consent".
  * `legIntPurposeIDs` (*Set\<String>*) the Purpose list with legal basis "legitimate interest".
  * `featureIDs` (*Set\<String>*) the ID list that represent features.
  * `flexiblePurposeIDs` (*Set\<String>*) the ID list that represent flexible purposes.
  * `specialFeatureIDs` (*Set\<String>*) the ID list that represent Special Features.
  * `specialPurposeIDs` (*Set\<String>*) the ID list that represent Special Purposes.
  * `urls` (*\[Url]?*) the localized Privacy policy and LI disclaimer urls introduced in TCF v2.2.
  * Removed properties:
    * `namespace` (*String?*)
    * `iabID` (*String?*)

**Fixes:**

* Make sure IAB Consent String is not stored on the device when no regulation applies.
* Filter vendors not having any purposes.

### 1.99.0 (February 8, 2024)

**Features:**

* Hide `Sensitive Personal Information` button from the Notice and Preferences screens if there is no such purpose to display.
* Ensure that regulation `NONE` will behave as expected (no consent required, notice and preferences screens can't be displayed and all vendors and purposes are enabled).

**Fixes:**

* Prevent logo to be scaled up from the Notice screen.

### 1.98.0 (January 22, 2024)

**Features:**

* Use default country code then default language when custom translations are missing for selected language.
* Create new public function `setCurrentUserStatus()` (See [setCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#setcurrentuserstatus) for more information).
* Create new public function `getCurrentUserStatus()` (See [getCurrentUserStatus](/cmp/mobile-sdk/ios/reference/api#getcurrentuserstatus) for more information).

**Fixes:**

* Fix typo in TCF 2.2 notice for Spanish translation.
* Check if SDK is ready before `isConsentRequired()` (see [isConsentRequired](/cmp/mobile-sdk/ios/reference/api#isconsentrequired) for more information).

### 1.97.0 (January 11, 2024)

**Features:**

* Update Didomi brand logo for preferences screens.
* Create new public function `isUserStatusPartial()` (See [isUserStatusPartial](/cmp/mobile-sdk/ios/reference/api#isuserstatuspartial) for more information).
* Create new public function `shouldUserStatusBeCollected()` (See [shouldUserStatusBeCollected](/cmp/mobile-sdk/ios/reference/api#shoulduserstatusbecollected) for more information).

**Fixes:**

* Serbian translation was containing some Latin labels instead of Cyrillic.

### 1.96.0 (December 12, 2023)

**Features:**

* Set TCF version 2.2 as default version (current TCF 2.1 notices will be treated as TCF 2.2 notices).

### 1.95.2 (December 4, 2023)

**Fixes:**

* Fix vendors’ privacy policy link.
* Fix margins on Device Storage details screen.
* Fix to ignore purposes and special features coming from Custom Vendors when creating the TCF Consent String.

### 1.95.1 (November 23, 2023)

**Fixes:**

* Update Notice logo constraints. Maximum height is now set to `150px` (instead of `50px`).
* Publisher restrictions now applies to `Facebook` vendor.
* Fix Polish translation for Partners count label on Notice screen.

### 1.95.0 (November 17, 2023)

**Features:**

* Update IAB policy links URLs to <https://iabeurope.eu/iab-europe-transparency-consent-framework-policies/>.
* Add support for new language regions: Arabic (Jordan), Dutch (Belgium), English (New Zealand), English (United Kingdom), French (Belgium), French (Canada), German (Austria), German (Switzerland).
* Handle Regulation field (`user.regs`) in synchronization requests and API events.
* Specify "non-IAB partners" instead of just "partners" when presenting count of partners associated to a purpose.
* Update list of purposes associated to Facebook vendor.
* Handle `notice.enableBulkActionOnPurpose` config parameter, to allow to hide the `enable / disable all purposes` switch on preferences screen.

**Fixes:**

* In some configs, color of the `Refuse all` button on preferences screen was not correct.

### 1.94.0 (November 6, 2023)

{% hint style="info" %}
This is the minimum required sdk version to fully handle TCF v2.2 notices on iOS and tvOS.
{% endhint %}

**Features:**

* Add methods to get vendors count: [`getTotalVendorCount()`](/cmp/mobile-sdk/ios/reference/api#gettotalvendorcount), [`getIABVendorCount()`](/cmp/mobile-sdk/ios/reference/api#getiabvendorcount), [`getNonIABVendorCount()`](/cmp/mobile-sdk/ios/reference/api#getnoniabvendorcount)

**Fixes:**

* Support IAB purpose 11 from TCF 2.2

### 1.93.1 (October 20, 2023)

**Fixes:**

* Handle translation of TCF v2.2 purposes and GVL 3 even when there is no internet connection.

### 1.93.0 (October 17, 2023)

{% hint style="info" %}
This version added support for TCF v2.2 notices on tvOS. However it does not correctly handle purpose 11 (`Use limited data to select content`), sdk version 1.94.0 or higher should be used instead.
{% endhint %}

**Features:**

* Full TCF v2.2 support for tvOS.
* Change label of "View our partners" notice button to "Manage our partners" .

**Fixes:**

* Improve loading time to display the list of vendors associated to a purpose.

### 1.92.0 (October 4, 2023)

{% hint style="info" %}
This version added support for TCF v2.2 notices on iOS. However it does not correctly handle purpose 11 (`Use limited data to select content`), sdk version 1.94.0 or higher should be used instead.
{% endhint %}

**Features:**

* TCF v2.2 support.
* Revert the design and label of the partners button displayed on the notice (underlined / "View our partners").
* Add support for new macros (`numberOfPartners`, `numberOfIABPartners` and `numberOfNonIABPartners`) from the Preferences screens, see the full list [here](/cmp/web-sdk/consent-notice/preferences#macros).
* Remove support of `notice.content.viewOurPartners` configuration parameter from AppleTV Notice (the same default label as mobile will be used).

**Fixes:**

* Fix `popup` notice's height taking too much space.
* Fix `onHideNotice` event not triggered when Didomi notice is not enabled.

### 1.91.0 (September 19, 2023)

**Features:**

* Better layouts (fonts, margins, etc...) for `Additional Data Processing`, `Purposes` and `Vendors` detail screens.

**Fixes:**

* Add missing IAB tag on `Vendor` detail screen.
* Manage empty privacy policy url from `Custom Vendor` detail screen.
* Fix `onShowNotice` event not triggered when Didomi notice is not enabled.
* Fix the bottom button bar from Preferences screens on iPad not using the expected width when only the `Save` button is displayed.
* Fix the Device Storage section description displayed in a single line on tvOS (from the Partner detail screen).

### 1.90.0 (July 18, 2023)

**Features:**

* Change the "Learn More" link into button.

**Fixes:**

* The Vendor button from the Notice will use the `theme.color` parameter if no highlighted button theme is defined.
* tvOS Vendor bulk action was displaying IAB tag after changing its status.
* tvOS wasn't reverting Purpose and Vendor consent when closing and bringing back the Preferences without saving (UI issue only - consent was always accurate).

### 1.89.1 (July 10, 2023)

**Features:**

* In notice, modify design of "Manage our partners" and "Learn more" links
* In vendor details screen, move links to IAB and privacy policy outside of privacy policy disclaimer (improves accessibility)
* Mark `disableDidomiRemoteConfig` initialization parameter as deprecated.

{% hint style="info" %}
Didomi SDK configuration should be done through the console. In the future, local configuration file will no longer be supported.
{% endhint %}

**Fixes:**

* GDPR was not correctly applied for additional countries set in console.

### 1.89.0 (July 7, 2023)

{% hint style="info" %}
This version has a graphical issue, it should not be used
{% endhint %}

### 1.88.1 (May 11, 2023)

**Fixes:**

* Handle 3-digit color codes and alpha component position
* Improve handling of indented html lists in notice and preferences texts

### 1.88.0 (April 20, 2023)

**Features:**

* Display message on Sensitive Personal Information screen when no Personal Data is present.
* Display IAB TCF tag for IAB Vendors on tvOS vendors list.
* Prevent warnings when using Swift 6.

**Fixes:**

* Handle special features linked to custom vendors.
* Better handle html line breaks in notice text.

### 1.87.0 (April 3, 2023)

**Features:**

* Enable **`CPRA`** regulation support.
* Create new `Sensitive Personal Information` screens.
* Create new Internal events for `Sensitive Personal Information` interactions (see [Events](/cmp/mobile-sdk/ios/reference/events)).
* Update `Additional Data Processing` list from `Purpose` screen in order to improve accessibility.
* Replace a deprecated method used when encoding the consent string

**Fixes:**

* Notch detection was not accurate for iPhone 14

### 1.86.0 (March 20, 2023)

**Features:**

* Add a link to `privacyPolicyURL` on preferences (Purpose) screen when the link is not present in text description.
* Remove link to `privacyPolicyURL` in embedded default preferences (Purpose) screen description.
* Accessibility improvements for buttons in Notice screen.

**Fixes:**

* Fix Purpose labels not using the same language as the rest of the Preferences screen when the language is set during the initialization.
* Allow multiline buttons from the preferences screens footer.
* Trigger warning log when `clearUser()` is called before SDK initialization.
* Remove extra bottom margin for Purpose list Description for iOS 13.0.

### 1.85.0 (March 8, 2023)

**Features:**

* On preferences screen, display **Agree to all** / **Disagree to all** buttons only if regulation is GDPR.

**Fixes:**

* When notice was not enabled from configuration, default notice was briefly displayed before the preferences screen.
* Fix layout issues after device orientation changes.

### 1.84.1 (February 28, 2023)

**Fixes:**

* Fix line break from Notice description, Purpose header description and Vendor header description.
* Revert public methods `getNoticeViewController()` and `getPreferencesViewController()`.

### 1.84.0 (February 22, 2023)

**Features:**

* Accessibility improvements in purposes and vendors screens.
* Call `onError` callback when invalid API key is submitted to `Didomi.initialize`.

**Fixes:**

* Incorrect rendering of `<ul><li>` tags in preferences description.
* Theme was not applied to purposes screen header.
* Modify some constraints to remove warning logs.
* Invalid consent string when publisher restrictions were duplicated.

### 1.83.0 (February 8, 2023)

**Features:**

* Accessibility improvements in:
  * Partners button on main notice.
  * Purposes screen.
  * Purpose details buttons.
  * Vendors screen.
  * Vendor details buttons.
* New User Information button from the Vendor screen.

**Fixes:**

* Prevent Required Purpose detail screen to display the footer from the Purpose screen.

### 1.82.0 (January 30, 2023)

**Features:**

* Accessibility improvements on Notice screen
* Accessibility improvements on Purposes screen

**Fixes:**

* When opening Partners screen from Notice, Purposes screen was briefly displayed just before
* Some large title could overlap the Close button in Preferences screens (Purposes and Vendors)

### 1.81.0 (December 14, 2022)

**Features:**

* Allow font family to be applied to all UI elements on the screen (see [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#custom-font-family) for more details).
* Cross-device: do not reset Didomi User ID by default, unless `clearUser` is called (see [Share consents across devices](/cmp/mobile-sdk/share-consents-across-devices#multi-account) for more details).

### 1.80.0 (November 17, 2022)

**Features:**

* Remove TCF v1 support.
* Supporting url and resource name from `logoUrl` configuration parameter.

### 1.79.1 (October 24, 2022)

**Fixes:**

* Fix transparent background for fullscreen notices on older iOS version (below 14.0).

### 1.79.0 (October 20, 2022)

**Features:**

* Optimize display of Purpose legal description.
* Added support for Swift Package Manager (see [Setup](/cmp/mobile-sdk/ios/setup#using-swift-package-manager) documentation).

**Fixes:**

* Fix transparent Notice background for older iOS version (below 14.0).
* Fix some text colors for darker background color.
* Fix missing device disclosure url for some Vendors.

### 1.78.0 (September 16, 2022)

**Features:**

* Add ability to enable sticky buttons on the notice (see [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#sticky-buttons)).
* Disable location query from device GPS when the location permissions are granted (we now rely only on our API to get the user location and to provide the matching regulation).

**Fixes:**

* Update link to IAB TCF v2 from the vendor detail page.

### 1.77.0 (September 13, 2022)

**Features**:

* Add support for [Broken mention](broken://pages/VZfMhuOHLCX779bHGobx)

{% hint style="info" %}
CCPA support is still in beta, please contact <support@didomi.io> if you are interested to participate
{% endhint %}

### 1.76.0 (September 8, 2022)

**Features:**

* Improve how texts scale based on the device settings.
* Improved accessibility on buttons displayed on the notice.

**Fixes:**

* Consent asked events was using all required purposes as both consent and legitimate interest.

### 1.75.0 (August 25, 2022)

**Features:**

* Improve accessibility of close buttons and headings on Preferences screens.

**Fixes:**

* Reduce tvOS SDK size by removing unnecessary classes.

### 1.74.0 (August 8, 2022)

**Features:**

* Simplify Vendors button from Purpose list page.
* Add ability to enable fullscreen mode (see [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#fullscreen-mode) for more details).
* Handle device storage disclosure as link (instead of json) from IAB vendor list.
* Improve accessibility of Preferences screen.

### 1.73.0 (July 21, 2022)

**Features:**

* Query purposes for current language in order to always provide up-to-date translations.
* Add new events for language change (see [Events](/cmp/mobile-sdk/ios/reference/events) for more details).

{% hint style="info" %}
`updateSelectedLanguage` is now asynchronous.
{% endhint %}

**Fixes:**

* Disable neutral state when controlled value is legitimate interest.
* `setUserAgreeToAll` and `setUserDisagreeToAll` methods were not thread safe which could have caused crashes if called concurrently from multiple threads.

### 1.72.0 (June 27, 2022)

**Features:**

* Handle mutli-account for Cross-device feature (see [Share consents across devices](/cmp/mobile-sdk/share-consents-across-devices#multi-account) for more details).
* Allow to customize font family of title and description in notice and preferences screen (see [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#custom-font-family) for more details).
* Hide bulk action in purposes and vendors screens when there is only one item in the list.
* Allow to call `reset()` method while SDK is not initialized.

### 1.71.2 (June 16, 2022)

**Features:**

* Add an optional title field in notice (see[Customize the notice](/cmp/mobile-sdk/consent-notice/customize-the-notice#texts) for more details)
* Allow to customize font size, color and alignment of title and description in notice and preferences screen (see[Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#notice), [Customize the theme & UI](/cmp/mobile-sdk/consent-notice/customize-the-theme#preferences) for more details)

**Bug fixes:**

* Improve device storage disclosure screens transitions

### 1.70.0 (Mai 17, 2022)

**Features:**

* Handle custom background color (see [Customize the theme & UI](https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme#color) for more detail).

**Bug fixes:**

* Fix wrong background for Vendors detail screens.

### 1.69.0 (April 27, 2022)

**Features:**

* Update design for tablets.
* Improve accessibility for Vendor detail and Purpose detail screen.
* Add new languages support (Norwegian, Brazilian, Azerbaijani, Bengali, Filipino/Tagalog, Hebrew, Hindi, Indonesian, Macedonian, Swahili).

{% hint style="info" %}
New languages must be enabled from the Console once they are available.
{% endhint %}

**Bug fixes:**

* Disable neutral state for legitimate interest from the Vendor detail screen.
* Improve accessibility of preferences screen and purpose and vendor details screens

### 1.68.0 (April 4, 2022)

**Features:**

* tvOS: Display `Disagree` button on TV notice only when it is requested in configuration.

{% hint style="info" %}
For the moment, TV notice configurations generated by the console always display the `Disagree` button. To remove it, it has to be specified using custom json, as described [here](/cmp/mobile-sdk/consent-notice/customize-the-notice#remove-disagree-and-close-button).
{% endhint %}

* Support `removeEventListener` method.

**Bug fixes:**

* Italic HTML tags not taken into account for notice and preferences text.
* Fix "seconds" translation in device storage disclosure description in some languages.

### 1.67.1 (March 29, 2022)

**Bug fixes:**

* Purpose Categories with custom icons have wrong alignment.
* Purposes screen margin issue for iOS 15.4.
* Wrong focus on tvOS Vendor Details screen after back navigation.
* Some HTML tags not taken into account for Preferences (Purposes) text.

### 1.67.0 (March 21, 2022)

**Features:**

* Improve accessibility of User Information screen
* Add support for setUser method with authentication on Objective-C

**Bug fixes:**

* In some configurations, the IAB TCF Consent String was storing publisher restrictions with too many vendors.

### 1.66.0 (March 7, 2022)

**Features:**

* Improve accessibility for purposes and partners screens.

**Bug fixes:**

* Ignore invalid Vendor IDs from Publisher Restrictions instead of invalidating the complete list.

### 1.65.0 (February 10, 2022)

**Features:**

* Minor accessibility improvements on the Vendors screen.

**Bug fixes:**

* A few API Events were not being sent on the tvOS SDK.

### 1.64.0 (January 26, 2022)

**Features:**

* Support new IAB rules regarding timestamp: the timestamp stored in the GDPR consent string has now only day-level granularity. See <https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/pull/306/files#diff-99d4d9da93e17e584b04a239a04503a776d54503b0e2db52fc157b77fc950bbbR65>

### 1.63.1 (January 2022)

**Bug fixes:**

* Long vendor names were being cut off.
* Vendors were enabled after setting the switch to the neutral position and saving.

### 1.63.0 (January 2022)

**Features:**

* Improve accessibility for the notice and purposes screens

**Bug fixes:**

* Button state in the purpose details screen was always disabled when purpose required LI only.
* The status of some switches was not behaving properly on tvOS when the save button was pressed without making changes.
* Focus was not working properly on tvOS 15 after selecting a vendor or purpose.

### 1.62.0 (December 2021)

**Features:**

* Update fallback data for IAB TCF global vendors list.

### 1.61.0 (November 2021)

**Features:**

* Implemented `onShowPreferences` and `onHidePreferences` events. These events are triggered when the preferences screens are opened and closed respectively.

**Bug fixes:**

* `preferences.content.save` custom text was not being used in the Vendors screen.

### 1.60.3 (November 2021)

**Bug fixes:**

* The XCFramework was not including `dSYM` nor `BCSymbolMap` files.

### 1.60.2 (November 2021)

**Features:**

* Added Legitimate Interest in TCF Consent String by default once the notice has been shown.
* Added a new `initialize` method with a `DidomiInitializeParameters` parameters object. This is the recommended way to initialize the sdk, the previous methods are now deprecated. See the [reference](/cmp/mobile-sdk/android/reference/api#initialize) for more information.

### 1.59.0 (October 2021)

**Features:**

* Handle deny option as a cross in notice.

**Bug fixes:**

* Vendors with no consent or LI purposes were still in the UserStatus global disabled list after calling setUserAgreeToAll.

### 1.58.1 (September 2021)

**Features:**

* Apply publisher restrictions with "allow" type to non-IAB vendors as well.

**Fixes:**

* Vendors with no associated consent or legitimate interest purpose are now always returned in `UserStatus.vendors.global.enabled` list.

### 1.58.0 (September 2021)

**Features:**

* Display non-TCF purposes in disclosures
* Add salesforce vendor to global configuration
* Add a parameter to determine if user consent choice was set from Didomi UI or from a call to `Didomi.setUserStatus`.

**Bug fixes:**

* Hide blank device storage disclosure fields
* Fix an issue for device storage disclosures when no cookie info is available

### 1.57.1 (August 2021)

**Features:**

* Change the default focus on CTV notice according to CNIL guidelines.

### 1.56.2 (August 2021)

**Bug fixes:**

* Removed unused Xcode 11 code.

### 1.56.1 (July 2021)

**Bug fixes:**

* French translation for `required` was wrong.
* `getUserStatus().vendors.global` was not returning the right value.

### 1.56.0 (July 2021)

**Features:**

* Added new getUserStatus method.

**Bug fixes:**

* Fixed purpose details button theme.
* Ensure configuration is only loaded from Didomi on CTV SDK.

### 1.55.1 (June 2021)

**Bug fixes:**

* No event was being triggered when the user switched the toggles in the vendor or purpose details views.

**Features:**

* Added `getQueryStringForWebView` method.
* Migrated framework to Swift 5.0.

### 1.54.1 (June 2021)

**Bug fixes:**

* `getUserLegitimateInterestStatusForPurpose` and `getUserLegitimateInterestStatusForVendor`: return `.enabled` when status is not set (align status with Android).
* Dismiss preferences sub-screens before dismissing preferences screen.

### 1.54.0 (May 2021)

**Features:**

* Applied optimizations around the parsing of vendors information that should reduce the initialization time.

**Bug fixes:**

* Hide notice event was not being triggered when user gave/denied consent from the notice.

### 1.53.1 (May 2021)

**Bug fixes:**

* Manage languages with specific script code from device
* Handle vendor with no consent or LI in `getUserStatusForVendor`

### 1.53.0 (May 2021)

**Features:**

* Add new languages support, see <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-notice#supported-languages>
* Add missing methods:
  * `getUserLegitimateInterestStatusForPurpose`
  * `getUserLegitimateInterestStatusForVendor`
  * `getUserLegitimateInterestStatusForVendorAndRequiredPurposes`
  * `getUserStatusForVendor`

### 1.52.1 (May 2021)

**Features:**

* Improved header's layout and made bulk action sticky on the Vendors view.
* Handle setUserStatus with detailed purposes and vendors ids
* Send dedicated CTV source type to the privacy center on sync request

**Bug fixes:**

* Fix setUserConsentStatus result

### 1.51.0 (May 2021)

**Bug fixes:**

* Legitimate interest purposes were not staying as enabled when the user taps on `Disagree to all` in the Preferences view on tvOS.
* SDK was getting into a weird state when the IAB Config file was being removed by the OS.
* Vendors Bulk Action didn't have the right state if there is vendors without consent

### 1.50.1 (May 2021)

**Features:**

* Added support for `app.deploymentId`.

**Bug Fixes:**

* Preferences screen title was ignoring text from preferences property.
* SDK was getting into a weird state when cache directory was being removed by the OS.

### 1.49.3 (April 2021)

{% hint style="warning" %}
This version requires Xcode 12.
{% endhint %}

**Features:**

* Added support for tvOS.

### 1.48.2 (April 2021)

{% hint style="warning" %}
Please note that this release replaces the IDFA provided by AdSupport for a random custom identifier.
{% endhint %}

**Features:**

* Allow users to see and copy their information (Consent Token, User Id and SDK version)
* Remove usage of `IDFA`.
* Added support for Denied Consent Duration (`app.deniedConsentDuration`)

**Bug fixes:**

* The `Learn more` button was in the wrong position in the notice view.
* Some HTML tags were being ignored in the notice view.

### 1.47.0 (March 2021)

**Features:**

* Added support for purpose categories.
* Added support to sync user choices across devices.
* Added a global toggle in the purposes screen that allows to toggle all purposes at once.

**Bug fixes:**

* `getUserConsentStatusForVendorAndRequiredPurposes` was returning `false` when a vendor had only essential/required purposes.

### 1.46.0 (March 2021)

**Features:**

* Updated the behaviour of the `Disagree to all` buttons in the preferences screen to align with other platforms.
* Added support for the `denyAppliesToLI` feature in notice and preferences screen.

### 1.45.0 (March 2021)

**Features:**

* Added support for specifying consent expiration.

**Bug fixes:**

* Size of consent notice was wrong when displayed a second time.
* There was an error in the API Events' sampling calculation.

### 1.44.0 (February 2021)

**Features:**

* Added support to include Publisher Country Code into Consent String.

**Bug fixes:**

* UI event were being triggered before consent was saved.

### 1.43.0 (February 2021)

{% hint style="warning" %}

* If you were passing the `consent` and `legitimateInterest` parameters to the `setUserDisagreeToAll` method in your Swift code, it won't compile anymore. If you want to set the consent and legitimate interest status for all vendors and purposes you should use the `setUserStatus` method instead <https://developers.didomi.io/cmp/mobile-sdk/ios/reference#setuserstatus>.
* If you were directly calling `setUserDisagreeToAll` from Objective-C (`setUserDisagreeToAllWithConsent:legitimateInterest:`) you would need to use `setUserDisagreeToAll` instead which does not accept parameters. If you want to set the consent and legitimate interest status for all vendors and purposes you should use the setUserStatus method instead <https://developers.didomi.io/cmp/mobile-sdk/ios/reference#setuserstatus>.
* This release also makes private some views and view controllers classes. Currently this SDK is not designed to access these classes directly but only through the available methods which are documented in the references section <https://developers.didomi.io/cmp/mobile-sdk/ios/reference>.
  {% endhint %}

**Features:**

* Added ability to display "Disagree & Close" button on the notice (`notice.type = "optin"`).
* Added ability to display "Disagree & Close" button as primary (`notice.denyAsPrimary = true`).
* Added ability to display "Continue without agreeing" link on the notice (`notice.denyAsLink = true`).
* Added some UI updates on the notices.
* Added new method to set user status for all purposes and vendors `setUserStatus(purposesConsentStatus: Bool, purposesLIStatus: Bool, vendorsConsentStatus: Bool, vendorsLIStatus: Bool)`

### 1.42.0 (January 2021)

**Features:**

* Indicate platform and SDK version when downloading notice configuration.
* Added support for TCF v2.1.
* Send TCF and Additional Consent information in API events.

### 1.41.1 (December 2020)

**Bug fixes:**

* In some cases consent was not being properly kept after an update of the GVL.
* A translation in Croatian was not being displayed properly.

### 1.41.0 (December 2020)

**Features:**

* Added Device storage section in the vendor details view.
* Updated some texts from vendors and purposes.

**Bug fixes:**

* Custom initializer `hexString:alpha:` was being publicly exposed through an extension of the `UIColor` class which was causing conflicts for some clients that had the same implementation.

### 1.40.1 (December 2020)

{% hint style="warning" %}
Please notice that this release includes the ability to download the GVL (Global Vendor List) file. If you don't want the SDK initialization to wait for this step, set the `app.vendors.iab.requireUpdatedGVL` to false as explained here <https://developers.didomi.io/cmp/mobile-sdk/ios/setup#download-global-vendor-list-gvl>
{% endhint %}

**Features:**

* Essential/Required purposes section in the detailed view for each vendor.
* Download the GVL (Global Vendor List).
* Optimizations around Publisher Restrictions.

**Fixes:**

* Long purpose names were being cut-off.

### 1.39.0 (November 2020)

**Features:**

* Detailed additional data processing information
* Added `onError` method.

### 1.38.0 (October 2020)

**Features:**

* GVL update
* Remove TCFv1 storage keys when TCFv2 is enabled
* Improved responsiveness when saving consent

**Bug fixes:**

* Ensure that the legitimate interest status is correctly passed to Webviews in `getJavaScriptForWebView`

### 1.37.0 (October 2020)

**Features:**

* Support for Publisher Restrictions.

### 1.36.1 (September 2020)

**Bug fixes:**

* Fixed ratio issue with logo on popup notice.

### 1.36.0 (September 2020)

**Features:**

* Updated initialization process to stop requesting location when `gdprAppliesGlobally` is set to `true`.

### 1.35.1 (September 2020)

**Bug fixes:**

* App logo was not being displayed on the popup notice.
* Detailed view of essential purposes contained toggles.

### 1.35.0 (September 2020)

**Features:**

* When `user.ignoreConsentBefore` is set and if consent was collected from the user at a date earlier than user.ignoreConsentBefore, show the consent notice to recollect consent (irrespective of the consent status of the user).
* Improved the UI of the popup notice to force users to see all the content of the view before selecting any action.

**Bug fixes:**

* Close button was not very responsive on the purposes view.

### 1.34.0 (September 2020)

**Features:**

* Collect and send organization user ID in API events.

### 1.33.1 (September 2020)

**Bug fixes:**

* Vendors button was not responsive when text on popup notice was long enough to require scroll.

### 1.33.0 (September 2020)

**Features:**

* Disable TCF if it is disabled from the Console or if config file does not come from Didomi.

### 1.32.0 (August 2020)

**Features:**

* Updated IAB vendors list to 52.

### 1.31.1 (August 2020)

**Bug fixes:**

* Save button on purposes list view didn't have the right state when selections of Consent and Legitimate interest were opposite.

### 1.31.0 (August 2020)

**Features:**

* Added support for Google as a TCF vendor.

### 1.30.2 (July 2020)

**Bug fixes:**

* `getUserConsentStatusForVendorAndRequiredPurposes` was not returning the right status for `google` and other custom vendors.

### 1.30.1 (July 2020)

**Features:**

* Added `Show our vendors` button to the notice which allows users to navigate directly to the Vendors list view.
* Added `Additional Data Processing` section on Purposes list and Vendor Details views.

### 1.29.0 (July 2020)

**Features:**

* Ensure that consent is recollected when switching TCF version

**Bug fixes:**

* Ensure switch state is accurate on the list of vendors

### 1.28.0 (July 2020)

**Features:**

* Better support for dark mode in purpose and vendor detailed views
* IAB TCF label on TCF vendors in the list of vendors
* Notice configuration by ID

### 1.27.2 (July 2020)

**Bug fixes:**

* Minor fixes regarding TCFv2.
* Fixed broken custom text on the Vendors view.

### 1.27.0 (June 2020)

**Features:**

* `showPreferences` allows selecting which view should open (purposes or vendors)

### 1.26.0 (June 2020)

**Features:**

* IAB TCF v2 initial support

### 1.21.0 (June 2020)

**Features:**

* Use `os_log` for logging on iOS 10+.
* Allow setting minimum log level via `setLogLevel`.
* Changed the way Purpose details are displayed from expanding a cell to displaying a new view.

### 1.20.1 (May 2020)

**Bug fixes:**

* Banner notice was displaying the rounded top border without transparency.

### 1.18.1 (March 2020)

**Features:**

* Added support for `XCFramework` which means there is no need to use a different Pod (or binary) for newer versions of Xcode (since Xcode >= 11). Using this Pod/binary should be enough: `Didomi-XCFramework`.

### 1.17.1 (March 2020)

**Features:**

* Updated Global Vendor List to version 192.
* Improved the way in which optionals are handled.

### 1.16.5 (February 2020)

**Bug fixes:**

* Calling the `setupUI` method multiple times could have resulted in crashes.
* UI constraints were breaking in some cases when views were displayed behind an interstitial ad.
* Fixed a race condition when triggering API events which could have resulted in crashes.

### 1.16.4 (January 2020)

**Bug fixes:**

* UI improvements around the scroll bar and the scrolling animation on the Purposes screen when items are expanded/collapsed.

**Features:**

* Added `Didomi.notice.hide();` to the JavaScript code that gets returned by method `getJavaScriptForWebView`. This means that the notice view on the web app that's loaded on the native app will be hidden automatically when injecting the JavaScript code returned by this method.

### 1.16.0 (January 2020)

**Features:**

* Added Xcode 11.3 support.

### 1.15.4 (Dec 2019)

**Features:**

* Updated `getTranslatedText` method to get translated text from multiple sources <https://developers.didomi.io/cmp/mobile-sdk/reference-ios#gettranslatedtext>
* Created new method `updateSelectedLanguage` method that allows app developers to change the language of the Didomi SDK.
* Added the ability to pass a language code when calling the `initialize` method. This language code will be used to set the selected language.

{% hint style="warning" %}
Existing apps using this implementation of the `initialize` method in Objective-C:`Didomi *didomi = [Didomi shared];`\
`[didomi initializeWithApiKey:@"<Your API key>" localConfigurationPath:nil remoteConfigurationURL:nil providerId:nil disableDidomiRemoteConfig:NO];`

will have to add the `languageCode` parameter and set it to nil unless they want to set a language code:\
`Didomi *didomi = [Didomi shared];`\
`[didomi initializeWithApiKey:@"<Your API key>" localConfigurationPath:nil remoteConfigurationURL:nil providerId:nil disableDidomiRemoteConfig:NO languageCode:nil];`
{% endhint %}

**Bugs:**

* The `save` button in the purposes view was not being enabled property in some cases when the user had previously saved their preferences using an old list of purposes.

### 1.14.1 (Nov 2019)

**Features:**

* Added support for Xcode 11.2.
* Updated the way API events are sampled to be based on user ID rather than on a random number.

### 1.13.0 (Oct 2019)

**Features:**

* Introduced `ui.action` type for events sent to the API for tracking the interactions of the user with the consent UI. Actions added: `preferences.shownpurposes`, `preferences.shownvendors`, `preferences.purposechanged` and `preferences.vendorchanged`.

**Bug fixes:**

* The `IABConsent_SubjectToGDPR` key was not being set properly in the user defaults.

### 1.12.2 (Oct 2019)

**Bug fixes:**

* UI issue with the purpose switches keeping a stale state when the user toggled the switch and expanded the purpose description right after.

### 1.12.1 (Sep 2019)

**Features:**

* Added support for Xcode 11 and bitcode.

**Bug fixes:**

* Build was being created using the Debug configuration.
* Some views were not displaying correctly on iOS 13 when dark mode was enabled.
* In some cases getting the device location could cause a long delay.
* Objective-C projects were not compiling correctly under certain configurations.
* Objective-C projects were not compiling correctly when running on simulator on Xcode 10.2 and 10.3.

### 1.10.1 (Sep 2019)

**Features:**

* Improved internal implementation of the SDK to ease the creation of custom views.

### 1.9.6 (Jul 2019)

**Bug fixes:**

* Some mapping keys related to the getText and getTranslatedText methods were not matching the JSON properties of the preferences and notice properties.

### 1.9.5 (Jul 2019)

**Features:**

* Updated IAB vendors list to 155.
* Added the ability to provide translatable texts through the `texts` property in the `didomi_config.json` file that can be used when creating a custom notice.

### 1.**9**.4 (Jul 2019)

**Features:**

* Added the ability to block/disable the `Agree to all` and `Disable to all` buttons by providing the `preferences.disableButtonsUntilScroll` flag and setting it to `true`.

### **1.9.3 (Jun 2019)**

**Bug fixes:**

* Event `HideNoticeEvent` was not triggered as required in some cases.

### **1.9.2 (Jun 2019)**

**Bug fixes:**

* The Console generates custom purpose IDs within `[A-Za-z0-9-_]` and SDKs only allowed `[a-z0-9-_]`

### **1.9.1 (May 2019)**

**Features:**

* Added logs to indicate app developers when methods that require the Didomi SDK to be ready are called before that.

### **1.8.1 (May 2019)**

**Features:**

* Update IAB vendors list (version 146)

### **1.8.0 (May 2019)**

**Features:**

* [Share consent status with WebViews](/cmp/mobile-sdk/share-consent-with-webviews)

### **1.7.0 (Apr 2019)**

**Features:**

* Add the possibility to get the configuration remotely from the Didomi console

{% hint style="warning" %}
If you are coming from a previous version and want to enable the remote Didomi configuration created from the console, please add `disableDidomiRemoteConfig: false` as a new parameter in your `initialize` function. [See documentation](/cmp/mobile-sdk/ios/setup#initialize-the-sdk).
{% endhint %}

### 1.6.0 (Apr 2019)

Features:

* Added pod `Didomi-xcode10.2` which supports Xcode 10.2.

Bug fixes:

* Exposed missing properties of `Purpose` and `Vendor` classes.

### 1.5.1 (Apr 2019)

**Features:**

* [Add events to track user interaction](/cmp/mobile-sdk/android/reference/api#addeventlistener)

### 1.5.0 (Apr 2019)

**Features:**

* Exposed the following methods: `getRequiredPurposes`, `getRequiredVendors`, `getEnabledPurposes`, `getEnabledPurposeIds`, `getDisabledPurposes`, `getDisabledPurposeIds`, `getEnabledVendors`, `getEnabledVendorIds`, `getDisabledVendors`, `getDisabledVendorIds`, `getPurpose` and `getVendor`.
* Add Russian and Ukrainian languages

### 1.4.5 (Mar 2019)

**Bug fixes:**

* Preferences popup was being displayed on each visit when `notice.enable` was set to `false` and `preferences.showWhenConsentIsMissing` to `true`.

### 1.4.3 (Feb 2019)

**Features:**

* Updated master config file adding countries, translations, purposes and partners.
* Exposing `shouldConsentBeCollected` method used to allow developers to check if consent should be collected or not.

**Bug fixes:**

* Items on Purposes and Vendors list were not expanding when clicking right on the expand arrow.
* SDK had to wait for the country code to get initialised which in some cases could result in the app having to wait for it before starting.
* Fix translation for "View privacy policy" on the Vendors view

### 1.4.1 (Feb 2019)

**Bug fixes:**

* Purposes description was not being displayed on iPad running iOS 9.3.
* Fixed strong reference cycles.

### 1.4.0 (Jan 2019)

{% hint style="danger" %}
**Breaking change**

This release modifies how we treat the ID of your custom vendors. If you are getting the user consent status with an API function like `getUserConsentStatusForVendorAndRequiredPurposes("vendor-id")`, you need to update your code to prefix the vendor ID with `c:`. Your function call now becomes: `getUserConsentStatusForVendorAndRequiredPurposes("c:vendor-id")`.

This change will also trigger consent re-collection for your users.
{% endhint %}

**Features:**

* Customize buttons and links color <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme>.
* Details about purposes and vendors by expanding the list items.
* Purposes are listed under each vendor item on the Vendors screen when they are expanded.
* Customize logo on the Purposes view <https://developers.didomi.io/cmp/mobile-sdk/getting-started#configure-your-app-name-and-logo>.
* Bypass notice and open Preferences pop-in directly <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#display-when-consent-is-missing>.
* Customize purposes order and icons by providing purpose categories <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#purposes>.
* Prevent the Preferences pop-in from being closed when consent is missing <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#prevent-the-popup-from-being-closed-when-consent-is-missing>.
* Remove "Number of Partners" on the Preferences view.
* Update content translations.

**Bug fixes:**

* The "Disagree to all" button did not use the same text and background color as the "Agree to all" button.
* Inline style of HTML content was being overridden on the Preferences pop-in.
* The "Save" button was present but disabled even though all purposes were set to unknown.
* Purposes were not being properly updated when categories were being used.
* The "c:" prefix was missing from custom vendors IDs. **Important**: this could be a breaking change since on the previous version the "c:" prefix was not required before each custom vendor ID.
* Purposes were not sorted properly on the vendors and purposes views.

### 1.3.2 (Jan 2019)

#### Features:

* Supports the 24 European languages
* Number of days before recollecting consent option in the configuration tag
* Updates on helpers to ease testability

### 1.3.1 (Dec 2018)

**Features:**

* Added the ability to load a remote configuration file so app developers can customize how the SDK is displayed to users

**Bug fixes:**

* Fixed potential issue around macros and the way they get replaced in the content

### 1.2.1 (Dec 2018)

**Bug fixes:**

* Fixed logic around `showPreferences` and `forceShowNotice` methods so app does not crash after consent has been given
* Fixed the way notices display long content by enabling scroll when required
* Correctly load purposes and vendors statuses in the Preferences popup after consent has been given
* Show the Save button when the Preferences popup is open after consent has been given

### 1.2.0 (Nov 2018)

**Features:**

* Custom purposes
* Map custom vendor to IAB ID
* Expose `getUserConsentStatusForPurpose` and `getUserConsentStatusForVendorAndRequiredPurposes` in the public API
* Ability to customize texts in the preferences popup

### 1.1.3 (Nov 2018)

**Bug fixes:**

* Minor UI fixes.
* Updated default notice text.

### 1.1.2 (Nov 2018)

**Bug fixes:**

* Minor UI fixes.

### 1.1.1 (Nov 2018)

**Bug fixes:**

* Exposed additional methods.

### 1.1.0 (Nov 2018)

**Features:**

* Added support for Xcode 9
* Added support for Objective-C

### 1.0.0 (Nov 2018)

Initial version.


# Unity

This section will guide you through the required steps to setup the Didomi SDK for your Unity applications on mobile (Android and iOS) and TV (Android TV and tvOS) devices.

We are assuming that you have a Didomi account and an API key. If not, please go to our [website](https://www.didomi.io) and sign up for an account.

* [Setup](/cmp/mobile-sdk/unity-sdk/setup): Import the Unity plugin and configure it
* [Third-party SDKs](/cmp/mobile-sdk/third-party-sdks): How to pass consent to third-party SDKs
* [Reference](/cmp/mobile-sdk/unity-sdk/reference): API reference of the Unity SDK
* [Versions](/cmp/mobile-sdk/unity-sdk/versions): List of published versions


# Setup

Follow these steps to setup the Didomi Unity SDK:

* [Requirements](#add-the-sdk-to-your-project)
* ​[Add the SDK to your project​](#add-the-sdk-to-your-project)
* [​Initialize the SDK​](#initialize-the-sdk)
* ​[Setup the Didomi SDK UI​](#setup-the-sdk-ui)
* [​Configure the SDK​](#configure-the-sdk)

## Requirements <a href="#add-the-sdk-to-your-project" id="add-the-sdk-to-your-project"></a>

The Didomi Unity SDK currently supports Unity Version 2021.3.34f1 or newer.

For Android build, targeting Android SDK version 34 (Android 14) or newer is required (version required to publish apps on Google Play Store). When using Unity versions prior to 2022.3.38f1, this may require updating JDK and Gradle versions in Unity settings.

## Add the SDK to your project <a href="#add-the-sdk-to-your-project" id="add-the-sdk-to-your-project"></a>

Download the latest version of the `Didomi.unitypackage` from [our releases page on Github](https://github.com/didomi/unity/releases).

You can then import the package `Didomi.unitypackage` into your project:

![Install Didomi Unity SDK plugin](/files/-M8XTLkhJiMLP2TtOP3I)

{% hint style="info" %}
In case of errors after adding the SDK or at build time, check if issue is referenced in the [Troubleshooting](/cmp/mobile-sdk/unity-sdk/troubleshooting) section.
{% endhint %}

## Initialize the SDK

Once our SDK has been added to your project, you need to initialize it. The initialization process will prepare the SDK for interactions with the user and your application. It is important to launch the SDK initialization as soon as possible.

In your main entry code, call the `Initialize` method and pass your API key, and optionally your notice Id:

{% tabs %}
{% tab title="C#" %}

```swift
private void InitDidomi()
{
   // Setup a listener to know when the SDK is ready
   Didomi.GetInstance().OnReady( () => {
       // The Didomi SDK is ready to go, you can call other functions on the SDK
   });
   
   // Initialize the SDK
   Didomi.GetInstance().Initialize(
      new DidomiInitializeParameters(
         apiKey: "<Your API key>",
         noticeId: "<Your notice Id>"
   ));
}
```

{% endtab %}
{% endtabs %}

Keep in mind that the SDK initialization is an asynchronous process so you must avoid interacting with the `Didomi` object until it is actually ready to handle your requests. Use the `OnReady` event in C# to register a listener for the ready event.

Take a look at our [sample app](https://github.com/didomi/unity#sample-app) to see how the setup is done.

## Add a Proguard rule for Didomi (Android-only)

The Didomi SDK uses GSON to generate JSON-encoded API events sent back to the Didomi platform for analytics. We use `@SerializedName` to indicate the name of the JSON properties and ensure that they are correctly encoded into JSON.

In certain configurations, the host app configuration for Proguard will obfuscate some key SDK classes and break the API events sent to Didomi. This translates into incorrect analytics for the app on Android and is hard to catch as it usually only becomes apparent once in production (as debug/test builds usually do not run through Proguard).

If you are using Proguard in your Unity project and to ensure that this does not happen, add the following rule to your Proguard file:

```
-keep class io.didomi.sdk.apiEvents.** { *; })
```

If you want to check whether that issue applies to you, you can monitor the events sent by the Didomi SDK in your production build.

Correct events should look like:

![](/files/-M0JktidRYGT338ttgYl)

Notice how the `parameters` and `user.token` properties have a lot of data.

Incorrect events will look like this:

![](/files/-M0JlC_LGSgC7RoRu3_8)

Notice how the `parameters` and `user.token` properties are empty.

## Setup the SDK UI

{% hint style="info" %}
Note: the `SetupUI` method should be called only from your contexts where the application starts.

You do not need to call `OnReady`, `IsReady` or `ShouldConsentBeCollected` before calling `SetupUI` because they are called internally. Therefore, by calling this method the consent notice will be displayed if it is required and only once the SDK is ready.
{% endhint %}

Call the `SetupUI` function of the SDK in your context where the application starts:

{% tabs %}
{% tab title="C#" %}

```swift
public class AppStartup : MonoBehaviour 
{ 
    void Awake () 
    {
        Didomi.GetInstance().SetupUI();
    }
}
```

{% endtab %}
{% endtabs %}

### Deep links

If you are using deep links or have multiple main user interfaces in your Unity app, make sure that the `SetupUI` function is called on every context that the user can launch the app on.\
\
This will ensure that consent is always collected as needed and there is no path where the user can launch the app without consent being collected. If `SetupUI` is missing in some entry points, you will see lower consent rates as users will be using the app without giving consent.

## Configure the SDK

We support three options for configuring the UI and the behavior of the SDK:

* [Didomi Console](#from-the-console-recommended): the SDK is configured remotely from the Didomi Console
* [Local file](#local-file): the SDK is configured from a `didomi_config.json` file embedded in your app package
* [Remote file](#remote-file): the SDK is configured from a remote `didomi_config.json` file

### From the Console (Recommended)

You can configure the consent notice in your app by creating a notice in your Didomi Console. It will automatically be linked to your app through your API Key and, optionally, your app package name or notice id. You can access the Didomi console [here](http://console.didomi.io).

In order to enable this option, make sure to pass the `disableDidomiRemoteConfig` parameter as `false` when calling the initialize method as shown below.

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().Initialize(
       apiKey: "<Your API key>",
       localConfigurationPath: null,
       remoteConfigurationURL: null,
       providerId: null,
       disableDidomiRemoteConfig: false,
       languageCode: null,
       noticeId: "<Your notice Id>");
```

{% endtab %}
{% endtabs %}

This is the default behavior when using the recommended parameter `DidomiInitializeParameters`:

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().Initialize(
   new DidomiInitializeParameters(
      apiKey: "<Your API key>",
      noticeId: "<Your notice Id>"
));
```

{% endtab %}
{% endtabs %}

The SDK will automatically use the remote configuration hosted by Didomi and cache it locally. The cached version is refreshed every 60 minutes.\
If there is no connection available to download the remote configuration and no locally cached version, the SDK will try to use a local `didomi_config.json` configuration file as a fallback. See the Local option below for more information on how to configure the SDK through a local configuration file.

### Local file (Deprecated)

{% hint style="danger" %}
Using a local file automatically disables the TCF integration.\
If your app uses the TCF, you must use a configuration from the Didomi Console.
{% endhint %}

{% hint style="warning" %}
Using a local file will prevent you to support multiple regulations.
{% endhint %}

With this option, you create your own SDK configuration file and embed it in your app package.

The SDK behavior is configured in a `didomi_config.json` file that must be placed in the `Assets/DidomiConfig` folder of your Unity project.

You can create a file with the following content to get started:

{% tabs %}
{% tab title="didomi\_config.json" %}

```javascript
{
    "app": {
        "name": "My App Name",
        "privacyPolicyURL": "http://www.website.com/privacy",
        "vendors": {
            "iab": {
                "all": true
            }
        },
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    }
}
```

{% endtab %}
{% endtabs %}

To be able set local configuration file for Didomi, you must create a `DidomiConfig` folder under the `Assets` folder of your Unity Project. Put your `didomi_config.json` file in the `Assets/DidomiConfig` folder.

Creating the `DidomiConfig` folder is **mandatory** for local configuration files as the configuration file must be moved to the correct directories when the Android and iOS projects are being generated.\
On the post process of the Unity project, the Didomi Plugin moves the files from `Assets/DidomiConfig` to the `assets/` folder of the Android apps and to the `Data/Resources` folder of iOS apps. For iOS projects, the configuration files will also be added to Copy Bundle Resources.

![DidomiConfig Folder for local configuration files.](/files/-M8bjmLKyuWx4D1FkHdv)

You also need to disable loading the remote configuration to ensure that only the local file is loaded and that no HTTP request is sent. Update your [`initialize`](https://developers.didomi.io/cmp/mobile-sdk/unity-sdk/reference#initialize) call to set the `disableDidomiRemoteConfig` parameter to `true`:

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().Initialize(
   new DidomiInitializeParameters(
       apiKey: "<Your API key>",
       disableDidomiRemoteConfig: true
));
```

{% endtab %}
{% endtabs %}

Your SDK is now setup. [Read the Getting started section](/cmp/mobile-sdk/consent-notice/getting-started) of our Mobile SDKs to learn more about how to configure it to match your app UI and requirements.

### Remote file

{% hint style="info" %}
Enabling this option will prevent the configuration from being loaded from the Didomi Console.
{% endhint %}

You can provide a remote URL for the SDK to download the `didomi_config.json` configuration file from. That allows you to update the SDK configuration without having to re-publish you mobile application.

When that configuration is enabled, the SDK will automatically use the remote configuration and cache it locally. The cached version is refreshed every 60 minutes. If there is no connection available to download the remote file and no locally cached version, the SDK will try to use the local `didomi_config.json` (provided in the app bundle) as a fallback.

To enable that option, change your call to [initialize ](https://developers.didomi.io/cmp/mobile-sdk/unity-sdk/reference#initialize)to provide the remote file URL:

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().Initialize(
   new DidomiInitializeParameters(
       apiKey: "<Your API key>",
       remoteConfigurationURL: "http://www.website.com/didomi_config.json",
       disableDidomiRemoteConfig: true
));
```

{% endtab %}
{% endtabs %}

Also see the [reference documentation of the initialize](/cmp/mobile-sdk/unity-sdk/reference#initialize) function for more information.


# Reference

This section is a comprehensive reference of the methods and events exposed by the Unity SDK that you can leverage in your application.

Always use `Didomi.GetInstance()` to get a reference to the Didomi SDK. Also make sure to always call the SDK after it is fully initialized (see [OnReady](https://developers.didomi.io/cmp/mobile-sdk/unity-sdk/reference#onready))

## AddEventListener

Add an event listener to catch events triggered by the SDK. Events listeners allow you to react to different events of interest. This function is safe to call before the `Ready` event has been triggered.

{% hint style="warning" %}
At the moment, on iOS, only one event listener is supported at the same time. If additional callbacks are required, they should be appended to the event handlers as in the example below.
{% endhint %}

**Requires SDK to be initialized**

No.

**Parameters**

| Name          | Type                  | Description                                                                                                                  |
| ------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| eventListener | `DidomiEventListener` | The event listener. An instance or a subclass of `DidomiEventListener`. Contains handlers for the different possible events. |

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

<pre class="language-java"><code class="lang-java">   
    private void RegisterEventHandlers()
    {
        DidomiEventListener eventListener = new DidomiEventListener();
        eventListener.ConsentChanged += EventListener_ConsentChanged;
        eventListener.Ready += EventListener_Ready;
        eventListener.ShowNotice += EventListener_ShowNotice;
        eventListener.HideNotice += EventListener_HideNotice;
        eventListener.NoticeClickAgree += EventListener_NoticeClickAgree;
        eventListener.NoticeClickMoreInfo += EventListener_NoticeClickMoreInfo;
        eventListener.NoticeClickViewSPIPurposes += EventListener_NoticeClickViewSPIPurposes;
        eventListener.PreferencesClickAgreeToAll += EventListener_PreferencesClickAgreeToAll;
        eventListener.PreferencesClickDisagreeToAll += EventListener_PreferencesClickDisagreeToAll;
        eventListener.PreferencesClickViewVendors += EventListener_PreferencesClickViewVendors;
        eventListener.PreferencesClickViewSPIPurposes += EventListener_PreferencesClickViewSPIPurposes;
        eventListener.PreferencesClickSaveChoices += EventListener_PreferencesClickSaveChoices;
        eventListener.PreferencesClickPurposeAgree += EventListener_PreferencesClickPurposeAgree;
        eventListener.PreferencesClickPurposeDisagree += EventListener_PreferencesClickPurposeDisagree;
        eventListener.PreferencesClickCategoryAgree += EventListener_PreferencesClickCategoryAgree;
        eventListener.PreferencesClickCategoryDisagree += EventListener_PreferencesClickCategoryDisagree;
        eventListener.PreferencesClickSPIPurposeAgree += EventListener_PreferencesClickSPIPurposeAgree;
        eventListener.PreferencesClickSPIPurposeDisagree += EventListener_PreferencesClickSPIPurposeDisagree;
        eventListener.PreferencesClickSPICategoryAgree += EventListener_PreferencesClickSPICategoryAgree;
        eventListener.PreferencesClickSPICategoryDisagree += EventListener_PreferencesClickSPICategoryDisagree;
        eventListener.PreferencesClickSPIPurposeSaveChoices += EventListener_PreferencesClickSPIPurposeSaveChoices;
        eventListener.PreferencesClickVendorAgree += EventListener_PreferencesClickVendorAgree;
        eventListener.PreferencesClickVendorDisagree += EventListener_PreferencesClickVendorDisagree;
        eventListener.PreferencesClickVendorSaveChoices += EventListener_PreferencesClickVendorSaveChoices;
        eventListener.HidePreferences += EventListener_HidePreferences;
        eventListener.ShowPreferences += EventListener_ShowPreferences;
        eventListener.SyncReady += EventListener_SyncReady;
<strong>        eventListener.SyncDone += EventListener_SyncDone;
</strong>        eventListener.SyncError += EventListener_SyncError;
        eventListener.LanguageUpdated += EventListener_LanguageUpdated;
        eventListener.LanguageUpdateFailed += EventListener_LanguageUpdateFailed;

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

    private void EventListener_ConsentChanged(object sender, ConsentChangedEvent e)
    {
        // The consent status of the user has changed
    }
    
    private void EventListener_Ready(object sender, ReadyEvent e)
    {
        // The Didomi SDK is ready
    }

    private void EventListener_ShowNotice(object sender, ShowNoticeEvent e)
    {
        // The notice is being shown or needs to be shown
    }
    
   private void EventListener_HideNotice(object sender, HideNoticeEvent e)
    {
        // The notice is being hidden
    }
    
    private void EventListener_NoticeClickAgree(object sender, NoticeClickAgreeEvent e)
    {
        // Click on agree on notice
    }

    private void EventListener_NoticeClickMoreInfo(object sender, NoticeClickMoreInfoEvent e)
    {
        // Click on learn more on notice
    }
    
    private void EventListener_NoticeClickViewSPIPurposes(object sender, NoticeClickViewSPIPurposesEvent e)
    {
        // Click on "Limit the use of my Sensitive Personal Information" on notice
    }
    
    private void EventListener_PreferencesClickAgreeToAll(object sender, PreferencesClickAgreeToAllEvent e)
    {
        // Click on agree to all on preferences popup
    }
    
    private void EventListener_PreferencesClickDisagreeToAll(object sender, PreferencesClickDisagreeToAllEvent e)
    {
        // Click on disagree to all on preferences popup
    }
  
    private void EventListener_PreferencesClickViewSPIPurposes(object sender, PreferencesClickViewSPIPurposesEvent e)
    {
        // Click on "Limit the use of my Sensitive Personal Information" on preferences screen
    }
      
    private void EventListener_PreferencesClickViewVendors(object sender, PreferencesClickViewVendorsEvent e)
    {
        // Click view vendors on purposes view on preferences popup
    }
    
    private void EventListener_PreferencesClickSaveChoices(object sender, PreferencesClickSaveChoicesEvent e)
    {
        // Click on save on the purposes view on preferences popup
    }
    
    private void EventListener_PreferencesClickPurposeAgree(object sender, PreferencesClickPurposeAgreeEvent e)
    {
        // Click on agree to a purpose on preferences popup
    }
    
    private void EventListener_PreferencesClickPurposeDisagree(object sender, PreferencesClickPurposeDisagreeEvent e)
    {
        // Click on disagree to a purpose on preferences popup
    }
    
    private void EventListener_PreferencesClickCategoryAgree(object sender, PreferencesClickCategoryAgreeEvent e)
    {
        // Click on agree to a purposes category on preferences popup
    }
    
    private void EventListener_PreferencesClickCategoryDisagree(object sender, PreferencesClickCategoryDisagreeEvent e)
    {
        // Click on disagree to a purposes category on preferences popup
    }
    
    private void EventListener_PreferencesClickSPIPurposeAgree(object sender, PreferencesClickSPIPurposeAgreeEvent e)
    {
        // Click on agree to a purpose on sensitive personal information screen
    }
    
    private void EventListener_PreferencesClickSPIPurposeDisagree(object sender, PreferencesClickSPIPurposeDisagreeEvent e)
    {
        // Click on disagree to a purpose on sensitive personal information screen
    }
    
    private void EventListener_PreferencesClickSPICategoryAgree(object sender, PreferencesClickSPICategoryAgreeEvent e)
    {
        // Click on agree to a purposes category on sensitive personal information screen
    }
    
    private void EventListener_PreferencesClickCategoryDisagree(object sender, PreferencesClickSPICategoryDisagreeEvent e)
    {
        // Click on disagree to a purposes category on sensitive personal information screen
    }
    
    private void EventListener_PreferencesClickSPIPurposeSaveChoices(object sender, PreferencesClickSPIPurposeSaveChoicesEvent e)
    {
        // Click on save on the sensitive personal information screen
    }

    private void EventListener_PreferencesClickVendorAgree(object sender, PreferencesClickVendorAgreeEvent e)
    {
        // Click on agree to a vendor on preferences popup
    }

    private void EventListener_PreferencesClickVendorDisagree(object sender, PreferencesClickVendorDisagreeEvent e)
    {
        // Click on disagree to a vendor on preferences popup
    }
    
    private void EventListener_PreferencesClickVendorSaveChoices(object sender, PreferencesClickVendorSaveChoicesEvent e)
    {
        // Click on save on the vendors view on preferences popup
    }
    
    private void EventListener_ShowPreferences(object sender, ShowPreferencesEvent e)
    {
        // The preferences screen is being shown
    }
    
    private void EventListener_HidePreferences(object sender, HidePreferencesEvent e)
    {
        // The preferences screen is being hidden
    }
    
    private void EventListener_SyncReady(object sender, SyncReadyEvent e)
    {
        // Synchronization process is complete
    }
    
    private void EventListener_SyncDone(object sender, SyncDoneEvent e)
    {
        // Synchronization was done successfully
    }
    
    private void EventListener_SyncError(object sender, SyncErrorEvent e)
    {
        // An error occurred during synchronization
    }
    
    private void EventListener_LanguageUpdated(object sender, LanguageUpdatedEvent e)
    {
        // Language update was completed
    }
    
    private void EventListener_LanguageUpdateFailed(object sender, LanguageUpdateFailedEvent e)
    {
        // Language update was not completed
    }

    
</code></pre>

{% endtab %}
{% endtabs %}

**Event types**

The following events are supported by the Didomi SDK:

| Event                                      | Description                                                                                                                                                                                                  |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ConsentChangedEvent                        | When a consent is given or withdrawn by the user. Only triggered when the consent status actually changes (ie if the user saves consents without adding/removing any consent then this does not get called). |
| HideNoticeEvent                            | When the consent notice is hidden. If you have disabled our default consent notice to replace it with your own, you need to hide your custom notice when this event gets triggered.                          |
| ShowNoticeEvent                            | When the consent notice gets displayed. If you have disabled our default consent notices to replace them with your own, you need to show your custom notice when this event gets triggered.                  |
| NoticeClickAgreeEvent                      | When user clicks on agree on the notice                                                                                                                                                                      |
| NoticeClickMoreInfoEvent                   | When user clicks on learn more on the notice                                                                                                                                                                 |
| NoticeClickViewSPIPurposesEvent            | When user clicks on "Limit the use of my personal information" on the notice                                                                                                                                 |
| PreferencesClickAgreeToAllEvent            | When user clicks on agree to all on the preferences popup                                                                                                                                                    |
| PreferencesClickDisagreeToAllEvent         | When user clicks on disagree to all on the preferences popup                                                                                                                                                 |
| PreferencesClickPurposeAgreeEvent          | When user agrees to a purpose on the preferences popup. (`purposeId` provided as a parameter)                                                                                                                |
| PreferencesClickPurposeDisagreeEvent       | When user disagrees to a purpose on the preferences popup. (`purposeId` provided as a parameter)                                                                                                             |
| PreferencesClickCategoryAgreeEvent         | When user agrees to a purposes category on the preferences popup. (`categoryId` provided as a parameter)                                                                                                     |
| PreferencesClickCategoryDisagreeEvent      | When user disagrees to a purposes category on the preferences popup. (`categoryId` provided as a parameter)                                                                                                  |
| PreferencesClickViewSPIPurposesEvent       | When user clicks on "Limit the use of my personal information" on the preferences popup                                                                                                                      |
| PreferencesClickViewVendorsEvent           | When user clicks on view vendors on the preferences popup                                                                                                                                                    |
| PreferencesClickSaveChoicesEvent           | When user saves his choice on the preferences popup                                                                                                                                                          |
| PreferencesClickSPIPurposeAgreeEvent       | When user agrees to a purpose on the sensitive personal information screen. (`purposeId` provided as a parameter)                                                                                            |
| PreferencesClickSPIPurposeDisagreeEvent    | When user disagrees to a purpose on the sensitive personal information screen. (`purposeId` provided as a parameter)                                                                                         |
| PreferencesClickSPICategoryAgreeEvent      | When user agrees to a purposes category on the sensitive personal information screen. (`categoryId` provided as a parameter)                                                                                 |
| PreferencesClickSPICategoryDisagreeEvent   | When user disagrees to a purposes category on the sensitive personal information screen. (`categoryId` provided as a parameter)                                                                              |
| PreferencesClickSPIPurposeSaveChoicesEvent | When user saves his choice on the sensitive personal information screen                                                                                                                                      |
| PreferencesClickVendorAgreeEvent           | When user agrees to a vendor on the preferences popup. (`vendorId` provided as a parameter)                                                                                                                  |
| PreferencesClickVendorDisagreeEvent        | When user disagrees to a vendor on the preferences popup. (`vendorId` provided as a parameter)                                                                                                               |
| PreferencesClickVendorSaveChoicesEvent     | When user saves his choice on the vendors view on the preferences popup                                                                                                                                      |
| HidePreferencesEvent                       | When preferences screen is hidden                                                                                                                                                                            |
| ShowPreferencesEvent                       | When preferences screen is shown                                                                                                                                                                             |
| SyncReadyEvent                             | <p>When synchronization is complete.</p><p>Provides the methods <code>GetOrganizationUserId</code>, <code>IsStatusApplied</code> and <code>SyncAcknowledged</code> (see below)</p>                           |
| `SyncReadyEvent.OrganizationUserId`        | `organizationUserId` of the user that was synchronized                                                                                                                                                       |
| `SyncReadyEvent.IsStatusApplied`           | `bool` indicating whether the user status was applied                                                                                                                                                        |
| `SyncReadyEvent.SyncAcknowledged`          | Function that triggers a `sync.acknowledged` API event when called. It returns `true` if the API event was sent successfully.                                                                                |
| SyncDoneEvent                              | <p><strong>Deprecated, use <code>SyncReady</code> instead.</strong></p><p>When synchronization is complete (synchronized <code>organizationUserId</code> provided as parameter)</p>                          |
| SyncErrorEvent                             | When synchronization encountered an error (`errorMessage` provided as parameter)                                                                                                                             |
| LanguageUpdatedEvent                       | When selected language update was completed (selected `languageCode` provided as parameter)                                                                                                                  |
| LanguageUpdateFailedEvent                  | When language selection update was not able to complete (`reason` provided as parameter)                                                                                                                     |

## addVendorStatusListener <a href="#addvendorstatuslistener" id="addvendorstatuslistener"></a>

Listen for changes on the user status linked to a specific vendor.

{% hint style="warning" %}
At the moment, on iOS, only one listener per vendor is supported at the same time. If additional callbacks are required, they should be appended to the vendor status listener handler, as in the example below.
{% endhint %}

**Requires SDK to be initialized**

No.

**Parameters**

| Name                 | Type                         | Description                                                                                                                                                                                                                           |
| -------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendorId             | `string`                     | <p>The ID of the vendor for which we want to start listening for changes.</p><p>This ID should be the ID provided by Didomi, which doesn't contain prefixes.</p>                                                                      |
| vendorStatusListener | `DidomiVendorStatusListener` | <p>An instance or a subclass of <code>DidomiVendorStatusListener</code>. Contains a handler called when vendor status is changed.</p><p>When this callback is executed, the status linked to the specified vendor will be passed.</p> |

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

<pre class="language-csharp"><code class="lang-csharp"><strong>private void RegisterVendorStatusListener()
</strong><strong>{
</strong>    DidomiVendorStatusListener vendorStatusListener = new DidomiVendorStatusListener();
    vendorStatusListener.VendorStatusChanged += VendorStatusListener_VendorStatusChanged;
    Didomi.GetInstance().AddVendorStatusListener("vendor1", vendorStatusListener);
}

private void VendorStatusListener_VendorStatusChanged(object sender, CurrentUserStatus.VendorStatus status)
{
    Debug.Log(status.Id + "status has changed: " + status.Enabled);
}
</code></pre>

{% endtab %}
{% endtabs %}

## removeVendorStatusListener <a href="#removevendorstatuslistener" id="removevendorstatuslistener"></a>

Stop listening for changes on the user status linked to a specific vendor.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type     | Description                                                                                                                                                     |
| -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendorId | `string` | <p>The ID of the vendor for which we want to stop listening for changes.</p><p>This ID should be the ID provided by Didomi, which doesn't contain prefixes.</p> |

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```csharp
Didomi.GetInstance().RemoveVendorStatusListener("vendor1");
```

{% endtab %}
{% endtabs %}

## DisableMockUI

Disable or enable the mock UI when testing in Unity Editor.

{% hint style="warning" %}
**Android and iOS platform builds**

This function has no effect for iOS or Android platform builds. It can safely be called in all environments and will only impact the Unity Editor.
{% endhint %}

**Requires SDK to be initialized**

No

**Parameters**

| Name    | Type      | Description                   |
| ------- | --------- | ----------------------------- |
| disable | `boolean` | `true` to disable the mock UI |

**Returns**

No return value

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().DisableMockUI(true);
```

{% endtab %}
{% endtabs %}

## GetJavaScriptForWebView

Get JavaScript to embed into a WebView to pass the consent status from the app to the Didomi Web SDK embedded into the WebView.

Inject the returned tag into a WebView with `evaluateJavaScript`.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type     | Description                           |
| -------- | ------------------------------------- |
| `string` | JavaScript code to embed in a WebView |

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().GetJavaScriptForWebView();
```

{% endtab %}
{% endtabs %}

## GetPurpose

Get a purpose based on its ID.

{% hint style="warning" %}
**Not available for IOS platform builds**

This function is only exposed to Unity Android platform builds. It cannot be called from Unity IOS platform builds.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name      | Type     | Description                       |
| --------- | -------- | --------------------------------- |
| purposeId | `string` | ID of the purpose we want to get. |

**Returns**

| Type      | Description                                                              |
| --------- | ------------------------------------------------------------------------ |
| `Purpose` | A `Purpose` with ID `purposeId` found in the array of required purposes. |

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().GetPurpose("purpose-id");
```

{% endtab %}
{% endtabs %}

## GetRequiredPurposes

Get the list of purpose that are required (automatically determined from the list of required vendors).

{% hint style="warning" %}
**Not available for IOS platform builds**

This function is only exposed to Unity Android platform builds. It cannot be called from Unity IOS platform builds.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type            | Description                                               |
| --------------- | --------------------------------------------------------- |
| `ISet<Purpose>` | A set of type `Purpose` containing the required purposes. |

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().GetRequiredPurposes();
```

{% endtab %}
{% endtabs %}

## GetRequiredPurposeIds

Get the list of purpose IDs that are required (automatically determined from the list of required vendors).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type           | Description                                                     |
| -------------- | --------------------------------------------------------------- |
| `ISet<string>` | A set of type `string` containing the IDs of required purposes. |

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().GetRequiredPurposeIds();
```

{% endtab %}
{% endtabs %}

## GetRequiredVendors

Get the list of vendors that are required (determined from the configuration).

{% hint style="warning" %}
**Not available for IOS platform builds**

This function is only exposed to Unity Android platform builds. It cannot be called from Unity IOS platform builds.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type           | Description                                             |
| -------------- | ------------------------------------------------------- |
| `ISet<Vendor>` | A set of type `Vendor` containing the required vendors. |

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().GetRequiredVendors();
```

{% endtab %}
{% endtabs %}

## GetRequiredVendorIds

Get the list of vendor IDs that are required (determined from the configuration).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type           | Description                                                    |
| -------------- | -------------------------------------------------------------- |
| `ISet<string>` | A set of type `string` containing the IDs of required vendors. |

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().GetRequiredVendorIds();
```

{% endtab %}
{% endtabs %}

## GetText

Method used to get a dictionary/map based on the key being passed. These keys and texts are extracted from the notice content, preferences content and the `texts` property specified in the `didomi_config.json` file as described here <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme#translatable-texts-for-custom-notices>.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name | Type   | Description                                           |
| ---- | ------ | ----------------------------------------------------- |
| key  | string | key associated to the dictionary that we want to get. |

**Returns**

| Type                        | Description                                                                                                                                             |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| IDictionary\<string,string> | Dictionary containing the translations for an specific key in different languages, with the form { "en:" "text in English", "fr": "texte en Français" } |

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().GetText("key");
```

{% endtab %}
{% endtabs %}

## GetTranslatedText

Method used to get a translated text based on the key being passed.

The language and the source of this translated text will depend on the availability of the translation for the specific key.

The language being used will be either the selected language of the SDK (based on device Locale and other parameters) or the language specified by app developers as the default language being used by the SDK. The source can be either the `didomi_config.json` file, which can be either local or remote, or a file that is bundled within the SDK.

These are the attempts performed by the SDK to try to find a translation for the specific key:

* Get translated value in user locale (selected language) from `didomi_config.json` (either local or remote).
* Get translated value in default locale (from the config) from `didomi_config.json` (either local or remote).
* Get translated value in user locale (selected language) from the Didomi-provided translations (bundled within the Didomi SDK).
* Get translated value in default locale (from the config) from the Didomi-provided translations (bundled within the Didomi SDK).

If no translation can be found after these 4 attempts, the key will be returned.

App developers can provide these translated texts through the `didomi_config.json` file (locally or remotely) in 3 different ways:

* Custom texts for the consent notice: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-notice#texts>
* Custom texts for the preferences: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#text>
* Custom texts for custom notices: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme#translatable-texts-for-custom-notices>

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name | Type   | Description                                                |
| ---- | ------ | ---------------------------------------------------------- |
| key  | string | key associated to the text that we want to get translated. |

**Returns**

Translated text.

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().GetTranslatedText("key");
```

{% endtab %}
{% endtabs %}

## GetCurrentUserStatus

Exposes the user status for the current regulation that applies.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameters.

**Returns**

The user status containing the computed global status for Vendors and purposes:

* A vendor's global status is enabled, if and only if:
  * the vendor is enabled directly in the vendors layer in all legal basis
  * **AND** all its related purposes are enabled or essential.
* A purpose's global status is enabled in one of the two conditions:
  * the purpose is enabled for all the legal basis that it is configured for.
  * **OR** when the purpose is essential.

| Parameter         | Type     | Description                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| didomiDcs         | `string` | Didomi Consent String that stores end-user choices for custom and Google ATP vendors, and custom and global purposes across all regulations. [Click here](/cmp/didomi-consent-string) for more information.                                                                                                                                                                                                                             |
| Vendors           | `object` | <ul><li>Dictionary that maps the ID of a vendor to an object representing its status.</li><li>The IDs used in this dictionary correspond to the Didomi IDs i.e.: without the <code>c:</code> or any other prefix.</li><li>Vendors with undefined user status are included in the response with <code>enabled: false.</code></li><li>Vendors with ONLY essential purposes are automatically set with <code>enable: true</code></li></ul> |
| Purposes          | `object` | <ul><li>Dictionary that maps the ID of a purpose to an object representing its status.</li><li>Purposes with undefined user status are included in the response with <code>enabled: false.</code></li><li>Essential purposes are automatically set with <code>enable: true</code></li></ul>                                                                                                                                             |
| Regulation        | `String` | <ul><li>Representation of the current regulation as a <code>Regulation</code> enum value, such as <code>GDPR</code>, <code>CCPA</code>, <code>CPRA</code>, or <code>NONE</code>.</li><li>Note that some regulations present as enum values are not available yet.</li></ul>                                                                                                                                                             |
| UserId            | `String` | Didomi user id.                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Created           | `String` | User choices creation date.                                                                                                                                                                                                                                                                                                                                                                                                             |
| Updated           | `String` | User choices update date.                                                                                                                                                                                                                                                                                                                                                                                                               |
| ConsentString     | `String` | TCF consent as string                                                                                                                                                                                                                                                                                                                                                                                                                   |
| AdditionalConsent | `String` | Additional consent.                                                                                                                                                                                                                                                                                                                                                                                                                     |
| GppString         | `String` | GPP string.                                                                                                                                                                                                                                                                                                                                                                                                                             |

**Throws**

<table data-header-hidden><thead><tr><th width="334">Type</th><th>Description</th></tr></thead><tbody><tr><td><strong>Type</strong></td><td>Description</td></tr><tr><td>DidomiNotReadyException</td><td>Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the <code>onReady</code> method.</td></tr></tbody></table>

**Example**

{% tabs %}
{% tab title="C#" %}

```csharp
Didomi.GetInstance().GetCurrentUserStatus();
```

{% endtab %}
{% endtabs %}

## GetVendor

Get a vendor based on its ID.

{% hint style="warning" %}
**Not available for IOS platform builds**

This function is only exposed to Unity Android platform builds. It cannot be called from Unity IOS platform builds.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name     | Type     | Description                      |
| -------- | -------- | -------------------------------- |
| vendorId | `string` | ID of the vendor we want to get. |

**Returns**

| Type     | Description                                                           |
| -------- | --------------------------------------------------------------------- |
| `Vendor` | A `Vendor` with ID `vendorId` found in the array of required vendors. |

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().GetVendor("vendor-id");
```

{% endtab %}
{% endtabs %}

## HideNotice

Hide the consent notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().HideNotice();
```

{% endtab %}
{% endtabs %}

## HidePreferences

Hide the preferences popup.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().HidePreferences();
```

{% endtab %}
{% endtabs %}

## Initialize

Initialize the SDK. The initialization runs on a background thread to avoid blocking your UI. Use the [onReady](/cmp/mobile-sdk/ios/reference/api#onready) function to know when the initialization is done and the SDK is ready to be used.

**Parameters**

<table data-header-hidden><thead><tr><th width="319">Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Type</td><td>Description</td></tr><tr><td>initializeParameters</td><td>DidomiInitializeParameters</td><td>Object containing the application parameters, see below</td></tr></tbody></table>

The **DidomiInitializeParameters** object contains all the information needed to initialize the SDK.

{% hint style="warning" %}
The parameter `disableDidomiRemoteConfig` is deprecated, we strongly suggest you to create your notice from the console (see [Setup from the Console](/cmp/mobile-sdk/unity-sdk/setup#from-the-console-recommended) for more information).
{% endhint %}

| Name                                       | Type   | Optional | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ------------------------------------------ | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| apiKey                                     | string | No       | Your API key                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| localConfigurationPath                     | string | Yes      | The path to your local config file in your `assets/` folder. Defaults to `didomi_config.json` if null.                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| remoteConfigurationURL                     | string | Yes      | The URL to a remote configuration file to load during initialization. When provided, the file at the URL will be downloaded and cached to be used instead of the local `assets/didomi_config.json`. If there is no Internet connection available and no previously cached file, the local file will be used as fallback.                                                                                                                                                                                                                                                 |
| providerId                                 | string | Yes      | Your provider ID (if any). A provider ID is assigned when you work with Didomi through a third-party. If are not sure if you have one, set this to `null`.                                                                                                                                                                                                                                                                                                                                                                                                               |
| disableDidomiRemoteConfig (deprecated)     | bool   | Yes      | <p>Prevent the SDK from loading a remote configuration from the Didomi Console. Defaults to <code>false</code> (allows loading remote config).</p><p>Set this parameter to <code>false</code> to use a remote consent notice configuration loaded from the Didomi Console.</p><p>Set this parameter to <code>true</code> to disable loading configurations from the Didomi Console.</p>                                                                                                                                                                                  |
| languageCode                               | string | Yes      | Language in which the consent UI should be displayed. By default, the consent UI is displayed in the language configured in the device settings. This property allows you to override the default setting and specify a language to display the UI in. String containing the language code e.g.: `"es"`, `"fr"`, `"en-US"`*,* `"zh-HK"`, etc.                                                                                                                                                                                                                            |
| noticeId                                   | string | Yes      | Notice ID to load the configuration from. If provided, the SDK bypasses the app ID targeting and directly loads the configuration from the notice ID.                                                                                                                                                                                                                                                                                                                                                                                                                    |
| tvNoticeId (only used on Android TV        | string | Yes      | TV notice ID to load the configuration from. If provided and SDK is initialized on Android TV, the SDK bypasses the app ID targeting and directly loads the configuration from the notice ID.                                                                                                                                                                                                                                                                                                                                                                            |
| androidTvEnabled (only used on Android TV) | bool   | Yes      | <p>Enable the Android TV SDK. Defaults to <code>false</code> (Android TV is not enabled).</p><p>This parameter will be checked if sdk is initialized from a TV device.</p><p>If set to <code>false</code>, the sdk initialization will fail with an error.</p><p>If set to <code>true</code>, the sdk will try to initialize in TV mode, using the API key and the optional <code>tvNoticeId</code> parameter.</p><p>Please note that the TV notice option must be enabled on Didomi side. Please reach out to your dedicated customer success manager to know more.</p> |
| countryCode                                | string | Yes      | <p>Override user country code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user country.</p>                                                                                                                                                                                                                                                                                                                                                                                                       |
| regionCode                                 | string | Yes      | <p>Override user region code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user region.</p><p>Ignored if countryCode is not set.</p>                                                                                                                                                                                                                                                                                                                                                                |
| isUnderage                                 | bool   | Yes      | Whether the user is underage or not. Defaults to `False`. This parameters can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).                                                                                                                                                                                                                                                                                                                                                                          |

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
 Didomi.GetInstance().Initialize(
     new DidomiInitializeParameters(
          apiKey: "<Your API key>",
          localConfigurationPath: null,
          remoteConfigurationURL: null,
          providerId: null,
          disableDidomiRemoteConfig: false,
          languageCode: null,
          noticeId: "<Your notice Id>",
          tvNoticeId: null,
          androidTvEnabled: false
));
```

{% endtab %}
{% endtabs %}

## IsConsentRequired

Determine if consent is required for the user. This takes into account the location of the user and the configuration of the SDK:

* If your app is configured to apply GDPR to all users then this function always returns `true`.
* If your app is configured to apply GDPR to EU users only then this function returns `true` only if the user in the EU.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`bool`

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().IsConsentRequired();
```

{% endtab %}
{% endtabs %}

## IsUserConsentStatusPartial

Determine if all consent information is available for the user.

This function returns `true` if and only if:

* Consent is required for the user (ie the user is in the EU or your tag is configured to apply GDPR to all users)
* At least one vendor is configured (if there is no vendor configured, this function always returns `false` as there is no consent to collect)
* We miss consent information for some vendors or purposes

If there is at least one piece of consent information missing for a single vendor/purpose, this function will return `true`. The consent notice is usually displayed when this function returns `true` although there is no guarantee of the direct mapping between the two.

An important edge case is when you add new vendors or if configured vendors ask for new purposes: the consent notice will be displayed again and this function will return `true` until the user has given or denied consent. Vendors that already had consent before will still operate normally as we only recollect consent for additional vendors/purposes.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`bool`

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().IsUserConsentStatusPartial();
```

{% endtab %}
{% endtabs %}

## IsUserStatusPartial

Determine if the user has provided a choice for all vendors selected for the regulation and linked data processing.

This function returns `true` if the user has not expressed a choice for all the required vendors and data processing.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`bool`

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().IsUserStatusPartial();
```

{% endtab %}
{% endtabs %}

## IsNoticeVisible

Check if the consent notice is currently displayed.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`bool`

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().IsNoticeVisible();
```

{% endtab %}
{% endtabs %}

## IsPreferencesVisible

Check if the preferences popup is currently displayed.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`bool`

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().IsPreferencesVisible();
```

{% endtab %}
{% endtabs %}

## IsReady

Check if the SDK is ready.

**Requires SDK to be initialized**

No.

**Parameters**

No parameter.

**Returns**

`bool`

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().IsReady();
```

{% endtab %}
{% endtabs %}

## OnReady

Add an event listener that will be called when the SDK is ready (ie fully initialized). If the event listener is added after the SDK initialization, the listener will be called immediately.

All calls to other functions of this API must only be made in a listener to the ready event to make sure that the SDK is initialized before it is used.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type     | Description                             |
| -------- | -------- | --------------------------------------- |
| callback | `Action` | An action to call when the SDK is ready |

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().OnReady( () => {
     // The SDK is ready 
});
```

{% endtab %}
{% endtabs %}

## OnError

Add an event listener that will be called when the SDK initialization encounters an error or if an unexpected situation occurs. Note that the behavior of the callback may slightly differ between Android and iOS platforms.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type     | Description                                        |
| -------- | -------- | -------------------------------------------------- |
| callback | `Action` | An action to call when the SDK encounters an error |

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().OnError( () => {
     // The SDK encountered an error 
});
```

{% endtab %}
{% endtabs %}

## OpenCurrentUserStatusTransaction

**Definition**

Create an instance of the `CurrentUserStatusTransaction` class.

This class provides mechanisms to stage updates to the user status regarding purposes and vendors, allowing for batch operations.

Updates made through its methods are queued and applied simultaneously to the user status only once the `commit` method of the returned object is called.

Additional details:

* The status of vendors and purposes whose IDs are not not specified through the methods provided by `CurrentUserStatusTransaction` are kept unchanged.
* Essential purposes are always set to enabled and can’t be updated by the methods provided by `CurrentUserStatusTransaction`.
* When the regulation applied for a user is `none`, the methods provided by `CurrentUserStatusTransaction` should not update the status of any vendor or purpose which will always remain as enabled. When the `commit` method is called it will return `false`.
* If the IDs that are passed through the methods provided by `CurrentUserStatusTransaction` don’t correspond to vendors or purposes required by the Notice Config, they will be ignored.

**Requires SDK to be initialized**

Yes.

#### Parameters

No parameter.

**Returns**

An instance of the `CurrentUserStatusTransaction` class.

**Description of the** `CurrentUserStatusTransaction` **class**

<table><thead><tr><th width="207">Method</th><th width="233">Parameters</th><th>Returns</th><th>Description</th></tr></thead><tbody><tr><td><code>EnablePurpose</code></td><td><code>id</code> (<code>string</code>): ID of the purpose to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single purpose based on its ID.</td></tr><tr><td><code>EnablePurposes</code></td><td><code>ids</code> (<code>string[]</code>): IDs of the purposes to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple purposes based on their IDs.</td></tr><tr><td><code>DisablePurpose</code></td><td><code>id</code> (<code>string</code>): ID of the purpose to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single purpose based on its ID.</td></tr><tr><td><code>DisablePurposes</code></td><td><code>ids</code> (<code>string[]</code>): IDs of the purposes to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple purposes based on their IDs.</td></tr><tr><td><code>EnableVendor</code></td><td><code>id</code> (<code>string</code>): Didomi ID of the vendor to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single vendor based on its Didomi ID.</td></tr><tr><td><code>EnableVendors</code></td><td><code>ids</code> (<code>string[]</code>): Didomi IDs of the vendors to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>DisableVendor</code></td><td><code>id</code> (<code>string</code>): Didomi ID of the vendor to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single vendor based on its Didomi ID.</td></tr><tr><td><code>DisableVendors</code></td><td><code>ids</code> (<code>string[]</code>): Didomi IDs of the vendors to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>Commit</code></td><td>No parameters.</td><td><code>bool</code>: <code>true</code> if user status has been updated, <code>false</code> otherwise.</td><td>Commit the changes that have been made through other methods.</td></tr></tbody></table>

#### Examples

{% tabs %}
{% tab title="C#" %}

```csharp
var transaction = Didomi.GetInstance().OpenCurrentUserStatusTransaction();

// Enable a purpose
transaction.EnablePurpose("cookies");
// Enable purposes
transaction.EnablePurposes("cookies", "analytics");
// Disable a purpose
transaction.DisablePurpose("analytics");
// Disable purposes
transaction.DisablePurposes("cookies", "analytics");
// Enable a vendor
transaction.EnableVendor("vendor-1");
// Enable vendors
transaction.EnableVendors("vendor-1", "vendor-2");
// Disable a vendor
transaction.DisableVendor("vendor-1");
// Disable vendors
transaction.DisableVendors("vendor-1", "vendor-2");

// Chain multiple calls
transaction.EnablePurpose("cookies").DisablePurpose("analytics");

// Save user choices
var updated = transaction.Commit();
```

{% endtab %}
{% endtabs %}

## SetupUI

{% hint style="info" %}
Internally, the setupUI method calls the `showNotice` method, which calls the `shouldUserStatusBeCollected` method. Therefore, by calling the `setupUI` method, the notice or preferences view will be displayed only if required.
{% endhint %}

Setup the SDK UI workflows. By calling this method the notice or the preferences views will be displayed only once the SDK is ready and if consent should be collected.

For IOS platforms`UIViewController` returned by UnityGetGLViewController at Unity is used as base UI. For Android platforms `Activity` returned by com.unity3d.player.UnityPlayer.currentActivity is used as base UI.

**Requires SDK to be initialized**

No.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().SetupUI();
```

{% endtab %}
{% endtabs %}

## **S**howNotice

{% hint style="info" %}
In most cases this method should be called if the notice should be displayed in response to a user action (e.g.: select the privacy settings section within your app). By calling the setupUI method, the notice will be displayed if required.
{% endhint %}

Show the consent notice. The consent notice actually only gets shown if needed (consent is required and we are missing consent information for some vendor or purpose).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().ShowNotice();
```

{% endtab %}
{% endtabs %}

## ShowPreferences

{% hint style="info" %}
In most cases this method should be called if you want to show the Preferences screen in response to a user action (the user pressing a Consent Preferences button in your app menu, for instance).
{% endhint %}

Show the Preferences view to the user. This can be used to allow the user to update their preferences after the banner has been closed. We suggest adding a link with this function call somewhere in your app.

**Requires SDK to be initialized**

Yes.

**Parameters**

<table><thead><tr><th width="206.72727272727272">Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>view</code></td><td><code>Didomi.Views</code></td><td>Optional, specify which view to open. Can be <code>Didomi.Views.Purposes</code> or <code>Didomi.View.Vendors</code>. By default, opens the Purposes screen.</td></tr></tbody></table>

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().ShowPreferences();    // Open the purposes screen
Didomi.GetInstance().ShowPreferences(Didomi.Views.Vendors);    // Open the vendors screen
```

{% endtab %}
{% endtabs %}

## Reset

Reset all the consent information for the current user. This will remove all consent information stored on the device by Didomi and will trigger re-collection of consent. The consent notice will be displayed again.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().Reset();
```

{% endtab %}
{% endtabs %}

## SetUser

Set custom user information from organization. More information about the organization user information behavior: [Share consents across devices](/cmp/mobile-sdk/share-consents-across-devices#setting-user-organization-id)

**Parameter**

| Name           | Type                   | Description                                          |
| -------------- | ---------------------- | ---------------------------------------------------- |
| userParameters | `DidomiUserParameters` | Object containing properties required to set a user. |

***Description for*** `DidomiUserParameters`***:***

<table><thead><tr><th width="193">Name</th><th width="219">Type</th><th>Description</th></tr></thead><tbody><tr><td>userAuth</td><td><code>UserAuth</code></td><td>User authentication object. Can be either <code>UserAuthWithoutParams</code>, <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.</td></tr><tr><td>dcsUserAuth</td><td><code>UserAuthParams</code></td><td>Optional. Dedicated user with encryption or hash used for Didomi Consent String signature. Can be either <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.<br>This parameter can only be used if you are using the Didomi Consent String feature (This feature is currently in beta version)</td></tr><tr><td>isUnderage</td><td><code>bool?</code></td><td>Optional. Whether the user is underage or not. This parameter can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).</td></tr></tbody></table>

Parameters for `UserAuthWithoutParams` :

<table><thead><tr><th width="204">Name</th><th width="228">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>Organization ID to associate with the user.</td></tr></tbody></table>

Parameters for `UserAuthWithEncryptionParams` :

<table><thead><tr><th width="211">Name</th><th width="202">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>string</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>string</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>initializationVector</td><td><code>string</code></td><td>Initialization Vector used for encrypting the message.</td></tr><tr><td>expiration</td><td><code>long?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0).</td></tr></tbody></table>

Parameters for `UserAuthWithHashParams` :

<table><thead><tr><th width="212">Name</th><th width="205">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>string</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>string</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>digest</td><td><code>string</code></td><td>Digest used for representing the user ID</td></tr><tr><td>salt</td><td><code>string?</code></td><td>Optional. Salt used for computing the user ID.</td></tr><tr><td>expiration</td><td><code>long?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0)</td></tr></tbody></table>

**Other signatures for `SetUser` are deprecated and should not be used.**

**Returns**

Nothing

**Example**

```csharp
Didomi.GetInstance().SetUser(new DidomiUserParameters(
            new UserAuthWithoutParams("e3222031-7c45-4f4a-8851-ffd57dbf0a2a")
));

Didomi.GetInstance().SetUser(new DidomiUserParameters(
            new UserAuthWithEncryptionParams(
                        "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
                        "algorithm",
                        "secret_id",
                        "initialization_vector",
                        10000L // or null
            )
));

Didomi.GetInstance().SetUser(new DidomiUserParameters(
            new UserAuthWithHashParams(
                        "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
                        "algorithm",
                        "secret_id",
                        "digest",
                        "salt", // or null
                        10000L // or null
            )
));

Didomi.GetInstance().SetUser(new DidomiUserParameters(
            new UserAuthWithHashParams(
                        "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
                        "algorithm",
                        "secret_id",
                        "digest"
            ),
            dcsUserAuth: new UserAuthWithHashParams(
                        "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
                        "algorithm",
                        "secret_id",
                        "digest"
            ),
            isUnderage: false
));
```

## SetUserAndSetupUI

Set custom user information from organization, and call `SetupUI` after synchronization if sdk was initialized

**Parameters**

See [#setuser](#setuser "mention")

**Returns**

Nothing

**Example**

```csharp
Didomi.GetInstance().SetUserAndSetupUI("e3222031-7c45-4f4a-8851-ffd57dbf0a2a");

Didomi.GetInstance().SetUserAndSetupUI(new UserAuthWithEncryptionParams(
            "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
            "algorithm",
            "secret_id",
            "initialization_vector",
            10000L // or null
));

Didomi.GetInstance().SetUserAndSetupUI(new UserAuthWithHashParams(
            "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
            "algorithm",
            "secret_id",
            "digest",
            "salt", // or null
            10000L // or null
)); 
```

## ClearUser

Remove custom user information from organization

**Requires SDK to be initialized**

No.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

```csharp
Didomi.GetInstance().ClearUser();
```

## SetUserAgreeToAll

Report that the user has given consent to all purposes and vendors setup for your app programmatically.\
This function will log the consent on our platform and close the notice.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`bool`

`true` if the user consent status has changed (ie the user had given different consent information before this function got called).

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().SetUserAgreeToAll();
```

{% endtab %}
{% endtabs %}

## SetCurrentUserStatus

Set the user status for purposes and vendors. This function will trigger events and API calls every time it is called (and the user status changes) so make sure to push all user choices at once and not one by one.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

Add the desired global status for each vendor and each purpose:

* the vendor status specified in this function will be reflected on the vendor’s layer.
  * vendor enabled : true → means the vendor is enabled in all the legal basis that this vendor uses.
  * vendor enabled : false → means the vendor is disabled in all the legal basis that this vendor uses
* the purposes status specified in this function will be reflected on the preferences layer.
  * purpose enabled : true → means the purpose is enabled in all the legal basis in which it’s defined.
  * purpose enabled : false → means the purpose is disabled in all the legal basis in which it’s defined.

**Returns**

`boolean`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

{% tabs %}
{% tab title="C#" %}

```csharp
var currentUserStatus = new CurrentUserStatus();

var purposes = new Dictionary<string, PurposeStatus>
{
    { "1", new PurposeStatus("1", true) },
    { "2", new PurposeStatus("2", true) },
    { "3", new PurposeStatus("3", false) },
    { "4", new PurposeStatus("4", false) }
};

var vendors = new Dictionary<string, VendorStatus>
{
    { "1", new VendorStatus("1", true) },
    { "2", new VendorStatus("2", true) },
    { "3", new VendorStatus("3", false) },
    { "4", new VendorStatus("4", false) }
};

bool updated = Didomi.GetInstance().SetCurrentUserStatus(currentUserStatus);
```

{% endtab %}
{% endtabs %}

## SetUserDisagreeToAll

Report that the user has denied consent to all purposes and vendors setup for your app programmatically.\
This function will log the consent information on our platform and close the banner.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`bool`

`true` if the user consent status has changed (ie the user had given different consent information before this function got called).

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().SetUserDisagreeToAll();
```

{% endtab %}
{% endtabs %}

## ShouldConsentBeCollected

**Deprecated**, use [ShouldUserStatusBeCollected](#shoulduserstatusbecollected) instead.

Determine if consent should be collected for the visitor. Returns `true` if consent is required for the current user and one of following two conditions is met:

* Consent has never been collected for this visitor yet
* New consents should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `false`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`bool`

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().ShouldConsentBeCollected();
```

{% endtab %}
{% endtabs %}

## ShouldUserStatusBeCollected

Determine if user status (consent) should be collected for the user. Returns `true` if status is required for the current user and one of following two conditions is met:

* User status has never been collected for this user yet
* New user status should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `False`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`bool`

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().ShouldUserStatusBeCollected();
```

{% endtab %}
{% endtabs %}

## UpdateSelectedLanguage

Method used to update the selected language of the Didomi SDK and any property that depends on it.

In most cases this method doesn't need to be called. It would only be required for those apps that allow language change on-the-fly, i.e.: from within the app rather than from the device settings.

In order to update the language of the views displayed by the Didomi SDK, this method needs to be called before these views are displayed.

The language update is performed asynchronously. If you need to make sure the update is done, you can listen to the events `LanguageUpdated` / `LanguageUpdateFailed`.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name         | Type     | Description                                                              |
| ------------ | -------- | ------------------------------------------------------------------------ |
| languageCode | `string` | string containing the 2-letter language code e.g. `en`, `es`, `fr`, etc. |

**Returns**

Nothing

**Example**

{% tabs %}
{% tab title="C#" %}

```swift
Didomi.GetInstance().OnReady( () => {
     // The SDK is ready 
     Didomi.GetInstance().UpdateSelectedLanguage("en");
});           
```

{% endtab %}
{% endtabs %}


# Deprecated

See the following sections for methods and events that have been deprecated in the Didomi Unity SDK

* [Notice Config](#notice-config)
* [User Status](#user-status)

***

### Notice Config

The following notice configuration methods and events have been deprecated in the Didomi Unity SDK:

<table><thead><tr><th width="207">Method/Event</th><th>Description</th></tr></thead><tbody><tr><td><code>GetDisabledPurposes</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetDisabledPurposeIds</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetDisabledVendors</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetDisabledVendorIds</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetEnabledPurposes</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetEnabledPurposeIds</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetEnabledVendors</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetEnabledVendorIds</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr></tbody></table>

### User Status

The following user status methods and events have been deprecated in the Didomi Unity SDK:

<table><thead><tr><th width="276">Method/Event</th><th>Description</th></tr></thead><tbody><tr><td><code>GetUserConsentStatusForPurpose</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetUserConsentStatusForVendor</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetUserConsentStatusForVendorAndRequiredPurposes</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetUserLegitimateInterestStatusForPurpose</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetUserLegitimateInterestStatusForVendor</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetUserLegitimateInterestStatusForVendorAndRequiredPurposes</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetUserStatusForVendor</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr><tr><td><code>SetUserConsentStatus</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#setcurrentuserstatus">SetCurrentUserStatus</a> instead.</td></tr><tr><td><code>SetUserStatus</code></td><td>Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#setcurrentuserstatus">SetCurrentUserStatus</a> instead.</td></tr><tr><td><code>GetUserStatus</code></td><td>Use <a href="/pages/-M7mgQ5xjGcg3-jtyaw8#getcurrentuserstatus">GetCurrentUserStatus</a> instead.</td></tr></tbody></table>


# Versions

Releases of the Didomi Unity SDK are published and documented on our Github repository: <https://github.com/didomi/unity/releases>


# Troubleshooting

### Newtonsoft dll error

In some Unity versions (including several Unity 2020 and 2021 versions), you may encounter this error:

`Multiple precompiled assemblies with the same name Newtonsoft.Json.dll included or the current platform. Only one assembly with the same name is allowed per platform.`

In this case, use the `Didomi-noDll.unitypackage` release file instead of `Didomi.unitypackage`, or manually remove the file `Assets/Plugins/Didomi/IOS/Newtonsoft.Json.dll` from the regular package after importing it.

### Gradle 6.1.1

This is the default gradle version on Unity version 2021.3 and below.

With this version, you may encounter an error at build time:

```log
> Cannot choose between the following variants of com.google.guava:guava:32.1.3-android:
    - androidRuntimeElements
    - jreRuntimeElements
```

If changing the gradle version is not possible, it is possible to fix this issue:

* In Player settings, in Android section, activate `Custom Main Gradle Template` and `Custom Launcher Gradle Template`
* Modify `Assets/Plugins/Android/mainTemplate.gradle` and `Assets/Plugins/Android/launcherTemplate.gradle` by adding

```gradle
configurations.all {
    resolutionStrategy {
        force 'com.google.guava:guava:32.0.1-android'
    }
}
```

before the `dependencies` block.

{% code title="mainTemplate.gradle" %}

```gradle
configurations.all {
    resolutionStrategy {
        force 'com.google.guava:guava:32.0.1-android'
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
**DEPS**}
```

{% endcode %}

{% code title="launcherTemplate.gradle" %}

```gradle
configurations.all {
    resolutionStrategy {
        force 'com.google.guava:guava:32.0.1-android'
    }
}

dependencies {
    implementation project(':unityLibrary')
}
```

{% endcode %}


# React Native

This section will guide you through the required steps to set up the Didomi plugin for your React Native applications on mobile devices (Android and iOS).

[Didomi plugin 2.20.0](https://github.com/didomi/react-native/releases/tag/2.20.0) and above use version `0.81.5`. It is compatible with apps using React Native from `0.77.x` to `0.82.x`. Older versions may require some changes in Gradle (Android) and/or Xcode (iOS).

We assume that you have a Didomi account and an API key. If not, please go to our [website](https://www.didomi.io/) and sign up for an account.


# Setup

## Add the SDK to your project

Install using `yarn add @didomi/react-native` or `npm i @didomi/react-native`

Then install required pods for iOS with `cd ios && pod install`

As Didomi requires Swift runtime for iOS, if your project does not contain Swift code, you need to add an empty Swift file (to create a bridging header) into Xcode project.

Then you can import project from your js code:

```javascript
import { Didomi, DidomiEventType } from '@didomi/react-native';
```

## Initialize the SDK

Once our SDK has been added to your project, you need to initialize it. The initialization process will prepare the SDK for interactions with the user and your application. It is important to launch the SDK initialization as soon as possible.

In your code, call the `initialize` method and pass your API key:

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

```javascript
function init() {
    Didomi.onReady().then(() => {
        // From this point, SDK is ready
    });

    var parameters = {
      apiKey: '<YOUR_API_KEY>',
      noticeId: '<YOUR_NOTICE_ID>'
    };
    Didomi.initializeWithParameters(parameters);
}
```

{% endtab %}
{% endtabs %}

�Keep in mind that the SDK initialization is an asynchronous process so you must avoid interacting with the `DidomiSdk` object until it is actually ready to handle your requests. Use the `onReady` event in js to register a listener for the ready event.

Take a look at our sample app to see how the setup is done.

## Setup the SDK UI

{% hint style="info" %}
Note: the `setupUI` method should be called only from your contexts where the application starts.

You do not need to call `onReady`, `isReady` or `shouldConsentBeCollected` before calling `setupUI` because they are called internally. Therefore, by calling this method the consent notice will be displayed if it is required and only once the SDK is ready.
{% endhint %}

Call the `setupUI` function of the SDK in your context where the application starts:

```javascript
Didomi.setupUI();
```

### Deep links

If you are using deep links or have multiple pages in your react-native app, make sure that the `setupUI` function is called on every context that the user can launch the app on.\
\
This will ensure that consent is always collected as needed and there is no path where the user can launch the app without consent being collected. If `setupUI` is missing in some entry points, you will see lower consent rates as users will be using the app without giving consent.

## Configure the SDK

We support three options for configuring the UI and the behavior of the SDK:

* [Didomi Console](/cmp/mobile-sdk/flutter/setup#from-the-console-recommended): the SDK is configured remotely from the Didomi Console
* [Local file](/cmp/mobile-sdk/flutter/setup#local-file): the SDK is configured from a `didomi_config.json` file embedded in your app package
* [Remote file](/cmp/mobile-sdk/flutter/setup#remote-file): the SDK is configured from a remote `didomi_config.json` file

### From the Console (Recommended)

You can configure the consent notice in your app by creating a notice in your Didomi Console. It will automatically be linked to your app through your API Key and, optionally, your notice id. You can access the Didomi console [here](http://console.didomi.io).

To enable this option, omit the `disableDidomiRemoteConfig` parameter or pass it as `false` when calling the `initialize` method, as shown below.

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

```dart
var parameters = {
  apiKey: '<YOUR_API_KEY>',
  disableDidomiRemoteConfig: false, // it can be omitted as well.
  noticeId: '<YOUR_NOTICE_ID>'
};
Didomi.initializeWithParameters(parameters);
```

{% endtab %}
{% endtabs %}

The SDK will automatically use the remote configuration hosted by Didomi and cache it locally. The cached version is refreshed every 60 minutes.\
If there is no connection available to download the remote configuration and no locally cached version, the SDK will try to use a local `didomi_config.json` configuration file as a fallback. See the Local option below for more information on how to configure the SDK through a local configuration file.

### Local file

{% hint style="danger" %}
Using a local file automatically disables the TCF integration.\
If your app uses the TCF, you must use a configuration from the Didomi Console.
{% endhint %}

{% hint style="warning" %}
Using a local file will prevent you to support multiple regulations.
{% endhint %}

With this option, you create your own SDK configuration file and embed it in your app package.

The SDK behavior is configured in a `didomi_config.json` file that must be placed in the Android and iOS folders of your project.

You can create a file with the following content to get started:

{% tabs %}
{% tab title="didomi\_config.json" %}

```javascript
{
    "app": {
        "name": "My App Name",
        "privacyPolicyURL": "http://www.website.com/privacy",
        "vendors": {
            "iab": {
                "all": true
            }
        },
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    }
}
```

{% endtab %}
{% endtabs %}

For Android, the configuration file must be placed in the assets folder of the Android platform code (in this example: `android/app/src/main/assets`)

![](/files/-MbGmSdvukwn0MZhhmA7)

For iOS, add the configuration file to the project and make sure the `project.pbxproj` file is updated.

![](/files/-Me-LFWH-5eFf1TWljih)

You also need to disable loading the remote configuration to ensure that only the local file is loaded and that no HTTP request is sent. Update your [`initialize`](https://developers.didomi.io/cmp/unity-sdk/reference-unity#initialize) call to set the `disableDidomiRemoteConfig` parameter to `true`:

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

```dart
var parameters = {
  apiKey: '<YOUR_API_KEY>',
  disableDidomiRemoteConfig: true,
  noticeId: '<YOUR_NOTICE_ID>'
};
Didomi.initializeWithParameters(parameters);
```

{% endtab %}
{% endtabs %}

Your SDK is now setup. [Read the Getting started section](/cmp/mobile-sdk/consent-notice/getting-started) of our Mobile SDKs to learn more about how to configure it to match your app UI and requirements.

### Remote file

{% hint style="info" %}
Enabling this option will prevent the configuration from being loaded from the Didomi Console.
{% endhint %}

You can provide a remote URL for the SDK to download the `didomi_config.json` configuration file from. That allows you to update the SDK configuration without having to re-publish you mobile application.

When that configuration is enabled, the SDK will automatically use the remote configuration and cache it locally. The cached version is refreshed every 60 minutes. If there is no connection available to download the remote file and no locally cached version, the SDK will try to use the local `didomi_config.json` (described above) as a fallback.

To enable that option, change your call to initialize to provide the remote file URL:�

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

```dart
var parameters = {
  apiKey: '<YOUR_API_KEY>',
  remoteConfigurationUrl: 'http://www.website.com/didomi_config.json',
  noticeId: '<YOUR_NOTICE_ID>'
};
Didomi.initializeWithParameters(parameters);
```

{% endtab %}
{% endtabs %}

Also see the reference documentation of the initialize function for more information.


# Reference

## Reference

This section is a comprehensive reference of the methods and events exposed by the react-native SDK that you can leverage in your application.

These methods are accessible in the `Didomi` class. Also make sure to always call the SDK after it is fully initialized (see [onReady](#onready)).

## addEventListener

Add an event listener to catch events triggered by the SDK. Events listeners allow you to react to different events of interest. This function is safe to call before the `READY` event has been triggered.

**Requires SDK to be initialized**

No.

**Parameters**

| Name      | Type                  | Description                                                                                |
| --------- | --------------------- | ------------------------------------------------------------------------------------------ |
| eventType | `DidomiEventType`     | The type of event to listen to                                                             |
| callback  | `(data: any) => void` | Callback to call when event occurs. `data` is an optional parameter sent with some events. |

**Event types**

`DidomiEventType` is an enum with the following values:

```javascript
export enum DidomiEventType {
    // Consent
    CONSENT_CHANGED = "on_consent_changed",
    // SDK lifecycle events
    ERROR = "on_error",
    READY = "on_ready",
    // Notice
    HIDE_NOTICE = "on_hide_notice",
    SHOW_NOTICE = "on_show_notice",
    NOTICE_CLICK_AGREE = "on_notice_click_agree",
    NOTICE_CLICK_DISAGREE = "on_notice_click_disagree",
    NOTICE_CLICK_VIEW_VENDORS = "on_notice_click_view_vendors",
    NOTICE_CLICK_VIEW_SPI_PURPOSES = "on_notice_click_view_spi_purposes",
    NOTICE_CLICK_MORE_INFO = "on_notice_click_more_info",
    NOTICE_CLICK_PRIVACY_POLICY = "on_notice_click_privacy_policy",
    // Preferences
    HIDE_PREFERENCES = "on_hide_preferences",
    SHOW_PREFERENCES = "on_show_preferences",
    // Preferences - Views
    PREFERENCES_CLICK_VIEW_PURPOSES = "on_preferences_click_view_purposes",
    PREFERENCES_CLICK_VIEW_VENDORS = "on_preferences_click_view_vendors",
    PREFERENCES_CLICK_VIEW_SPI_PURPOSES = "on_preferences_click_view_spi_purposes",
    // Preferences - Purpose
    PREFERENCES_CLICK_AGREE_TO_ALL = "on_preferences_click_agree_to_all",
    PREFERENCES_CLICK_DISAGREE_TO_ALL = "on_preferences_click_disagree_to_all",
    PREFERENCES_CLICK_AGREE_TO_ALL_PURPOSES = "on_preferences_click_agree_to_all_purposes",
    PREFERENCES_CLICK_DISAGREE_TO_ALL_PURPOSES = "on_preferences_click_disagree_to_all_purposes",
    PREFERENCES_CLICK_RESET_ALL_PURPOSES = "on_preferences_click_reset_all_purposes",
    PREFERENCES_CLICK_PURPOSE_AGREE = "on_preferences_click_purpose_agree",
    PREFERENCES_CLICK_PURPOSE_DISAGREE = "on_preferences_click_purpose_disagree",
    PREFERENCES_CLICK_CATEGORY_AGREE = "on_preferences_click_category_agree",
    PREFERENCES_CLICK_CATEGORY_DISAGREE = "on_preferences_click_category_disagree",
    PREFERENCES_CLICK_SAVE_CHOICES = "on_preferences_click_save_choices",
    // Preferences - Vendor
    PREFERENCES_CLICK_AGREE_TO_ALL_VENDORS = "on_preferences_click_agree_to_all_vendors",
    PREFERENCES_CLICK_DISAGREE_TO_ALL_VENDORS = "on_preferences_click_disagree_to_all_vendors",
    PREFERENCES_CLICK_VENDOR_AGREE = "on_preferences_click_vendor_agree",
    PREFERENCES_CLICK_VENDOR_DISAGREE = "on_preferences_click_vendor_disagree",
    PREFERENCES_CLICK_VENDOR_SAVE_CHOICES = "on_preferences_click_vendor_save_choices",
    // Preferences - Sensitive Personal Information
    PREFERENCES_CLICK_SPI_PURPOSE_AGREE = "on_preferences_click_spi_purpose_agree",
    PREFERENCES_CLICK_SPI_PURPOSE_DISAGREE = "on_preferences_click_spi_purpose_disagree",
    PREFERENCES_CLICK_SPI_CATEGORY_AGREE = "on_preferences_click_spi_category_agree",
    PREFERENCES_CLICK_SPI_CATEGORY_DISAGREE = "on_preferences_click_spi_category_disagree",
    PREFERENCES_CLICK_SPI_PURPOSE_SAVE_CHOICES = "on_preferences_click_spi_purpose_save_choices",
    // Sync
    SYNC_READY = "on_sync_ready",
    SYNC_DONE = "on_sync_done", // Deprecated
    SYNC_ERROR = "on_sync_error",
    // Language
    LANGUAGE_UPDATED = "on_language_updated",
    LANGUAGE_UPDATE_FAILED = "on_language_update_failed",
}
```

These events are supported by the Didomi SDK:

<table data-header-hidden><thead><tr><th width="374">Value</th><th>Description</th></tr></thead><tbody><tr><td><strong>Value</strong></td><td>Description</td></tr><tr><td>CONSENT_CHANGED</td><td>When a consent is given or withdrawn by the user. Only triggered when the consent status actually changes (ie if the user saves consents without adding/removing any consent then this does not get called).</td></tr><tr><td>ERROR</td><td>When the SDK encountered an error (<code>message</code> provided as parameter).</td></tr><tr><td>READY</td><td>When the SDK is ready.</td></tr><tr><td>HIDE_NOTICE</td><td>When the consent notice is hidden. If you have disabled our default consent notice to replace it with your own, you need to hide your custom notice when this event gets triggered.</td></tr><tr><td>SHOW_NOTICE</td><td>When the consent notice gets displayed. If you have disabled our default consent notices to replace them with your own, you need to show your custom notice when this event gets triggered.</td></tr><tr><td>NOTICE_CLICK_AGREE</td><td>When user clicks on agree on the notice.</td></tr><tr><td>NOTICE_CLICK_DISAGREE</td><td>When user clicks on disagree on the notice.</td></tr><tr><td>NOTICE_CLICK_VIEW_VENDORS</td><td>When user clicks on Partners on the notice.</td></tr><tr><td>NOTICE_CLICK_VIEW_SPI_PURPOSES</td><td>When user clicks on Sensitive Personal Information on the notice.</td></tr><tr><td>NOTICE_CLICK_MORE_INFO</td><td>When user clicks on learn more on the notice.</td></tr><tr><td>NOTICE_CLICK_PRIVACY_POLICY</td><td>When user clicks on privacy policy on the notice.</td></tr><tr><td>HIDE_PREFERENCES</td><td>When the preferences screen is hidden.</td></tr><tr><td>SHOW_PREFERENCES</td><td>When the preferences screen is displayed.</td></tr><tr><td>PREFERENCES_CLICK_VIEW_PURPOSES</td><td>When user clicks on view purposes on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_VIEW_VENDORS</td><td>When user clicks on view vendors on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_VIEW_SPI_PURPOSES</td><td>When user clicks on view Sensitive Personal Information on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_AGREE_TO_ALL</td><td>When user clicks on agree to all on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_DISAGREE_TO_ALL</td><td>When user clicks on disagree to all on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_AGREE_TO_ALL_PURPOSES</td><td>When user flips ON all purposes switch on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_DISAGREE_TO_ALL_PURPOSES</td><td>When user flips OFF all purposes switch on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_RESET_ALL_PURPOSES</td><td>When user resets all purposes switch on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_PURPOSE_AGREE</td><td>When user agree to a purpose on the preferences popup. (<code>purposeId</code> provided as parameter).</td></tr><tr><td>PREFERENCES_CLICK_PURPOSE_DISAGREE</td><td>When user disagree to a purpose on the preferences popup. (<code>purposeId</code> provided as parameter)</td></tr><tr><td>PREFERENCES_CLICK_CATEGORY_AGREE</td><td>When user agree to a category on the preferences popup (<code>categoryId</code> provided as parameter).</td></tr><tr><td>PREFERENCES_CLICK_CATEGORY_DISAGREE</td><td>When user disagree to a category on the preferences popup (<code>categoryId</code> provided as parameter).</td></tr><tr><td>PREFERENCES_CLICK_SAVE_CHOICES</td><td>When user saves his choice on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_AGREE_TO_ALL_VENDORS</td><td>When user flips ON all vendors switch on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_DISAGREE_TO_ALL_VENDORS</td><td>When user flips OFF all vendors switch on the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_VENDOR_AGREE</td><td>When user agree to a vendor on the preferences popup (<code>vendorId</code> provided as parameter).</td></tr><tr><td>PREFERENCES_CLICK_VENDOR_DISAGREE</td><td>When user disagree to a vendor on the preferences popup (<code>vendorId</code> provided as parameter).</td></tr><tr><td>PREFERENCES_CLICK_VENDOR_SAVE_CHOICES</td><td>When user saves his choice on the vendors view from the preferences popup.</td></tr><tr><td>PREFERENCES_CLICK_SPI_PURPOSE_AGREE</td><td>When user agree to a purpose on the Sensitive Personal Information view from preferences popup. (<code>purposeId</code> provided as parameter).</td></tr><tr><td>PREFERENCES_CLICK_SPI_PURPOSE_DISAGREE</td><td>When user disagree to a purpose on Sensitive Personal Information view from the preferences popup. (<code>purposeId</code> provided as parameter)</td></tr><tr><td>PREFERENCES_CLICK_SPI_CATEGORY_AGREE</td><td>When user agree to a category on the Sensitive Personal Information view from preferences popup (<code>categoryId</code> provided as parameter).</td></tr><tr><td>PREFERENCES_CLICK_SPI_CATEGORY_DISAGREE</td><td>When user disagree to a category on the Sensitive Personal Information view from preferences popup (<code>categoryId</code> provided as parameter).</td></tr><tr><td>PREFERENCES_CLICK_SPI_PURPOSE_SAVE_CHOICES</td><td>When user saves his choice on the Sensitive Personal Information view from preferences popup.</td></tr><tr><td>SYNC_READY</td><td><p>When the consent synchronization process is over.</p><p><code>data</code> parameter is a <code>SyncReadyEvent</code> object that contains the fields <code>statusApplied</code> and <code>syncAcknowledged</code> (see below)</p></td></tr><tr><td><code>SyncReadyEvent.statusApplied</code></td><td>Whether the user status was applied</td></tr><tr><td><code>SyncReadyEvent.syncAcknowledged</code></td><td>Function that triggers a <code>sync.acknowledged</code> API event when called. It returns <code>true</code> if the API event was sent successfully.</td></tr><tr><td>SYNC_DONE</td><td><p><strong>Deprecated, use <code>SYNC_READY</code> instead.</strong></p><p>When the consent synchronization is successful (<code>organizationUserId</code> provided as parameter).</p></td></tr><tr><td>SYNC_ERROR</td><td>When the consent synchronization has failed (<code>error</code> provided as parameter).</td></tr><tr><td>LANGUAGE_UPDATED</td><td>When the language has changed (<code>languageCode</code> provided as parameter).</td></tr><tr><td>LANGUAGE_UPDATE_FAILED</td><td>When the language change has failed (<code>reason</code> provided as parameter).</td></tr></tbody></table>

**Returns**

Nothing

**Example**

```javascript
const registerListener = (eventType: DidomiEventType) => {
  Didomi.addEventListener(eventType, (data: any) => {
    console.log('Event received: ' + eventType + ', data:' + data);
  });
};
  
registerListener(DidomiEventType.READY);
registerListener(DidomiEventType.CONSENT_CHANGED);
registerListener(DidomiEventType.SHOW_NOTICE);
registerListener(DidomiEventType.HIDE_NOTICE);
```

## addVendorStatusListener <a href="#addvendorstatuslistener" id="addvendorstatuslistener"></a>

Listen for changes on the user status linked to a specific vendor.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type                               | Description                                                                                                                                                                     |
| -------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendorId | `string`                           | <p>The ID of the vendor for which we want to start listening for changes.</p><p>This ID should be the ID provided by Didomi, which doesn't contain prefixes.</p>                |
| callback | callback: `(VendorStatus) => void` | Callback that will be executed whenever changes are detected on the specified vendor. When this callback is executed, the status linked to the specified vendor will be passed. |

**Returns**

Nothing

**Example**

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

```javascript
Didomi.addVendorStatusListener('vendorId', (vendorStatus: VendorStatus) => {
    console.log("Event received: Vendor status for " + vendorStatus.id + " is " + vendorStatus.enabled);
});
```

{% endtab %}
{% endtabs %}

## removeVendorStatusListener <a href="#removevendorstatuslistener" id="removevendorstatuslistener"></a>

Stop listening for changes on the user status linked to a specific vendor.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type     | Description                                                                                                                                                     |
| -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendorId | `string` | <p>The ID of the vendor for which we want to stop listening for changes.</p><p>This ID should be the ID provided by Didomi, which doesn't contain prefixes.</p> |

**Returns**

Nothing

**Example**

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

```javascript
Didomi.removeVendorStatusListener('vendorId');
```

{% endtab %}
{% endtabs %}

## getCurrentUserStatus

**Definition**

Exposes the user status for the current regulation that applies.

**Parameters**

No parameters.

**Returns**

The user status containing the computed global status for Vendors and purposes:

* A vendor's global status is enabled, if and only if:
  * the vendor is enabled directly in the vendors layer in all legal basis
  * **AND** all its related purposes are enabled or essential.
* A purpose's global status is enabled in one of the two conditions:
  * the purpose is enabled for all the legal basis that it is configured for.
  * **OR** when the purpose is essential.

<table><thead><tr><th width="185">Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td>vendors</td><td><code>object</code></td><td><ul><li>Object that maps the ID of a vendor to an object representing its status.</li><li>The IDs used in this dictionary correspond to the Didomi IDs i.e.: without the <code>c:</code> or any other prefix.</li><li>Vendors with undefined user status are included in the response with <code>enabled: false.</code></li><li>Vendors with ONLY essential purposes are automatically set with <code>enable: true</code></li></ul></td></tr><tr><td>purposes</td><td><code>object</code></td><td><ul><li>Object that maps the ID of a purpose to an object representing its status.</li><li>Purposes with undefined user status are included in the response with <code>enabled: false.</code></li><li>Essential purposes are automatically set with <code>enable: true</code></li></ul></td></tr><tr><td>regulation</td><td><code>object</code></td><td><ul><li>Representation of the current regulation as a <code>Regulation</code> enum value, such as <code>GDPR</code>, <code>CCPA</code>, <code>CPRA</code>, or <code>NONE</code>.</li><li>Note that some regulations present as enum values are not available yet.</li></ul></td></tr><tr><td>userId</td><td><code>string</code></td><td>Didomi user id.</td></tr><tr><td>created</td><td><code>string</code></td><td>User choices creation date.</td></tr><tr><td>updated</td><td><code>string</code></td><td>User choices update date.</td></tr><tr><td>consentString</td><td><code>string</code></td><td>TCF consent as string</td></tr><tr><td>additionalConsent</td><td><code>string</code></td><td>Additional consent.</td></tr></tbody></table>

**Examples**

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

```javascript
let userStatus = await Didomi.getCurrentUserStatus();

let isVendorEnabled = userStatus.vendors["vendor-id"].enabled;
```

{% endtab %}
{% endtabs %}

## getJavaScriptForWebView

Get JavaScript to embed into a WebView to pass the consent status from the app to the Didomi Web SDK embedded into the WebView.

Inject the returned tag into a WebView with `evaluateJavaScript`.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type              | Description                           |
| ----------------- | ------------------------------------- |
| `Promise<string>` | JavaScript code to embed in a WebView |

**Example**

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

```dart
await Didomi.getJavaScriptForWebView();
```

{% endtab %}
{% endtabs %}

## getQueryStringForWebView

Get a query string parameter to append to the URL of a WebView to pass the consent status from the app to the Didomi Web SDK embedded into the WebView.

Read our article on [sharing consent with WebViews](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/docs/cmp/mobile-sdk/share-consent-with-webviews.md) for more information.

{% hint style="info" %}
This method is currently available on Android platform only.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type              | Description                                                                                                                                                                            |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Promise<string>` | Query string parameter with the format `didomiConfig.user.externalConsent.value=...`. It can be appended to your URL after a `?` or a `&` if your URL already contains a query string. |

**Example**

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

```dart
await Didomi.getQueryStringForWebView();
```

{% endtab %}
{% endtabs %}

## getPurpose

Get a purpose based on its ID.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name      | Type     | Description                       |
| --------- | -------- | --------------------------------- |
| purposeId | `string` | ID of the purpose we want to get. |

**Returns**

| Type               | Description                                                                              |
| ------------------ | ---------------------------------------------------------------------------------------- |
| `Promise<Purpose>` | A `Purpose` with ID `purposeId` found in the array of required purposes, or `undefined`. |

`Purpose` interface is defined in `DidomiTypes.ts`

**Example**

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

```dart
await Didomi.getPurpose("purpose-id") as Purpose;
```

{% endtab %}
{% endtabs %}

## getRequiredPurposes

Get the list of purpose that are required (automatically determined from the list of required vendors).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type                 | Description                                                |
| -------------------- | ---------------------------------------------------------- |
| `Promise<Purpose[]>` | A list of type `Purpose` containing the required purposes. |

`Purpose` interface is defined in `DidomiTypes.ts`

**Example**

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

```dart
await Didomi.getRequiredPurposes();
```

{% endtab %}
{% endtabs %}

## getRequiredPurposeIds

Get the list of purpose IDs that are required (automatically determined from the list of required vendors).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type                | Description                                                      |
| ------------------- | ---------------------------------------------------------------- |
| `Promise<string[]>` | A list of type `string` containing the IDs of required purposes. |

**Example**

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

```dart
await Didomi.getRequiredPurposeIds();
```

{% endtab %}
{% endtabs %}

## getRequiredVendors

Get the list of vendors that are required (determined from the configuration).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type                | Description                                              |
| ------------------- | -------------------------------------------------------- |
| `Promise<Vendor[]>` | A list of type `Vendor` containing the required vendors. |

**Example**

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

```dart
await Didomi.getRequiredVendors();
```

{% endtab %}
{% endtabs %}

## getRequiredVendorIds

Get the list of vendor IDs that are required (determined from the configuration).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type                | Description                                                     |
| ------------------- | --------------------------------------------------------------- |
| `Promise<string[]>` | A list of type `string` containing the IDs of required vendors. |

**Example**

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

```dart
await Didomi.getRequiredVendorIds();
```

{% endtab %}
{% endtabs %}

## getText

Method used to get a dictionary/map based on the key being passed. These keys and texts are extracted from the notice content, preferences content and the `texts` property specified in the `didomi_config.json` file as described here <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme#translatable-texts-for-custom-notices>.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name | Type   | Description                                           |
| ---- | ------ | ----------------------------------------------------- |
| key  | String | key associated to the dictionary that we want to get. |

**Returns**

| Type                             | Description                                                                                                                                                |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Dictionary/map: `Promise<any[]>` | Dictionary/map containing the translations for a specific key in different languages, with the form { "en:" "text in English", "fr": "texte en Français" } |

**Example**

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

```dart
await Didomi.getText("key");
```

{% endtab %}
{% endtabs %}

## getTranslatedText

Method used to get a translated text based on the key being passed.

The language and the source of this translated text will depend on the availability of the translation for the specific key.

The language being used will be either the selected language of the SDK (based on device Locale and other parameters) or the language specified by app developers as the default language being used by the SDK. The source can be either the `didomi_config.json` file, which can be either local or remote, or a file that is bundled within the SDK.

These are the attempts performed by the SDK to try to find a translation for the specific key:

* Get translated value in user locale (selected language) from `didomi_config.json` (either local or remote).
* Get translated value in default locale (from the config) from `didomi_config.json` (either local or remote).
* Get translated value in user locale (selected language) from the Didomi-provided translations (bundled within the Didomi SDK).
* Get translated value in default locale (from the config) from the Didomi-provided translations (bundled within the Didomi SDK).

If no translation can be found after these 4 attempts, the key will be returned.

App developers can provide these translated texts through the `didomi_config.json` file (locally or remotely) in 3 different ways:

* Custom texts for the consent notice: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-notice#texts>
* Custom texts for the preferences: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#text>
* Custom texts for custom notices: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/build-your-own-custom-notice#translatable-texts-for-custom-notices>

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name | Type   | Description                                                |
| ---- | ------ | ---------------------------------------------------------- |
| key  | string | key associated to the text that we want to get translated. |

**Returns**

Translated text.

**Example**

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

```dart
await Didomi.getTranslatedText("key");
```

{% endtab %}
{% endtabs %}

## getVendor

Get a vendor based on its ID.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name     | Type     | Description                      |
| -------- | -------- | -------------------------------- |
| vendorId | `string` | ID of the vendor we want to get. |

**Returns**

| Type           | Description                                                                           |
| -------------- | ------------------------------------------------------------------------------------- |
| `Promise<any>` | A `Vendor` with ID `vendorId` found in the array of required vendors, or `undefined`. |

`Vendor` interface is defined in `DidomiTypes.ts`

**Example**

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

```dart
await Didomi.getVendor("vendor-id") as Vendor;
```

{% endtab %}
{% endtabs %}

## hideNotice

Hide the consent notice.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```dart
await Didomi.hideNotice();
```

{% endtab %}
{% endtabs %}

## hidePreferences

Hide the preferences popup.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```javascript
await Didomi.hidePreferences();
```

{% endtab %}
{% endtabs %}

## initialize

**Deprecated**, use [initializeWithParameters](#initializewithparameters) instead.

Initialize the SDK. The initialization runs on a background thread to avoid blocking your UI. Use the [onReady](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/docs/cmp/mobile-sdk/android/reference/api.md#onready) function to know when the initialization is done and the SDK is ready to be used.

**Parameters**

{% hint style="warning" %}
The parameter `disableDidomiRemoteConfig` is deprecated, we strongly suggest you to create your notice from the console (see [Setup from the Console](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/docs/cmp/mobile-sdk/react-native/setup.md#from-the-console-recommended) for more information).
{% endhint %}

| Name                      | Type      | Optional | Description                                                                                                                                                                                                                                                                                                                                                                      |
| ------------------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| apiKey                    | `string`  | No       | Your API key                                                                                                                                                                                                                                                                                                                                                                     |
| localConfigurationPath    | `string`  | Yes      | The path to your local config file in your `assets/` folder. Defaults to `didomi_config.json` if undefined.                                                                                                                                                                                                                                                                      |
| remoteConfigurationPath   | `string`  | Yes      | The URL to a remote configuration file to load during initialization. When provided, the file at the URL will be downloaded and cached to be used instead of the local `assets/didomi_config.json`. If there is no Internet connection available and no previously cached file, the local file will be used as fallback.                                                         |
| providerId                | `string`  | Yes      | Your provider ID (if any). A provider ID is assigned when you work with Didomi through a third-party. If are not sure if you have one, set this to `undefined`.                                                                                                                                                                                                                  |
| disableDidomiRemoteConfig | `boolean` | Yes      | <p>Prevent the SDK from loading a remote configuration from the Didomi Console. Defaults to <code>false</code> (loading remote config).</p><p>Set this parameter to <code>false</code> to use a remote consent notice configuration loaded from the Didomi Console.</p><p>Set this parameter to <code>true</code> to disable loading configurations from the Didomi Console.</p> |
| languageCode              | `string`  | Yes      | Language in which the consent UI should be displayed. By default, the consent UI is displayed in the language configured in the device settings. This property allows you to override the default setting and specify a language to display the UI in. String containing the language code e.g.: "es", "fr", etc.                                                                |
| noticeId                  | `string`  | Yes      | Notice ID to load the configuration from. If provided, the SDK bypasses the app ID targeting and directly loads the configuration from the notice ID.                                                                                                                                                                                                                            |
| androidTvNoticeId         |           |          | Given the same binary is used for Android and Android TV, this property allows clients to provide the notice ID used for CTV.                                                                                                                                                                                                                                                    |
| androidTvEnabled          |           |          | Given the same binary is used for Android and Android TV, this property allows clients to specify if the app will run on Android TV or not.                                                                                                                                                                                                                                      |
| countryCode               |           |          | <p>Override user country code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user country.</p>                                                                                                                                                                                                               |
| regionCode                |           |          | <p>Override user region code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user region.</p><p>Ignored if countryCode is not set.</p>                                                                                                                                                                        |

**Returns**

`Promise<void>`

**Example**

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

```javascript
await Didomi.initialize(
    '465ca0b2-b96f-43b4-a864-f87e18d2fd38',
    undefined,
    undefined,
    undefined,
    false,
    undefined,
    undefined
  );
```

{% endtab %}
{% endtabs %}

## initializeWithParameters

Initialize the SDK. The initialization runs on a background thread to avoid blocking your UI. Use the [onReady](#onready) function to know when the initialization is done and the SDK is ready to be used.

**Parameter**

| Name                       | Type                         | Description                                                   |
| -------------------------- | ---------------------------- | ------------------------------------------------------------- |
| didomiInitializeParameters | `DidomiInitializeParameters` | Object containing properties required to initilalize the SDK. |

**Description for** `DidomiInitializeParameters`:

{% hint style="warning" %}
The parameter `disableDidomiRemoteConfig` is deprecated, we strongly suggest you to create your notice from the console (see [Setup from the Console](/cmp/mobile-sdk/flutter/setup#from-the-console-recommended) for more information).
{% endhint %}

| Name                      | Type      | Optional | Description                                                                                                                                                                                                                                                                                                                                                                      |
| ------------------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| apiKey                    | `string`  | No       | Your API key                                                                                                                                                                                                                                                                                                                                                                     |
| localConfigurationPath    | `string`  | Yes      | The path to your local config file in your `assets/` folder. Defaults to `didomi_config.json` if undefined.                                                                                                                                                                                                                                                                      |
| remoteConfigurationPath   | `string`  | Yes      | The URL to a remote configuration file to load during initialization. When provided, the file at the URL will be downloaded and cached to be used instead of the local `assets/didomi_config.json`. If there is no Internet connection available and no previously cached file, the local file will be used as fallback.                                                         |
| providerId                | `string`  | Yes      | Your provider ID (if any). A provider ID is assigned when you work with Didomi through a third-party. If are not sure if you have one, set this to `undefined`.                                                                                                                                                                                                                  |
| disableDidomiRemoteConfig | `boolean` | Yes      | <p>Prevent the SDK from loading a remote configuration from the Didomi Console. Defaults to <code>false</code> (loading remote config).</p><p>Set this parameter to <code>false</code> to use a remote consent notice configuration loaded from the Didomi Console.</p><p>Set this parameter to <code>true</code> to disable loading configurations from the Didomi Console.</p> |
| languageCode              | `string`  | Yes      | Language in which the consent UI should be displayed. By default, the consent UI is displayed in the language configured in the device settings. This property allows you to override the default setting and specify a language to display the UI in. String containing the language code e.g.: "es", "fr", etc.                                                                |
| noticeId                  | `string`  | Yes      | Notice ID to load the configuration from. If provided, the SDK bypasses the app ID targeting and directly loads the configuration from the notice ID.                                                                                                                                                                                                                            |
| androidTvNoticeId         | `string`  | Yes      | Given the same binary is used for Android and Android TV, this property allows clients to provide the notice ID used for CTV.                                                                                                                                                                                                                                                    |
| androidTvEnabled          | `boolean` | Yes      | Given the same binary is used for Android and Android TV, this property allows clients to specify if the app will run on Android TV or not.                                                                                                                                                                                                                                      |
| countryCode               | `string`  | Yes      | <p>Override user country code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user country.</p>                                                                                                                                                                                                               |
| regionCode                | `string`  | Yes      | <p>Override user region code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user region.</p><p>Ignored if countryCode is not set.</p>                                                                                                                                                                        |
| isUnderage                | `boolean` | No       | Whether the user is underage or not. This parameters can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).                                                                                                                                                                                                       |

**Returns**

`Promise<void>`

**Example**

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

```typescript
const parameters = {
  apiKey: '<API key>',
  noticeId: '<notice ID>'
};
await Didomi.initializeWithParameters(parameters);
```

{% endtab %}
{% endtabs %}

## isConsentRequired

Determine if consent is required for the user. This takes into account the location of the user and the configuration of the SDK:

* If your app is configured to apply GDPR to all users then this function always returns `true`.
* If your app is configured to apply GDPR to EU users only then this function returns `true` only if the user in the EU.

**Parameters**

No parameter.

**Returns**

`Promise<boolean>`

**Example**

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

```javascript
await Didomi.isConsentRequired();
```

{% endtab %}
{% endtabs %}

## isUserConsentStatusPartial

Determine if all consent information is available for the user.

This function returns `true` if and only if:

* Consent is required for the user (ie the user is in the EU or your tag is configured to apply GDPR to all users)
* At least one vendor is configured (if there is no vendor configured, this function always returns `false` as there is no consent to collect)
* We miss consent information for some vendors or purposes

If there is at least one piece of consent information missing for a single vendor/purpose, this function will return `true`. The consent notice is usually displayed when this function returns `true` although there is no guarantee of the direct mapping between the two.

An important edge case is when you add new vendors or if configured vendors ask for new purposes: the consent notice will be displayed again and this function will return `true` until the user has given or denied consent. Vendors that already had consent before will still operate normally as we only recollect consent for additional vendors/purposes.

**Parameters**

No parameter.

**Returns**

`Promise<boolean>`

**Example**

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

```javascript
await Didomi.isUserConsentStatusPartial();
```

{% endtab %}
{% endtabs %}

## isNoticeVisible

Check if the consent notice is currently displayed.

**Parameters**

No parameter.

**Returns**

`Promise<boolean>`

**Example**

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

```javascript
await Didomi.isNoticeVisible();
```

{% endtab %}
{% endtabs %}

## isPreferencesVisible

Check if the preferences popup is currently displayed.

**Parameters**

No parameter.

**Returns**

`Promise<boolean>`

**Example**

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

```javascript
await Didomi.isPreferencesVisible();
```

{% endtab %}
{% endtabs %}

## isReady

Check if the SDK is ready.

**Parameters**

No parameter.

**Returns**

`Promise<boolean>`

**Example**

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

```javascript
await Didomi.isReady();
```

{% endtab %}
{% endtabs %}

## isUserStatusPartial

Determine if the user has provided a choice for all vendors selected for the regulation and linked data processing.

This function returns `true` if the user has not expressed a choice for all the required vendors and data processing.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`Promise<boolean>`

**Example**

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

```javascript
await Didomi.isUserStatusPartial();
```

{% endtab %}
{% endtabs %}

## onError

Add a callback that will be called when the SDK initialization encounters an error. If the callback is added after the SDK initialization already failed, it will be called immediately.

**Parameters**

| Type               | Description                                                       |
| ------------------ | ----------------------------------------------------------------- |
| `(): Promise<any>` | A callback to run when the SDK initialization encounters an error |

**Returns**

Nothing

**Example**

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

```dart
Didomi.onError().then((err: any) => {
    console.log('Error: ' + err);
});
```

{% endtab %}
{% endtabs %}

## onReady

Add a callback that will be called when the SDK is ready (ie fully initialized). If the callback is added after the SDK initialization, it will be called immediately.

All calls to other functions of this API must only be made in a callback to the ready event to make sure that the SDK is initialized before it is used.

**Parameters**

| Type                | Description                             |
| ------------------- | --------------------------------------- |
| `(): Promise<void>` | A callback to run when the SDK is ready |

**Returns**

Nothing

**Example**

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

```javascript
Didomi.onReady().then(() => {
    // SDK is ready
});

```

{% endtab %}
{% endtabs %}

### openCurrentUserStatusTransaction

**Definition**

Create a `CurrentUserStatusTransaction` object.

This object provides mechanisms to stage updates to the user status regarding purposes and vendors, allowing for batch operations.

Updates made through its methods are queued and applied simultaneously to the user status only once the `commit` method of the returned object is called.

Additional details:

* The status of vendors and purposes whose IDs are not not specified through the methods provided by `CurrentUserStatusTransaction` are kept unchanged.
* Essential purposes are always set to enabled and can’t be updated by the methods provided by `CurrentUserStatusTransaction`.
* When the regulation applied for a user is `none`, the methods provided by `CurrentUserStatusTransaction` should not update the status of any vendor or purpose which will always remain as enabled. When the `commit` method is called it will return `false`.
* If the IDs that are passed through the methods provided by `CurrentUserStatusTransaction` don’t correspond to vendors or purposes required by the Notice Config, they will be ignored.

**Requires SDK to be initialized**

Yes.

#### Parameters

No parameter.

**Returns**

An`CurrentUserStatusTransaction` object.

**Description of a** `CurrentUserStatusTransaction` **object**

<table><thead><tr><th width="207">Method</th><th width="233">Parameters</th><th>Returns</th><th>Description</th></tr></thead><tbody><tr><td><code>enablePurpose</code></td><td><code>id</code> (<code>string</code>): ID of the purpose to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single purpose based on its ID.</td></tr><tr><td><code>enablePurposes</code></td><td><code>ids</code> (<code>string[]</code>): IDs of the purposes to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple purposes based on their IDs.</td></tr><tr><td><code>disablePurpose</code></td><td><code>id</code> (<code>string</code>): ID of the purpose to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single purpose based on its ID.</td></tr><tr><td><code>disablePurposes</code></td><td><code>ids</code> (<code>string[]</code>): IDs of the purposes to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple purposes based on their IDs.</td></tr><tr><td><code>enableVendor</code></td><td><code>id</code> (<code>string</code>): Didomi ID of the vendor to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single vendor based on its Didomi ID.</td></tr><tr><td><code>enableVendors</code></td><td><code>ids</code> (<code>string[]</code>): Didomi IDs of the vendors to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>disableVendor</code></td><td><code>id</code> (<code>string</code>): Didomi ID of the vendor to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single vendor based on its Didomi ID.</td></tr><tr><td><code>disableVendors</code></td><td><code>ids</code> (<code>string[]</code>): Didomi IDs of the vendors to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>commit</code></td><td>No parameters.</td><td><code>boolean</code>: <code>true</code> if user status has been updated, <code>false</code> otherwise.</td><td>Commit the changes that have been made through other methods.</td></tr></tbody></table>

#### Examples

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

```javascript
const transaction = Didomi.openCurrentUserStatusTransaction();

// enable a purpose
transaction.enablePurpose("cookies");
// enable purposes
transaction.enablePurpose(["cookies", "analytics"]);
// disable a purpose
transaction.enablePurpose("analytics");
// disable purposes
transaction.disablePurposes(["cookies", "analytics"]);
// enable a vendor
transaction.enableVendor("vendor-1");
// enable vendors
transaction.enableVendors(["vendor-1","vendor-2"]);
// disable a vendor
transaction.disableVendor("vendor-1");
// disable vendors
transaction.disableVendors(["vendor-1", "vendor-1"]);

// Chain multiple calls
transaction.enablePurpose("cookies").disablePurpose("analytics");

// Save user choices
let updated = await transaction.commit();
```

{% endtab %}
{% endtabs %}

## setLogLevel

Set the minimum level of messages to log. The SDK will not log messages under that level.

It uses a `number` argument which can have different values on Android and iOS platforms., for example:

iOS

| Level   | Value |
| ------- | ----- |
| `info`  | 1     |
| `debug` | 2     |
| `error` | 16    |
| `fault` | 17    |

Android

| Level   | Value |
| ------- | ----- |
| `debug` | 3     |
| `info`  | 4     |
| `warn`  | 5     |
| `error` | 6     |

For more information see

* [Logging for Android](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/docs/cmp/mobile-sdk/android/logging.md)
* [Logging for iOS](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/docs/cmp/mobile-sdk/ios/logging.md)

**Parameters**

| Name  | Type     | Description                       |
| ----- | -------- | --------------------------------- |
| level | `number` | Minimum level of messages to log. |

**Returns**

Nothing

**Example**

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

```javascript
// "Debug" log level is 2 on iOS, 3 on Android
let level = Platform.OS === 'ios' ? 2 : 3
Didomi.setLogLevel(level);
```

{% endtab %}
{% endtabs %}

## setupUI

Setup the SDK UI. By calling this method, the consent notice will be displayed once the SDK is ready and if consent should be collected. It does not show any view if consent was already collected or is not required.\
This method should be called only from your contexts where the application starts.

**Returns**

Nothing

**Example**

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

```dart
Didomi.setupUI();
```

{% endtab %}
{% endtabs %}

## setUserWithParameters

Set user information from the organization, with or without authentication parameters.

**Parameter:**

| Name                 | Type                   | Description                                          |
| -------------------- | ---------------------- | ---------------------------------------------------- |
| didomiUserParameters | `DidomiUserParameters` | Object containing properties required to set a user. |

***Description for*** `DidomiUserParameters`***:***

<table><thead><tr><th width="193">Name</th><th width="219">Type</th><th>Description</th></tr></thead><tbody><tr><td>userAuth</td><td><code>UserAuth</code></td><td>User authentication object. Can be either <code>UserAuthWithoutParams</code>, <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.</td></tr><tr><td>dcsUserAuth</td><td><code>UserAuthParams?</code></td><td>Optional. Dedicated user with encryption or hash used for Didomi Consent String signature. Can be either <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.<br>This parameter can only be used if you are using the Didomi Consent String feature (This feature is currently in beta version)</td></tr><tr><td>isUnderage</td><td><code>boolean?</code></td><td>Optional. Whether the user is underage or not. This parameters can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).</td></tr></tbody></table>

Parameters for `UserAuthWithoutParams` :

<table><thead><tr><th width="204">Name</th><th width="228">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>Organization ID to associate with the user.</td></tr></tbody></table>

Parameters for `UserAuthWithEncryptionParams` :

<table><thead><tr><th width="211">Name</th><th width="202">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>string</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>string</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>initializationVector</td><td><code>string</code></td><td>Initialization Vector used for encrypting the message.</td></tr><tr><td>expiration</td><td><code>number?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0).</td></tr></tbody></table>

Parameters for `UserAuthWithHashParams` :

<table><thead><tr><th width="212">Name</th><th width="205">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>string</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>string</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>digest</td><td><code>string</code></td><td>Digest used for representing the user ID</td></tr><tr><td>salt</td><td><code>string?</code></td><td>Optional. Salt used for computing the user ID.</td></tr><tr><td>expiration</td><td><code>number?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0)</td></tr></tbody></table>

**Returns**

Nothing

**Example**

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

```typescript

const userAuth = {
  id: '<user ID>',
  algorithm: 'aes-256-cbc',
  secretId: '<secret ID>',
  initializationVector: 'abcd',
  expiration: 3600
};

const dcsUserAuth = {
  id: '<user ID for DCS>',
  algorithm: 'aes-256-cbc',
  secretId: '<secret ID>',
  initializationVector: 'abcd',
  expiration: 3600
};

const parameters = {
  userAuth: userAuth,
  dcsUserAuth: dcsUserAuth
};

await Didomi.setUserWithParameters(parameters);
```

{% endtab %}
{% endtabs %}

## setUserWithParametersAndSetupUI

Set user information from the organization, with or without authentication parameters, and display the notice if required.

**Parameter:**

| Name                 | Type                   | Description                                          |
| -------------------- | ---------------------- | ---------------------------------------------------- |
| didomiUserParameters | `DidomiUserParameters` | Object containing properties required to set a user. |

***Description for*** `DidomiUserParameters`***:***

<table><thead><tr><th width="193">Name</th><th width="219">Type</th><th>Description</th></tr></thead><tbody><tr><td>userAuth</td><td><code>UserAuth</code></td><td>User authentication object. Can be either <code>UserAuthWithoutParams</code>, <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.</td></tr><tr><td>dcsUserAuth</td><td><code>UserAuthParams?</code></td><td>Optional. Dedicated user with encryption or hash used for Didomi Consent String signature. Can be either <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.<br>This parameter can only be used if you are using the Didomi Consent String feature (This feature is currently in beta version)</td></tr><tr><td>isUnderage</td><td><code>boolean?</code></td><td>Optional. Whether the user is underage or not. This parameters can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).</td></tr></tbody></table>

Parameters for `UserAuthWithoutParams` :

<table><thead><tr><th width="204">Name</th><th width="228">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>Organization ID to associate with the user.</td></tr></tbody></table>

Parameters for `UserAuthWithEncryptionParams` :

<table><thead><tr><th width="211">Name</th><th width="202">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>string</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>string</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>initializationVector</td><td><code>string</code></td><td>Initialization Vector used for encrypting the message.</td></tr><tr><td>expiration</td><td><code>number?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0).</td></tr></tbody></table>

Parameters for `UserAuthWithHashParams` :

<table><thead><tr><th width="212">Name</th><th width="205">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>string</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>string</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>digest</td><td><code>string</code></td><td>Digest used for representing the user ID</td></tr><tr><td>salt</td><td><code>string?</code></td><td>Optional. Salt used for computing the user ID.</td></tr><tr><td>expiration</td><td><code>number?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0)</td></tr></tbody></table>

**Returns**

Nothing

**Example**

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

```typescript

const userAuth = {
  id: '<user ID>',
  algorithm: 'aes-256-cbc',
  secretId: '<secret ID>',
  initializationVector: 'abcd',
  expiration: 3600
};

const dcsUserAuth = {
  id: '<user ID for DCS>',
  algorithm: 'aes-256-cbc',
  secretId: '<secret ID>',
  initializationVector: 'abcd',
  expiration: 3600
};

const parameters = {
  userAuth: userAuth,
  dcsUserAuth: dcsUserAuth
};

await Didomi.setUserWithParametersAndSetupUI(parameters);
```

{% endtab %}
{% endtabs %}

## clearUser

Remove custom user information from organization

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```javascript
await Didomi.clearUser();
```

{% endtab %}
{% endtabs %}

## showNotice

{% hint style="info" %}
In most cases this method should be called if the notice should be displayed in response to a user action (e.g.: select the privacy settings section within your app). By calling the setupUI method, the notice will be automatically displayed if required.
{% endhint %}

Show the consent notice. The consent notice actually only gets shown if needed (consent is required and we are missing consent information for some vendor or purpose).

**Returns**

Nothing

**Example**

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

```javascript
await Didomi.showNotice();
```

{% endtab %}
{% endtabs %}

## showPreferences

{% hint style="info" %}
In most cases this method should be called if you want to show the Preferences screen in response to a user action (the user pressing a "Consent Preferences" button in your app menu, for instance).
{% endhint %}

Show the Preferences view to the user. This method can be used to allow the user to update their preferences after the banner has been closed. We suggest adding a link/button/item that calls this method somewhere in your app, for example from your settings menu. By default, the Purposes view is displayed first. By calling this method, users will have the opportunity to modify the choices previously made.

**Parameters**

| Type              |                                                                                                                                                                                                                                                                                                                                  |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `view` (Optional) | <p>Defines which view is displayed to the user first between the purposes view or the vendors view.</p><p>Can be <code>purposes</code> , <code>sensitive-personal-information</code> or <code>vendors</code>.</p><p>If this parameter is not defined or contains an unexpected string, the purposes' view will be displayed.</p> |

**Returns**

Nothing

**Example**

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

```javascript
await Didomi.showPreferences();
await Didomi.showPreferences("purposes");
await Didomi.showPreferences("sensitive-personal-information");
await Didomi.showPreferences("vendors");
```

{% endtab %}
{% endtabs %}

## reset

Reset all the consent information for the current user. This will remove all consent information stored on the device by Didomi and will trigger re-collection of consent. The consent notice will be displayed again.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```java
await Didomi.reset();
```

{% endtab %}
{% endtabs %}

## setUserAgreeToAll

Report that the user has enabled consents and legitimate interests for all purposes and vendors configured for your app.

This function will log the user choice on our platform and close the notice.

Consent statuses for essential purposes are not stored.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

No parameter.

**Returns**

`Promise<boolean>`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```javascript
await Didomi.setUserAgreeToAll();
```

{% endtab %}
{% endtabs %}

## setUserDisagreeToAll

Report that the user has disabled consents and legitimate interests for all purposes and vendors configured for your app.

This function will log the user choice on our platform and close the notice.

Consent statuses for essential purposes are not stored.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

No parameter.

**Returns**

`Promise<boolean>`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```javascript
Didomi.setUserDisagreeToAll();
```

{% endtab %}
{% endtabs %}

## setCurrentUserStatus <a href="#setcurrentuserstatus" id="setcurrentuserstatus"></a>

**Definition**

Set the user status for purposes and vendors. This function will trigger events and API calls every time it is called (and the user status changes) so make sure to push all user choices at once and not one by one.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

Add the desired global status for each vendor and each purpose:

* the vendor status specified in this function will be reflected on the vendor’s layer.
  * vendor enabled : true → means the vendor is enabled in all the legal basis that this vendor uses.
  * vendor enabled : false → means the vendor is disabled in all the legal basis that this vendor uses
* the purposes status specified in this function will be reflected on the preferences layer.
  * purpose enabled : true → means the purpose is enabled in all the legal basis in which it’s defined.
  * purpose enabled : false → means the purpose is disabled in all the legal basis in which it’s defined.

**Returns**

`boolean`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```javascript
// Define purposes
const purposes = {
  purpose1: {
    id: 'purpose1',
    enabled: true,
  },
};

// Define vendors
const vendors = {
  vendor1: {
    id: 'vendor1',
    enabled: true,
  },
};

// Create the current user status object
const currentUserStatus = {
    purposes: purposes,
    vendors: vendors,
    user_id: '',
    created: '',
    updated: '',
    consent_string: '',
    addtl_consent: '',
    didomi_dcs: '',
    gpp_string: '',
    regulation: ''
  };

// Set the user status
const updated = await Didomi.setCurrentUserStatus(currentUserStatus);
```

{% endtab %}
{% endtabs %}

## setUserStatus

Set the global status for consent purposes, legitimate interest purposes, consent vendors, legitimate interest vendors. This function will trigger events and API calls every time it is called.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

| Name                  | Type      | Description                                                                                             |
| --------------------- | --------- | ------------------------------------------------------------------------------------------------------- |
| purposesConsentStatus | `boolean` | `true` if purposes on a consent basis should be enabled, `false` if they should be disabled             |
| purposesLIStatus      | `boolean` | `true` if purposes on a legitimate interest basis should be enabled, `false` if they should be disabled |
| vendorsConsentStatus  | `boolean` | `true` if vendors on a consent basis should be enabled, `false` if they should be disabled              |
| vendorsLIStatus       | `boolean` | `true` if vendors on a legitimate interest basis should be enabled, `false` if they should be disabled  |

**Returns**

`Promise<boolean>`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```javascript
// Disable everything except vendors legitimate interest
let result = await Didomi.setUserStatus(
    false, false, false, true
);
```

{% endtab %}
{% endtabs %}

## shouldConsentBeCollected

**Deprecated**, use [shouldUserStatusBeCollected](#shoulduserstatusbecollected) instead.

Determine if consent should be collected for the visitor. Returns `true` if consent is required for the current user and one of following two conditions is met:

* Consent has never been collected for this visitor yet
* New consents should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `false`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

**Parameters**

No parameter.

**Returns**

`Promise<boolean>`

**Example**

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

```dart
await Didomi.shouldConsentBeCollected()
```

{% endtab %}
{% endtabs %}

## shouldUserStatusBeCollected

Determine if user status (consent) should be collected for the user. Returns `true` if status is required for the current user and one of following two conditions is met:

* User status has never been collected for this user yet
* New user status should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `False`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`Promise<boolean>`

**Example**

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

```dart
await Didomi.shouldUserStatusBeCollected()
```

{% endtab %}
{% endtabs %}

## updateSelectedLanguage

Method used to update the selected language of the Didomi SDK and any property that depends on it.

In most cases this method doesn't need to be called. It would only be required for those apps that allow language change on-the-fly, i.e.: from within the app rather than from the device settings.

In order to update the language of the views displayed by the Didomi SDK, this method needs to be called before these views are displayed.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name         | Type     | Description                                                              |
| ------------ | -------- | ------------------------------------------------------------------------ |
| languageCode | `string` | string containing the 2-letter language code e.g. `en`, `es`, `fr`, etc. |

**Returns**

Nothing

**Example**

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

```java
Didomi.onReady().then(() => {
    Didomi.updateSelectedLanguage("fr");
});
```

{% endtab %}
{% endtabs %}


# Deprecated

## User Status

## getDisabledPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
The result of this method has been replaced by `getUserStatus().purposes.consent.disabled`.
{% endhint %}

## getDisabledPurposeIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
The result of this method has been replaced by `getUserStatus().purposes.consent.disabled`.
{% endhint %}

## getDisabledVendors

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
The result of this method has been replaced by `getUserStatus().vendors.consent.disabled`.
{% endhint %}

## getDisabledVendorIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
The result of this method has been replaced by `getUserStatus().vendors.consent.disabled`.
{% endhint %}

## getEnabledPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
The result of this method has been replaced by `getUserStatus().purposes.global.enabled`.
{% endhint %}

## getEnabledPurposeIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
The result of this method has been replaced by `getUserStatus().purposes.global.enabled`.
{% endhint %}

## getEnabledVendors

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
The result of this method has been replaced by `getUserStatus().vendors.consent.enabled`.
{% endhint %}

## getEnabledVendorIds

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
The result of this method has been replaced by `getUserStatus().vendors.consent.enabled`.
{% endhint %}

## getUserConsentStatusForPurpose

**Deprecated**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the purposeId in `getUserStatus().purposes.consent.enabled` or `getUserStatus().purposes.consent.disabled`.
{% endhint %}

Get the user consent status for a given purpose. You must also check that the user has given consent to a vendor before being able to load a vendor.

**Parameters**

| Name      | Type   | Description                                         |
| --------- | ------ | --------------------------------------------------- |
| purposeId | string | The ID of the purpose to check the user consent for |

**Returns**

A `Promise<boolean>` that indicates if the user has given consent or not to the specific purpose.

`undefined` is returned if the consent status is not known yet. From a GDPR perspective, you'll want to treat `undefined` as `false` (ie no consent given) but it is helpful to know that the user has not interacted with the consent UI yet so that you can subscribe to events and wait for consent information to be collected.

If consent is not required because GDPR does not apply to that user, this function will return `true`.

**Example**

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

```dart
await Didomi.getUserConsentStatusForPurpose("analytics");
```

{% endtab %}
{% endtabs %}

## getUserConsentStatusForVendor

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the vendorId in `getUserStatus().vendors.consent.enabled` or `getUserStatus().vendors.consent.disabled`.
{% endhint %}

## getUserConsentStatusForVendorAndRequiredPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the purposeId in `getUserStatus().vendors.global_consent.enabled` or `getUserStatus().vendors.global_consent.disabled`.
{% endhint %}

## getUserLegitimateInterestStatusForPurpose

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the purposeId in `getUserStatus().purposes.legitimate_interest.enabled` or `getUserStatus().purposes.legitimate_interest.disabled`.
{% endhint %}

## getUserLegitimateInterestForVendor

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the vendorId in `getUserStatus().vendors.legitimate_interest.enabled` or `getUserStatus().vendors.legitimate_interest.disabled`.
{% endhint %}

## getUserLegitimateInterestStatusForVendorAndRequiredPurposes

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the vendorId in `getUserStatus().vendors.global_legitimate_interest.enabled` or `getUserStatus().vendors.global_legitimate_interest.disabled`.
{% endhint %}

## getUserStatus

**Deprecated**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

Get all the user consent status.

**Returns**

A `UserStatus` object describing all the available and computed user information.

| Parameter                                        | Type      | Description                                                                                                                                                                                                                                                                                                                 |
| ------------------------------------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| purposes.global.disabled                         | string\[] | Computed sets/lists of disabled IDs of purposes that have been chosen by the user regarding the consent or legitimate interest Legal Basis.                                                                                                                                                                                 |
| purposes.global.enabled                          | string\[] | Computed sets/lists of enabled IDs of purposes that have been chosen by the user regarding the consent or legitimate interest Legal Basis. Purposes considered as essential will be part of the enabled IDs.                                                                                                                |
| purposes.consent.disabled                        | string\[] | Disabled IDs of purposes that have been explicitly chosen by the user regarding the consent Legal Basis.                                                                                                                                                                                                                    |
| purposes.consent.enabled                         | string\[] | Enabled IDs of purposes that have been explicitly chosen by the user regarding the consent Legal Basis.                                                                                                                                                                                                                     |
| purposes.legitimate\_interest.disabled           | string\[] | Disabled IDs of purposes that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.                                                                                                                                                                                                        |
| purposes.legitimate\_interest.enabled            | string\[] | Enabled IDs of purposes that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.                                                                                                                                                                                                         |
| purposes.essential                               | string\[] | IDs of purposes that are considered essential.                                                                                                                                                                                                                                                                              |
| vendors.global.disabled                          | string\[] | Computed sets/lists of disabled IDs of vendors that have been chosen by the user regarding the consent or legitimate interest Legal Basis. This takes into account the consent and legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled. |
| vendors.global.enabled                           | string\[] | Computed sets/lists of enabled IDs of vendors that have been chosen by the user regarding the consent or legitimate interest Legal Basis. This takes into account the consent and legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.  |
| vendors.global\_consent.disabled                 | string\[] | Computed sets/lists of disabled IDs of vendors that have been chosen by the user regarding the consent Legal Basis. This takes into account the consent required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.                                                |
| vendors.global\_consent.enabled                  | string\[] | Computed sets/lists of enabled IDs of vendors that have been chosen by the user regarding the consent Legal Basis. This takes into account the consent required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.                                                 |
| vendors.global\_legitimate\_interest.disabled    | string\[] | Computed sets/lists of disabled IDs of vendors that have been chosen by the user regarding the legitimate interest Legal Basis. This takes into account the legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.                        |
| vendors.global\_legitimate\_\_\_interest.enabled | string\[] | Computed sets/lists of enabled IDs of vendors that have been chosen by the user regarding the legitimate interest Legal Basis. This takes into account the legitimate interest required purposes linked to vendors. When computing this property, essential purposes will be considered as enabled.                         |
| vendors.consent.disabled                         | string\[] | Disabled IDs of vendors that have been explicitly chosen by the user regarding the consent Legal Basis.                                                                                                                                                                                                                     |
| vendors.consent.enabled                          | string\[] | Enabled IDs of vendors that have been explicitly chosen by the user regarding the consent Legal Basis.                                                                                                                                                                                                                      |
| vendors.legitimate\_interest.disabled            | string\[] | Disabled IDs of vendors that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.                                                                                                                                                                                                         |
| vendors.legitimate\_interest.enabled             | string\[] | Enabled IDs of vendors that have been explicitly chosen by the user regarding the legitimate interest Legal Basis.                                                                                                                                                                                                          |
| user\_id                                         | String    | Didomi user id.                                                                                                                                                                                                                                                                                                             |
| created                                          | String    | User choices creation date.                                                                                                                                                                                                                                                                                                 |
| updated                                          | String    | User choices update date.                                                                                                                                                                                                                                                                                                   |
| consent\_string                                  | String    | TFC consent as string.                                                                                                                                                                                                                                                                                                      |
| additional\_consent                              | String    | Additional consent for [Google Additional Consent Mode](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/docs/cmp/mobile-sdk/third-party-sdks.md#google-additional-consent-mode).                                                                                                                        |

**Example**

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

<pre class="language-dart"><code class="lang-dart"><strong>let userStatus = await Didomi.getUserStatus();
</strong>
// Enabled consent ids for vendors
let enabledVendorsConsentIds = userStatus.vendors.consent.enabled;
</code></pre>

{% endtab %}
{% endtabs %}

## getUserStatusForVendor

**Removed since version 2.0.0**, use [getCurrentUserStatus](/cmp/mobile-sdk/react-native/reference#getcurrentuserstatus) instead.

{% hint style="info" %}
Search the vendorId in `getUserStatus().vendors.global.enabled` or `getUserStatus().vendors.global.disabled`.
{% endhint %}

## setUser

**Deprecated**, use [setUserWithParameters](#setuserwithparameters) instead.

Set custom user information from organization

**Parameters**

Name

| Name               | Type     | Description                                |
| ------------------ | -------- | ------------------------------------------ |
| organizationUserId | `string` | Organization ID to associate with the user |

**Returns**

Nothing

**Example**

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

```javascript
await Didomi.setUser("e3222031-7c45-4f4a-8851-ffd57dbf0a2a");
```

{% endtab %}
{% endtabs %}

## setUser

**Deprecated**, use [setUserWithParameters](#setuserwithparameters) instead.

Set custom user information from organization, with optional authentication parameters.

Name

| Name                            | Type     | Optional | Description                                    |
| ------------------------------- | -------- | -------- | ---------------------------------------------- |
| organizationUserId              | `string` | No       | Organization ID to associate with the user     |
| organizationUserIdAuthAlgorithm | `string` | Yes      | Algorithm used for computing the digest        |
| organizationUserIdAuthSid       | `string` | Yes      | ID of the secret used for computing the digest |
| organizationUserIdAuthSalt      | `string` | Yes      | Salt used for computing the digest (optional)  |
| organizationUserIdAuthDigest    | `string` | Yes      | Digest of the organization user ID and secret  |

**Returns**

Nothing

**Example**

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

```javascript
await Didomi.setUser(
            "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
            "hash-md5",
            "secret_id",
            "salt",
            "098f6bcd4621d373cade4e832627b4f6"
);
```

{% endtab %}
{% endtabs %}

## setUserStatusSets

Set the user status for purposes and vendors. This function will trigger events and API calls every time it is called (and the user status changes) so make sure to push all user choices at once and not one by one.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

| Name                      | Type       | Description                                                                                                                                 |
| ------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| enabledConsentPurposeIds  | `string[]` | List of purpose IDs that the user has given consent to                                                                                      |
| disabledConsentPurposeIds | `string[]` | List of purpose IDs that the user has not given consent to                                                                                  |
| enabledLIPurposeIds       | `string[]` | List of purpose IDs that the user has allowed legitimate interest processing to                                                             |
| disabledLIPurposeIds      | `string[]` | List of purpose IDs that the user has disallowed legitimate interest processing to                                                          |
| enabledConsentVendorIds   | `string[]` | <p>List of vendor IDs that the user has given consent to.</p><p>Prefix custom vendor IDs with <code>c:</code>.</p>                          |
| disabledConsentVendorIds  | `string[]` | List of vendor IDs that the user has not given consent to                                                                                   |
| enabledLIVendorIds        | `string[]` | <p>List of vendor IDs that the user has allowed legitimate interest processing to.</p><p>Prefix custom vendor IDs with <code>c:</code>.</p> |
| disabledLIVendorIds       | `string[]` | List of vendor IDs that the user has not allowed legitimate interest processing to                                                          |

**Returns**

`Promise<boolean>`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```javascript
let result = await Didomi.setUserStatus(
    ["cookies", "advertising_personalization"],
    ["ad_delivery"],
    ["advertising_personalization"],
    ["ad_delivery"],
    ["123", "c:custom-vendor-id"],
    [],
    ["123", "c:custom-vendor-id"],
    []
);
```

{% endtab %}
{% endtabs %}


# Versions

Releases of the Didomi React-Native SDK are published and documented on our Github repository: <https://github.com/didomi/react-native/releases/>


# Flutter

This section will guide you through the required steps to setup the Didomi plugin for your Flutter applications on mobile devices (Android and iOS).

We are assuming that you have a Didomi account and an API key. If not, please go to our [website](https://www.didomi.io) and sign up for an account.

* [Setup](/cmp/mobile-sdk/flutter/setup): Import the Flutter plugin and configure it
* [Reference](/cmp/mobile-sdk/flutter/reference): API reference of the Flutter plugin
* [Versions](/cmp/mobile-sdk/flutter/versions): List of published versions


# Setup

## Add the SDK to your project

SDK is available from pub.dev: <https://pub.dev/packages/didomi_sdk/install>

Add the Didomi SDK dependency:

```bash
 $ flutter pub add didomi_sdk
```

{% hint style="info" %}
This will add a line like this to your package's pubspec.yaml (and run an implicit `dart pub get`):

```
dependencies:
  didomi_sdk: ^1.0.1
```

Afterwards, to update the dependency to the latest version, you can use the command

```
$ flutter pub upgrade
```

{% endhint %}

{% hint style="warning" %}
On Android, the error `Module was compiled with an incompatible version of Kotlin.` may occur. Make sure `ext.kotlinVersion` is set to `1.5.31` in `android/build.gradle`.
{% endhint %}

Then you can import project from your dart code:

```
import 'package:didomi_sdk/didomi_sdk.dart';
```

## Initialize the SDK

Once our SDK has been added to your project, you need to initialize it. The initialization process will prepare the SDK for interactions with the user and your application. It is important to launch the SDK initialization as soon as possible.

In your code, call the `initialize` method and pass your API key:

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

```dart
void initDidomi() {
  // Setup a listener to know when the SDK is ready
  DidomiSdk.onReady(() => {
    // The Didomi SDK is ready to go, you can call other functions
  });
  DidomiSdk.initializeWithParameters(
      DidomiInitializeParameters(apiKey:"<Your API key>",
      noticeId: "<Your Notice ID>"));
}
```

{% endtab %}
{% endtabs %}

�Keep in mind that the SDK initialization is an asynchronous process so you must avoid interacting with the `DidomiSdk` object until it is actually ready to handle your requests. Use the `onReady` event in dart to register a listener for the ready event.

Take a look at our [sample app](https://github.com/didomi/flutter/tree/main/example) to see how the setup is done.

## Use FlutterFragmentActivity instead of FlutterActivity (Android)

The Didomi SDK requires a FragmentActivity to display the notice. By default, Flutter projects use FlutterActivity which extends Activity: to use the SDK, it must be changed to a FlutterFragmentActivity instead.

The activity class should be present in folder `android/app/src/main/kotlin/` under the package name described in `android/app/src/main/AndroidManifest.xml`. Update it to use FlutterFragmentActivity.

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

```kotlin
package <Your package name>

import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity: FlutterFragmentActivity() {
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
Some sdk users reported a dependency conflict after updating the MainActivity class. They solved it by adding the dependency

`implementation "androidx.activity:activity-ktx:1.3.1"`

in the file `android/app/build.gradle` .
{% endhint %}

## �Setup the SDK UI

{% hint style="info" %}
Note: the `setupUI` method should be called only from your contexts where the application starts.

You do not need to call `onReady`, `isReady` or `shouldConsentBeCollected` before calling `setupUI` because they are called internally. Therefore, by calling this method the consent notice will be displayed if it is required and only once the SDK is ready.
{% endhint %}

Call the `setupUI` function of the SDK in your context where the application starts:

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

```dart
class _MyHomePageState extends State<MyHomePage> {

  @override
  void initState() {
    super.initState();
    DidomiSdk.setupUI();
  }
}
```

{% endtab %}
{% endtabs %}

### �Deep links

If you are using deep links or have multiple pages in your Flutter app, make sure that the `setupUI` function is called on every context that the user can launch the app on.\
\
This will ensure that consent is always collected as needed and there is no path where the user can launch the app without consent being collected. If `setupUI` is missing in some entry points, you will see lower consent rates as users will be using the app without giving consent.

## Configure the SDK

We support three options for configuring the UI and the behavior of the SDK:

* [Didomi Console](#from-the-console-recommended): the SDK is configured remotely from the Didomi Console
* [Local file](#local-file): the SDK is configured from a `didomi_config.json` file embedded in your app package
* [Remote file](#remote-file): the SDK is configured from a remote `didomi_config.json` file

### From the Console (Recommended)

You can configure the consent notice in your app by creating a notice in your Didomi Console. It will automatically be linked to your app through your API Key and, optionally, your notice id. You can access the Didomi console [here](http://console.didomi.io).

In order to enable this option, make sure to pass the `disableDidomiRemoteConfig` parameter as `false` (default value) when calling the initialize method as shown below.

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

```dart
  DidomiSdk.initializeWithParameters(
      DidomiInitializeParameters(
          apiKey: "<Your API key>",
          disableDidomiRemoteConfig: false,
          noticeId: "<Your notice ID>"
      )
  );
```

{% endtab %}
{% endtabs %}

The SDK will automatically use the remote configuration hosted by Didomi and cache it locally. The cached version is refreshed every 60 minutes.\
If there is no connection available to download the remote configuration and no locally cached version, the SDK will try to use a local `didomi_config.json` configuration file as a fallback. See the Local option below for more information on how to configure the SDK through a local configuration file.

### Local file (Deprecated)

{% hint style="danger" %}
Using a local file automatically disables the TCF integration.\
If your app uses the TCF, you must use a configuration from the Didomi Console.
{% endhint %}

{% hint style="warning" %}
Using a local file will prevent you to support multiple regulations.
{% endhint %}

With this option, you create your own SDK configuration file and embed it in your app package.

The SDK behavior is configured in a `didomi_config.json` file that must be placed in the Android and iOS folders of your project.

You can create a file with the following content to get started:

{% tabs %}
{% tab title="didomi\_config.json" %}

```javascript
{
    "app": {
        "name": "My App Name",
        "privacyPolicyURL": "http://www.website.com/privacy",
        "vendors": {
            "iab": {
                "all": true
            }
        },
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    }
}
```

{% endtab %}
{% endtabs %}

For Android, the configuration file must be placed in the assets folder of the Android platform code (in this example: `android/app/src/main/assets`)

![](/files/-MbGmSdvukwn0MZhhmA7)

For iOS, the configuration file must be placed in the `Resources` group (make sure `project.pbxproj` file is updated)

![](/files/-MbGmtiQFItKukiShtRE)

You also need to disable loading the remote configuration to ensure that only the local file is loaded and that no HTTP request is sent. Update your [`initialize`](/cmp/mobile-sdk/flutter/reference#initialize) call to set the `disableDidomiRemoteConfig` parameter to `true`:

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

```dart
 DidomiSdk.initializeWithParameters(
      DidomiInitializeParameters(
            apiKey: "<Your API key>",
            disableDidomiRemoteConfig: true,
            noticeId: "<Your notice ID>"
      )
);
```

{% endtab %}
{% endtabs %}

Your SDK is now setup. [Read the Getting started section](/cmp/mobile-sdk/consent-notice/getting-started) of our Mobile SDKs to learn more about how to configure it to match your app UI and requirements.

### Remote file

{% hint style="info" %}
Enabling this option will prevent the configuration from being loaded from the Didomi Console.
{% endhint %}

You can provide a remote URL for the SDK to download the `didomi_config.json` configuration file from. That allows you to update the SDK configuration without having to re-publish you mobile application.

When that configuration is enabled, the SDK will automatically use the remote configuration and cache it locally. The cached version is refreshed every 60 minutes. If there is no connection available to download the remote file and no locally cached version, the SDK will try to use the local `didomi_config.json` (described above) as a fallback.

To enable that option, change your call to [initialize](/cmp/mobile-sdk/flutter/reference#initialize) to provide the remote file URL:�

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

```dart
 DidomiSdk.initializeWithParameters(
      DidomiInitializeParameters(
            apiKey: "<Your API key>",
            remoteConfigurationURL: "http://www.website.com/didomi_config.json",
            disableDidomiRemoteConfig: false
      )
);

```

{% endtab %}
{% endtabs %}

Also see the [reference documentation of the initialize function](/cmp/mobile-sdk/flutter/reference#initialize) for more information.


# Reference

This section is a comprehensive reference of the methods and events exposed by the Flutter SDK that you can leverage in your application.

These methods are accessible in the `DidomiSdk` class. Also make sure to always call the SDK after it is fully initialized (see [onReady](#onready)).

## addEventListener

Add an event listener to catch events triggered by the SDK. Events listeners allow you to react to different events of interest. This function is safe to call before the `ready` event has been triggered.

**Requires SDK to be initialized**

No.

**Parameters**

| Name          | Type            | Description                                       |
| ------------- | --------------- | ------------------------------------------------- |
| eventListener | `EventListener` | The event listener. An instance of`EventListener` |

**Returns**

Nothing

**Example**

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

```dart
EventListener didomiListener = EventListener();

// SDK lifecycle events
didomiListener.onReady = () {
  onEvent("SDK Ready");
};
didomiListener.onError = (message) {
  onEvent("Error : $message");
};

// Notice events
didomiListener.onShowNotice = () {
  onEvent("Notice displayed");
};
didomiListener.onHideNotice = () {
  onEvent("Notice hidden");
};
didomiListener.onShowPreferences = () {
  onEvent("Preferences screen displayed");
};
didomiListener.onHidePreferences = () {
  onEvent("Preferences screen hidden");
};
didomiListener.onNoticeClickAgree = () {
  onEvent("Click Agree from Notice");
};
didomiListener.onNoticeClickDisagree = () {
  onEvent("Click Disagree from Notice");
};
didomiListener.onNoticeClickViewVendors = () {
  onEvent("Click View vendors from Notice");
};
didomiListener.onNoticeClickViewSPIPurposes = () {
  onEvent("Click View SPI from Notice");
};
didomiListener.onNoticeClickMoreInfo = () {
  onEvent("Click More info from Notice");
};
didomiListener.onNoticeClickPrivacyPolicy = () {
  onEvent("Click Privacy policy from Notice");
};

// Preferences screen events
didomiListener.onPreferencesClickAgreeToAll = () {
  onEvent("Click Agree to all from Preferences");
};
didomiListener.onPreferencesClickDisagreeToAll = () {
  onEvent("Click Disagree to all from Preferences");
};
didomiListener.onPreferencesClickPurposeAgree = (purposeId) {
  onEvent("Click Agree to purpose $purposeId from Preferences");
};
didomiListener.onPreferencesClickPurposeDisagree = (purposeId) {
  onEvent("Click Disagree to purpose $purposeId from Preferences");
};
didomiListener.onPreferencesClickCategoryAgree = (categoryId) {
  onEvent("Click Agree to category $categoryId from Preferences");
};
didomiListener.onPreferencesClickCategoryDisagree = (categoryId) {
  onEvent("Click Disagree to category $categoryId from Preferences");
};
didomiListener.onPreferencesClickViewVendors = () {
  onEvent("Click View vendors from Preferences");
};
didomiListener.onPreferencesClickViewSPIPurposes = () {
  onEvent("Click View SPI from Preferences");
};
didomiListener.onPreferencesClickSaveChoices = () {
  onEvent("Click Save choices from Preferences");
};
didomiListener.onPreferencesClickAgreeToAllPurposes = () {
  onEvent("Click Agree to all purposes from Preferences");
};
didomiListener.onPreferencesClickDisagreeToAllPurposes = () {
  onEvent("Click Disagree to all purposes from Preferences");
};
didomiListener.onPreferencesClickResetAllPurposes = () {
  onEvent("Click Reset all purposes from Preferences");
};

// Vendors screen events
didomiListener.onPreferencesClickVendorAgree = (vendorId) {
  onEvent("Click Agree to vendor $vendorId from Preferences");
};
didomiListener.onPreferencesClickVendorDisagree = (vendorId) {
  onEvent("Click Disagree to vendor $vendorId from Preferences");
};
didomiListener.onPreferencesClickVendorSaveChoices = () {
  onEvent("Click Save vendor choices from Preferences");
};
didomiListener.onPreferencesClickViewPurposes = () {
  onEvent("Click View purposes from Preferences");
};
didomiListener.onPreferencesClickAgreeToAllVendors = () {
  onEvent("Click Agree to all vendors from Preferences");
};
didomiListener.onPreferencesClickDisagreeToAllVendors = () {
  onEvent("Click Disagree to all vendors from Preferences");
};

// SPI screen events
didomiListener.onPreferencesClickSPIPurposeAgree = (purposeId) {
  onEvent("Click Agree to SPI purpose $purposeId from Preferences");
};
didomiListener.onPreferencesClickSPIPurposeDisagree = (purposeId) {
  onEvent("Click Disagree to SPI purpose $purposeId from Preferences");
};
didomiListener.onPreferencesClickSPICategoryAgree = (categoryId) {
  onEvent("Click Agree to SPI category $categoryId from Preferences");
};
didomiListener.onPreferencesClickSPICategoryDisagree = (categoryId) {
  onEvent("Click Disagree to SPI category $categoryId from Preferences");
};
didomiListener.onPreferencesClickSPIPurposeSaveChoices = () {
  onEvent("Click Save SPI choices from Preferences");
};

// Consent events
didomiListener.onConsentChanged = () {
  onEvent("Consent has changed");
};
didomiListener.onSyncReady = (event) {
  onEvent("Sync is complete. Status applied: ${event.statusApplied}");
  
  if (event.statusApplied) {
    print("User status has been applied locally.");
  }
  if (event.syncAcknowledged()) {
    print("sync.acknowledged API event has been triggered successfully.");
  }
};
didomiListener.onSyncDone = (organizationUserId) {
  onEvent("Sync has been done for user $organizationUserId");
};
didomiListener.onSyncError = (error) {
  onEvent("Sync failed with error $error");
};

// Language change events
didomiListener.onLanguageUpdated = (languageCode) {
  onEvent("Language has changed ($languageCode)");
};
didomiListener.onLanguageUpdateFailed = (reason) {
  onEvent("Language has not changed: $reason");
};

DidomiSdk.addEventListener(didomiListener);
```

{% endtab %}
{% endtabs %}

**Event types**

The following events are supported by the Didomi SDK:

| Method                                  | Description                                                                                                                                                                                                                               |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| onReady                                 | When the SDK is ready.                                                                                                                                                                                                                    |
| onError                                 | When the SDK encountered an error (`message` provided as parameter).                                                                                                                                                                      |
| onShowNotice                            | When the consent notice gets displayed. If you have disabled our default consent notices to replace them with your own, you need to show your custom notice when this event gets triggered.                                               |
| onHideNotice                            | When the consent notice is hidden. If you have disabled our default consent notice to replace it with your own, you need to hide your custom notice when this event gets triggered.                                                       |
| onShowPreferences                       | When the preferences screen is displayed.                                                                                                                                                                                                 |
| onHidePreferences                       | When the preferences screen is hidden.                                                                                                                                                                                                    |
| onNoticeClickAgree                      | When user clicks on agree on the notice.                                                                                                                                                                                                  |
| onNoticeClickDisagree                   | When user clicks on disagree on the notice.                                                                                                                                                                                               |
| onNoticeClickViewVendors                | When user clicks on partners on the notice.                                                                                                                                                                                               |
| onNoticeClickViewSPIPurposes            | When user clicks on view Sensitive Personal Information on the preferences popup.                                                                                                                                                         |
| onNoticeClickMoreInfo                   | When user clicks on learn more on the notice.                                                                                                                                                                                             |
| onNoticeClickPrivacyPolicy              | When user clicks on privacy policy on the notice.                                                                                                                                                                                         |
| onPreferencesClickAgreeToAll            | When user clicks on agree to all on the preferences popup.                                                                                                                                                                                |
| onPreferencesClickDisagreeToAll         | When user clicks on disagree to all on the preferences popup.                                                                                                                                                                             |
| onPreferencesClickPurposeAgree          | When user agree to a purpose on the preferences popup (`purposeId` provided as parameter).                                                                                                                                                |
| onPreferencesClickPurposeDisagree       | When user disagree to a purpose on the preferences popup (`purposeId` provided as parameter).                                                                                                                                             |
| onPreferencesClickCategoryAgree         | When user agree to a category on the preferences popup (`categoryId` provided as parameter).                                                                                                                                              |
| onPreferencesClickCategoryDisagree      | When user disagree to a category on the preferences popup (`categoryId` provided as parameter).                                                                                                                                           |
| onPreferencesClickViewVendors           | When user clicks on view vendors on the preferences popup.                                                                                                                                                                                |
| onPreferencesClickViewSPIPurposes       | When user clicks on view Sensitive Personal Information on the preferences popup.                                                                                                                                                         |
| onPreferencesClickSaveChoices           | When user saves his choice on the preferences popup.                                                                                                                                                                                      |
| onPreferencesClickAgreeToAllPurposes    | When user flips ON all purposes switch on the preferences popup.                                                                                                                                                                          |
| onPreferencesClickDisagreeToAllPurposes | When user flips OFF all purposes switch on the preferences popup.                                                                                                                                                                         |
| onPreferencesClickResetAllPurposes      | When user reset all purposes switch on the preferences popup.                                                                                                                                                                             |
| onPreferencesClickVendorAgree           | When user agree to a vendor on the preferences popup (`vendorId` provided as parameter).                                                                                                                                                  |
| onPreferencesClickVendorDisagree        | When user disagree to a vendor on the preferences popup (`vendorId` provided as parameter).                                                                                                                                               |
| onPreferencesClickVendorSaveChoices     | When user saves his choice on the vendors view on the preferences popup.                                                                                                                                                                  |
| onPreferencesClickViewPurposes          | When user clicks on view purposes on the preferences popup.                                                                                                                                                                               |
| onPreferencesClickAgreeToAllVendors     | When user flips ON all vendors switch on the preferences popup.                                                                                                                                                                           |
| onPreferencesClickDisagreeToAllVendors  | When user flips OFF all vendors switch on the preferences popup.                                                                                                                                                                          |
| onPreferencesClickSPIPurposeAgree       | When user agree to a purpose on the Sensitive Personal Information view from the preferences popup (`purposeId` provided as parameter).                                                                                                   |
| onPreferencesClickSPIPurposeDisagree    | When user disagree to a purpose on the Sensitive Personal Information view from the preferences popup (`purposeId` provided as parameter).                                                                                                |
| onPreferencesClickSPICategoryAgree      | When user agree to a category on the Sensitive Personal Information view from the preferences popup (`categoryId` provided as parameter).                                                                                                 |
| onPreferencesClickSPICategoryDisagree   | When user disagree to a category on the Sensitive Personal Information view from preferences popup (`categoryId` provided as parameter).                                                                                                  |
| onPreferencesClickSPIPurposeSaveChoices | When user saves his choice on the Sensitive Personal Information view from preferences popup.                                                                                                                                             |
| onConsentChanged                        | When a consent is given or withdrawn by the user. Only triggered when the consent status actually changes (ie if the user saves consents without adding/removing any consent then this does not get called).                              |
| onSyncReady                             | <p>When the consent synchronization process is complete.</p><p><code>event</code> parameter is a <code>SyncReadyEvent</code> object that contains the fields <code>statusApplied</code> and <code>syncAcknowledged</code> (see below)</p> |
| `SyncReadyEvent.statusApplied`          | Whether the user status was applied locally                                                                                                                                                                                               |
| `SyncReadyEvent.syncAcknowledged`       | Function that triggers a `sync.acknowledged` API event when called. It returns `true` if the API event was sent successfully.                                                                                                             |
| onSyncDone                              | When the consent synchronization is successful (`organizationUserId` provided as parameter).                                                                                                                                              |
| onSyncError                             | When the consent synchronization has failed (`error` provided as parameter).                                                                                                                                                              |
| onLanguageUpdated                       | When the language has changed (`languageCode` provided as parameter).                                                                                                                                                                     |
| onLanguageUpdateFailed                  | When the language change has failed (`reason` provided as parameter).                                                                                                                                                                     |

## addVendorStatusListener <a href="#addvendorstatuslistener" id="addvendorstatuslistener"></a>

Listen for changes on the user status linked to a specific vendor.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type                     | Description                                                                                                                                                                   |
| -------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendorId | `String`                 | <p>The ID of the vendor for which we want to start listening for changes.</p><p>This ID should be the ID provided by Didomi, which doesn't contain prefixes.</p>              |
| listener | `Function(VendorStatus)` | Method that will be executed whenever changes are detected on the specified vendor. When this callback is executed, the status linked to the specified vendor will be passed. |

**Returns**

Nothing

**Example**

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

```dart
DidomiSdk.addVendorStatusListener("vendorId", (vendorStatus) => {
    print("${vendorStatus.id} status has changed: ${vendorStatus.enabled}")
});
```

{% endtab %}
{% endtabs %}

## removeVendorStatusListener <a href="#removevendorstatuslistener" id="removevendorstatuslistener"></a>

Stop listening for changes on the user status linked to a specific vendor.

**Requires SDK to be initialized**

No.

**Parameters**

| Name     | Type     | Description                                                                                                                                                     |
| -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendorId | `String` | <p>The ID of the vendor for which we want to stop listening for changes.</p><p>This ID should be the ID provided by Didomi, which doesn't contain prefixes.</p> |

**Returns**

Nothing

**Example**

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

```dart
DidomiSdk.removeVendorStatusListener('vendorId');
```

{% endtab %}
{% endtabs %}

## getJavaScriptForWebView

Get JavaScript to embed into a WebView to pass the consent status from the app to the Didomi Web SDK embedded into the WebView.

Inject the returned tag into a WebView with `evaluateJavaScript`.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type             | Description                           |
| ---------------- | ------------------------------------- |
| `Future<String>` | JavaScript code to embed in a WebView |

**Example**

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

```dart
await DidomiSdk.javaScriptForWebView;
```

{% endtab %}
{% endtabs %}

## getQueryStringForWebView

Get a query string parameter to append to the URL of a WebView to pass the consent status from the app to the Didomi Web SDK embedded into the WebView.

Read our article on [sharing consent with WebViews](/cmp/mobile-sdk/share-consent-with-webviews) for more information.

{% hint style="info" %}
This method is currently available on Android platform only. Calling `getQueryStringForWebView` on iOS platform will return an empty String.
{% endhint %}

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type             | Description                                                                                                                                                                            |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Future<String>` | Query string parameter with the format `didomiConfig.user.externalConsent.value=...`. It can be appended to your URL after a `?` or a `&` if your URL already contains a query string. |

**Example**

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

```dart
await DidomiSdk.queryStringForWebView;
```

{% endtab %}
{% endtabs %}

## getPurpose

Get a purpose based on its ID.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name      | Type     | Description                       |
| --------- | -------- | --------------------------------- |
| purposeId | `String` | ID of the purpose we want to get. |

**Returns**

| Type               | Description                                                                         |
| ------------------ | ----------------------------------------------------------------------------------- |
| `Future<Purpose?>` | A `Purpose` with ID `purposeId` found in the array of required purposes, or `null`. |

**Example**

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

```dart
await DidomiSdk.getPurpose("purpose-id");
```

{% endtab %}
{% endtabs %}

## getRequiredPurposes

Get the list of purpose that are required (automatically determined from the list of required vendors).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type                    | Description                                                |
| ----------------------- | ---------------------------------------------------------- |
| `Future<List<Purpose>>` | A list of type `Purpose` containing the required purposes. |

**Example**

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

```dart
await DidomiSdk.requiredPurposes;
```

{% endtab %}
{% endtabs %}

## getRequiredPurposeIds

Get the list of purpose IDs that are required (automatically determined from the list of required vendors).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type                   | Description                                                      |
| ---------------------- | ---------------------------------------------------------------- |
| `Future<List<String>>` | A list of type `String` containing the IDs of required purposes. |

**Example**

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

```dart
await DidomiSdk.requiredPurposeIds;
```

{% endtab %}
{% endtabs %}

## getRequiredVendors

Get the list of vendors that are required (determined from the configuration).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type                   | Description                                              |
| ---------------------- | -------------------------------------------------------- |
| `Future<List<Vendor>>` | A list of type `Vendor` containing the required vendors. |

**Example**

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

```dart
await DidomiSdk.requiredVendors;
```

{% endtab %}
{% endtabs %}

## getRequiredVendorIds

Get the list of vendor IDs that are required (determined from the configuration).

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

| Type                   | Description                                                     |
| ---------------------- | --------------------------------------------------------------- |
| `Future<List<String>>` | A list of type `String` containing the IDs of required vendors. |

**Example**

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

```dart
await DidomiSdk.requiredVendorIds;
```

{% endtab %}
{% endtabs %}

## getText

Method used to get a dictionary/map based on the key being passed. These keys and texts are extracted from the notice content, preferences content and the `texts` property specified in the `didomi_config.json` file as described here <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-theme#translatable-texts-for-custom-notices>.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name | Type   | Description                                           |
| ---- | ------ | ----------------------------------------------------- |
| key  | String | key associated to the dictionary that we want to get. |

**Returns**

| Type                                          | Description                                                                                                                                                 |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Dictionary/map: `Future<Map<String, String>>` | Dictionary/map containing the translations for an specific key in different languages, with the form { "en:" "text in English", "fr": "texte en Français" } |

**Example**

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

```dart
await DidomiSdk.getText("key");
```

{% endtab %}
{% endtabs %}

## getTranslatedText

Method used to get a translated text based on the key being passed.

The language and the source of this translated text will depend on the availability of the translation for the specific key.

The language being used will be either the selected language of the SDK (based on device Locale and other parameters) or the language specified by app developers as the default language being used by the SDK. The source can be either the `didomi_config.json` file, which can be either local or remote, or a file that is bundled within the SDK.

These are the attempts performed by the SDK to try to find a translation for the specific key:

* Get translated value in user locale (selected language) from `didomi_config.json` (either local or remote).
* Get translated value in default locale (from the config) from `didomi_config.json` (either local or remote).
* Get translated value in user locale (selected language) from the Didomi-provided translations (bundled within the Didomi SDK).
* Get translated value in default locale (from the config) from the Didomi-provided translations (bundled within the Didomi SDK).

If no translation can be found after these 4 attempts, the key will be returned.

App developers can provide these translated texts through the `didomi_config.json` file (locally or remotely) in 3 different ways:

* Custom texts for the consent notice: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-notice#texts>
* Custom texts for the preferences: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup#text>
* Custom texts for custom notices: <https://developers.didomi.io/cmp/mobile-sdk/consent-notice/build-your-own-custom-notice#translatable-texts-for-custom-notices>

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name | Type   | Description                                                |
| ---- | ------ | ---------------------------------------------------------- |
| key  | String | key associated to the text that we want to get translated. |

**Returns**

Translated text.

**Example**

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

```dart
await DidomiSdk.getTranslatedText("key");
```

{% endtab %}
{% endtabs %}

## getCurrentUserStatus

Exposes the user status for the current regulation that applies.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameters.

**Returns**

The user status containing the computed global status for Vendors and purposes:

* A vendor's global status is enabled, if and only if:
  * the vendor is enabled directly in the vendors layer in all legal basis
  * **AND** all its related purposes are enabled or essential.
* A purpose's global status is enabled in one of the two conditions:
  * the purpose is enabled for all the legal basis that it is configured for.
  * **OR** when the purpose is essential.

| Parameter         | Type     | Description                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| didomiDcs         | `string` | Didomi Consent String that stores end-user choices for custom and Google ATP vendors, and custom and global purposes across all regulations. [Click here](/cmp/didomi-consent-string) for more information.                                                                                                                                                                                                                             |
| vendors           | `object` | <ul><li>Dictionary that maps the ID of a vendor to an object representing its status.</li><li>The IDs used in this dictionary correspond to the Didomi IDs i.e.: without the <code>c:</code> or any other prefix.</li><li>Vendors with undefined user status are included in the response with <code>enabled: false.</code></li><li>Vendors with ONLY essential purposes are automatically set with <code>enable: true</code></li></ul> |
| purposes          | `object` | <ul><li>Dictionary that maps the ID of a purpose to an object representing its status.</li><li>Purposes with undefined user status are included in the response with <code>enabled: false.</code></li><li>Essential purposes are automatically set with <code>enable: true</code></li></ul>                                                                                                                                             |
| regulation        | `String` | <ul><li>Representation of the current regulation as a <code>Regulation</code> enum value, such as <code>GDPR</code>, <code>CCPA</code>, <code>CPRA</code>, or <code>NONE</code>.</li><li>Note that some regulations present as enum values are not available yet.</li></ul>                                                                                                                                                             |
| userId            | `String` | Didomi user id.                                                                                                                                                                                                                                                                                                                                                                                                                         |
| created           | `String` | User choices creation date.                                                                                                                                                                                                                                                                                                                                                                                                             |
| updated           | `String` | User choices update date.                                                                                                                                                                                                                                                                                                                                                                                                               |
| consentString     | `String` | TCF consent as string                                                                                                                                                                                                                                                                                                                                                                                                                   |
| additionalConsent | `String` | Additional consent.                                                                                                                                                                                                                                                                                                                                                                                                                     |
| gppString         | `String` | GPP string.                                                                                                                                                                                                                                                                                                                                                                                                                             |

**Throws**

<table><thead><tr><th width="334">Type</th><th>Description</th></tr></thead><tbody><tr><td>DidomiNotReadyException</td><td>Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the <code>onReady</code> method.</td></tr></tbody></table>

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

```dart
await DidomiSdk.getCurrentUserStatus();
```

{% endtab %}
{% endtabs %}

## getVendor

Get a vendor based on its ID.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name     | Type     | Description                      |
| -------- | -------- | -------------------------------- |
| vendorId | `String` | ID of the vendor we want to get. |

**Returns**

| Type              | Description                                                                      |
| ----------------- | -------------------------------------------------------------------------------- |
| `Future<Vendor?>` | A `Vendor` with ID `vendorId` found in the array of required vendors, or `null`. |

**Example**

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

```dart
await DidomiSdk.getVendor("vendor-id");
```

{% endtab %}
{% endtabs %}

## hideNotice

Hide the consent notice.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```dart
await DidomiSdk.hideNotice();
```

{% endtab %}
{% endtabs %}

## hidePreferences

Hide the preferences popup.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```dart
await DidomiSdk.hidePreferences();
```

{% endtab %}
{% endtabs %}

## initializeWithParameters

Initialize the SDK. The initialization runs on a background thread to avoid blocking your UI. Use the [onReady](/cmp/mobile-sdk/android/reference/api#onready) function to know when the initialization is done and the SDK is ready to be used.

**Parameter**

| Name                       | Type                         | Description                                                   |
| -------------------------- | ---------------------------- | ------------------------------------------------------------- |
| didomiInitializeParameters | `DidomiInitializeParameters` | Object containing properties required to initilalize the SDK. |

**Description for** `DidomiInitializeParameters`:

{% hint style="warning" %}
The parameter `disableDidomiRemoteConfig` is deprecated, we strongly suggest you to create your notice from the console (see [Setup from the Console](/cmp/mobile-sdk/flutter/setup#from-the-console-recommended) for more information).
{% endhint %}

<table data-header-hidden><thead><tr><th width="260.3333333333333">Name</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Type</td><td>Description</td></tr><tr><td>apiKey</td><td><code>String</code></td><td>Your API key</td></tr><tr><td>localConfigurationPath</td><td><code>String?</code></td><td>Optional. The path to your local config file in your <code>assets/</code> folder. Defaults to <code>didomi_config.json</code> if null.</td></tr><tr><td>remoteConfigurationPath</td><td><code>String?</code></td><td>Optional. The URL to a remote configuration file to load during initialization. When provided, the file at the URL will be downloaded and cached to be used instead of the local <code>assets/didomi_config.json</code>. If there is no Internet connection available and no previously cached file, the local file will be used as fallback.</td></tr><tr><td>providerId</td><td><code>String?</code></td><td>Optional. Your provider ID (if any). A provider ID is assigned when you work with Didomi through a third-party. If are not sure if you have one, set this to <code>null</code>.</td></tr><tr><td>disableDidomiRemoteConfig</td><td><code>bool</code></td><td><p>Prevent the SDK from loading a remote configuration from the Didomi Console. Defaults to <code>false</code> (loading remote config).</p><p>Set this parameter to <code>false</code> to use a remote consent notice configuration loaded from the Didomi Console.</p><p>Set this parameter to <code>true</code> to disable loading configurations from the Didomi Console.</p></td></tr><tr><td>languageCode</td><td><code>String?</code></td><td>Optional. Language in which the consent UI should be displayed. By default, the consent UI is displayed in the language configured in the device settings. This property allows you to override the default setting and specify a language to display the UI in. String containing the language code or the local code e.g.: <code>"es"</code>, <code>"fr"</code>, <code>"en-US"</code><em>,</em> <code>"zh-HK"</code>, etc.</td></tr><tr><td>noticeId</td><td><code>String?</code></td><td>Optional. Notice ID to load the configuration from. If provided, the SDK bypasses the app ID targeting and directly loads the configuration from the notice ID.</td></tr><tr><td>androidTvNoticeId</td><td><code>String?</code></td><td>Optional. TV notice ID to load the configuration from. If provided and SDK is initialized on TV, the SDK bypasses the app ID targeting and directly loads the configuration from the notice ID.</td></tr><tr><td>androidTvEnabled</td><td><code>bool</code></td><td><p>Enable the Android TV SDK. Defaults to <code>false</code> (Android TV is not enabled).</p><p>This parameter will be checked if sdk is initialized from a TV device.</p><p>If set to <code>false</code>, the sdk initialization will fail with an error.</p><p>If set to <code>true</code>, the sdk will try to initialize in TV mode, using the API key and the optional <code>tvNoticeId</code> parameter.</p><p>Please note that the TV notice option must be enabled on Didomi side. Please reach out to your dedicated customer success manager to know more.</p></td></tr><tr><td>countryCode</td><td><code>String?</code></td><td><p>Optional. Override user country code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user country.</p></td></tr><tr><td>regionCode</td><td><code>String?</code></td><td><p>Optional. Override user region code when determining the privacy regulation to apply.</p><p>Keep <code>null</code> to let the Didomi SDK determine the user region.</p><p>Ignored if <code>countryCode</code> is not set.</p></td></tr><tr><td>isUnderage</td><td><code>bool</code></td><td>Whether the user is underage or not. This parameters can only be used if the Underage feature has been configured in your notice<a data-footnote-ref href="#user-content-fn-1">.</a> (Underage is currently in beta version).</td></tr></tbody></table>

**Returns**

Nothing

**Example**

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

```dart
DidomiInitializeParameters didomiInitializeParameters = DidomiInitializeParameters(
    apiKey: "<Your API key>",
    noticeId: "<Your notice ID>"
);

await DidomiSdk.initializeWithParameters(didomiInitializeParameters);
```

{% endtab %}
{% endtabs %}

## isConsentRequired

Determine if consent is required for the user. This takes into account the location of the user and the configuration of the SDK:

* If your app is configured to apply GDPR to all users then this function always returns `true`.
* If your app is configured to apply GDPR to EU users only then this function returns `true` only if the user in the EU.

**Parameters**

No parameter.

**Returns**

`Future<bool>`

**Example**

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

```dart
await DidomiSdk.isConsentRequired();
```

{% endtab %}
{% endtabs %}

## isUserConsentStatusPartial

Determine if all consent information is available for the user.

This function returns `true` if and only if:

* Consent is required for the user (ie the user is in the EU or your tag is configured to apply GDPR to all users)
* At least one vendor is configured (if there is no vendor configured, this function always returns `false` as there is no consent to collect)
* We miss consent information for some vendors or purposes

If there is at least one piece of consent information missing for a single vendor/purpose, this function will return `true`. The consent notice is usually displayed when this function returns `true` although there is no guarantee of the direct mapping between the two.

An important edge case is when you add new vendors or if configured vendors ask for new purposes: the consent notice will be displayed again and this function will return `true` until the user has given or denied consent. Vendors that already had consent before will still operate normally as we only recollect consent for additional vendors/purposes.

**Parameters**

No parameter.

**Returns**

`Future<bool>`

**Example**

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

```dart
await DidomiSdk.isUserConsentStatusPartial();
```

{% endtab %}
{% endtabs %}

## isNoticeVisible

Check if the consent notice is currently displayed.

**Parameters**

No parameter.

**Returns**

`Future<bool>`

**Example**

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

```dart
await DidomiSdk.isNoticeVisible();
```

{% endtab %}
{% endtabs %}

## isPreferencesVisible

Check if the preferences popup is currently displayed.

**Parameters**

No parameter.

**Returns**

`Future<bool>`

**Example**

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

```dart
await DidomiSdk.isPreferencesVisible();
```

{% endtab %}
{% endtabs %}

## isReady

Check if the SDK is ready.

**Parameters**

No parameter.

**Returns**

`Future<bool>`

**Example**

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

```dart
await DidomiSdk.isReady();
```

{% endtab %}
{% endtabs %}

## isUserStatusPartial

Determine if the user has provided a choice for all vendors selected for the regulation and linked data processing.

This function returns `true` if the user has not expressed a choice for all the required vendors and data processing.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`Future<bool>`

**Example**

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

```dart
await DidomiSdk.isUserStatusPartial();
```

{% endtab %}
{% endtabs %}

## onError

Add a callback that will be called when the SDK initialization encounters an error. If the callback is added after the SDK initialization already failed, it will be called immediately.

**Parameters**

| **Name** | Type         | Description                                                       |
| -------- | ------------ | ----------------------------------------------------------------- |
| callback | `Function()` | A callback to run when the SDK initialization encounters an error |

**Returns**

Nothing

**Example**

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

```dart
DidomiSdk.onError(() =>
    // The SDK has encountered an error
});
```

{% endtab %}
{% endtabs %}

## onReady

Add a callback that will be called when the SDK is ready (ie fully initialized). If the callback is added after the SDK initialization, it will be called immediately.

All calls to other functions of this API must only be made in a callback to the ready event to make sure that the SDK is initialized before it is used.

**Parameters**

| Name     | Type         | Description                             |
| -------- | ------------ | --------------------------------------- |
| callback | `Function()` | A callback to run when the SDK is ready |

**Returns**

Nothing

**Example**

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

```dart
DidomiSdk.onReady(() =>
    // The SDK is ready
});
```

{% endtab %}
{% endtabs %}

## openCurrentUserStatusTransaction

**Definition**

Create an instance of the `CurrentUserStatusTransaction` class.

This class provides mechanisms to stage updates to the user status regarding purposes and vendors, allowing for batch operations.

Updates made through its methods are queued and applied simultaneously to the user status only once the `commit` method of the returned object is called.

Additional details:

* The status of vendors and purposes whose IDs are not not specified through the methods provided by `CurrentUserStatusTransaction` are kept unchanged.
* Essential purposes are always set to enabled and can’t be updated by the methods provided by `CurrentUserStatusTransaction`.
* When the regulation applied for a user is `none`, the methods provided by `CurrentUserStatusTransaction` should not update the status of any vendor or purpose which will always remain as enabled. When the `commit` method is called it will return `false`.
* If the IDs that are passed through the methods provided by `CurrentUserStatusTransaction` don’t correspond to vendors or purposes required by the Notice Config, they will be ignored.

**Requires SDK to be initialized**

Yes.

#### Parameters

No parameter.

**Returns**

An instance of the `CurrentUserStatusTransaction` class.

**Description of the** `CurrentUserStatusTransaction` **class**

<table><thead><tr><th width="207">Method</th><th width="233">Parameters</th><th>Returns</th><th>Description</th></tr></thead><tbody><tr><td><code>enablePurpose</code></td><td><code>id</code> (<code>String</code>): ID of the purpose to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single purpose based on its ID.</td></tr><tr><td><code>enablePurposes</code></td><td><code>ids</code> (<code>List&#x3C;String></code>): IDs of the purposes to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple purposes based on their IDs.</td></tr><tr><td><code>disablePurpose</code></td><td><code>id</code> (<code>String</code>): ID of the purpose to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single purpose based on its ID.</td></tr><tr><td><code>disablePurposes</code></td><td><code>ids</code> (<code>List&#x3C;String></code>): IDs of the purposes to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple purposes based on their IDs.</td></tr><tr><td><code>enableVendor</code></td><td><code>id</code> (<code>String</code>): Didomi ID of the vendor to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable a single vendor based on its Didomi ID.</td></tr><tr><td><code>enableVendors</code></td><td><code>ids</code> (<code>List&#x3C;String></code>): Didomi IDs of the vendors to be enabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Enable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>disableVendor</code></td><td><code>id</code> (<code>String</code>): Didomi ID of the vendor to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable a single vendor based on its Didomi ID.</td></tr><tr><td><code>disableVendors</code></td><td><code>ids</code> (<code>List&#x3C;String></code>): Didomi IDs of the vendors to be disabled.</td><td>Current <code>CurrentUserStatusTransaction</code> object.</td><td>Disable multiple vendors based on their Didomi IDs.</td></tr><tr><td><code>commit</code></td><td>No parameters.</td><td><code>bool</code>: <code>true</code> if user status has been updated, <code>false</code> otherwise.</td><td>Commit the changes that have been made through other methods.</td></tr></tbody></table>

#### Examples

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

```dart
final transaction = DidomiSdk.openCurrentUserStatusTransaction()

// enable a purpose
transaction.enablePurpose("cookies");
// enable purposes
transaction.enablePurpose(["cookies", "analytics"]);
// disable a purpose
transaction.enablePurpose("analytics");
// disable purposes
transaction.disablePurposes(["cookies", "analytics"]);
// enable a vendor
transaction.enableVendor("vendor-1");
// enable vendors
transaction.enableVendors(["vendor-1","vendor-2"]);
// disable a vendor
transaction.disableVendor("vendor-1");
// disable vendors
transaction.disableVendors(["vendor-1", "vendor-1"]);

// Chain multiple calls
transaction.enablePurpose("cookies").disablePurpose("analytics");

// Save user choices
final updated = await transaction.commit();
```

{% endtab %}
{% endtabs %}

## setLogLevel

Set the minimum level of messages to log. The SDK will not log messages under that level.

It uses a `LogLevel` object which maps log levels to corresponding values in iOS / Android native platforms.

```dart
enum LogLevel { verbose, debug, info, warn, error }
```

�

For more information see

* [Logging for Android](/cmp/mobile-sdk/android/logging)
* [Logging for iOS](/cmp/mobile-sdk/ios/logging)

\
**Parameters**

| Name     | Type       | Description                       |
| -------- | ---------- | --------------------------------- |
| minLevel | `LogLevel` | Minimum level of messages to log. |

**Returns**

Nothing

**Example**

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

```dart
DidomiSdk.setLogLevel(LogLevel.info);
```

{% endtab %}
{% endtabs %}

## setupUI

Setup the SDK UI. By calling this method, the consent notice will be displayed once the SDK is ready and if consent should be collected. It does not show any view if consent was already collected or is not required.\
This method should be called only from your contexts where the application starts.

**Returns**

Nothing

**Example**

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

```dart
DidomiSdk.setupUI();
```

{% endtab %}
{% endtabs %}

## setUser

**Deprecated**, use [setUserWithParameters](#setuserwithparameters) instead.

Set custom user information from organization.

**Parameters**

| Name               | Type     | Description                                |
| ------------------ | -------- | ------------------------------------------ |
| organizationUserId | `String` | Organization ID to associate with the user |

**Returns**

Nothing

**Example**

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

```dart
await DidomiSdk.setUser("e3222031-7c45-4f4a-8851-ffd57dbf0a2a");
```

{% endtab %}
{% endtabs %}

## setUserWithAuthentication

**Deprecated**, use [setUserWithParameters](#setuserwithparametersandsetupui) instead.

Set custom user information from organization, with authentication parameters.

**Parameters**

| Name                            | Type      | Description                                    |
| ------------------------------- | --------- | ---------------------------------------------- |
| organizationUserId              | `String`  | Organization ID to associate with the user     |
| organizationUserIdAuthAlgorithm | `String`  | Algorithm used for computing the digest        |
| organizationUserIdAuthSid       | `String`  | ID of the secret used for computing the digest |
| organizationUserIdAuthSalt      | `String?` | Salt used for computing the digest (optional)  |
| organizationUserIdAuthDigest    | `String`  | Digest of the organization user ID and secret  |

**Returns**

Nothing

**Example**

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

```dart
await DidomiSdk.setUser(
            "e3222031-7c45-4f4a-8851-ffd57dbf0a2a",
            "hash-md5",
            "secret_id",
            "salt",
            "098f6bcd4621d373cade4e832627b4f6"
);
```

{% endtab %}
{% endtabs %}

## setUserWithParameters

Set custom user information from organization, with or without authentication parameters.

**Parameter:**

| Name                 | Type                   | Description                                          |
| -------------------- | ---------------------- | ---------------------------------------------------- |
| didomiUserParameters | `DidomiUserParameters` | Object containing properties required to set a user. |

***Description for*** `DidomiUserParameters`***:***

<table><thead><tr><th width="193">Name</th><th width="219">Type</th><th>Description</th></tr></thead><tbody><tr><td>userAuth</td><td><code>UserAuth</code></td><td>User authentication object. Can be either <code>UserAuthWithoutParams</code>, <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.</td></tr><tr><td>dcsUserAuth</td><td><code>UserAuthParams?</code></td><td>Optional. Dedicated user with encryption or hash used for Didomi Consent String signature. Can be either <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.<br>This parameter can only be used if you are using the Didomi Consent String feature (This feature is currently in beta version)</td></tr><tr><td>isUnderage</td><td><code>Boolean?</code></td><td>Optional. Whether the user is underage or not. This parameters can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).</td></tr></tbody></table>

Parameters for `UserAuthWithoutParams` :

<table><thead><tr><th width="204">Name</th><th width="228">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr></tbody></table>

Parameters for `UserAuthWithEncryptionParams` :

<table><thead><tr><th width="211">Name</th><th width="202">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>String</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>String</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>initializationVector</td><td><code>String</code></td><td>Initialization Vector used for encrypting the message.</td></tr><tr><td>expiration</td><td><code>Long?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0).</td></tr></tbody></table>

Parameters for `UserAuthWithHashParams` :

<table><thead><tr><th width="212">Name</th><th width="205">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>String</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>String</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>digest</td><td><code>String</code></td><td>Digest used for representing the user ID</td></tr><tr><td>salt</td><td><code>String?</code></td><td>Optional. Salt used for computing the user ID.</td></tr><tr><td>expiration</td><td><code>Long?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0)</td></tr></tbody></table>

**Returns**

Nothing

**Example**

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

```dart
DidomiUserParameters didomiUserParameters = DidomiUserParameters(
    userAuth: UserAuthWithoutParams("user-id"),
    dcsUserAuth: UserAuthWithHashParams("dcs-user-id", "hash-md5", "secredID", "digest", "salt"),
    isUnderage: false
);

await DidomiSdk.setUserWithParameters(didomiUserParameters);
```

{% endtab %}
{% endtabs %}

## setUserWithParametersAndSetupUI

Set custom user information from organization, with or without authentication parameters and display the notice if required.

**Parameter:**

| Name                 | Type                   | Description                                          |
| -------------------- | ---------------------- | ---------------------------------------------------- |
| didomiUserParameters | `DidomiUserParameters` | Object containing properties required to set a user. |

***Description for*** `DidomiUserParameters`***:***

<table><thead><tr><th width="193">Name</th><th width="219">Type</th><th>Description</th></tr></thead><tbody><tr><td>userAuth</td><td><code>UserAuth</code></td><td>User authentication object. Can be either <code>UserAuthWithoutParams</code>, <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.</td></tr><tr><td>dcsUserAuth</td><td><code>UserAuthParams?</code></td><td>Optional. Dedicated user with encryption or hash used for Didomi Consent String signature. Can be either <code>UserAuthWithEncryptionParams</code> or <code>UserAuthWithHashParams</code>.<br>This parameter can only be used if you are using the Didomi Consent String feature (This feature is currently in beta version)</td></tr><tr><td>isUnderage</td><td><code>Boolean?</code></td><td>Optional. Whether the user is underage or not. This parameters can only be used if the Underage feature has been configured in your notice. (Underage is currently in beta version).</td></tr></tbody></table>

Parameters for `UserAuthWithoutParams` :

<table><thead><tr><th width="204">Name</th><th width="228">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr></tbody></table>

Parameters for `UserAuthWithEncryptionParams` :

<table><thead><tr><th width="211">Name</th><th width="202">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>String</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>String</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>initializationVector</td><td><code>String</code></td><td>Initialization Vector used for encrypting the message.</td></tr><tr><td>expiration</td><td><code>Long?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0).</td></tr></tbody></table>

Parameters for `UserAuthWithHashParams` :

<table><thead><tr><th width="212">Name</th><th width="205">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>String</code></td><td>Organization ID to associate with the user.</td></tr><tr><td>algorithm</td><td><code>String</code></td><td>Algorithm used for computing the user ID.</td></tr><tr><td>secretId</td><td><code>String</code></td><td>ID of the secret used for the computing the user ID.</td></tr><tr><td>digest</td><td><code>String</code></td><td>Digest used for representing the user ID</td></tr><tr><td>salt</td><td><code>String?</code></td><td>Optional. Salt used for computing the user ID.</td></tr><tr><td>expiration</td><td><code>Long?</code></td><td>Optional. Expiration time as UNIX timestamp (must be > 0)</td></tr></tbody></table>

**Returns**

Nothing

**Example**

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

```dart
DidomiUserParameters didomiUserParameters = DidomiUserParameters(
    userAuth: UserAuthWithoutParams("user-id"),
    dcsUserAuth: UserAuthWithHashParams("dcs-user-id", "hash-md5", "secredID", "digest", "salt"),
    isUnderage: false
);

await DidomiSdk.setUserWithParametersAndSetupUI(didomiUserParameters);
```

{% endtab %}
{% endtabs %}

## clearUser

Remove custom user information from organization

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```dart
await DidomiSdk.clearUser();
```

{% endtab %}
{% endtabs %}

## showNotice

{% hint style="info" %}
In most cases this method should be called if the notice should be displayed in response to a user action (e.g.: select the privacy settings section within your app). By calling the setupUI method, the notice will be automatically displayed if required.
{% endhint %}

Show the consent notice. The consent notice actually only gets shown if needed (consent is required and we are missing consent information for some vendor or purpose).

**Returns**

Nothing

**Example**

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

```dart
await DidomiSdk.showNotice();
```

{% endtab %}
{% endtabs %}

## showPreferences

{% hint style="info" %}
In most cases this method should be called if you want to show the Preferences screen in response to a user action (the user pressing a "Consent Preferences" button in your app menu, for instance).
{% endhint %}

Show the Preferences view to the user. This method can be used to allow the user to update their preferences after the banner has been closed. We suggest adding a link/button/item that calls this method somewhere in your app, for example from your settings menu. By default, the Purposes view is displayed first. By calling this method, users will have the opportunity to modify the choices previously made.

**Parameters**

| Type                         |                                                                                                                                                                                                                                                                                                                                                                            |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PreferencesView` (Optional) | Defines which view is displayed to the user first between the purposes view or the vendors view. We expose the values to provide on the Didomi class as `PreferencesView.purposes`, `PreferencesView.sensitivePersonalInformation` and `PreferencesView.vendors`. If this parameter is not defined or contains an unexpected string, the purposes' view will be displayed. |

**Returns**

Nothing

**Example**

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

```dart
await DidomiSdk.showPreferences();
await DidomiSdk.showPreferences(PreferencesView.purposes);
await DidomiSdk.showPreferences(PreferencesView.sensitivePersonalInformation);
await DidomiSdk.showPreferences(PreferencesView.vendors);
```

{% endtab %}
{% endtabs %}

## reset

Reset all the consent information for the current user. This will remove all consent information stored on the device by Didomi and will trigger re-collection of consent. The consent notice will be displayed again.

**Parameters**

No parameter.

**Returns**

Nothing

**Example**

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

```dart
await DidomiSdk.reset();
```

{% endtab %}
{% endtabs %}

## setUserAgreeToAll

Report that the user has enabled consents and legitimate interests for all purposes and vendors configured for your app.

This function will log the user choice on our platform and close the notice.

Consent statuses for essential purposes are not stored.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

No parameter.

**Returns**

`Future<bool>`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```dart
await DidomiSdk.setUserAgreeToAll();
```

{% endtab %}
{% endtabs %}

## setUserDisagreeToAll

Report that the user has disabled consents and legitimate interests for all purposes and vendors configured for your app.

This function will log the user choice on our platform and close the notice.

Consent statuses for essential purposes are not stored.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

No parameter.

**Returns**

`Future<bool>`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```dart
DidomiSdk.setUserDisagreeToAll();
```

{% endtab %}
{% endtabs %}

## setCurrentUserStatus

**Definition**

Set the user status for purposes and vendors. This function will trigger events and API calls every time it is called (and the user status changes) so make sure to push all user choices at once and not one by one.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

**Parameters**

Add the desired global status for each vendor and each purpose:

* the vendor status specified in this function will be reflected on the vendor’s layer.
  * vendor enabled : true → means the vendor is enabled in all the legal basis that this vendor uses.
  * vendor enabled : false → means the vendor is disabled in all the legal basis that this vendor uses
* the purposes status specified in this function will be reflected on the preferences layer.
  * purpose enabled : true → means the purpose is enabled in all the legal basis in which it’s defined.
  * purpose enabled : false → means the purpose is disabled in all the legal basis in which it’s defined.

**Returns**

`boolean`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Throws**

<table><thead><tr><th width="334">Type</th><th>Description</th></tr></thead><tbody><tr><td>DidomiNotReadyException</td><td>Exception thrown when a method that requires the Didomi SDK to be ready is called before that. Developers can call this method within a try/catch or within a lambda expression passed into the <code>onReady</code> method.</td></tr></tbody></table>

**Example**

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

```dart
// Define purposes
final Map<String, PurposeStatus> purposes = {
  'purpose1': PurposeStatus(
    id: 'purpose1',
    enabled: true,
  ),
};

// Define vendors
final Map<String, VendorStatus> vendors = {
  'vendor1': VendorStatus(
    id: 'vendor1',
    enabled: true,
  ),
};

// Create current user status
final CurrentUserStatus currentUserStatus = CurrentUserStatus(
  purposes: purposes,
  vendors: vendors,
);

// Set the user status
final bool updated =
    await Didomi.instance.setCurrentUserStatus(currentUserStatus);
```

{% endtab %}
{% endtabs %}

## setUserStatusGlobally

Set the global status for consent purposes, legitimate interest purposes, consent vendors, legitimate interest vendors. This function will trigger events and API calls every time it is called.

Please read [our article](https://docs.didomi.io/analytics/consent-management-platform-cmp-analytics/introduction/custom-behavior-impact-on-cmp-analytics) on what to expect from your analytics when setting a custom behavior for your consent notice.

| Name                  | Type   | Description                                                                                             |
| --------------------- | ------ | ------------------------------------------------------------------------------------------------------- |
| purposesConsentStatus | `bool` | `true` if purposes on a consent basis should be enabled, `false` if they should be disabled             |
| purposesLIStatus      | `bool` | `true` if purposes on a legitimate interest basis should be enabled, `false` if they should be disabled |
| vendorsConsentStatus  | `bool` | `true` if vendors on a consent basis should be enabled, `false` if they should be disabled              |
| vendorsLIStatus       | `bool` | `true` if vendors on a legitimate interest basis should be enabled, `false` if they should be disabled  |

**Returns**

`Future<bool>`

`true` if the user choices have changed (i.e. the user had made different choices before this function got called).

**Example**

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

```dart
// Disable everything except vendors legitimate interest
final bool result = await DidomiSdk.setUserStatus(
    false, false, false, true
);
```

{% endtab %}
{% endtabs %}

## shouldConsentBeCollected

**Deprecated**, use [shouldUserStatusBeCollected](#shoulduserstatusbecollected) instead.

Determine if consent should be collected for the visitor. Returns `true` if consent is required for the current user and one of following two conditions is met:

* Consent has never been collected for this visitor yet
* New consents should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `false`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

**Parameters**

No parameter.

**Returns**

`Future<bool>`

**Example**

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

```dart
await DidomiSdk.shouldConsentBeCollected()
```

{% endtab %}
{% endtabs %}

## shouldUserStatusBeCollected

Determine if user status (consent) should be collected for the user. Returns `true` if status is required for the current user and one of following two conditions is met:

* User status has never been collected for this user yet
* New user status should be collected (as new vendors have been added) AND the number of days before recollecting them has exceeded

If none of these two conditions is met, the function returns `False`. This function is mainly present to allow you to know when to display your own notice if you have disabled our standard notice.

**Requires SDK to be initialized**

Yes.

**Parameters**

No parameter.

**Returns**

`Future<bool>`

**Example**

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

```dart
await DidomiSdk.shouldUserStatusBeCollected()
```

{% endtab %}
{% endtabs %}

## updateSelectedLanguage

Method used to update the selected language of the Didomi SDK and any property that depends on it.

In most cases this method doesn't need to be called. It would only be required for those apps that allow language change on-the-fly, i.e.: from within the app rather than from the device settings.

If your configuration involves country code (`en-US`), you can provide a locale code to change the regional configuration as well. If only language code (`en`) is provided and your configuration requires a country code, the country from the device location will be used (and will fallback to the default country if required).

In order to update the language of the views displayed by the Didomi SDK, this method needs to be called before these views are displayed.

**Requires SDK to be initialized**

Yes.

**Parameters**

| Name         | Type     | Description                                                                                                        |
| ------------ | -------- | ------------------------------------------------------------------------------------------------------------------ |
| languageCode | `String` | string containing the 2-letter language code or 5-letter locale code e.g. `en`, `es`, `fr`, `en-US`, `zh-HK`, etc. |

**Returns**

Nothing

**Example**

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

```dart
DidomiSdk.onReady(() -> {
    DidomiSdk.updateSelectedLanguage("fr");
});
```

{% endtab %}
{% endtabs %}

| Type                    | Description                                                            |
| ----------------------- | ---------------------------------------------------------------------- |
| `Future<List<Purpose>>` | A list of type `Purpose` containing the purposes disabled by the user. |

## applicableRegulation

Get the applicable regulation.

**Requires SDK to be initialized**

**yes.**

**Returns**

| Type     | Description                                                                                                                                                                                                                                                      |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `String` | <p>Representation of the current regulation as a <code>Regulation</code> String value, such as <code>GDPR</code>, <code>CCPA</code>, <code>CPRA</code>, or <code>NONE</code>.</p><p>Note that some regulations present as enum values are not available yet.</p> |

**Example**

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

```dart
await DidomiSdk.applicableRegulation;
```

{% endtab %}
{% endtabs %}

[^1]: this dot s


# Deprecated

See the following sections for methods and events that have been deprecated in the Didomi Flutter SDK:

* Notice Config
* User Status

***

### Notice Config

The following notice configuration methods and events have been deprecated in the Didomi Flutter SDK:

<table><thead><tr><th width="233">Method/Event</th><th>Description</th></tr></thead><tbody><tr><td><code>getDisabledPurposes</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getDisabledPurposeIds</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getDisabledVendors</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getDisabledVendorIds</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getEnabledPurposes</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getEnabledPurposeIds</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getEnabledVendors</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getEnabledVendorIds</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>initialize</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#initializewithparameters">initializeWithParameters</a> instead.</td></tr><tr><td><code>setUserWithAuthentication</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#setuserwithparameters">setUserWithParameters</a> instead.</td></tr></tbody></table>

### User Status

The following user status methods and events have been deprecated in the Didomi Flutter SDK:

<table><thead><tr><th width="241">Method/Event</th><th>Description</th></tr></thead><tbody><tr><td><code>getUserConsentStatusForPurpose</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getUserConsentStatusForVendor</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getUserConsentStatusForVendorAndRequiredPurposes</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getUserLegitimateInterestStatusForPurpose</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getUserLegitimateInterestForVendor</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getUserLegitimateInterestStatusForVendorAndRequiredPurposes</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>getUserStatusForVendor</code></td><td>Removed since <strong>version 2.0.0</strong>. Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr><tr><td><code>setUserStatus</code></td><td>Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#setcurrentuserstatus">setCurrentUserStatus</a> instead.</td></tr><tr><td><code>getUserStatus</code></td><td>Use <a href="/pages/-MbHdyPZ5OewJ2xPW8mU#getcurrentuserstatus">getCurrentUserStatus</a> instead.</td></tr></tbody></table>


# Versions

Releases of the Didomi Flutter SDK are published and documented on our Github repository: <https://github.com/didomi/flutter/releases/>


# Vega OS

The **Didomi Vega SDK** integrates Didomi’s Consent Management Platform (CMP) with **Amazon’s Vega platform**. It allows applications to **display consent notices, manage user preferences, and synchronize consent data** in compliance with privacy regulations.\\

We are assuming that you have a Didomi account and an API key. If not, please go to our [website](https://www.didomi.io) and sign up for an account.

* [Setup](/cmp/mobile-sdk/vega-os/setup): Import the Vega SDK and configure it
* [Reference](/cmp/mobile-sdk/vega-os/reference): API reference of the Vega SDK
* [Versions](/cmp/mobile-sdk/vega-os/versions): List of published versions


# Setup

#### Installation

```bash
npm install @didomi/vega-sdk
```

#### Peer Dependencies

This SDK requires the following peer dependencies:

* `react` (>=18.0.0 <=18.2.0)
* `react-dom` (>=18.0.0 <=18.2.0)
* `react-native` (^0.72.0)
* `@amazon-devices/react-native-kepler` (^2.0.0)
* `@amazon-devices/webview`

> **Note:** For **WebView support**, update your app’s `manifest.toml` file to include the required Vega services.\
> Please refer to <https://developer.amazon.com/docs/vega/0.21/set-up-webview.html>

### Basic Integration

```tsx
import { DidomiSDK, DidomiSDKAPI } from '@didomi/vega-sdk';
import React, { useRef } from 'react';

const MyApp = () => {
  const didomiRef = useRef<DidomiSDKAPI>(null);

  return (
    <DidomiSDK
      noticeId="YOUR_NOTICE_ID"
      didomiPublicApiKey="YOUR_PUBLIC_API_KEY"
      ref={didomiRef}
      onReady={() => console.log('Didomi SDK is ready')}
      onConsentChanged={(consent) => console.log('Consent changed:', consent)}
    >
      {/* Your app content */}
      <YourApp />
    </DidomiSDK>
  );
};
```

***

### Programmatic Usage

All SDK functionality is exposed through the component `ref`:

```tsx
const didomiSDK = didomiRef.current;

// Display UI
didomiSDK?.notice.show();                  // Show consent notice
didomiSDK?.preferences.show('purposes');   // Show preferences dialog, the parameter is optional, and "vendors" can also be set to display the associated layer.

// Query SDK state
const isConsentRequired = await didomiSDK?.isConsentRequired();

// Manage user consent
const userStatus = await didomiSDK?.getCurrentUserStatus();
await didomiSDK?.setUserAgreeToAll();
await didomiSDK?.setCurrentUserStatus({
  purposes: { /* purpose status */ },
  vendors: { /* vendor status */ },
});
```

***

### API Reference

#### Component Props

| Prop                 | Type                     | Description                                                                      |
| -------------------- | ------------------------ | -------------------------------------------------------------------------------- |
| `noticeId`           | string                   | ID of the consent notice to display                                              |
| `didomiPublicApiKey` | string                   | Your Didomi **public API key**                                                   |
| `sdkPath`            | string                   | (Optional) Path to the Didomi SDK, defaults to `https://sdk.privacy-center.org/` |
| `onReady`            | `() => void`             | Fired when the SDK is initialized and ready.                                     |
| `onConsentChanged`   | `(consent: any) => void` | Fired whenever the user’s consent status changes.                                |

Other events are available as props, please refer to [Events](/cmp/mobile-sdk/vega-os/reference/events) for more details.


# Reference

### Usage

You can access all methods through a `ref` to the `<DidomiSDK />` component.

```tsx
import { DidomiSDK, DidomiSDKAPI } from '@didomi/vega-sdk';
import React, { useRef } from 'react';

const App = () => {
  const didomiRef = useRef<DidomiSDKAPI>(null);

  return (
    <DidomiSDK
      noticeId="YOUR_NOTICE_ID"
      didomiPublicApiKey="YOUR_PUBLIC_API_KEY"
      ref={didomiRef}
      onReady={() => console.log('SDK ready')}
    >
      <YourApp />
    </DidomiSDK>
  );
};
```

***

### addEventListener

Attach a listener to SDK events (consent changes, UI visibility, errors, etc.).

**Signature**

```ts
didomi.addEventListener(event: DidomiEvent, handler: (payload?: unknown) => void): void
```

**Parameters**

* `event` — Event name (see **Events** list below).
* `handler` — Callback invoked with an optional payload.

**Returns**

* `void`

**Example**

```ts
didomiRef.current?.addEventListener('consent.changed', (status) => {
  console.log('Consent changed', status);
});
```

***

### removeEventListener

Detach a previously registered event listener.

**Signature**

```ts
didomi.removeEventListener(event: DidomiEvent, handler: (payload?: unknown) => void): void
```

**Parameters**

* `event` — Event name.
* `handler` — The same function reference passed to `addEventListener`.

**Returns**

* `void`

**Example**

```ts
const onChanged = (s: unknown) => {/* ... */};
didomiRef.current?.addEventListener('consent.changed', onChanged);
// later
didomiRef.current?.removeEventListener('consent.changed', onChanged);
```

***

### getJavaScriptForWebView

Generate an inline JS snippet to inject into a Vega WebView that mirrors the current consent state.

**Signature**

```ts
didomi.getJavaScriptForWebView(): Promise<string>
```

**Parameters**

* *None*

**Returns**

* `Promise<string>` — JavaScript to inject.

**Example**

```ts
const js = await didomiRef.current?.getJavaScriptForWebView();
vegaWebView.injectJavaScript(js!);
```

***

### getQueryStringForWebView

Build a query string carrying the current consent information for WebView navigation.

**Signature**

```ts
didomi.getQueryStringForWebView(): Promise<string>
```

**Parameters**

* *None*

**Returns**

* `Promise<string>` — Query string (without the leading `?`).

**Example**

```ts
const qs = await didomiRef.current?.getQueryStringForWebView();
vegaWebView.loadUrl(`https://example.app/privacy?${qs}`);
```

***

### showNotice

Display the consent notice. If already visible, it becomes focused.

**Signature**

```ts
didomi.notice.show(): void
```

**Parameters**

* *None*

**Returns**

* `void`

**Example**

```ts
didomiRef.current?.notice.show();
```

***

### hideNotice

Hide the consent notice if visible.

**Signature**

```ts
didomi.notice.hide(): void
```

**Parameters**

* *None*

**Returns**

* `void`

**Example**

```ts
didomiRef.current?.notice.hide();
```

***

### isNoticeVisible

Check if the consent notice is currently visible.

**Signature**

```ts
didomi.notice.isVisible(): Promise<boolean>
```

**Parameters**

* *None*

**Returns**

* `Promise<boolean>`

**Example**

```ts
const visible = await didomiRef.current?.notice.isVisible();
```

***

### showPreferences

Open the preferences dialog.

**Signature**

```ts
didomi.preferences.show(type?: 'information' | 'purposes' | 'vendor'): void
```

**Parameters**

* `type` *(optional)* — Initial tab to open (`'information'`, `'purposes'`, or `'vendor'`). Defaults to `'purposes'`.

**Returns**

* `void`

**Example**

```ts
didomiRef.current?.preferences.show('vendor');
```

***

### hidePreferences

Close the preferences dialog if open.

**Signature**

```ts
didomi.preferences.hide(): void
```

**Parameters**

* *None*

**Returns**

* `void`

**Example**

```ts
didomiRef.current?.preferences.hide();
```

***

### isPreferencesVisible

Check if the preferences dialog is visible.

**Signature**

```ts
didomi.preferences.isVisible(): Promise<boolean>
```

**Parameters**

* *None*

**Returns**

* `Promise<boolean>`

**Example**

```ts
const isOpen = await didomiRef.current?.preferences.isVisible();
```

***

### isReady

Return whether the SDK has finished initialization.

**Signature**

```ts
didomi.isReady(): boolean
```

**Parameters**

* *None*

**Returns**

* `boolean`

**Example**

```ts
if (didomiRef.current?.isReady()) { /* ... */ }
```

***

### onReady

Register a callback to run once the SDK is ready.

**Signature**

```ts
didomi.onReady(callback: () => void): void
```

**Parameters**

* `callback` — Invoked when the SDK is ready (called immediately if already ready).

**Returns**

* `void`

**Example**

```ts
didomiRef.current?.onReady(() => console.log('Vega SDK ready'));
```

***

### onError

Register a callback for SDK-level errors (configuration, network, rendering).

**Signature**

```ts
didomi.onError(callback: (error: unknown) => void): void
```

**Parameters**

* `callback` — Receives an error object or message.

**Returns**

* `void`

**Example**

```ts
didomiRef.current?.onError((e) => console.error('Didomi error', e));
```

***

### isError

Returns whether the SDK is in an error state.

**Signature**

```ts
didomi.isError(): boolean
```

**Parameters**

* *None*

**Returns**

* `boolean`

**Example**

```ts
if (didomiRef.current?.isError()) { /* show fallback */ }
```

***

### setLogLevel

Set the SDK log verbosity.

**Signature**

```ts
didomi.setLogLevel(level: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'): void
```

**Parameters**

* `level` — Desired log level.

**Returns**

* `void`

**Example**

```ts
didomiRef.current?.setLogLevel('INFO');
```

***

### getText

Resolve a UI text key using the current language.

**Signature**

```ts
didomi.getText(key: string): Promise<string | undefined>
```

**Parameters**

* `key` — Text key.

**Returns**

* `Promise<string | undefined>`

**Example**

```ts
const title = await didomiRef.current?.getText('notice.title');
```

***

### getTranslatedText

Resolve a UI text key for a specific language.

**Signature**

```ts
didomi.getTranslatedText(key: string, lang: string): Promise<string | undefined>
```

**Parameters**

* `key` — Text key.
* `lang` — IETF language tag (e.g., `en`, `fr-FR`).

**Returns**

* `Promise<string | undefined>`

**Example**

```ts
const titleFr = await didomiRef.current?.getTranslatedText('notice.title', 'fr');
```

***

### updateSelectedLanguage

Change the SDK UI language at runtime.

**Signature**

```ts
didomi.updateSelectedLanguage(lang: string): Promise<void>
```

**Parameters**

* `lang` — IETF language tag.

**Returns**

* `Promise<void>`

**Example**

```ts
await didomiRef.current?.updateSelectedLanguage('es');
```

***

### getVendor

Retrieve a vendor definition by ID.

**Signature**

```ts
didomi.getVendor(vendorId: string): Promise<Vendor | undefined>
```

**Parameters**

* `vendorId` — Vendor identifier.

**Returns**

* `Promise<Vendor | undefined>`

**Example**

```ts
const vendor = await didomiRef.current?.getVendor('google');
```

***

### getPurpose

Retrieve a purpose definition by ID.

**Signature**

```ts
didomi.getPurpose(purposeId: string): Promise<Purpose | undefined>
```

**Parameters**

* `purposeId` — Purpose identifier.

**Returns**

* `Promise<Purpose | undefined>`

**Example**

```ts
const purpose = await didomiRef.current?.getPurpose('cookies');
```

***

### getTotalVendorCount / getIabVendorCount / getNonIabVendorCount

Counts for vendors in the current configuration.

**Signatures**

```ts
didomi.getTotalVendorCount(): Promise<number>
didomi.getIabVendorCount(): Promise<number>
didomi.getNonIabVendorCount(): Promise<number>
```

**Parameters**

* *None*

**Returns**

* `Promise<number>`

**Example**

```ts
const [all, iab, nonIab] = await Promise.all([
  didomiRef.current!.getTotalVendorCount(),
  didomiRef.current!.getIabVendorCount(),
  didomiRef.current!.getNonIabVendorCount(),
]);
```

***

### getRequiredPurposes / getRequiredVendors

Return lists of purposes/vendors that are required by configuration.

**Signatures**

```ts
didomi.getRequiredPurposes(): Promise<string[]>
didomi.getRequiredVendors(): Promise<string[]>
```

**Parameters**

* *None*

**Returns**

* `Promise<string[]>`

**Example**

```ts
const requiredPurposes = await didomiRef.current?.getRequiredPurposes();
```

***

### applicableRegulation

Get the regulation currently applied to the user (e.g., `gdpr`, `cpra`, `none`).

**Signature**

```ts
didomi.applicableRegulation(): Promise<string>
```

**Parameters**

* *None*

**Returns**

* `Promise<string>`

**Example**

```ts
const reg = await didomiRef.current?.applicableRegulation();
```

***

### getCurrentUserStatus

Return the current user consent status.

**Signature**

```ts
didomi.getCurrentUserStatus(): Promise<UserStatus>
```

**Parameters**

* *None*

**Returns**

* `Promise<UserStatus>`

**Example**

```ts
const status = await didomiRef.current?.getCurrentUserStatus();
```

***

### isUserStatusPartial

Whether the stored status is partial (some choices missing).

**Signature**

```ts
didomi.isUserStatusPartial(): Promise<boolean>
```

**Parameters**

* *None*

**Returns**

* `Promise<boolean>`

**Example**

```ts
const partial = await didomiRef.current?.isUserStatusPartial();
```

***

### setCurrentUserStatus

Set the user consent status at purpose/vendor level.

**Signature**

```ts
didomi.setCurrentUserStatus(status: {
  purposes?: Record<string, 'granted' | 'denied'>,
  vendors?: Record<string, 'granted' | 'denied'>
}): Promise<void>
```

**Parameters**

* `status` — Object with per-purpose and/or per-vendor decisions.

**Returns**

* `Promise<void>`

**Example**

```ts
await didomiRef.current?.setCurrentUserStatus({
  purposes: { storage: 'granted', measurement: 'denied' },
  vendors: { google: 'granted' }
});
```

***

### setUserAgreeToAll

Grant consent for all purposes and vendors.

**Signature**

```ts
didomi.setUserAgreeToAll(): Promise<void>
```

**Parameters**

* *None*

**Returns**

* `Promise<void>`

**Example**

```ts
await didomiRef.current?.setUserAgreeToAll();
```

***

### setUserDisagreeToAll

Deny consent for all purposes and vendors.

**Signature**

```ts
didomi.setUserDisagreeToAll(): Promise<void>
```

**Parameters**

* *None*

**Returns**

* `Promise<void>`

**Example**

```ts
await didomiRef.current?.setUserDisagreeToAll();
```

***

### openCurrentUserStatusTransaction

Create a **transaction** to stage updates to the current user status (purposes & vendors) and apply them **atomically** on commit.

Updates made via the transaction are **queued** and only written to the user status when you call `commit()`.

**Signature**

```ts
didomi.openCurrentUserStatusTransaction(): CurrentUserStatusTransaction
```

**Parameters**

* *None*

**Returns**

* `CurrentUserStatusTransaction` — A chainable object for batching purpose/vendor updates.

**Behavior & Notes**

* Purposes/vendors **not specified** in the transaction remain **unchanged**.
* **Essential purposes** are always enabled and cannot be changed by the transaction.
* If the applied regulation is **none**, vendors and purposes remain enabled; `commit()` will return `false`.
* IDs not present in the **Notice Config** are **ignored** (no-op).
* Invalid IDs are ignored; errors may be logged to the console (see *Error handling* below).

**Example**

```ts
const tx = didomiRef.current!.openCurrentUserStatusTransaction();

// enable / disable purposes
tx.enablePurpose('cookies');
tx.enablePurposes(['cookies', 'analytics']);
tx.disablePurpose('analytics');
tx.disablePurposes(['cookies', 'analytics']);

// enable / disable vendors
tx.enableVendor('vendor-1');
tx.enableVendors(['vendor-1', 'vendor-2']);
tx.disableVendor('vendor-1');
tx.disableVendors(['vendor-1', 'vendor-2']);

// chain calls
tx.enablePurpose('cookies').disablePurpose('analytics');

// apply all staged changes
const updated = await tx.commit(); // true if changes applied, false otherwise
```

**Error handling**

* Invalid purposes or vendors are ignored; the SDK may log messages to the browser console.\
  Example:

  ```ts
  const tx = didomiRef.current!.openCurrentUserStatusTransaction();
  tx.enablePurposes(['cookies', 'invalid_ID']);
  const ok = await tx.commit();
  // Console:
  // 'Didomi SDK - disablePurpose ignored due to invalid purpose: invalid_ID'
  // ok === true
  ```

***

#### CurrentUserStatusTransaction (Methods)

| Method            | Parameters      | Returns                        | Description                                                                                 |
| ----------------- | --------------- | ------------------------------ | ------------------------------------------------------------------------------------------- |
| `enablePurpose`   | `id: string`    | `CurrentUserStatusTransaction` | Enable a single purpose by ID.                                                              |
| `enablePurposes`  | `ids: string[]` | `CurrentUserStatusTransaction` | Enable multiple purposes by ID.                                                             |
| `disablePurpose`  | `id: string`    | `CurrentUserStatusTransaction` | Disable a single purpose by ID.                                                             |
| `disablePurposes` | `ids: string[]` | `CurrentUserStatusTransaction` | Disable multiple purposes by ID.                                                            |
| `enableVendor`    | `id: string`    | `CurrentUserStatusTransaction` | Enable a single vendor by Didomi ID.                                                        |
| `enableVendors`   | `ids: string[]` | `CurrentUserStatusTransaction` | Enable multiple vendors by Didomi ID.                                                       |
| `disableVendor`   | `id: string`    | `CurrentUserStatusTransaction` | Disable a single vendor by Didomi ID.                                                       |
| `disableVendors`  | `ids: string[]` | `CurrentUserStatusTransaction` | Disable multiple vendors by Didomi ID.                                                      |
| `commit`          | —               | `Promise<boolean>`             | Apply all staged changes. Returns `true` if the user status was updated, `false` otherwise. |

***

### Types

Add these to the **Types** section for completeness:

```ts
export interface CurrentUserStatusTransaction {
  enablePurpose: (id: string) => CurrentUserStatusTransaction;
  enablePurposes: (ids: string[]) => CurrentUserStatusTransaction;
  disablePurpose: (id: string) => CurrentUserStatusTransaction;
  disablePurposes: (ids: string[]) => CurrentUserStatusTransaction;
  enableVendor: (id: string) => CurrentUserStatusTransaction;
  enableVendors: (ids: string[]) => CurrentUserStatusTransaction;
  disableVendor: (id: string) => CurrentUserStatusTransaction;
  disableVendors: (ids: string[]) => CurrentUserStatusTransaction;
  commit: () => Promise<boolean>;
}
```

And add the method to your API surface:

```ts
export interface DidomiSDKAPI {
  // ...
  openCurrentUserStatusTransaction: () => CurrentUserStatusTransaction;
  // ...
}
```

***

### reset

Clear locally stored consent data and re-evaluate.

**Signature**

```ts
didomi.reset(): Promise<void>
```

**Parameters**

* *None*

**Returns**

* `Promise<void>`

**Example**

```ts
await didomiRef.current?.reset();
```

***

### shouldUserStatusBeCollected

Whether the app should prompt for consent (e.g., user is in-scope, no valid status yet).

**Signature**

```ts
didomi.shouldUserStatusBeCollected(): Promise<boolean>
```

**Parameters**

* *None*

**Returns**

* `Promise<boolean>`

**Example**

<pre class="language-ts"><code class="lang-ts"><strong>if (await didomiRef.current?.shouldUserStatusBeCollected()) {
</strong>  didomiRef.current?.notice.show();
}
</code></pre>

***

#### syncUser

Update the **local user status** from the Didomi servers in a **single-page application**.

If your site is **not** an SPA, do **not** call this method directly — syncing is automatically performed when `window.didomiConfig.user` is set on page load.

Synchronization will only run if:

* Sync is enabled in the configuration,
* An `organizationUserId` is provided,
* The user is not a bot, and
* The sync frequency has not been exceeded.

**Signature**

```ts
didomi.syncUser(): Promise<SyncReadyEvent>
```

**Parameters**

* *None*

**Returns**

* `Promise<SyncReadyEvent>` — An object describing the result of the sync.

***

#### SyncReadyEvent

| Property           | Type                     | Description                                                                                                                                                                         |
| ------------------ | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `statusApplied`    | `boolean`                | `true` if the local user status was updated from the server, `false` otherwise.                                                                                                     |
| `syncAcknowledged` | `() => Promise<boolean>` | Call this to confirm to Didomi that the synchronized status has been communicated to the user. Returns `true` if the acknowledgment event was sent successfully, `false` otherwise. |
| `syncError`        | `string \| undefined`    | Error message if the sync failed.                                                                                                                                                   |

***

#### Examples

**Simple sync**

```ts
await didomiRef.current!.syncUser();
```

**Reassurance notice flow**

```ts
const syncResult = await didomiRef.current!.syncUser();

if (syncResult.statusApplied) {
  // The user status actually changed from syncing

  // Show your reassurance notice to the user

  // Report that the reassurance notice has been shown
  const acknowledged = await syncResult.syncAcknowledged();
  console.log('Sync acknowledged:', acknowledged);
}
```

***

**Notes**

* Use `syncUser()` only when you need to **refresh consent state** in an SPA.
* Always check `statusApplied` — if it’s `false`, the local state is already up to date.
* If you show any UI reassurance (e.g., “Your preferences are updated”), remember to call `syncAcknowledged()`.

***

#### setUser

Update the user configuration details in a **single-page application**.\
In multi-page apps, do **not** call this method directly. Instead, set the user configuration details via `window.didomiConfig.user` on page load.

The function updates all the provided properties and sets any omitted properties to `undefined`.

**Signature**

```ts
didomi.setUser(userConfiguration: UserConfiguration): Promise<void>
```

**Parameters**

| Name                              | Type     | Description                                                  |
| --------------------------------- | -------- | ------------------------------------------------------------ |
| `organizationUserId`              | `string` | Organization User ID to associate with the user.             |
| `organizationUserIdAuthAlgorithm` | `string` | Algorithm used for computing the digest.                     |
| `organizationUserIdAuthSid`       | `string` | ID of the secret used for computing the digest.              |
| `organizationUserIdAuthSalt`      | `string` | Salt used for computing the digest.                          |
| `organizationUserIdAuthDigest`    | `string` | Digest of the organization user ID and secret.               |
| `organizationUserIdExp`           | `number` | Unix timestamp (expiration).                                 |
| `organizationUserIdIv`            | `string` | Initialization vector if encryption was used for the digest. |

**Returns**

* `Promise<void>`

**Example**

```ts
await didomiRef.current?.setUser({
  organizationUserId: 'organizationUserID',
  organizationUserIdAuthAlgorithm: 'HS256',
  organizationUserIdAuthSid: 'sid_123',
  organizationUserIdAuthSalt: 'random_salt',
  organizationUserIdAuthDigest: 'abcdef123456',
  organizationUserIdExp: 1699999999,
  organizationUserIdIv: 'iv_string'
});
```

**Notes**

* Call `setUser` **only once per session** unless you explicitly need to update the user identity.
* If you pass only a subset of fields, any omitted ones will be reset to `undefined`.
* Always ensure the digest values (if used) are generated securely on your backend.

***

### clearUser

Disassociate any user identifier from the current session.

**Signature**

```ts
didomi.clearUser(): Promise<void>
```

**Parameters**

* *None*

**Returns**

* `Promise<void>`

**Example**

```ts
await didomiRef.current?.clearUser();
```

***

### Notice Config

These helpers expose details about the loaded notice/config.

> Depending on your Vega integration, some fields may be undefined until `onReady`.

***

#### Types

Below are the key TypeScript interfaces surfaced by the SDK.

```ts
type DidomiEvent =
  | 'sdk.ready'
  | 'sdk.error'
  | 'notice.shown'
  | 'notice.hidden'
  | 'preferences.shown'
  | 'preferences.hidden'
  | 'preferences.saved'
  | 'consent.changed';

interface Vendor {
  id: string;
  name?: string;
  policyUrl?: string;
  purposeIds?: string[];
  [key: string]: unknown;
}

interface Purpose {
  id: string;
  name?: string;
  description?: string;
  [key: string]: unknown;
}

interface UserStatus {
  purposes: Record<string, 'granted' | 'denied'>;
  vendors: Record<string, 'granted' | 'denied'>;
  regulation?: 'gdpr' | 'cpra' | 'none' | string;
  updatedAt?: string;
}
```


# Events

You can subscribe to SDK events through component props or programmatically via the `ref`.

| Event                | Description                                      |
| -------------------- | ------------------------------------------------ |
| `onReady`            | Fired when the SDK is initialized and ready      |
| `onConsentChanged`   | Fired whenever the user’s consent status changes |
| `onNoticeShown`      | Fired when the notice is displayed               |
| `onNoticeHidden`     | Fired when the notice is closed                  |
| `onPreferencesShown` | Fired when the preferences dialog is displayed   |
| `onPreferencesSaved` | Fired when preferences are saved                 |


# Versions

#### 0.2.2 (Jun 25th, 2026) <a href="#id-2.30.0-september-17-2025" id="id-2.30.0-september-17-2025"></a>

* fix: `isCMPDisplayed` staying stuck after `preferences.hidden`. Notice and preferences visibility are now tracked independently and the displayed state is derived from both, so the CMP hides correctly when preferences close and stays visible when navigating back from preferences to the notice.
* fix: setCurrentUserStatus now performs partial consent updates

#### 0.2.1 (May 22nd, 2026) <a href="#id-2.30.0-september-17-2025" id="id-2.30.0-september-17-2025"></a>

* fix: preferences screen back navigation handling

#### 0.2.0 (May 6th, 2026) <a href="#id-2.30.0-september-17-2025" id="id-2.30.0-september-17-2025"></a>

* fix: missing mehods `notice.hide` and `preferences.hide`
* Add `onNoticeClickDisagree` event callback and improve `onError` callback
* fix: existing `click` events are incorrectly triggered

#### 0.1.0 (April 23rd, 2026) <a href="#id-2.30.0-september-17-2025" id="id-2.30.0-september-17-2025"></a>

* fix: inconsistent skdPath set by default

#### 0.0.2 (October 1st, 2025) <a href="#id-2.30.0-september-17-2025" id="id-2.30.0-september-17-2025"></a>

**Features:**

* Official release: upgrade to the latest Amazon Vega libraries


# Consent notice

The notice is required by the EU legislation on cookies and other tracking technologies and is also used for informing the user on other GDPR data processing and collecting consent. Before collecting data or processing it, you must let your users know that your app is using such tools and why, as well as give them options to opt out.

We are assuming that you already have an API key. If not, please go to our [website](https://www.didomi.io) and sign up for an account.

**Topics**

* [Customize the notice](/cmp/mobile-sdk/consent-notice/customize-the-notice)
* [Customize the theme](/cmp/mobile-sdk/consent-notice/customize-the-theme)


# Getting started

This section shows you how to configure a consent notice via a `didomi_config.json` file, or from the `Behavior` > `Custom json` field in the console. We recommend using our Console to configure your notice instead of a local configuration file.

In this section, you will learn how to display a consent notice to let your users know that you and your vendors are using cookies, personalizing content and advertising, etc. in your mobile applications.

The notice is fully compliant with the [IAB GDPR framework](http://advertisingconsent.eu/) and will share the consent information collected from users with third-parties adhering to this framework to let them know what processing they are allowed to run. We also offer options to control the loading or behavior of third-party SDKs.

{% hint style="warning" %}
**Make sure that our SDK is setup**

Before continuing, please read our section on setting up our SDK ([Android / Android TV](/cmp/mobile-sdk/android/setup) and [iOS / tvOS](/cmp/mobile-sdk/ios/setup)) to learn how to do the initial setup of our SDK. You must do that before being able to continue with the configuration of your SDK.
{% endhint %}

## Show the consent notice

Use the following `didomi_config.json` content to get started:

{% code title="Custom JSON" %}

```javascript
{
    "app": {
        "name": "My App Name",
        "privacyPolicyURL": "http://www.website.com/privacy",
        "vendors": {
            "iab": {
                "all": true
            }
        },
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    }
}
```

{% endcode %}

This will display our standard banner to all app users, collecting consent for all the IAB vendors (more on this later, for now, just keep in mind that if you remove the `vendors` property, no banner will be displayed as the banner will consider that there is no consent to collect). Keep reading to see what configuration options you can use to customize the banner.

## What visitors to collect consent for?

If you are an EU-based company then you must collect consent and enforce GDPR for all users no matter where they are located. There is no exception to that rule so you'll want to keep the properties `app.gdprAppliesGlobally` and `app.gdprAppliesWhenUnknown` to `true`.

If you are not an EU company then your only obligation is to enforce GDPR for EU-based users. We offer the following two configuration options for you to define what behavior you want:

* `app.gdprAppliesGlobally` defines whether GDPR should be applied to all visitors or not. If set to `true`, all visitors will see consent notices. If set to `false`, only visitors from the EU will see the consent notices.
* `app.gdprAppliesWhenUnknown` defines what to do when the user country is unknown. If the SDK is unable to determine the user country (because the device does not have a location, the location permission is not available, or there is no Internet connection), this flag will decide if the user should see a consent notice or not. If set to `true`, the user will see a consent notice when its country is unknown.

## Configure your app name and logo

The name of your website (or company) is used to customize our default messages.

Set the `app.name` and `app.logoUrl` properties to configure your app name and logo:

```javascript
{
    "app": {
        "name": "My App Name",
        "logoUrl": "nameOfTheAssetInYourAppBundle",
        "privacyPolicyURL": "http://www.website.com/privacy",
        "vendors": {
            "iab": {
                "all": true
            }
        },
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    }
}
```

{% hint style="info" %}
The `logoUrl` parameter can be the name of your logo in the assets of your app bundle, or an url leading to your logo.
{% endhint %}

{% hint style="warning" %}
When using a remote image url, svg format is not supported.
{% endhint %}

If `logoUrl` is provided and the image exists, then that image will be displayed at the top of the Preferences screen as shown below:

![](/files/-LqHlcpG3fMoQQu-Qmgf)

Otherwise, the `name` text will be displayed at the top of the Preferences screen as shown below:

![](/files/-LqHlNUkTHR4C3iX7iCO)

## Configure your supported languages (optional)

Our SDK supports multiple European languages out-of-the-box with translations for all our standard messages. See below if your website uses other languages.\
English is the default language: if a visitor does not use a supported language, the banner and popups will be displayed in English.

You do not need to do anything to use Didomi's languages. However, you can choose to enable only certain languages and set up a different default language.\
Set the `languages.enabled` property to your list of supported languages and `languages.default` property as the default language in case the customer language is not supported:

```javascript
{
    "app": {
        "name": "My App Name",
        "logoUrl": "nameOfTheAssetInYourAppBundle"
        "privacyPolicyURL": "http://www.website.com/privacy",
        "vendors": {
            "iab": {
                "all": true
            }
        },
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    },
    "languages": {
        "enabled": ["fr", "en"],
        "default": "fr"
    }
}
```

{% hint style="info" %}
By default, `enabled` is the list of supported languages by Didomi and `default` is `en.`

You can support a different language by changing the English texts and setting English as the only enabled language.
{% endhint %}

## Add your privacy policy URL

Our default text includes a link to your privacy policy. You can set that URL with the `app.privacyPolicyURL` property.

Example:

```javascript
{
    "app": {
        "name": "My App Name",
        "logoUrl": "nameOfTheAssetInYourAppBundle",
        "privacyPolicyURL": "http://www.website.com/privacy",
        "vendors": {
            "iab": {
                "all": true
            }
        },
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    }
}
```

## Customize the consent notice

We offer further configuration options to customize the notice for your app.\
For instance, you can pretty easily change the colors of the notice and the buttons by setting the theme's primary color:

```javascript
{
    "app": {
        "name": "My App Name",
        "logoUrl": "nameOfTheAssetInYourAppBundle",
        "privacyPolicyURL": "http://www.website.com/privacy",
        "vendors": {
            "iab": {
                "all": true
            }
        },
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    },
    "theme": {
        "color": "#BD081C"
    }
}
```

You can also customize the shape and position of the notice and much more. Read the [Customization](/cmp/web-sdk/consent-notice/notice) section to get more information on the configuration options of the notice.

## Configure vendors and purposes

As per the regulation, the consent notice collects consents for a specific set of vendors and purposes.\
You must configure the notice to let it know what vendors are used on your website and it will automatically determine what purposes are required.

Read our dedicated section to [learn how to configure your vendors](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/cmp/mobile-sdk/consent-notice/broken-reference/README.md).

## Add a link for the user to manage their preferences

After the user has given consent or closed the banner, you must given them an easy access to their choices so that they can update them.

You can use the function `showPreferences()` (see the [Android](/cmp/mobile-sdk/android/reference/api#showpreferences) or [iOS](/cmp/mobile-sdk/ios/reference/api#showpreferences) documentation) to open the preferences manager and let the user update her choices.

We suggest adding this link in your privacy policy or in a header or footer menu in your app.

## What's next?

There is plenty more to customize on our banner, read the following sections for more information:

* [Customize the banner](/cmp/mobile-sdk/consent-notice/customize-the-notice)
* [Customize the preferences popup](/cmp/mobile-sdk/consent-notice/customize-the-preferences-popup)
* [Configure the vendors and purposes](https://gitlab.com/didomi/developers-documentation/-/tree/main/docs/cmp/mobile-sdk/consent-notice/broken-reference/README.md)


# Customize the notice

The notice is the first banner or pop-in that gets displayed on your app to ask the user to give consent. It is a short version of the full Preferences pop-in that has all the details on the purposes and vendors that you are collecting consent for.

This section presents the main customization options that are available for the consent notice.

## Country and GDPR

If you are an EU-based company then you must collect consent and enforce GDPR for all users no matter where they are located. There is no exception to that rule so you'll want to keep the properties `app.gdprAppliesGlobally` and `app.gdprAppliesWhenUnknown` to `true`.

If you are not an EU company then your only obligation is to enforce GDPR for EU-based users. We offer the following two configuration options for you to define what behavior you want:

* `app.gdprAppliesGlobally` defines whether GDPR should be applied to all visitors or not. If set to `true`, all visitors will see consent notices. If set to `false`, only visitors from the EU will see the consent notices.
* `app.gdprAppliesWhenUnknown` defines what to do when the user country is unknown. If the SDK is unable to determine the user country (because the device does not have a location, the location permission is not available, or there is no Internet connection), this flag will decide if the user should see a consent notice or not. If set to `true`, the user will see a consent notice when its country is unknown.

Example:

{% code title="Custom JSON" %}

```javascript
{
    "app": {
        "gdprAppliesGlobally": true,
        "gdprAppliesWhenUnknown": true
    }
}
```

{% endcode %}

### Publisher country

You can define your publisher country code by setting `app.country` property in the configuration file (2 letters, ISO 3166-1 alpha-2). This value will be used when generating the IAB TCF consent, both in the consent string and stored on device with the `IABTCF_PublisherCC` key.

Example:

{% code title="Custom JSON" %}

```javascript
{
    "app": {
        "country": "ES"
    }
}
```

{% endcode %}

## Supported languages

Our SDK supports multiple languages out-of-the-box with translations for all our standard messages. See below if your website uses other languages.\
English is the default language: if a visitor does not use a supported language, the banner and popups will be displayed in English.

You do not need to do anything to use Didomi's languages. However, you can choose to enable only certain languages and set up a different default language.\
Set the `languages.enabled` property to your list of supported languages and `languages.default` property as the default language in case the customer language is not supported:

{% code title="Custom JSON" %}

```javascript
{
  "languages": {
    "enabled": ['en', 'fr'],
    "default": 'fr'
  }
}
```

{% endcode %}

By default, `enabled` is the list of supported languages by Didomi and `default` is `en`. You can support a different language by changing the English texts and setting English as the only enabled language.

We currently support the following languages: [Translations](/api-and-platform/introduction/translations#languages-supported)

## Position (Mobile only)

On mobile, the notice can be displayed as a popup or a regular bottom banner.

The `notice.position` configuration parameter lets you define the position of the notice. The possible values are:

| Values   | Description                                                                                                            |
| -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `popup`  | Display the notice as a full-screen popup. Also set your website logo and name to make sure the popup is personalized. |
| `bottom` | Display a banner notice at the bottom of the screen                                                                    |

Examples:

{% tabs %}
{% tab title="Bottom banner" %}
{% code title="Custom JSON" %}

```javascript
{
  "notice": {
    "position": "bottom"
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="Popup" %}
{% code title="Custom JSON" %}

```javascript
{
  "notice": {
    "position": "popup"
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Disagree & Close

You can enable the "Disagree & Close" option from the notice by setting the `denyOptions` property. In this case, the "Learn More" button will be shown as a link.

To show a button containing the "Disagree & Close" text, set the `denyOptions.button` property to `primary` or `secondary`. Default is `none`. Note that on TV, the Disagree & Close button will always be displayed with the same style, whether the property is set to `primary` or `secondary`.

#### Disagree & Close as primary

You can show the "Disagree & Close" button styled as a primary button by setting the `denyOptions.button` to `primary` as shown below:

{% code title="Custom JSON" %}

```json
{
    "notice": {
        "denyOptions": {
            "button": "primary"
        }
    }
}
```

{% endcode %}

Expected result:

![Disagree & Close button when deny button is set to primary (mobile)](/files/GGRjw72FNqZ4eBKQNcaF)

<figure><img src="/files/TURMqMXu1tcwxcT8YXJj" alt=""><figcaption><p>Disagree &#x26; Close button when deny button is set to primary or secondary (TV)</p></figcaption></figure>

#### Disagree & Close as secondary

On mobile, you can show the "Disagree & Close" button styled as a secondary button by setting the `denyOptions.button` to `secondary` as shown below:

{% code title="Custom JSON" %}

```json
{
    "notice": {
        "denyOptions": {
            "button": "secondary"
        }
    }
}
```

{% endcode %}

Expected result:

![Disagree & Close button when deny button is set to secondary (mobile)](/files/j9VlabPze5HAfOih5V4p)

#### Remove Disagree & Close button

To make sure the "Disagree & Close" button is not displayed, you can disable it by setting `denyOptions.button` to `none`, as shown below:

{% code title="Custom JSON" %}

```json
{
    "notice": {
        "denyOptions": {
            "button": "none"
        }
    }
}
```

{% endcode %}

### "Continue without agreeing" link (mobile)

On mobile, you can also display a "Continue without agreeing" link rather than the "Disagree & Close" button by setting the `denyOptions.link` property to `true` and `denyOptions.button` to `none`, as shown below:

{% code title="Custom JSON" %}

```json
{
    "notice": {
        "denyOptions": {
            "link": true,
            "button": "none"
        }
    }
}
```

{% endcode %}

Expected result:

The "Continue without agreeing" link has the same behavior as the "Disagree & Close" button.

### Close cross (mobile)

In order to comply with Italian regulations, you should display a cross allowing users to close the notice. On mobile, you can display a cross instead of the "Continue without agreeing" link by setting the `denyOptions.cross` property to `true` and `denyOptions.button` to `none`, as shown below:

{% code title="Custom JSON" %}

```json
{
    "notice": {
        "denyOptions": {
            "cross": true,
            "button": "none"
        }
    }
}
```

{% endcode %}

Expected result:

![Cross allowing to close the notice without agreeing](/files/iX62Pg3lYybSvIax2Oti)

The cross has the same behavior as the "Disagree & Close" button.

### "Disagree" and legitimate interest

By default, "Disagree & close" and "Continue without agreeing" only apply to consent, not legitimate interest. This means that after this option was selected, purposes based on legitimate interest will still be enabled, and vendors using these purposes will still be enabled for data processing based on legitimate interest.

This behavior can be controlled by setting the `denyAppliesToLI` property. When set to `true`, selecting "Disagree & close" or "Continue without agreeing" will disable both consent and legitimate interest based data processing for all purposes and all vendors..json

{% code title="Custom JSON" %}

```json
{
    "notice": {
        "denyOptions": {
            "button": "primary"
        },
        "denyAppliesToLI": true
    }
}
```

{% endcode %}

## Texts

You can change the message of the notice as well as the "Agree & Close" and "Learn More" buttons.

| Configuration Key               | Description                    |
| ------------------------------- | ------------------------------ |
| `notice.content.title`          | Title of the banner or popup   |
| `notice.content.notice`         | Message in the banner or popup |
| `notice.content.dismiss`        | "Agree & Close" button         |
| `notice.content.deny`           | "Disagree & Close" button      |
| `notice.content.learnMore`      | "Learn More" button            |
| `notice.content.privacyPolicy*` | "Our Privacy Policy" button    |

*\* Fields marked with asterisk are relevant only for TV SDKs for now*

Example:

{% code title="didomi\_config.json" %}

```javascript
{
  "notice": {
    "content": {
      "notice": {
        "en": "This website uses cookies to provide you with tailored commercial offers",
        "fr": "Ce site utilise des cookies pour vous fournir des offres commerciales personalisées"
      },
      "dismiss": {
        "en": "Agree & Close",
        "fr": "Accepter et fermer"
      },
      "deny": {
        "en": "Disagree & Close",
        "fr": "Refuser et fermer"
      },
      "learnMore": {
        "en": "Learn More",
        "fr": "En savoir plus"
      },
      "privacyPolicy": {
        "en": "Our Privacy Policy",
        "fr": "Notre politique de confidentialité"
      },
      "viewOurPartners": {
        "en": "View our partners",
        "fr": "Voir nos partenaires"
      }
    }
  }
}
```

{% endcode %}

Note that you should provide translations for all the languages that your app supports. We provide translations for all our standard messages.

## Vendors and purposes

You must configure the vendors for which consent is collected by our consent notice and displayed in the preferences popup.

## Window for recollecting consent

By default, consent is automatically re-collected and the notice is displayed in these cases:

* After 13 months (maximum acceptable cookie lifetime)
* When a new vendor is added in the IAB vendors list (if you choose the option `all`)

The third case (a new vendor is added) can happen pretty often so you have the option to choose a number of days during which the notice will not be displayed even though there are new vendors to collect consent for. By default, the number is zero and the notice will be displayed automatically if a new vendor is added.

During that consent recollection window:

* New users will be asked for consent for the new vendor immediately.
* Previous users that had already given consent within the window (ie less than X days ago) will not be asked again until the expiration of the window. The new vendor will not have consent during that time.
* Previous users that had already given consent outside of the window (ie more than X days ago) will be asked again immediately.

```javascript
{
    "notice": {
        "daysBeforeShowingAgain": 5 // Number of days. Default is 0
    }
 } 
```

{% hint style="info" %}
If you choose that option and because the notice is not shown again, the user consent status will be partial and some vendors will not have consent information. The function `Didomi.isUserConsentStatusPartial()` can return `true` in these cases.
{% endhint %}

## Recollect consent after a certain date

In some cases, you might want to force recollect consent for all users after a certain date, irrespective of their choices and the configured window for recollecting consent.

This can be achieved by setting an ISO8601 date in the `user.ignoreConsentBefore` property:

```javascript
{
    "user": {
       "ignoreConsentBefore": "2020-09-09T00:00:00Z"
    }
}
```

When the user has given consent before the provided date, consent will be automatically recollected. Dates in the future are ignored until they become current so you can schedule a consent recollection for a specific date in the future.

## Consent expiration

Didomi CMP allows you to customize the lifetime of the consent so that it expires after a specific time.

You can use `app.consentDuration` configuration option to specify custom consent duration:

```javascript
{
    "app": {
        "consentDuration": 2592000 // Custom consent duration in seconds
    }
}
```

The `app.consentDuration` configuration option accepts custom consent duration value in seconds.

By default, consent expires after 31,622,400 seconds (approximately 12 months) if custom consent duration is not specified.

## Denied consent duration

It is possible to apply a specific consent duration when user denies consent for all purposes and vendors. This is done by setting the `app.deniedConsentDuration` configuration option.

```javascript
{
    "app": {
        "deniedConsentDuration": 1296000 // Denied consent duration in seconds
    }
}
```

If this option is set and user disagrees to consent based data processing for all purposes and vendors (legitimate interest based data processing is ignored), the consent will expire after this time instead of the standard consent duration, and user consent will be asked again.

{% hint style="info" %}
If user selects "disagree to all" button from notice or from preferences screen, and `app.deniedConsentDuration` is set, this duration will apply.

`app.deniedConsentDuration` value should be shorter than `app.consentDuration`, otherwise it will be ignored.
{% endhint %}

The `app.deniedConsentDuration` configuration option accepts custom consent duration value in seconds.

If no value is set, the standard consent duration will still be applied to denied consents.




---

[Next Page](/llms-full.txt/1)

