Dlaczego licznik odpowiadał HTTP 200, a mimo to nie ufałem wynikowi
Ten problem zaczął się jak typowa historia o „cache”. Post Views Counter działał w trybie REST API, endpoint odpowiadał, a mimo to przy testach na aktualnym wpisie licznik nie zachowywał się wiarygodnie. Dopiero rozdzielenie kilku warstw — page cache, minifikacji JavaScriptu, kontekstu bieżącego wpisu i zgody statystycznej — pokazało, co naprawdę się dzieje.
Opisuję dokładnie przypadek z bybrzoza.com z 2 września 2026. To nie jest twierdzenie, że WP-Optimize zawsze psuje Post Views Counter albo że każda strona powinna klasyfikować taki licznik identycznie. To wynik testów konkretnej instalacji, który warto potraktować jako metodę diagnostyczną.
Środowisko, na którym problem został odtworzony
| Komponent | Wersja w czasie testu |
|---|---|
| WordPress | 7.1 |
| PHP | 8.5.7 |
| Post Views Counter | 1.7.15 |
| WP-Optimize | 4.6.1 |
| Complianz | 7.5.4 |
| Polylang | 3.8.7 |
Przed kopiowaniem ustawień sprawdź swoje wersje i faktyczną ścieżkę assetu PVC. W tym przypadku używany był post-views-counter/js/frontend.js.
1. Najpierw ustaliłem, kto naprawdę zarządza page cache
Audyt ujawnił realny problem konfiguracyjny: jednocześnie aktywne były Page Cache w WP-Optimize oraz Cache Enabler. WP-Optimize sam ostrzegał o drugim cache pluginie. Wyłączyłem Cache Enabler, zostawiłem WP-Optimize jako jedynego właściciela page cache, wykonałem purge i sprawdziłem anonimowy frontend.
To było potrzebne, żeby usunąć szum z diagnostyki. Nie jest jednak dowodem, że podwójny page cache powodował późniejszy błąd kontekstu Post Views Counter. Page Cache i Minify to dwie różne funkcje.

2. REST API 200 nie wystarcza: trzeba sprawdzić, jaki wpis jest liczony
Post Views Counter ma kilka trybów zliczania. W finalnej konfiguracji użyłem REST API. Podczas debugowania popełniłem też banalny, ale ważny błąd: jeden z testów zrobiłem na zwykłej Page, podczas gdy licznik był skonfigurowany do właściwego scope’u Posts. Taki test niczego nie rozstrzyga.
Na prawdziwym opublikowanym poście endpoint potrafił odpowiadać HTTP 200, ale to nadal nie było wystarczającym dowodem. Sprawdzałem w DevTools, jaki postID znajduje się w konfiguracji pvcArgsFrontend, jaki URL wywołuje request i który plik JavaScript jest initiatorem.
Gdy frontend.js był przetwarzany we wspólnym bundle WP-Optimize, request mógł mieć nieaktualny lub niewłaściwy kontekst wpisu. Sam kod 200 wyglądał więc „zdrowo”, podczas gdy licznik nie odpowiadał temu, czego oczekiwałem na bieżącej stronie.
3. Zamiast wyłączać Minify, wykluczyłem tylko asset PVC
WP-Optimize miał włączoną minifikację i łączenie JavaScriptu. Zamiast wyłączać całą optymalizację, dodałem konkretny asset Post Views Counter w:
WP-Optimize → Minify → JavaScript → Exclude JavaScript from processingW mojej wersji wystarczyło wykluczenie ścieżki zawierającej:
post-views-counter/js/frontend.jsOficjalna dokumentacja WP-Optimize nadal opisuje to pole jako wyłączenie wskazanego skryptu zarówno z minifikacji, jak i z merging. Po zapisaniu ustawienia zresetowałem pliki Minify/cache i wykonałem świeży test anonimowy.

Po tej zmianie frontend.js ładował się osobno. W DevTools widziałem request inicjowany przez właściwy skrypt, z poprawnym ID aktualnego wpisu. Widoczny licznik i licznik backendowy zaczęły rosnąć zgodnie z oczekiwaniem.

4. Dopiero działający licznik podpiąłem pod zgodę Statistics
Na tej instalacji PVC potraktowałem jako mechanizm statystyczny. To decyzja konfiguracyjna wynikająca z mojego sposobu użycia; nie jest to uniwersalna porada prawna.
W Complianz → Integrations → Script Center dodałem regułę blokującą frontend PVC przed zgodą:
- Name: Post Views Counter
- Action: Block a script, iframe or plugin
- URL/script:
post-views-counter/js/frontend.js - Category: Statistics
Oficjalna dokumentacja Complianz zaleca przy takich regułach użycie możliwie charakterystycznego identyfikatora/URL. Zbyt szeroki wzorzec może zablokować także inne skrypty.

5. Test zgody: przed wyborem, Deny i Accept
Najważniejszy test zrobiłem w świeżej prywatnej sesji na realnym opublikowanym wpisie. Nie opierałem się na samym stanie backendu Complianz.
| Stan | Request PVC | pvc_visits[0] | Licznik |
|---|---|---|---|
| Przed wyborem | brak | brak | brak inkrementu PVC |
| Deny | brak | brak | brak inkrementu PVC |
| Accept | jest | jest | inkrement potwierdzony |


pvc_visits[0]; jego wartość na zrzucie została trwale zredagowana.6. Ręczna dokumentacja usługi i cookie w Complianz
Sam Script Center steruje uruchomieniem skryptu, ale chciałem też, aby Cookie Policy opisywała to, co faktycznie widziałem w runtime. Utworzyłem więc własną usługę i własny wpis cookie.
| Pole | Wartość |
|---|---|
| Service | Post Views Counter |
| Service type | website statistics |
| Data shared | No |
| Cookie | pvc_visits[0] |
| Expiration | 1 day |
| Purpose | Statistics |
| CookieDatabase sync | Off — custom entry |
Polski opis funkcji ustawiłem jako: „Przechowuje informacje o odwiedzonych wpisach i sesji, aby zapobiec wielokrotnemu zliczaniu odsłon.” Analogiczne opisy utrzymałem ręcznie po niemiecku i angielsku.
7. Drugi problem: customowe „Usage” nadal było po angielsku
Tu łatwo pomylić dwie różne usterki. Wcześniej opisałem osobny problem, w którym zsynchronizowany dokument Complianz był budowany za wcześnie względem trybu Polylang „The language is set from content”. Ten artykuł jest dostępny osobno: Complianz + Polylang: Cookie Policy po angielsku – fix.
W obecnym przypadku główny dokument był już poprawny. Nie lokalizowało się tylko zdanie generowane dla własnej usługi PVC:
- PL:
Używamy Post Views Counter dla website statistics. - DE:
Wir verwenden Post Views Counter für website statistics.
Ręczne Service Type i Polylang String Translations nie zmieniły tego fragmentu. To był osobny, bardzo wąski przypadek.

8. Wąski workaround przez cmplz_document_html
Nie edytowałem plików Complianz. Istniejący MU-plugin 0.1.0 został rozszerzony do 0.2.0 o osobny filtr finalnego HTML dokumentu. Kod działa tylko na zsynchronizowanym EU Cookie Policy, tylko dla PL/DE, tylko w oknie Complianz >=7.5.4 i <8.0.0, a angielskiej wersji nie dotyka.
Najważniejsza część dodatkowego fixu wygląda tak:
function bybrzoza_cmplz_localize_pvc_usage( string $html, string $type, int $post_id ): string {
if ( $html === '' || is_admin() || wp_doing_ajax() || wp_doing_cron() ||
( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
return $html;
}
if ( ! function_exists( 'pll_current_language' ) || ! class_exists( 'COMPLIANZ' ) ) {
return $html;
}
if ( ! defined( 'CMPLZ_VERSION' ) || ! isset( COMPLIANZ::$document ) ||
! method_exists( COMPLIANZ::$document, 'get_document_data' ) ) {
return $html;
}
$cmplz_version = strtok( (string) CMPLZ_VERSION, '#' );
if ( version_compare( $cmplz_version, '7.5.4', '<' ) ||
version_compare( $cmplz_version, '8.0.0', '>=' ) ) {
return $html;
}
$pll_locale = pll_current_language( 'locale' );
$wp_locale = get_locale();
if ( ! is_string( $pll_locale ) || $pll_locale === '' || $pll_locale !== $wp_locale ) {
return $html;
}
if ( ! in_array( $wp_locale, array( 'pl_PL', 'de_DE' ), true ) ) {
return $html;
}
$document_data = COMPLIANZ::$document->get_document_data( $post_id );
if ( ! is_array( $document_data ) || ( $document_data['type'] ?? '' ) !== 'cookie-statement' ) {
return $html;
}
$region = $document_data['region'] ?? false;
if ( ! $region && function_exists( 'cmplz_get_region_from_legacy_type' ) ) {
$region = cmplz_get_region_from_legacy_type( 'cookie-statement' );
}
if ( $region !== 'eu' ) {
return $html;
}
$replacements = array(
'de_DE' => array(
'old' => 'Wir verwenden Post Views Counter für website statistics',
'new' => 'Wir verwenden Post Views Counter für Website-Statistiken',
),
'pl_PL' => array(
'old' => 'Używamy Post Views Counter dla website statistics',
'new' => 'Używamy Post Views Counter dla statystyk witryny',
),
);
$replacement = $replacements[ $wp_locale ] ?? null;
if ( ! is_array( $replacement ) ) {
return $html;
}
return str_replace( $replacement['old'], $replacement['new'], $html );
}
add_filter( 'cmplz_document_html', 'bybrzoza_cmplz_localize_pvc_usage', 20, 3 );To celowo nie jest „tłumacz wszystko przez str_replace”. Replacement jest dokładny i związany tylko z nazwą Post Views Counter. Jeśli przyszła wersja Complianz zacznie generować poprawne zdanie, stary fragment nie wystąpi i ten kawałek kodu stanie się no-op. Przy Complianz 8.x fix również automatycznie się wyłącza i wymaga nowego audytu.
9. Finalny wynik PL / DE / EN
Po wdrożeniu 0.2.0 i purge sprawdziłem publiczny dokument we wszystkich trzech językach. Wynik:
- PL: „Używamy Post Views Counter dla statystyk witryny.” + „1 dzień” + polski opis funkcji;
- DE: „Wir verwenden Post Views Counter für Website-Statistiken.” + „1 Tag” + niemiecki opis funkcji;
- EN: „We use Post Views Counter for website statistics.” + „1 day” + angielski opis funkcji.

Co było fałszywym tropem
- Website Scan na 50%. Raz doszedł do 100% i wykrył 18 cookies, później znów stanął na 50%. Nie był udowodnioną przyczyną problemu PVC i nie użyłem go jako completion gate.
- Test na Page. Przy scope ustawionym na Posts taki test prowadzi w złą stronę.
- HTTP 200. Sukces transportu nie oznacza jeszcze, że liczony jest właściwy wpis.
- Sam purge. Czyszczenie cache bez sprawdzenia initiatora i
postIDnie pokazuje, czy problem zniknął. - Polylang String Translations. Pomagają w wielu miejscach, ale w tym konkretnym customowym zdaniu Usage nie zmieniły outputu.
Rollback i test po aktualizacjach
Ta konfiguracja ma dwa niezależne punkty rollbacku. Jeśli exclusion PVC w WP-Optimize spowoduje nieoczekiwany efekt, usuń wpis z listy exclusion, zapisz ustawienia i zresetuj pliki Minify/cache. Jeśli problem dotyczy MU-pluginu, rollback to przywrócenie poprzedniej wersji pliku 0.1.0 albo usunięcie dodatkowej funkcji 0.2.0, a następnie purge i ponowny test dokumentu.
Po aktualizacji PVC sprawdź ponownie rzeczywistą ścieżkę frontend.js. Po aktualizacji WP-Optimize sprawdź, czy exclusion nadal jest respektowane. Po aktualizacji Complianz lub Polylang wykonaj krótki test PL → DE → EN; przy Complianz 8.x nie omijaj guardraila wersji bez świeżego source audytu.
Wnioski
Najwięcej czasu oszczędziło mi rozdzielenie warstw. Najpierw jeden właściciel page cache. Potem właściwy Post i właściwy request. Następnie pojedynczy asset wykluczony z Minify zamiast wyłączania całej optymalizacji. Dopiero na stabilnym liczniku warto budować consent i dokumentację cookie. Dzięki temu każdy krok ma własny test i własny rollback.
Źródła i dalsze czytanie
- Post Views Counter — WordPress.org
- WP-Optimize — excluding individual JavaScript from Minify
- Complianz — Script Center / integrations
- Complianz — hooks and filters
- Polylang — String translations
Pomogła Ci ta instrukcja?
Jeśli zaoszczędziła Ci trochę czasu albo nerwów, możesz postawić mi kawę.

