E-E-A-T dla devów e-commerce: praktyczny przewodnik po sygnałach, które Google faktycznie czyta
Co realnie wpływa na ocenę sklepu w Google z perspektywy kodu, schematów i konfiguracji — bez marketingowego lania wody.
Problem
E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness) jest najczęściej omawiany na blogach marketingowych jako zbiór ogólników: "pisz lepszą treść", "buduj autorytet", "dbaj o zaufanie". Z perspektywy developera takie porady są bezużyteczne — nie wiesz, co dodać do kodu, jakim schema oznaczyć stronę, ani co wystawić w nagłówkach HTTP.
Tymczasem większość sygnałów E-E-A-T, które Google realnie odczytuje, to dane strukturalne, konfiguracja serwera, atrybuty DOM i mierzalne metryki techniczne. Po wycieku Google Content Warehouse API w maju 2024 wiemy też trochę więcej o tym, jakie konkretne atrybuty Google przechowuje (siteAuthority, OriginalContentScore, isAuthor, hostAge i ~14 000 innych).
Ten wpis to wyciąg sygnałów E-E-A-T sprowadzonych do poziomu, który dev e-commerce może faktycznie wdrożyć — z kodem, schematami i konfiguracją.
Co Google faktycznie sprawdza (i jak to zakodować)
1. Tożsamość firmy — Schema.org Organization
Najważniejszy pojedynczy sygnał Trust dla sklepu. Bez tego Google nie ma pewności kim jesteś.
{
"@context": "https://schema.org",
"@type": "OnlineStore",
"@id": "https://twojsklep.pl/#organization",
"name": "Twój Sklep Sp. z o.o.",
"url": "https://twojsklep.pl",
"logo": "https://twojsklep.pl/logo.png",
"image": "https://twojsklep.pl/og-image.jpg",
"telephone": "+48-22-123-45-67",
"email": "kontakt@twojsklep.pl",
"taxID": "PL5252123456",
"vatID": "PL5252123456",
"address": {
"@type": "PostalAddress",
"streetAddress": "ul. Przykładowa 1",
"addressLocality": "Warszawa",
"postalCode": "00-001",
"addressCountry": "PL"
},
"contactPoint": {
"@type": "ContactPoint",
"telephone": "+48-22-123-45-67",
"contactType": "customer service",
"areaServed": "PL",
"availableLanguage": ["Polish", "English"]
},
"sameAs": [
"https://www.facebook.com/twojsklep",
"https://www.instagram.com/twojsklep",
"https://www.linkedin.com/company/twojsklep",
"https://www.youtube.com/@twojsklep"
],
"foundingDate": "2018-03-15",
"numberOfEmployees": {
"@type": "QuantitativeValue",
"value": "25"
}
}
Wstaw to raz, w <head> na każdej podstronie, z tym samym @id. Reszta schematów (Product, Article, BreadcrumbList) odwołuje się do tego @id przez "publisher": {"@id": "..."}.
2. Polityka zwrotów jako structured data
Google od 2023 ma osobny typ na to i wyświetla w wynikach wyszukiwania.
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Nazwa produktu",
"offers": {
"@type": "Offer",
"price": "199.00",
"priceCurrency": "PLN",
"availability": "https://schema.org/InStock",
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"applicableCountry": "PL",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/FreeReturn"
},
"shippingDetails": {
"@type": "OfferShippingDetails",
"shippingRate": {
"@type": "MonetaryAmount",
"value": "15.99",
"currency": "PLN"
},
"shippingDestination": {
"@type": "DefinedRegion",
"addressCountry": "PL"
},
"deliveryTime": {
"@type": "ShippingDeliveryTime",
"businessDays": {
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
},
"transitTime": {
"@type": "QuantitativeValue",
"minValue": 1,
"maxValue": 3,
"unitCode": "DAY"
}
}
}
}
}
To bezpośredni sygnał Trust — Google wie, że masz jawnie zdefiniowaną politykę zwrotów, i pokazuje to w SERP.
3. Autorzy treści — Schema Person + Article
Sklep prowadzi bloga? Każdy wpis musi mieć autora. Nie "Admin", nie "Redakcja".
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Jak wybrać rower MTB do 5000 zł",
"datePublished": "2026-05-10T10:00:00+02:00",
"dateModified": "2026-05-14T15:30:00+02:00",
"author": {
"@type": "Person",
"@id": "https://twojsklep.pl/zespol/jan-kowalski#person",
"name": "Jan Kowalski",
"jobTitle": "Specjalista ds. rowerów górskich",
"image": "https://twojsklep.pl/zespol/jan-kowalski.jpg",
"description": "15 lat doświadczenia w serwisie rowerowym, certyfikowany mechanik Shimano.",
"url": "https://twojsklep.pl/zespol/jan-kowalski",
"sameAs": [
"https://www.linkedin.com/in/jan-kowalski",
"https://www.strava.com/athletes/12345"
]
},
"publisher": {"@id": "https://twojsklep.pl/#organization"}
}
Atrybut isAuthor z wycieku Google API potwierdza, że Google buduje encje autorów i ich autorytet jest mierzony niezależnie od domeny. Dlatego strona zespołu pod URL-em typu /zespol/jan-kowalski z biogramem, zdjęciem i sameAs do LinkedIna ma sens techniczny, nie tylko PR-owy.
4. Karty produktowe — minimum techniczne
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Rower MTB Trek X-Caliber 8",
"image": [
"https://twojsklep.pl/img/produkty/trek-x-caliber-8-front.jpg",
"https://twojsklep.pl/img/produkty/trek-x-caliber-8-side.jpg",
"https://twojsklep.pl/img/produkty/trek-x-caliber-8-detail.jpg"
],
"description": "Opis własny, minimum 200 słów, NIE skopiowany od producenta.",
"sku": "TRK-XC8-2026-M",
"mpn": "5259876",
"gtin13": "0601842500125",
"brand": {"@type": "Brand", "name": "Trek"},
"review": [
{
"@type": "Review",
"reviewRating": {"@type": "Rating", "ratingValue": "5", "bestRating": "5"},
"author": {"@type": "Person", "name": "Marcin K."},
"datePublished": "2026-04-20",
"reviewBody": "Konkretna treść opinii, najlepiej z weryfikacją zakupu."
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "89"
}
}
5. Oryginalność opisów — bez tego cię przesieje
Wyciek Google API ujawnił atrybut OriginalContentScore (skala 0–512). To bezpośredni sygnał, że Google porównuje twoje opisy z innymi w internecie.
Praktyczne implikacje dla deva:
- Nie wyciągaj opisów z feedu producenta przez API i nie wrzucaj as-is — to robi 90% sklepów i wszyscy mają identyczny tekst.
- Jeśli już pobierasz feed, wymuś przepisanie przez backendowy workflow zanim opis trafi na produkcję. Można to zautomatyzować z LLM API (claude-haiku-4-5 wystarczy do przepisania opisu produktu i kosztuje grosze).
- W bazie trzymaj dwa pola:
description_source(oryginał z feedu) idescription_published(przepisana wersja, ta idzie do users i schema). - Endpoint robotom serwuj tylko
description_published.
# Przykład: prosty pipeline przepisania opisów przez Claude API
import anthropic
import hashlib
client = anthropic.Anthropic()
def rewrite_product_description(original: str, product_name: str) -> str:
cache_key = hashlib.sha256(original.encode()).hexdigest()
# ... sprawdź cache, jeśli jest, zwróć ...
response = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=1024,
messages=[{
"role": "user",
"content": f"""Przepisz opis produktu w języku polskim.
Zachowaj wszystkie fakty i specyfikację techniczną.
Zmień strukturę zdań, użyj innego słownictwa.
Dodaj informacje praktyczne (dla kogo, do czego, na co uważać).
Minimum 250 słów. Nie używaj marketingowego żargonu.
Produkt: {product_name}
Oryginał: {original}"""
}]
)
return response.content[0].text
6. Wiek domeny i hostAge
Atrybut hostAge z wycieku potwierdza, że Google trzyma metadane wieku hosta i traktuje świeże domeny z większą rezerwą (piaskownica).
Nie ma na to kodu — trzeba czekać. Ale jako dev możesz:
- Nie migrować sklepu na nową domenę bez powodu — tracisz
hostAge. - Jeśli musisz migrować, ustaw poprawne 301 redirecty wszystkich URL-i (nie tylko strony głównej):
# nginx redirect map dla migracji
map $request_uri $new_uri {
/old/category/rowery /kategoria/rowery;
/old/produkt/trek-123 /produkt/trek-x-caliber-8;
default "";
}
server {
listen 443 ssl http2;
server_name oldshop.pl;
if ($new_uri != "") {
return 301 https://newshop.pl$new_uri;
}
return 301 https://newshop.pl$request_uri;
}
Zachowuj Last-Modified i ETag headers konsekwentnie — Google używa ich do oceny świeżości treści.
7. Sygnały bezpieczeństwa — nagłówki HTTP
Trust nie kończy się na HTTPS. Google sprawdza pełną konfigurację bezpieczeństwa.
# Minimum dla sklepu w 2026
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; ..." always;
Dorzuć HSTS preload (https://hstspreload.org/), a sklep zyska zaufanie nawet przy pierwszym kontakcie.
8. Core Web Vitals jako sygnał Authority
Z wycieku wiemy o NavBoost — systemie, który mocno waży sygnały kliknięć z Chrome. Im szybsza strona, tym lepsze metryki zaangażowania (bounce, dwell time, pogo-sticking), tym lepszy NavBoost.
Konkretne benchmarki, które dev musi trzymać:
| Metryka | Cel "good" |
|---|---|
| LCP (Largest Contentful Paint) | < 2.5s |
| INP (Interaction to Next Paint) | < 200ms |
| CLS (Cumulative Layout Shift) | < 0.1 |
| TTFB (Time to First Byte) | < 600ms |
Dla deva PrestaShop / Magento / WooCommerce typowe wąskie gardła:
# Cache statycznych assetów
location ~* \.(jpg|jpeg|png|webp|avif|gif|ico|css|js|woff2|svg)$ {
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
}
# Brotli compression
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
W kodzie — loading="lazy" na obrazach poniżej fold, fetchpriority="high" na obrazie LCP (zazwyczaj główne zdjęcie produktu na karcie), preconnect do CDN.
<link rel="preconnect" href="https://cdn.twojsklep.pl" crossorigin>
<link rel="preload" as="image" href="/img/hero.webp" fetchpriority="high">
<!-- Obraz LCP -->
<img src="/img/produkty/glowne.webp"
alt="Konkretny opis"
fetchpriority="high"
width="800" height="600">
<!-- Reszta obrazów -->
<img src="/img/produkty/inne.webp"
loading="lazy"
decoding="async"
width="800" height="600">
width i height ZAWSZE — to eliminuje CLS.
9. Sitemap, robots i kanoniczne — bez podstaw nic nie działa
<!-- sitemap_index.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://twojsklep.pl/sitemap-products.xml</loc>
<lastmod>2026-05-14</lastmod>
</sitemap>
<sitemap>
<loc>https://twojsklep.pl/sitemap-categories.xml</loc>
<lastmod>2026-05-14</lastmod>
</sitemap>
<sitemap>
<loc>https://twojsklep.pl/sitemap-blog.xml</loc>
<lastmod>2026-05-14</lastmod>
</sitemap>
</sitemapindex>
# robots.txt
User-agent: *
Allow: /
Disallow: /koszyk
Disallow: /checkout
Disallow: /konto/
Disallow: /szukaj?
Disallow: /*?sort=
Disallow: /*?filter=
Disallow: /*?page=
Sitemap: https://twojsklep.pl/sitemap_index.xml
<link rel="canonical"> na każdej stronie. Dla wariantów produktu (kolor, rozmiar) z parametrami w URL — kanoniczne wskazujące na bazowy URL produktu. Inaczej Google indeksuje ci 50 wariantów tego samego produktu i każdy ma rozcieńczony PageRank.
10. Wykrywalne sygnały weryfikowanych opinii
Trustmarki (Trusted Shops, Opineo, Zaufane Opinie Google) wstaw nie tylko jako logo w stopce — Google patrzy na skrypty i widgety.
<!-- Trusted Shops badge — Google rozpoznaje skrypt -->
<script src="//widgets.trustedshops.com/js/X1234ABCDE.js" async></script>
<!-- Opineo badge -->
<script src="//www.opineo.pl/sklep/widget/12345.js" async></script>
<!-- Schema.org Review z atrybutem source -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "AggregateRating",
"itemReviewed": {
"@type": "OnlineStore",
"name": "Twój Sklep",
"@id": "https://twojsklep.pl/#organization"
},
"ratingValue": "4.8",
"reviewCount": "1247",
"publisher": {
"@type": "Organization",
"name": "Trusted Shops"
}
}
</script>
Wskazanie publisher opinii ma znaczenie — Google odróżnia oceny generowane przez sklep od ocen z niezależnych źródeł.
Co się dzieje pod spodem
Z perspektywy deva, najważniejsze wnioski po wycieku Google API:
Google trzyma encje, nie strony. Każda firma, każdy autor, każdy produkt ma swoje @id w grafie wiedzy. Schema.org z konsekwentnymi @id w całym serwisie pozwala Google złożyć ten graf bez zgadywania. Brak @id = Google sam musi guessować, i guesses często są błędne.
siteAuthority istnieje, mimo że Google publicznie temu zaprzeczało. Atrybut z leak'a potwierdza, że jest jeden wskaźnik per domena, który wpływa na ranking wszystkich podstron. Dlatego nie warto trzymać sklepu w jednej domenie i bloga w innej — rozdrabniasz autorytet.
NavBoost używa danych z Chrome. Dane o klikalności, czasach sesji, pogo-stickingu trafiają do rankingu. To znaczy, że UX = SEO, dosłownie. Powolny checkout, broken filter, mobile bug — to nie tylko UX problem, to też SEO problem.
OriginalContentScore jest mierzony per strona, nie per witryna. Jedna karta produktu z opisem skopiowanym od producenta nie zaszkodzi całemu sklepowi. Ale 5000 kart z kopią = tak.
hostAge + siteFocusScore — Google premiuje witryny tematycznie spójne i o ustabilizowanym autorytecie. Nie rozszerzaj sklepu rowerowego o sprzedaż suplementów diety pod tą samą domeną. Lepiej osobna marka.
E-E-A-T to nie jest marketingowy buzzword — to konkretny zbiór sygnałów, które w 80% sprowadzają się do kodu, schemy i konfiguracji. Marketing dorzuca pozostałe 20% (treści ekspertów, opinie, autorzy), ale bez technicznego fundamentu nawet najlepsze treści nie przebiją się przez ranking.
Najtańsza i najszybsza wygrana dla większości sklepów: pełne, poprawne JSON-LD na wszystkich typach stron (Organization, Product z return policy, Article z Person, BreadcrumbList). To tydzień pracy deva, który daje sygnały trudne do uzyskania jakąkolwiek inną drogą.