Aggiunge cookie policy, banner consenso e Google Analytics opzionale.
Il banner consente solo necessari o tutti i cookie; GA4 si carica solo dopo consenso. Aggiornati privacy, footer, sitemap e variabile GOOGLE_ANALYTICS_MEASUREMENT_ID. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
134
backend/public/cookie-consent.js
Normal file
134
backend/public/cookie-consent.js
Normal file
@@ -0,0 +1,134 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var STORAGE_KEY = "mltv_cookie_consent";
|
||||
var COOKIE_NAME = "mltv_cookie_consent";
|
||||
var COOKIE_MAX_AGE = 365 * 24 * 60 * 60;
|
||||
|
||||
function readConsent() {
|
||||
try {
|
||||
var raw = localStorage.getItem(STORAGE_KEY);
|
||||
if (!raw) return null;
|
||||
return JSON.parse(raw);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function writeConsent(consent) {
|
||||
var payload = {
|
||||
necessary: true,
|
||||
analytics: !!consent.analytics,
|
||||
ts: Date.now()
|
||||
};
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));
|
||||
} catch (e) { /* ignore */ }
|
||||
var value = payload.analytics ? "all" : "necessary";
|
||||
document.cookie =
|
||||
COOKIE_NAME + "=" + value +
|
||||
"; path=/; max-age=" + COOKIE_MAX_AGE +
|
||||
"; SameSite=Lax" +
|
||||
(location.protocol === "https:" ? "; Secure" : "");
|
||||
return payload;
|
||||
}
|
||||
|
||||
function measurementId() {
|
||||
return document.body && document.body.getAttribute("data-ga-id");
|
||||
}
|
||||
|
||||
function loadGoogleAnalytics() {
|
||||
var id = measurementId();
|
||||
if (!id || window.__mltvGaLoaded) return;
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() { window.dataLayer.push(arguments); }
|
||||
window.gtag = gtag;
|
||||
|
||||
gtag("consent", "default", {
|
||||
analytics_storage: "denied",
|
||||
ad_storage: "denied",
|
||||
ad_user_data: "denied",
|
||||
ad_personalization: "denied",
|
||||
functionality_storage: "granted",
|
||||
security_storage: "granted"
|
||||
});
|
||||
|
||||
gtag("consent", "update", { analytics_storage: "granted" });
|
||||
|
||||
var script = document.createElement("script");
|
||||
script.async = true;
|
||||
script.src = "https://www.googletagmanager.com/gtag/js?id=" + encodeURIComponent(id);
|
||||
script.onload = function () {
|
||||
gtag("js", new Date());
|
||||
gtag("config", id, { anonymize_ip: true, allow_google_signals: false });
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
window.__mltvGaLoaded = true;
|
||||
}
|
||||
|
||||
function applyConsent(consent) {
|
||||
if (consent && consent.analytics) {
|
||||
loadGoogleAnalytics();
|
||||
}
|
||||
}
|
||||
|
||||
function hideBanner(banner) {
|
||||
if (!banner) return;
|
||||
banner.hidden = true;
|
||||
banner.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
|
||||
function showBanner(banner) {
|
||||
if (!banner) return;
|
||||
banner.hidden = false;
|
||||
banner.removeAttribute("aria-hidden");
|
||||
}
|
||||
|
||||
function bindBanner(banner) {
|
||||
var acceptAll = banner.querySelector("[data-cookie-accept-all]");
|
||||
var reject = banner.querySelector("[data-cookie-reject]");
|
||||
|
||||
if (acceptAll) {
|
||||
acceptAll.addEventListener("click", function () {
|
||||
var c = writeConsent({ analytics: true });
|
||||
applyConsent(c);
|
||||
hideBanner(banner);
|
||||
});
|
||||
}
|
||||
|
||||
if (reject) {
|
||||
reject.addEventListener("click", function () {
|
||||
writeConsent({ analytics: false });
|
||||
hideBanner(banner);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
var banner = document.getElementById("cookie-banner");
|
||||
var consent = readConsent();
|
||||
|
||||
if (consent) {
|
||||
applyConsent(consent);
|
||||
hideBanner(banner);
|
||||
} else {
|
||||
showBanner(banner);
|
||||
}
|
||||
|
||||
bindBanner(banner);
|
||||
|
||||
document.querySelectorAll("[data-cookie-manage]").forEach(function (el) {
|
||||
el.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
showBanner(banner);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -1060,6 +1060,7 @@ body.nav-menu-open { overflow: hidden; }
|
||||
.legal-doc { max-width: 760px; padding-top: 24px; padding-bottom: 48px; color: #bbb; line-height: 1.65; font-size: 0.95rem; }
|
||||
.legal-doc h1 { color: #fff; font-size: 1.6rem; margin-bottom: 8px; }
|
||||
.legal-doc h2 { color: #fff; font-size: 1.1rem; margin: 28px 0 10px; }
|
||||
.legal-doc h3 { color: #ddd; font-size: 1rem; margin: 20px 0 8px; }
|
||||
.legal-doc p { margin: 0 0 12px; }
|
||||
.legal-doc ul { margin: 0 0 14px; padding-left: 1.25rem; }
|
||||
.legal-doc a { color: #e53935; }
|
||||
@@ -1272,3 +1273,84 @@ label { display: block; margin-bottom: 6px; font-size: 0.9rem; color: #c8c8d4; f
|
||||
.plan-change-info__box li + li {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* Cookie banner (GDPR / ePrivacy) */
|
||||
.cookie-banner {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 9999;
|
||||
padding: 16px;
|
||||
background: rgba(10, 10, 14, 0.96);
|
||||
border-top: 1px solid #2a2a36;
|
||||
box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.cookie-banner[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.cookie-banner__inner {
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px 24px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.cookie-banner__text {
|
||||
flex: 1 1 280px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.cookie-banner__title {
|
||||
margin: 0 0 6px;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.cookie-banner__desc {
|
||||
margin: 0;
|
||||
color: #aaa;
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.cookie-banner__link {
|
||||
color: #e53935;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cookie-banner__actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cookie-banner__btn {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.footer-link-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font: inherit;
|
||||
color: #ff6b6b;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer-link-btn:hover {
|
||||
color: #e53935;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
body.cookie-banner-visible {
|
||||
padding-bottom: 120px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user