webinale Blog

Development | SEO mit JavaScript

SEO-optimierte JavaScript-Seiten erstellen

Mar 11, 2019

Historisch gesehen hatten Suchmaschinen mit der Indexierung von Inhalten, die per JavaScript geladen werden, immer große Probleme und zum Teil immer noch. Kein Wunder also, dass viele Mitarbeiter von SEOs JavaScript lange fürchteten wie der Teufel das Weihwasser. Es gibt aber Lösungen für das Problem.

Mit der immer stärkeren Verbreitung von modernen JavaScript-Frameworks wie Angular, React oder Vue.js kommt man heute in der SEO kaum mehr daran vorbei, sich mit dem Thema JavaScript und SEO auseinanderzusetzen. Gleichzeitig sollten sich aber auch Entwickler im Klaren darüber sein, wie Suchmaschinen ihre auf JavaScript-Frameworks basierenden Seiten verarbeiten. Während sich viele Suchmaschinen auch 2019 noch schwertun, JavaScript-basierte Seiten zu verarbeiten, kommt Branchenprimus Google mittlerweile recht gut damit zurecht. Trotzdem gibt es noch zahlreiche Stolpersteine, die verhindern können, dass eine Seite gut gefunden wird. In diesem Beitrag wollen wir uns ansehen, welche Hindernisse JavaScript aus SEO-Perspektive mit sich bringt und mit welchen Best Practices man Google und Co. beim Crawlen und Indizieren unterstützen kann.

Wie funktioniert eine Suchmaschine?

Damit ein Dokument, also in der Regel eine Website, überhaupt in den Suchergebnissen aufscheinen kann, muss jede Suchmaschine das Dokument zunächst einmal finden und anschließend den Inhalt verstehen. Im ersten Schritt geht es also darum, einen Überblick über möglichst alle verfügbaren Dokumente zu bekommen. Ein Crawler, etwa der Google Bot, tut dazu im Prinzip nichts anderes, als allen URLs zu folgen und so ständig neue Seiten zu entdecken.

Landet der Crawler auf einem URL, wird zunächst einmal das HTML-Dokument heruntergeladen und der Quellcode nach grundsätzlichen Informationen einerseits und Links zu weiteren URLs andererseits durchsucht. Metainformationen wie das Robots-Meta-Tag oder das Canonical-Tag geben Auskunft darüber, wie die Seite grundsätzlich zu verarbeiten ist. Den gefundenen Links kann der Crawler weiter folgen.

Noch mehr Expertentipps mit unserem kostenlosen Newsletter

Dazu schickt der Crawler die HTML-Datei und alle Ressourcen an den Indexer, in Googles Fall ist das Caffeine. Der Indexer rendert das Dokument und kann dann die Inhalte der Webseite indizieren. Anschließend sorgt der Algorithmus dafür, dass die relevantesten Dokumente für treffende Suchanfragen gefunden werden können.

Kommt jetzt aber JavaScript zum Einsatz, um das DOM (Document Object Model) erst clientseitig, also im Browser, fertig zu rendern, findet der Crawler beim Besuch eines URLs ein HTML-Dokument, das vereinfacht so aussieht, wie in Listing 1 dargestellt.

<!doctype html>
<html>
<head>
</head>
<body> 
<app-root></app-root>
<script src="runtime.js"></script>
<script src="polyfills.js"></script>
<script src="main.js"></script>
</body>
</html>

Während beim Abruf eines serverseitig gerenderten Dokuments Struktur und Inhalte bereits im HTML-Quellcode enthalten sind, kommt bei React, Angular und Co. das Prä-DOM-HTML ziemlich leer daher. Wird nun der gesamte Inhalt einer Seite auf diese Art und Weise geladen, bekommt ein Suchmaschinen-Crawler, der nur den HTML-Code einer Seite ausliest, quasi keine Informationen. Der Robot findet weder Links, denen er weiter folgen kann, noch grundsätzliche Informationen zum Inhalt der Seite, noch irgendwelche Metatags.

Daher muss der Crawler nun das HTML sowie CSS- und JavaScript-Ressourcen an den Indexer schicken, der anschließend zunächst einmal das JavaScript ausführen muss, um die Seite zu rendern, bevor Inhalte und Metainformation verarbeitet werden können. Erst dann können aus dem gerenderten DOM auch weitere Links entnommen werden, die zurück an den Crawler gegeben werden, der so zu weiteren URLs kommt.

Online Marketing Track auf der webinale

 

Können Suchmaschinen JavaScript rendern?

Bisher ist Google leider die einzige Suchmaschine, von der wir wissen, dass sie tatsächlich eine Rendering-Engine einsetzt, um JavaScript auszuführen und auch Informationen zum Prozess in ihrer Dokumentation bereitstellt. Die anderen größeren Suchmaschinen, inklusive Bing, sind da noch nicht so weit, wie ein Experiment des polnischen SEO-Spezialisten Bartosz Góralewicz gezeigt hat. Auch wenn Bing von sich behauptet, ebenfalls JavaScript zu rendern, scheint das dort nur bei sehr großen und prominenten Seiten auch tatsächlich stattzufinden.

Tatsächlich wissen wir, dass Google in Caffeine einen Web Rendering Service (WRS) nutzt, der auf einem headless Chrome basiert. Leider wissen wir auch, dass dieser aktuell noch immer auf dem Stand der Chrome-Version 41 ist, sich also verhält wie ein drei Jahre alter Browser. Zum Glück hat das verantwortliche Team rund um John Müller und Martin Splitt bereits betont, dass man mit Hochdruck daran arbeitet, möglichst bald auf eine neuere Version zu kommen und in Zukunft mit den Chrome-Updates Schritt halten möchte.

Solange das aber nicht der Fall ist, kann auf caniuse.com oder dem Chrome Platform Status nachgelesen werden, welche Features von eben jenem Chrome 41 unterstützt werden und welche nicht.

Voraussetzung für ein erfolgreiches Rendering ist jedenfalls, dass man keinerlei JavaScript- und CSS-Ressourcen durch die robots.txt-Datei blockiert. Darf Google nicht auf diese Ressourcen zugreifen, fällt ein korrektes Rendering schwer. Außerdem müssen alle relevanten Inhalte vor dem Abfeuern des Load Events geladen sein. Alle Inhalte, die nach dem Load Event durch ein User Event geladen werden, werden bei der Indexierung nicht mehr beachtet.

Interessant ist auch, dass Google hier in zwei Wellen indiziert und crawlt. Weil das JavaScript-Rendering extrem ressourcenaufwendig ist, wird der URL zunächst einmal indiziert. Hier kann natürlich lediglich auf die Informationen zurückgegriffen werden, die unmittelbar in der Pre-DOM-HTML-Source zu finden sind. In einer zweiten Welle wird die Seite dann gerendert und der komplette Inhalt des Post-DOM-HTML indiziert (Abb. 1). Um zu testen, wie Google eine JS-basierte Website rendert, kann man auf die „Abruf wie durch Google“-Funktion (Fetch as Google) in der (alten) Search Console zurückgreifen. Hier sieht man einerseits, wie Google die Seite tatsächlich rendert, andererseits kann man auch den Quellcode einsehen.

 

Abb. 1: Indizierung bei Google in zwei Wellen

 

Zwei weitere Tools, um das Rendering durch Google zu testen, sind der Mobile-Friendly-Test, mit dem die Ansicht auf Mobilgeräten getestet werden kann, sowie der Rich-Results-Test. Hier findet man jeweils das gerenderte HTML, sowie beim Mobile-Friendly-Test auch einen Screenshot der gerenderten Seite.

Neben Problemen mit dem Rendering der einzelnen Seiten kommen bei der Verwendung von JavaScript-Frameworks aber auch immer wieder ganz andere Fehlerquellen zum Tragen. Auch die SEO-Basics werden oft vergessen.

URLs sind das API für Crawler

Zunächst einmal braucht jede Seite einen URL. Denn URLs sind die Entitäten, die Suchmaschinen in den Suchergebnissen listen. Per JavaScript kann man Inhalte dynamisch verändern, ohne dass sich dabei der URL ändert. Aber jede einzelne Seite muss einen einzigartigen, unterscheidbaren und dauerhaften URL haben, damit sie überhaupt indexiert werden kann! Wird also ein neuer Inhalt geladen, muss auch ein neuer URL mit serverseitiger Unterstützung aufgerufen werden. Dabei muss man unbedingt darauf achten, dass normale URLs verwendet werden und keine Hashes (#) oder Hashbangs (#!), auch wenn diese als Standard im Framework vorgesehen sind:

example.com/#about
example.com/!#about

example.com/about

Dabei ist es wichtig, bei internen Links pushState-Fehler zu vermeiden, damit auch wirklich der serverseitig unterstützte URL aufgerufen wird. Ansonsten kann es dazu kommen, dass Inhalte plötzlich auf mehreren URLs verfügbar sind und so zu Duplicate Content werden.

Eine weitere Fehlerquelle: Wenn JavaScript die Navigation übernimmt, kann es vorkommen, dass ein URL nur aus der Applikation heraus funktioniert. Das passiert genau dann, wenn zwar der Inhalt nachgeladen und auch der URL brav manipuliert wird, dieser aber serverseitig nicht unterstützt wird. Kommt ein User direkt auf den URL oder lädt man ihn neu, gibt es keinen Inhalt auf diesem URL.

Dazu muss man wissen, dass der Google-Bot immer Stateless arbeitet. Cookies, Local Storage, Session Storage, IndexedDB, ServiceWorkers usw. werden nicht unterstützt. Der Crawler besucht jeden URL als komplett neuer User. Daher muss man unbedingt sicherstellen, dass alle Routes, also alle URLs, immer auch direkt aufrufbar sind.

Serverstatuscodes

In Bezug auf URLs gilt auch die generelle SEO Best Practice, nämlich die Serverstatuscodes korrekt zu nutzen. Wenn sich der URL eines Inhalts ändert, dieser aber weiterhin auf der Seite verfügbar ist, sollte man User und Suchmaschinen mit einem serverseitigen Redirect (HTTP-Statuscode 301) oder einer entsprechenden clientseitigen JavaScript-Weiterleitung auf den neuen URL leiten. Durch die Weiterleitung kommt man nicht nur auf den gewünschten Inhalt, sondern die Redirects geben auch die Autorität des alten URLs (Stichwort Backlinks) an den neuen URL weiter.

Ist ein Inhalt nicht mehr verfügbar, sollte korrekterweise auch ein 404-Status zurückgegeben werden. Suchmaschinen entfernen diese URLs dann aus den Suchergebnissen. Dazu gehört auch, Soft-404-Fehler zu vermeiden: Eine 404-Seite heißt 404-Seite, weil sie einen solchen Status ausgibt, und nicht nur ein „Ups! Sorry, diese Seite gibt es nicht“ angezeigt wird, während der Server einen 200-(OK-)Code ausspielt.

Markup nutzen

HTML ist eine Markup Language: Das zur Verfügung stehende Markup sollte man auch entsprechend nutzen. Auch wenn es mit JavaScript verschiedene Möglichkeiten gibt, URLs aufzurufen, sollte man für einen Link zu einem anderen URL das dafür vorgesehene Anchor-Tag inklusive href-Attribut nutzen:

<a onclick=”location.href(‘https://www.example.com/unterseite’); “> Meine Unterseite </a>
<span onclick=”goTo(‘/unterseite’); “> Meine Unterseite </span>

<a href=”/unterseite”> Meine Unterseite </a>

Zum Markup gehören außerdem Metatags im HTML Head, die wichtige Informationen für Suchmaschinen enthalten. Dazu gehören der Title-Tag, die Meta-Description, Canonical-Links oder hreflang-Auszeichnungen. Auch Social Media Crawler holen sich hier Informationen ab, zum Beispiel OpenGraph Markup. Im Idealfall erstellt man die Metatags ganz ohne JavaScript. Dafür gibt es für die verschiedenen Frameworks mittlerweile gängige Module, die sich relativ leicht integrieren lassen.

Im HTML Head finden wir oft auch gröbere Probleme. Immer wieder kommt es vor, dass Entwickler auf allen Seiten per Default ein generelles noindex-Tag im Markup ausspielen, um es dann erst per JavaScript wieder zu entfernen (Listing 2).

<meta name="robots" content="noindex">
<script>
  var robots = document.querySelector ('meta[name="robots"] ');
  document.head.removeChild (robots);
</script>

Aber im ersten Schritt kommt – wir erinnern uns – der Google-Bot auf die Seite und lädt das unfertige HTML herunter, um dort das noindex zu finden. Damit wird die Seite gar nicht an Caffeine weitergegeben, wo die Seite gerendert würde, und Google sieht nicht, dass im fertigen DOM dann eben kein noindex mehr im Head stehen würde. Das führt dazu, dass die Seite überhaupt nicht indexiert wird.

JavaScript serverseitig vorrendern

Das Rendern von Webseiten ist enorm ressourcenaufwendig – auch für Branchenriesen wie Google. Daher geschieht der Renderingprozess auch, wie oben bereits erwähnt, nicht unmittelbar nachdem der Crawler einen URL entdeckt hat, sondern erst, wenn entsprechende Ressourcen frei sind. Bis eine Seite gerendert wird, kann es bis zu einer Woche dauern. Dadurch wird der an sich recht einfache Prozess des Crawlens und Indizierens enorm aufwendig und ineffizient.

Andere Crawler von Suchmaschinen, sowie die Crawler von Facebook, Twitter, LinkedIn usw., die Seiten beispielsweise für die Generierung einer Previewbox besuchen, rendern noch überhaupt kein JavaScript.

Um sicherzustellen, dass eine Seite auch von Crawlern abseits des Google-Bots verstanden wird, aber auch um Google zu entlasten, empfehlen wir, Seiten bereits serverseitig vorzurendern. Damit wird sichergestellt, dass Google alle wichtigen Inhalte auch wirklich findet und diese zügiger indiziert.

Ganz abgesehen von den Problemen der Bots kann clientseitiges Rendering auch für User Nachteile mit sich bringen. Zumindest der Initial Page Load, also das Laden der ersten Seite, dauert in der Regel deutlich länger, weil das Rendering komplett vom Client übernommen werden muss. Zusätzlich hängt die Ladezeit von der Qualität und Rechenleistung des jeweiligen Endgeräts ab. Deshalb lautet das Zauberwort, um JavaScript-Frameworks SEO-tauglich zu machen: Server-Side-Rendering. Statt den HMTL-Code erst auf Clientseite errechnen zu lassen, wird die Seite schon serverseitig vorgerendert (Pre-Rendering, Abb. 2) und fertig ausgeliefert. Dazu gibt es neben kostenpflichtigen Pre-Rendering-Services mittlerweile auch diverse Open-Source-Lösungen, die PhantomJS, einen Headless Chrome oder einen anderen Headless Browser nutzen, um die Seiten bereits auf dem Server zu rendern. Sowohl Browser als auch Crawler bekommen direkt das serverseitig vorgerenderte HTML ausgespielt. Alles JavaScript, das nötig ist, um die Seite grundsätzlich zu rendern, läuft bereits auf dem Server. Clientseitig wird nur noch JavaScript ausgeführt, das von Nutzerinteraktionen herrührt.

 

Abb. 2: Rendering und Pre-Rendering

 

Große Erfolge mit dieser Technik verbuchte etwa Netflix, die ihre React-Anwendung komplett auf serverseitiges Rendering umstellten und clientseitig nur noch Vanilla-JavaScript ausführen. Durch diese Umstellung auf serverseitiges Rendering konnte Netflix die Ladezeiten um 50 Prozent verbessern.

Dynamic Rendering

Bei dem Modell, das Google Dynamic Rendering nennt, wird zwischen Browser und Crawler unterschieden (Abb. 3). Während ein normaler Browser die JavaScript-Version der Seite ausgeliefert bekommt und clientseitig rendern muss, bekommen Crawler eine serverseitig vorgerenderte Version.

 

Abb. 3: Rendering und Pre-Rendering

 

Dabei bedarf es einer Middleware, die unterscheidet, ob der Zugriff von einem normalen Browser oder einem Bot kommt. Hier wird einfach der Useragent ausgelesen und gegebenenfalls auch die IP-Adresse verifiziert, von der der jeweilige Bot üblicherweise zugreift. Dazu erwähnte John Müller, seines Zeichens Senior Webmaster Trends Analyst bei Google, im Google I/O 18 Talk, dass diese Variante nicht als Cloaking gewertet wird. Dass die vorgerenderte und die clientseitige Version sich inhaltlich nicht unterscheiden dürfen, sollte dabei aber klar sein.

Hybrid „Isomorphic“ Rendering

Google selbst empfiehlt stets eine Hybrid-Rendering-Lösung, bei der sowohl normale User als auch Suchmaschinen zunächst eine vorgerenderte Version der Seite ausgeliefert bekommen. Erst wenn der User beginnt, mit der Seite zu interagieren, beginnt das JavaScript über das DOM den Quellcode zu verändern (Abb. 4). So weit wie möglich wird das JavaScript also bereits auf dem Server gerendert, für alle weiteren Aktionen wird JavaScript dann clientseitig ausgeführt. Und weil Crawler ja stateless sind, bekommen sie bei jedem einzelnen URL immer eine vorgerenderte Seite ausgeliefert.

 

Abb. 4: Hybrid Rendering

 

Ein weiterer Vorteil dieser Lösung ist, dass auch User, die JavaScript deaktiviert haben, eine funktionierende Seite ausgeliefert bekommen. In der Praxis gestaltet sich das Set-up einer solchen Lösung allerdings oft recht kompliziert, auch wenn es für die gängigsten Frameworks mittlerweile sehr gute Module gibt.

Testen, ob man gefunden wird

Um zu testen, wie Google die eigene JavaScript-basierte Website verarbeitet, gibt es diverse Tools, die von Google selbst zur Verfügung gestellt werden. Die oben bereits erwähnten Tools Mobile-Friendly-Test und Rich-Results-Test können missbraucht werden, um zu sehen, ob und wie der Indexer die Seite rendern kann. Ob die für JavaScript-Audits praktische Fetch-as-Google-Funktion auch in die neuen Search Console integriert wird, muss sich erst zeigen.

Natürlich kann man sich auch jederzeit die Version 41 des Chrome-Browsers herunterladen und dort sehen, wie die Seite gerendert wird. Die Konsole der dortigen DevTools gibt Aufschluss darüber, welche Features diese alte Version noch nicht unterstützt.

Auch einige SEO Crawler können mittlerweile JavaScript rendern, zum Beispiel der beliebte SEO Crawler Screaming Frog. In der Bezahlversion des Tools lässt sich in der Spider-Konfiguration JavaScript-Rendering aktivieren. Unter RENDERED PAGE lassen sich dann der Screenshot der Seite betrachten und auch das Prä-DOM-und Post-DOM-HTML direkt vergleichen. Weil das JavaScript-Rendering viele Ressourcen verbraucht, lassen sich sehr große Seiten mit der Desktopanwendung aber kaum komplett crawlen.

Um zu testen, ob die Inhalte der eigenen Seite korrekt indexiert wurden, bietet sich auch eine einfache Google-Suche an. Mit dem Suchoperator site:example.com und einem Textausschnitt aus der zu überprüfenden Seite lässt sich schnell feststellen, ob Google die Inhalte findet.

Fazit

Das Thema SEO ist bei den Entwicklerteams der großen Frameworks angekommen. Man setzt sich mit den Problemen hinsichtlich Crawling und Indexing auseinander und entwickelt entsprechende Lösungen. Auch Google geht das Thema JavaScript offensiv an und veröffentlicht Dokumentationen und Hilfestellungen. Wenn sich Entwickler mit dem Thema auseinandersetzen und bei ihrer Applikation an den richtigen Stellschrauben drehen, schließen sich eine JavaScript-basierte Website und eine gute Auffindbarkeit in Suchmaschinen heute nicht mehr aus.

Für Suchmaschinenoptimierer bringt JavaScript ganz neue Herausforderungen mit sich. SEO-Mitarbeiter müssen in Zukunft noch viel tiefer in technische Details eintauchen und sich intensiver mit JavaScript auseinandersetzen, um potenzielle Hindernisse erkennen und gemeinsam mit Entwicklern aus dem Weg räumen zu können.

MEHR INFOS ZUR WEBINALE?

JETZT NEWSLETTER ABONNIEREN

Programm-Updates der Webinale