Prev, next y canonical.

Resumen.

En este artículo de gran importancia en términos SEO vamos a ver como generar los valores para las etiquetas “pre”, “next” y “canonical”, es decir, URL anterior, URL siguiente y URL canónica en los listados paginados. Con esto le estamos diciendo a los motores de búsqueda que estamos en un “fragmento” de una misma página, y donde esta el “fragmento” anterior o el siguiente, así como la URL canónica, o lo que es lo mismo, la URL del fragmento de la página actual.

Artículo.

Para comprender de qué va este artículo lo primero que tenemos que saber es que es un listado paginado, algo por lo que pasamos continuamente cuando navegamos por Internet. Listados paginados los hay en todas partes, la misma página en que se presenta este artículo https://www.artesaniaweb.es/codigo-php.php es un listado paginado. Y lo sabemos por que en la parte inferior aparece algo así como esto:

1 | 2 | 3 | Siguiente » | Última »»
Artículos desde el 1 hasta el 10 de un total de 28

Esto quiere decir que la URL mencionada anteriormente esta dividida en varias partes, en este caso concreto 3 partes, tres fragmentos. Estos tres fragmentos se puede acceder desde la siguientes URLs:

https://www.artesaniaweb.es/codigo-php.php
https://www.artesaniaweb.es/codigo-php.php?pg=1
https://www.artesaniaweb.es/codigo-php.php?pg=2
https://www.artesaniaweb.es/codigo-php.php?pg=3


Como podemos ver, tenemos 4 URLs para 3 páginas. Eso ocurre por que el sistema de paginación considera de igual valor que la variable “pg” sea nulo como si fuera 1. Esto genera un problema de duplicidad de URL, es decir, dos URLs diferentes que tienen exactamente el mismo contenido, lo que supone un problema de penalización en términos SEO.

Para solventar este problema de URLs repetidas o duplicadas podemos recurrir a la etiqueta “canonical”, cuya sintaxis es la siguiente:
<link rel="canonical" href="https://www.artesaniaweb.es/codigo-php.php" />
Así, aparecerá esta misma URL como canonical tanto si no se pasa valor por “pg”, como si el valor que se pasa es 1. Cuando el valor que se pasa es, por ejemplo 2, el valor de la URL canónica seria:

<link rel="canonical" href="https://www.artesaniaweb.es/codigo-php.php?pg=2" />

Ahora, ya teniendo claro que es una URL canónica, podemos entender que es la URL anterior “prev” o la URL siguiente “next”.

Si enviamos el valor 2 “pg=2”, la “prev” seria 1, por tanto, la misma URL sin paso de variable. Si el valor fuera “pg=4”, la “prev” seria “pg=3” y la “next” seria “pg=5”.

La sintaxis de para la página anterior “prev” y siguiente “next” para la canónica “…pg=2” es esta:
<link rel="prev" href="https://www.artesaniaweb.es/codigo-php.php" /> <link rel="next" href="https://www.artesaniaweb.es/codigo-php.php?pg=3" />
Hasta aquí todo claro. Pero nos encontramos con un problema, y es que dado que los listados paginados agregan o restan páginas en función del número de registros totales y el número de registros mostrados en cada página, tenemos tomar en consideración como determinar la primera página y no la anterior a la primera, y la última, y nunca la posterior a ella.

Para hacer estos cálculos solo necesitamos dos datos, el número total de registros que vamos a paginar, y el número de registros que vamos a presentar en cada página (o mejor dicho, fragmento de página). codigo-php.php es la página, mientras que codigo-php.php?pg=2, es un fragmento de codigo-php.php.

Con este problema en mente, tenemos la siguiente función:
<?php // Extrae el valor canonico pagina anterior y siguiente // https://www.artesaniaweb.es/articulo.php?titulo=prev-next-y-canonical-eiyjn function CanPreNex($V_Url$Nombre_Pg$total_reg$N_reg_pag$domin){      @$_pagi_actual abs($_GET[$V_Url]);          $Ult_Pag ceil($total_reg/$N_reg_pag);                  $eti_can '<link rel="canonical" href="';         $eti_pre '<link rel="prev" href="';         $eti_nex '<link rel="next" href="';         $eti_fin '"/>';              if($_pagi_actual <= $Ult_Pag){         switch($_pagi_actual){             case $_pagi_actual == null:                 $_Canonica $eti_can.$domin.'/'.$Nombre_Pg.$eti_fin;                 $_Pag_prev null;                 $_Pag_next $eti_nex.$domin.'/'.$Nombre_Pg.'?'.$V_Url.'=2'.$eti_fin;                 break;             case $_pagi_actual == 1:                 $_Canonica $eti_can.$domin.'/'.$Nombre_Pg.$eti_fin;                 $_Pag_prev null;                 $_Pag_next $eti_nex.$domin.'/'.$Nombre_Pg.'?'.$V_Url.'=2'.$eti_fin;                 break;             case $_pagi_actual == 2:                 $_Canonica $eti_can.$domin.'/'.$Nombre_Pg.'?'.$V_Url.'=2'.$eti_fin;                 $_Pag_prev $eti_pre.$domin.'/'.$Nombre_Pg.$eti_fin;                 $_Pag_next $eti_nex.$domin.'/'.$Nombre_Pg.'?'.$V_Url.'=3'.$eti_fin;                 break;             case $_pagi_actual AND $_pagi_actual $Ult_Pag:                 $_Canonica $eti_can.$domin.'/'.$Nombre_Pg.'?'.$V_Url.'='.$_pagi_actual.$eti_fin;                 $_Ant $_pagi_actual 1;                 $_Sig $_pagi_actual 1;                 $_Pag_prev $eti_pre.$domin.'/'.$Nombre_Pg.'?'.$V_Url.'='.$_Ant.$eti_fin;                 $_Pag_next $eti_nex.$domin.'/'.$Nombre_Pg.'?'.$V_Url.'='.$_Sig.$eti_fin;                 break;             default:                 if($_pagi_actual <= $Ult_Pag){                     $_Canonica $eti_can.$Nombre_Pg.'?'.$V_Url.'='.$_pagi_actual.$eti_fin;                     $_Ant $_pagi_actual 1;                     $_Pag_prev $eti_pre.$Nombre_Pg.'?'.$V_Url.'='.$_Ant.$eti_fin;                     $_Pag_next null;                 }else{                     $_Canonica $eti_can.$domin.'/'.$Nombre_Pg.'?'.$V_Url.'='.$Ult_Pag.$eti_fin;                     $_Ant $Ult_Pag 1;                     $_Pag_prev $eti_pre.$domin.'/'.$Nombre_Pg.'?'.$V_Url.'='.$_Ant.$eti_fin;                     $_Pag_next null;                 }                 break;         }         $respuesta = array($_Canonica,$_Pag_prev,$_Pag_next,'Error'=>null);     }else{         $respuesta = array('Total registros'=>$total_reg,                         'Registros por pagina'=>$N_reg_pag,                         'Maximo de paginas'=>$Ult_Pag,                         'Error'=>"No puede haber mas de $Ult_Pag paginas");     }     return $respuesta; } // Aplicamos la funcion $V_Url 'pg';    // _pagi_pg $nombre_pg 'codigo-php.php'; $total_reg 129; $N_reg_pag 10; $dominio 'https://www.artesaniaweb.es'; $paginas CanPreNex($V_Url$nombre_pg$total_reg$N_reg_pag$dominio); echo '<pre>'; print_r($paginas); echo '</pre>'; echo "<hr> $paginas[0] <br /> $paginas[1] || $paginas[2] <br /> $paginas[Error]"; ?>
Como podemos ver, esta función recibe 5 parámetros y aunque antes dijimos que solo necesitábamos 2 para hacer los cálculos, también es cierto que necesitamos conocer el nombre del campo con que enviamos el número de página (que en los ejemplos anteriores era _pagi_pg), y ahora lo hemos optimizado y se llama “pg”, también precisamos el nombre de la página a paginar, que será null (nulo) si la página se llama index.php.

Con esto, la lógica de la función es muy simple, aunque si laboriosa de realizar. Lo primero que hemos hecho ha sido aplicar la función abs() al número de página ya que no tiene sentido el uso de valores negativos, y la función de redondeo ceil() que redondea al valor entero superior para calcular el número de páginas.

Pero, ¿por qué ceil()? Es sencillo, si tenemos 43 registros paginados a 10 por página, precisaremos 5 páginas, así 43 / 10 = 4,3 que se redondea a 5.

Lo siguiente es tener en cuenta que el número de páginas nunca exceda el número de páginas posibles, así la página actual nunca podrá tener un valor superior al de la última.

Seguidamente mediante una estructura condicional switch() realizamos los cálculos de página en función de en que página estamos.

La variable $respuesta será el return de la función, que al tener que devolver varios valores, será una variable tipo array. Este array, en la condición sin error devuelve los siguientes valores en función de la clave (key):
  • [0] – URL canónica
  • [1] – URL prev (anterior)
  • [2] – URL next (siguiente)
  • [Error] – null
Ni que decir tiene que si probais esta función, el array aparecerá como vacio, sin values, pero si accedeis al codigo fuente, podreis ver el resultado.

Esperando que os resulte muy útil, me despido hasta el siguiente artículo, que no tardará en llegar.
Tags: Prev || next || canónica || SEO || paginación

Comentarios.

Sin comentarios, publica el tuyo.