# Working with iframes

iframes on your website can use the commands provided by the [CMP API](https://cmp.docs.sirdata.net/v/en/cmp-api/how-it-works).\
They can do this by making calls to the parent's (or ancestor's) frame that the CMP is loaded on, sending the commands as a message with the `postMessage()` function.

The frame to make the call to can be determined by the ancestor by looking for a`.frames["__tcfapiLocator"]` child.

### Send a command <a href="#iframe-send-command" id="iframe-send-command"></a>

The message to send should have the below form where the `__tcfapiCall` object holds the information about the command to execute.\
`command` and `parameter` are the same as the parameters passed to the `__tcfapi()` function, and `callId` est un ID unique à déterminer.

{% tabs %}
{% tab title="\_\_tcfapiCall format" %}

```javascript
{
  __tcfapiCall: {
   command: *command*, // name of the command to execute
   version: 2, // version of the TCF specification
   parameter: *parameter*, // parameter to be passed to the command function
   callId: *uniqueId* // unique call ID
   }
}
```

{% endtab %}

{% tab title="Example" %}

```javascript
this.callId = this.callId || 0;
var message = {
	__tcfapiCall: {
		command: 'getTCData',
		version: 2,
		parameter: null,
		callId: ++this.callId
	}
};
window.top.postMessage(message, '*');
```

{% endtab %}
{% endtabs %}

### Retrieve the command result <a href="#iframe-get-result" id="iframe-get-result"></a>

Before sending messages, the iframe must define a JavaScript function to execute when a message is sent back. To do this, it must add a listener for the event message with the `window.addEventListener()` function.\
By doing this, it will be able to receive and process the command result in `__tcfapiReturn`.

{% hint style="danger" %}
The`window.addEventListener()`function is different from the [addEventListener](https://cmp.docs.sirdata.net/v/en/cmp-api/examples#add-a-listener) command, which is included in the CMP API.
{% endhint %}

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

```javascript
function processMessage(event) {
	if (event && event.data && event.data.__tcfapiReturn && event.data.__tcfapiReturn.success) {
		console.log(event.data.__tcfapiReturn.returnValue);
	}
}
window.addEventListener('message', processMessage);
```

{% endtab %}
{% endtabs %}

When a command is sent, the returned message (*event.data*) holds the `__tcfapiReturn` object with the command result.\
`returnValue` and `success` are the same as the parameters passed to the callback of the `__tcfapi()` function, and `callId` is the ID from the origin call (`__tcfapiCall`).

{% tabs %}
{% tab title="\_\_tcfapiReturn format" %}

```javascript
{
    __tcfapiReturn: {
      returnValue: *returnValue*, // result of the command
      success: *boolean*, // true if the call to the command was successful
       callId: *uniqueId* // call ID sent in the __tcfapiCall
    }
}
```

{% endtab %}

{% tab title="Example" %}

```javascript
function processMessage(event) {
	if (event && event.data && event.data.__tcfapiReturn && event.data.__tcfapiReturn.success) {
		var tcData = event.data.__tcfapiReturn.returnValue;
		if (!tcData.gdprApplies) {
			console.log("GDPR doesn't apply to user");
		}
		console.log("TC String : ", tcData.tcString);
	}
}
window.addEventListener('message', processMessage);

this.callId = this.callId || 0;
var message = {
	__tcfapiCall: {
		command: 'addEventListener',
		version: 2,
		parameter: null,
		callId: ++this.callId
	}
};
window.top.postMessage(message, '*');
```

{% endtab %}
{% endtabs %}

Below is an example script that emulates the in-frame `__tcfapi()` call.

It locates the ancestor frame running the CMP, performs the `postMessage` and listens for the return message and passes its values to the callback.

In other words, the scripts in the iframe will work as if the CMP was loaded directly into it.

```javascript
<script>
    !function(){var a=window,c;var o={};for(;a;){try{if(a.frames.__tcfapiLocator){c=a;break}}catch(a){}if(a===window.top)break;a=a.parent}window.__tcfapi=function(a,t,n,e){c?(t={__tcfapiCall:{command:a,parameter:e,version:t,callId:e=Math.random()+""}},o[e]=n,c.postMessage(t,"*")):n({msg:"CMP not found"},!1)},window.addEventListener("message",function(a){var t={};try{t="string"==typeof a.data?JSON.parse(a.data):a.data}catch(a){}var n=t.__tcfapiReturn;n&&"function"==typeof o[n.callId]&&(o[n.callId](n.returnValue,n.success))},!1);window.__sdcmpapi=window.__tcfapi;}();
</script>
```

{% hint style="warning" %}
Do not load the CMP scripts as well :)
{% endhint %}
