Matomo-Tracking und Aufrufzaehlung absichern

This commit is contained in:
2026-08-27 12:20:56 +02:00
parent 528af07890
commit c86803bbd6
26 changed files with 1019 additions and 106 deletions
+21 -6
View File
@@ -5,7 +5,8 @@ declare(strict_types=1);
require_once __DIR__ . '/bootstrap.php';
const APP_ANALYTICS_CONSENT_COOKIE = 'kaffeeliste_analytics_consent';
const APP_ANALYTICS_CONSENT_VERSION = '1';
const APP_ANALYTICS_VISITOR_COOKIE = 'kaffeeliste_analytics_visitor';
const APP_ANALYTICS_CONSENT_VERSION = '2';
const APP_ANALYTICS_CONSENT_MAX_AGE = 15552000; // 180 Tage
/**
@@ -71,7 +72,7 @@ function app_matomo_configuration_errors(): array
}
/**
* @return array{matomoUrl: string, siteId: string, consentCookie: string, consentVersion: string, consentMaxAge: int, cookieDomain: string, secureCookies: bool}|null
* @return array{matomoUrl: string, siteId: string, consentCookie: string, visitorCookie: string, consentVersion: string, consentMaxAge: int, cookieDomain: string, secureCookies: bool}|null
*/
function app_matomo_configuration(): ?array
{
@@ -90,6 +91,7 @@ function app_matomo_configuration(): ?array
'matomoUrl' => rtrim($url, '/') . '/',
'siteId' => $siteId,
'consentCookie' => APP_ANALYTICS_CONSENT_COOKIE,
'visitorCookie' => APP_ANALYTICS_VISITOR_COOKIE,
'consentVersion' => APP_ANALYTICS_CONSENT_VERSION,
'consentMaxAge' => APP_ANALYTICS_CONSENT_MAX_AGE,
'cookieDomain' => trim((string)app_env('MATOMO_CONSENT_COOKIE_DOMAIN', '')),
@@ -103,7 +105,7 @@ function app_analytics_head_html(): string
return '';
}
return '<link rel="stylesheet" href="assets/css/analytics-consent.css">' . "\n";
return '<link rel="stylesheet" href="assets/css/privacy-settings.css">' . "\n";
}
function app_analytics_body_html(): string
@@ -113,8 +115,21 @@ function app_analytics_body_html(): string
return '';
}
// Matomo-Host und Site-ID bleiben serverseitig. Der Browser sendet nach
// Einwilligung nur an den First-Party-Endpunkt; dieser leitet die eng
// validierte Seitenansicht an die fest konfigurierte Matomo-Site weiter.
$browserConfiguration = [
'consentCookie' => $configuration['consentCookie'],
'visitorCookie' => $configuration['visitorCookie'],
'consentVersion' => $configuration['consentVersion'],
'consentMaxAge' => $configuration['consentMaxAge'],
'cookieDomain' => $configuration['cookieDomain'],
'secureCookies' => $configuration['secureCookies'],
'trackingEndpoint' => 'nutzungsanalyse.php',
];
$json = json_encode(
$configuration,
$browserConfiguration,
JSON_UNESCAPED_SLASHES
| JSON_UNESCAPED_UNICODE
| JSON_HEX_TAG
@@ -131,7 +146,7 @@ function app_analytics_body_html(): string
<div class="analytics-consent__inner">
<div class="analytics-consent__copy">
<h2 id="analytics-consent-title">Optionale Nutzungsanalyse</h2>
<p id="analytics-consent-description">Wir möchten mit Matomo verstehen, wie unsere Website und App genutzt werden. Erst nach deiner Zustimmung laden wir Matomo und setzen Analyse-Cookies. Notwendige Cookies funktionieren immer. Mehr dazu steht im <a href="datenschutz.php">Datenschutz</a>.</p>
<p id="analytics-consent-description">Wir möchten mit Matomo verstehen, wie unsere Website und App genutzt werden. Erst nach deiner Zustimmung übermitteln wir Seitenaufrufe an unser selbst betriebenes Matomo und setzen ein Analyse-Cookie. Notwendige Cookies funktionieren immer. Mehr dazu steht im <a href="datenschutz.php">Datenschutz</a>.</p>
</div>
<div class="analytics-consent__actions">
<button type="button" data-analytics-consent="denied">Nur notwendige</button>
@@ -142,5 +157,5 @@ function app_analytics_body_html(): string
<button type="button" class="analytics-consent-settings" id="analytics-consent-settings" hidden>Cookie-Einstellungen</button>
HTML
. "\n<script type=\"application/json\" id=\"analytics-configuration\">{$json}</script>\n"
. '<script src="assets/js/analytics-consent.js" defer></script>' . "\n";
. '<script src="assets/js/privacy-settings.js" defer></script>' . "\n";
}