Karta produktu pod LLM: jakie dane muszą być w HTML, żeby model je odczytał

17 sierpnia, 2026

Karta produktu przez lata była projektowana pod jednego odbiorcę: człowieka z myszką i cierpliwością. Można było schować specyfikację w zakładce, doładować opinie po kliknięciu, a cenę wstrzyknąć skryptem. Model językowy takiej cierpliwości nie ma. Nie kliknie w zakładkę, nie przewinie do sekcji i najczęściej nie poczeka, aż JavaScript dokończy pracę. Zobaczy to, co znajdzie w statycznym HTML w momencie pobrania strony, i na tej podstawie zdecyduje, czy Twój produkt nadaje się do zacytowania.

To nie jest wyłącznie problem techniczny, tylko kwestia tego, czy sklep istnieje w warstwie, w której coraz częściej zapada decyzja zakupowa. Szerszy obraz tej zmiany opisaliśmy w tekście o tym, jak przygotować sklep na zakupy realizowane przez AI. Tutaj schodzimy poziom niżej, do konkretnego pliku HTML pojedynczej karty produktu.

Co model widzi na karcie produktu, a czego nie

Wyobraź sobie, że ktoś pobiera Twoją stronę poleceniem curl, wyrzuca tagi HTML i zostawia goły tekst plus dane strukturalne. To mniej więcej materiał, na którym pracuje crawler zasilający model. Jeżeli po takiej operacji nie da się odpowiedzieć na pytanie „ile to kosztuje, czy jest dostępne i czym różni się od konkurencji”, karta produktu jest dla modelu niema.

Trzy rzeczy znikają najczęściej. Pierwsza to treść renderowana wyłącznie po stronie klienta, czyli klasyczne SPA, w którym HTML zawiera pusty kontener i pakiet skryptów. Druga to zawartość ukryta za interakcją, na przykład opinie ładowane po kliknięciu przycisku „pokaż więcej”. Trzecia to informacje przekazywane wyłącznie obrazem: tabela parametrów zapisana jako grafika albo cena wypalona w bannerze promocyjnym.

Model nie karze Cię za brak tych danych w sposób jawny. On po prostu wybiera inny sklep, o którym wie więcej.

Schema Product, Offer i AggregateRating w praktyce

Dane strukturalne to najkrótsza droga do tego, żeby maszyna zrozumiała stronę bez zgadywania. Standard opisany w specyfikacji schema.org dla typu Product jest dziś traktowany jako wspólny język między sklepem a systemami, które go czytają. Google publikuje własne wytyczne implementacyjne w dokumentacji Search Central i warto trzymać się ich literalnie, bo modele bardzo często korzystają z tego samego pipeline’u parsowania.

Minimalny zestaw, który realnie robi różnicę, wygląda tak:

  • name: pełna nazwa handlowa, ta sama, która widnieje w nagłówku strony.
  • sku oraz gtin13 lub mpn: identyfikatory pozwalające połączyć Twoją ofertę z tym samym produktem u innych sprzedawców.
  • brand: jako obiekt typu Brand, nie jako luźny string wewnątrz nazwy.
  • description: opis zgodny z tym, co widzi użytkownik, bez upychania fraz.
  • image: kilka URL-i w dobrej rozdzielczości.
  • offers: obiekt Offer z ceną, walutą, dostępnością i datą ważności ceny.
  • aggregateRating i review: wyłącznie wtedy, gdy opinie faktycznie istnieją na stronie.

Najczęstszy błąd w tej sekcji to rozjazd między danymi strukturalnymi a treścią widoczną. Jeżeli w JSON-LD deklarujesz cenę 1299 zł, a w HTML widnieje 1499 zł, model traktuje kartę jako niespójną i obniża zaufanie do całego źródła. To samo dotyczy ocen: aggregateRating bez ani jednej opinii w treści to sygnał ostrzegawczy, nie przewaga.

Drugi błąd jest subtelniejszy. Wiele platform generuje osobny blok Product dla każdego wariantu kolorystycznego na tej samej stronie, bez powiązania ich w ProductGroup. Model dostaje wtedy pięć produktów o niemal identycznej nazwie i nie wie, który opisać.

Specyfikacja techniczna: tabela zamiast prozy

Jeżeli miałbyś zmienić w karcie produktu tylko jedną rzecz, zmień sposób podania parametrów. Zdanie „urządzenie wyposażono w pojemny akumulator zapewniający długą pracę na jednym ładowaniu” nie niesie informacji, którą model mógłby porównać z konkurencją. Wiersz tabeli „Pojemność akumulatora: 5000 mAh” niesie ją w całości. Najlepiej sprawdza się zwykła tabela HTML z kolumną nazw parametrów i kolumną wartości:

ParametrWartość
Przekątna ekranu15,6 cala
Rozdzielczość1920 x 1080 px
Pamięć RAM16 GB
Waga1,74 kg
Gwarancja24 miesiące

Trzy zasady warto wymusić w szablonie. Jednostka zawsze przy wartości, nigdy tylko w nagłówku kolumny. Nazwy parametrów spójne w obrębie kategorii, żeby model mógł zestawić dziesięć laptopów po tym samym polu. Żadnych wartości typu „tak” bez kontekstu.

Te same parametry powinny zasilać feed produktowy. Jak zbudować go tak, żeby dane zgadzały się w obu miejscach, opisaliśmy w materiale o tym, które pola feedu decydują o rekomendacji. Rozjazd między feedem a kartą produktu to częsta przyczyna tego, że sklep pojawia się w porównaniach z nieaktualnymi danymi.

Cena, waluta i dostępność bez pułapek

Cena dezaktualizuje się najszybciej, więc systemy oparte o modele są na nią najbardziej wyczulone. Musi być w statycznym HTML, nie w odpowiedzi zapytania AJAX wykonanego po załadowaniu strony. Jeżeli architektura wymusza dociąganie stanów magazynowych, wyrenderuj serwerowo ostatnią znaną cenę i aktualizuj ją skryptem, zamiast zostawiać puste miejsce. Waluta powinna być podana jawnie jako priceCurrency w formacie ISO, czyli PLN, nie jako sam symbol „zł” w tekście. Dostępność koduj wartościami ze słownika schema.org: InStock, OutOfStock, PreOrder, BackOrder. Własne stringi typu „ostatnie sztuki” działają w interfejsie, ale nie w danych strukturalnych.

Osobna sprawa to ceny promocyjne. Warto rozdzielić cenę regularną i obniżoną przy użyciu priceSpecification, zamiast pokazywać tylko wartość po rabacie. Model, który widzi wyłącznie cenę promocyjną, po zakończeniu promocji będzie ją powtarzał jeszcze przez tygodnie, a Ty odpowiesz za tę rozbieżność przed klientem. Jeżeli sprzedajesz w kilku krajach, każda wersja językowa potrzebuje własnej pary cena plus waluta i poprawnych tagów hreflang.

Opinie i pytania klientów w treści strony

Opinie to materiał, po który modele sięgają najchętniej, bo dostarczają języka, którym realni ludzie opisują produkt. Problem w tym, że w większości sklepów są dociągane asynchronicznie z zewnętrznego widgetu, czyli praktycznie nie istnieją poza przeglądarką. Rozwiązanie jest proste w opisie i uciążliwe we wdrożeniu: co najmniej kilka najnowszych opinii powinno być wyrenderowanych serwerowo w HTML, razem z oceną liczbową, datą i autorem. Resztę można ładować dynamicznie. Podobnie z sekcją pytań i odpowiedzi, która mapuje się na typ QAPage. To zwykle najbogatsze semantycznie miejsce na karcie, bo klienci pytają dokładnie o to, o co potem pytają modele.

Warto też zadbać, żeby treść opinii nie była wyłącznie zbiorem gwiazdek. Dwa zdania konkretu o tym, jak produkt sprawdza się w codziennym użyciu, są dla modelu wartościowsze niż sto ocen bez komentarza. Mechanikę trafiania do zestawień zakupowych opisaliśmy przy okazji tekstu o tym, jak sklep trafia do wyników zakupowych ChatGPT.

Zakładki, akordeony i lazy loading: kiedy zabijają odczyt

Nie każdy element ukryty wizualnie jest niewidoczny dla maszyny, a od tego rozróżnienia zależy, czy trzeba przebudowywać szablon. Treść obecna w HTML, a jedynie schowana przez CSS (na przykład display: none w nieaktywnej zakładce), jest odczytywana bez problemu. Crawler pobiera źródło, nie zrzut ekranu. Treść, której w źródle nie ma i która pojawia się dopiero po zdarzeniu kliknięcia, jest dla modelu nieistniejąca. To najważniejsza granica na całej karcie produktu.

Praktyczne wnioski dla szablonu:

  1. Zakładki „Opis”, „Specyfikacja”, „Dostawa” mogą zostać, o ile ich zawartość jest w HTML od razu.
  2. Akordeony na <details> i <summary> są bezpieczne, bo treść siedzi w źródle.
  3. Lazy loading stosuj do obrazów, nie do tekstu i nie do tabel parametrów.
  4. Wszystko, co ładuje się z zewnętrznej domeny widgetem, traktuj jako niewidoczne, dopóki nie udowodnisz inaczej.

Testowanie: jak sprawdzić, co model faktycznie widzi

Weryfikacja zajmuje kilka minut. Najprostszy test to pobranie strony bez wykonywania JavaScriptu i przejrzenie tego, co zostało. Wystarczy curl -s https://twojsklep.pl/produkt/ | less i przeszukanie źródła pod kątem ceny, nazwy parametru i fragmentu opinii. Jeżeli którejkolwiek z tych rzeczy nie ma, masz odpowiedź.

Drugi krok to walidacja danych strukturalnych. Test wyników z elementami rozszerzonymi od Google pokaże błędy składniowe i brakujące pola wymagane, a walidator schema.org zweryfikuje sam typ. Warto uruchomić oba, bo wyłapują różne klasy problemów.

Trzeci krok, najbardziej praktyczny, to zapytanie modelu wprost. Podaj adres karty produktu i poproś o wypisanie ceny, dostępności, pięciu parametrów technicznych i ogólnego wydźwięku opinii. Jeżeli model zmyśla parametry albo odmawia podania ceny, problem leży w HTML, nie w modelu.

Ten test warto wpiąć w proces wdrożeniowy. Zespoły frontendowe optymalizują wydajność przez przenoszenie renderowania na klienta, co bywa świetne dla Core Web Vitals i katastrofalne dla widoczności w odpowiedziach generowanych przez AI. Bez regularnej kontroli ta regresja przechodzi niezauważona przez miesiące.

Nie zaczynaj przy tym od pełnej przebudowy szablonu. Weź dwadzieścia najlepiej sprzedających się produktów, przepuść przez test curl i wypisz braki. W praktyce niemal zawsze wychodzą te same trzy rzeczy: specyfikacja jako proza zamiast tabeli, opinie z zewnętrznego widgetu i cena wstrzykiwana skryptem. Naprawienie ich w szablonie działa od razu na cały katalog.

Czy dane strukturalne wystarczą, jeśli treść widoczna jest uboga?

Nie. JSON-LD i treść widoczna muszą się zgadzać, a modele coraz częściej weryfikują jedno przez drugie. Dane strukturalne bez pokrycia w HTML bywają traktowane jako sygnał niskiej jakości, a w skrajnych przypadkach jako próba manipulacji. Traktuj schema jako opis tego, co faktycznie jest na stronie, nie jako zamiennik treści.

Czy treść ukryta w zakładce jest widoczna dla modelu?

Zależy od implementacji. Jeżeli tekst znajduje się w źródle HTML i jest jedynie schowany przez CSS, model go odczyta. Jeżeli pojawia się dopiero po kliknięciu, w wyniku zapytania do serwera, jest nieobecny. Rozstrzyga to test pobrania strony bez wykonywania JavaScriptu.

Co zrobić, gdy sklep działa na frameworku renderowanym po stronie klienta?

Najczystszym rozwiązaniem jest renderowanie serwerowe lub prerendering kart produktowych. Większość nowoczesnych frameworków ma to wbudowane i wystarczy przełączyć tryb dla tej jednej ścieżki. Jeżeli to niemożliwe w krótkim terminie, minimum to wstrzyknięcie do statycznego HTML nazwy, ceny, dostępności, tabeli parametrów i kilku opinii.

Czy warianty produktu powinny mieć osobne adresy URL?

Zwykle tak, jeśli różnią się ceną, dostępnością lub kodem EAN. Warianty spina się wtedy typem ProductGroup i relacją hasVariant, co pozwala modelowi zrozumieć, że to jedna rodzina produktów. Kilka niepowiązanych bloków Product na jednej stronie to najczęstsza przyczyna błędnego cytowania oferty.