From feba12d4431ccb3351455438626f3a90b7a84792 Mon Sep 17 00:00:00 2001 From: Beast Date: Thu, 30 Jul 2026 19:06:37 +0800 Subject: [PATCH 1/5] fix: duplicate en-US URL --- website/astro.config.mjs | 3 ++- website/public/_redirects | 5 ++++- website/src/pages/[lang]/404.astro | 4 ++-- website/src/pages/[lang]/about.astro | 4 ++-- website/src/pages/[lang]/blog/[...slug].astro | 6 +++--- website/src/pages/[lang]/blog/index.astro | 4 ++-- website/src/pages/[lang]/blog/tags/[tag].astro | 4 ++-- website/src/pages/[lang]/community.astro | 4 ++-- website/src/pages/[lang]/index.astro | 4 ++-- website/src/pages/[lang]/privacy-policy.astro | 4 ++-- website/src/pages/[lang]/quantum-risk-checker.astro | 4 ++-- website/src/pages/[lang]/technology.astro | 4 ++-- website/src/pages/[lang]/terms.astro | 4 ++-- website/src/pages/[lang]/wallet.astro | 4 ++-- website/src/pages/[lang]/whitepaper.astro | 4 ++-- website/src/pages/[lang]/whitepaper/[version].astro | 4 ++-- website/src/utils/i18n.ts | 5 +++++ 17 files changed, 40 insertions(+), 31 deletions(-) diff --git a/website/astro.config.mjs b/website/astro.config.mjs index 106618b..659616c 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -71,7 +71,8 @@ export default defineConfig({ !page.includes("/tags/") && !page.includes("/account/") && !page.includes("/oauth/") && - !page.includes("/invite/") + !page.includes("/invite/") && + !page.includes("/en-US") ); }, serialize: (item) => { diff --git a/website/public/_redirects b/website/public/_redirects index 1a83d31..b4c530b 100644 --- a/website/public/_redirects +++ b/website/public/_redirects @@ -1,4 +1,7 @@ /quantum-security-checker /quantum-risk-checker 301 /quantum-security-checker/ /quantum-risk-checker 301 /quests /quests/shill 301 -/quests/ /quests/shill 301 \ No newline at end of file +/quests/ /quests/shill 301 +/en-US / 301 +/en-US/ / 301 +/en-US/* /:splat 301 diff --git a/website/src/pages/[lang]/404.astro b/website/src/pages/[lang]/404.astro index e3e6f91..33e860c 100644 --- a/website/src/pages/[lang]/404.astro +++ b/website/src/pages/[lang]/404.astro @@ -2,10 +2,10 @@ import Layout from "@/components/layout/Layout.astro"; import Button from "@/components/ui/Button.astro"; import { createMetadata } from "@/utils/create-metadata"; -import { SUPPORTED_LOCALES } from "@/utils/i18n"; +import { PREFIXED_LOCALES } from "@/utils/i18n"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const metadata = createMetadata({ diff --git a/website/src/pages/[lang]/about.astro b/website/src/pages/[lang]/about.astro index b518fc6..dd8a4da 100644 --- a/website/src/pages/[lang]/about.astro +++ b/website/src/pages/[lang]/about.astro @@ -3,7 +3,7 @@ import Layout from "@/components/layout/Layout.astro"; import { createTranslator, getLocaleFromUrl, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { createMetadata } from "@/utils/create-metadata"; import { JsonLdGraph } from "@/utils/build-json-ld"; @@ -20,7 +20,7 @@ import AdvisorsAndInvestorsSection from "@/components/features/about/AdvisorsAnd import ContactSection from "@/components/features/about/ContactSection.astro"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const locale = getLocaleFromUrl(Astro.url.pathname); diff --git a/website/src/pages/[lang]/blog/[...slug].astro b/website/src/pages/[lang]/blog/[...slug].astro index f0dfda8..0a3d583 100644 --- a/website/src/pages/[lang]/blog/[...slug].astro +++ b/website/src/pages/[lang]/blog/[...slug].astro @@ -1,7 +1,7 @@ --- import { type CollectionEntry, getCollection, render } from "astro:content"; import BlogPost from "@/components/features/blog/BlogPost.astro"; -import { DEFAULT_LOCALE, SUPPORTED_LOCALES, type Locale } from "@/utils/i18n"; +import { DEFAULT_LOCALE, PREFIXED_LOCALES, SUPPORTED_LOCALES, type Locale } from "@/utils/i18n"; export async function getStaticPaths() { const posts = await getCollection("blog"); @@ -21,9 +21,9 @@ export async function getStaticPaths() { }; }); - // Filter paths to ensure only supported locales are generated + // Prefixed locales only — default English lives at unprefixed /blog/... return paths.filter(({ params }) => - SUPPORTED_LOCALES.includes(params.lang as Locale), + PREFIXED_LOCALES.includes(params.lang as Locale), ); } diff --git a/website/src/pages/[lang]/blog/index.astro b/website/src/pages/[lang]/blog/index.astro index 4706cc5..14ec932 100644 --- a/website/src/pages/[lang]/blog/index.astro +++ b/website/src/pages/[lang]/blog/index.astro @@ -6,12 +6,12 @@ import { getLocaleFromUrl, getLocalizedPath, createTranslator, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { createMetadata } from "@/utils/create-metadata"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const locale = getLocaleFromUrl(Astro.url.pathname); diff --git a/website/src/pages/[lang]/blog/tags/[tag].astro b/website/src/pages/[lang]/blog/tags/[tag].astro index be713c5..4397a01 100644 --- a/website/src/pages/[lang]/blog/tags/[tag].astro +++ b/website/src/pages/[lang]/blog/tags/[tag].astro @@ -6,7 +6,7 @@ import { getLocaleFromUrl, getLocalizedPath, createTranslator, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { createMetadata } from "@/utils/create-metadata"; @@ -14,7 +14,7 @@ export async function getStaticPaths() { const allPosts = await getCollection("blog"); const paths = []; - for (const lang of SUPPORTED_LOCALES) { + for (const lang of PREFIXED_LOCALES) { const langPosts = allPosts.filter((post) => post.id.toLowerCase().startsWith(`${lang.toLowerCase()}/`), ); diff --git a/website/src/pages/[lang]/community.astro b/website/src/pages/[lang]/community.astro index 885a3e9..2222de5 100644 --- a/website/src/pages/[lang]/community.astro +++ b/website/src/pages/[lang]/community.astro @@ -3,7 +3,7 @@ import Layout from "@/components/layout/Layout.astro"; import { createTranslator, getLocaleFromUrl, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { createMetadata } from "@/utils/create-metadata"; import { JsonLdGraph } from "@/utils/build-json-ld"; @@ -21,7 +21,7 @@ import TelegramSection from "@/components/features/community/TelegramSection.ast import SocialsSection from "@/components/features/community/SocialsSection.astro"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const locale = getLocaleFromUrl(Astro.url.pathname); diff --git a/website/src/pages/[lang]/index.astro b/website/src/pages/[lang]/index.astro index 8069329..fe62fff 100644 --- a/website/src/pages/[lang]/index.astro +++ b/website/src/pages/[lang]/index.astro @@ -3,7 +3,7 @@ import Layout from "@/components/layout/Layout.astro"; import { createTranslator, getLocaleFromUrl, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { createMetadata } from "@/utils/create-metadata"; import { JsonLdGraph } from "@/utils/build-json-ld"; @@ -23,7 +23,7 @@ import BlogSection from "@/components/features/home/BlogSection.astro"; import NewsletterSection from "@/components/features/home/NewsletterSection.astro"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const locale = getLocaleFromUrl(Astro.url.pathname); diff --git a/website/src/pages/[lang]/privacy-policy.astro b/website/src/pages/[lang]/privacy-policy.astro index 985a76e..d35bd16 100644 --- a/website/src/pages/[lang]/privacy-policy.astro +++ b/website/src/pages/[lang]/privacy-policy.astro @@ -5,7 +5,7 @@ import Layout from "@/components/layout/Layout.astro"; import { createTranslator, getLocaleFromUrl, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { createMetadata } from "@/utils/create-metadata"; import { JsonLdGraph } from "@/utils/build-json-ld"; @@ -17,7 +17,7 @@ import { } from "@/constants/default-jsonld"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const locale = getLocaleFromUrl(Astro.url.pathname); diff --git a/website/src/pages/[lang]/quantum-risk-checker.astro b/website/src/pages/[lang]/quantum-risk-checker.astro index 8180c07..35dc9be 100644 --- a/website/src/pages/[lang]/quantum-risk-checker.astro +++ b/website/src/pages/[lang]/quantum-risk-checker.astro @@ -3,7 +3,7 @@ import Layout from "@/components/layout/Layout.astro"; import { createTranslator, getLocaleFromUrl, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { createMetadata } from "@/utils/create-metadata"; import { JsonLdGraph } from "@/utils/build-json-ld"; @@ -19,7 +19,7 @@ import MethodSection from "@/components/features/qday-checker/MethodSection.astr import AdviceSection from "@/components/features/qday-checker/AdviceSection.astro"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const locale = getLocaleFromUrl(Astro.url.pathname); diff --git a/website/src/pages/[lang]/technology.astro b/website/src/pages/[lang]/technology.astro index aae13ec..e415532 100644 --- a/website/src/pages/[lang]/technology.astro +++ b/website/src/pages/[lang]/technology.astro @@ -3,7 +3,7 @@ import Layout from "@/components/layout/Layout.astro"; import { createTranslator, getLocaleFromUrl, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { createMetadata } from "@/utils/create-metadata"; import { JsonLdGraph } from "@/utils/build-json-ld"; @@ -21,7 +21,7 @@ import ConsensusSection from "@/components/features/technology/ConsensusSection. import CtaSection from "@/components/features/technology/CtaSection.astro"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const locale = getLocaleFromUrl(Astro.url.pathname); diff --git a/website/src/pages/[lang]/terms.astro b/website/src/pages/[lang]/terms.astro index 4ce72fe..35e2b6e 100644 --- a/website/src/pages/[lang]/terms.astro +++ b/website/src/pages/[lang]/terms.astro @@ -5,7 +5,7 @@ import Layout from "@/components/layout/Layout.astro"; import { createTranslator, getLocaleFromUrl, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { createMetadata } from "@/utils/create-metadata"; import { JsonLdGraph } from "@/utils/build-json-ld"; @@ -17,7 +17,7 @@ import { } from "@/constants/default-jsonld"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const locale = getLocaleFromUrl(Astro.url.pathname); diff --git a/website/src/pages/[lang]/wallet.astro b/website/src/pages/[lang]/wallet.astro index b1ecab4..a1bd19b 100644 --- a/website/src/pages/[lang]/wallet.astro +++ b/website/src/pages/[lang]/wallet.astro @@ -3,7 +3,7 @@ import Layout from "@/components/layout/Layout.astro"; import { createTranslator, getLocaleFromUrl, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { createMetadata } from "@/utils/create-metadata"; import { JsonLdGraph } from "@/utils/build-json-ld"; @@ -20,7 +20,7 @@ import IssuesSection from "@/components/features/wallet/IssuesSection.astro"; import CtaSection from "@/components/features/wallet/CtaSection.astro"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const locale = getLocaleFromUrl(Astro.url.pathname); diff --git a/website/src/pages/[lang]/whitepaper.astro b/website/src/pages/[lang]/whitepaper.astro index eaa9b84..166dff3 100644 --- a/website/src/pages/[lang]/whitepaper.astro +++ b/website/src/pages/[lang]/whitepaper.astro @@ -4,7 +4,7 @@ import Layout from "@/components/layout/Layout.astro"; import { getLocaleFromUrl, createTranslator, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { JsonLdGraph } from "@/utils/build-json-ld"; import { getWhitepaperJsonLd } from "@/constants/default-jsonld"; @@ -22,7 +22,7 @@ import { import WhitepaperPrintCover from "@/components/features/whitepaper/WhitepaperPrintCover.astro"; export async function getStaticPaths() { - return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); + return PREFIXED_LOCALES.map((lang) => ({ params: { lang } })); } const locale = getLocaleFromUrl(Astro.url.pathname); diff --git a/website/src/pages/[lang]/whitepaper/[version].astro b/website/src/pages/[lang]/whitepaper/[version].astro index 4d61e38..bea56c4 100644 --- a/website/src/pages/[lang]/whitepaper/[version].astro +++ b/website/src/pages/[lang]/whitepaper/[version].astro @@ -4,7 +4,7 @@ import Layout from "@/components/layout/Layout.astro"; import { getLocaleFromUrl, createTranslator, - SUPPORTED_LOCALES, + PREFIXED_LOCALES, } from "@/utils/i18n"; import { JsonLdGraph } from "@/utils/build-json-ld"; import { getWhitepaperJsonLd } from "@/constants/default-jsonld"; @@ -26,7 +26,7 @@ export async function getStaticPaths() { const allEntries = await getCollection("whitepaper"); const paths: { params: { lang: string; version: string } }[] = []; - for (const lang of SUPPORTED_LOCALES) { + for (const lang of PREFIXED_LOCALES) { const langEntries = allEntries.filter((e) => e.id.toLowerCase().startsWith(`${lang.toLowerCase()}/`), ); diff --git a/website/src/utils/i18n.ts b/website/src/utils/i18n.ts index 980a94e..7296b10 100644 --- a/website/src/utils/i18n.ts +++ b/website/src/utils/i18n.ts @@ -34,6 +34,11 @@ export const HOMEPAGE_LINK = SUPPORTED_LOCALES.map((locale) => { export const DEFAULT_LOCALE: Locale = "en-US"; +/** Locales that use a URL path prefix (excludes default English at root). */ +export const PREFIXED_LOCALES = SUPPORTED_LOCALES.filter( + (locale) => locale !== DEFAULT_LOCALE, +); + export const LOCALES_MAP: Record = { // URL-path: hreflang-value "en-US": "en-US", From 9802cbf99e73ec99f16a4dc83d2f3ad97a746859 Mon Sep 17 00:00:00 2001 From: Beast Date: Thu, 30 Jul 2026 19:45:37 +0800 Subject: [PATCH 2/5] feat: fix nested locale paths + mixxing x-default --- website/astro.config.mjs | 21 +++++++++++ website/src/components/layout/Layout.astro | 19 ++++++---- website/src/utils/i18n.ts | 42 +++++++++++++--------- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/website/astro.config.mjs b/website/astro.config.mjs index 659616c..60217f3 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -87,6 +87,27 @@ export default defineConfig({ item.url = item.url.replace(/^https?:\/\/[^/]+/, baseUrl); } + if (item.links?.length) { + item.links = item.links.map((link) => ({ + ...link, + url: link.url.replace(/^https?:\/\/[^/]+/, baseUrl), + })); + + // Point x-default at the English (root) alternate + const defaultLink = item.links.find( + (link) => link.lang === LOCALES_MAP[DEFAULT_LOCALE], + ); + if ( + defaultLink && + !item.links.some((link) => link.lang === "x-default") + ) { + item.links.push({ + url: defaultLink.url, + lang: "x-default", + }); + } + } + // Check if this is a homepage link using the current base URL const homepageLinks = SUPPORTED_LOCALES.map((locale) => { if (locale === DEFAULT_LOCALE) return `${baseUrl}/`; diff --git a/website/src/components/layout/Layout.astro b/website/src/components/layout/Layout.astro index 4cc2e52..c761ad4 100644 --- a/website/src/components/layout/Layout.astro +++ b/website/src/components/layout/Layout.astro @@ -28,6 +28,7 @@ import { getLocaleFromUrl, getTextDirection, getAlternateUrls, + removeLocaleFromUrl, createTranslator, } from "@/utils/i18n"; import { generateBreadcrumbs } from "@/utils/build-json-ld"; @@ -46,7 +47,7 @@ const currentLocale = getLocaleFromUrl(Astro.url.pathname); const t = await createTranslator(currentLocale); const textDirection = getTextDirection(currentLocale); -// Fix canonical for default locale duplicate content +// Fix canonical for default locale duplicate content (e.g. /en-US/about → /about) let canonical = metadata.canonical; const currentPath = Astro.url.pathname; @@ -54,15 +55,19 @@ if ( currentLocale === DEFAULT_LOCALE && currentPath.startsWith(`/${DEFAULT_LOCALE}`) ) { - const rootPath = currentPath.replace(`/${DEFAULT_LOCALE}`, "") || "/"; - canonical = `${env.SITE_BASE_URL}${rootPath}`; + canonical = `${env.SITE_BASE_URL}${removeLocaleFromUrl(currentPath)}`; } const alternates = getAlternateUrls(currentPath); -const languageAlternates = Object.entries(alternates).map(([lang, path]) => ({ - href: `${env.SITE_BASE_URL}${path}`, - hrefLang: lang, -})); +const defaultHref = `${env.SITE_BASE_URL}${alternates[DEFAULT_LOCALE]}`; +const languageAlternates = [ + ...Object.entries(alternates).map(([lang, path]) => ({ + href: `${env.SITE_BASE_URL}${path}`, + hrefLang: lang, + })), + // Fallback language for unmatched locales (Google hreflang requirement) + { href: defaultHref, hrefLang: "x-default" }, +]; const breadcrumbs = generateBreadcrumbs({ pathname: currentPath, diff --git a/website/src/utils/i18n.ts b/website/src/utils/i18n.ts index 7296b10..ff64078 100644 --- a/website/src/utils/i18n.ts +++ b/website/src/utils/i18n.ts @@ -182,15 +182,7 @@ export async function createTranslator(locale: Locale) { export function getLocalizedPath(locale: Locale, pathname: string): string { if (pathname.includes("http")) return pathname; - // If it's the default language, don't add a prefix. - if (locale === DEFAULT_LOCALE) { - return pathname; - } - - // For other languages, add the language prefix. - // Make sure the path starts with a slash for consistency. - const finalPath = pathname.startsWith("/") ? pathname : `/${pathname}`; - return `/${locale}${finalPath}`; + return addLocaleToUrl(pathname, locale); } /** @@ -208,28 +200,44 @@ export function getLocaleFromUrl(pathname: string): Locale { } /** - * Remove locale from URL pathname + * Remove locale from URL pathname. + * Strips any supported locale prefix (including nested `/zh-CN/en-US/...`) + * and preserves a trailing slash when the input had one. */ export function removeLocaleFromUrl(pathname: string): string { - const locale = getLocaleFromUrl(pathname); + let path = pathname || "/"; + const hadTrailingSlash = path.length > 1 && path.endsWith("/"); - if (locale === DEFAULT_LOCALE) { - return pathname; + while (true) { + const segments = path.split("/").filter(Boolean); + const potentialLocale = segments[0] as Locale; + + if (!SUPPORTED_LOCALES.includes(potentialLocale)) { + break; + } + + const rest = segments.slice(1).join("/"); + path = rest ? `/${rest}` : "/"; + } + + if (path !== "/" && hadTrailingSlash && !path.endsWith("/")) { + path += "/"; } - return pathname.replace(`/${locale}`, "") || "/"; + return path; } /** * Add locale to URL pathname */ export function addLocaleToUrl(pathname: string, locale: Locale): string { - // Don't add locale for default locale + const cleanPath = removeLocaleFromUrl(pathname); + + // Default English lives at the root (no prefix). if (locale === DEFAULT_LOCALE) { - return pathname; + return cleanPath; } - const cleanPath = removeLocaleFromUrl(pathname); return `/${locale}${cleanPath === "/" ? "" : cleanPath}`; } From e1b3baa752a8b519c3724c7d2fce158cbd9e953d Mon Sep 17 00:00:00 2001 From: Beast Date: Fri, 31 Jul 2026 11:19:21 +0800 Subject: [PATCH 3/5] feat: allow AI bot access --- website/public/robots.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/public/robots.txt b/website/public/robots.txt index cd352e8..9d2ff90 100644 --- a/website/public/robots.txt +++ b/website/public/robots.txt @@ -1,4 +1,6 @@ User-agent: * +Content-Signal: search=yes, ai-input=yes, ai-train=no + Allow: / Sitemap: https://www.quantus.com/sitemap-index.xml \ No newline at end of file From 784575bc5bb236d77e8c9386d247e10aa42d0dcc Mon Sep 17 00:00:00 2001 From: Beast Date: Fri, 31 Jul 2026 12:38:27 +0800 Subject: [PATCH 4/5] feat: add custom event tracker --- .../features/about/ContactSection.astro | 4 + .../features/community/EventSection.astro | 5 +- .../features/community/SocialsSection.astro | 9 ++ .../features/community/TelegramSection.astro | 6 +- .../features/home/CommunitySection.astro | 12 ++ .../features/home/EcosystemSection.astro | 15 +- .../components/features/home/HeroBanner.astro | 2 + .../features/home/NewsletterSection.astro | 12 +- .../features/qday-checker/AdviceSection.astro | 5 +- .../features/qday-checker/HeroBanner.astro | 6 + .../features/technology/CtaSection.astro | 2 + .../features/wallet/CtaSection.astro | 6 + .../features/wallet/HeroBanner.astro | 6 + .../features/whitepaper/DownloadButton.astro | 2 + .../src/components/layout/footer/Footer.astro | 2 + .../src/components/layout/navbar/Navbar.astro | 26 ++- .../src/components/ui/AppInformation.astro | 6 + website/src/components/ui/Button.astro | 2 + website/src/components/ui/CookieConsent.astro | 3 + website/src/components/ui/SiteSocials.astro | 17 ++ website/src/constants/footer-navigations.ts | 15 ++ website/src/constants/site-navigations.ts | 5 + website/src/pages/invite.astro | 6 + website/src/scripts/shared/analytics.ts | 152 ++++++++++++++++++ 24 files changed, 317 insertions(+), 9 deletions(-) create mode 100644 website/src/scripts/shared/analytics.ts diff --git a/website/src/components/features/about/ContactSection.astro b/website/src/components/features/about/ContactSection.astro index 2aa770e..bd8681b 100644 --- a/website/src/components/features/about/ContactSection.astro +++ b/website/src/components/features/about/ContactSection.astro @@ -21,6 +21,8 @@ const t = await createTranslator(locale); href="mailto:hello@quantus.com" class="contact-email about-animate" data-delay="0.45" + data-track="contact_email_click" + data-track-cta-location="about_contact" > {t("about.contact.email")} @@ -28,6 +30,8 @@ const t = await createTranslator(locale); href="mailto:hello@quantus.com?subject=Enquiry%20from%20Quantus%20Website" class="contact-cta about-animate" data-delay="0.6" + data-track="contact_email_click" + data-track-cta-location="about_contact" > {t("about.contact.cta")} diff --git a/website/src/components/features/community/EventSection.astro b/website/src/components/features/community/EventSection.astro index 0a10373..2838c86 100644 --- a/website/src/components/features/community/EventSection.astro +++ b/website/src/components/features/community/EventSection.astro @@ -26,7 +26,10 @@ const t = await createTranslator(locale); href="https://tally.so/r/D4502E" target="_blank" rel="noopener" - class="event-cta">{t("community.events.card.cta")}{t("community.events.card.cta")}
diff --git a/website/src/components/features/community/SocialsSection.astro b/website/src/components/features/community/SocialsSection.astro index 9f15f29..044a9c9 100644 --- a/website/src/components/features/community/SocialsSection.astro +++ b/website/src/components/features/community/SocialsSection.astro @@ -20,6 +20,9 @@ const t = await createTranslator(locale); rel="noopener" class="social-box comm-animate" data-delay="0" + data-track="community_click" + data-track-channel="x" + data-track-cta-location="community_socials" >
diff --git a/website/src/components/features/home/CommunitySection.astro b/website/src/components/features/home/CommunitySection.astro index e7ca9f6..7f2a377 100644 --- a/website/src/components/features/home/CommunitySection.astro +++ b/website/src/components/features/home/CommunitySection.astro @@ -43,6 +43,9 @@ const t = await createTranslator(locale); href="https://t.me/quantusnetwork" target="_blank" class="community-panel-cta" + data-track="community_click" + data-track-channel="telegram" + data-track-cta-location="home_community" > {t("home.community.cards.telegram.cta")} @@ -73,6 +76,9 @@ const t = await createTranslator(locale); href="https://x.com/QuantusNetwork" target="_blank" class="community-panel-cta" + data-track="community_click" + data-track-channel="x" + data-track-cta-location="home_community" > {t("home.community.cards.x.cta")} @@ -118,6 +124,9 @@ const t = await createTranslator(locale); href="https://www.instagram.com/quantusnetwork/" target="_blank" class="community-panel-cta" + data-track="community_click" + data-track-channel="instagram" + data-track-cta-location="home_community" > {t("home.community.cards.instagram.cta")} @@ -148,6 +157,9 @@ const t = await createTranslator(locale); href="https://www.youtube.com/@QuantusNetwork" target="_blank" class="community-panel-cta" + data-track="community_click" + data-track-channel="youtube" + data-track-cta-location="home_community" > {t("home.community.cards.youtube.cta")} diff --git a/website/src/components/features/home/EcosystemSection.astro b/website/src/components/features/home/EcosystemSection.astro index 6b20774..cef6c87 100644 --- a/website/src/components/features/home/EcosystemSection.astro +++ b/website/src/components/features/home/EcosystemSection.astro @@ -128,6 +128,9 @@ const t = await createTranslator(locale); target="_blank" rel="noopener" class="eco-dl-tag" + data-track="wallet_store_click" + data-track-store="ios" + data-track-cta-location="home_ecosystem" > {t("home.ecosystem.cards.wallet.app_store")} @@ -136,6 +139,9 @@ const t = await createTranslator(locale); target="_blank" rel="noopener" class="eco-dl-tag" + data-track="wallet_store_click" + data-track-store="android" + data-track-cta-location="home_ecosystem" > {t("home.ecosystem.cards.wallet.google_play")} @@ -340,7 +346,14 @@ const t = await createTranslator(locale); {t("home.ecosystem.cards.network.validators")} diff --git a/website/src/components/features/home/HeroBanner.astro b/website/src/components/features/home/HeroBanner.astro index ced483d..e5f68d3 100644 --- a/website/src/components/features/home/HeroBanner.astro +++ b/website/src/components/features/home/HeroBanner.astro @@ -25,6 +25,8 @@ const t = await createTranslator(locale); class="wallet-cta-link" target="_blank" rel="noopener" + data-track="wallet_store_click" + data-track-cta-location="home_hero" > {t("home.hero_banner.cta_download_wallet")} diff --git a/website/src/components/features/home/NewsletterSection.astro b/website/src/components/features/home/NewsletterSection.astro index dc88a06..c04014f 100644 --- a/website/src/components/features/home/NewsletterSection.astro +++ b/website/src/components/features/home/NewsletterSection.astro @@ -310,6 +310,7 @@ const t = await createTranslator(locale); diff --git a/website/src/components/ui/AppInformation.astro b/website/src/components/ui/AppInformation.astro index f277f36..6987984 100644 --- a/website/src/components/ui/AppInformation.astro +++ b/website/src/components/ui/AppInformation.astro @@ -45,6 +45,9 @@ const t = await createTranslator(locale); href={APP_LINKS.ios} target="_blank" rel="noopener noreferrer" + data-track="wallet_store_click" + data-track-store="ios" + data-track-cta-location="account" > {t("app.download.ios")} @@ -54,6 +57,9 @@ const t = await createTranslator(locale); href={APP_LINKS.android} target="_blank" rel="noopener noreferrer" + data-track="wallet_store_click" + data-track-store="android" + data-track-cta-location="account" > {t("app.download.android")} diff --git a/website/src/components/ui/Button.astro b/website/src/components/ui/Button.astro index 6d32795..72431d2 100644 --- a/website/src/components/ui/Button.astro +++ b/website/src/components/ui/Button.astro @@ -14,6 +14,8 @@ export interface Props { href?: string; target?: string; rel?: string; + /** Allow data-track* and other passthrough HTML attributes */ + [key: `data-${string}`]: string | undefined; } const { diff --git a/website/src/components/ui/CookieConsent.astro b/website/src/components/ui/CookieConsent.astro index 2419db5..a2557ef 100644 --- a/website/src/components/ui/CookieConsent.astro +++ b/website/src/components/ui/CookieConsent.astro @@ -41,6 +41,9 @@ const t = await createTranslator(locale);