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)logoalsImageObjectmit width/heightcontactPoint, Telefon, E-Mail,areaServed,availableLanguagesameAs, 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:
- DevStudio.it →
https://devstudioit.com/{locale} - Blog →
https://devstudioit.com/{locale}/blog - 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,dateModifiedauthor(Person oder Organization mit Autor-URL)publishermit Organization-LogomainEntityOfPage→ Canonicalimage, absolute OG-URLinLanguage,pl-PL,en-US,de-DEwordCountaus 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:
BreadcrumbListBlogPostingFAQPage(wennfaqItems.length > 0)WebPagemitmainEntity→#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:
translationsfürpl | en | debaseUrl = '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
- Rich Results Test öffnen.
- Produktions-URL eingeben (z. B.
https://devstudioit.com/de/blog/json-ld-schema-org-seo-strona-firmowa-2026). - Typen prüfen: Article/BlogPosting, FAQ, Breadcrumb.
- 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.parsedes Skripts, trailing comma bricht alles- FAQ-Zahl im DOM vs. FAQPage
mainEntity
Typische Fehler auf Unternehmensseiten
- Eine Organization ohne Locale, schwächeres Signal für DE/EN.
- Doppeltes BlogPosting, Plugin + manuelles Skript.
- FAQPage ohne sichtbare FAQ, auch
display:noneproblematisch. - Relative URLs in
imageunditem, absolutehttps://nötig. - author ohne URL, Person mit
urlstärkt E-E-A-T. - dateModified = datePublished immer,
updatedim 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
- Produktions-URL einfügen (nicht localhost, nicht Preview ohne Index).
- „Test URL“, Google fetcht gerendertes HTML von Vercel Edge.
- Prüfen: Artikel (BlogPosting), FAQ (falls Sektion), Breadcrumbs.
- Warnungen lesen: „optional field missing“ oft OK; „invalid object“ immer fixen.
- 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.)
- Homepage je Locale, Organization + WebSite.
- Ein Blogartikel, BlogPosting, Breadcrumb, FAQ.
- Ein Service-Landing, WebPage/Service.
- Search Console URL Inspection.
dateModifiedvs Frontmatterupdatednach 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?
Ü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 und Referenzen.
