[ ENGINEERING_GUIDE ][ JSON-LD ][ SCHEMA.ORG ][ SEO ][ NEXTJS ]

JSON-LD und Schema.org — SEO für Unternehmenswebsites in Next.js (Leitfaden 2026)

10. Juni 20269 Min. Lesezeit
Autor: DevStudio.itWeb & KI Studio

Organization, WebSite, BreadcrumbList, BlogPosting und FAQPage — App Router-Implementierung, getStructuredData, hreflang und Rich-Results-Tests für mehrsprachige Dienstleistungsseiten.

READ_TIME: 9 MIN_COMPLEXITY: MED_
STAMP: VERIFIED_BY_DS_

TL;DR

JSON-LD ist der einfachste Weg, Google mitzuteilen, dass Ihre Site ein Dienstleister mit Blog ist — nicht ein zufälliger Haufen von Divs. Auf produktivem Next.js 15 (App Router) reichen fünf Typen: Organization und WebSite im Locale-Layout (getStructuredData in src/lib/structured-data.ts), BreadcrumbList + BlogPosting auf Blogartikeln und FAQPage, wenn im Markdown eine FAQ-Sektion steht. Jede Sprachversion (/pl, /en, /de) braucht eigenes JSON-LD mit korrektem inLanguage und hreflang in den Metadaten — kein globaler englischer Block. Testen mit Rich Results Test und Search Console, nicht nur „Skript im DOM?“.

Für wen das ist

  • Dienstleistungsunternehmen mit mehrsprachiger Next.js App Router-Website
  • Entwickler, die technisches SEO ohne WordPress-Plugins umsetzen
  • Teams mit Meta Title/Description, aber ohne Rich Snippets und konsistente Organisation-Entität
  • Corporate-Blog-Autoren, die echtes BlogPosting wollen, nicht nur og:article

Keywords (SEO)

json-ld schema.org unternehmenswebsite, structured data nextjs 2026, organization website breadcrumblist blogposting, faqpage seo, google rich results test, hreflang json-ld

Warum JSON-LD, nicht Microdata im HTML

Google unterstützt offiziell drei Formate: JSON-LD, Microdata und RDFa. In React/Next.js gewinnt fast immer JSON-LD in <script type="application/ld+json">:

Format Vorteile Nachteile in Next.js
JSON-LD Getrennt vom JSX, einfach aus Daten Ein JSON-Fehler = ganzer Block ignoriert
Microdata „Sichtbar“ im HTML Attribute in Komponenten, Refactoring schwer
RDFa Selten Geringe Adoption im React-Ökosystem

JSON-LD ersetzt keinen guten Content — ohne JSON-LD erkennt Google oft nicht, dass DevStudio.it dieselbe Firma wie das Footer-Logo ist oder dass /de/blog/... ein Blogpost ist.

Fünf Typen, die Unternehmensseiten wirklich helfen

1. Organization — die Firmenentität

Organization beschreibt den wirtschaftlichen Auftritt: Name, Logo, Kontakt, Services, Angebote. Im DevStudio.it-Projekt liefert getStructuredData(locale) in src/lib/structured-data.ts ein Objekt mit @type: Organization, @id (https://devstudioit.com/#organization), contactPoint, sameAs, service-Liste und offers.

Wichtige Felder für Dienstleister:

  • @id — stabile ID; andere Typen verweisen darauf (publisher, provider)
  • logo als ImageObject mit width/height
  • contactPoint — Telefon, E-Mail, areaServed, availableLanguage
  • sameAs — LinkedIn, GitHub, Twitter

Hinweis: aggregateRating bei Organization wird oft geprüft — ohne echte Bewertungen laut Google-Richtlinie keine Sterne „hardcoded“. Im Repo kommen Reviews über getReviewStructuredData aus Testimonials auf der Seite.

2. WebSite — Website und SearchAction

WebSite verbindet Domain und Organisation: name, url, inLanguage, publisher. Optional SearchAction über potentialAction bei Suche (/search?q=).

In getStructuredData enthält inLanguage ['pl', 'en', 'de']. Die WebSite-url zeigt auf die Locale-Root (https://devstudioit.com/de, etc.).

3. BreadcrumbList — Pfad in Suchergebnissen

BreadcrumbList ist eine itemListElement-Liste 1…n. Im Blog baut src/app/[locale]/blog/[slug]/page.tsx:

  1. DevStudio.it → https://devstudioit.com/{locale}
  2. Blog → https://devstudioit.com/{locale}/blog
  3. Artikeltitel → Canonical des Posts

Jedes Element: @type: ListItem, position, name, item (volle URL). UI-Breadcrumbs und JSON-LD sollten dieselbe Hierarchie haben.

4. BlogPosting — Artikel, nicht generische WebPage

Für Blogposts BlogPosting (oder Article), nicht nur WebPage. articleJsonLd enthält:

  • headline, description, datePublished, dateModified
  • author (Person oder Organization mit Autor-URL)
  • publisher mit Organization-Logo
  • mainEntityOfPage → Canonical
  • image — absolute OG-URL
  • inLanguagepl-PL, en-US, de-DE
  • wordCount aus Markdown
  • optional speakable

Canonical muss identisch zu alternates.canonical in generateMetadata sein.

5. FAQPage — nur mit FAQ im Content

Google FAQPage verlangt echte Fragen und Antworten sichtbar für Nutzer. Hier parst getBlogFaq(post.content) die ## FAQ-Sektion — jedes ### Frage plus Antwortabsatz.

FAQ nur in JSON-LD ohne Seiteninhalt riskiert Manual Action wegen Structured-Data-Spam. Immer: Content zuerst, JSON-LD danach.

Implementierung in Next.js App Router

Locale-Layout — Organization + WebSite

In src/app/[locale]/layout.tsx nach getStructuredData(locale):

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{
    __html: JSON.stringify(structuredData.organization),
  }}
/>
<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{
    __html: JSON.stringify(structuredData.website),
  }}
/>

Zusätzlich hostingService als Service und getReviewStructuredData aus Testimonials.

Server Components — JSON-LD serverseitig, kein useEffect. Wichtig für Crawler und erstes HTML vom Edge.

Blog-Post — mehrere JSON-LD-Blöcke

Auf [slug]/page.tsx typisch vier Skripte:

  1. BreadcrumbList
  2. BlogPosting
  3. FAQPage (wenn faqItems.length > 0)
  4. WebPage mit mainEntity#article

Mehrere Blöcke sind korrekt — Google verknüpft über @id und URL. Alternative: ein @graph; in Next.js sind separate <script> oft klarer.

getStructuredData — eine Datei, drei Locales

src/lib/structured-data.ts hält organization-Übersetzungen und baut vollständige schema.org-Objekte:

  • translations für pl | en | de
  • baseUrl = 'https://devstudioit.com'
  • Locale-URL: pl/pl, sonst /{locale}

Neue Service auf der Marketing-Site → structured data mitaktualisieren.

hreflang und JSON-LD — parallele Signale

hreflang steht in HTML-Metadaten (alternates.languages), nicht in JSON-LD. Für den Blog verknüpft getBlogPostHreflangLanguages Posts über translationId im Frontmatter — gleiche translationId in allen drei Markdown-Dateien.

Signal Ort Botschaft an Google
hreflang <link rel="alternate" hreflang="..."> „Diese Inhalte haben PL/EN/DE-Pendants“
inLanguage in BlogPosting JSON-LD „Dieser Artikel ist deutsch“
Canonical Meta + JSON-LD mainEntityOfPage „Offizielle URL dieser Version“

Fehler: hreflang zeigt /de/blog/falscher-slug, Canonical und JSON-LD einen anderen — geteilte Signale, oft kein Rich Result.

Für die Firmenhomepage: jedes Locale mit Organization-url https://devstudioit.com/{locale}.

Testen — Rich Results und mehr

Google Rich Results Test

  1. Rich Results Test öffnen.
  2. Produktions-URL eingeben (z. B. https://devstudioit.com/de/blog/json-ld-schema-org-seo-strona-firmowa-2026).
  3. Typen prüfen: Article/BlogPosting, FAQ, Breadcrumb.
  4. Kritische Fehler beheben.

Test liest gerendertes HTML — funktioniert auf Vercel Production. Preview-URLs oft andere env/robots — Structured Data auf devstudioit.com testen.

Schema Markup Validator (schema.org)

Prüft Spec-Konformität, nicht nur Google Rich Results. Hilfreich bei komplexem Organization mit offers.

Search Console

Nach Deploy: Enhancements → FAQ, Articles. „Valid“ ≠ garantiertes Rich-Snippet-UI — „Error“ immer fixen.

DevTools — Checkliste

  • View Source — JSON-LD im ersten HTML
  • JSON.parse des Skripts — trailing comma bricht alles
  • FAQ-Zahl im DOM vs. FAQPage mainEntity

Typische Fehler auf Unternehmensseiten

  1. Eine Organization ohne Locale — schwächeres Signal für DE/EN.
  2. Doppeltes BlogPosting — Plugin + manuelles Skript.
  3. FAQPage ohne sichtbare FAQ — auch display:none problematisch.
  4. Relative URLs in image und item — absolute https:// nötig.
  5. author ohne URL — Person mit url stärkt E-E-A-T.
  6. dateModified = datePublished immer — updated im Frontmatter vergessen.

Erweiterungen — wann mehr Typen

Typ Wann Hinweis
LocalBusiness Standort + Karte, NAP Adresse und Öffnungszeiten
Service Service-Landing provider → Organization @id
HowTo Schritt-für-Schritt getHowToStructuredData auf Homepage
SoftwareApplication SaaS im Portfolio eigene Funktion in structured-data.ts

Nicht alles auf jeder Seite — Relevanz zählt.

Performance und Sicherheit

JSON-LD ist leicht (wenige bis einige Dutzend KB). Nicht von externer API zur Laufzeit laden — statisch mit SSG/ISR generieren. dangerouslySetInnerHTML ist hier beabsichtigt; Daten stammen aus eigenem Code, nicht aus User Input (Frontmatter liegt im Repo).

Sehr große Organization mit vielen offers — Liste auf Top-Angebote kürzen: kleineres HTML, gleiches Business-Signal.

JSON-LD auf Service-Landingpages

Neben dem Blog structured data auf Landings wie /de/strony-www ausgeben. Minimum: WebPage mit about auf Service oder Organization @id. Beschreibt die Landing eine Dienstleistung mit Preis „ab X €“, verstärkt Offer mit priceCurrency und provider das Service-SEO — ohne falsches LocalBusiness bei remote-first Firmen.

In getStructuredData soll die service-Liste in Organization dieselben Leistungen abdecken wie die Navigation. Widerspruch („Chatbots im Menü, nur Websites in JSON-LD“) schwächt die Entität. Bei neuem Landing: (1) Content + Meta, (2) hreflang bei Mehrsprachigkeit, (3) Service-JSON-LD oder WebPage-Link zur globalen Organization.

Implementierungsdetails in page.tsx (Blog)

Die Blog-Seite src/app/[locale]/blog/[slug]/page.tsx berechnet wordCount aus Markdown-Body — dieses Feld erscheint im BlogPosting-JSON-LD und hilft Suchmaschinen die Tiefe des Artikels einzuschätzen. speakable mit cssSelector auf .blog-content h2, h3, p ist optional für Sprachassistenten; es schadet nicht, wenn die Selektoren im gerenderten HTML existieren.

faqJsonLd wird nur erzeugt, wenn getBlogFaq Einträge liefert — leeres FAQ im Markdown bedeutet kein FAQPage-Skript. Das verhindert leere mainEntity-Arrays, die Validator-Warnungen erzeugen.

webPageJsonLd ergänzt BlogPosting: die Seite ist WebPage, die Hauptentität ist der Artikel unter #article. Diese Trennung ist gängig in Next.js-Projekten und entspricht Google-Empfehlungen für Artikel-URLs.

hreflang im Blog — translationId praktisch

Jeder Post in content/blog/{locale}/ hat Frontmatter translationId — identisch über PL/EN/DE für Übersetzungen. getBlogPostHreflangLanguages baut die Map pl, en, de → absolute URLs. Fehlt eine Sprachversion, hreflang für diese Locale fehlt — kein erfundener Link.

Beim Anlegen eines neuen Artikels: zuerst translationId festlegen, dann drei Markdown-Dateien mit gleichem ID — JSON-LD und hreflang bleiben synchron ohne manuelle URL-Listen.

Rich Results Test — Schritt-für-Schritt

  1. Produktions-URL einfügen (nicht localhost, nicht Preview ohne Index).
  2. „Test URL“ — Google fetcht gerendertes HTML von Vercel Edge.
  3. Prüfen: Artikel (BlogPosting), FAQ (falls Sektion), Breadcrumbs.
  4. Warnungen lesen: „optional field missing“ oft OK; „invalid object“ immer fixen.
  5. Nach Deploy erneut testen — ISR/SSG kann ersten Fetch verzögern.

Schema.org Validator parallel: strenger bei nested offers in Organization (wie in structured-data.ts). Fehler dort können Rich Results trotzdem passieren — beide Tools nutzen.

Typische Fehler im Detail

Doppeltes @id: Zwei Organization-Blöcke mit gleichem @id aber unterschiedlichen name — Google kann Entität verwerfen. Eine Quelle: getStructuredData.

image nur relative Pfad: /og-image-large.png in JSON-LD ohne https://devstudioit.com — Rich Results Test markiert als Fehler. Im Code immer absolute URLs wie in articleJsonLd.

FAQ nur auf Englisch in JSON-LD, UI auf Deutsch — Policy-Risiko. FAQPage-Text muss der sichtbaren Sprache der Seite entsprechen (inLanguage konsistent).

Structured-Data-Audit vor Launch (15 Min.)

  1. Homepage je Locale — Organization + WebSite.
  2. Ein Blogartikel — BlogPosting, Breadcrumb, FAQ.
  3. Ein Service-Landing — WebPage/Service.
  4. Search Console URL Inspection.
  5. dateModified vs Frontmatter updated nach Content-Edit.

Ergebnisse im Deploy-Ticket speichern — erleichtert „SEO durch diesen PR kaputt?“.

Zusammenspiel mit Open Graph und Twitter Cards

JSON-LD ergänzt — nicht ersetzt — openGraph und twitter in generateMetadata auf Blog-Posts. OG liefert Social-Preview; BlogPosting liefert Such-Signale. ogImage im Frontmatter sollte dieselbe absolute URL wie image in BlogPosting verwenden (post.ogImage oder Fallback /og-image-large.png). Inkonsistente Bilder verwirren QA, obwohl Google oft nur JSON-LD für Rich Results nutzt.

FAQ

Zeigt Google immer Sterne und FAQ?

Nein. Structured Data = Berechtigung, keine UI-Garantie. FAQ Rich Results sind eingeschränkt — korrektes FAQPage trotzdem sinnvoll für AEO.

Ein Skript oder mehrere?

Beides OK. In Next.js mehrere <script type="application/ld+json"> bei bedingtem FAQPage klarer.

JSON-LD nur im <head>?

Google liest JSON-LD in head und body. App Router rendert oft in Page-Komponenten — OK bei SSR.

BlogPosting mit Organization verknüpfen?

publisher: { '@type': 'Organization', ... } und globale Organization @id. Optional isPartOf: WebSite.

Ersetzt hreflang übersetztes JSON-LD?

Nein. hreflang verknüpft URLs; JSON-LD beschreibt Inhalt unter einer URL. Beides nötig.

Zusammenfassung

Unternehmens-SEO 2026: Entitätsschicht (Organization, WebSite) plus per-page Typen (BreadcrumbList, BlogPosting, FAQPage). In Next.js App Router Generatoren in src/lib/structured-data.ts und Blog-page.tsx, Canonical, hreflang und inLanguage synchron, auf Produktion mit Rich Results Test prüfen. Ohne sichtbares FAQ kein FAQPage — Structured Data unterstützt Marketing, ersetzt keinen ehrlichen Content.

Structured Data für Ihre Website?

  • Kontakt — JSON-LD- und hreflang-Audit für Ihre Domain
  • Websites — Next.js, technisches SEO und Rich Results ab dem ersten Release
  • Blog — weitere Leitfäden zu Performance und Conversion

Über den Autor

Wir bauen schnelle Websites, Web/Mobile-Apps, KI-Chatbots und Hosting — mit Fokus auf SEO und Conversion.

Empfohlene Links

Von Theorie zu Produktion — Branchly, Hosting-Stack, Betreuung und Referenzen.

GEFÄLLT EUCH UNSERE ARCHITEKTUR DES DENKENS? LASST UNS GEMEINSAM BAUEN.

[ PROJEKT_KONFIGURATION_STARTEN ]