Programación

Creando un sitemap.xml desde cero

Programar un sitemap en PHP

Como ya comentamos en el post “¡A navegar grumetes!: Rastreo e indexación, primer contacto con Google“, los buscadores  siguen los enlaces de una web para saltar de una página a otra.

Por lo tanto, si no tenemos una estructura de enlaces internos bien desarrollada, puede que los buscadores no sean capaces de llegar a todo nuestro contenido.

Para solventar el problema hay dos estrategias que debemos seguir, la que vimos en el post Internal Linking y la que os vamos a contar ahora: Desarrollar un sitemap.xml.

 

¿Qué es exactamente un sitemap.xml?

Hace unos años era muy común ver, a pie de página, los “mapas de sitio“. Eran secciones dentro de una web, dedicadas exclusivamente a listar todo el árbol de categorías, secciones y páginas de las que se componía.

Con el tiempo, Google se dio cuenta de lo útil que resultaban estos “mapas de sitio” para conocer el contenido de las páginas, así que creó un estándar basándose en el lenguaje XML. Así, sus bots rastreadores podrían entender con mayor facilidad el contenido a indexar.

Este estándar era una lista de todos los enlaces que contenía una web, junto a su fecha de actualización, su relevancia o peso dentro de la web, y su autoría. Con el tiempo, el resto de buscadores también incorporaron este avance.

Hoy día, ese archivo, que hace las veces de mapa de sitio bajo el lenguaje XML, se llama sitemap.xml y es uno de los puntos más importantes para el posicionamiento SEO.

Es público y casi siempre se ubica en dominio.com/sitemap.xml
El nuestro está en https://www.loopeando.com/sitemap.xml

 

sitemap.xml de Loopeando.com
sitemap.xml de Loopeando.com

 

Tengo WordPress, ¿Cómo crear un sitemap?

Hay múltiples plugins que nos permiten automatizar esta tarea, entre los más populares están:

Una vez descargado uno de esos plugins, y creado el sitemap, debemos notificar a Google de su existencia haciéndole llegar el enlace a través de Google Search Console. En “¿Cómo concertar una cita con los bots de Google?“, explicamos cómo.

 

No dispongo de ningún CMS, ¿Hay alguna herramienta para crear un sitemap?

Si tu web no tiene ningún gestor de contenidos popular, o es un desarrollo propio, te recomendamos las siguientes herramientas para que te generen automáticamente un sitemap.xml:

Lo único que tendrás que hacer será acceder a cualquiera de ellas, facilitarles la url de tu web, y te dejarán descargar el archivo. A continuación habrás de subirlo a tu web y mostrar a Google la ruta dónde está.

 

Se programar y quiero crear un sitemap que se actualice en tiempo real

Si acudimos a una web para que nos genere un sitemap de manera automática, tendremos dos problemas:

  • El Sitemap generado será estático, por lo que salvo que cada vez que publiquemos o creemos algo en nuestro site, generemos un nuevo sitemap, lo volvamos a subir, etc Con el tiempo quedará desactualizado.
  • Habremos perdido la maravillosa oportunidad de aprender a hacerlo nosotros mismos. ¿Cursi? ¡Ni os imagináis lo que se aprende trasteando!

Pues manos a la obra:

Cabecera de un archivo XML:

<?xml version="1.0" encoding="UTF-8"?>
 <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

 

Estructura de un sitemap XML:

<url>
     <loc>https://www.loopeando.com/</loc>
     <lastmod>'.date("Y-m-d").'</lastmod>
     <changefreq>hourly</changefreq>
     <priority>1</priority>
</url>

 

Donde entre las etiquetas <loc> debe ir la url a indexar.

Entre las <lastmod> la fecha de la última edición (en nuestro caso, ahora mismo). Si lo vas a poner a mano, el formato es AAAA-MM-DD.

En <changefreq> la frecuencia de actualización, pudiendo ser:

  • always
  • hourly
  • daily
  • weekly
  • monthly
  • yearly
  • never

Esto es una guía para los buscadores, que pueden seguir o no. Se recomienda poner tasas de actualización muy bajas para las páginas estáticas (Quienes Somos, Contacto…) y tasas realistamente altas para aquellas donde publiquemos contenido periódico (blog, portada con noticias, foro…).

Y en <priority> la importancia de esa página dentro de la web, siendo 1 la más alta. De esa forma, Google indexará primero las más importantes.

 

Si nuestro XML fuese estático, deberíamos repetir esa estructura con todas las urls de nuestra web:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

<url>
     <loc>https://www.loopeando.com/</loc>
     <lastmod>'.date("Y-m-d").'</lastmod>
     <changefreq>hourly</changefreq>
     <priority>1</priority>
</url>

<url>
     <loc>https://www.loopeando.com/contacto/</loc>
     <lastmod>'.date("Y-m-d").'</lastmod>
     <changefreq>yearly</changefreq>
     <priority>5</priority>
</url>

<url>
     <loc>https://www.loopeando.com/category/actualidad/</loc>
     <lastmod>'.date("Y-m-d").'</lastmod>
     <changefreq>hourly</changefreq>
     <priority>2</priority>
</url>

</urlset>

Sin olvidar la etiqueta de cierre “</urlset>” .
Y lo guardaríamos con el nombre de sitemap.xml, lo subiríamos a la raíz de nuestro site, y listo.

 

Pero lógicamente, la gracia de hacerlo nosotros por programación, es que el sitemap se actualice sólo. ¿Cómo lo hacemos? Con consultas a la base de datos:

1º Ponemos la conexión con la BBDD:

//Conectamos con la base de datos
$config_host = "localhost";
$config_db = "nombre_base_datos";
$config_user = "usuario_base_datos";
$config_password = "contraseña_base_datos";

$link = mysql_connect($config_host, $config_user, $config_password);
mysql_select_db($config_db);

 

2º Creamos una función que nos parsee el texto por si tuviese tildes o cualquier otro caracter no permitido en las urls (ñ, ü, à…):

//Definimos la función que utilizaremos después para formar las urls de la web
function limpiarCadenaa($string){
    
                  
      $string = str_replace (' ','-',$string);		
      $string = str_replace(array('á', 'à', 'ä', 'â', 'ª', 'Á', 'À', 'Â', 'Ä'),
                  array('a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'),
                  $string);

      $string = str_replace(array('é', 'è', 'ë', 'ê', 'É', 'È', 'Ê', 'Ë'),
                  array('e', 'e', 'e', 'e', 'e', 'e', 'e', 'e'),
                  $string);

      $string = str_replace(array('í', 'ì', 'ï', 'î', 'Í', 'Ì', 'Ï', 'Î'),
                  array('i', 'i', 'i', 'i', 'i', 'i', 'i', 'i'),
                  $string);

      $string = str_replace(array('ó', 'ò', 'ö', 'ô', 'Ó', 'Ò', 'Ö', 'Ô'),
                  array('o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'),
                  $string);

      $string = str_replace(array('ú', 'ù', 'ü', 'û', 'Ú', 'Ù', 'Û', 'Ü'),
                  array('u', 'u', 'u', 'u', 'u', 'u', 'u', 'u'),
                  $string);

      $string = str_replace(array('ñ', 'Ñ', 'ç', 'Ç'),
                  array('n', 'n', 'c', 'c',),
                  $string);

      //Esta parte se encarga de eliminar cualquier caracter extraño
      $string = str_replace(array("\\", "¨", "º", "~", "#", "@", "|", "!", "\"", "·", "$", "%", "&", "/", "(", ")", "?", "'", "¡",
                    "¿", "[", "^", "`", "]", "+", "}", "{", "¨", "´", ">", "< ", ";", ",", ":", "."),
                  '',
                  $string);
      return $string;
    }
    /* FIN LIMPIAR CADENA */

 

3º Realizamos las consultas pertinentes a la BBDD para formar las urls.

Esta parte ya es muy personal dependiendo de cada web y su estructura de la BBDD. En nuestro caso, la estructura es:

https://www.loopeando.com/seccion/id_entrada/titular_de_la_entrada

Por lo que debemos sacar de cada entrada los parámetros: seccion, id_entrada y titular_de_la_entrada

Nuestro código, por si os da ideas, sería:

//Listamos todas las entradas que se han publicado hasta ahora   
$consultanoticias = mysql_query("SELECT * FROM noticias LIMIT 0, 35000");
    
    while ($pintanoticias = mysql_fetch_array($consultanoticias)){
      $titulolimpio = limpiarCadenaa(strtolower(utf8_encode($pintanoticias['titulo'])));
      
      //Formamos el nombre de la sección donde está publicada
      $seccion = $pintanoticias['seccion'];
      $consultaseccion = mysql_query("SELECT * FROM secciones WHERE id ='$seccion'");
      
      //Verificamos que el resultado de la consulta existe, pues hay noticias antiguas cuyas secciones ya no existen
      if (mysql_num_rows($consultaseccion) > 0){
        
      while ($pintaseccion = mysql_fetch_array($consultaseccion)){
        
        if ($pintaseccion['titulo'] ==""){
          $seccionlimpia = "secciones";
        }else{
          $seccionlimpia = limpiarCadenaa(strtolower(utf8_encode($pintaseccion['titulo'])));
        }
        
      }


//Las añadimos al XML 
 $xml .='<url>

 <loc>https://www.loopeando.com/'.$seccionlimpia.'/'.$pintanoticias['id'].'/'.$titulolimpio.'</loc>

 <lastmod>'.date("Y-m-d",strtotime($pintanoticias['fecha_modificacion'])).'</lastmod>

 <priority>0.5</priority>

 </url>'; 
 }
 }

 

De manera que todo el código quedaría de la siguiente manera:

<?php 
//Conectamos con la base de datos
$config_db = "nombre_base_datos";
$config_user = "usuario_base_datos";
$config_password = "contraseña_base_datos";

$link = mysql_connect($config_host, $config_user, $config_password);
mysql_select_db($config_db);

$link = mysql_connect($config_host, $config_user, $config_password);
mysql_select_db($config_db);

//Definimos la función que utilizaremos después para formar las urls de las noticias
function limpiarCadenaa($string){
    
                  
      $string = str_replace (' ','-',$string);		
      $string = str_replace(array('á', 'à', 'ä', 'â', 'ª', 'Á', 'À', 'Â', 'Ä'),
                  array('a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'),
                  $string);

      $string = str_replace(array('é', 'è', 'ë', 'ê', 'É', 'È', 'Ê', 'Ë'),
                  array('e', 'e', 'e', 'e', 'e', 'e', 'e', 'e'),
                  $string);

      $string = str_replace(array('í', 'ì', 'ï', 'î', 'Í', 'Ì', 'Ï', 'Î'),
                  array('i', 'i', 'i', 'i', 'i', 'i', 'i', 'i'),
                  $string);

      $string = str_replace(array('ó', 'ò', 'ö', 'ô', 'Ó', 'Ò', 'Ö', 'Ô'),
                  array('o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'),
                  $string);

      $string = str_replace(array('ú', 'ù', 'ü', 'û', 'Ú', 'Ù', 'Û', 'Ü'),
                  array('u', 'u', 'u', 'u', 'u', 'u', 'u', 'u'),
                  $string);

      $string = str_replace(array('ñ', 'Ñ', 'ç', 'Ç'),
                  array('n', 'n', 'c', 'c',),
                  $string);

      //Esta parte se encarga de eliminar cualquier caracter extraño
      $string = str_replace(array("\\", "¨", "º", "~", "#", "@", "|", "!", "\"", "·", "$", "%", "&", "/", "(", ")", "?", "'", "¡",
                    "¿", "[", "^", "`", "]", "+", "}", "{", "¨", "´", ">", "< ", ";", ",", ":", "."),
                  '',
                  $string);
      return $string;
    }
    /* FIN LIMPIAR CADENA */
    
//Iniciamos el xml con su codificación y su certificación de referencia
$xml = '<?xml version="1.0" encoding="UTF-8"?>
        <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
    
  //Pintamos las secciones fijas
  $xml .='<url>

    <loc>https://www.loopeando.com/</loc>

    <lastmod>'.date("Y-m-d").'</lastmod>

    <changefreq>hourly</changefreq>

    <priority>1</priority>

  </url>';
   
  $xml .='<url>

    <loc>https://www.loopeando.com/empleo</loc>

    <lastmod>'.date("Y-m-d").'</lastmod>

    <changefreq>daily</changefreq>

    <priority>0.8</priority>

  </url>';
   
  $xml .='<url>

    <loc>https://www.loopeando.com/portada</loc>

    <lastmod>'.date("Y-m-d").'</lastmod>

    <changefreq>daily</changefreq>

    <priority>0.8</priority>

  </url>';
   
  $xml .='<url>

    <loc>http://cursos.loopeando.com/index.html</loc>

    <lastmod>'.date("Y-m-d").'</lastmod>

    <changefreq>daily</changefreq>

    <priority>0.8</priority>

  </url>';
   
  $xml .='<url>

    <loc>https://www.loopeando.com/noticias</loc>

    <lastmod>'.date("Y-m-d").'</lastmod>

    <changefreq>daily</changefreq>

    <priority>0.8</priority>

  </url>';
   
  $xml .='<url>

    <loc>https://www.loopeando.com/hemeroteca</loc>

    <lastmod>'.date("Y-m-d").'</lastmod>

    <changefreq>daily</changefreq>

    <priority>0.8</priority>

  </url>';
   
  $xml .='<url>

    <loc>https://www.loopeando.com/rss.feeds</loc>

    <lastmod>'.date("Y-m-d").'</lastmod>

    <changefreq>daily</changefreq>

    <priority>0.8</priority>

  </url>';
   
  $xml .='<url>

    <loc>https://www.loopeando.com/legal.php</loc>

    <lastmod>'.date("Y-m-d").'</lastmod>

    <changefreq>monthly</changefreq>

    <priority>0.8</priority>

  </url>';

  $xml .='<url>

    <loc>https://www.loopeando.com/contacto</loc>

    <lastmod>'.date("Y-m-d").'</lastmod>

    <changefreq>monthly</changefreq>

    <priority>0.6</priority>

  </url>';
   
  $xml .='<url>

      <loc>https://www.loopeando.com/acceso-empresas</loc>

      <lastmod>'.date("Y-m-d").'</lastmod>

      <changefreq>monthly</changefreq>

    <priority>0.6</priority>

  </url>';
   
  $xml .='<url>

    <loc>https://www.loopeando.com/acceso-candidatos</loc>

    <lastmod>'.date("Y-m-d").'</lastmod>

    <changefreq>monthly</changefreq>

    <priority>0.6</priority>

  </url>';
   

   
//Listamos todas las noticias que se han publicado hasta ahora   
$consultanoticias = mysql_query("SELECT * FROM noticias LIMIT 0, 35000");
    
    while ($pintanoticias = mysql_fetch_array($consultanoticias)){
      $titulolimpio = limpiarCadenaa(strtolower(utf8_encode($pintanoticias['titulo'])));
      
      //Formamos el nombre de la sección donde está publicada
      $seccion = $pintanoticias['seccion'];
      $consultaseccion = mysql_query("SELECT * FROM secciones WHERE id ='$seccion'");
      
      //Verificamos que el resultado de la consulta existe, pues hay noticias antiguas cuyas secciones ya no existen
      if (mysql_num_rows($consultaseccion) > 0){
        
      while ($pintaseccion = mysql_fetch_array($consultaseccion)){
        
        if ($pintaseccion['titulo'] ==""){
          $seccionlimpia = "secciones";
        }else{
          $seccionlimpia = limpiarCadenaa(strtolower(utf8_encode($pintaseccion['titulo'])));
        }
        
      }
      
  //Las añadimos al XML	
  $xml .='<url>

      <loc>https://www.loopeando.com/'.$seccionlimpia.'/'.$pintanoticias['id'].'/'.$titulolimpio.'</loc>

      <lastmod>'.date("Y-m-d",strtotime($pintanoticias['fecha_modificacion'])).'</lastmod>

      <priority>0.5</priority>

   </url>';	 
      }
  }
   
   
//Cerramos el XML
$xml .='</urlset>';

header('Content-type:text/xml;charset:utf8');
echo $xml;
?>

 

Y por supuesto, ahora al ser dinámico, no debemos olvidarnos de guardarlo como sitemap.php, subirlo a la raíz de nuestro sitemostrar a Google la ruta dónde está.

 

¿Te ha sido de utilidad esta entrada? ¡Compártela para que también le sirva a tus amigos!

Cristian Sarabia Martínez

Desde que a principios de los 90 mi padre desempolvó su Spectrum, no he dejado de probar y experimentar con la tecnología.

Enamorado del mundo web, Full Stack Developer de profesión y diseñador por devoción.

Ahora hago mis pinitos en esto del blogging para compartir con vosotros un poquito de todo lo que la comunidad me ha dado.

1 Comentario

Haz clic aquí para dejar tu comentario

Flickr

  • Iowa
  • brigandine
  • un autre matin
  • THF Inside
  • THF Top
  • THF Back
  • Empoli
  • p.p.p.
  • l'autre matin

About Author

ThemeForest

Collaboratively harness market-driven processes whereas resource-leveling internal or "organic" sources. Competently formulate.

Calendar

marzo 2025
L M X J V S D
 12
3456789
10111213141516
17181920212223
24252627282930
31  

RSS Meks Blog

  • How Adding Slack Bot Boosted Our Culture of Appreciation 3 julio, 2024
    Sweet Kudos is a Slack bot that enhances employee recognition, rewards, and celebrations within your team. It empowers team members to express gratitude and appreciation effortlessly by giving virtual Kudos. The post How Adding Slack Bot Boosted Our Culture of Appreciation appeared first on Meks.
    Dusan Milovanovic
  • 10 Best Knowledge Base & Wiki WordPress Themes 2021 15 septiembre, 2021
    Running a successful online business requires an exceptional WordPress knowledge base theme that organizes documentation and helps customers. Customization options, intuitive navigation, unique layouts, and fast responsiveness are just some of the features you need. The following 10 WordPress wiki themes represent the best options for 2021 and beyond. Explore the full range to determine […]
    Dusan Milovanovic
  • How to increase WordPress Memory Limit (quick fixes) 16 junio, 2021
    Here is a post about how to increase the memory limit in WordPress. Allowed memory size exhausted error message showed up in your WordPress installation? No worries – this is one of the most common errors in WordPress. You can apply an easy fix by increasing the memory limit in your PHP. Table of Contents […]
    Dusan Milovanovic
  • How to use (and why) WordPress sitemap plugin 1 marzo, 2021
    Did you know that by knowing how to use the WordPress sitemap plugin you can significantly improve your site’s visibility and traffic? Although it isn’t mandatory to have a sitemap on your site, having one significantly improves the site’s quality, crawlability and indexing. All this is important for better optimization, which is why we wanted […]
    Ivana Cirkovic
  • 22 free and premium podcast software for your show [2021 edition] 18 enero, 2021
    You’re determined to start or improve your podcast but don’t know which podcast software to use to really make it stand out? We’ve got you! #podcasting Top 22 free and premium podcast software for your show #WordPressTips #podcasting The post 22 free and premium podcast software for your show [2021 edition] appeared first on Meks.
    Ivana Cirkovic
  • Digital storytelling with WordPress – an all-in-one guide to make your web stories pop! 23 noviembre, 2020
    Wondering how to improve digital storytelling with WordPress and build more awareness and exposure of your business? Let our guide lead the way. The post Digital storytelling with WordPress – an all-in-one guide to make your web stories pop! appeared first on Meks.
    Ivana Cirkovic
  • How to use WordPress autoposting plugin to improve your visibility and SEO? 10 septiembre, 2020
    Did you know you can use the WordPress autoposting plugin for your content efforts and improve not only your time management but your business and visibility as well? The post How to use WordPress autoposting plugin to improve your visibility and SEO? appeared first on Meks.
    Ivana Cirkovic
  • How to create a personal branding site? Step-by-step DIY guide 15 agosto, 2020
    Looking for ways and means to create a personal branding site? Well, look no further ’cause we’re giving away all the how-to’s to do it yourselves! The post How to create a personal branding site? Step-by-step DIY guide appeared first on Meks.
    Ivana Cirkovic
  • Top 15 WordPress content plugins and tools to improve your visibility and rankings 16 julio, 2020
    Let’s take a look at some of the must-have WordPress content plugins and tools to use to improve both your UX and rankings. The post Top 15 WordPress content plugins and tools to improve your visibility and rankings appeared first on Meks.
    Ivana Cirkovic
  • WCEU 2020 recap – key takeaways from the biggest online WordPress conference 9 junio, 2020
    Missed WCEU 2020 and all the exciting stuff from there? Here are all the key takeaways and main points to remember so, take notes! The post WCEU 2020 recap – key takeaways from the biggest online WordPress conference appeared first on Meks.
    Ivana Cirkovic

Text

Distinctively utilize long-term high-impact total linkage whereas high-payoff experiences. Appropriately communicate 24/365.

Archives