Crear un sitemap.xml de forma dinámica con PHP

Siguiendo con las optimizaciones para mejorar la indexación por parte de Google, vi en las herramientas que proporciona Google a webmasters que se puede proporcionar un sitemap en formato xml para que Google pueda rastrear con mayor facilidad algunas páginas de difícil rastreo.

En teoría, con la actualización de las Friendly URLs ya no tengo páginas de difícil rastreo, pero viendo que no me indexa, pues mejor dar todas las facilidades posibles.

Lo primero que hice fue crear un sitemap.xml mediante esta página.

La página se encarga de rastrear el sitio y obtener el listado de enlaces y te genera un xml para descargar. Después se deja en la raíz del blog, y ya es accesible en la ruta /sitemap.xml.

El problema es que según se generan nuevos artículos, tendría que estar volviendo a generar manualmente el sitemap. Además, aparecían enlaces que no estoy especialmente interesado en que se indexen, como las etiquetas o la página de registro.

La solución, por tanto, es que el sitemap se genere de forma dinámica. Estuve buscando generadores de sitemap en PHP y al final encontré este tutorial de como hacer el tuyo propio. Lamentablemente el tutorial ya no está disponible.

Usando ese código como base y el sitemap.xml que había generado con la primera página como plantilla, lo he adaptado para poder funcionar con la base de datos de eggBlog.

Al final, solo añado las URLs de los artículos, ya que son mi prioridad en la indexación, pero no debería ser complicado modificar el código para añadir más enlaces.

[ACTUALIZACIóN 05/03/2011]

He realizado algunas modificaciones al sitemap.php. Anteriormente estaba utilizando la fecha de publicación como la fecha de modificación el el sitemap, pero claro, yo quiero indicar a Google que un articulo ha sido actualizado, por lo que necesito tener una fecha de modificación. Para eso añadí una nueva columna a la tabla “eb_articles” con el nombre “mod_date”.

Hay que establecer su valor en dos métodos, eb_admin_editarticle y eb_admin_newarticle, ambos en admin.php. Simplemente hay que añadir .",mod_date="".time(). en el INSERT.

También es interesante añadirlo a la definición de la tabla en el método eb_install para una futura migración o reinstalación. Solo hay que añadir:

"mod_date int NOT NULL DEFAULT '0',".

Por si alguien lo quiere aprovechar, aquí os dejo el código para descargar. Me ha tocado subirlo como un txt, ya que no me deja subir ficheros zip… ¬

[ACTUALIZACIóN 11/10/2011]

Con tanto cambio de servidor, el fichero zip se perdió en algún lado, así que a continuación pongo la útima versión que hice para eggBlog. Para wordpress lo mejor es optar por un plugin como el Google (XML) Sitemap Generator.

<?php
require_once "_lib/global.php";
header( "Content-Type: text/xml;charset=iso-8859-1" );

// Connectamos con la base de datos
mysql_connect( $config['mysql_host'], $config['mysql_user'], $config['mysql_pass'] );
@mysql_select_db( $config['mysql_db'] ) or die( "Unable to select DB" );

// Realizamos la consulta
$sql = "SELECT article_id, mod_date, article_title, article_date"
." FROM eb_articles"
." WHERE article_flag = 1 OR article_flag = 2"
." ORDER BY article_date DESC";
$query = mysql_query( $sql ) or die( "Query failed" );

// Escribimos la cabezera del xml
echo '<?xml version="1.0" encoding="UTF-8"?>
    <urlset
      xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
            http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">';

$maxArticleDate = 0;
settype( $maxArticleDate, "integer" );

while( $row = mysql_fetch_array( $query ) ) {

    // Obtenemos la Friendly URL del articulo
    $article_link = eb_links_article( $row['article_title'], $row['article_id'] );

    // Componemos la fecha de modificación (p.e. 2011-02-18)
    $year = date( "Y", $row[1] );
    $mon  = date( "m", $row[1] );
    $day  = date( "d", $row[1] );

    $lastModDate = $year . '-' . $mon . '-' . $day;

    echo
        '<url>
            <loc>' . $article_link . '</loc>
            <lastmod>' . $lastModDate . '</lastmod>
            <changefreq>monthly</changefreq>
        </url>';

    $articleDate = $row['article_date'];
    settype( $articleDate, "integer" );
    if( $articleDate > $maxArticleDate ) {
        $maxArticleDate = $articleDate;
    }
}

mysql_close(); //Cerramos la conexión

$year = date( "Y", $maxArticleDate );
$mon  = date( "m", $maxArticleDate );
$day  = date( "d", $maxArticleDate );

$lastCreateDate = $year . '-' . $mon . '-' . $day;

echo
    '<url>
        <loc>' . $config['domain'] . 'index.php</loc>
        <lastmod>' . $lastCreateDate . '</lastmod>
        <changefreq>daily</changefreq>
    </url>';

echo '</urlset>';
?>