Skip to content

Commit 36e9003

Browse files
committed
feat(consent_manager): ready-event und dev-kurzhilfe ergänzen
1 parent 7bcd659 commit 36e9003

6 files changed

Lines changed: 227 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
- **Cleanup (Issue #470):** Inline-JS aus `pages/config.php` und `pages/help.php` in externe Assets ausgelagert.
1313
- **Fix:** Backend-JS wird zentral im Boot-Prozess eingebunden, statt seitenlokal verteilt.
1414
- **Fix:** Initialisierung im Backend auf `rex:ready` vereinheitlicht; PJAX-spezifische Zusatzpfade entfernt.
15+
- **Fix:** Consent-Logging-Request auf same-origin umgestellt (`window.location` statt `fe_controller`), um `TypeError: Load failed` bei Host-/Protokoll-Mismatch zu vermeiden.
16+
- **Feature (JS API):** Neues Event `consent_manager-ready` eingeführt, damit eigene Skripte zuverlässig auf die Initialisierung reagieren können.
17+
- **Docs:** Neue Entwickler-Kurzhilfe `DEV_QUICKSTART.md` mit Einbindungsvarianten sowie Consent-Abfragen per PHP/JavaScript ergänzt und in die Hilfe-Navigation integriert.
1518

1619
## Version 5.6.0-beta1 - 05.03.2026
1720

DEV_QUICKSTART.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Consent Manager – Dev Kurzhilfe (Schnellstart)
2+
3+
Kurz und praktisch: Einbindung, Consent-Abfrage und typische Snippets.
4+
5+
## 1) Einbindung wählen
6+
7+
### Option A: Auto-Inject (empfohlen)
8+
1. Backend öffnen: `Consent Manager -> Domains -> Domain bearbeiten`
9+
2. `Automatische Frontend-Einbindung` auf **Aktiviert** setzen
10+
3. Speichern
11+
12+
Ergebnis: Der Consent Manager wird automatisch vor `</head>` eingebunden.
13+
14+
### Option B: Manuell im Template (komplett)
15+
16+
```php
17+
<?php
18+
use FriendsOfRedaxo\ConsentManager\Frontend;
19+
20+
echo Frontend::getFragment(0, 0, 'ConsentManager/box_cssjs.php');
21+
```
22+
23+
### Option C: Manuell, Komponenten getrennt
24+
25+
```php
26+
<?php
27+
use FriendsOfRedaxo\ConsentManager\Frontend;
28+
?>
29+
<style><?= Frontend::getCSS() ?></style>
30+
<script<?= Frontend::getNonceAttribute() ?>>
31+
<?= Frontend::getJS() ?>
32+
</script>
33+
<?= Frontend::getBox() ?>
34+
```
35+
36+
---
37+
38+
## 2) Consent in PHP abfragen
39+
40+
```php
41+
<?php
42+
use FriendsOfRedaxo\ConsentManager\Utility;
43+
44+
if (Utility::has_consent('google-analytics')) {
45+
// Script/Markup nur bei erteiltem Consent ausgeben
46+
}
47+
```
48+
49+
---
50+
51+
## 3) Consent in JavaScript abfragen
52+
53+
Wichtig: Eigene Skripte sollten warten, bis der Consent Manager initialisiert ist.
54+
55+
```javascript
56+
document.addEventListener('consent_manager-ready', function (e) {
57+
if (!e.detail.initialized) {
58+
console.warn('Consent Manager nicht bereit:', e.detail.reason);
59+
return;
60+
}
61+
62+
if (typeof consent_manager_hasconsent === 'function' && consent_manager_hasconsent('google-analytics')) {
63+
console.log('GA darf geladen werden');
64+
}
65+
});
66+
```
67+
68+
Direkte Abfrage (wenn bereits sicher initialisiert):
69+
70+
```javascript
71+
if (typeof consent_manager_hasconsent === 'function' && consent_manager_hasconsent('google-analytics')) {
72+
// Consent vorhanden
73+
}
74+
```
75+
76+
---
77+
78+
## 4) Auf Consent-Änderung reagieren
79+
80+
```javascript
81+
document.addEventListener('consent_manager-saved', function (e) {
82+
var consents = JSON.parse(e.detail);
83+
// z. B. Tracking dynamisch starten/stoppen
84+
});
85+
```
86+
87+
---
88+
89+
## 5) Einstellungen-Dialog per Link öffnen
90+
91+
Standard (ohne Reload):
92+
93+
```html
94+
<a href="#" data-consent-action="settings">Cookie-Einstellungen</a>
95+
```
96+
97+
Variante mit Reload nach Speichern:
98+
99+
```html
100+
<a href="#" data-consent-action="settings,reload">Cookie-Einstellungen</a>
101+
```
102+
103+
Tipp: `reload` ist sinnvoll, wenn externe Skripte keinen sauberen Live-Reinit unterstützen und erst nach einem Seiten-Reload korrekt starten/stoppen.
104+
105+
---
106+
107+
## 6) Häufige Stolpersteine
108+
109+
- `consent_manager_hasconsent is not defined`: Consent Manager ist noch nicht geladen oder gar nicht eingebunden.
110+
- `TypeError: Load failed` beim Speichern: meist URL-/Host-/HTTPS-Mismatch im Setup; aktuelle Version nutzt same-origin Logging.
111+
- Falsche Quotes in JS vermeiden: normale `'` oder `"` verwenden, keine typografischen Anführungszeichen.
112+
113+
---
114+
115+
## 7) Spezialfälle (Tipps)
116+
117+
### A) Mehrere Services gleichzeitig prüfen
118+
119+
```javascript
120+
function hasAllConsents(serviceKeys) {
121+
if (typeof consent_manager_hasconsent !== 'function') return false;
122+
return serviceKeys.every(function (key) {
123+
return consent_manager_hasconsent(key);
124+
});
125+
}
126+
127+
document.addEventListener('consent_manager-ready', function () {
128+
if (hasAllConsents(['google-analytics', 'google-tag-manager'])) {
129+
// Nur wenn beide erlaubt sind
130+
}
131+
});
132+
```
133+
134+
### B) Script erst nach Consent dynamisch laden
135+
136+
```javascript
137+
function loadScript(src) {
138+
var script = document.createElement('script');
139+
script.src = src;
140+
script.async = true;
141+
document.head.appendChild(script);
142+
}
143+
144+
document.addEventListener('consent_manager-ready', function () {
145+
if (typeof consent_manager_hasconsent === 'function' && consent_manager_hasconsent('google-analytics')) {
146+
loadScript('https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX');
147+
}
148+
});
149+
```
150+
151+
### C) Reaktion auf spätere Änderungen (Opt-in/Opt-out)
152+
153+
```javascript
154+
document.addEventListener('consent_manager-saved', function () {
155+
if (typeof consent_manager_hasconsent !== 'function') return;
156+
157+
if (consent_manager_hasconsent('google-analytics')) {
158+
// Tracking aktivieren
159+
} else {
160+
// Tracking deaktivieren / keine neuen Events senden
161+
}
162+
});
163+
```
164+
165+
### D) Fallback, wenn eigenes Script sehr früh läuft
166+
167+
```javascript
168+
function onConsentManagerReady(callback) {
169+
document.addEventListener('consent_manager-ready', function (e) {
170+
if (e.detail.initialized) callback();
171+
});
172+
173+
document.addEventListener('DOMContentLoaded', function () {
174+
if (typeof consent_manager_hasconsent === 'function') {
175+
callback();
176+
}
177+
});
178+
}
179+
180+
onConsentManagerReady(function () {
181+
// hier sicher mit consent_manager_hasconsent arbeiten
182+
});
183+
```

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,8 @@ $legalId = $consent->links['legal_notice'] ?? 0;
620620

621621
## 👨‍💻 Für Developer
622622

623+
👉 **Kurzhilfe / Schnellstart für Entwickler:** [DEV_QUICKSTART.md](DEV_QUICKSTART.md)
624+
623625
### JavaScript API
624626

625627
```javascript
@@ -634,6 +636,18 @@ document.addEventListener('consent_manager-saved', function(e) {
634636
// Scripts nachladen, UI aktualisieren etc.
635637
});
636638

639+
// Event wenn Consent Manager initialisiert ist
640+
document.addEventListener('consent_manager-ready', function(e) {
641+
if (!e.detail.initialized) {
642+
console.warn('Consent Manager nicht initialisiert:', e.detail.reason);
643+
return;
644+
}
645+
646+
if (typeof consent_manager_hasconsent === 'function' && consent_manager_hasconsent('google-analytics')) {
647+
// Eigene Scripts sicher ausführen
648+
}
649+
});
650+
637651
// Box öffnen
638652
consent_manager_showBox();
639653

assets/consent_manager_frontend.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ function safeJSONParse(input, fallback) {
5151
var showDelay = parseInt(autoInjectOptions.showDelay, 10) || 0;
5252
var autoFocus = autoInjectOptions.autoFocus !== false; // default true
5353

54+
function emitReady(initialized, reason) {
55+
document.dispatchEvent(new CustomEvent('consent_manager-ready', {
56+
detail: {
57+
initialized: initialized,
58+
reason: reason || null,
59+
noCookieSet: !!consent_manager_parameters.no_cookie_set,
60+
domain: consent_manager_parameters.domain || '',
61+
hasConsentApi: typeof consent_manager_hasconsent === 'function',
62+
hasShowBoxApi: typeof consent_manager_showBox === 'function'
63+
}
64+
}));
65+
}
66+
5467
// Es gibt keinen Datenschutzcookie, Consent zeigen
5568
if (typeof cmCookieAPI.get(cmCookieName) === 'undefined') {
5669
cmCookieAPI.set(cmCookieName + '_test', 'test');
@@ -75,6 +88,7 @@ function safeJSONParse(input, fallback) {
7588

7689
if (consent_manager_box_template === '') {
7790
console.warn('Addon consent_manager: Keine Cookie-Gruppen / Cookies ausgewählt bzw. keine Domain zugewiesen! (' + location.hostname + ')');
91+
emitReady(false, 'missing_template');
7892
return;
7993
}
8094
consent_managerBox = new DOMParser().parseFromString(consent_manager_box_template, 'text/html');
@@ -409,11 +423,15 @@ function safeJSONParse(input, fallback) {
409423
console.warn('Addon consent_manager: Es konnte kein Cookie für die Domain ' + document.domain + ' gesetzt werden!');
410424
} else {
411425
// Async logging to avoid blocking UI (replaced deprecated synchronous XHR)
412-
var url = consent_manager_parameters.fe_controller + '?rex-api-call=consent_manager&buster=' + new Date().getTime();
426+
// Use same-origin current URL to avoid mixed-content/CORS failures when fe_controller differs.
427+
var url = window.location.pathname + window.location.search;
428+
var separator = url.indexOf('?') === -1 ? '?' : '&';
429+
url = url + separator + 'rex-api-call=consent_manager&buster=' + new Date().getTime();
413430
var params = 'domain=' + encodeURIComponent(document.domain) + '&consentid=' + encodeURIComponent(consent_manager_parameters.consentid) + '&buster=' + new Date().getTime();
414431

415432
fetch(url, {
416433
method: 'POST',
434+
credentials: 'same-origin',
417435
headers: {
418436
'Content-Type': 'application/x-www-form-urlencoded',
419437
'Cache-Control': 'no-cache, no-store, max-age=0'
@@ -666,6 +684,8 @@ function safeJSONParse(input, fallback) {
666684
document.dispatchEvent(new CustomEvent('consent_manager-show'));
667685
}
668686

687+
emitReady(true);
688+
669689
})();
670690

671691
function mapConsentsToGoogleFlags(consents) {

assets/consent_manager_frontend.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pages/help.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
'icon' => 'rex-icon fa-book',
99
'file' => 'README.md'
1010
],
11+
'dev_quickstart' => [
12+
'title' => 'Dev Kurzhilfe',
13+
'icon' => 'rex-icon fa-bolt',
14+
'file' => 'DEV_QUICKSTART.md'
15+
],
1116
'inline' => [
1217
'title' => 'Inline Consent',
1318
'icon' => 'rex-icon fa-play-circle',

0 commit comments

Comments
 (0)