# Blocking tags using Guardian

Asking consent is not enough for your website, you need to be sure that cookies or others tracking technologies are not used without the consent of the user.

**For this, we propose a script called Guardian.**

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

At this point, we assume that you followed the instructions in this section to install the CMP
{% endhint %}

## 1. Setup the whitelist/blacklist list in the `<head>`

In the `<head>` section, configure the urls to be blacklisted or whitelisted in the **dynamicallyLoadedScripts** in the parameter of the **configSFBXAppConsent** configuration variable like this :

```html
<script type="text/javascript">
    const configSFBXAppConsent = {
        appKey: 'YOUR_APP_KEY',
        dynamicallyLoadedScripts: {
            blacklist: [
                /facebook/, /youtube/,
            ],
            whitelist: [
                /appconsent/,
            ]
        },
    }
</script>
```

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

In the code above, we take control on Facebook and Youtube. If you want to add a new domain, let's say **ads-twitter.com, just add this new entry**

```
,/ads-twitter.com/
```

{% endhint %}

## 2. Add the Guardian script

Add the Guardian script in the `<head>` section, after the definition of the **configSFBXAppConsent** variable.

```html
<script>
    (function(h,p){typeof exports=="object"&&typeof module<"u"?p(exports):typeof define=="function"&&define.amd?define(["exports"],p):(h=typeof globalThis<"u"?globalThis:h||self,p(h.sfbxguardian={}))})(this,function(h){"use strict";let p=!1;function P(t){function e(i){for(var s=0,r=0;r<i.length;r++)s=i.charCodeAt(r)+((s<<5)-s);return s}function n(i){return"hsl("+e(i)%360+", 100%, 80%)"}return function(i,...s){if(p&&console.log){if(i instanceof Error&&console.error){console.error(i);return}console.log("%c "+t+" %c "+i,"background: "+n(t)+"; color: #000","",...s)}}}function _(t){if(t===void 0)return p;p=!!t}const B=()=>{const t=window.location.search.substr(1).split("&");if(t==="")return{};for(var e={},n=0;n<t.length;++n){var i=t[n].split("=",2);if(i.length===1)e[i[0]]="";else{var s=decodeURIComponent(i[1].replace(/\+/g," "));s==="false"&&(s=!1),s==="0"&&(s=0),s==="true"&&(s=!0),s===""&&(s=null),e[i[0]]=s}}return e},d=P("guardian"),H=()=>{const t=B();(t.ac_cmd&&t.ac_cmd==="debug"||configSFBXAppConsent&&configSFBXAppConsent.debug)&&_(!0)},f="javascript/blocked",F="application/javascript",c={SCRIPT:"SCRIPT",IFRAME:"IFRAME",BLOCKQUOTE:"BLOCKQUOTE"},w=[c.SCRIPT,c.IFRAME,c.BLOCKQUOTE],o={blacklist:configSFBXAppConsent.dynamicallyLoadedScripts.blacklist,whitelist:configSFBXAppConsent.dynamicallyLoadedScripts.whitelist},l={blacklisted:[],hiddenBlacklisted:[]},U="sfbx_guardian_",b={INSTAGRAM:"instagram-media",TWITTER:"twitter-tweet",TIKTOK:"tiktok-embed"},g={};g[b.INSTAGRAM]="instagram.com",g[b.TIKTOK]="tiktok.com",g[b.TWITTER]="twitter.com";const D=[b.INSTAGRAM,b.TWITTER,b.TIKTOK],k=t=>{switch(t.tagName){case c.BLOCKQUOTE:return j(t);case c.IFRAME:case c.SCRIPT:return K(t)}},K=t=>t.src&&(!t.type||t.type!==f)&&E(t.src),j=function(t){return t.className.split(" ").some(n=>D.includes(n)&&W(n))},W=function(t){const e=g[t];return E(e)},E=t=>(!o.blacklist||o.blacklist.some(e=>e.test(t)))&&(!o.whitelist||o.whitelist.every(e=>!e.test(t))),v=t=>{switch(t.tagName){case c.BLOCKQUOTE:return q(t);case c.IFRAME:case c.SCRIPT:return X(t)}},X=function(t){const e=t.getAttribute("src");return A(e)},q=function(t){return t.className.split(" ").some(n=>G(n))},G=function(t){const e=g[t];return A(e)};function A(t){return o.blacklist&&o.blacklist.every(e=>!e.test(t))||o.whitelist&&o.whitelist.some(e=>e.test(t))}const Q=t=>t.offsetHeight>0&&t.offsetWidth>0,u=(t,e)=>{Object.keys(e).forEach(n=>{t.style[n]=e[n]})},$=function(){let t="";const e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for(let n=0;n<8;n++)t+=e.charAt(Math.floor(Math.random()*e.length));return t},S="#0252B6",V={width:"100%",height:"100%",display:"flex",justifyContent:"center",alignItems:"center"},z={display:"flex",flexDirection:"column",borderRadius:"9px",backgroundColor:"white",padding:"20px",border:`1px solid${S}`,fontFamily:"Montserrat, Roboto, Tahoma, Helvetica, Arial, sans-serif"},Y={display:"flex",justifyContent:"center",marginTop:"20px"},J={display:"flex",justifyContent:"center",alignItems:"center",padding:"10px 20px",borderRadius:"6px",fontStyle:"normal",fontWeight:"500",fontSize:"1.1rem",borderColor:`1px solid ${S}`,cursor:"pointer",backgroundColor:`${S}`,color:"white",boxShadow:"none",letterSpacing:"0.05rem"},Z={fontSize:"1rem",fontWeight:400,color:"#02244F",lineHeight:"1.6rem"};class ee{constructor(e,n,i){this.node=e,this.parentElement=i,this.id=n,this.isVisible=!0,this.wrapper=document.createElement("div"),this.init()}init(){this.isVisible=Q(this.node),this.isVisible||this.addToHiddenBlacklisted(),this.buildHtml()}addToHiddenBlacklisted(){y.observe(this.parentElement),C.observe(this.parentElement),l.hiddenBlacklisted.push(this)}buildHtml(){u(this.wrapper,V),this.wrapper.setAttribute("id",this.id),this.buildContainer()}buildContainer(){const e=document.createElement("div");e.classList.add("message-container"),u(e,z),this.isVisible||u(e,{display:"none"}),e.appendChild(this.buildHeader()),e.appendChild(this.buildMessage()),e.appendChild(this.buildButton()),this.wrapper.appendChild(e)}buildHeader(){return document.createElement("div")}buildMessage(){const e=document.createElement("aside");return u(e,Z),e.innerHTML=this.buildDefaultText(),e}buildDefaultText(){return"<p>Le contenu est bloqué, car vous avez décidé de refuser les cookies et usages nécessaires à son affichage.</p>  <p>Usages nécessaires : </p> <ul style='margin-bottom: 16px'><li>Interactions avec les réseaux sociaux : Ces cookies vous permettent de partager des contenus de notre site, d’interagir avec les réseaux sociaux et d'afficher des contenus provenant des réseaux sociaux.</li></ul>"}buildButton(){const e=document.createElement("div"),n=document.createElement("div");return u(e,Y),u(n,J),n.innerHTML="Modifier mon consentement",n.onclick=this.callbackDisplayCMP,e.appendChild(n),e}callbackDisplayCMP(){window.__tcfapi("show",2,()=>{},{})}getMessageContainer(){return this.wrapper.querySelector(".message-container")}}class te{constructor(e){this.node=e,this.oldType=null,this.parentElement=this.node.parentElement,this.message=null,this.id=`${U}${$()}`,this.init()}init(){const{tagName:e}=this.node;switch(e){case c.SCRIPT:this.blockScript();break;case c.IFRAME:case c.BLOCKQUOTE:this.blockElementWithSrc();break}this.removeNodeToDocument()}blockScript(){const{type:e}=this.node;this.oldType=e,this.node.setAttribute("type",f),this.addBeforeScriptListener()}blockElementWithSrc(){this.addWrapper()}addBeforeScriptListener(){const e=function(n){this.node.getAttribute("type")===f&&n.preventDefault(),this.node.removeEventListener("beforescriptexecute",e)};this.node.addEventListener("beforescriptexecute",e)}removeNodeToDocument(){this.parentElement&&this.parentElement.removeChild(this.node)}addWrapper(){d("add wrapper",this.id,this.node,this.parentElement),this.message=new ee(this.node,this.id,this.parentElement),this.parentElement.appendChild(this.message.wrapper)}}const O=new MutationObserver(t=>{for(let e=0;e<t.length;e++){const{addedNodes:n}=t[e];for(let i=0;i<n.length;i++){const s=n[i],{tagName:r,nodeType:a}=s;a===1&&w.includes(r)&&d("checking",k(s),s),a===1&&w.includes(r)&&k(s)&&(L(s),d("observer",l))}}}),y=new ResizeObserver(t=>{t.forEach(e=>{const n=I(e.target);if(n){const i=n.getMessageContainer(),s=e.target.offsetHeight>0?"flex":"none";d("resizeObserver",e.target,n.id,s,e.target.offsetHeight),u(i,{display:s})}})}),C=new IntersectionObserver(t=>{t.forEach(e=>{const n=I(e.target);if(n){const i=n.getMessageContainer(),s=e.isIntersecting&&e.target.offsetHeight>0?"flex":"none";d("intersectionObserver",e.target,n.id,s,e.target.offsetHeight),u(i,{display:s})}})});function I(t){return l.hiddenBlacklisted.find(e=>t&&e.parentElement.isEqualNode(t))}function L(t){const e=new te(t);l.blacklisted.push(e)}const ne=()=>{O.observe(document.documentElement,{childList:!0,subtree:!0})},x=document.createElement,m={src:Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype,"src"),type:Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype,"type")};document.createElement=function(...t){if(t[0].toLowerCase()!=="script")return x.bind(document)(...t);const e=x.bind(document)(...t);try{Object.defineProperties(e,{src:{...m.src,set(n){E(n)&&m.type.set.call(this,f),m.src.set.call(this,n)}},type:{...m.type,get(){const n=m.type.get.call(this);return n===f||E(this.src)?null:n},set(n){const i=k(e.src)?f:n;m.type.set.call(this,i)}}}),e.setAttribute=function(n,i){n==="type"||n==="src"?e[n]=i:HTMLScriptElement.prototype.setAttribute.call(e,n,i)}}catch{console.warn("sfbxguardian: unable to prevent script execution for script src ",e.src,`.
`,'A likely cause would be because you are using a third-party browser extension that monkey patches the "document.createElement" function.')}return e};const se=new RegExp("[|\\{}()[\\]^$+*?.]","g"),ie=function(...t){oe(t),re();let e=0;[...l.blacklisted].forEach((n,i)=>{const{id:s,node:r,oldType:a}=n;if(v(r)){switch(r.tagName){case c.SCRIPT:ce(r,a);break;case c.IFRAME:N(s),le(r,s);break;case c.BLOCKQUOTE:N(s),ae(r,s);break}d("node unblocked",r),l.blacklisted.splice(i-e,1),e++}}),o.blacklist&&o.blacklist.length<1&&(O.disconnect(),y.disconnect(),C.disconnect(),d("observers disconnected"))},N=t=>{const e=l.hiddenBlacklisted.find(n=>n.id===t);e&&(y.unobserve(e.parent),C.unobserve(e.parent),l.hiddenBlacklisted=l.hiddenBlacklisted.filter(n=>n.id!==t))};function oe(t){t.length<1?(o.blacklist=[],o.whitelist=[]):(o.blacklist&&(o.blacklist=o.blacklist.filter(e=>t.every(n=>{if(typeof n=="string")return!e.test(n);if(n instanceof RegExp)return e.toString()!==n.toString()}))),o.whitelist&&(o.whitelist=[...o.whitelist,...t.map(e=>{if(typeof e=="string"){const i=".*"+e.replace(se,"\\$&")+".*";if(o.whitelist.every(s=>s.toString()!==i.toString()))return new RegExp(i)}else if(e instanceof RegExp&&o.whitelist.every(n=>n.toString()!==e.toString()))return e;return null}).filter(Boolean)]))}function re(){const t=document.querySelectorAll(`script[type="${f}"]`);for(let e=0;e<t.length;e++){const n=t[e];v(n)&&L(n)}}function ce(t,e){const n=document.createElement("script");for(let i=0;i<t.attributes.length;i++){let s=t.attributes[i];s.name!=="src"&&s.name!=="type"&&n.setAttribute(s.name,t.attributes[i].value)}n.setAttribute("src",t.src),n.setAttribute("type",e||F),document.head.appendChild(n)}function le(t,e){M(t,"iframe",e).setAttribute("src",t.src)}function ae(t,e){const n=M(t,"blockquote",e),i=t.children;for(let s=0;s<i.length;s++)n.appendChild(i[s].cloneNode(!0))}function M(t,e,n){const i=document.getElementById(n),s=i.parentElement,r=document.createElement(e);for(let a=0;a<t.attributes.length;a++){let T=t.attributes[a];T.name!=="src"&&T.name!=="type"&&r.setAttribute(T.name,t.attributes[a].value)}return s.removeChild(i),s.appendChild(r),r}if(typeof configSFBXAppConsent>"u")throw console.error("SFBX Guardian has not been executed! The configuration (configSFBXAppConsent) must be placed before calling the script "),Error();if(!configSFBXAppConsent.dynamicallyLoadedScripts||!configSFBXAppConsent.dynamicallyLoadedScripts.blacklist&&!configSFBXAppConsent.dynamicallyLoadedScripts.whitelist)throw console.warn("SFBX Guardian: No whitelist or blacklist has been defined"),Error();function de(){H(),d("init"),ne()}const R=B();(!R.ac_cmd||R.ac_cmd!=="no_guardian")&&de(),h.unblock=ie,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})});
</script>
```

{% hint style="danger" %}
**IMPORTANT**

&#x20;The Guardian script must be placed after the configSFBXAppConsent variable to work.
{% endhint %}

That's it - All the tags are now blocked until the user consent. If the user deny cookies in the cmp, the tags will remains blocked.

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

This library is using observer and override CreateElement core JS functionalities. If you expriment tests that are not working, please deactivate Chrome or Firefox extension in your browser.
{% endhint %}

We will add new capabilities regularly (more controls, shared database of tags...)

Any issue or suggestions ? Drop an email at [**support@sfbx.io**](mailto:support@sfbx.io)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sfbx.io/configuration/step-3-notice-implementation-web-app-tv/web-cmp/blocking-tags-using-guardian.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
