Jak działa wtyczka Stats4U dla WordPressa: kod licznika, umiejscowienie, zgoda i żądania

Spis treści
Stats4U to licznik odwiedzin od LW IT Solutions: mały obrazek na stronie, który liczy odsłony, oraz statystyki na stats4u.net z informacją, skąd przyszli odwiedzający, jak długo zostali, jak daleko przewinęli stronę i ilu z nich jest teraz online. Konto nie jest potrzebne, wystarczy numer licznika. Dla WordPressa istnieje osobna wtyczka. Od 29.09.2026 znajduje się w katalogu wtyczek WordPress.org, w wersji 1.6.0, a jej kod źródłowy jest publicznie dostępny na GitHubie.
Ten artykuł pokazuje, jak działa wtyczka: jak odczytuje wklejony kod licznika, jak umieszcza licznik pod stopką dowolnego motywu, jak czeka na narzędzie do zgód i co przeglądarka wysyła potem do stats4u.net. Wszystko zostało ponownie zmierzone 02.10.2026 na lokalnej instalacji testowej z WordPressem 7.1.2, PHP 8.4 i motywem Twenty Twenty-Five, z wtyczką pobraną z katalogu. Na końcu opisana jest droga przez przegląd WordPress.org i zebrane są wszystkie linki.
Od wklejonego kodu do licznika
W menu „Ustawienia → Stats4U” kreator prowadzi przez konfigurację w pięciu krokach: licznik, wygląd, umiejscowienie, zgoda, gotowe. Alternatywą jest konfiguracja własna ze wszystkimi ustawieniami na jednej stronie. W pierwszym kroku trafia tam kod, który generuje kreator na stats4u.net. Są trzy drogi: istniejący kod, przycisk otwierający kreator, który na końcu przenosi kod z powrotem, albo nowy numer licznika na żądanie. Dwie ostatnie działają z przeglądarki administratora, a nie z serwera.
Kreator zna kilka formatów, a wtyczka przyjmuje wszystkie. Tabela pokazuje, co stats4u_code_lesen() zrobiła z dwunastu danych wejściowych:
| Wklejono | Wynik |
|---|---|
| HTML, obrazek z linkiem | numer, wzór, tryb ciemny i rozmiar 150% |
| BBCode | numer, wzór, tryb ciemny |
| Markdown | numer, wzór, język niemiecki |
kod skryptu z s4u.js |
numer, wzór, tryb ciemny, liczenie „unikalnych odwiedzających”, język polski |
| sam adres obrazka | numer i wzór |
stara długa forma ?action=pic&s4uid=… |
numer i wzór |
sam numer, także z # |
numer, wzór bez zmian |
adres strony statystyk /live/<numer> |
numer |
| strona statystyk z własną nazwą | wskazówka: wkleić kod albo numer |
widżet globusa globe.js |
wskazówka: wtyczka pokazuje liczniki obrazkowe |
| dowolny inny tekst | wskazówka: kod nierozpoznany |
Na stronie stoi potem już nie sam obrazek, lecz oficjalny skrypt usługi, ten sam <script src="https://www.stats4u.net/s4u.js" data-id="…" async>, który generuje kreator. Do wersji 1.4.0 wtyczka wstawiała tylko obrazek. Było to lżejsze, ale przy obrazku z obcego serwera przeglądarka wysyła tylko domenę witryny, bez strony i bez informacji, skąd przyszedł odwiedzający. Dopiero skrypt dostarcza te dane, a do tego czas na stronie, głębokość przewinięcia i „teraz online”. O tym, co stoi w miejscu licznika, decyduje jedna funkcja:
// stats4u.php (excerpt)
function stats4u_zaehler_teile($e) {
$daten = stats4u_skript_daten($e);
if (stats4u_cmp($e) === null) {
return array('skript' => array('src' => STATS4U_SKRIPT, 'async' => true) + $daten);
}
stats4u_wartet(true);
return array('platzhalter' => $daten);
}
function stats4u_html() {
$e = stats4u_einstellungen();
if ($e['id'] === '') { return ''; }
$t = stats4u_zaehler_teile($e);
if (isset($t['skript'])) {
return '<span class="stats4u-zaehler">' . trim(wp_get_script_tag($t['skript'])) . '</span>';
}
return '<span class="stats4u-zaehler" data-stats4u="' . esc_attr(wp_json_encode($t['platzhalter'])) . '"></span>';
}
Bez narzędzia do zgód jest to znacznik skryptu zbudowany przez wp_get_script_tag(), która maskuje każdy atrybut. Z narzędziem jest to pusty element zastępczy, który niesie ustawienia licznika jako JSON. Więcej o tym poniżej.
Pod stopką każdego motywu
Domyślnie licznik pojawia się bezpośrednio pod stopką motywu. Brzmi to prosto, ale WordPress nie zna miejsca „za stopką”. Zwykły hook wp_footer znajduje się tuż przed </body>. Do wersji 1.3.0 licznik wisiał właśnie tam, a na stronie, której body jest ułożone jako flexbox, stawał się kolumną obok treści, w połowie wysokości. Od wersji 1.3.1 wtyczka buforuje wyjście od końca wp_head, szuka w buforze stopki i umieszcza licznik za nią. Za stopkę uchodzi element, który sam się nią przedstawia:
// stats4u.php (excerpt)
function stats4u_ist_seitenfuss($name, $tag) {
if (preg_match('/(?<![\w-])role\s*=\s*["\']?contentinfo\b/i', $tag)) { return true; }
if (preg_match('/(?<![\w-])itemtype\s*=\s*["\']?[^"\'>]*WPFooter/i', $tag)) { return true; }
$namen = array('colophon', 'footer', 'site-footer', 'main-footer', 'page-footer', 'global-footer',
'elementor-location-footer');
if ($name === 'footer') { $namen[] = 'wp-block-template-part'; }
foreach (array('id', 'class') as $attr) {
if (preg_match('/(?<![\w-])' . $attr . '\s*=\s*(?:"([^"]*)"|\'([^\']*)\'|([^\s>]+))/i', $tag, $m)) {
$wert = strtolower(($m[1] ?? '') . ($m[2] ?? '') . ($m[3] ?? ''));
if (array_intersect(preg_split('/\s+/', trim($wert)), $namen)) { return true; }
}
}
return false;
}
Spośród kilku kandydatów wygrywa ostatni najbardziej zewnętrzny, żeby przy motywach, które opakowują <footer> w kolejny obszar stopki, licznik stał pod całym paskiem. Bez rozpoznawalnej stopki licznik trafia na koniec strony. Zanim skrypt narysuje obrazek, reguła CSS z :has() ukrywa pusty kontener, żeby margines nie zostawiał luki. Od wersji 1.6.0 tę pracę wykonuje funkcja zwrotna bufora wyjścia; wtyczka nie wypisuje już sama zbuforowanej strony. Ta zmiana wyszła z przeglądu WordPress.org.
Na instalacji testowej licznik przy każdym ustawieniu trafiał w opisane miejsce. „Pod stopką” stawiało go bezpośrednio za </footer>, „w stopce” tuż przed nim, „na końcu strony” przed końcowymi skryptami. „Pod treścią” umieszczało go tylko na pojedynczych stronach, nie na stronie głównej. Narożniki przypinały go na dole po prawej albo po lewej, a „nigdzie automatycznie” go pomijało. Do własnych miejsc służą blok „Stats4U counter” i shortcode , w szablonie jako do_shortcode( '' ). Blok i shortcode na tej samej stronie dały dwa liczniki, blok z własnym wyrównaniem.
Dopiero po zgodzie
Witryna z narzędziem do zgód wybiera je w czwartym kroku. Lista ma 27 pozycji: 25 narzędzi, CookieYes dodatkowo w starym trybie oraz WP Consent API, a do tego każde narzędzie, które blokuje skrypty przez własne atrybuty. W miejscu licznika stoi wtedy pusty span z ustawieniami w data-stats4u. Na końcu strony znajduje się mały skrypt zwalniający, który narzędzie uruchamia dopiero po zgodzie i który wstawia wtedy do każdego elementu zastępczego oficjalny s4u.js. W pomiarze wyglądało to tak:
| Narzędzie | Skrypt zwalniający w HTML |
|---|---|
| Complianz | <script type="text/plain" data-category="statistics"> |
| Cookiebot | <script type="text/plain" data-cookieconsent="statistics"> |
| consented.eu | <script type="text/plain" data-consented="stats4u"> |
| CookieYes | <script data-cookieyes="cookieyes-analytics" src="…/freigabe.js"> |
| WP Consent API | skrypt inline, który pyta wp_has_consent() i nasłuchuje zmian |
W żadnym z tych przypadków s4u.js nie stał bezpośrednio w HTML. Dla narzędzi, które zwalniają tylko skrypty z własnym adresem, takich jak CookieYes, wtyczka dołącza plik freigabe.js. Przy WP Consent API skrypt najpierw sprawdza, czy w ogóle ustawiono typ zgody, bo bez typu wp_has_consent() zwraca true nawet po odmowie. Dla narzędzia spoza listy da się wpisać własne atrybuty. Przechodzą przy tym tylko type, class i data-*:
// stats4u.php (excerpt)
function stats4u_eigene_attribute($roh) {
$aus = array('type' => 'text/plain');
if (preg_match_all('/([a-zA-Z][a-zA-Z0-9_.:-]*)\s*=\s*(?:"([^"]*)"|\'([^\']*)\'|([^\s"\'>]+))/', (string) $roh, $m, PREG_SET_ORDER)) {
foreach ($m as $a) {
$name = strtolower($a[1]);
if (!preg_match('/^(data-[a-z0-9_.:-]+|class|type)$/', $name)) { continue; }
$wert = $a[2] !== '' ? $a[2] : ((isset($a[3]) && $a[3] !== '') ? $a[3] : ($a[4] ?? ''));
$aus[$name] = substr(preg_replace('/[^A-Za-z0-9 _.:\/,#-]/', '', $wert), 0, 80);
}
}
return $aus;
}
Wpisanego onload="alert(1)" zabrakło w wyniku; zostały type="text/plain" i data-category="statistics".

Co przeglądarka wysyła do stats4u.net
Do tego pomiaru posłużył Chrome ze świeżym profilem, który zatrzymywał każde żądanie. Załadować mógł się tylko sam plik skryptu s4u.js. Każde inne żądanie do stats4u.net zostało zapisane, a potem przerwane, więc do usługi nie dotarło żadne testowe zliczenie. Strona była otwarta przez 70 sekund, potem przeglądarka przeszła dalej.
| Moment | Żądanie | Treść |
|---|---|---|
| przy ładowaniu | s4u.js |
13 237 bajtów przesłanych, Brotli, godzina w pamięci podręcznej, bez Set-Cookie |
| przy ładowaniu | action=cfg, GET |
tylko numer licznika: ustawienia licznika |
| przy ładowaniu | action=pic, obrazek |
numer licznika, wzór, tryb ciemny, język, adres strony, adres odsyłający i liczba losowa przeciw pamięci podręcznej; to żądanie liczy |
| po 60 s | action=ping, POST |
tylko numer licznika, dla „teraz online” |
| przy opuszczaniu | action=puls, beacon |
numer licznika, adres strony, widoczne sekundy, głębokość przewinięcia i czas ładowania |
Po załadowaniu w przeglądarce nie było żadnych ciasteczek ani niczego w pamięci lokalnej. Skrypt zamienił licznik w link do strony statystyk, https://www.stats4u.net/live/<numer>. Ten link ustawia usługa, a nie wtyczka; licznik oznaczony na stats4u.net jako niepubliczny prowadzi do strony głównej usługi. Sam serwer WordPressa nigdy nie łączy się ze stats4u.net: w kodzie wtyczki nie ma ani jednego wywołania HTTP. Podgląd na stronie ustawień i w edytorze ma parametr rl=1 i nie jest liczony.
Wielojęzycznie i bez pełnego przeładowania
Gdy język licznika ustawiono na „język każdej strony”, wtyczka pobiera go z ustawień regionalnych każdego żądania. Z Polylang licznik miał data-lang="en" na angielskiej stronie głównej, de na niemieckiej i pl na polskiej. Motywy, które zmieniają strony bez pełnego przeładowania, bez pomocy liczą tylko pierwszą stronę. Dla nich istnieje zdarzenie s4u:seiteweg, które zamyka czas spędzony na starej stronie, oraz, po zgodzie, funkcja window.stats4uAn(), która wypełnia nowe elementy zastępcze. Ta witryna korzysta właśnie z tej drogi: działa ze Stats4U 1.6.0 i consented.eu, a jej zmiana stron bez przeładowania wywołuje s4u:seiteweg przed każdą podmianą.
Przez przegląd WordPress.org
Pierwsze zgłoszenie zostało wstrzymane 26.09.2026. Zespół przeglądu zażądał maskowania każdej wartości dopiero przy wypisywaniu, także HTML zwracanego przez funkcję, i usunięcia plików tłumaczeń z paczki. Wersja 1.6.0 spełnia oba wymagania. Każde wyjście przechodzi przez esc_html(), esc_attr(), esc_url(), wp_kses() albo wp_print_script_tag(), a licznik pod stopką umieszcza funkcja zwrotna bufora wyjścia. 18 tłumaczeń, które do wersji 1.5.0 były w paczce, leży teraz w repozytorium GitHub jako wzór; tłumaczenie odbywa się na translate.wordpress.org, a WordPress sam ładuje pakiety językowe. 29.09.2026 zespół przeglądu zatwierdził Stats4U.
Przy usuwaniu wtyczka kasuje własną opcję i zapamiętany widok strony ustawień. Pomiar: opcja o rozmiarze 236 bajtów i widok istniały przed usunięciem, potem zniknęły obie. Licznik na stats4u.net i jego statystyki pozostają.
Wszystkie linki
- Stats4U w katalogu wtyczek WordPress.org
- Kod źródłowy na GitHubie, z README i wzorami tłumaczeń
- Tłumaczenie na translate.wordpress.org
- stats4u.net, z kreatorem nowych liczników
- Akapit do polityki prywatności witryny, dla każdego numeru licznika i w 19 językach
- Warunki korzystania i polityka prywatności Stats4U
Pytania i odpowiedzi
Czy Stats4U ustawia ciasteczko?
Nie. W pomiarze ze świeżym profilem przeglądarki po załadowaniu nie było w przeglądarce żadnego ciasteczka ani niczego w pamięci lokalnej, a odpowiedź z s4u.js nie zawierała Set-Cookie. Jak przy każdym żądaniu do innego serwera, do stats4u.net trafiają adres IP i user agent przeglądarki. Gotowy akapit do polityki prywatności jest dostępny pod adresem stats4u.net/privacy-embed.
Co się dzieje, gdy stats4u.net jest niedostępne?
Wtedy na stronie brakuje licznika i nic więcej. Skrypt ładuje się asynchronicznie i nie wstrzymuje strony. Dopóki nie narysuje obrazka, reguła CSS ukrywa pusty kontener, więc nie zostaje żadna luka.
Czy wizyty w podglądzie albo w edytorze są liczone?
Nie. Podgląd na stronie ustawień i w edytorze bloków ładuje tylko obrazek licznika z parametrem rl=1, który oznacza „tylko wyświetl”. Do wersji 1.1.0 każde otwarcie strony ustawień liczyło się jako wizyta; zostało to poprawione.
Czy usunięcie wtyczki usuwa też licznik?
Nie. Przy usuwaniu wtyczka kasuje własną opcję i zapamiętany widok strony ustawień, nic więcej. Licznik na stats4u.net należy do właściciela witryny i zachowuje statystyki.
Źródła
- Stats4U 1.6.0 w katalogu wtyczek, dostęp 02.10.2026
- Stats4U-Wordpress, kod źródłowy na GitHubie, dostęp 02.10.2026
- WordPress.org: Detailed Plugin Guidelines, dostęp 02.10.2026
- WP Consent API, dostęp 02.10.2026
- wp_get_script_tag(), dostęp 02.10.2026
- wp_print_inline_script_tag(), dostęp 02.10.2026
- PHP: ob_start(), dostęp 02.10.2026
- MDN: Navigator.sendBeacon(), dostęp 02.10.2026
- MDN: :has(), dostęp 02.10.2026
- Stats4U: akapit do polityki prywatności, dostęp 02.10.2026