Wir haben anirova.de umgebaut. Vorher stand dort eine Navigation, die zeigen sollte, was die App einmal werden kann. Jetzt stehen dort Seiten, die beantworten, wonach Leute tatsächlich suchen: eine für Watchlist-Nutzer, eine für Cosplayer, eine für Manga-Leser. Aus einer Handvoll Seiten wurden 32.
Dabei lag eine Falle im Weg, die mit Inhalten nichts zu tun hat.
Ein Element über allem
Die Seite hat einen Preloader: eine Fläche, die während des Ladens über allem liegt und danach ausgeblendet wird. Sinnvoll, damit niemand halb aufgebaute Inhalte sieht.
Zwei Eigenschaften machen ihn gefährlich:
.preloader { z-index: 10000; opacity: 1; }Er liegt über der gesamten Seite, und er ist sichtbar. Entfernt wird er von einer einzigen Zeile JavaScript. Läuft dieses JavaScript nicht, bleibt er liegen. Darunter liegt dann eine Seite, die vollständig geladen und vollständig unbedienbar ist.
Warum das ausgerechnet SEO trifft
Ein Umbau auf Suchmaschinen lebt davon, dass Google den Text sieht. Google rendert JavaScript zwar, aber nicht zuverlässig und nicht sofort: Das Rendern läuft in einer zweiten Runde, die Tage später kommen kann oder ausbleibt.
In dieser ersten Runde bekommt der Crawler eine Seite, deren Inhalt hinter einer undurchsichtigen Fläche liegt. Dasselbe sieht jeder Nutzer, bei dem das Skript nicht durchläuft, egal ob wegen eines Blockers oder wegen eines Fehlers weiter oben im Code.
Die Prüfung, die nichts merkt
Im Browser fällt das nie auf. Dort läuft das JavaScript, der Preloader verschwindet nach Millisekunden, die Seite sieht perfekt aus. Auch der Build ist zufrieden: Das HTML ist gültig, alle Dateien liegen da, der Server antwortet mit 200.
Sichtbar wird es erst, wenn man die Seite so abruft, wie ein Crawler sie zuerst sieht — ohne JavaScript auszuführen:
curl -s https://example.com/seite | perl -0777 -pe \
's{<(script|style|noscript)\b.*?</\1>}{}gs; s/<[^>]+>/ /g; s/\s+/ /g' \
| wc -cDie Zahl am Ende ist der Text, der ohne JavaScript ankommt. Bleibt sie klein, steht der Inhalt nicht im HTML — egal wie gut die Seite im Browser aussieht.
Die Lösung ist drei Zeilen lang
Das <noscript>-Element wird nur ausgewertet, wenn kein JavaScript läuft. Genau dann, und nur dann, wird der Preloader abgeschaltet:
<noscript><style>
.preloader { display: none !important; }
</style></noscript>Mit JavaScript ändert sich nichts — der Ladebildschirm funktioniert wie vorher. Ohne JavaScript ist er von vornherein weg, und darunter liegt eine normale, lesbare Seite.
Wichtig ist die Richtung: Die Regel schaltet etwas ab, das ohne JavaScript stört. Sie schaltet nichts ein, das dann funktionieren müsste. Ein Fallback, der selbst Voraussetzungen hat, ist kein Fallback.
Was wir daraus mitnehmen
Nach jedem Umbau rufen wir jede Seitenvorlage ohne JavaScript ab und messen die Textmenge. Nicht den Statuscode, nicht den Eindruck im Browser — die Zeichen, die tatsächlich im ausgelieferten HTML stehen. Auf anirova.de sind das zwischen 2.600 und 6.800 pro Seite. Eine Seite, die dort bei ein paar hundert landet, liefert ihren Inhalt nicht aus.
Der Fall gehört zu einer Familie: Alles, was Inhalte zunächst verdeckt und sich auf ein späteres Ereignis verlässt, kann sie dauerhaft verdecken — Ladebildschirme, Einblend-Animationen, Zustimmungsdialoge, Overlays jeder Art. Die Frage ist immer dieselbe: Was passiert, wenn das Ereignis ausbleibt? Lautet die Antwort „dann bleibt es verdeckt", ist es keine Politur mehr, sondern ein Schalter, der den Inhalt abschaltet.