PageSourceSearch

https://beehome.company/assets/widgets/cookie-banner.js

js beehome.company collected 2026-10-02 14:40:24 UTC 5,213 bytes, 153 lines download raw bytes

1/**
2 * beehome-cookie-banner.js — LGPD-compliant cookie banner.
3 *
4 * Replaces HubSpot's cookie banner. Zero deps. Shows once on first visit;
5 * stores choice in localStorage under `beehome_consent_v1`. Exposes
6 * window.BeehomeConsent with { status, canLoad(category), on(event, cb) }.
7 *
8 * Categories supported:
9 *   - "necessary" — always true
10 *   - "analytics" — Google Analytics, GTM, LinkedIn Insight
11 *   - "marketing" — ads pixels, retargeting
12 *
13 * Consent options: accept-all, reject-non-essential, or per-category via settings.
14 */
15(function () {
16  "use strict";
17
18  var STORAGE_KEY = "beehome_consent_v1";
19  var LISTENERS = { change: [] };
20  var state = loadState();
21
22  function loadState() {
23    try {
24      var raw = localStorage.getItem(STORAGE_KEY);
25      if (!raw) return null;
26      var parsed = JSON.parse(raw);
27      if (!parsed || typeof parsed !== "object") return null;
28      return parsed;
29    } catch (e) { return null; }
30  }
31
32  function saveState(s) {
33    try { localStorage.setItem(STORAGE_KEY, JSON.stringify(s)); } catch (e) {}
34    state = s;
35    applyConsent(s);
36    emit("change", s);
37  }
38
39  // Avisa o Google Consent Mode da escolha do usuário.
40  // Sem isto, o gtag fica DENIED por padrão pra sempre, o cookie _gcl_aw
41  // (GCLID) nunca é gravado e as conversões NÃO contam no Google Ads.
42  function applyConsent(s) {
43    if (typeof window.gtag !== "function") return;
44    var marketing = s && s.marketing ? "granted" : "denied";
45    var analytics = s && s.analytics ? "granted" : "denied";
46    window.gtag("consent", "update", {
47      ad_storage: marketing,
48      ad_user_data: marketing,
49      ad_personalization: marketing,
50      analytics_storage: analytics,
51    });
52  }
53
54  function emit(event, payload) {
55    (LISTENERS[event] || []).forEach(function (cb) {
56      try { cb(payload); } catch (e) { console.error("[BeehomeConsent]", e); }
57    });
58  }
59
60  function el(tag, attrs, children) {
61    var e = document.createElement(tag);
62    if (attrs) for (var k in attrs) {
63      if (k === "class") e.className = attrs[k];
64      else if (k === "html") e.innerHTML = attrs[k];
65      else if (k === "text") e.textContent = attrs[k];
66      else e.setAttribute(k, attrs[k]);
67    }
68    (children || []).forEach(function (c) {
69      if (c == null) return;
70      e.appendChild(typeof c === "string" ? document.createTextNode(c) : c);
71    });
72    return e;
73  }
74
75  function renderBanner() {
76    if (document.getElementById("beehome-cookie-banner")) return;
77    var wrap = el("div", { id: "beehome-cookie-banner", role: "dialog", "aria-live": "polite", "aria-label": "Aviso de cookies" });
78
79    var inner = el("div", { class: "bh-cb-inner" });
80
81    inner.appendChild(
82      el("div", { class: "bh-cb-text" }, [
83        el("strong", {}, ["Usamos cookies "]),
84        "para melhorar sua experiência, analisar tráfego e personalizar conteúdo. Você pode aceitar todos ou apenas os essenciais. Veja nossa ",
85        el("a", { href: "/politica-de-privacidade", target: "_blank", rel: "noopener" }, ["Política de Privacidade"]),
86        ".",
87      ])
88    );
89
90    var btns = el("div", { class: "bh-cb-actions" });
91    btns.appendChild(el("button", { class: "bh-cb-btn bh-cb-btn-secondary", type: "button", id: "bh-cb-reject" }, ["Apenas essenciais"]));
92    btns.appendChild(el("button", { class: "bh-cb-btn bh-cb-btn-primary", type: "button", id: "bh-cb-accept" }, ["Aceitar todos"]));
93    inner.appendChild(btns);
94
95    wrap.appendChild(inner);
96    document.body.appendChild(wrap);
97
98    document.getElementById("bh-cb-accept").addEventListener("click", function () {
99      saveState({ necessary: true, analytics: true, marketing: true, at: Date.now(), v: 1 });
100      dismiss();
101    });
102    document.getElementById("bh-cb-reject").addEventListener("click", function () {
103      saveState({ necessary: true, analytics: false, marketing: false, at: Date.now(), v: 1 });
104      dismiss();
105    });
106
107    // Trigger slide-in after paint
108    requestAnimationFrame(function () { wrap.classList.add("bh-cb-visible"); });
109  }
110
111  function dismiss() {
112    var wrap = document.getElementById("beehome-cookie-banner");
113    if (wrap) {
114      wrap.classList.remove("bh-cb-visible");
115      setTimeout(function () { if (wrap.parentNode) wrap.parentNode.removeChild(wrap); }, 300);
116    }
117  }
118
119  function boot() {
120    if (!state) {
121      renderBanner();
122    } else {
123      // visitante que já decidiu: reaplica o consent (default da página é denied)
124      applyConsent(state);
125    }
126  }
127
128  // Public API
129  window.BeehomeConsent = {
130    get status() { return state; },
131    canLoad: function (category) {
132      if (category === "necessary") return true;
133      if (!state) return false;  // no decision yet → deny non-essentials
134      return Boolean(state[category]);
135    },
136    on: function (event, cb) {
137      if (!LISTENERS[event]) LISTENERS[event] = [];
138      LISTENERS[event].push(cb);
139      return this;
140    },
141    openSettings: function () {
142      try { localStorage.removeItem(STORAGE_KEY); } catch (e) {}
143      state = null;
144      renderBanner();
145    },
146  };
147
148  if (document.readyState === "loading") {
149    document.addEventListener("DOMContentLoaded", boot);
150  } else {
151    boot();
152  }
153})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.