Przejdź do treści

Schema.org w Next.js: LocalBusiness, Service i FAQ

Schema.org na stronie usługowej to coś więcej niż gwiazdki. Zobacz, jak poprawnie wdrożyć LocalBusiness, FAQ oraz Service, by zyskać cytowania w AI.

Maciej Sala

Founder StriveLab

4 min czytaniaOpublikowano 10 kwietnia 2026 (Aktualizacja 7 lipca 2026)

na stronie usługowej zaczyna się od trzech schematów, jakimi są LocalBusiness lub ProfessionalService, Service i BreadcrumbList. Z kolei FAQ, Review i AggregateRating dodawaj dopiero wtedy, gdy użytkownik naprawdę widzi taką treść na stronie i gdy mieści się ona w odpowiednich wytycznych Google.

LocalBusiness i ProfessionalService dla strony usługowej

Schemat LocalBusiness (lub ProfessionalService) dostarcza Google najważniejszych informacji o Twojej firmie, takich jak lokalizacja, dane kontaktowe, godziny otwarcia i branża. Dzięki niemu Google może wyświetlać Twoją firmę w wynikach lokalnych, panelach wiedzy i innych rozszerzonych formatach, budując zaufanie i ułatwiając użytkownikom znalezienie Twoich usług. Ważne, by wszystkie informacje były zgodne ze stanem faktycznym i precyzynie opisywały firmę.

Code
// components/schema/business-schema.tsx
export function BusinessSchema() {
  const data = {
    '@context': 'https://schema.org',
    '@type': 'ProfessionalService',
    '@id': 'https://example.com/#organization',
    name: 'Acme — Tworzenie stron internetowych Next.js',
    alternateName: 'Acme',
    description:
      'Projektujemy i budujemy szybkie strony internetowe w Next.js dla firm, freelancerów i startupów. SEO, wydajność i nowoczesny design.',
    url: 'https://example.com',
    logo: 'https://example.com/logo.png',
    image: 'https://example.com/og-image.jpg',
    telephone: '+48-XXX-XXX-XXX',
    email: 'kontakt@example.com',
    address: {
      '@type': 'PostalAddress',
      streetAddress: 'ul. Przykładowa 10',
      addressLocality: 'Kraków',
      postalCode: '30-001',
      addressRegion: 'Małopolska',
      addressCountry: 'PL',
    },
    geo: {
      '@type': 'GeoCoordinates',
      latitude: 50.0647,
      longitude: 19.945,
    },
    areaServed: [
      { '@type': 'City', name: 'Kraków' },
      { '@type': 'Country', name: 'Polska' },
    ],
    priceRange: '$$',
    currenciesAccepted: 'PLN, EUR',
    paymentAccepted: 'Przelew bankowy, Faktura VAT',
    openingHoursSpecification: [
      {
        '@type': 'OpeningHoursSpecification',
        dayOfWeek: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
        opens: '09:00',
        closes: '17:00',
      },
    ],
    sameAs: ['https://linkedin.com/company/acme', 'https://github.com/acme'],
    knowsAbout: ['Next.js', 'React', 'SEO', 'Web Development', 'TypeScript'],
    hasOfferCatalog: {
      '@type': 'OfferCatalog',
      name: 'Usługi webowe',
      itemListElement: [
        {
          '@type': 'OfferCatalog',
          name: 'Strony internetowe',
          itemListElement: [
            {
              '@type': 'Offer',
              itemOffered: {
                '@type': 'Service',
                name: 'Strona wizytówkowa Next.js',
                description: 'Szybka, responsywna strona firmowa z SEO i CMS.',
              },
            },
            {
              '@type': 'Offer',
              itemOffered: {
                '@type': 'Service',
                name: 'Landing page dla Google Ads',
                description:
                  'Strona zoptymalizowana pod konwersje z kampanii PPC.',
              },
            },
          ],
        },
      ],
    },
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{
        __html: JSON.stringify(data).replace(/</g, '\\u003c'),
      }}
    />
  )
}

Service Schema: opis usługi w JSON-LD

Każda usługa oferowana na Twojej stronie powinna być opisana za pomocą osobnego schematu Service. Właśnie taki typ danych strukturalnych pozwala Google precyzyjnie zrozumieć, jakie konkretne usługi świadczysz, kto je dostarcza (Twoja firma), a także potencjalne ceny oraz obszar działania. Poprawne wdrożenie Service Schema zwiększa szanse na pojawienie się Twoich usług w wynikach rozszerzonych i bezpośrednich odpowiedziach wyszukiwarek.

Code
// components/schema/service-schema.tsx
interface ServiceSchemaProps {
  name: string
  description: string
  url: string
  price?: string
  image?: string
}
 
export function ServiceSchema({
  name,
  description,
  url,
  price,
  image,
}: ServiceSchemaProps) {
  const data = {
    '@context': 'https://schema.org',
    '@type': 'Service',
    name,
    description,
    url: `https://example.com${url}`,
    provider: {
      '@type': 'ProfessionalService',
      name: 'Acme',
      '@id': 'https://example.com/#organization',
    },
    areaServed: {
      '@type': 'Country',
      name: 'Polska',
    },
    ...(price && {
      offers: {
        '@type': 'Offer',
        price,
        priceCurrency: 'PLN',
      },
    }),
    ...(image && { image }),
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{
        __html: JSON.stringify(data).replace(/</g, '\\u003c'),
      }}
    />
  )
}

Użycie na stronie usługi:

Code
// app/uslugi/strony-internetowe/page.tsx
export default function WebsitesPage() {
  return (
    <main>
      <ServiceSchema
        name="Strony internetowe w Next.js"
        description="Projektuję i buduję nowoczesne strony internetowe z Next.js — szybkie, responsywne, zoptymalizowane pod SEO."
        url="/uslugi/strony-internetowe"
        price="3000"
      />
      <h1>Strony internetowe w Next.js</h1>
      {/* ... treść strony */}
    </main>
  )
}

FAQ Schema na stronach usługowych w Next.js

Rich results (po polsku: wyniki z elementami rozszerzonymi lub wyniki wzbogacone) to rozszerzone formy prezentacji stron w wynikach wyszukiwania Google — wyróżniają się na tle standardowych linków dodatkowymi informacjami, takimi jak gwiazdki z ocenami, zdjęcia, ceny produktów czy przepisy.

Aktualizacja: od 7 maja 2026, Google całkowicie wycofało wyniki wzbogacone dla FAQ i dlatego rozwijane pytania nie pojawiają się już w wynikach wyszukiwania. Wcześniej były ograniczone do wybranych, autorytatywnych domen (rządowych lub zdrowotnych).

Należy jednak pamietać, że schemat FAQPage nadal opisuje treść w sposób czytelny dla wyszukiwarek i modeli AI (asystenci, wyszukiwanie generatywne coraz częściej sięgają po ustrukturyzowane pytania i odpowiedzi). Jeśli sekcja FAQ jest naprawdę widoczna na stronie i odpowiada na realne pytania klientów, FAQPage wciąż wnosi wartość, ale dla maszyn.

Sam schemat to typ FAQPage z listą Question, z których każde ma dokładnie jedną acceptedAnswer. Warto zbudować go z tej samej tablicy danych, która zasila widoczną sekcję FAQ — dzięki temu schemat i treść nigdy się nie rozjadą:

Code
// components/schema/faq-schema.tsx
interface FaqItem {
  question: string
  answer: string
}
 
export function FaqSchema({ items }: { items: FaqItem[] }) {
  const data = {
    '@context': 'https://schema.org',
    '@type': 'FAQPage',
    mainEntity: items.map((item) => ({
      '@type': 'Question',
      name: item.question,
      acceptedAnswer: {
        '@type': 'Answer',
        text: item.answer,
      },
    })),
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{
        __html: JSON.stringify(data).replace(/</g, '\\u003c'),
      }}
    />
  )
}

Na stronie renderujesz schemat z tej samej tablicy co widoczną sekcję FAQ:

Code
// app/uslugi/page.tsx
import { FaqSection } from '@/components/faq-section'
import { FaqSchema } from '@/components/schema/faq-schema'
 
const serviceFaqs = [
  {
    question: 'Ile kosztuje strona internetowa w Next.js?',
    answer:
      'Ceny zaczynają się od 3000 PLN za prostą stronę wizytówkową. Strony z CMS, sklepem lub zaawansowaną funkcjonalnością kosztują 5000–15000 PLN. Wycena zależy od zakresu projektu.',
  },
  {
    question: 'Jak długo trwa realizacja strony?',
    answer:
      'W wypadku prostej strona wizytówkowej około 2 tygodni. Strona z CMS i blogiem, około 3–5 tygodni, a sklep internetowy lub aplikacja webowa może trwać od 6–12 tygodni.',
  },
  {
    question: 'Czy strona będzie zoptymalizowana pod SEO?',
    answer:
      'Tak, każda ze strona jest budowana z myślą o SEO. Obejmuje to szybkość ładowania (Core Web Vitals), poprawną strukturę HTML, meta tagi, dane strukturalne Schema.org i konfigurację Google Search Console.',
  },
  {
    question: 'Czy mogę samodzielnie edytować treści na stronie?',
    answer:
      'Tak — integruję headless CMS (Sanity, Strapi, WordPress), który pozwala edytować teksty, zdjęcia i dodawać wpisy blogowe bez znajomości programowania.',
  },
  {
    question: 'Dlaczego Next.js, a nie WordPress?',
    answer:
      'Next.js daje lepszą wydajność (szybsze ładowanie), bezpieczeństwo (brak podatności WordPress), elastyczność (dowolny design) i skalowalność. WordPress nadal ma sens dla prostych blogów z ograniczonym budżetem.',
  },
]
 
export default function ServicesPage() {
  return (
    <main>
      <h1>Usługi</h1>
      {/* ... opis usług */}
      <FaqSchema items={serviceFaqs} />
      <FaqSection items={serviceFaqs} />
    </main>
  )
}

Review i AggregateRating: kiedy wolno używać opinii?

Google nie promuje tak zwanych self-serving reviews, co oznacza, że gwiazdki dla własnej strony usługowej lub LocalBusiness nie kwalifikują się do wyświetlania w wynikach wzbogaconych. Dane typu Review i AggregateRating należy dodawać wyłącznie wtedy, gdy opinie są autentyczne, widoczne bezpośrednio na stronie i pochodzą z wiarygodnego procesu zbierania recenzji. W przeciwnym razie, fałszywe lub wprowadzające w błąd recenzje mogą skutkować manualną karą od Google, co negatywnie wpłynie na widoczność całej domeny.

Code
function ReviewsSchema({ reviews }: { reviews: Review[] }) {
  const avgRating =
    reviews.reduce((sum, r) => sum + r.rating, 0) / reviews.length
 
  const data = {
    '@context': 'https://schema.org',
    '@type': 'ProfessionalService',
    name: 'Acme',
    aggregateRating: {
      '@type': 'AggregateRating',
      ratingValue: avgRating.toFixed(1),
      bestRating: '5',
      worstRating: '1',
      ratingCount: reviews.length,
    },
    review: reviews.map((r) => ({
      '@type': 'Review',
      author: { '@type': 'Person', name: r.author },
      datePublished: r.date,
      reviewBody: r.text,
      reviewRating: {
        '@type': 'Rating',
        ratingValue: r.rating,
        bestRating: '5',
      },
    })),
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{
        __html: JSON.stringify(data).replace(/</g, '\\u003c'),
      }}
    />
  )
}

Na końcu jest BreadcrumbList, który opisuje pozycję strony w hierarchii serwisu i, w odróżnieniu od FAQ czy sitelinks searchbox, nadal generuje widoczny wynik wzbogacony. Mowa tutaj o ścieżce okruszków zamiast surowego URL-a w wynikach Google. Dlatego własnie, buduj BreadcrumbList dla każdej strony, z listy ListItem z rosnącą position:

Code
// components/schema/breadcrumb-schema.tsx
interface Crumb {
  name: string
  url: string
}
 
export function BreadcrumbSchema({ items }: { items: Crumb[] }) {
  const data = {
    '@context': 'https://schema.org',
    '@type': 'BreadcrumbList',
    itemListElement: items.map((item, index) => ({
      '@type': 'ListItem',
      position: index + 1,
      name: item.name,
      item: `https://example.com${item.url}`,
    })),
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{
        __html: JSON.stringify(data).replace(/</g, '\\u003c'),
      }}
    />
  )
}

Ostatni ListItem (bieżąca strona) może mieć item wskazujący na własny URL albo pominąć to pole — Google akceptuje obie formy.

Czytelna i uporządkowana WebSite Schema

WebSite porządkuje dane o serwisie, ale nie dodawaj SearchAction, ponieważ pole wyszukiwania w wynikach Google (sitelinks searchbox), które ten schemat obsługiwał, Google wycofało w listopadzie 2024. Zostaw WebSite w minimalnej formie:

Code
function WebsiteSchema() {
  const data = {
    '@context': 'https://schema.org',
    '@type': 'WebSite',
    name: 'Acme',
    url: 'https://example.com',
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{
        __html: JSON.stringify(data).replace(/</g, '\\u003c'),
      }}
    />
  )
}

Centralizacja Schema.org w layoucie Next.js

Code
// app/layout.tsx
import { BusinessSchema } from '@/components/schema/business-schema'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="pl">
      <body>
        <BusinessSchema />
        {children}
      </body>
    </html>
  )
}

Schematy globalne (LocalBusiness, WebSite) umieść w root layout, a schematy per-strona (Service, FAQ, Article) umieść w poszczególnych page.

Audyt techniczny i optymalizacja pod kątem SEO i GEO.
Audyt techniczny SEO

Często zadawane pytania

Które schematy Schema.org są najważniejsze dla strony usługowej?

Fundament to LocalBusiness (lub ProfessionalService) opisujący firmę, Service opisujący każdą usługę oraz BreadcrumbList. FAQ, Review i AggregateRating dodawaj wyłącznie wtedy, gdy realnie odpowiadają treści strony i mieszczą się w aktualnych wytycznych Google. W innym wypadku, ryzykiem jest utrata wyników wzbogaconych na całej domenie.

Czy FAQ schema pokaże rozwijane pytania w wynikach Google?

Nie. Google całkowicie wycofało wyniki wzbogacone dla FAQ od 7 maja 2026. Aktualnie, rozwijane pytania nie pojawiają się już w wynikach wyszukiwania. Schemat FAQPage nadal warto wdrożyć, jeśli sekcja pytań jest realnie widoczna na stronie, ale wyłącznie jako czytelny dla wyszukiwarek i modeli AI opis treści.

Czy mogę dodać gwiazdki Review do własnej strony usługowej?

Google nie promuje tzw. self-serving reviews, więc gwiazdki dla własnej strony usługowej lub LocalBusiness często nie kwalifikują się do wyników wzbogaconych. Dane Review i AggregateRating dodawaj tylko, gdy opinie są prawdziwe, widoczne na stronie i pochodzą z realnego procesu zbierania recenzji, ponieważ fałszywe opinie grożą karą manualną. Taka kara może bardzo zaboleć.

Jak wdrożyć dane strukturalne w Next.js App Router?

Dane strukturalne to komponenty React renderujące <script type="application/ld+json">. Schematy globalne — LocalBusiness, WebSite — umieść w root layout. Schematy per-strona — Service, FAQ, Article — w poszczególnych page. Zawsze escapuj znak < przez \\u003c, by uniknąć wstrzyknięcia HTML.

Jak często aktualizować dane strukturalne?

Przy każdej zmianie informacji biznesowych: adres, godziny, usługi, cennik. Dane strukturalne muszą zawsze odzwierciedlać aktualny stan strony — niespójność między schematem a widoczną treścią może skutkować utratą rich snippets.

O autorze

Maciej Sala

Maciej Sala — Product Manager i Frontend Developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwijam własne projekty.

Pomagam przekładać takie tematy na konkretne wdrożenia w frontendzie, SEO, analityce i procesie produktowym.

Skontaktuj się ze mną

Biblioteka wiedzy

Czytaj dalej

Zobacz więcej wpisów
SEO w Astro — Core Web Vitals, dane uporządkowane i techniczny fundament rankingu w 2026

Astro dostarcza przyjazność SEO już na poziomie architektury, gwarantując świetne wyniki w Lighthouse dzięki brakowi domyślnego JavaScriptu i statycznemu renderowaniu HTML. Jednak prawdziwa widoczność w Google oraz systemach AI to efekt świadomych decyzji inżynieryjnych, a nie tylko wyboru frameworka. W tym artykule rozbieram na części pierwsze każdą z nich: od Core Web Vitals, przez metadane i schema.org , aż po optymalizację GEO / AEO .

Maciej Sala

Maciej Sala

Founder StriveLab

Programmatic SEO z Next.js i AI — jak generować tysiące zoptymalizowanych stron

Klasyczne SEO skaluje się jednym sposobem: więcej ludzi piszących więcej artykułów. W 2026 roku, dzięki Next.js z ISR / SSG i modelom AI do treści, ta reguła się zmienia. Teraz nawet mała firma ma szansę pokryć rynek long-tail , na który nigdy nie opłacałoby się pisać ręcznie. Kluczem jest wiedzieć, jak to zrobić, ponieważ nie każda serwowana Google treść jest indeksowana...

Maciej Sala

Maciej Sala

Founder StriveLab

Google Search Console + Next.js — indeksacja, błędy, performance i co z nimi robić

Trudno wyobrazić sobie współczesną analitykę bez Google Search Console GSC , czyli podstawowego narzędzia pokazującego dane bezpośrednio z Google Search. PageSpeed Insights mierzy wydajność, Ahrefs śledzi backlinki, ale GSC pokazuje całą paletę danych ale też problemów/błędów dotyczących strony internetowej. Przykładowo, które strony są zaindeksowane, jakie błędy crawlowania występują, na jakie frazy rankujesz i jakie wyniki Core Web Vitals Dane Core Web Vitals w GSC pochodzą z Chrome UX Report, czyli realnych wizyt użytkowników, a nie z pojedynczego testu laboratoryjnego Lighthouse. mają istniejący użytkownicy.

Maciej Sala

Maciej Sala

Founder StriveLab