Zum Inhalt springen
Von Aktualisiert am 20 Min. Lesezeit Desarrollo Web

JavaScript SEO: Diagnose und Lösungen für React, Next.js, Vue und Nuxt

SVG- und CSS-Code in einem Editor mit dunklem Hintergrund

JavaScript schadet deinem SEO nicht von selbst. Google führt JavaScript aus, sogar für Titel und Canonical. Riskant wird es, wenn wichtige Inhalte erst nach dem Rendern existieren, wenn der Server für jede URL Status 200 liefert oder wenn Links keine echten Adressen haben. Dazu kommt ein zweiter Punkt: Nicht jeder Bot führt JavaScript aus. Ob du ein Problem hast, klärst du in fünf Minuten mit dem Vergleich von Quelltext und gerenderter Seite.

Dieser Beitrag richtet sich an SEOs und an Entwickler. Zuerst kommt die Diagnose, danach acht Fehlerbilder mit Code, dann Next.js, Nuxt, Vue und React ohne Framework sowie Astro. Gelesen haben wir die Dokumentationen am 5. November 2026: Next.js 16.4, Nuxt 4.6, React 19.3. Die Codebeispiele liefen am selben Tag mit Next.js 16.4.3, Nuxt 4.6.2, React 19.3.0 und Astro 7.4.2.

Welche Rendering-Art welches Risiko hat

Die entscheidende Frage lautet: Steht der Inhalt im HTML, das der Server schickt? Die Einordnung in der Spalte „Risiko für SEO“ ist unsere Einschätzung, keine Messung.

ArtWo das HTML entstehtRisiko für SEOPasst für
CSR (Client-Side Rendering)Im Browser, der Server schickt eine leere HülleAm höchsten. Inhalte, Links und Status hängen an JavaScriptBereiche hinter dem Login, Werkzeuge
SSR (Server-Side Rendering)Auf dem Server, je AnfrageNiedrig, solange der Server schnell antwortet und Fehlercodes stimmenSeiten, die sich oft oder je Nutzer ändern
SSG (Static Site Generation)Beim Bauen, als fertige DateiNiedrig. Aktualität hängt am nächsten BauRatgeber, Dokumentation, Landingpages
ISR (Incremental Static Regeneration)Statisch, wird nach Zeit oder Ereignis neu erzeugtNiedrig. Bei Fehlern prüfen, welche Fassung gerade ausgeliefert wirdGroße Kataloge

Google selbst schreibt, serverseitiges Rendern oder Vorrendern sei weiterhin eine gute Idee, weil es die Website für Nutzer und Crawler schneller macht und nicht alle Bots JavaScript ausführen können. Das frühere Prerendering nur für Bots, das dynamische Rendering, nennt Google einen Notbehelf und keine langfristige Lösung.

Wie Google JavaScript verarbeitet

Die Grundlagen stehen in Googles Doku, Stand 4. März 2026. Viele ältere Texte, auch unsere frühere Fassung dieses Beitrags, sprechen von einer „zweiten Welle“ mit Tagen oder Wochen Wartezeit. Google schreibt heute etwas anderes: Eine Seite kann „für einige Sekunden“ in der Warteschlange bleiben, es kann aber auch länger dauern. Eine verlässliche Dauer nennt Google nicht, auch keine lange.

Der Ablauf hat drei Phasen:

  1. Crawling. Googlebot prüft die robots.txt und ruft die URL ab. Er liest Links aus dem href der HTML-Antwort.
  2. Rendering. Alle Seiten mit Status 200 kommen in die Warteschlange, egal ob sie JavaScript enthalten, außer ein Robots-Meta-Tag oder -Header verbietet die Indexierung. Ein Headless-Chromium führt das JavaScript aus, sobald Ressourcen frei sind.
  3. Indexierung. Google nutzt das gerenderte HTML, und Links darin kommen in die Crawling-Warteschlange.

Daraus folgen einige Punkte, die in der Praxis wichtig sind:

  • Status ungleich 200: Das Rendering kann entfallen. Eine 404 muss also schon der Server liefern.
  • noindex im Ausgangs-HTML: Google überspringt möglicherweise Rendering und JavaScript. Später per Skript entfernen kann also scheitern.
  • Keine Erinnerung: Jede URL lädt ohne Zustand. Local Storage, Session Storage und Cookies werden zwischen den Seitenaufrufen geleert.
  • Keine Erlaubnisse: Googlebot lehnt Berechtigungsanfragen ab, etwa für die Kamera.
  • Nur HTTP: WebSockets und WebRTC unterstützt er nicht. Inhalte, die nur darüber kommen, sieht er nicht.
  • Caching: Googlebot cacht stark und ignoriert unter Umständen Cache-Header. Deshalb empfiehlt Google Dateinamen mit Prüfsumme wie main.2bb85551.js.
  • Titel und Canonical per JavaScript: Beides ist möglich, Google rät aber beim Canonical zum HTML. JavaScript darf das Canonical nicht auf einen anderen Wert ändern als im Original.

KI-Crawler: Was sich belegen lässt und was nicht

Zu KI-Crawlern kursiert der Satz „sie führen kein JavaScript aus“, oft ohne Quelle. Wir haben am 5. November 2026 die Crawler-Seiten von OpenAI, Anthropic und Perplexity gelesen. Dort geht es um Namen der Crawler, IP-Bereiche und robots.txt. Zum Rendern von JavaScript steht auf diesen Seiten nichts, weder dafür noch dagegen.

Belegt sind zwei benachbarte Aussagen. Google schreibt allgemein, dass nicht alle Bots JavaScript ausführen können. Und die Next.js-Dokumentation führt „HTML-limited bots“ als eigene Gruppe, mit facebookexternalhit als Beispiel, und behandelt sie gesondert.

Für die Praxis reicht das, denn die Empfehlung hängt nicht an der offenen Frage: Steht dein Inhalt im HTML des Servers, bist du unabhängig davon, was ein Bot kann. Willst du es für deine Website wissen, prüfe deine Server-Logs nach Crawlern und nach Abrufen deiner JavaScript-Dateien. Dabei sind drei Fallen zu beachten: Bots cachen Dateien, Kennungen lassen sich fälschen, und wenige Abrufe beweisen noch nichts. Prüfe die IP-Bereiche, die die Anbieter veröffentlichen, und lies 0 Abrufe als Hinweis, nicht als Beweis.

Woher stammt dieser Satz in deinen eigenen Unterlagen?

Diagnose in fünf Minuten

Diese Reihenfolge kostet nichts und beantwortet die meisten Fragen.

  1. Quelltext ansehen. Rufe Strg+U auf oder nimm curl. Suche einen Satz aus dem Hauptinhalt, den Titel und einen wichtigen internen Link.
  2. Gerenderte Fassung ansehen. In der Search Console zeigt das URL-Prüftool den gerenderten Code, die geladenen Ressourcen und die Konsolenausgabe. Für fremde Seiten geht der Test für Rich-Suchergebnisse.
  3. Vergleichen. Steht der Satz nur in der gerenderten Fassung, hängt er an JavaScript.
  4. Status prüfen. Rufe eine URL auf, die es nicht gibt. Bekommst du 200 statt 404, hast du ein Soft-404-Problem.
  5. JavaScript abschalten. Was dann fehlt, sieht auch ein Bot nicht, der kein JavaScript ausführt.
#!/bin/sh
# Schnelldiagnose: eine Phrase im HTML des Servers suchen
URL="$1"
PHRASE="$2"
curl -s -o /dev/null -w 'Status: %{http_code}\n' -A "Mozilla/5.0" "$URL"
curl -s -A "Mozilla/5.0" "$URL" | grep -o -F "$PHRASE" | wc -l
curl -s -A "Mozilla/5.0" "$URL" | grep -i -o '<meta[^>]*name="robots"[^>]*>'
curl -s -A "Mozilla/5.0" "$URL" | grep -i -o '<link[^>]*rel="canonical"[^>]*>'
SymptomWahrscheinliche UrsachePrüfung
Seite indexiert, ein Textteil fehlt im gerenderten HTMLInhalt lädt erst nach Interaktion oder über WebSocketURL-Prüftool, gerendertes HTML
„Gecrawlt, nicht indexiert“ bei vielen gleichen SeitenLeere App-Hülle, alle Seiten sehen gleich ausQuelltext mehrerer URLs vergleichen
Soft 404 in der Search ConsoleFehlerseite mit Status 200curl auf eine erfundene URL
Neue Seiten werden nicht gefundenLinks ohne href oder Rauten-RoutenLinks im gerenderten HTML prüfen
Inhalt fehlt, im Browser ist alles gutJavaScript-Datei per robots.txt gesperrt, Zustand aus Cookie oder Local Storage erwartetGeladene Ressourcen im URL-Prüftool
Google zeigt alte Inhalte oder Fehler nach einem DeployAlte JavaScript-Datei im CacheDateinamen mit Prüfsumme?
Unerwartetes CanonicalJavaScript ändert es, oder es gibt mehrereQuelltext gegen gerendertes HTML

Die Tabelle knüpft an Googles Fehlerliste an. Die Zuordnung von Symptom zu Ursache ist unsere Lesart. Sie zeigt, wo du zuerst nachsiehst, und beweist die Ursache noch nicht.

Acht Fehlerbilder mit Prüfung und Lösung

Die Reihenfolge ist keine Rangliste. Wie oft jeder Fehler vorkommt, haben wir nicht gemessen. Weitere Punkte aus Googles Liste, die wir hier nicht einzeln zeigen: Lazy Loading muss so gebaut sein, dass Google die Bilder findet, strukturierte Daten lassen sich per JavaScript einfügen und müssen dann getestet werden, und von Web Components sieht Google nur, was im gerenderten HTML sichtbar wird.

1. Inhalt erscheint erst nach dem Abruf im Browser

Symptom: Im Quelltext steht „Lädt…“. Prüfung: Suche einen Satz des Hauptinhalts im Quelltext. Lösung: Daten auf dem Server holen.

'use client'
import { useEffect, useState } from 'react'

export default function Produkt({ slug }) {
  const [produkt, setProdukt] = useState(null)
  useEffect(() => {
    fetch(`/api/produkte/${slug}`).then((r) => r.json()).then(setProdukt)
  }, [slug])
  if (!produkt) return <p>Lädt…</p>
  return <h1>{produkt.name}</h1>
}

Google kann das rendern, aber du verlässt dich auf die Warteschlange, auf deine API und darauf, dass der Bot JavaScript ausführt. Besser ist eine Server-Komponente, wie sie unter Next.js gezeigt wird.

2. Titel und Beschreibung fehlen im Head

Symptom: Alle Seiten tragen im Quelltext denselben Titel, oder er fehlt. Prüfung: Suche <title innerhalb des Heads. Lösung: Metadaten auf dem Server erzeugen. Google liest zwar per JavaScript gesetzte Titel, soziale Netzwerke und viele andere Bots aber nicht unbedingt.

#!/bin/sh
URL="$1"
rm -f seite.html
curl -sf -A "Mozilla/5.0" "$URL" -o seite.html || { echo "Abruf fehlgeschlagen"; exit 1; }
# nur der Bereich bis zum ersten </head>
tr '\n' ' ' < seite.html | sed 's#</head>.*##' > seite_kopf.txt
grep -o -i '<title[ >]' seite_kopf.txt | wc -l
grep -o -i 'name="description"' seite_kopf.txt | wc -l
grep -o -i '<title[ >]' seite.html | wc -l

Die ersten beiden Zahlen zählen im Head, die dritte im ganzen Dokument. Steht oben 0 und unten 1, liegt der Titel im Body.

3. JavaScript ändert das Canonical

Symptom: Das Canonical im Quelltext weicht vom gerenderten ab. Prüfung: Beide Fassungen vergleichen und die Tags zählen. Lösung: Setze es im HTML und nur einmal. Mehrere oder widersprüchliche Canonicals können laut Google zu unerwarteten Ergebnissen führen.

<link rel="canonical" href="https://example.com/produkte/roter-schuh">

4. Links ohne echte Adresse

Symptom: Unterseiten werden nicht gefunden, obwohl die Navigation im Browser funktioniert. Prüfung: Sind es <a> mit href? Lösung: Google kann Links in der Regel nur so crawlen. Ein zusätzliches onclick stört nicht.

<!-- Kann Google folgen -->
<a href="/produkte/schuhe">Schuhe</a>
<a href="/produkte/schuhe" onclick="geheZu('schuhe')">Schuhe</a>

<!-- Kann Google nicht zuverlässig folgen -->
<a onclick="geheZu('schuhe')">Schuhe</a>
<span onclick="geheZu('schuhe')">Schuhe</span>

5. Routen über das Rautezeichen

Symptom: Adressen wie /#/produkte. Prüfung: Adressleiste. Lösung: Google kann solche Adressen nicht zuverlässig auflösen und rät zur History API.

<!-- Schlecht -->
<a href="#/produkte">Produkte</a>

<!-- Gut -->
<a href="/produkte">Produkte</a>
<script>
  document.querySelector('a[href="/produkte"]').addEventListener('click', (e) => {
    e.preventDefault()
    history.pushState({}, '', '/produkte')
    // hier die Ansicht laden
  })
</script>

Damit diese URLs auch beim direkten Aufruf funktionieren, muss der Server sie kennen.

6. Fehlerseite mit Status 200

Symptom: Erfundene URLs liefern 200. Prüfung: curl -I auf eine erfundene Adresse. Lösung: Richtig ist ein 404 vom Server. In einer reinen SPA nennt Google zwei Auswege:

fetch(`/api/produkte/${id}`)
  .then((r) => r.json())
  .then((produkt) => {
    if (!produkt.existiert) {
      // Weg 1: auf eine URL leiten, die der Server mit 404 beantwortet
      window.location.href = '/nicht-gefunden'
      // Weg 2, stattdessen: die Seite auf noindex setzen
      // const m = document.createElement('meta')
      // m.name = 'robots'
      // m.content = 'noindex'
      // document.head.appendChild(m)
    }
  })

7. noindex, das JavaScript entfernen soll

Symptom: Seite bleibt draußen, obwohl das gerenderte HTML sauber aussieht. Prüfung: robots-Meta im Quelltext. Lösung: Soll die Seite in den Index, gehört kein noindex ins Ausgangs-HTML. Google überspringt sonst möglicherweise das Rendern.

<!-- Riskant -->
<meta name="robots" content="noindex">
<script>
  document.querySelector('meta[name="robots"]').remove()
</script>

8. Gesperrte JavaScript-Dateien

Symptom: Das URL-Prüftool meldet nicht geladene Ressourcen. Prüfung: robots.txt und Ressourcenliste. Lösung: Google führt JavaScript aus gesperrten Dateien nicht aus.

# Schlecht
User-agent: *
Disallow: /_next/
Disallow: /assets/js/

# Besser
User-agent: *
Disallow: /admin/

Next.js mit App Router

In der Dokumentation von Next.js 16 werden Metadaten über metadata oder generateMetadata festgelegt. notFound() liefert laut Doku eine 404-Seite und fügt ein noindex ein.

// app/produkte/[slug]/page.tsx
import type { Metadata } from 'next'
import { notFound } from 'next/navigation'
import { getProdukt } from '@/lib/produkte'

type Props = { params: Promise<{ slug: string }> }

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { slug } = await params
  const produkt = await getProdukt(slug)
  if (!produkt) return {}
  return {
    title: produkt.name,
    description: produkt.zusammenfassung,
    alternates: { canonical: `/produkte/${slug}` },
  }
}

export default async function Page({ params }: Props) {
  const { slug } = await params
  const produkt = await getProdukt(slug)
  if (!produkt) notFound()
  return <h1>{produkt.name}</h1>
}

Was unser Testlauf gezeigt hat

Wir haben die Beispiele am 5. November 2026 mit Next.js 16.4.3 laufen lassen. Ein unbekannter Slug lieferte Status 404 mit noindex, wie in der Doku. Lag aber eine loading.tsx darüber, kam Status 200, und nur das noindex blieb. Die Next.js-Doku beschreibt das ebenso: Die Antwort streamt schon, bevor notFound() greift, und behält Status 200. Prüfe also bei jeder Ladegrenze eine erfundene URL mit curl -I, statt dich auf den Code zu verlassen.

Metadaten im Body: Das überrascht bei der Prüfung

Wenn generateMetadata dynamisch ist, kann Next.js die Metadaten nach der ersten Ausgabe streamen. Sie landen dann im <body> statt im <head>. Die Doku sagt, das sei für Bots geprüft, die JavaScript ausführen, etwa Googlebot. Für „HTML-limited bots“ wie facebookexternalhit blockiert Next.js dagegen weiter und schreibt die Tags in den Head. Erkannt wird das am User-Agent.

In unserem Lauf landete der Titel dann im Body, wenn eine Suspense-Grenze wie loading.tsx darüber lag, und zwar mit normaler Browser-Kennung ebenso wie mit der von Googlebot. Ohne diese Grenze stand er im Head, auch bei einer um 1,5 Sekunden verzögerten Datenquelle. Achte also auf Ladegrenzen. Für Google ist das laut Doku kein Fehler. Ob ein KI-Crawler den Titel im Body liest, sagen die Anbieter nicht. Wer sichergehen will, setzt htmlLimitedBots, das holte den Titel bei uns zurück in den Head. Die Doku warnt, dass dies längere Antwortzeiten bringen kann, und nennt die Standardeinstellung für die meisten Fälle ausreichend.

// next.config.ts
import type { NextConfig } from 'next'

const config: NextConfig = {
  htmlLimitedBots: /.*/,
}

export default config
Welche deiner Routen hat eine Ladegrenze?

Nuxt

Die aktuelle Dokumentation gilt für Nuxt 4, gelesen haben wir Version 4.6. Wer noch Beispiele für Nuxt 3 nutzt, sollte sie gegenprüfen. Standard ist universelles Rendering: Der Server liefert den Inhalt im HTML, und der Browser übernimmt danach durch Hydration. useSeoMeta nennt die Doku den empfohlenen Weg für Meta-Tags.

<!-- pages/produkte/[slug].vue -->
<script setup lang="ts">
const route = useRoute()
const { data: produkt } = await useFetch(`/api/produkte/${route.params.slug}`)

if (!produkt.value) {
  throw createError({ status: 404, statusText: 'Nicht gefunden' })
}

useSeoMeta({
  title: () => produkt.value?.name,
  description: () => produkt.value?.zusammenfassung,
})
</script>

<template>
  <h1>{{ produkt?.name }}</h1>
</template>

Über routeRules legst du je Pfad fest, was gerendert wird. Ein ssr: false im Bereich, den Suchmaschinen sehen sollen, ist der Fehler, den du hier suchst:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/ratgeber/**': { prerender: true },
    '/konto/**': { ssr: false },
  },
})

Eine Einschränkung aus unserem Lauf mit Nuxt 4.6.2: /ratgeber/x entstand mit nuxt build --prerender und einem Link auf die Seite als statische Datei. Prüfe also nach dem Bau, ob die Datei wirklich im Ausgabeordner liegt.

Vue ohne Nuxt

Vue Router kennt zwei Modi, und der Unterschied entscheidet über deine URLs. createWebHistory() erzeugt normale Adressen und ist laut Doku die empfohlene Variante. createWebHashHistory() hängt ein Rautezeichen an, und die Adresse dahinter geht nicht an den Server. Das ist das Fehlerbild 5 von oben.

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [],
})

Der History-Modus braucht eine passende Serverkonfiguration, sonst liefert der direkte Aufruf einer Unterseite laut Doku einen 404. Umgekehrt solltest du prüfen, dass der Server nicht für jede erfundene Adresse dieselbe Hülle mit Status 200 ausliefert. Das wäre Fehlerbild 6.

Die Vue-Doku geht beim Rendern weiter als Google. Sie schreibt, Google und Bing könnten synchrone JavaScript-Anwendungen indexieren, bei Inhalten nach einem Ladekreisel warte der Crawler aber nicht. Google selbst beschreibt das nicht so und sagt nur, dass es JavaScript ausführt. Für deine Entscheidung ändert das wenig: Vue rät für ein paar Marketingseiten zu SSG statt SSR, und für Inhalte wie Dokumentation oder Blogs ebenfalls. Der Vergleich von Quelltext und gerendertem HTML zeigt dir, was bei dir ankommt.

React ohne Framework

Eine reine React-App mit Vite oder Ähnlichem liefert eine leere Hülle. Für öffentliche Inhalte hast du drei Wege:

  • Framework einführen. Der gründlichste Weg, aber oft ein Umbau.
  • Beim Bauen vorrendern. Für Seiten, die sich selten ändern. Die Server-APIs von react-dom erzeugen das HTML.
  • Öffentlichen Teil trennen. Marketing und Ratgeber statisch, die App dahinter wie bisher.

Seit React 19 kannst du <title> und <meta> aus jeder Komponente rendern, und die Doku sagt, React setze sie immer in den Head. In unserem Lauf mit React 19.3.0 gilt das nur, wenn React auch die Hülle rendert. Bauten wir das Ergebnis von renderToString als Fragment in einen eigenen <body> ein, blieben Titel und Meta im Body. Mit <html> und <head> im React-Baum landeten sie im Head, obwohl sie in der Komponente stehen:

// Karte.jsx
export default function Karte({ produkt }) {
  return (
    <article>
      <title>{produkt.name}</title>
      <meta name="description" content={produkt.zusammenfassung} />
      <h1>{produkt.name}</h1>
    </article>
  )
}
// vorrendern.mjs. Vorher: esbuild Karte.jsx --jsx=automatic --format=esm --outfile=Karte.js
import { writeFileSync } from 'node:fs'
import { createElement as h } from 'react'
import { renderToString } from 'react-dom/server'
import Karte from './Karte.js'

const produkt = { name: 'Roter Schuh', zusammenfassung: 'Beispielkarte' }
const html = renderToString(
  h('html', { lang: 'de' },
    h('head', null, h('meta', { charSet: 'utf-8' })),
    h('body', null, h(Karte, { produkt }))),
)
writeFileSync('roter-schuh.html', `<!doctype html>${html}`)

renderToString reicht für dieses einfache Beispiel. Die React-Doku führt es aber unter den Legacy-APIs, und es unterstützt weder Streaming noch das Warten auf Daten. Für solche Fälle nennt die Doku prerender aus react-dom/static, das wir nicht haben laufen lassen.

Astro auf zds.es, und was das zeigt

Auch diese Website läuft mit Astro. Astro rendert Seiten laut Doku zu statischem HTML und lädt JavaScript nur für Inseln, die du ausdrücklich markierst. Mehr zur Entscheidung steht in unserem Beitrag über Headless CMS und Astro.

---
// Ohne client:* bleibt die Komponente HTML, ohne JavaScript im Browser
import Rechner from '../components/Rechner.jsx'
import Karte from '../components/Karte.astro'
---
<Karte />
<Rechner client:visible />

Wir haben den Vergleich aus der Diagnose an unseren eigenen Seiten gemacht. Am 5. November 2026 lieferte unser spanischer Glossareintrag zu JavaScript SEO im HTML des Servers 2.567 Wörter, gerendert 2.591. Der Unterschied von 24 Wörtern ist im Wesentlichen der Cookie-Hinweis. Titel, H1 und Canonical waren in beiden Fassungen gleich, und ohne JavaScript blieb der Inhalt vollständig da. Bei Startseite und einem Beitrag ergab sich dasselbe Bild.

Das zeigt, wie dieser Test aussieht, wenn nichts fehlt. Es zeigt nicht, dass Astro bessere Rankings bringt. Fehler gibt es auch hier, nur an anderen Stellen. Vier davon sind bei uns dokumentiert, und keiner hat mit JavaScript im Browser zu tun:

  • Falscher Fehlercode (31.08.2026): Eine Störung im CMS führte zu 404 statt 503. Das hätte Seiten aus dem Index nehmen können. Googles Doku erklärt den Unterschied: 404 entfernt indexierte URLs, 5xx bremst zunächst das Crawling, und indexierte URLs fallen erst irgendwann heraus.
  • Großbuchstaben in Pfaden (08.10.2026): Sie lieferten 200 mit eigenem Canonical, also Dubletten. Die Weiterleitung, die das behob, erzeugte bei Prozent-Kodierung eine 301-Schleife, entdeckt am 30.10.2026. Ein Fix braucht denselben Test wie der Fehler.
  • Sprachen laufen über verschiedene Wege (05.11.2026): Ein SEO-Plugin setzte nofollow nur über den Inhaltsfilter des CMS. Die spanischen Inhalte liefen darüber, die englischen und deutschen aus eigenen Feldern, und dort fehlte es. Eine Prüfung in nur einer Sprache sieht das nicht.
  • Sitemap im Speicher: Ein Dienst hält sie bis zu einer Stunde vor. Am 5. November 2026 zeigte der Header 54 Minuten. Nach einem Update kann lastmod also kurz alt sein, ohne dass etwas kaputt ist.

Checkliste

  • Steht ein Satz des Hauptinhalts im Quelltext?
  • Stehen Titel, Beschreibung und Canonical im Head und nur einmal?
  • Sind alle wichtigen Links <a href> mit echten Pfaden?
  • Liefert eine erfundene URL Status 404?
  • Gibt es im Ausgangs-HTML kein noindex, das später wegsoll?
  • Sind JavaScript und CSS nicht per robots.txt gesperrt?
  • Haben JavaScript-Dateien eine Prüfsumme im Namen?
  • Kommt der Inhalt ohne Interaktion, Berechtigung, Cookie und WebSocket?
  • Stimmt das gerenderte HTML im URL-Prüftool mit der Erwartung überein?

Häufige Fragen

Kann Google JavaScript lesen?

Ja. Google führt JavaScript mit einem aktuellen Chromium aus und nutzt das gerenderte HTML für den Index. Grenzen gibt es trotzdem: Blockierte Dateien, Inhalte hinter Interaktion oder WebSockets und Zustände aus Cookies sieht Googlebot nicht. Deshalb bleibt die Prüfung im URL-Prüftool nötig, auch wenn der Inhalt im Browser erscheint.

Wie lange wartet eine Seite auf das Rendering?

Google schreibt, eine Seite könne einige Sekunden in der Warteschlange bleiben, es könne aber länger dauern. Eine feste Zeit gibt es nicht. Ältere Angaben von Tagen oder Wochen stehen nicht in der aktuellen Dokumentation vom 4. März 2026. Eine eigene Messung dazu haben wir nicht.

Brauche ich SSR für SEO?

Nicht zwingend für Google, das auch clientseitige Seiten rendert. Google empfiehlt serverseitiges Rendern oder Vorrendern trotzdem, weil es schneller ist und nicht alle Bots JavaScript ausführen. Für öffentliche Seiten, die gefunden werden sollen, ist SSR oder SSG die sichere Wahl. Für Bereiche hinter dem Login nicht nötig.

Sollte ich dynamisches Rendering einrichten?

Für neue Projekte nicht. Google nennt es einen Notbehelf und keine langfristige Lösung und empfiehlt serverseitiges Rendern, statisches Rendern oder Hydration. Dynamisches Rendering bedeutet, Bots eine andere Fassung zu liefern als Nutzern, und das musst du dauerhaft pflegen und überwachen.

Führen ChatGPT und andere KI-Dienste JavaScript aus?

Die Crawler-Seiten von OpenAI, Anthropic und Perplexity, gelesen am 5. November 2026, sagen dazu nichts. Eine Aussage dazu können wir also nicht belegen. Mit dem Inhalt im HTML des Servers musst du die Antwort nicht kennen. Für deine Website zeigen die Server-Logs Hinweise, aber keinen Beweis.

Quellen

Abgerufen am 5. November 2026. Die Google-Doku verlinken wir auf Englisch, weil die deutsche Fassung maschinell übersetzt ist.

Begriffe zum Weiterlesen: JavaScript SEO, Soft 404, Canonical-Tag, noindex und Logfile-Analyse.

Wie dieser Artikel entstanden ist

Die erste Fassung stammt vom März 2026. Im November 2026 wurde der Beitrag mit KI-Unterstützung neu geschrieben, anhand der oben verlinkten Dokumentationen und einer eigenen Stichprobe von drei Seiten, und vor der Veröffentlichung geprüft. Die Beispiele zu Next.js, Nuxt, React und Astro sind in Testprojekten mit Next.js 16.4.3, Nuxt 4.6.2, React 19.3.0 und Astro 7.4.2 gelaufen. HTML, robots.txt und Skriptausschnitte haben wir nur auf Syntax oder gegen Testseiten geprüft, der Ausschnitt zu Vue Router lief nicht.

Wählst du ZDS als bevorzugte Quelle, zeigt dir Google unsere Artikel öfter unter „Top-Meldungen“.

Füge uns bei Google als bevorzugte Quelle hinzu

Wie steht deine Website in Google und in der KI da?

Nenn uns deine Domain, und wir schicken dir einen Erstbefund: wie sie in Google und in KI-Assistenten wie ChatGPT erscheint. Kostenlos und unverbindlich.

Erstbefund anfordern
Manuel Riveiro

CEO & Digital Strategist — ZDS

Über 20 Jahre Erfahrung in SEO, Performance-Marketing und KI-Werkzeugen. Gründer von ZDS und B2 Performance, mit Sitz in Barcelona und Herdecke.