64 lines
2.8 KiB
Plaintext
64 lines
2.8 KiB
Plaintext
---
|
|
/**
|
|
* The Matomo opt-out on the privacy page, in the site's own type rather than Matomo's embed. It
|
|
* asks the tracker already on the page: optUserOut stores the one cookie the tracker keeps with
|
|
* cookies disabled (mtm_consent_removed), forgetUserOptOut removes it. If the tracker never
|
|
* arrives (a content blocker, or a development build), the page says so: nothing is counted.
|
|
*/
|
|
import { t, type Lang } from '../i18n/ui';
|
|
interface Props { lang: Lang }
|
|
const { lang } = Astro.props;
|
|
const o = t(lang).legal.optOut;
|
|
---
|
|
<div class="optout" data-optout data-status-in={o.in} data-status-out={o.out} data-status-dnt={o.dnt} data-status-missing={o.missing} data-label-out={o.stop} data-label-in={o.resume}>
|
|
<p class="optout__status" role="status" data-optout-status>{o.checking}</p>
|
|
<button class="button button--small" type="button" data-optout-toggle hidden></button>
|
|
<noscript><p class="optout__status">{o.noscript}</p></noscript>
|
|
</div>
|
|
|
|
<style>
|
|
.optout { display: grid; gap: var(--space-4); justify-items: start; }
|
|
.optout__status { color: var(--ink-muted); }
|
|
.optout .button { font: inherit; font-size: var(--step-small); font-weight: var(--weight-medium); border: 0; cursor: pointer; }
|
|
</style>
|
|
|
|
<script>
|
|
type Tracker = { isUserOptedOut(): boolean; optUserOut(): void; forgetUserOptOut(): void };
|
|
type Paq = { push(cmd: unknown[]): void };
|
|
|
|
const root = document.querySelector<HTMLElement>('[data-optout]');
|
|
const status = root?.querySelector<HTMLElement>('[data-optout-status]');
|
|
const toggle = root?.querySelector<HTMLButtonElement>('[data-optout-toggle]');
|
|
|
|
if (root && status && toggle) {
|
|
const d = root.dataset;
|
|
const dnt = navigator.doNotTrack === '1' || (window as { doNotTrack?: string }).doNotTrack === '1';
|
|
let tracker: Tracker | undefined;
|
|
|
|
const render = () => {
|
|
if (dnt) { status.textContent = d.statusDnt!; toggle.hidden = true; return; }
|
|
if (!tracker) { status.textContent = d.statusMissing!; toggle.hidden = true; return; }
|
|
const out = tracker.isUserOptedOut();
|
|
status.textContent = out ? d.statusOut! : d.statusIn!;
|
|
toggle.textContent = out ? d.labelIn! : d.labelOut!;
|
|
toggle.hidden = false;
|
|
};
|
|
|
|
toggle.addEventListener('click', () => {
|
|
if (!tracker) return;
|
|
if (tracker.isUserOptedOut()) tracker.forgetUserOptOut(); else tracker.optUserOut();
|
|
render();
|
|
});
|
|
|
|
// A function pushed onto _paq runs with the tracker as `this` once matomo.js has loaded.
|
|
const paq = (window as { _paq?: Paq })._paq;
|
|
if (paq && !dnt) {
|
|
paq.push([function (this: Tracker) { tracker = this; render(); }]);
|
|
// If it has not arrived in a few seconds, it is blocked or not part of this build.
|
|
window.setTimeout(() => { if (!tracker) render(); }, 4000);
|
|
} else {
|
|
render();
|
|
}
|
|
}
|
|
</script>
|