diff --git a/.changelog/1294.feature.md b/.changelog/1294.feature.md index 67ee11315..e65ff7892 100644 --- a/.changelog/1294.feature.md +++ b/.changelog/1294.feature.md @@ -1 +1 @@ -Analytics: integrate matomo with UI (using matomo cookies for storage) +Integrate matomo analytics diff --git a/.changelog/1325.feature.md b/.changelog/1325.feature.md new file mode 100644 index 000000000..e65ff7892 --- /dev/null +++ b/.changelog/1325.feature.md @@ -0,0 +1 @@ +Integrate matomo analytics diff --git a/src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx b/src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx new file mode 100644 index 000000000..880460e36 --- /dev/null +++ b/src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx @@ -0,0 +1,70 @@ +import Snackbar from '@mui/material/Snackbar' +import Typography from '@mui/material/Typography' +import { styled } from '@mui/material/styles' +import Button from '@mui/material/Button' +import Link from '@mui/material/Link' +import { Trans, useTranslation } from 'react-i18next' +import Card from '@mui/material/Card' +import CardContent from '@mui/material/CardContent' +import CardActions from '@mui/material/CardActions' +import { useScreenSize } from 'app/hooks/useScreensize' +import { legalDocuments } from '../../utils/externalLinks' + +const StyledButton = styled(Button)(({ theme }) => ({ + paddingLeft: theme.spacing(5), + paddingRight: theme.spacing(5), +})) + +export const AnalyticsIsBlocked = (props: { isOpen: boolean; onReload: () => void; onClose: () => void }) => { + const { t } = useTranslation() + const { isMobile } = useScreenSize() + return ( + <> + + + + + + ), + }} + /> + + + + props.onReload()} color="secondary" variant="outlined"> + {t('analyticsConsent.reloadButtonLabel')} + + props.onClose()} color="secondary" variant="outlined"> + {t('analyticsConsent.closeButtonLabel')} + + + + + + ) +} diff --git a/src/app/components/AnalyticsConsent/index.tsx b/src/app/components/AnalyticsConsent/index.tsx index cd7401821..99e33a5bf 100644 --- a/src/app/components/AnalyticsConsent/index.tsx +++ b/src/app/components/AnalyticsConsent/index.tsx @@ -15,6 +15,7 @@ import * as matomo from './initializeMatomo' import { legalDocuments } from '../../utils/externalLinks' import { ThemeByNetwork } from '../ThemeByNetwork' import { Network } from '../../../types/network' +import { AnalyticsIsBlocked } from './AnalyticsIsBlocked' const AnalyticsContext = createContext<{ reopenAnalyticsConsent: () => void @@ -23,7 +24,9 @@ const AnalyticsContext = createContext<{ export const AnalyticsConsentProvider = (props: { children: React.ReactNode }) => { if (process.env.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS !== 'true') return <>{props.children} - const [hasAccepted, setHasAccepted] = useState('timed_out_matomo_not_loaded') + const [hasAccepted, setHasAccepted] = useState< + matomo.HasAccepted | 'loading' | 'timed_out_matomo_not_loaded_force_open' + >('loading') useEffect(() => { matomo.addMatomo() @@ -53,7 +56,17 @@ export const AnalyticsConsentProvider = (props: { children: React.ReactNode }) = }, [location.key, hasAccepted]) return ( - setHasAccepted('not-chosen') }}> + { + if (hasAccepted === 'timed_out_matomo_not_loaded' || hasAccepted === 'loading') { + setHasAccepted('timed_out_matomo_not_loaded_force_open') + } else { + setHasAccepted('not-chosen') + } + }, + }} + > {props.children} {/* Theme is needed because AnalyticsConsentProvider is outside network-themed routes */} @@ -68,6 +81,11 @@ export const AnalyticsConsentProvider = (props: { children: React.ReactNode }) = setHasAccepted(await matomo.hasAccepted({ timeout: 10_000 })) }} /> + window.location.reload()} + onClose={() => setHasAccepted('timed_out_matomo_not_loaded')} + /> ) @@ -86,12 +104,7 @@ export const ReopenAnalyticsConsentButton = () => { ) } -const AcceptCookiesButton = styled(Button)(({ theme }) => ({ - paddingLeft: theme.spacing(5), - paddingRight: theme.spacing(5), -})) - -const DeclineCookiesButton = styled(Button)(({ theme }) => ({ +const StyledButton = styled(Button)(({ theme }) => ({ paddingLeft: theme.spacing(5), paddingRight: theme.spacing(5), })) @@ -118,6 +131,7 @@ export const AnalyticsConsentView = (props: { - props.onAccept()} color="primary" variant="contained"> + props.onAccept()} color="primary" variant="contained"> {t('analyticsConsent.acceptButtonLabel')} - - props.onDecline()} color="secondary" variant="outlined"> + + props.onDecline()} color="secondary" variant="outlined"> {t('analyticsConsent.declineButtonLabel')} - + diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 18dde2369..222152981 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -33,8 +33,11 @@ "analyticsConsent": { "settings": "Privacy settings", "text": "At Oasis Foundation we believe in your privacy, so you can choose to browse our site without any tracking or by clicking “{{acceptButtonLabel}}”, you help us to improve our site and help us grow our ecosystem. View our Privacy Policy for more information.", + "blockedText": "Our analytics tracking failed to load. Therefore, you will continue using the site with user tracking disabled. If you are willing to accept tracking please pause your adblocker and reload the page to accept tracking. View our Privacy Policy for more information.", "acceptButtonLabel": "Accept", - "declineButtonLabel": "Decline" + "declineButtonLabel": "Decline", + "reloadButtonLabel": "Reload page", + "closeButtonLabel": "Close" }, "blocks": { "latest": "Latest Blocks",