Das Putzlowitsch Test- und SEO-Blog

Alles Nichts oder nicht alles?

Google-Treffer mit Parameter

Wenn Besucher über Google auf die eigene Webseite kommen, ist das ja normalerweise eine schöne Sache. Allerdings nicht, wenn es über einen seltsamen Link, wie er oben zu sehen ist, passiert. Wie kommt aber soetwas überhaupt in den Index einer Suchmaschine?

Das gibts doch gar nicht

Bereits im Oktober letzen Jahres hatte ich etwas Ähnliches beobachtet. Da wurden Google massiv mit Links auf irgendwelche nicht existierende Seiten gefüttert. Wenn nun eine dieser nicht vorhandenen Seiten auf die Anfrage des Googlebots einen HTTP-Status „200 OK“ zurückliefert, geht Google davon aus, daß es die Seite gibt und nimmt sie in den Index auf. Korrekterweise sollte aber mit dem Fehlerstatus „404 Not found“ geantwortet werden, so daß die Seite nicht im Index landet. Genau das war damals bei mir der Fall, also ist eigentlich alles in Butter. Nur habe nicht mit der Großzügigkeit von WordPress gerechnet.

Die WordPress.presse.pressung

In manchen Dingen ist WordPress recht großzügig. Früher war es möglich, wenn in den Permalinks die Artikel ID verwendet wurde, einen Artikel über nahezu beliebig viele URLs aufzurufen. Sobald die ID erkannt wurde und existierte, wurde der Rest der URL nicht weiter überprüft. So hätte man diesen Beitrag hier auch noch mit /alles-quark-399/ oder /blafasel-399/ aufrufen können. Das geht mittlwerweile nicht mehr. Allerdings ist zur Zeit etwas Ähnliches immer noch möglich, wenn man in den Permalinks die Kategorie verwendet.

Wenn nun eine WordPress-Seite mit Parametern in der Form /?parameter=wert aufgerufen wird, ignoriert WordPress einfach unbekannte Patemeter oder ungültige Paremeterwerte und tut so, als würde es diese Parameter gar nicht geben. Somit führen folgende Aufrufe zu gültigen Seiten:

http://testblog.schnurpsel.de/?q=Diese Seite gibt es nicht
http://testblog.schnurpsel.de/?quark=Gesund und schmeckt lecker
http://testblog.schnurpsel.de/?p=Hier steht normalerweise die ID

Bei den ersten beiden Beispielen wir ein unbekannter Paremeter verwendet, im dritten Beispiel der gültige Parameter p= (Short-Link), der allerdings eine numerische Artikel-ID erwartet. In allen Fällen wird die Startseite mit dem Status „200 OK“ angezeigt. Es funktioniert aber ebenso mit Einzelseiten oder anderen Permalinks:

http://testblog.schnurpsel.de/...hallo-welt/?frage=was-soll-das
http://testblog.schnurpsel.de/2010/03/?jahreszeit=Frühling

Gut oder schlecht

Ob dieses Verhalten von WordPress nun gut oder schlecht, gewollt oder ein Fehler ist, mag ich nicht beurteilen. Ich finde es zumindest suboptimal, denn dadurch entstehet z.B. die oben gezeigte URL als Google-Treffer, und sowas möchte ich nicht haben. Dabei wäre es für WordPress kein größeres Problem, unbekannte Parameter oder ungültige Parameterwerte als Fehler zu behandeln. Das schöne an WordPress ist ja, daß es recht einfach erweitert und modifiziert werde kann.

Fehler bleibt Fehler

Deshalb habe ich mir diese Parameterprüfung hier nachgerüstet (aber nicht für den Testblog!), übrigens auch für die worpdresseigene Suchfunktion. Denn falls es keinen Suchtreffer gibt, finde ich, ist das auch einen „404 Not Found“ wert :-)
Nun sollte auch die ganz oben gezeigte, hier nicht existierende Seite nach einiger Zeit aus dem Suchindex verschwinden.

Nachtrag:
Weil es angefragt wurde, hier mein Code zur Parameterprüfung, der sich per Action-Hook in parse_request reinhängt:

<?php
 function plw123_parse_request( $data ) {
  // Liste der numerischen Parameter
  $num_para = array( 'p', 'page_id', 'attachment_id', 'tag_id',
          'page', 'paged',
          'year', 'monthnum', 'day', 'w', 'm',
          'hour', 'minute', 'second' );
  // Parameter übergeben, aber nicht gefunden
  foreach( $_GET as $key => $value )
   if( !array_key_exists( $key, $data->query_vars ) ) {
    $data->query_vars['error'] = '404';
    return;
   }
  // Numerische Parameter prüfen
  foreach( $data->query_vars as $key => $value ) {
   // Sonderbehandlung Kategorie-IDs
   if( 'cat' == $key ) {
    // darf eine Liste von kommaseparierten Integerwerten sein
    $test_value = preg_replace( '|[^0-9,-]|', '', $value );
    if( $test_value != $value ) {
     $data->query_vars['error'] = '404';
     return;
    }
   }
   // Numerische Werte
   if( in_array( $key, $num_para ) ) {
    $value = trim( $value );
    // Page bei Einzelansicht (Seite, Artikel) kann führenden Slash enthalten
    if( 'page' == $key )
      $value = ltrim( $value, '/' );
    $test_value = absint( $value );
    if( !$test_value ) {
     $data->query_vars['error'] = '404';
     return;
    }
   }
  }
 }
 add_action( 'parse_request', 'plw123_parse_request' );
?>

Habe das jetzt mal erweitert und in ein Plugin gepackt: 123 Prameter Check

4 Kommentare »

Höher, schneller, weiter

Mit den Google-Webmastertools bekommt man einen guten Überblick, wie oft der Googlebot vorbeischaut und wieviele Daten er in welcher Zeit Abfragt.

Pro Tag gecrawlte Seiten

Google - Crawling Anzahl der Seiten pro Tag Februar 2010
Auf dem Diagramm ist noch das Ende vom November, der ganze Dezember und Januar und der Anfang vom Februar zu sehen. Scheinbar tritt der Googlebot auch über den Jahreswechsel etwas kürzer, feiert Weihnachten und Silvester und legt dann erst Mitte Januar wieder richtig los.

Pro Tag heruntergeladene Kilobyte

Google - Crawling Datenmenge in kByte pro Tag Februar 2010
In etwa parallel dazu verläuft normlerweise die Kurve zu den täglich heruntergeladenen Datenmengen. Klar, je mehr Seiten angefragt werden, um so mehr Daten fallen da durchschnittlich an.

Eines fällt aber auf, denn obwohl die Anzahl der pro Tag abgefragten Seiten ab Mitte Januar und im Februar höher liegen als noch im November, ist die Datenmenge nicht in gleichem Maße angestiegen. Der Grund ist recht einfach. Ich hatte Anfang/Mitte Dezember die gzip-Komprimierung für die Seiten aktiviert.

Dauer des Herunterladens einer Seite (in Millisekunden)

Google - Crawling Zeit in Millisekunden pro Seite Februar 2010
Die Geschwindigkeit der Seitenauslieferung ist die für den normalen Nutzer, also den Besucher einer Website der wohl wichtigste, technische Wert. Wenn erstmal ein paar Sekunden nach dem Aufrufen einer Seite oder länger nichts passiert, ist das aus Anwendersicht eher unerfreulich.

Der Wert lag im November bei etwa 1,5 Sekunden und schließt damit an die Zahlen vom Oktober an. Anfang Dezember bin ich dann Dank SpeedPlus wieder zu Strato zurückgekehrt und seitdem liegen die Ladezeiten fast immer bei erfreulichen 0,8 Sekunden. Aber eben nur fast. Wie man im Diagramm sieht, gab es schon im Dezember und Anfang Januar Ladezeitspitzen, die dann im Februar nochmal deutlich zunahmen. Allerdings ist das eher darin zu sehen, daß durch die größere Anzahl der pro Tag abgefragten Seiten auch die Wahrscheinlichkeit für den Googlebots auf eine Lastspitze zu treffen, größer war.

Ungeachtet dessen gibt es aber diese Lastspitzen, die nicht nur der Googlebot „sieht“, sondern auch der normale Nutzer bemerkt. Wenn man Pech hat, dauert das Laden einer Seite wieder 4 bis 6 Sekunden, ganz so wie vor der SpeedPlus-Zeit bei Strato. Diesmal ist es aber meiner Meinung nach nicht die schlechte PHP-Performance, sondern eher die Datenbank. Die Datenbankserver sind zwar grundsätzlich nicht wirklich lahm, legen aber ab und zu ein paar Gedenkminuten ein, wie mir scheint. Und genau dann dauert der Seitenaufruf wieder mehrere Sekunden. Kürzlich gab es auch wieder mal einen Totalausfall, der dann zu einem 500er Fehler führt.

Hin und weg

Nun sind zwar PHP und Webserver bei Strato schnell, aber die Datenbank klemmt mitunter. Deshalb bin ich vorerst wieder zu meiner externen Datenbank zurückgekehrt. Das eigentlich langsame ist hierbei die Datenübertragung über das Internet zwischen Strato (Karlsruhe/Berlin) und Host-Europe (Köln). Um das etwas abzudämpfen, habe ich zusätzlich ein Datenbank-Cache-Plugin installiert, welches häufig benötigte Daten auf dem Webspace bei Strato im Dateisystem ablegt, um diese nicht jedesmal neu übertragen zu müssen. Zumal sich viele Daten, z.B. die Artikel und Seiten normalerweise eh nicht ändern.

Nun werde ich das Alles mal weiter beobachten, wie das mit den Ladezeiten so aussieht und hoffe aber trotzdem, das Strato die Datenbankaussetzer in den Griff bekommt.

Keine Kommentare »

Permalinks – Was verwenden die 33 deutschen Top-Blogs

Welcher Permalink ist das beste Ding?

Die Diskussion taucht immer wieder mal auf, wie sieht optimalerweise ein Permalink, also die Struktur der URL aus. Sollten das Datum oder die Artikel-ID enthalten sein, ist es sinnvoll Kategorien oder Tags mit aufzunehmen?

Eine allgemeingültige und endgültige Empfehlung kann es nicht geben, wenn man die unterschiedlichen Sichtweisen dazu berücksichtigt, die dann zu eher widersprüchliche Aussagen führen.

Betreibt man ein Blog im Sinne eines Tagebuches, ist sicher das Datum oder Bestandteile davon eine gute Wahl. Aus SEO-Gesichtspunkten bzw. für eine eher thematische Ausrichtung wird oft die Kategorie mit in die Permalinkstruktur aufgenommen. Für eine Webseite mit vielen Schreibern könnte auch der Autorenname eine geeignete Option sein.

Ich habe mir einfach mal die Permalink-Struktur der 33 deutschen Top-Blogs angesehen. Vielleicht läßt sich ja daraus eine Empfehlung ableiten.

Die Permalink-Struktur der 33 deutschen Top-Blogs

Zunächst stellt sich natürlich die Frage, welche sind denn die Top-Blogs in Deutschland? Auch hier kann man sich endlos streiten, wenn man will. Ich habe als erste Näherung einfach die aktuell zusammengerechnete Liste von heute, dem 24.02.2010, genommen. Die Permalinkstruktur habe ich in Gruppen zusammengefaßt, vor dem jeweiligen Blog steht der aktuelle Platz in der Top-33-Liste :

Mehr als die Hälfte (57,6%) der Top-33-Blogs verwendet neben dem Artikelnamen das Datum oder einen Bestandteil davon in der URL. Bei allein fast 40% findet man das komplette Datum mit Jahr, Monat und Tag im Permalink. Gut 18% benutzen nur den Namen des Artikels als Permalink und weitere etwa 12% kombinieren dazu noch eine Nummer (Artikel-ID). Immerhin knapp 10% der Top-Blogs verwenden keine Permalinks, sondern setzen auf die Artikelnummer als URL-Parameter (?id=1234).

Erste Ableitung des Permalink-Aufbaus

Wenn man Permalinks verwendet, ist der Artikelname (in seiner Umwandlung zu einem URL-Pfad) gewissermaßen eine feste Größe. Die Einbeziehung des Datums oder von Teilen kann so schlecht nicht sein, diese Verwendet ein Großteil der Top-Blogs. Auch ganz auf Permalinks zu verzichten, hat gewisse Vorteile. Die URLs sind kurz und bleiben immer gültig, auch wenn man mal was am Artikel-Titel, dem Datum oder sonstigen Einflußfaktoren ändert.

Ich habe mir stichprobenartig noch weitere Blogs der Top-100 angesehen und zumindest keine Seite entdeckt, die etwa die Kategorie oder gar Tags in der URL verwendet. Mal davon abgesehen, daß Tags bei WordPress bis zur Version 2.9.x nicht als Bestandteil der Permalinks funktionieren (obwohl in der Dokumentation genannt), gibt es auch noch andere Probleme.

Kategorie oder Tag im Permalink

In WordPress kann man Artikel in mehreren Kategorien ablegen. Einem Artikel können zudem auch mehrere Tags zugeordnet werden. Verwendet man Kategorien oder Tags in Permalinks, erstellt WordPress die die URL aus der Kategorie oder dem Tag mit der kleinsten ID. Ändert man nun die Kategoriezuordnung oder die Tags, kann sich möglicherweise auch die URL ändern.

Das ist aber erstmal nicht weiter schlimm, denn der Artikel wird auch weiterhin mit der alten Kategorie gefunden und angezeigt. WordPress geht sogar soweit, einfach die Kategorie beim Auflösen der Permalinks zu ignorieren. Damit ergeben sich dann theoretisch beliebig viele URLs für einen Artikel.

Als Beispiel ist das auf meinem Testblog zu sehen. Die Permalink-Struktur sieht so aus:

/%category%/%postname%/

Der Artikel ist in der Kategorie „Allgemein“ einsortiert, die URL sieht so aus:
http://testblog.schnurpsel.de/allgemein/hallo-welt/

Er ist aber auch mit der Kategorie „Blafasel“, „Hundekuchen“ oder „Gibtesnicht“ aufrufbar:
http://testblog.schnurpsel.de/blafasel/hallo-welt/
http://testblog.schnurpsel.de/hundekuchen/hallo-welt/
http://testblog.schnurpsel.de/gibtesnicht/hallo-welt/
Genau, diese Kategorien gibt es gar nicht.

Man hat damit potentiell also ganz viel bösen „Duplicate content“ (DC). Da sage noch einer, die Kategorie im Permalink sei unter SEO-Gesichtspunkten empfehlenswert. ;-)

Permalink, so oder so

Letztendlich muß jeder selbst entscheiden, ob und wie er seine Permalinks gestaltet. Bei Putzlowitsch habe ich mich für das Datum entschieden, da ich dort eher im Sinne eines Tagebuchs schreibe. Hier verwende ich eine Kombination aus Artikelname und Artikel-ID, weil die sichtbare ID schnelle interne Links mit dem 123 IntLink-Plugin ermöglicht. Bei Twitter verwende ich übrigens gerne die WP-Shortlinks mit der ID als URL-Parameter, die sind schön kurz und funktionieren auch ohne Shortlink-Dienst.

Ein Kommentar »

Mit welcher WordPress-Version läuft ein WordPress-Blog?

WordPress habe ich seit Oktober 2006 in Benutzung (1&1 Fertigblog), mein erstes selbstinstalliertes WordPress im November 2006 hatte die Version 2.0.4. Seitdem ist einige Zeit ins Land gegangen und mittlerweile sind wir bei WordPress Version 2.9.1 angekommen, die Version 3.0 ist schon angekündigt und soll im März erscheinen.

Mit jeder neuen WordPress-Version gab es meist neue Funktionen, manchmal war eine neue Ausgabe aber auch nur ein Sicherheits-Release, um bekannt gewordene Sicherheitslöcher zu stopfen. Damit sind Sicherheitslücken und deren Ausnutzbarkeit immer von der WordPress-Version abhängig, wodurch die Versions-Information für einen Angreifer durchaus interessant ist.

Die WordPress-Versionsnummer anzeigen

WordPress liefert in der Standardinstallation die Versionsinformationen gleich an drei Stellen mit. Zwar sind diese für den normalen Besucher üblicherweise nicht sichtbar, aber in der Seite vorhanden.

Im Header der Seite
Wen man sich den HTML-Quelltext einer Seite ansieht, findet man dort möglicherweise im Header einen Eintrag wie <meta name=“generator“ content=“WordPress 2.9.1″ />
Wordpress-Version im Header der Seite

Im Feed
Wen man sich den XML-Quelltext eines Feeds (RSS, Atom) ansieht, findet man dort möglicherweise am Anfang (channel) einen Eintrag wie <generator>http://wordpress.org/?v=2.9.1</generator>

Wordpress-Version im Feed

In der readme.html
Mit jeder WordPress-Version wird eine Datei readme.html und in der deutschen Version auch liesmich.html mitgeliefert bzw. installiert. Diese findet man im WordPress-Wurzelverzeichnis. Da steht die WordPress-Version ebenso drin:
Wordpress-Version in der readme.html

WordPress-Version verbergen

Man mag darüber streiten, ob es sinnvoll ist, die Versionsnummer vor Bots oder wem auch immer zu verbergen. Für die Unterdrückung der Ausgabe in den Seiten und Feeds gibt es diverse Lösungen. Wenn man nun aber so großen Wert darauf legt, die WP-Version zu verstecken, sollte man unbedingt auch die readme.html (liesmich.html) löschen. Aber Achtung, beim nächtens (automatischen) Update ist sie wieder da.

Weitere Artikel mit Bezug zu diesem:
Keine Kommentare »

WordPress für statische Seiten optimieren

WordPress und Permalinks

In WordPress kann man für schönere URLs die Permalinks aktivieren. Diese werden nur für die Struktur der Artikel-URL festgelegt, zusätzlich kann ein Präfix für Kategorien und Tags vorgegeben werden, für Seiten jedoch gibt es keine extra Einstellmöglichkeit.

Für Artikle steht eine Vielzahl von von Platzhaltern (Variablen) zur Verfügung, die bei Zusammensetzen der URL durch die jeweiligen Daten des konkreten Artikels ersetzt werden.

Auch wenn man Permalinks nur für die Artikle wirklich konfigurieren kann, wirken sich die dort gewählten Optionen auch auf die Seiten und andere URLs in WordPress aus. Einen sichtbaren Effekt hat die Entscheidung, ob man die Permalinks mit einem Schrägstrich abschließt oder nicht. Entsprechend erhalten auch alle anderen von WordPress generierten URLs diesen Schrägstrich oder nicht. Das gilt übrigens nur für den Schrägstrich (Slash), alle anderen Endungen wie z.B. .html werden dabei nicht übernommen.

WordPress und Rewrite-Rules

Damit WordPress die Permalinks wieder in konkrete Artikel- und Seiten-IDs auflösen kann, wird eine Liste von Regeln (RewriteRules) erstellt, die sequentiell abgearbeitet wird. Mit dem ersten passenden Treffer wird dann die Datenbankabfrage für einen Artikel oder eine Seite, für eine Kategorie- oder Tagübersicht oder einen Feed usw. erstellt.

Wie diese interne Liste aussieht hängt unter anderem auch davon ab, welche Struktur für die Artikel bei der Permalinkkonfiguration gewählt wird. WordPress muß Artikel von Seiten eindeutig unterscheiden können und das funktioniert nur, wenn die Permalinks als ersten Platzhalter keinen variablen Wert wie Postname (%postnam%), Kategorie (%category%), Tag (%tag%) oder Autor (%author%) enthalten. Andernfalls werden für jede statische Seite jeweils 11 Einträge in der Liste der RewriteRules erstellt, die so aussehen:

[seite-1/attachment/([^/]+)/?$] => index.php?attachment=$matches[1]
[seite-1/attachment/([^/]+)/trackback/?$] => index.php?attachment=$matches[1]&tb=1
[seite-1/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
[seite-1/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
[seite-1/attachment/([^/]+)/comment-page-([0-9]{1,})/?$] => index.php?attachment=$matches[1]&cpage=$matches[2]
[(seite-1)/trackback/?$] => index.php?pagename=$matches[1]&tb=1
[(seite-1)/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?pagename=$matches[1]&feed=$matches[2]
[(seite-1)/(feed|rdf|rss|rss2|atom)/?$] => index.php?pagename=$matches[1]&feed=$matches[2]
[(seite-1)/page/?([0-9]{1,})/?$] => index.php?pagename=$matches[1]&paged=$matches[2]
[(seite-1)/comment-page-([0-9]{1,})/?$] => index.php?pagename=$matches[1]&cpage=$matches[2]
[(seite-1)(/[0-9]+)?/?$] => index.php?pagename=$matches[1]&page=$matches[2]

Das mag bei wenigen Seiten zwar kaum ins Gewicht fallen, bei hunderten oder gar tausenden Seiten aber schon. Einerseits belegen diese vielen Regeln Speicher, andererseits müssen sie jedesmal abgearbeitet werden, bei z.B. 300 Seiten mehr als 3300 Listeneinträge. Probleme kann es auch beim Anlegen und Ändern von Seiten geben, denn die Liste muß dann jedesmal neu erstellt werden.

Permalinks für statische Seiten optimieren

Wenn man viele statische Seiten verwendet oder vielleicht gar keine Artikel (WordPress als CMS), sollte man als ersten Platzhalter (Strukturtag) in den Permalinks einen numerischen Wert wie Datum (year,monthnum,day), Zeit (hour,minute,second) oder die ID (post_id) verwenden. Die von WordPress zur Auswahl angebotenen Möglichkeiten erfüllen diese Bedingungen:

Tag und Name: /%year%/%monthnum%/%day%/%postname%/
Monat und Name: /%year%/%monthnum%/%postname%/
Numerisch: /archives/%post_id%

Für Benutzerdefinierte Einstellungen wären z.B. /%post_id%-%postname%/ geeignet. Es darf auch ein fester Text vor dem ersten numerischen Wert stehen, also z.B. /news/%post_id%-%postname%/.

Mit diesen Permalinkeinstellungen werden keine extra Rules je Seite erzeugt, das spart zumindest bei WordPressinstallationen mit sehr vielen statischen Seiten Speicherplatz und Abarbeitungszeit.

Weitere Artikel mit Bezug zu diesem:
7 Kommentare »