From af0c98d6e14593d8447a778c9d971bad0ebca450 Mon Sep 17 00:00:00 2001 From: ytkimirti Date: Wed, 15 Oct 2025 09:00:43 +0300 Subject: [PATCH 1/4] feat: cache the geolocation request --- script.js | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/script.js b/script.js index 4f0a63ff..858ad452 100644 --- a/script.js +++ b/script.js @@ -73,12 +73,71 @@ function initializePosthog() { }); posthog.opt_in_capturing(); } +// Validation function to replace zod +function validateCacheData(data) { + if (!data || typeof data !== "object") return false; + if (typeof data.isEuropean !== "boolean") return false; + if (typeof data.expiresAt !== "number") return false; + return true; +} + +// Cache management functions +const GEO_CACHE_KEY = "geo:is_eu"; +const GEO_CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours + +/** + * @returns {boolean | null} + */ +function getCachedIsEuropean() { + try { + const raw = localStorage.getItem(GEO_CACHE_KEY); + if (!raw) return null; + + const parsed = JSON.parse(raw); + if (!validateCacheData(parsed)) { + localStorage.removeItem(GEO_CACHE_KEY); + return null; + } + + if (Date.now() > parsed.expiresAt) { + localStorage.removeItem(GEO_CACHE_KEY); + return null; + } + + return parsed.isEuropean; + } catch { + return null; + } +} + +function setCachedIsEuropean(isEuropean) { + const expiresAt = Date.now() + GEO_CACHE_TTL_MS; + localStorage.setItem( + GEO_CACHE_KEY, + JSON.stringify({ isEuropean, expiresAt }) + ); +} + const checkGeolocation = () => { + const cachedIsEU = getCachedIsEuropean(); + if (cachedIsEU !== null) { + if (!cachedIsEU) { + localStorage.setItem("cookieConsent", "true"); + initializePosthog(); + return Promise.resolve(true); // indicates we've handled non-European user + } + return Promise.resolve(false); // indicates we should show the banner + } + + // If no cache, fetch from API return fetch("https://upstash.com/api/geolocation") .then((response) => { return response.json(); }) .then((data) => { + // Cache the result + setCachedIsEuropean(data.isEuropean); + if (!data.isEuropean) { localStorage.setItem("cookieConsent", "true"); initializePosthog(); From 014cf81d1eb76868c2e79d286ddcf292a45f9725 Mon Sep 17 00:00:00 2001 From: ytkimirti Date: Mon, 20 Oct 2025 12:38:09 +0300 Subject: [PATCH 2/4] fix: simplify the logic --- script.js | 39 ++++++--------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/script.js b/script.js index 858ad452..a626f9a8 100644 --- a/script.js +++ b/script.js @@ -73,49 +73,22 @@ function initializePosthog() { }); posthog.opt_in_capturing(); } -// Validation function to replace zod -function validateCacheData(data) { - if (!data || typeof data !== "object") return false; - if (typeof data.isEuropean !== "boolean") return false; - if (typeof data.expiresAt !== "number") return false; - return true; -} -// Cache management functions +// Cache for geolocation check const GEO_CACHE_KEY = "geo:is_eu"; -const GEO_CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours /** * @returns {boolean | null} */ function getCachedIsEuropean() { - try { - const raw = localStorage.getItem(GEO_CACHE_KEY); - if (!raw) return null; - - const parsed = JSON.parse(raw); - if (!validateCacheData(parsed)) { - localStorage.removeItem(GEO_CACHE_KEY); - return null; - } - - if (Date.now() > parsed.expiresAt) { - localStorage.removeItem(GEO_CACHE_KEY); - return null; - } - - return parsed.isEuropean; - } catch { - return null; - } + const value = localStorage.getItem(GEO_CACHE_KEY); + if (value === "true") return true; + if (value === "false") return false; + return null; } function setCachedIsEuropean(isEuropean) { - const expiresAt = Date.now() + GEO_CACHE_TTL_MS; - localStorage.setItem( - GEO_CACHE_KEY, - JSON.stringify({ isEuropean, expiresAt }) - ); + localStorage.setItem(GEO_CACHE_KEY, String(isEuropean)); } const checkGeolocation = () => { From f5894d2bc877ce07348fb57e997d8fcc413202a2 Mon Sep 17 00:00:00 2001 From: ytkimirti Date: Wed, 22 Oct 2025 07:25:47 +0300 Subject: [PATCH 3/4] refactor: simplify cookie consent --- script.js | 181 ++++++++++++++++++++++++------------------------------ 1 file changed, 81 insertions(+), 100 deletions(-) diff --git a/script.js b/script.js index a626f9a8..6171ae59 100644 --- a/script.js +++ b/script.js @@ -74,75 +74,58 @@ function initializePosthog() { posthog.opt_in_capturing(); } -// Cache for geolocation check -const GEO_CACHE_KEY = "geo:is_eu"; - -/** - * @returns {boolean | null} - */ -function getCachedIsEuropean() { - const value = localStorage.getItem(GEO_CACHE_KEY); - if (value === "true") return true; - if (value === "false") return false; - return null; +function getCookieConsent() { + const value = localStorage.getItem("cookieConsent"); + // Backwards compatibility: convert old "true" to "granted" + if (value === "true") { + localStorage.setItem("cookieConsent", "granted"); + return "granted"; + } + return value; } -function setCachedIsEuropean(isEuropean) { - localStorage.setItem(GEO_CACHE_KEY, String(isEuropean)); +function setCookieConsent(value) { + localStorage.setItem("cookieConsent", value); } -const checkGeolocation = () => { - const cachedIsEU = getCachedIsEuropean(); - if (cachedIsEU !== null) { - if (!cachedIsEU) { - localStorage.setItem("cookieConsent", "true"); +async function checkGeolocation() { + try { + const response = await fetch("https://upstash.com/api/geolocation"); + const data = await response.json(); + + data.isEuropean = true; + + if (data.isEuropean) { + setCookieConsent("pending-eu"); + createCookieConsentBanner(); + } else { + setCookieConsent("granted"); initializePosthog(); - return Promise.resolve(true); // indicates we've handled non-European user } - return Promise.resolve(false); // indicates we should show the banner + } catch (error) { + console.error("Error checking geolocation:", error); } - - // If no cache, fetch from API - return fetch("https://upstash.com/api/geolocation") - .then((response) => { - return response.json(); - }) - .then((data) => { - // Cache the result - setCachedIsEuropean(data.isEuropean); - - if (!data.isEuropean) { - localStorage.setItem("cookieConsent", "true"); - initializePosthog(); - return true; // indicates we've handled non-European user - } - return false; // indicates we should show the banner - }) - .catch((error) => { - return false; - }); -}; +} function initialize() { - if (localStorage.getItem("cookieConsent") === "true") { + const cookieConsent = getCookieConsent(); + + if (cookieConsent === "granted") { initializePosthog(); - } else { + } else if (cookieConsent === "pending-eu") { createCookieConsentBanner(); + } else { + checkGeolocation(); } } initialize(); + function createCookieConsentBanner() { - if ( - document.getElementById("cookie-consent-banner") || - localStorage.getItem("cookieConsent") - ) - return; - - return checkGeolocation().then((isHandled) => { - if (!isHandled) { - const style = document.createElement("style"); - style.textContent = ` + if (document.getElementById("cookie-consent-banner")) return; + + const style = document.createElement("style"); + style.textContent = ` #cookie-consent-banner { position: fixed; bottom: 0; @@ -171,27 +154,27 @@ function createCookieConsentBanner() { } } `; - document.head.appendChild(style); + document.head.appendChild(style); - const banner = document.createElement("div"); - banner.id = "cookie-consent-banner"; + const banner = document.createElement("div"); + banner.id = "cookie-consent-banner"; - const message = document.createElement("span"); - message.innerHTML = - 'We use cookies to improve your experience. Read our privacy policy.'; + const message = document.createElement("span"); + message.innerHTML = + 'We use cookies to improve your experience. Read our privacy policy.'; - const buttonContainer = document.createElement("div"); - buttonContainer.style.cssText = ` + const buttonContainer = document.createElement("div"); + buttonContainer.style.cssText = ` display: flex; align-items: center; gap: 10px; `; - const acceptButton = document.createElement("button"); - const acceptText = document.createElement("p"); - acceptText.textContent = "Accept"; - acceptButton.appendChild(acceptText); - acceptButton.style.cssText = ` + const acceptButton = document.createElement("button"); + const acceptText = document.createElement("p"); + acceptText.textContent = "Accept"; + acceptButton.appendChild(acceptText); + acceptButton.style.cssText = ` display: flex; align-items: center; background-color: white; @@ -203,9 +186,9 @@ function createCookieConsentBanner() { transition: background-color 0.2s; `; - const closeButton = document.createElement("button"); - closeButton.textContent = "x"; - closeButton.style.cssText = ` + const closeButton = document.createElement("button"); + closeButton.textContent = "x"; + closeButton.style.cssText = ` display: flex; height: 24px; width: 24px; @@ -219,36 +202,34 @@ function createCookieConsentBanner() { transition: background-color 0.2s; `; - acceptButton.addEventListener( - "mouseover", - () => (acceptButton.style.backgroundColor = "#f3f4f6") - ); - acceptButton.addEventListener( - "mouseout", - () => (acceptButton.style.backgroundColor = "white") - ); - closeButton.addEventListener( - "mouseover", - () => (closeButton.style.backgroundColor = "rgb(16, 185, 129)") - ); - closeButton.addEventListener( - "mouseout", - () => (closeButton.style.backgroundColor = "transparent") - ); - - acceptButton.addEventListener("click", () => { - localStorage.setItem("cookieConsent", "true"); - banner.remove(); - initializePosthog(); - }); - - closeButton.addEventListener("click", () => banner.remove()); - - buttonContainer.appendChild(acceptButton); - buttonContainer.appendChild(closeButton); - banner.appendChild(message); - banner.appendChild(buttonContainer); - document.body.appendChild(banner); - } + acceptButton.addEventListener( + "mouseover", + () => (acceptButton.style.backgroundColor = "#f3f4f6") + ); + acceptButton.addEventListener( + "mouseout", + () => (acceptButton.style.backgroundColor = "white") + ); + closeButton.addEventListener( + "mouseover", + () => (closeButton.style.backgroundColor = "rgb(16, 185, 129)") + ); + closeButton.addEventListener( + "mouseout", + () => (closeButton.style.backgroundColor = "transparent") + ); + + acceptButton.addEventListener("click", () => { + setCookieConsent("granted"); + banner.remove(); + initializePosthog(); }); + + closeButton.addEventListener("click", () => banner.remove()); + + buttonContainer.appendChild(acceptButton); + buttonContainer.appendChild(closeButton); + banner.appendChild(message); + banner.appendChild(buttonContainer); + document.body.appendChild(banner); } From 45eba5aaa2e1a68c3485a45b242b2d7bf03e688a Mon Sep 17 00:00:00 2001 From: CahidArda Date: Wed, 22 Oct 2025 09:32:32 +0300 Subject: [PATCH 4/4] fix: remove unnecessary assignment in geolocation check --- script.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/script.js b/script.js index 6171ae59..9b6efc63 100644 --- a/script.js +++ b/script.js @@ -93,8 +93,6 @@ async function checkGeolocation() { const response = await fetch("https://upstash.com/api/geolocation"); const data = await response.json(); - data.isEuropean = true; - if (data.isEuropean) { setCookieConsent("pending-eu"); createCookieConsentBanner();