Logo David Burdelak
SEO

Jak wdrożyć dane strukturalne – typy, kod JSON-LD i testowanie

Dane strukturalne

Dane strukturalne wdrażam w niemal każdym projekcie, ale coraz rzadziej zaczynam od pytania „jaki znacznik dodać”. Ważniejsze jest, które typy faktycznie dają coś w wynikach Google, jak utrzymać je zgodne z treścią strony i jak sprawdzić, że działają. W tym wpisie pokazuję, jak podchodzę do wdrożenia krok po kroku: od wyboru typów, przez kod JSON-LD, po testowanie i błędy, przez które Google pomija oznaczenia.

Czego realnie oczekiwać od danych strukturalnych

Zanim zacznę wdrożenie, ustalam z klientem oczekiwania. Dane strukturalne nie są bezpośrednim czynnikiem rankingowym i nie podniosą pozycji same z siebie. Dają dwie rzeczy: pomagają wyszukiwarce jednoznacznie zrozumieć, czym jest strona i kto za nią stoi, oraz sprawiają, że strona może kwalifikować się do wyników rozszerzonych, np. z ceną, dostępnością czy oceną produktu. „Może” jest tu kluczowe, bo nawet bezbłędny kod nie gwarantuje, że Google pokaże wynik rozszerzony.

Warto też wiedzieć, że lista wyników rozszerzonych się zmienia. Część typów, które jeszcze kilka lat temu dawały rozbudowany wygląd w wynikach, dziś nie działa albo działa tylko dla wybranych serwisów, o czym niżej przy FAQ.

Które typy wdrażam w zależności od strony

Nie oznaczam wszystkiego, co się da. Dobieram typy do rodzaju strony i do tego, co dany typ może dać w wynikach wyszukiwania.

Każda strona: organizacja i okruszki

Na stronie głównej dodaję Organization albo LocalBusiness z nazwą, logo, adresem, kontaktem i profilami społecznościowymi. Dla firmy lokalnej wybieram możliwie dokładny podtyp, np. Dentist czy AutoRepair, a dane muszą się zgadzać z wizytówką w Google. Na podstronach z nawigacją okruszkową dokładam BreadcrumbList, dzięki czemu wyszukiwarka widzi miejsce strony w strukturze serwisu.

Sklep: produkty z ceną i dostępnością

Na kartach produktów wdrażam Product z Offer: cenę, walutę, dostępność i stan. To typ, który daje najbardziej widoczny efekt, bo produkt może pojawić się z ceną i informacją o dostępności nie tylko w zwykłych wynikach, ale też w Grafice Google i w zakładce Zakupy.

Opinie i oceny w gwiazdkach

Jeśli opinie klientów są widoczne na stronie produktu, dodaję AggregateRating i Review. Gwiazdki pod wynikiem to jeden z najbardziej przyciągających wzrok elementów w wynikach wyszukiwania.

Jedna pułapka wraca regularnie: oceny dla samej firmy. Opinie, które firma zbiera o sobie i oznacza na własnej stronie jako LocalBusiness lub Organization, nie kwalifikują się do wyświetlenia gwiazdek w Google. Oceny działają przy produktach, przepisach czy wydarzeniach, a nie przy autopromocji firmy.

Blog: artykuły z autorem i datami

Dla wpisów stosuję Article lub BlogPosting z tytułem, autorem, zdjęciem oraz datami publikacji i modyfikacji. Tu efekt w wynikach jest mniej spektakularny, ale wyszukiwarka dostaje jednoznaczną informację, kto jest autorem i kiedy treść była ostatnio aktualizowana.

Wydarzenia

Organizatorom koncertów, szkoleń czy wystaw wdrażam Event z datą, godziną, miejscem i informacją o biletach. Wydarzenia mogą wtedy pojawiać się w wynikach z datą i lokalizacją, zanim użytkownik wejdzie na stronę.

Hotele i apartamenty

Dla obiektów noclegowych stosuję typy z grupy LodgingBusiness, np. Hotel, z adresem, udogodnieniami i ocenami gości. W tej branży wyniki Google łączą dane z witryny, mapy, zdjęcia i porównanie cen, więc spójność danych ze stroną i wizytówką ma szczególne znaczenie.

Przepisy

Serwisy kulinarne korzystają z Recipe: zdjęcia, czasu przygotowania, składników, kroków i ocen. Przepisy z poprawnymi oznaczeniami mogą trafiać do karuzeli przepisów na górze wyników, gdzie liczy się przede wszystkim dobre zdjęcie i ocena.

FAQ, czyli typ, który stracił znaczenie

Przez kilka lat rozwijane pytania i odpowiedzi pod wynikiem były najprostszym sposobem na zajęcie większej części ekranu. Od 2023 roku Google pokazuje wyniki FAQ tylko wybranym, autorytatywnym serwisom, głównie rządowym i medycznym, a wyniki HowTo zostały wycofane. Na stronach firmowych nie dodaję już FAQPage z myślą o wyglądzie w Google. Sekcja pytań ma sens, jeśli pomaga czytelnikom.

Dlaczego JSON-LD i gdzie go umieścić

Google obsługuje trzy formaty: JSON-LD, mikrodane i RDFa. W nowych projektach używam wyłącznie JSON-LD, bo dane są w jednym bloku <script type="application/ld+json">, oddzielone od szablonu. Zmiana wyglądu strony nie psuje oznaczeń, a oznaczenia można zmieniać bez dotykania HTML-a. Mikrodane spotykam głównie w starszych motywach i sklepach, gdzie atrybuty są wplecione w znaczniki. Nie mieszam formatów na jednej stronie, bo łatwo wtedy o zdublowane lub sprzeczne dane.

Blok JSON-LD może stać w sekcji head albo w body, Google odczyta go w obu miejscach. Ważniejsze jest, żeby był w HTML-u wysłanym przez serwer. Jeśli dane strukturalne dokłada dopiero JavaScript po załadowaniu strony, Google zwykle je odczyta po wyrenderowaniu, ale inne wyszukiwarki i narzędzia mogą ich nie zobaczyć. To jeden z powodów, dla których przy wyborze metody renderowania sprawdzam, gdzie powstają metadane. Z tego samego powodu nie wstrzykuję danych strukturalnych przez Google Tag Manager, choć technicznie się da.

Przykłady kodu, od których zaczynam

Firma lokalna. Poniżej poprawiona wersja przykładu, który kiedyś publikowałem w tym wpisie. Stara wersja miała przecinek po ostatnim elemencie obiektu, przez co cały blok był niepoprawnym JSON-em i Google go ignorował. To jeden z najczęstszych błędów, jakie znajduję w audytach.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "@id": "https://domena.pl/#firma",
  "name": "Nazwa firmy",
  "url": "https://domena.pl/",
  "logo": "https://domena.pl/images/logo.png",
  "telephone": "+48 575 587 858",
  "email": "biuro@domena.pl",
  "vatID": "PL1246813567",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "Firmowa 7",
    "postalCode": "60-101",
    "addressLocality": "Poznań",
    "addressRegion": "wielkopolskie",
    "addressCountry": "PL"
  },
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
    "opens": "08:00",
    "closes": "16:00"
  }]
}
</script>

Produkt w sklepie. Minimum, które ma sens, to nazwa, zdjęcie i oferta z ceną, walutą i dostępnością:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Lodówka XYZ 300",
  "image": "https://sklep.pl/img/lodowka-xyz-300.webp",
  "sku": "XYZ300",
  "brand": { "@type": "Brand", "name": "XYZ" },
  "offers": {
    "@type": "Offer",
    "url": "https://sklep.pl/lodowka-xyz-300",
    "price": "2499.00",
    "priceCurrency": "PLN",
    "availability": "https://schema.org/InStock",
    "itemCondition": "https://schema.org/NewCondition"
  }
}
</script>

Wpis na blogu. Dla artykułów najważniejsze są tytuł, autor z adresem strony o nim, zdjęcie oraz daty publikacji i modyfikacji. Na tym blogu generuję je automatycznie z tych samych danych, z których powstaje lista wpisów, więc data aktualizacji w kodzie zawsze zgadza się z datą widoczną dla czytelnika.

Generuj dane z bazy, a nie ręcznie

Ręcznie wklejony JSON-LD działa do pierwszej zmiany ceny. Potem w kodzie zostaje stara cena, produkt jest oznaczony jako dostępny, choć zniknął z magazynu, a godziny otwarcia różnią się od tych w stopce. Dlatego w sklepach i serwisach z wieloma podstronami dane strukturalne zawsze generuję w szablonie z tych samych pól, z których budowana jest treść strony. W PHP sprowadza się to do zbudowania tablicy i przepuszczenia jej przez json_encode() z flagami JSON_UNESCAPED_UNICODE i JSON_UNESCAPED_SLASHES, co przy okazji eliminuje błędy składni.

W WordPressie część pracy wykonują wtyczki SEO, które dodają oznaczenia dla stron, wpisów i organizacji. Przy wyborze wtyczek do WordPressa sprawdzam, czy nie dublują się z oznaczeniami z motywu lub wtyczki sklepu. Dwie wtyczki generujące Product dla tej samej strony to częsty powód ostrzeżeń w Search Console.

Przy rozbudowanych serwisach łączę obiekty przez @id, np. wpis wskazuje autora i wydawcę, a wydawca to ta sama organizacja co na stronie głównej. Dzięki temu wyszukiwarka dostaje spójny obraz, a nie kilka niepowiązanych opisów tej samej firmy.

Jak testuję wdrożenie

Każde wdrożenie sprawdzam na trzech poziomach:

  • Składnia i słownik: walidator Schema.org pokazuje, czy JSON jest poprawny i czy właściwości pasują do typu.
  • Kwalifikacja do wyników rozszerzonych: test wyników z elementami rozszerzonymi Google pokazuje, czy strona spełnia wymagania danego typu i których pól brakuje.
  • Cały serwis w czasie: raporty w sekcji Ulepszenia w Google Search Console pokazują błędy i ostrzeżenia dla wszystkich stron danego typu. Tu wychodzą problemy, których nie widać przy testowaniu pojedynczego adresu, np. brak ceny w części produktów.

Sprawdzanie danych strukturalnych jest też stałym punktem, gdy robię audyt techniczny SEO, bo oznaczenia psują się najczęściej po zmianach w szablonie, o których nikt nie pomyślał w kontekście SEO.

Błędy, przez które Google pomija oznaczenia

  • Dane niezgodne z treścią strony. Cena, ocena czy dostępność w kodzie muszą być widoczne na stronie i takie same jak dla użytkownika. Oznaczanie rzeczy, których czytelnik nie widzi, to naruszenie wytycznych i może skończyć się ręcznym działaniem Google.
  • Błędy składni. Przecinek na końcu, niezamknięty nawias czy cudzysłów skopiowany z edytora tekstu unieważniają cały blok.
  • Brak wymaganych pól. Produkt bez oferty, oceny ani opinii nie kwalifikuje się do wyniku rozszerzonego, nawet jeśli reszta jest poprawna.
  • Zły typ. Strona kategorii oznaczona jako jeden Product albo strona usługi oznaczona jako Article wprowadza wyszukiwarkę w błąd.
  • Duplikaty. Te same dane wygenerowane przez motyw, wtyczkę i ręcznie dodany skrypt, często z różnymi wartościami.

Jak sprawdzić, czy wdrożenie się opłaciło

Efekt mierzę w raporcie skuteczności w Search Console. Po wdrożeniu porównuję współczynnik klikalności stron, które zaczęły pokazywać się z wynikami rozszerzonymi, z okresem przed zmianą, a raport „Wygląd w wyszukiwarce” pokazuje, ile kliknięć i wyświetleń przypada na dany typ wyniku. Przy kartach produktów cena i dostępność widoczne bezpośrednio w wynikach zwykle wyraźnie zwiększają klikalność, ale wolę opierać się na danych z konkretnego serwisu niż na ogólnych obietnicach. Jeśli po kilku tygodniach nic się nie zmienia, wracam do testów i sprawdzam, czy Google w ogóle uznał oznaczenia za poprawne.