Suchmaschinenfreundliches contenido

Contenido hat sich in den letzten Jahren zu einem der führenden Open-Source Content Management Systeme im deutschsprachigen Raum entwickelt. Was nicht zuletzt auf eine einfache Bedienung und flexible Anpassungsmöglichkeiten zurückzuführen ist. Dieser Artikel soll aber nicht die Vorzüge von contenido ausarbeiten, sondern wendet sich an contenido Entwickler, die Ihre contenido Seite für Suchmaschinen optimieren wollen. Die On-Page Optimierung ist hier das alleinige Thema, also alle Arbeiten, die an der Seite selber (Quellcode, Texte, Indizierbarkeit usw.) durchgeführt werden. Die hier beschriebenen Anpassungen sind von mir bereits auf einer contenido Testseite umgesetzt worden. Das lockert vielleicht die trockene Theorie hier ein wenig auf.

Directory Index

Contenido bringt von Haus aus bereits eine Eigenschaft mit, die Suchmaschinen überhaupt nicht schmeckt. Die Weiterleitung von der index.php auf front_content.php. Zum Glück gibt es hierfür eine bestechend einfache Lösung:

  1. Die Domain Root auf das cms Verzeichnis des Mandanten legen. Für den contenido Log-In muss dementsprechend eine eigene Domain/Subdomain angelegt werden.
  2. Im Hauptverzeichnis eine .htaccess mit folgendem Inhalt anlegen:
DirectoryIndex front_content.php 
		index.php index.htm index.html

Wer versucht, die front_content.php z.B. in index.php umzubenennen macht sich jede Menge unnötige Arbeit bei den Codeanpassungen im contenido Quellcode.

Duplicate Content

Es gibt 3 Möglichkeiten auf einen Startartikel in contenido zuzugreifen (2 Varianten für gewöhnliche Artikel):

  1. Nur die idcat übergeben und der Startartikel wird automatisch angezeigt
  2. idcat und idart des Startartikel übergeben
  3. idcatart des Startartikels übergeben

Möglichkeit Nr. 1 wird meistens in der Navigation verwendet, Nr. 2 wird von einigen Modulen ausgegeben und Nr. 3 erscheint bei einer Verlinkung über den WYSIWYG-Editor. Für die Suchmaschinen sind das 3 verschiedene Seiten mit exakt dem gleichen Inhalt. Bei einer Seite mit 50 Artikeln macht das schon jede Menge doppelten Content, was viele Suchmaschinen als Spamming auslegen und unter Umständen negativ bewerten. Die Anpassungen, um das zu vermeiden beschränken sich lediglich auf die Module und die Navigation, wenn man sich für die konsequente Verwendung der idcatart entscheidet. Oder man liest den nächsten Abschnitt über Url-Rewriting

Url-Rewriting

Das Apache Modul mod_rewrite ist ein fantastisches Modul, um dynamischen Seiten einfache URL´s zu verpassen. Nicht nur für Suchmaschinen, sondern auch für den ganz normalen Besucher, den es ja auch noch geben soll. Das neue contenido 4.6 hat zu diesem Thema bereits die Aliase eingeführt und damit einen ersten Schritt in Richtung Suchmaschinenfreundlichkeit getan. In diesem Artikel will ich aber nur auf die Möglichkeiten von contenido 4.4 und kleiner eingehen. Ziel ist es eine URL mit diesem Schema zu erhalten: [domain].de/[Kategorie]-[idcat]-[client]-[lang]-[idart].html. Da die Kategorien einer Webseite in den meisten Fällen auch relevante Keywords sind, haben wir dadurch viele URL´s mit wichtigen Keywords.

Als erstes brauchen wir wieder eine .htaccess im Hauptverzeichnis mit folgendem Inhalt:

Rewrite Engine On
RewriteRule ^(.*)-([0-9]*)-([0-9]*)-([0-9]*)-
	([0-9]*).html$
/front_content.php?idcat=$2&client=$3&
lang=$4&idart=$5

RewriteRule ^(.*)-([0-9]*)-([0-9]*)-
	([0-9]*)-.html$ 
/front_content.php?idcat=$2&
	client=$3&lang=$4

Im Layout muss eine PHP-Datei includiert werden, die 2 Funktionen enthält, welche wir für die Ausgabe von den oben beschriebenen URL´s verwenden. Am besten diese Datei im Hauptverzeichnis des Mandanten ablegen, so kann man für jeden Mandanten individuelle Anpassungen am URL-Rewriting machen. Hier nun die PHP-Funktionen:

/**
 * Ausgabe der URL´s für mod_rewrite
 * 
 * @param $arrValues Array Eigenschaften 
 * der Kategorie als 
 * Assoziatives Array z.B. 
 *Array("idcat"=>10,"idart"=>24)
 * @return Array URL in der Form 
 *[Kategorie]-[idcat]-[client]-[lang]-[idart].html
 **/
function url ($arrValues) {
global $sess, $client, $lang;
  if (!$arrValues['lang']) $arrValues['lang']
   = $lang;
   $arrCat = getCatData($arrValues);
 $mylang = $lang;
if ($arrValues['lang']) $mylang = 
	$arrValues['lang'];
if ($arrCat['is_start'] == 1) 
	unset($arrValues['idart']);
$strURL = urlencode( ret_entities($arrCat['name']) )
."-".$arrValues['idcat']."-".$client."-".$mylang."-"
.$arrValues['idart'].".html";
return $strURL;
}

/**
 * Umwandeln von Sonderzeichen 
 * in suchmaschinenfreundliche
 * Zeichen für URL-Rewriting
 * @param $text String zu konvertierender Text
 * @return String konvertierter Text
 **/
function ret_entities($text) {
$patterns = array("ae","ue","oe","Ae","Ue","Oe","ss",
    "-","" ,""  ,"_",""  ,"" ,"" ,"_","-","-" ,"-" );
$replace = 	array("ä" ,"ü" ,"ö" ,"Ä" ,"Ü" ,"Ö" ,"ß" 
 ," ","'","\"","/","\?","´","`","&",",","\(","\)");
for ($i=0;$i<count($patterns);$i++) {
 $text = ereg_replace($replace[$i],$patterns[$i],$text);
}
return $text;
}

/**
 * Eigenschaften einer Kategorie auslesen 
 * @param $arrValues Array Eigenschaften 
 *der Kategorie als
 * Assoziatives Array z.B. 
 *Array("idcat"=>10,"idart"=>24)
 * @return Array Daten der Kategorie z.B. Name
 **/
function getCatData($arrValues, $idcatart = 0) {
	global $db3, $cfg, $lang;
 if ($idcatart > 0) {
     $sql = "SELECT idcat, is_start FROM "
     .$cfg["tab"]["cat_art"]." WHERE idcatart='"
	  .$idcatart."'";
     $db3->query($sql);
     $db3->next_record();
     $arrValues['idcat'] = $db3->f("idcat");
 }
if ($arrValues['idart']) {
   $sql = "SELECT is_start FROM ".$cfg["tab"]
		["cat_art"].
    " WHERE idart='".$arrValues['idart']."' 
	 	AND idcat='"
	 .$arrValues['idcat']."'";
       $db3->query($sql);
       $db3->next_record();
	$is_start = $db3->f("is_start");
}
$arrReturn = Array();
$sql = "SELECT
	CAT.idcat AS idcat, name ,parentid, level	
	FROM
	".$cfg["tab"]["cat"]." AS CAT,
	".$cfg["tab"]["cat_lang"]." AS CATLANG,
	".$cfg["tab"]["cat_tree"]." AS CATLEVEL

	WHERE
	CAT.idcat        = '".$arrValues['idcat']."' AND
	CAT.idcat        = CATLANG.idcat AND
	CATLANG.idlang   = '".$arrValues['lang']."' AND
	CAT.idcat        = CATLEVEL.idcat";

$db3->query($sql);
while ( $db3->next_record() ) {
	$arrReturn = Array(
	'level' 	=> $db3->f("level"),
	'name'  	=> $db3->f("name"),
	'parent'	=> $db3->f("parentid"),
	'cat'   	=> $db3->f("idcat"),
	'is_start'	=> $is_start,
	);
} // end while
return $arrReturn;
}

Um doppelten Content zu vermeiden wird vorher geprüft, ob es sich bei der übergebenen idart um einen Startartikel handelt. Falls ja wird die idart nicht ausgegeben. Die URL sieht dann z.B. so aus: Leistungen-12-1-1-.html. Es werden also nur idcat, lang und client angegeben. Wer will kann das System auch so vereinheitlichen, dass immer eine idart, selbst bei Startartikeln, angegeben wird. Das macht aber die Navigation etwas aufwendiger, da zu jeder Kategorie die idart des Startartikels abgefragt werden muss.

Für die konsequente Verwendung des URL-Rewriting müssen zu guter Letzt noch ein paar Anpassungen am WYSIWYG-Editor Spaw gemacht werden. Dieser schreibt beim Einfügen von Links immer noch front_content.php.... Also wieder eine potentielle Quelle für doppelten Content, denn front_content.php?idcat=24 ist das gleiche wie Leistungen-24-1-1-.html.

Die Änderungen müssen nur in folgender Datei vorgenommen werden /contenido/external/wysiwyg/spaw/dialogs/insert_link.php

  1. nach Zeile 16 einfügen:
    cInclude("includes", "functions.api.string.php");
    // HIER DEN PFAD ZU DER INCLUDE DATEI MIT 
    //DEN PHP-FUNKTIONEN ANPASSEN
     require_once($cfgClient[$client]['path']
     ['frontend']."
      /datei-mit-den-php-funktionen.inc.php");
  2. Zeile 133 ersetzten durch:
     echo "<option style=\"$style\" value=\""
     .url( Array("idcat"=>$db->f("idcat"),
     "lang"=>$lang,"client"=>$client) )
    ."\">$spaces > ".$db->f("name")."</option>";
    
  3. Zeile 170 ersetzten durch:
    echo "<option style=\"$style\" value=\""
    .url( Array("idcat"=>$db2->f("idcat"),
     "idart"=>$db2->f
    ("idart"),"lang"=>$lang,"client"=>$client) )."\"
    >  $spaces |  "
    .$tmp_title."</option>";
    

Mit diesen Änderungen sind bereits die wichtigsten Eigenschaften von contenido beseitigt, die den Suchmaschinen im Weg sind. Der Rest der On-Page Optimierung ist das übliche SEO-Handwerk. Zu diesem Thema findet man in Internet zahlreiche Informationsquellen mit vielen Hinweisen, die mit diesen Anpassungen an contenido leicht umgesetzt werden können. Die Weichen für eine suchmaschinenfreundliche Contenido-Seite sind also gestellt.

Weitere Artikel in der Rubrik Webdesign und Internet