Suchmaschinenfreundliche URLs

Johannes Beus
Johannes Beus
Johannes Beus ist Gründer und Geschäftsführer von SISTRIX.

Sprechende, suchmaschinenfreundliche URLs sind nicht erst, seit in der aktuellen c’t eine Einführung von Stefan Karzaunikat zu dem Thema und mod_rewrite zu lesen ist, gefragt. Da bei vielen Projekten keine fertigen Lösungen, wie es sie beispielsweise für Blogsysteme gibt, Anwendung finden, bastelt jeder selber mit den ihm gegeben Fähigkeiten drauf los. Ich möchte hier einige Hinweise auf mögliche Fallstricke und kurze Codeschnipsel, die bei uns funktionieren, zur Verfügung stellen.

Sprechende URLs werden häufig so aufgebaut, dass die ursprüngliche ID, die zur Identifikation des Datensatzes in der Datenbank notwendig ist, weiterhin in der URL verbleibt, zusätzlich aber noch der Titel oder Name des Datensatzes mit reingenommen wird. Zu sehen ist das beispielsweise bei der URL dieses Beitrages: während aus technischer Sicht eine URL wie www.sistrix.de/news/670 völlig ausreichen würde, wurde die Überschrift sowie die Endung „.html“ noch hinzugefügt. Die verwendete PHP-Funktion ist ähnlich wie folgende:

function filename($str) {

    static $from = array('ä',  'á''à''â''å''ö',  'ó''ò''ô''õ''ü',  'ú''ù''û''é''è''ê''í''ì''î''ß',  'ç''Ç''ñ''ý'); 
    static 
$to   = array('ae''a''a''a''a''oe''o''o''o''o''ue''u''u''u''e''e''e''i''i''i''ss''c''c''n''y');

    $str trim(preg_replace("#s+#"' 'preg_replace("#[^a-z0-9.]#"' 'str_replace($from$tostrtolower($str)))));
    
$str str_replace(' ''-'$str);

    return $str;

}

Übliche Sonderzeichen werden zuerst ersetzt (ä->ae), der komplette String wird in Kleinbuchstaben gewandelt und Leerzeichen sowie sonstige Sonderzeichen mit dem Bindestrich als Trennzeichen ersetzt. Um jetzt im PHP-Code der Seite einen Link zu setzen, muss einfach zusätzlich die Funktion aufgerufen werden:

echo '<a href="/news/'.$id.'-'.filename($titel).'.html">'.htmlentities($titel).'</a>';

Nachdem man jetzt schöne URLs hat, muss noch dafür gesorgt werden, dass die Scripte diese auch verstehen. Häufig kommt dabei mod_rewrite zum Einsatz: ein Modul für den verbreiteten Webserver Apache, das internes Umschreiben von URLs anhand vordefinierter regulärer Ausdrücke erlaubt. Hierbei wird allerdings häufig der Fehler gemacht, nur die Id zu übergeben und zu prüfen. Cyb hatte vor einiger Zeit schonmal auf das Problem aufmerksam gemacht, dass so – ob jetzt gut- oder böswillig sei mal dahingestellt – massive Duplicate-Content-Probleme auftreten können. Für oben genanntes Beispiel der URL dieses Beitrages wäre eine mod_rewrite-Anweisung wie diese zu benutzen:

RewriteEngine on
RewriteRule ^news/([0-9]+)-([a-z0-9-.]+).html$ beitrag.php?id=$1&title=$2

Im Script beitrag.php ist nun neben der Prüfung, ob die übergebene Id überhaupt existiert und der Ausgabe des Beitrages auch zu überprüfen, ob der übergebener, also tatsächlich angezeigter Dateiname auch dem entspricht, den die Funktion filename(); erzeugt hätte. Sollte dies nicht so sein, weil jemand falsch verlinkt oder sich der Titel geändert hat, so ist mit einem 301-Redirect auf die korrekte Adresse weiterzuleiten und das Script an dieser Stelle abzubrechen.

Ähnliche Beiträge
Kommentare
Avatar Pelle Boese   
5. September 2007, 10:35

Es muss natürlich heißen:

echo ‚<a href=“/news/‘.$id.‘-‚.filename($titel).‘.html“>‘.htmlentities($titel).'</a>‘;

NICHT dirname($titel)

Ansonsten prima Schnipsel, besonders für Einsteiger definitiv wertvoll!

Johannes   
5. September 2007, 10:57

Ja klar, danke für den Hinweis. Hab es im Posting schon verbessert.

Avatar David   
5. September 2007, 11:18

Weshalb überhaupt IDs in den URLs?

Wesentlich sinnvoller ist es, den Titel direkt von allen Sonderzeichen zu befreien und anschließend in einer eigenen Spalte abzulegen:

Bsp:
id | titel | url_title
—————————————-
id | Ist das besser? | ist-das-besser

Nun kann auf die ID in der URL komplett verzichtet werden, da sich ein Datensatz alleine durch seinen Titel bestimmen lässt. Vorrausgesetzt dieser ist eindeutig.

Etwas mehr Programmieraufwand, dafür schönere URLs!

Johannes   
5. September 2007, 11:43

David, prinzipiell hast du schon Recht damit, dass solche URLs schöner sind, wir setzen diese Variante auch bei einigen Projekten ein. Allerdings bedeutet sie auch einen deutlich höheren Aufwand im Backend und bei der Logik einiger Abläufe: Was passiert, wenn es diese URL bereits gibt, was passiert, wenn sich er Titel ändert (soll es dann eine Tabelle mit neuen und alten URL geben) und so weiter. Auch ist bei sehr großen Datenmengen die Suche über eine Int doch immer noch vorteilhafter.

Avatar David   
5. September 2007, 12:13

Der Programmieraufwand steigt, das ist richtig – wie ich auch schon geschrieben hatte. Sobald man allerdings eine vernünftige Datenbankabstraktionsschicht einsetzt, lässt sich dieser Mehraufwand auf ein minimales reduzieren (Stichworte: Propel, Behaviour, Wiederverwendbarer Code…).

Im Backend (für den Anwender) hat das meiner Meinung nacht jedoch nichts zu suchen.

Die einfachste Möglichkeit ist es, bei einer Titeländerung den alten „title_url“ beizubehalten.

Für höhere Ansprüche – 2 Ansätze:
– Tatsächlich eine weitere Tabelle in der alte Titel aufbewahrt werden
– Falls Datensätze sowieso in verschiedenen Revisionen vorhanden sind, kann der alte Titel noch in der Tabelle gefunden werden.

Der Geschwindigkeitsunterschied zwischen Indizes auf Integer und Varchar Spalten ist marginal und fällt wirklich nur bei riesigen Datenbeständen auf – und hier zumindest sollte genug Kapital vorhanden sein um skalierbare Hardware anzuschaffen.

Falls die URL schon existiert, wird die Datenbank meckern, da ein Unique Index auf der Spalte liegt. Entweder muss anschließend eine Korrektur des Titels, eine Korrektur des title_url – oder es wird einfach ein suffix angehängt (z.B. fortlaufende Nummern).

Das ganze mag jetzt durchaus komplex wirken. In dem Webframework meiner Wahl (Symfony – http://symfony-project.com ) ist die Implementierung eine Sache von 2 Stunden – und lässt sich anschließend beliebig häufig einsetzen.

Avatar Horst   
5. September 2007, 12:20

Wo wir dabei sind: Ich bin ein Freund echter HTML-Seiten. Also statt nur mit Rewrite so zu tun, als ob es statische HTML-Seiten wären, lege ich wirklich echte Seiten an, die dann bei Änderungen automatisch aufgefrischt werden.
Es ist ja relativ einfach möglich festzustellen, ob es sich um pseudo-statische-Seiten oder echte statische Seiten handelt. Aber hat das auch Einfluss auf das Ranking?

Avatar Pelle Boese   
5. September 2007, 13:41

Für flache Strukturen finde ich IDs im Titel kein Problem, habe damit auch in Bezug auf SEO keinerlei negativen Erfahrungen gemacht. Also z.B.

foo.de/1-tolle-sache.html
foo.de/2-noch-tollere-sache.html

Sobald ich mehr als eine Ebene habe, verzichte ich aber auf IDs im Verzeichnisnamen, nur der Dateiname darf evtl eine enthalten:

foo.de/geschenke/1-tolles-produkt.html
foo.de/geschenke/2-affenfeine-kiste.html
foo.de/bier/3-lecker.html

Symfony mag ich trotzdem nicht und Propel erst recht nicht 🙂 Besonders wegen des Stichwortes „Wiederverwertbarer Code“ – Klar, innerhalb des Frameworks wiederverwertbar, ansonsten eher nutzlos. Ich habe bisher (leider?) noch kein Framework gefunden, welches meinen Ansprüchen an Performance und Sicherheit gerecht wird.

Zu Horst: Wie unterscheidest Du dynamische von statischen Seiten? Wenn man die richtigen Header mitschickt, sollte dies unmöglich sein.

Avatar Leo   
6. September 2007, 17:44

Wie sieht es aus, wenn ein Artikelname Zeichen enthält, die nicht in der Adresszeile dargestellt werden können (z.B. aus einem anderen Alphabet)? Soll man es dann in Bezug auf Suchmaschinen so, wie auf Wikipedia tun (z.B. http://bg.wikipedia.org/wiki/%D0%A3%D0%B8%D0%BA%D0%B8 ) oder es lieber ganz lassen?

Johannes   
6. September 2007, 21:57

Leo, die Wikipedia lässt, wenn ich mich richtig erinnere, ein urlencode über ihre UTF-8-Namen der Artikel laufen. Probleme gibt es damit nicht, die meisten Browser und auch Google zeigen die URL dann direkt mit korrekten Umlauten an. Als Nachteil sehe ich eventuell, dass solche URLs schwerer und fehleranfälliger weitergegeben werden können.

Avatar Thomas   
10. September 2007, 18:36

pelle: wenn du performance und sicherheit willst, bist du bei php an der ganz falschen stelle.

Avatar Affiliatebusiness.de   
1. Oktober 2007, 14:32

[…]Da mir aber zu Ohren kam, dass das Alter einer Domain eine nicht unerhebliche Rolle auf ihr Listing in den Suchmaschinen hat, dachte ich mir, dass ich den Sumas schonmal ein wenig Futter gebe und habe ein kleines Script in die Tasten gehackt, welches die Domain vorweg schonmal mit etwas (CSV-)Content versorgt. Hier ein paar Fakten und Dinge, auf die ich geachtet habe[…]

Die Kommentarfunktion wird 30 Tage nach der Veröffentlichung des Beitrags deaktiviert.