diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 945ed555639..9cb6775bfb7 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -79,6 +79,8 @@ jobs: run: yarn workspace docs version::stables - name: Build docs + env: + MATOMO_ENV: staging # not really a secret, it will show in the footer anyway run: yarn workspaces foreach -Rpt --from docs run build - name: Upload artifact diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 49566c5c380..2d5b8941f55 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -47,7 +47,9 @@ export default { }, ], ], - + customFields: { + MATOMO_ENV: process.env.MATOMO_ENV, + }, themeConfig: { colorMode: { respectPrefersColorScheme: true, diff --git a/docs/package.json b/docs/package.json index f9e95fc02f8..c81d0b7b24f 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,11 +4,12 @@ "private": true, "scripts": { "preprocess": "yarn workspace @noir-lang/acvm_js build && ./scripts/codegen_nargo_reference.sh && yarn node ./scripts/preprocess/index.js", - "start": "yarn preprocess && docusaurus start", + "start": "yarn preprocess && MATOMO_ENV=dev docusaurus start", "build": "yarn preprocess && docusaurus build", "clean": "rm -rf ./processed-docs ./processed-docs ./build", "version::stables": "ts-node ./scripts/setStable.ts", "serve": "serve build", + "swizzle": "docusaurus swizzle", "version": "yarn version::stables && ./scripts/cut_version.sh" }, "dependencies": { diff --git a/docs/src/components/Matomo/matomo.jsx b/docs/src/components/Matomo/matomo.jsx new file mode 100644 index 00000000000..7ee34fc8e51 --- /dev/null +++ b/docs/src/components/Matomo/matomo.jsx @@ -0,0 +1,133 @@ +import { useEffect, useState } from 'react'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import Link from '@docusaurus/Link'; + +function getSiteId(env) { + if (env == 'dev') { + return '3'; + } else if (env == 'staging') { + return '2'; + } else { + return '1'; + } +} +function pushInstruction(name, ...args) { + return window._paq.push([name, ...args]); +} + +export default function useMatomo() { + const { siteConfig } = useDocusaurusContext(); + const [showBanner, setShowBanner] = useState(false); + + const env = siteConfig.customFields.MATOMO_ENV; + const urlBase = 'https://noirlang.matomo.cloud/'; + const trackerUrl = `${urlBase}matomo.php`; + const srcUrl = `${urlBase}matomo.js`; + + window._paq = window._paq || []; + + useEffect(() => { + const storedConsent = localStorage.getItem('matomoConsent'); + if (storedConsent === null) { + setShowBanner(true); + } + }, []); + + useEffect(() => { + pushInstruction('setTrackerUrl', trackerUrl); + pushInstruction('setSiteId', getSiteId(env)); + if (env !== 'prod') { + pushInstruction('setSecureCookie', false); + } + + const doc = document; + const scriptElement = doc.createElement('script'); + const scripts = doc.getElementsByTagName('script')[0]; + + scriptElement.type = 'text/javascript'; + scriptElement.async = true; + scriptElement.defer = true; + scriptElement.src = srcUrl; + + if (scripts && scripts.parentNode) { + scripts.parentNode.insertBefore(scriptElement, scripts); + } + }, []); + + useEffect(() => { + pushInstruction('trackPageView'); + }, [window.location.href]); + + const optIn = () => { + pushInstruction('rememberConsentGiven'); + localStorage.setItem('matomoConsent', true); + setShowBanner(false); + }; + + const optOut = () => { + pushInstruction('forgetConsentGiven'); + localStorage.setItem('matomoConsent', false); + setShowBanner(false); + }; + + const debug = () => { + pushInstruction(function () { + console.log(this.getRememberedConsent()); + console.log(localStorage.getItem('matomoConsent')); + }); + }; + + const reset = () => { + pushInstruction('forgetConsentGiven'); + localStorage.clear('matomoConsent'); + }; + + if (!showBanner && env === 'dev') { + return ( +
+
+

Debugging analytics

+
+ + +
+
+
+ ); + } else if (!showBanner) { + return null; + } + + return ( +
+
+

+ We value your privacy and we only collect statistics and essential cookies. If you'd like to help us improve + our websites, you can allow cookies for tracking page views, time on site, and other analytics. +
+
+ + Find out how we use cookies and how you can change your settings. + +

+
+ + + {env === 'dev' && ( + + )} +
+
+
+ ); +} diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index b08766fbc3b..fb6be87b519 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -214,3 +214,31 @@ input#docsearch-input { background-color: transparent; } + +#optout-form { + position: sticky; + bottom: 10px; + flex-direction: column; + display: flex; + max-width: 800px; + margin: 0 auto; + background-color: var(--ifm-breadcrumb-color-active); +} + + + +.homepage_footer { + text-align: center; + margin-bottom: 1rem; + padding: 1.5rem 2rem; + display: flex; + flex-direction: column; + border: 1px solid #BEC2C3; + border-radius: 12px; +} + +.homepage_cta_footer_container { + display: flex; + justify-content: center; +} + diff --git a/docs/src/pages/index.jsx b/docs/src/pages/index.jsx index b372871e7b4..c7de44b300d 100644 --- a/docs/src/pages/index.jsx +++ b/docs/src/pages/index.jsx @@ -1,9 +1,8 @@ -import React, { lazy, Suspense } from 'react'; +import React from 'react'; import Layout from '@theme/Layout'; import Link from '@docusaurus/Link'; import headerPic from '@site/static/img/homepage_header_pic.png'; -import { BeatLoader } from 'react-spinners'; export default function Landing() { return ( diff --git a/docs/src/theme/Root.js b/docs/src/theme/Root.js new file mode 100644 index 00000000000..68c1e529db3 --- /dev/null +++ b/docs/src/theme/Root.js @@ -0,0 +1,22 @@ +import React from 'react'; +import useMatomo from '@site/src/components/Matomo/matomo'; +import BrowserOnly from '@docusaurus/BrowserOnly'; +import useIsBrowser from '@docusaurus/useIsBrowser'; + +function OptOutForm() { + const banner = useMatomo(); + + return <>{banner}; +} + +export default function Root({ children }) { + const useIsBrowserValue = useIsBrowser(); + if (!useIsBrowserValue) return <>{children}; + + return ( + <> + {children} + {() => } + + ); +}