Phase 1 complete: - fbq noop na wp_head priority 1 — blokuje Facebook Pixel ze wszystkich źródeł (HFCM, PYS, woo-product-feed-pro) gdy brak zgody marketingowej - Early gtag consent update PHP-side dla powracających użytkowników — eliminuje race condition z GTM - Granularne filtry pys_disable_*_by_gdpr — PixelYourSite honoruje kategorie marketing/analytics - Fix: wp_unslash() przy odczycie $_COOKIE (WP wp_magic_quotes addslashes) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
12 KiB
12 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, delegation
| phase | plan | type | wave | depends_on | files_modified | autonomous | delegation | |
|---|---|---|---|---|---|---|---|---|
| 01-rodo-cookie-consent | 01 | execute | 1 |
|
false | off |
Purpose
Audyt kodu wykazał:
cookies.php(Diviheader.phplinia 4, przedwp_head()) już ustawia Consent Mode v2 defaults (all denied) — AC-4 jest spełnione ✅googleConsentModeHandler()w JS aktualizuje consent powindow.load— działa dla nowych użytkowników ✅- Problem 1: dla powracających użytkowników (mają cookie
cnp_consent=true) GTM czeka maks. 500ms (wait_for_update), a consent update przychodzi z JS po załadowaniu strony — ryzyko race condition na wolnych połączeniach ⚠️ - Problem 2: PixelYourSite ładuje Facebook Pixel server-side (PHP), niezależnie od cookies zgody — nie honoruje
cnp_consent❌
Cookies ustawiane przez Cookie Notice Pro (Flerosoft jQuery plugin w Divi/libs/CookieNoticePro/):
cnp_consent="true"(akceptacja) lub"false"(odmowa)cnp_prefs= JSON URL-encoded, np.["necessary","marketing","analytics"]
Output
wp-content/themes/body-relax/functions.php — dodane dwie funkcje:
- Early consent update (wp_head priority 1) — PHP odczytuje
cnp_consent/cnp_prefs, wywołujegtag('consent', 'update', ...)przed snippetem GTM — eliminuje race condition - PixelYourSite GDPR filter — granularnie blokuje pixele na podstawie kategorii zgody
Source Files
@wp-content/themes/body-relax/functions.php @wp-content/themes/Divi/libs/CookieNoticePro/cookies.php @wp-content/themes/Divi/libs/CookieNoticePro/cookienoticepro.script.js @wp-content/themes/Divi/header.php @wp-content/plugins/pixelyoursite/includes/class-events-manager.php @wp-content/plugins/pixelyoursite/includes/functions-gdpr.php
<acceptance_criteria>
AC-1: Powracający użytkownik — brak race condition w Consent Mode
Given użytkownik ma cookie cnp_consent="true" i cnp_prefs zawierający "marketing","analytics"
When strona się ładuje
Then w <head> PRZED snippetem GTM pojawia się gtag('consent', 'update', {all: 'granted'})
And GTM tagi śledzące mogą się uruchomić od razu (nie czekają na JS po window.load)
AC-2: Granularna blokada PixelYourSite
Given brak cookie cnp_consent lub cnp_consent="false"
When PHP renderuje stronę
Then PixelYourSite nie wstrzykuje kodu Facebook Pixel (fbq) na stronie
AC-3: Kategorie zgody honorowane przez PixelYourSite
Given cnp_consent="true" ale cnp_prefs NIE zawiera "marketing"
When PHP renderuje stronę
Then Facebook Pixel jest zablokowany (brak kategorii marketing)
And jeśli cnp_prefs zawiera "analytics" — pixele analityczne działają
AC-4: Consent Mode v2 defaults — już działa, nie psuć
Given cookies.php jest includowany w header.php linia 4 (przed wp_head)
When strona się ładuje
Then gtag('consent', 'default', {all: 'denied'}) jest ustawione przed GTM — NIE ZMIENIAJ tego mechanizmu
</acceptance_criteria>
Task 1: Early consent update dla powracających użytkowników wp-content/themes/body-relax/functions.php Dodaj na końcu pliku funkcję hookowaną do `wp_head` z priorytetem 1.Cel: gdy użytkownik ma już cookie `cnp_consent=true`, PHP odczytuje je server-side
i wstrzykuje `gtag('consent', 'update', ...)` PRZED snippetem GTM (GTM enqueuje się
przez wp_head, który odpala hooki w kolejności priorytetów — nasz priority 1 jest pierwszy).
Dla nowych użytkowników (brak cookie) — funkcja nic nie robi, defaults z cookies.php wystarczą.
```php
add_action( 'wp_head', 'szkolenia_consent_early_update', 1 );
function szkolenia_consent_early_update() {
$consent = isset( $_COOKIE['cnp_consent'] ) ? $_COOKIE['cnp_consent'] : '';
if ( $consent !== 'true' ) {
return; // Nowy użytkownik lub odmowa — defaults z cookies.php wystarczą
}
$prefs = [];
if ( isset( $_COOKIE['cnp_prefs'] ) ) {
$decoded = json_decode( urldecode( $_COOKIE['cnp_prefs'] ), true );
if ( is_array( $decoded ) ) {
$prefs = $decoded;
}
}
$analytics = in_array( 'analytics', $prefs ) ? 'granted' : 'denied';
$marketing = in_array( 'marketing', $prefs ) ? 'granted' : 'denied';
?>
<script>
// Early consent update — powracający użytkownik (server-side cookie check)
window.dataLayer = window.dataLayer || [];
if (typeof gtag !== 'function') { function gtag(){dataLayer.push(arguments);} }
gtag('consent', 'update', {
'analytics_storage': '<?php echo esc_js( $analytics ); ?>',
'ad_storage': '<?php echo esc_js( $marketing ); ?>',
'ad_user_data': '<?php echo esc_js( $marketing ); ?>',
'ad_personalization': '<?php echo esc_js( $marketing ); ?>'
});
</script>
<?php
}
```
UWAGA: `cookies.php` (z Divi) już definiuje `dataLayer` i `gtag` — `if (typeof gtag !== 'function')` jest zabezpieczeniem na wypadek gdyby kolejność kiedyś się zmieniła. Nie usuwaj.
UWAGA: Nie modyfikuj `cookies.php` ani żadnego pliku w `wp-content/themes/Divi/` ani `wp-content/plugins/`.
UWAGA: Dodaj na końcu pliku, za istniejącym kodem.
1. `php -l wp-content/themes/body-relax/functions.php` — brak błędów
2. W przeglądarce z cookie `cnp_consent=true` (ustaw ręcznie w DevTools): DevTools → Elements → `<head>` — szukaj `gtag('consent', 'update'` — powinno być PRZED skryptem GTM
3. W przeglądarce bez cookie: brak `gtag('consent', 'update'` w źródle — tylko `gtag('consent', 'default'` z cookies.php
AC-1 spełnione: early consent update dla powracających użytkowników
Task 2: PixelYourSite GDPR filter z granularnymi kategoriami
wp-content/themes/body-relax/functions.php
Dodaj po Task 1 granularne filtry WordPress dla PixelYourSite.
PixelYourSite używa filtrów:
- `pys_disable_by_gdpr` — blokuje WSZYSTKIE pixele (zwróć true = zablokuj)
- `pys_disable_facebook_by_gdpr` — tylko Facebook Pixel
- `pys_disable_analytics_by_gdpr` — tylko Google Analytics
- `pys_disable_bing_by_gdpr` — tylko Microsoft/Bing Ads
Mapowanie kategorii Cookie Notice Pro → typy pikseli:
- "marketing" → Facebook Pixel, Bing Ads
- "analytics" → Google Analytics
```php
add_filter( 'pys_disable_facebook_by_gdpr', 'szkolenia_pys_marketing_consent' );
add_filter( 'pys_disable_bing_by_gdpr', 'szkolenia_pys_marketing_consent' );
function szkolenia_pys_marketing_consent( $disabled ) {
if ( $disabled ) return true;
return ! szkolenia_cnp_has_preference( 'marketing' );
}
add_filter( 'pys_disable_analytics_by_gdpr', 'szkolenia_pys_analytics_consent' );
add_filter( 'pys_disable_google_ads_by_gdpr', 'szkolenia_pys_marketing_consent' );
function szkolenia_pys_analytics_consent( $disabled ) {
if ( $disabled ) return true;
return ! szkolenia_cnp_has_preference( 'analytics' );
}
function szkolenia_cnp_has_preference( $type ) {
if ( ! isset( $_COOKIE['cnp_consent'] ) || $_COOKIE['cnp_consent'] !== 'true' ) {
return false;
}
if ( ! isset( $_COOKIE['cnp_prefs'] ) ) {
return false;
}
$prefs = json_decode( urldecode( $_COOKIE['cnp_prefs'] ), true );
return is_array( $prefs ) && in_array( $type, $prefs, true );
}
```
UWAGA: Filtry `pys_disable_*_by_gdpr` zwracają `true` = zablokuj, `false` = pozwól.
UWAGA: `szkolenia_cnp_has_preference` jest funkcją pomocniczą — zdefiniuj ją tylko raz.
UWAGA: Nie dodawaj `pys_disable_by_gdpr` (globalnego) — granularne filtry są bardziej precyzyjne i nie zablokują Pinterest jeśli będzie potrzebny.
1. `php -l wp-content/themes/body-relax/functions.php` — brak błędów
2. Tryb incognito (brak cookies): DevTools → Elements → Ctrl+F szukaj `fbq(` — NIE powinno być w źródle
3. Z cookie `cnp_consent=true` i `cnp_prefs=["necessary","marketing","analytics"]` (URL-encoded, ustaw w DevTools): `fbq(` powinno być widoczne w źródle
4. Z cookie `cnp_consent=true` i `cnp_prefs=["necessary","analytics"]` (bez marketing): `fbq(` NIE powinno być (marketing zablokowany)
AC-2 i AC-3 spełnione: PixelYourSite honoruje kategorię "marketing" i "analytics"
Dwie funkcje w `wp-content/themes/body-relax/functions.php`:
1. `szkolenia_consent_early_update()` — PHP early gtag update dla powracających użytkowników
2. `szkolenia_pys_*_consent` filtry — granularna blokada PixelYourSite
**Test A — Nowy użytkownik (brak zgody):**
1. Otwórz stronę w trybie incognito
2. DevTools → Network: BRAK requestów do `facebook.com/tr`
3. DevTools → Elements → `<head>`: widoczny `gtag('consent', 'default', {...denied...})` z cookies.php, brak `gtag('consent', 'update', ...)`
4. DevTools → Elements: brak `fbq(` w kodzie strony
**Test B — Powracający użytkownik (pełna zgoda):**
1. DevTools → Application → Cookies → dodaj:
- `cnp_consent` = `true`
- `cnp_prefs` = `%5B%22necessary%22%2C%22preferences%22%2C%22marketing%22%2C%22analytics%22%5D`
2. Odśwież stronę (NIE incognito)
3. DevTools → Elements → `<head>`: widoczny `gtag('consent', 'update', {all: 'granted'})` PRZED snippetem GTM
4. DevTools → Elements: widoczny `fbq(` w kodzie strony
**Test C — Użytkownik zaakceptował tylko analitykę (bez marketingu):**
1. Ustaw cookies: `cnp_consent=true`, `cnp_prefs=%5B%22necessary%22%2C%22analytics%22%5D`
2. Odśwież
3. DevTools → Elements: BRAK `fbq(` (Facebook zablokowany bo brak "marketing")
4. `gtag('consent', 'update', {...})`: `analytics_storage: 'granted'`, `ad_storage: 'denied'`
**Test D — Kliknięcie "Akceptuj" w banerze:**
1. Wyczyść cookies, odśwież stronę incognito — baner powinien się pojawić
2. Kliknij "Akceptuj"
3. Odśwież stronę — cookie `cnp_consent=true` powinno być ustawione
4. Network tab: widoczne requesty Facebook Pixel
Wpisz "approved" jeśli wszystkie testy przeszły, lub opisz co nie działa
DO NOT CHANGE
- wp-content/themes/Divi/* (w tym
libs/CookieNoticePro/cookies.php,header.php) — Consent Mode v2 defaults już działają - wp-content/plugins/* (żadne pliki wtyczek)
- wp-content/themes/body-relax/style.css
- wp-content/themes/body-relax/divi-children-engine/*
SCOPE LIMITS
- Ten plan NIE konfiguruje GTM kontenera (tagi/triggery consent-aware) — osobna praca w GTM UI
- Ten plan NIE zmienia konfiguracji Cookie Notice Pro (config w cookienoticepro.script.js)
- Nie obsługuj Pinterest (
pys_disable_pinterest_by_gdpr) — brak przesłanek że jest używany - Nie dodawaj error handling dla scenariuszy niemożliwych
<success_criteria>
- Wszystkie 3 AC spełnione (AC-4 był już OK przed planem)
- Weryfikacja manualna przeszła (checkpoint approved)
- Brak błędów PHP
- Strona renderuje się normalnie, baner cookies działa </success_criteria>