# Web CMP

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

You can find details on each release here : [Release notes page](https://docs.sfbx.io/help/release-notes).
{% endhint %}

## Main steps to implement a web notice

{% hint style="info" %}
You wish integrate AppConsent into Shopify? See the dedicated page: [Implement Appconsent with Shopify](https://docs.sfbx.io/configuration/step-3-notice-implementation-web-app-tv/web-cmp/implement-with-shopify)
{% endhint %}

### 1. Implement the notice

{% hint style="info" %}
Open your HTML code source first.
{% endhint %}

1. Go to **Notices** tab in AppConsent configuration interface
2. Then under the notice you wish to integrate, copy the integration code using the "Copy" button

<figure><img src="https://4229351976-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkyFlZKFaKP4MUM0zILOg%2Fuploads%2F7fK0Hw4SkqYFhTUrnSi8%2Fcmp-web-implementation.png?alt=media&#x26;token=debcd58a-55af-4b6b-a362-f993d2977b4f" alt=""><figcaption></figcaption></figure>

3. Finally, paste the code in the `<head>` tag in your website

### 2. Add privacy center

With the GDPR, you have an obligation to provide a way for the user to be able to change their choices at any time and easily. That's why you need to add privacy center kit.

To configure and implement the privacy widget: see the [Display privacy widget](https://docs.sfbx.io/go-further/compliance/display-privacy-widget) page.

### 3. Results

Congratulations! You have now finished setting up the CMP, your code should look like this :

```html
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Your Website</title>
    <!-- MANDATORY: BEGIN IAB STUB -->
    <script type="text/javascript">
        !function(){var e=function(){var e,t="__tcfapiLocator",a=[],n=window;for(;n;){try{if(n.frames[t]){e=n;break}}catch(e){}if(n===window.top)break;n=n.parent}e||(!function e(){var a=n.document,r=!!n.frames[t];if(!r)if(a.body){var s=a.createElement("iframe");s.style.cssText="display:none",s.name=t,a.body.appendChild(s)}else setTimeout(e,5);return!r}(),n.__tcfapi=function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return a;if("setGdprApplies"===n[0])n.length>3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0));else if("ping"===n[0]){var s={gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"};"function"==typeof n[2]&&n[2](s)}else a.push(n)},n.addEventListener("message",(function(e){var t="string"==typeof e.data,a={};try{a=t?JSON.parse(e.data):e.data}catch(e){}var n=a.__tcfapiCall;n&&window.__tcfapi(n.command,n.version,(function(a,r){var s={__tcfapiReturn:{returnValue:a,success:r,callId:n.callId}};t&&(s=JSON.stringify(s)),e&&e.source&&e.source.postMessage&&e.source.postMessage(s,"*")}),n.parameter)}),!1))};"undefined"!=typeof module?module.exports=e:e()}();
    </script>
    <!-- MANDATORY: END IAB STUB -->

    <script type="text/javascript">
        const configSFBXAppConsent = {
            appKey: 'YOUR_APP_KEY'
        }
    </script>
    <script src="https://cdn.appconsent.io/tcf2-clear/current/core.bundle.js" defer async></script>
</head>
<body></body>
</html>
```

***

## Migrated your old configuration

Since version 29.0.0, the implementation of cmp in your website has been simplified. For users who have configured the cmp before this release, we have provided a guide to migrate to the new configuration.

[Configuration Migration Guide](#migrated-your-old-configuration)

***

## Go further

Now that you have implemented your CMP you can put some extra commands or settings by reading the following instructions.

### How heavy is this CMP ?

We're leveraging chunking to alleviate bandwidth. Code for the UI is only downloaded when user interaction is needed. Our core bundle is about 55 KB.

### Advanced properties for the configSFBXAppconsent configuration

All of the properties listed below are **optional.**

#### Debug mode

Active verbose logging in the browser console.

| Property  name | Type    | Default value |
| -------------- | ------- | ------------- |
| debug          | Boolean | false         |

Implementation example:&#x20;

```javascript
var configSFBXAppConsent = {
    appKey: 'YOUR_APPKEY',
    debug: true,
}
```

#### Activate GCM mode

Enables Google Ads & Analytics blocking.&#x20;

{% hint style="info" %}
We recommend that you enable this feature using the configuration interface ( Back-Office ) instead of using the code.. To learn how to implement GCM with AppConsent, see the [AppConsent configuration for Google Analytics](https://docs.sfbx.io/configuration/google-gtm/manage-google-analytics#appconsent-configuration-for-google-analytics-google-consent-mode-advanced-mode-gcmv2) section.
{% endhint %}

| Property  name | Type    | Default value |
| -------------- | ------- | ------------- |
| enableGCM      | boolean | false         |

Implementation example:&#x20;

```javascript
var configSFBXAppConsent = {
    appKey: 'YOUR_APPKEY',
    enableGCM: true,
}
```

#### Enforce compliance with the GDPR

Forces GDPR application for all visitors from any country in the world

| Property  name   | Type    | Default value |
| ---------------- | ------- | ------------- |
| forceGDPRApplies | boolean | false         |

Implementation example:&#x20;

```javascript
var configSFBXAppConsent = {
    appKey: 'YOUR_APPKEY',
    forceGDPRApplies: true,
}
```

#### Set GDPR applicability&#x20;

Manually sets GDPR applicability: `true` = applies, `false` = doesn’t apply, `null` = automatic

| Property  name | Type            | Default value |
| -------------- | --------------- | ------------- |
| gdprApplies    | boolean \| null | null          |

Implementation example:&#x20;

```javascript
var configSFBXAppConsent = {
    appKey: 'YOUR_APPKEY',
    gdprApplies: true,
}
```

#### Inject script after user consent

List of script URLs that should loaded and executed after the user consent. If your script relies on consent, use the [addEventListener method of \_\_tcfApi](#addeventlistener)&#x20;

| Property  name       | Type      | Default value |
| -------------------- | --------- | ------------- |
| thirdPartyScriptURLs | string\[] | \[]           |

Implementation example:&#x20;

```javascript
var configSFBXAppConsent = {
    appKey: 'YOUR_APPKEY',
    thirdPartyScriptURLs: ["https://www.your-site.com/script.js"]
}
```

#### Force uuid consent

For specific use cases like cross-domain or cross-device consent propagation, you can set your proper UUID. You must use unique UUID like UUIDv4 in order to avoid collisionning issue.

| Property  name | Type           | Default value |
| -------------- | -------------- | ------------- |
| uuid           | string \| null | null          |

Implementation example:&#x20;

```javascript
var configSFBXAppConsent = {
    appKey: 'YOUR_APPKEY',
    uuid: "7ab109-1203-4975-a2e5-c2ac148c3148"
}
```

#### Define time between two configuration checking&#x20;

Defines maximum cache duration between the calls `hello` .

| Property  name          | Type   | Default value |
| ----------------------- | ------ | ------------- |
| cmpVersionCacheDuration | number | 1800          |

Implementation example:&#x20;

```javascript
var configSFBXAppConsent = {
    appKey: 'YOUR_APPKEY',
    cmpVersionCacheDuration: 1800
}
```

#### Configuration url redirection after user action

Allow to define a redirection url after the user click on "accept all", "refuse all" and "continue without accepting"

| Property  name | Type   | Default value |
| -------------- | ------ | ------------- |
| urlRedirect    | object | null          |

Implementation example:&#x20;

```javascript
var configSFBXAppConsent = {
    appKey: 'YOUR_APPKEY',
    urlRedirect: {
      main: {
           denyAll : 'someURL',
           acceptAll : 'someURL',
           continueWithoutAccepting : 'someURL',
      },
      settings : {
           denyAll : 'someURL',
           acceptAll : 'someURL',
       }
   }
}
```

#### CMP callbacks

Allows you to define javascript callbacks on the events of cmp. The events are as follows:

* init : Triggers at the end of CMP initialization
* show: Triggers when the CMP is displayed
* listener: Triggered each time the iab listener is triggered
* choiceDone: Triggers when a user gives consent
* adcDetected: Triggers when a user blocks the display of the cmp using the Apple Distraction Control (ADC) feature
* adcUnblocked: Triggers when a user unlocks the CMP display and provides consent

| Property  name | Type   | Default value |
| -------------- | ------ | ------------- |
| enableGCM      | object | null          |

Implementation example:&#x20;

```javascript
var configSFBXAppConsent = {
    appKey: 'YOUR_APPKEY',
    callbacks: {
    init: (error, state) => {},
    show: (error) => {},
    listener: (tcData, success) => {},
    choiceDone: (tcData, success) => {},
    adcDetected: () => {},
    adcUnblocked: () => {},
  }
}
```

### Commands / CMP Calls

CMP can be controlled through iAB's `__tcfApi` global function, as [documented](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#what-required-api-commands-must-a-cmp-support).

#### addEventListener

This IAB command allows you to listen for events related to the consent string.

```javascript
__tcfapi('addEventListener', 2, function (tcData, success) {
    // some codes
})
```

**Getting Consent Object in JS**

Very simple example :

In this example, the `success` variable triggers the code to run once a user has given their consent.

```javascript
__tcfapi("addEventListener", 2, (tcData, success) => {
  if (success) {
    console.log(tcData.tcString);
  } else {
    // do something else
  }
});
```

Will output your tcString V2.3 in your console :

```javascript
CQhXYwAQhXYwAACAKAFRCKFgAPLAAELAAAqIF5wAQF5gXnABAXmAAAAA.IF5wAQF5gAAA.YAAAAAAAAAAA
```

**Working with tcData**

An example of retrieving the status of a purpose :

```javascript
__tcfapi("addEventListener", 2, (tcData, success) => {
  if (success) {
    console.log(tcData.purpose.consents[4]); // Here checking the state of purpose 4
  }
});
```

An example of retrieving the status of a vendor :

```javascript
__tcfapi("addEventListener", 2, (tcData, success) => {
  if (success) {
    console.log(tcData.vendor.consents[755]); // Here checking the state of Google vendor
  }
});
```

Another example of retrieving the status of an extra purpose:&#x20;

```javascript
__tcfapi("addEventListener", 2, (tcData, success) => {
  if (success) {
    console.log(tcData.extraPurpose.consents['taxK3L1v']); // Here checking the state of an extra purpose
  }
});
```

More information in the official IAB Documentation [here](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#addeventlistener).

#### accept

Registers a full consent on the CMP, as the user would have clicked on the "accept everything" button. The default behavior is to prevent overwriting any existing consent. You can force overwriting by specifying a special `force` parameter.

{% hint style="warning" %}
As this command forces an “accept all” action, make sure it is used appropriately
{% endhint %}

Note that no matter the outcome, this call will hide the UI.

| Argument  | Type     | Optional | Value                    |
| --------- | -------- | -------- | ------------------------ |
| command   | string   |          | `'accept'`               |
| version   | number   |          | `2`                      |
| callback  | function |          | `function(error: Error)` |
| parameter | Object   |          | AcceptOption             |

**Example:**

```javascript
__tcfapi("accept", 2, console.log);
```

#### deny

Registers a full consent on the CMP, as the user would have clicked on the "deny everything" button. The default behavior is to prevent overwriting any existing consent. You can force overwriting by specifying a special `force` parameter.

{% hint style="warning" %}
As this command forces an “deny all” action, make sure it is used appropriately
{% endhint %}

Note that no matter the outcome, this call will hide the UI.

| Argument  | Type     | Optional | Value                    |
| --------- | -------- | -------- | ------------------------ |
| command   | string   |          | `'deny'`                 |
| version   | number   |          | `2`                      |
| callback  | function |          | `function(error: Error)` |
| parameter |          |          |                          |

**Example:**

```javascript
__tcfapi("deny", 2, console.log);
```

#### fakeDeny

Generate a deny consent string and return it to all vendors without storing it as a valid user consent. This helps prevent non-compliant vendors from interpreting the absence of consent as granted. This will NOT hide the UI.

| Argument  | Type     | Optional | Value                    |
| --------- | -------- | -------- | ------------------------ |
| command   | string   |          | `'fakedeny'`             |
| version   | number   |          | `2`                      |
| callback  | function |          | `function(error: Error)` |
| parameter |          |          |                          |

**Example:**

```javascript
__tcfapi("fakedeny", 2, console.log);
```

### Passing commands in URL

You can pass commands to the CMP through the querystring. Querystring commands are evaluated on init.

`?ac_cmd=show`

The above link would show the CMP on init.

For more specific needs, other orders exist. Please contact the [support](mailto:support-cmp@sfbx.io).

You can also pass parameters to the command with the same mechanism. Parameters are passed as is from the querystring. Consider the following example:

`?ac_cmd=show&jumpAt=banner`

### Edition of consents without displaying the CMP

When you website embeds external integrations (Youtube, Twitch, Twitter, etc.), you may need to modify consents of a user (with their agreement) to give access to this content without redisplaying the CMP. To do this, you can use the `updateStatus` function. This is how to use it:

```javascript
__tcfapi('updateStatus', 2, () => {}, [{t: <type>, id: <id>, status: <bool-value> }])
```

The list of possible types `<type>` is the following one:

1 - Purpose

2 - Extra purpose

3 - Special feature

4 - IAB vendor

5 - Extra vendor

The ID `<id>` is the one of the object you want to enable/disable. Its nature depends on the object represented by `<type>`. You can see the list of available types and IDs for your notice through `getTCData` call (see usage example here).

The value `<bool-value>` enables (`true`) or disables (`false`) for the tuple `(<type>, <id>)`.

An error will be returned if the consent of the user does not exist yet, of if any of the input combinations `(<type>, <id>)` does not exist in the array in argument.

To find the latest updates of the CMP, see the [Release Notes](https://docs.sfbx.io/help/release-notes) section.
