feincms / feincms3-cookiecontrol

BSD 3-Clause "New" or "Revised" License
7 stars 0 forks source link

Possible implementation of a f3cc injection via only a script tag #23

Closed matthiask closed 2 years ago

matthiask commented 2 years ago

So könnte das aussehen, wenn kein HTML hinzugefügt wird, sondern ausschliesslich ein Skript eingebunden wird für das Cookie Control Panel.

Die projektspezifische Integration besteht aus:

from feincms3_cookiecontrol.views import inject
urlpatterns += [path("f3cc-inject.js", inject)]
<script async src="/f3cc-inject.js"></script>

Natürlich nicht gründlich getestet, aber hat mich interessiert.

matthiask commented 2 years ago

Ich fands etwas blöd, dass es hier zusätzliche Requests gibt, wenn das Panel so eingebunden wird. Aber, es wär einfach möglich die Assets so umzubauen, dass alles inline mitgeliefert wird:

;(function() {
window.f3ccData = {"panel": {"heading": "Ihre Cookie.........-- End Google Tag Manager -->", "inject_else": ""}]}}}

let el = document.createElement("div")
el.id = "f3cc"
document.body.appendChild(el)

el = document.createElement("style")
el.textContent = `:root{--f3cc-background-light-color: #ffffff;--f3........d+label:after{transform:translate(24px)}
`
document.body.appendChild(el)

;(function(){let h="f3cc",m=document.getElementById("f3cc"),c=window.f3ccData||........el]")&&v(e)}),S()?y():L()}I()})();
})()

Mit anständigem Caching und mit anständigen Cache Headern für den Browser wär das vermutlich ein gangbarer Weg.

Es ist insofern weniger flexibel, als dass nicht mehr mit einer Template-Anpassung die Standard-Styles weggelassen werden können. Aber das ist evtl. sowieso ein Feature, kein Bug.

yoshson commented 2 years ago

Ja, ich glaube durch das Caching sind zusätzliche requests kein Problem. Ansonsten kann man auch ein Maximum als Timestamp mitgeben und dann f3ccData nachladen wenn all zu lange gecacht wird.

matthiask commented 2 years ago

Generiert wird zB das hier:

(function(){window.f3ccData={"heading":"Cookies on Our Website","description":"We use cookies to enhance the user experience on our website. Click on \"Modify settings\" for a description of the different types of cookies and to decide which cookies you want to allow or not. Read our privacy policy to find out more about how we use cookies and protect your data.","buttonAccept":"Accept all cookies","buttonReject":"Refuse non-essential cookies","buttonModify":"Modify cookie settings","domain":null,"privacyPolicyURL":null,"privacyPolicyTitle":"Privacy policy","cookies":[]};(()=>{(function(){var f=document.createElement("style");f.textContent=":root{--f3cc-background-color:#e9e9e9;--f3cc-foreground-color:#000000;--f3cc-button-background:#cbcbcb;--f3cc-accept-background:#90f690;}#f3cc{font-size:16px;line-height:1.3;}#f3cc .f3cc-banner{position:fixed;bottom:0;width:100%;background:var(--f3cc-background-color);color:var(--f3cc-foreground-color);z-index:2000;padding:1rem 1rem 1.25rem;}#f3cc .f3cc-container{display:flex;gap:2rem;max-width:70em;margin:0 auto;width:80%;}@media screen and (max-width:60rem){#f3cc .f3cc-container{width:100%;flex-direction:column;}}#f3cc .f3cc-title{font-size:1.5em;font-weight:bold;margin-bottom:0.25em;}#f3cc .f3cc-description a{color:inherit;text-decoration:underline;}#f3cc .f3cc-description a:hover{opacity:0.7;}#f3cc .f3cc-buttons{display:flex;flex-direction:column;gap:1rem;justify-content:center;align-items:stretch;}#f3cc .f3cc-button{display:inline-block;background:var(--f3cc-button-background);color:var(--f3cc-foreground-color);padding:0.8rem 1.2rem;white-space:nowrap;text-decoration:none;text-align:center;cursor:pointer;}#f3cc .f3cc-button:hover{opacity:0.7;}#f3cc .f3cc-button.accept{background:var(--f3cc-accept-background);}#f3cc .f3cc-button.modify{position:fixed;z-index:2000;bottom:1rem;right:1rem;}",document.head.appendChild(f)})();(function(){let f="f3cc",c=window.f3ccData||JSON.parse(document.getElementById("f3cc-data").textContent),m={},l,a,d;function n(e,t=null,o=[]){let i=document.createElement(e);if(t)for(let[r,x]of Object.entries(t))r.startsWith("data-")?i.setAttribute(r,x):i[r]=x;return i.append(...o),i}function p(){if(a){a.style.display="";return}let e=[n("div",{className:"f3cc-title",textContent:c.heading}),n("div",{className:"f3cc-description",textContent:c.description})];c.privacyPolicyURL&&e[1].append(n("br"),n("a",{textContent:c.privacyPolicyTitle,href:c.privacyPolicyURL}));let t=[n("a",{className:"f3cc-button accept",textContent:c.buttonAccept,onclick:C}),n("a",{className:"f3cc-button reject",textContent:c.buttonReject,onclick:w})];a=n("div",{className:"f3cc f3cc-banner"},[n("div",{className:"f3cc-container"},[n("div",{className:"f3cc-content"},e),n("div",{className:"f3cc-buttons"},t)])]),l.append(a)}function s(){if(d){d.style.display="";return}c.buttonModify&&(d=n("a",{className:"f3cc-button modify",textContent:c.buttonModify,onclick:e=>{e.preventDefault(),u(d),p()}}),l.append(d))}function b(e){let t=`${f}=${e};max-age=31536000;path=/;sameSite=Strict`;c.domain&&(t+=`;domain=${c.domain}`),document.cookie=t}function g(){let e=new RegExp(`\\b${f}=(.+?)\\b`),t=document.cookie.match(e);if(t&&t.length)return t[1]}function k(){return["all","essential"].includes(g())}function v(){return g()==="all"}function u(e){e&&(e.style.display="none")}function C(e){e.preventDefault(),b("all"),u(a),s(),h()}function w(e){e.preventDefault(),b("essential"),u(a),s()}function h(){for(let e of c.cookies){let t=m[e.name];t||(m[e.name]=t=document.createElement("div"),t.dataset.name=e.name,l.append(t)),t.innerHTML=e.script,y(t)}}function N(){l=n("div",{id:"f3cc"}),document.body.append(l),v()&&h(),k()?s():p()}N();function y(e){if(j(e)===!0)e.parentNode.replaceChild(S(e),e);else{let t=-1,o=e.childNodes;for(;++t<o.length;)y(o[t])}return e}function S(e){let t=document.createElement("script");t.text=e.innerHTML;let o=-1,i=e.attributes,r;for(;++o<i.length;)t.setAttribute((r=i[o]).name,r.value);return t}function j(e){return e.tagName==="SCRIPT"}})();})();
})() 

Das kann auf einer beliebigen Seite in die Browserconsole gepastet werden, und es zeigt das Panel an :)

zB:

image

matthiask commented 2 years ago

Der Modify Button wird jetzt im Frontend abhängig von der privacyPolicyURL versteckt. Ich frage mich, ob das ein guter Weg ist. Es ist äquivalent zu dem, was wir bisher im Template Tag machen. Von daher wird es "gut genug" sein...