JavaScript pozwala budować szybkie, interaktywne aplikacje, konfiguratory, koszyki i rozbudowane serwisy. Problem zaczyna się wtedy, gdy kluczowa treść, linki albo metadane pojawiają się dopiero po wykonaniu skryptu, a Google nie może ich poprawnie pobrać, wyrenderować lub zinterpretować.
W przeglądarce wszystko może wyglądać idealnie. Użytkownik widzi nagłówki, produkty, menu i formularz. Googlebot może jednak otrzymać na początku tylko pusty kontener aplikacji, a właściwa zawartość ma zostać dopiero pobrana z API.
To nie oznacza, że każda strona JavaScript jest zła dla SEO. Google Search uruchamia JavaScript w nowoczesnej wersji Chromium, ale przetwarzanie odbywa się w etapach: crawl, renderowanie i indeksowanie. Każdy problem po drodze może sprawić, że część strony nie trafi do indeksu albo zostanie zinterpretowana słabiej.
Google może widzieć Twoją stronę w przeglądarce inaczej niż użytkownik. W JavaScript SEO trzeba sprawdzać nie tylko "czy działa", ale także "co znajduje się w HTML po renderowaniu i czy da się to zaindeksować".
Ten poradnik pokazuje, jak wykrywać problemy JavaScript SEO, jak je naprawiać i jak wykorzystać techniczną przewagę do outrankowania pięciu stron konkurencji.
JavaScript a SEO - gdzie pojawia się problem?
JavaScript może wpływać na SEO w kilku miejscach jednocześnie:
- treść jest nieobecna w początkowym HTML,
- Google nie może pobrać pliku JS lub danych z API,
- renderowanie kończy się błędem,
- linki nie są prawdziwymi elementami
<a href>, - routing zmienia widok bez poprawnego URL-a,
- meta tagi aktualizują się za późno albo niepoprawnie,
- aplikacja blokuje crawl przez robots.txt lub nagłówki,
- lazy loading nie uruchamia się w sposób przyjazny dla wyszukiwarki,
- schema powstaje z niepełnych lub niespójnych danych.
Najczęstszy błąd polega na założeniu, że skoro Google potrafi uruchomić JavaScript, to zawsze zobaczy wszystko. Google dokumentuje, że strony są najpierw crawlowane, potem trafiają do kolejki renderowania, a dopiero wyrenderowany HTML jest ponownie analizowany i indeksowany. To oznacza, że treść dostępna dopiero po skrypcie ma więcej punktów, w których może zostać utracona.
Jak Google przetwarza stronę JavaScript?
| Etap | Co robi Google? | Typowe ryzyko |
|---|---|---|
| Crawling | Pobiera URL i początkową odpowiedź serwera | Blokada robots, błędny status, brak linków |
| Renderowanie | Uruchamia JavaScript w środowisku renderującym | Błąd JS, niedostępne API, timeout, brak zasobów |
| Odczyt DOM | Analizuje HTML po wykonaniu skryptów | Treść lub linki nie pojawiają się w DOM |
| Indeksowanie | Decyduje, co zapisać i jak zrozumieć stronę | Brak głównego tematu, duplikacja, noindex |
| Ranking | Porównuje stronę z innymi wynikami | Słabsza treść, UX, linki albo intencja |
Ważne: strona może przejść pierwszy etap, ale nie przejść renderowania. Może też zostać wyrenderowana, lecz nie mieć crawlable links do kolejnych URL-i. Dlatego diagnoza powinna obejmować cały łańcuch, a nie tylko źródło HTML.
HTML początkowy a HTML wyrenderowany
HTML początkowy to odpowiedź, którą otrzymuje przeglądarka przed wykonaniem JavaScriptu. HTML wyrenderowany to DOM po uruchomieniu skryptów i pobraniu danych. Oba widoki mogą się znacząco różnić.
| Element | HTML początkowy | HTML po renderowaniu |
|---|---|---|
| H1 i tekst | Pusty placeholder | Nagłówek i opis z API |
| Produkty | Brak listy | Lista generowana komponentem |
| Linki | Przyciski z onclick | Linki dopiero po interakcji |
| Title | Jeden ogólny title | Title zmieniany przez router |
| Schema | Brak JSON-LD | JSON-LD wstrzyknięty skryptem |
Nie ma wymogu, aby cały tekst zawsze znajdował się w początkowym HTML. Najważniejsze elementy SEO i biznesowe powinny jednak być dostępne niezawodnie. Dla stron o dużej wartości organicznej bezpiecznym kierunkiem jest SSR, statyczne generowanie albo prerendering z poprawną hydratacją.
Najczęstsze elementy niewidoczne dla Google
Problemy często dotyczą elementów, które właściciel strony uznaje za oczywiste, bo widzi je po załadowaniu aplikacji.
- opisy kategorii i produktów,
- FAQ schowane w komponencie accordion,
- tekst alternatywny obrazów generowany dopiero po pobraniu danych,
- linki do kategorii i paginacji,
- ceny, dostępność i warianty produktów,
- lokalne dane firmy, godziny i adresy,
- title, description, canonical i hreflang,
- breadcrumbs i dane strukturalne,
- treść wpisywana dopiero po kliknięciu "ładuj więcej".
Największe ryzyko występuje na stronach, których początkowy HTML zawiera tylko <div id="root"> albo <div id="app">. Taki app shell może działać świetnie dla użytkownika, ale utrudniać szybkie odkrycie tematu, linków i struktury strony.
CSR, SSR, SSG i hydration - co wybrać?
| Model | Jak działa? | SEO i UX |
|---|---|---|
| CSR | Przeglądarka buduje większość widoku po JS | Duża elastyczność, większe ryzyko renderowania i opóźnień |
| SSR | Serwer wysyła gotowy HTML dla żądanej strony | Dobry start dla crawlowania i użytkownika |
| SSG | HTML jest generowany wcześniej, zwykle podczas buildu | Szybkość i stabilność dla treści, które nie zmieniają się co sekundę |
| ISR / hybrydowe | Część stron jest generowana i odświeżana etapami | Dobry kompromis dla dużych serwisów |
| Hydration | JS dodaje interakcje do istniejącego HTML | Bezpieczniejsze niż budowanie całej treści od zera |
Nie ma jednej technologii właściwej dla każdej strony. Dla SEO najważniejsze jest, aby krytyczna treść, tytuł, linki i metadane były dostępne, a aplikacja działała po dołączeniu interakcji. Google wskazuje SSR, statyczne renderowanie lub hydratację jako preferowane rozwiązania długoterminowe; dynamic rendering jest raczej obejściem niż docelową architekturą.
Linki i routing w aplikacjach JavaScript
Jedna z najdroższych pomyłek to stylizowanie przycisków tak, aby wyglądały jak linki, ale nie były crawlable.
Bezpieczny link powinien być elementem HTML z adresem:
<a href="/uslugi/audyt-seo">Audyt SEO</a>
Ryzykowne są między innymi:
<div onClick="goTo('/uslugi')">bez prawdziwego href,- przyciski, które zmieniają stan, ale nie URL,
- linki z
href="#", - adresy zależne od sesji lub localStorage,
- router, który nie obsługuje bezpośredniego wejścia na URL,
- trasy zwracające status 200 dla nieistniejących stron.
Google wskazuje, że najpewniej crawluje linki będące elementami <a> z atrybutem href. JavaScript może taki link wstawić dynamicznie, ale finalny markup nadal powinien mieć poprawną strukturę i sensowny URL.
Treść ładowana z API i infinite scroll
Jeśli opis, produkty, opinie albo artykuły są pobierane z zewnętrznego API, sprawdź, czy Googlebot może wykonać wszystkie żądania. Problemem może być autoryzacja, blokada CORS, token, geolokalizacja, limit zapytań albo czas odpowiedzi.
Przy treści z API zadbaj o:
- stabilny endpoint i prawidłowy status HTTP,
- brak wymogu zalogowania dla publicznej treści SEO,
- przewidywalny czas odpowiedzi,
- fallback w HTML lub SSR dla najważniejszych danych,
- unikalne URL-e dla stron szczegółowych,
- paginację z crawlable links zamiast samego "load more",
- canonical dla filtrów i wariantów,
- obsługę błędów i pustych odpowiedzi.
Infinite scroll może być wygodny dla użytkownika, ale nie powinien być jedyną drogą do kolejnych elementów. Każda ważna strona musi mieć własny URL i link możliwy do znalezienia bez klikania w aplikacji.
Meta tagi, canonical i robots w JavaScript
W aplikacji SPA title i description często są zmieniane przez router. To działa dla użytkownika, ale trzeba sprawdzić, czy w wyrenderowanym HTML trafiają na właściwy URL i nie są nadpisywane przez błąd.
Sprawdź dla każdej ważnej trasy:
- unikalny i opisowy
<title>, - unikalny meta description,
- canonical wskazujący preferowany URL,
- poprawny język i hreflang, jeśli masz wersje językowe,
- brak przypadkowego
noindex, - zgodność robots meta z nagłówkiem HTTP,
- status 200 dla istniejącej strony i 404 dla nieistniejącej.
Google ostrzega, że gdy napotka noindex, może pominąć renderowanie i wykonanie JavaScriptu. Nie zakładaj więc, że skrypt usunie później noindex i "naprawi" indeksację. Decyzja o indeksowaniu może zapaść wcześniej.
Dane strukturalne generowane skryptem
JSON-LD może być wstrzykiwany przez JavaScript, a Google potrafi go odczytać z wyrenderowanej strony. Ryzyko pojawia się wtedy, gdy schema zawiera dane niezgodne z widoczną treścią, nieaktualne ceny, brakujące pola albo generuje się dopiero po błędnym żądaniu API.
Przed wdrożeniem sprawdź:
- czy schema istnieje w HTML po renderowaniu,
- czy opisuje ten sam URL, nazwę i treść co strona,
- czy cena, dostępność i oceny są aktualne,
- czy nie generujesz wielu sprzecznych bloków JSON-LD,
- czy nie używasz danych ukrytych wyłącznie przed użytkownikiem,
- czy typ danych pasuje do rzeczywistej strony.
Google rekomenduje JSON-LD, jeśli konfiguracja serwisu na to pozwala. Dynamiczne generowanie jest dopuszczalne, ale im bardziej krytyczna i zmienna jest informacja, tym ważniejszy jest monitoring zgodności schema z faktycznym HTML.
Obrazy, lazy loading i multimedia
Obrazy mogą być ładowane leniwie, ale nie powinny wymagać nietypowej interakcji, której crawler nie wykona. Najważniejsze obrazy powinny mieć prawidłowe źródło, opisowy alt, odpowiedni rozmiar i wersję dostępną dla renderowania.
Sprawdź:
- czy obraz ma prawdziwy
srcalbo poprawny mechanizm lazy loading, - czy nie używasz wyłącznie tła CSS dla ważnych grafik,
- czy alt opisuje zawartość, a nie listę fraz,
- czy miniatury nie blokują głównej treści,
- czy wideo ma tekstowy kontekst i transkrypcję, jeśli jest istotne,
- czy ciężkie biblioteki nie opóźniają renderowania.
Jak sprawdzić, co Google widzi?
Nie zgaduj na podstawie zwykłej wizyty w Chrome. Zrób porównanie kilku widoków.
| Test | Co sprawdzasz? | Niepokojący wynik |
|---|---|---|
| View Source | HTML początkowy z serwera | Brak H1, tekstu, linków i canonical |
| DOM po renderowaniu | Elementy po wykonaniu JS | Treść nie pojawia się albo znika |
| URL Inspection | Widok Google i status indeksacji | Rendered HTML nie zawiera kluczowych elementów |
| Rich Results Test | Schema po renderowaniu | Brak danych lub błędne właściwości |
| Search Console | Indeksacja, crawl i problemy | Discovered/Crawled - currently not indexed |
| Wyłączony JS | Fallback i podstawowa dostępność | Cała strona jest pusta |
| Logi serwera | Żądania Googlebot i zasoby | 404, 5xx, blokady API lub JS |
W Search Console użyj inspekcji URL i porównaj zrzut ekranu oraz wyrenderowany HTML z wersją widoczną dla człowieka. Testuj nie tylko stronę główną, ale też kategorię, produkt, artykuł, filtr, paginację i stronę lokalną.
Jak naprawić problemy JavaScript SEO?
Naprawa powinna zaczynać się od stron o największej wartości biznesowej, nie od przypadkowego porządkowania bundla.
- Zidentyfikuj utracony element. Czy brakuje tekstu, linku, title, schema, obrazu czy całego URL-a?
- Znajdź etap awarii. Crawl, renderowanie, API, routing, indeksacja albo ranking?
- Dodaj bezpieczny fallback. Krytyczna treść powinna być dostępna bez konieczności skomplikowanej interakcji.
- Napraw URL i linki. Każda ważna strona musi mieć stabilny, crawlable adres.
- Ustaw właściwe meta i schema. Generuj dane zgodne z widoczną stroną.
- Sprawdź wydajność. Skróć JS, rozdziel bundle i odrocz skrypty niekrytyczne.
- Przetestuj ponownie. Renderowanie i indeksację weryfikuj po wdrożeniu, nie tylko lokalnie.
Dynamic rendering nie powinien być pierwszym wyborem dla nowej architektury. Jeśli projektujesz system od początku, rozważ SSR, SSG lub hybrydę. Jeżeli masz istniejącą aplikację, zacznij od stron, które generują przychód i mają największy potencjał organiczny.
Analiza konkurencji i plan outrankowania
Pięć stron z pierwszych pozycji może mieć podobne treści, ale różnić się sposobem renderowania. W analizie konkurencji sprawdź:
- czy ich główna treść jest w początkowym HTML,
- czy linki są dostępne bez interakcji,
- czy każda kategoria i produkt ma własny URL,
- czy title i schema zmieniają się per strona,
- czy strony są szybkie na telefonie,
- czy konkurenci mają lepszy fallback dla botów i użytkowników,
- czy ich treść po renderowaniu jest pełniejsza niż Twoja.
| Luka względem konkurencji | Wpływ | Działanie |
|---|---|---|
| Konkurent ma treść w HTML, Ty tylko app shell | Wysoki | SSR/SSG dla kluczowych szablonów |
| Konkurent ma crawlable linki kategorii | Wysoki | Napraw <a href>, sitemap i linkowanie |
| Konkurent ma unikalne meta na URL | Średni/wysoki | Wdroż dynamiczne title, description i canonical |
| Konkurent ma lepsze dane strukturalne | Średni | Dodaj zgodny JSON-LD i testy automatyczne |
| Konkurent ładuje stronę szybciej | Wysoki | Zmniejsz JS i zoptymalizuj krytyczny rendering |
"10 razy lepiej" oznacza tutaj przede wszystkim stabilność: Google i użytkownik dostają tę samą, kompletną stronę, a interaktywność jest dodatkiem, nie jedyną drogą do treści.
Techniczny plan 90 dni
| Okres | Priorytet | Działania |
|---|---|---|
| Dni 1-14 | Diagnoza | URL Inspection, View Source, rendered DOM, logi, robots, statusy, Search Console |
| Dni 15-30 | Najważniejsze URL-e | SSR/SSG lub fallback dla strony głównej, usług, kategorii, produktów i artykułów |
| Dni 31-45 | Crawl i routing | Linki href, URL-e, sitemap, paginacja, canonical, 404 i przekierowania |
| Dni 46-60 | Metadane | Title, description, hreflang, schema, breadcrumbs i testy po renderowaniu |
| Dni 61-75 | Wydajność | Redukcja JS, code splitting, lazy loading, cache, API i Core Web Vitals |
| Dni 76-90 | Monitoring | Automatyczne testy renderowania, indeksacji, linków i zmian w ważnych szablonach |
Po 90 dniach powinieneś mieć listę URL-i, które Google może pobrać, wyrenderować, zrozumieć i zindeksować. Dopiero na takim fundamencie warto skalować content, link building i kolejne funkcje aplikacji.
Najczęstsze błędy
| Błąd | Skutek | Lepsze rozwiązanie |
|---|---|---|
| "Google renderuje JS, więc wszystko jest dobrze" | Brak diagnozy realnego DOM | Porównuj HTML początkowy i wyrenderowany |
| Pusty app shell | Opóźnione lub niepełne indeksowanie | SSR, SSG, prerendering albo fallback treści |
| Przyciski zamiast linków | Google nie odkrywa URL-i | Używaj prawdziwych elementów <a href> |
| Jeden title dla całej SPA | URL-e wyglądają jak ta sama strona | Generuj unikalne metadane per trasa |
| Dane z API bez fallbacku | Brak treści przy błędzie lub opóźnieniu | Serwuj krytyczne dane w HTML |
| noindex usuwany przez JS | Renderowanie może zostać pominięte | Ustaw robots poprawnie już w odpowiedzi |
| Dynamic rendering jako stała architektura | Większa złożoność i rozjazdy | Docelowo przejdź na SSR/SSG/hybrydę |
| Schema niezgodna z widokiem | Błędy i utrata wiarygodności danych | Testuj JSON-LD po renderowaniu |
| Brak monitoringu po deployu | Regresje przechodzą niezauważone | Dodaj automatyczne testy kluczowych URL-i |
Chcesz sprawdzić, czy Google widzi całą Twoją stronę?
Przetestujemy HTML początkowy, renderowanie, routing, linki, API, meta tagi, dane strukturalne, indeksację i wydajność. Otrzymasz listę problemów oraz plan technicznego SEO pod wzrost widoczności.
Zarezerwuj darmową analizę SEONajczęstsze pytania
Czy Google widzi strony wykonane w JavaScript?
Google potrafi wykonywać JavaScript, ale strona przechodzi przez crawling, renderowanie i indeksowanie. Błąd w dowolnym etapie może spowodować, że część treści, linków lub metadanych nie zostanie poprawnie odczytana.
Czy JavaScript zawsze szkodzi SEO?
Nie. JavaScript może poprawiać UX i dodawać interakcje. Problem pojawia się wtedy, gdy zastępuje podstawowy HTML, blokuje linki, opóźnia treść, generuje błędne metadane albo wymaga niedostępnych zasobów.
Co jest lepsze dla SEO: SSR czy CSR?
Dla ważnych stron SSR, SSG lub hybrydowe renderowanie zwykle ułatwia dostarczenie gotowego HTML i poprawia start użytkownika. CSR może działać, ale wymaga dokładnego testowania renderowania, linków, API i metadanych.
Jak sprawdzić, czy Google widzi treść JavaScript?
Porównaj View Source z DOM po renderowaniu, użyj inspekcji URL w Google Search Console, sprawdź wyrenderowany HTML i przetestuj dane strukturalne w Rich Results Test. Weryfikuj kilka typów URL-i, nie tylko stronę główną.
Czy linki onclick są widoczne dla Google?
Nie należy na nich polegać. Najbezpieczniejsze są standardowe elementy a z atrybutem href. JavaScript może wzbogacać działanie linku, ale nie powinien zastępować podstawowego, crawlable adresu URL.
Czy dynamic rendering jest najlepszym rozwiązaniem?
Google traktuje dynamic rendering jako obejście dla określonych problemów, a nie docelową architekturę. Dla nowych wdrożeń lepiej rozważyć SSR, statyczne generowanie lub poprawną hydratację.
JavaScript powinien rozszerzać stronę, a nie ukrywać jej przed Google.
Najważniejsza zasada JavaScript SEO jest prosta: treść, URL-e, linki i metadane muszą być dostępne w sposób przewidywalny. Interaktywność może pojawić się później, ale nie powinna być jedyną drogą do informacji.
Jeśli chcesz outrankować pięć konkurencyjnych stron, nie wystarczy dodać więcej tekstu. Zbuduj lepszą techniczną podstawę: kompletny wyrenderowany HTML, crawlable linki, stabilne URL-e, poprawne schema, szybki start i monitoring po każdej zmianie aplikacji. To przewaga, której konkurent nie naprawi samym kolejnym artykułem.