Mis plugins para Firefox

De tanto en tanto se hace recurrente en mi vida una pregunta que me hacen: ¿Y tú que navegador usas? La respuesta es sencilla: Firefox. Y es que uso Firefox desde prácticamente cuando aún era Netscape Navigator. Y luego, viene la siguiente pregunta: ¿Y por qué Firefox? Pues básicamente por las ampliaciones que lleva. Y entonces comienzan las discusiones con los amantes de Chrome. En ese momento, casi antes de comenzar, simplemente me voy.

El hecho de usar Firefox (incluso os puedo decir que desde hace unas semanas ya me he lanzado a la piscina porque usaba primero las betas, luego Aurora y ahora Nightly de 64 bits -lo que significa que en este momento estoy con una alpha de Firefox 21-) viene dado principalmente por su lista de “plugins” (o addons).

¿Y cuáles son esas ampliaciones que utilizo? Pues es la siguiente:

  • Adblock Plus: Simplemente para no ver publicidad. Que conste que no siempre lo tengo activado, pero para desarrollar va bastante bien.
  • Advertising Cookie Opt-out: Pasando de las cookies de Adsense y Doubleclick.
  • Beef Taco: pasando de las cookies de otra decena de sitios de publicidad y de basurilla.
  • Classic Retweet: Lo siento, pero añoro el primer Twitter…
  • ColorZilla: Permite seleccionar cualquier color de una web. No lo uso mucho, que conste.
  • DNS Flusher: Cuando trabajas con muchas máquinas en desarrollo, preproducción y producción se vuelve algo básico la limpieza de las DNS.
  • Firebug: Herramienta básica del desarrollador.
  • Flash Video Downloader: Útil en algunas ocasiones. No lo suelo usar casi nunca.
  • Ghostery: Informa de todos los “spyware” que intentan colarte las webs…
  • HTTPS Everywhere: El nombre ya lo indica todo.
  • Live HTTP Headers: Un clásico para ver las cabeceras. Básico para el WPO.
  • Long URL Please: Muestra las URL de acortadores en su versión completa.
  • MeasureIt: Para medir anchos y altos de elementos web.
  • LessChrome HD: Oculta el menú. Pensando en saltar al LessChrome Modified.
  • Page Speed: Otro de los complementos básicos del WPO.
  • PDF Viewer: Muestra los PDF integrados en el navegador, sin el plugin de Adobe.
  • Pearl Crescent Page Saver Basic: Capturador de pantalla o de toda la página.
  • Pocket: Si usas Pocket, es necesario tenerlo también en el navegador bien integrado.
  • Web Developer: La barra básica en mi vida… si veo un Firefox sin ella, la instalo, porque lo digo yo.
  • YSlow: Otra de las herramientas clave en el WPO.

Tengo una lista de plugins pendientes de usar y/o de decidir si se quedan o no se quedan en mi lista de establecidos…

  • Cache Status: permite gestionar la caché de forma rápida (algo también de uso habitual en mi caso).
  • Modify Headers: A veces no sólo es necesario “ver” cabeceras, sino que hay que “tocarlas”.
  • Poster: Otro más que tiene que ver con las cabeceras. Lo veo muy completo, pero no sé si es lo que necesito, aún.

Vuelvo a decir, ya sé que Chrome y Opera tienen muchos plugins y muchas cosas… pero me gusta el zorro, ¡qué le vamos a hacer!

Buscadores y países

Hoy estaba repasando algunos datos de StatCounter para repasar el estado del “control absoluto” de Google por el mundo, también conocido como “en qué país Google no manda”. Y la verdade s que me ha sorprendido, porque aquellos pocos países que quedaban con más de la mitad de tráfico de buscadores fuera de las manos del grande de Mountain View se han reducido a 1: China.

Esto me ha hecho analizar un poco más los datos y hacerme la pregunta recursiva que me hago cada vez que tengo que lanzar un proyecto internacional: ¿he de apostar por otro buscador que no sea Google? La respuesta, por supuesto, siempre es sí, aunque Google se quedase con el 100% del tráfico 😉

Aunque pueda parecer que esto es así, y ciertamente Google dispone de una cuota de mercado superior al 90% en casi todo el mundo, siempre quedan algunos países en los que, aunque Google tiene la mayoría hay que observar otros motores que por un tema histórico aún siguen siendo importantes. Como detalle cuando hable de Bing hablaré de Bing+Yahoo! a menos que lo especifique.

  • Estados Unidos: sí, vale, el 80% de la gente usa Google, pero casi un 20% usa el Bing, lo que es bastante interesante teniendo en cuenta que esta cifra va subiendo poco a poco. Bing tiene muy buenos resultados en US debido a los acuerdos y demás información que, todavía, no ofrece en otros países.
  • China: Baidu se lleva un 70% del tráfico y el resto se lo reparten un 15% Google y un 10% Qihoo.
  • Taiwan: Aunque Google gana terreno con un 55%, sin duda Yahoo! aún tiene mucho que decir, ya que tiene una versión especial para este país.
  • Rusia: Google ha ido ganando terreno poco a poco, hasta quedarse con casi un 60% del tráfico, pero el otro 40% sin duda lo tiene Yandex, del que mucha gente usa sus servicios. Además, Yandex está optimizado para el texto cirílico lo que le da mucha ventaja sobre el resto.
  • Hong Kong: Sin duda, también ha ido ganando terreno Google, con un 65% del tráfico pero Yahoo! que también tiene una edición especial, con un 35%, sigue apostando duro.
  • Japón: cada vez Yahoo!, con sólo un 25% de la cuota, va perdiendo camino, y Google lo va ganando con un 70%.
  • Bielorusia, Kazajistán, Ucrania, Uzbekistan, Tajikistan (y otros): estos países que tocan Rusia o que fueron parte de la URSS también siguen teniendo una afinidad entre un 20% y un 10% con Yandex, lo que los sigue haciendo importantes.
  • Korea del Sur: históricamente Naver (9%) y Daum (8%) se han llevado el tráfico, pero Google les ha arrancado la mayoría superando ya el 75%.
  • República Checa: Una vez más, Google se lleva un 75% de las búsquedas, pero el otro 25% se las lleva el buscador local Seznam con un 25%.
  • Eslovenia: residual con un 3% queda Nadji y el resto se lo lleva Google.

Es curioso como antiguas tecnologías de búsqueda y sobretodo diferentes elementos culturales influyen tanto en el uso de los buscadores. Lo de los rusos es básicamente por la codificación del texto, al igual que ocurre con los chinos; los países de más al este es básicamente por un tema cultural… aunque parezca mentira, Google no les gusta porque es “demasiado blanco”, o sea, ellos lo que quieren son páginas “sobre cargadas” de contenido, algo que, como bien sabemos, Google no es precisamente su estilo.

Vale, Google, tiene de media mundial un 90% de cuota, Bing un 7% y el resto casi se lo reparten Yandex y Baidu… Ahora ¿qué vas a hacer con tu SEO?

Keep It Simple Lab a 54 millas náuticas por hora

A principios de diciembre, y tras 3 meses intensos os comentaba que Keep It Simple Lab estaba levantando el vuelo. En ellas os hablaba de que habíamos entrado en un par de empresas (y os adelanto que estamos preparando cosas nuevas); y hoy os quiero explicar un poco más de, en este caso, Boat Bureau.

Todo comenzó hace ya un par de años en los que la gente de Omitsis nos hablo de un proyecto bastante generalista que acabó convirtiéndose en algo mucho más verticalizado que acabó siendo un marketplace público de propietarios de embarcaciones y de los usuarios de este tipo de embarcaciones. El proyecto siempre ha tenido un apunte muy internacional aunque, como supongo que la mayoría de proyectos, se comenzó desde sólo un punto, en este caso España, aunque con la visión general de tener embarcaciones alrededor de todo el Mediterráneo. Sin duda, una de las incorporaciones que está haciendo posible todo este invento ha sido la de Pep Mercadé, CEO de la compañía.

El desarrollo de la plataforma ha pasado por muchas fases… aunque tras un año de desarrollo digamos que ya tenemos la segunda versión, muchísimo más estable que la primera (que se lanzó justo antes del verano pasado) y que básicamente era una plataforma hecha para verificar el negocio, algo que quedó bastante claro tras los meses estivales. A partir de ahí todo ha sido el montar la empresa de forma formal, crear un equipo propio (hasta ese momento las diferentes empresas proporcionaban parte de su equipo) y tener una nueva plataforma lista para principios de año.

Aunque es algo que no me mola (la comparación), se puede decir que el objetivo de Boat Bureau es el mismo del que tiene Airbnb, o sea, el de poner a disposición de cualquiera los recursos disponibles que son difíciles de exponer si no eres una empresa. Al igual que los alojamientos, que tienen muchas webs donde se ofrecen, pero siempre con una empresa detrás, con las embarcaciones pasa algo parecido y es que hay flotas de empresas que ya se anuncian y tienen un planteamiento así, pero no ocurre lo mismo (o no es tan sencillo) para los que sólo tienen una embarcación privada y que pasa mucho tiempo amarrada porque no se le da uso. El objetivo de Boat Bureau es que aquellos que tengan una embarcación sin uso consigan sacarle rentabilidad a la misma de una forma fácil y sencilla.

El proyecto ahora mismo está en plena expansión. Ya tenemos las versiones en español, inglés, francés, alemán y otros tantos idiomas más que saldrán en las próximas semanas. Además, tras la presentación del proyecto en un par de ferias internacionales del sector la acogida ha sido increíble e incluso las flotas que ya se ofrecen por sus medios han decidido apuntarse a la plataforma.

¿Hacia dónde vamos ahora? Pues, supongo que el primer paso es consolidar el proyecto y el negocio, seguir evolucionando la plataforma, seguir con el lanzamiento de nuevos mercados y, bueno, muchas más cosas que ahora mismo no puedo deciros.

Sin duda uno de los proyectos que mi día a día se lleva unas horas, uno de los que más ganas de ver cómo crece y, sobretodo, uno de los proyectos que tengo tan claro que va a funcionar que espero que me retire 😉

NOTA: 100 kilometro por hora [km/h] = 53,995 millas náuticas por hora [nm/h]

HTML5 download

En estas dos últimas semanas llevo revisando y revisando elementos del HTML5 que, como ya dije, me apasionan, porque básicamente han hecho mejoras muy impresionantes. Y por eso hoy os voy a hablar de una que me ha gustado muchísimo: el html5 download.

Voy a hacerlo sencillo… imaginad que tengo un fichero que se llama ejemplo123454321.txt. Si pulsáis veréis que es un texto normal y corriente que se abre (en principio) dentro del propio navegador al tratarse de un fichero de texto plano. El código fuente es sencillo:

<a href="ejemplo123454321.txt">ejemplo123454321.txt</a>

ejemplo123454321.txt

Pero, ¿por qué no forzar la descarga y además aprovechar el camino en cambiarle el nombre del fichero? Para ello ha aparecido un atributo en HTML5 que es el download que permite esto mismo… sin necesidad de cambiar nada en el servidor… El código sería algo tal que así:

<a href="ejemplo123454322.txt" download="cambiodenombre">ejemplo123454322</a>
(descárgalo como cambiodenombre.txt)

ejemplo123454322.txt (descárgalo como cambiodenombre.txt)

Un detalle importante es que este sistema únicamente funciona si el fichero está en el mismo hostname desde donde se hace la petición.

¿Cómo se te queda el cuerpo?

Rel-Canonical, duplicados y versiones móviles

Desde que apareció en escena el rel-canonical me he encontrado en una decena de situaciones distintas de las que, a base de palos, he ido aprendiendo. Hoy me gustaría compair algunas de estas casuísticas en las que me he visto.

Por norma general

Lo ideal del rel-canonical es ponerlo en todas las páginas de un sitio web. Al menos en las páginas públicas (las que los robot son capaces de encontrar). Si tu robots.txt tiene un Disallow de alguna sección, no está de más que estas páginas también lo incluyan. Repito, en general, siempre utilizar el rel-canonical.

El rel-canonical se puede usar de dos formas: vía HTML o vía Header. En el caso del HTML simplemente hemos de colocar la meta-etiqueta en la cabecera de la página:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Javier Casares</title>
  <link rel="canonical" href="http://javiercasares.com/">
</head>

La otra posibilidad es la de la cabecera, en cuyo caso hemos de indicar algo tal que así (por ejemplo en PHP):

header("Link: <http://javiercasares.com/> rel=\"canonical\"");

Páginas noindex-ables

Cuando tenemos un meta-noindex y un rel-canonical comienzan algunos problemas. Las opciones son dos posibles; la primera de ellas es simplemente indicar el meta-noindex y no indicar el rel-canonical.

URL actual: http://javiercasares.com/?prueba=si

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Javier Casares</title>
  <meta name="robots" value="noindex">
</head>

Con esto simplemente esa dirección no se indexaría… porque aunque existe no queremos que se muestre… el problema de esto es que, aunque la dirección exista y no queremos que se indexe porque es exactamente igual que la página principal, se puede generar un ataque. Bing y Google aunque se les indica el “noindex” rastrean y almacenan la página, aunque no la muestran en los resultados de búsqueda, pero se tiene en cuenta, y si es mala, no mola nada.

La otra solución es la de simplemente indicar el rel-canonical…

URL actual: http://javiercasares.com/?prueba=si

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Javier Casares</title>
  <link rel="canonical" href="http://javiercasares.com/">
</head>

En este caso, esta página también se indexa pero cualquier enlace, fuerza o como se le quiera llamar pasa automáticamente a integrarse con la página principal. En principio la URL “maligna” no debería aparecer en los resultados de búsqueda.

Y os podéis preguntar: Javi, ¿y no sería mejor poner las dos cosas? ¡Miiic!, ¡error!. Si hacemos esto se produce un agujero negro en el espacio infinito que desindexa muchas cosas. Vosotros pensáis en algo tal que así:

URL actual: http://javiercasares.com/?prueba=si

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Javier Casares</title>
  <link rel="canonical" href="http://javiercasares.com/">
  <meta name="robots" value="noindex">
</head>

Si hacemos esto, se produce una paradoja extraña. Lo que ocurre es que el rel-canonical se prioriza sobre el meta-noindex. Esto significa que:

  1. El buscador toma la URL http://javiercasares.com/?prueba=si y la almacena como http://javiercasares.com/
  2. El buscador toma la URL http://javiercasares.com/ y le aplica el noindex.

¡Bien! Acabamos de desindexar de Google y Bing nuestra página principal. Sí, esto pasa… así que, niños, no pongáis nunca un rel-canonical con un meta-noindex… pero… ¿qué corre si el rel-canonical apunta a la URL correcta que ya tenía un meta-noindex anteriormente? Os explico la situación.

Imaginad que tenéis una página que, antes de pensar en ponerles el rel-canonical ya tenía puesto el meta-noindex. Es una URL correcta (o sea, la URL del navegador y la del rel-canonical coinciden) por lo que… ¿por qué no podemos aplicar el rel-canonical si Javi ha dicho al principio que recomienda ponerlo siempre? Pues, en este caso sí que tendría sentido ponerse.

URL actual: http://javiercasares.com/?pagina=5

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Javier Casares</title>
  <meta name="robots" value="noindex">
</head>

Imaginemos que la paginación de mi sitio funciona por parámetros, y que yo ya tenía el código anterior… esta página, tal y como está no se indexa, lo que es correcto porque yo lo he decidido así… ¿por qué no poner algo como esto?

URL actual: http://javiercasares.com/?pagina=5

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Javier Casares</title>
  <link rel="canonical" href="http://javiercasares.com/?pagina=5">
  <meta name="robots" value="noindex">
</head>

Pues, en este caso en principio el código sí que sería correcto.

Versiones móviles

Versiones, hoy en día, para dispositivos hay 3: escritorio (versión normal), móviles (los zapatófonos) y smartphones (los que soportan HTML5). También hay varias formas de afrontar este tipo de páginas… lo que se recomienda (aunque a mi hay detalles que no me convencen, aunque se pueden llegar a corregir con un poco de ingeniería) es que se utilice responsive web design. Esto significa que dependiendo de ciertas especificaciones se carga un CSS u otro. Pero hay otras opciones como que se carguen CSS distintos según el tipo de “navegador” o directamente que haya URLs separadas según el tipo de web.

El caso que voy a tratar es concretamente el tercero, o sea, el caso en el que las versiones de los distintos dispositivos tienen URL distintas. Por ejemplo, podemos tener estas 3 versiones:

URL versión escritorio: http://www.example.com/page-one/

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Example</title>
  <link rel="alternate" media="only screen and (max-width: 640px)" href="http://m.example.com/page-one/">
  <link rel="alternate" media="handheld" href="http://phone.example.com/page-one/">
  <link rel="canonical" href="http://www.example.com/page-one/">
</head>

En este caso indicamos una URL alternativa para dispositivos móviles http://m.example.com/page-one/ y otra URL para dispositivos inteligentes http://phone.example.com/page-one/. ¿Qué habría que indicar en cada una de estas versiones?

URL versión móvil: http://m.example.com/page-one/

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Example</title>
  <link rel="canonical" href="http://www.example.com/page-one/">
</head>
URL versión smartphone: http://phone.example.com/page-one/

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Example</title>
  <link rel="canonical" href="http://www.example.com/page-one/">
</head>

Y en principio hasta aquí todo lo que hay que saber sobre los rel-canonical… pero antes de acabar, un detalle sobre esto último que tiene que ver con los Sitemaps… y es que en los Sitemaps XML también se le puede indicar las direcciones URL alternativas para las versiones móviles…

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <url>
    <loc>http://www.example.com/page-one/</loc>
    <xhtml:link rel="alternate" media="only screen and (max-width: 640px)" href="http://m.example.com/page-one/" />
    <xhtml:link rel="alternate" media="handheld" href="http://phone.example.com/page-one/" />
  </url>
</urlset>

¡Ala, ahí queda eso!

URL y las letras raras

Una de las preguntas recursivas en SEO, y sobre todo cuando se plantea un proyecto muy internacional es el de qué tipo de caracteres en las URL hay que usar en un sitio web que no es “occidental”. Supongo que cuando se hace uso del concepto “occidental” se hace referencia al sistema de caracteres ASCII.

La respuesta a este tipo de preguntas es un poco complejo. Si bien está permitido y es posible codificar las URL, la recomendación (de principios de Internet) es que no se haga uso de otros caracteres que no sean parte de un rango concreto del ASCII.

Para explicarlo todo mejor me voy a basar en la documentación oficial, es decir, los RFC, en este caso los siguientes:

  • RFC 1630: Universal Resource Identifiers in WWW
  • RFC 1736: Functional Recommendations for Internet Resource Locators
  • RFC 1737: Functional Requirements for Uniform Resource Names
  • RFC 1738: Uniform Resource Locators (URL)
  • RFC 1808: Relative Uniform Resource Locators
  • RFC 2368: The mailto URL scheme
  • RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax
  • RFC 2732: Format for Literal IPv6 Addresses in URL’s
  • RFC 3491: Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)
  • RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
  • RFC 3987: Internationalized Resource Identifiers (IRIs)
  • RFC 4248: The telnet URI Scheme
  • RFC 4266: The gopher URI Scheme
  • RFC 5987: Character Set and Language Encoding for Hypertext Transfer Protocol (HTTP) Header Field Parameters
  • RFC 6196: Moving mailserver: URI Scheme to Historic
  • RFC 6270: The ‘tn3270’ URI Scheme

Principalmente los RFC que hablan o que dejan de forma definitiva cómo ha de ser la estructura y qué y cómo funciona son el 1630 (documento de Tim Berners-Lee de Junio de 1994), 3986 y el 3987, con el añadido del 5987. ¿Y qué dicen estos estándar?

En el primer documento se habla de las diferencias entre URI, URL y URN, de la necesidad de establecer un sistema universal. El objetivo final tenía 3 propósitos: que fuera extensible para que se pudieran añadir nuevos formatos y estructuras en el futuro, completo de forma que se pudiera codificar cualquier sistema e “imprimible” por lo que se sugería el uso del ASCII 7-bits para que se pudiera escribir cualquier dirección “a mano” (vamos, en un papel, de forma sencilla).

NOTA sobre los recursos:

Una URI es lo que conocemos como la dirección completa que aparece en el navegador, lo que incluye el “protocolo” o “schema”.

Ejemplo: http://example.com/example.html?test=1#seccion

Una URL es la dirección sin necesidad de incorporar el protocolo…

Ejemplo: //example.com/example.html?test=1#seccion

Un URN es simplemente el nombre de un recurso…

Ejemplo: urn:isbn:9788441527829

Por eso, cuando hablemos de SEO propiamente dicho, habría que hablar de las URL ya que -en principio- no hay que tener en cuenta el protocolo (seguro o no) del HTTP.

Como detalles curiosos, se prefirió elegir la escritura de izquierda a derecha que la de derecha a izquierda por se la más común, y el hecho de haber elegido los “dos puntos” como separador (en los protocolos) fue algo de forma “arbitraria”.

Se definió el uso de los llamados caracteres “seguros” y “no-seguros”. Es por esto que quedaron algunos caracteres con funciones especiales:

  • “%” (ASCII 25 hex): Se usa para la codificación de caracteres “extraños”.
  • “/” (ASCII 2F hex): Se usa para delimitar subfragmentos de texto que dependen por herencia (vamos, lo que conocemos como “carpetas” o “niveles”). También se definía lo mismo con un punto (.) o dos puntos (..).
  • “#” (ASCII 23 hex): Se usa como delimitador para separar la URL de un objeto de un identificador.
  • “?” (ASCII 3F hex): Se usa como delimitador de la URI de un objeto “consultable” (vamos, un parámetro). En estos parámetros el símbolo “+” se usaría como “unión”. En el caso de tener que poner un símbolo “+” habría que codificarlo.
  • “*” (ASCII 2A hex) y “!” (ASCII 21 hex) se reservan para significados distintos según el schema pertinente (es decir, según el protocolo que se use: HTTP, Telnet, Mail, Gopher…).

Un detalle curioso es que, si os fijáis, hoy en día usamos otra serie de caracteres como habituales que en su momento no pasaron este corte. El caso más claro era el del “guión”. En aquel momento se planteaba que el guión no era un carácter especial.

Y tras esta base llegan un montón de RFC que, hoy en día, acaban siendo actualizados por el 3986. Este es el documento que hoy en día indica cómo han de ser las URI, en una sintaxis genérica. Es curioso que este documento es de 11 años después del primero, o sea, de enero de 2005, lo que significa que se podría plantear como una versión 2 muy importante y que deja claro cómo ha de ser el futuro de Internet.

Cuando hablamos de cómo ha de ser una URI (siguiendo lo que comentaba de los 3 grandes puntos al principio) tenemos que:

  • Una URI es una secuencia de caracteres que no siempre representa una secuencia de “octetos”.
  • Una URI debe poder ser transcrita desde una “no-red” (un papel, vamos) y debería constar de una serie de caracteres que pueden ser introducidos a un ordenador a través de un teclado, independientemente del idioma.
  • Una URI debería ser fácilmente recordable por las personas, y para ello debe estar formada por subpartes fácilmente familiares y significantes.

¿Qué caracteres deberíamos usar? Básicamente todo se basa en el US-ASCII. El símbolo % quedará como sistema de codificación. Esto implica que los caracteres no-seguros se pintarán como % seguido de 2 números. Estos números harán referencia al hexadecimal. Por ejemplo, el %20 hace referencia al caracter 20 del ASCII, que es el “espacio”. El resto de caracteres especiales queda definido en la lista: “!”, “$”, “&”, “‘”, “(“, “)”, “*”, “+”, “,”, “;” y “=”. Los caracteres no reservados son: “letras”, “números”, “-“, “.”, “_” y “~”. En estos últimos casos, cuando uno de ellos se encuentre codificado en la URL, se debe convertir a su valor original. Esto significa que si nos encontramos con una dirección así:

//example.com/ejemplo%2Dde%2Durl%2Ehtml

el navegador (o cualquier sistema) debe dejarlo estandarizado en:

//example.com/ejemplo-de-url.html

De esta forma, estos son caracteres semi-reservados ya que tienen un trato especial.

Las direcciones URI estarán formadas por los siguientes componentes:

  foo://example.com:8042/over/there?name=ferret#nose
  \_/   \______________/\_________/ \_________/ \__/
   |           |            |            |        |
scheme     authority       path        query   fragment
   |   _____________________|__
  / \ /                        \
  urn:example:animal:ferret:nose

No voy a entrar en qué ha de tener el “schema” o el “authority”, porque eso está muy limitado. De cara al SEO y a la Arquitectura de la Información, lo importante es el “path”, el “query” y el “fragment”.

¿Qué elementos son destacables en el “path”? Pues para empezar el uso de “.” o de “..”. Esto indica un nivel actual o un nivel “anterior”. Otros elementos serían el punto y coma “;” y el igual “=” que se reservan frecuentemente para delimitar parámetros y valores. La coma “,” también se reserva para un uso similar al anterior.

¿Qué elementos son destacables en el “query”? Pues principalmente el signo de interrogación “?” que indica el comienzo.

¿Qué elementos son destacables en el “fragment”? Pues principalmente el signo almohadilla “#” que indica el comienzo.

A lo largo de lo que llevo comentado he hablado de los dos puntos “..”. Este caso es muy concreto porque, al igual que los caracteres normales se han de recodificar, las direcciones URL que incluyan este caso también deberían codificarse. Esto es como ejemplo, lo siguiente:

//example.com/ejemplo-1/../ejemplo-2/

En realidad quedaría como:

//example.com/ejemplo-2/

Con respecto a la normalización del “schema” hay que tener presente que estas 4 direcciones son iguales:

http://example.com
http://example.com/
http://example.com:/
http://example.com:80/
HTTP://EXAMPLE.COM/

Pero de entre estas 4 direcciones hay que plantearse que una es la óptima. Esto significa que hay que aplicar algunas reglas. Para comenzar lo ideal es que acabe en “barra”, y que si el puerto es el de por defecto no se incluya. Además, esta primera parte debe estar en minúsculas. Esto significa que la dirección URI óptima sería la siguiente:

http://example.com/

Con respecto a otros componentes, y que hacen referencia a la “barra final”, tenemos por ejemplo estas dos direcciones:

http://example.com/data
http://example.com/data/

Aquí hay un detalle. Si estas dos direcciones acaban mostrando el mismo contenido (que es lo habitual), es más que recomendable que se utilice la de la barra final como principal.

http://example.com/data/

Cambiando al RFC 3987 tenemos un nuevo concepto delante: Internationalized Resource Identifier (IRI). Esto es un complemento de las URI, que es una secuencia de caracteres del Unicode / ISO 10646, formado por cerca de cien mil caracteres abstractos. Al final, como resumen, podemos decir que es el formato conocido como UTF-16.

¿Por qué hacer aparecer el IRI? Básicamente porque aunque se recomienda convertir caracteres no-ASCII a ASCII, hay veces que es conversión implica que algunas palabras no acaben de ser completamente razonables, o pueden implicar ambigüedad.

¿Cuándo se debe usar un IRI sobre un URI? Los protocolos deben estar designados para los IRI, algo que a priori no nos debería importar mucho para SEO y para nuestro trabajo habitual, pero, sí que hay otro punto y es el de usar IRI cuando la URI está codificada en UTF-8. El objetivo es cambiar las IRI a la codificación estándar de URI.

Personalmente las direcciones tales como:

http://example.com/𐌀𐌁𐌂

deberían transcribirse a una dirección tal que esta:

http://example.com/%F0%90%8C%80%F0%90%8C%81%F0%90%8C%82

Otro ejemplo de IRI es el tema de los dominios IDN (International Domain Name). En este caso la transcripción debe hacerse con el sistema PunyCode. Un ejemplo sería que la dirección del texto:

PorquénopuedensimplementehablarenEspañol
Porqu<eacute>nopuedensimplementehablarenEspa<ntilde>ol

acabaría siendo, en modo PunyCode así:

xn--PorqunopuedensimplementehablarenEspaol-fmd56a

Está claro que tener direcciones URI así está bien, porque todo son caracteres comprensibles, pero desde el unto de vista SEO no acaba de estar del todo bien.

Otro ejemplo, por ejemplo en checo, sería esto:

Pročprostěnemluvíčesky
Pro<ccaron>prost<ecaron>nemluv<iacute><ccaron>esky

acabaría como:

xn--Proprostnemluvesky-uyb24dma41a

Lo más difícil sería ya con algo tal que así, en ruso:

почемужеонинеговорятпорусски

que en formato PunyCode quedaría así:

xn--b1abfaaepdrnnbgefbaDotcwatmq2g4l

Hay que tener en cuenta otra cosa. Por norma general los elementos que incluyen una dirección URL (como por ejemplo los “a” o “img”) deben permitir que la dirección esté codificada. Es cosa de los navegadores la migración de la codificación a la codificación correspondiente. Esto significa que cuando en HTML se pone un enlace, habría que indicarlo de esta forma:

<a href="//ejeñplo.com/quéquieresdecirniño/">ejemplo</a>

En principio esto sería correcto, y el propio navegador hará la codificación, pero… ¿qué ocurre con los robots tipo Googlebot? Pues la verdad es que se puede decir que no hay mucha documentación sobre ello, y documentación oficial no parece haber ninguna, lo que significa que las codificaciones “extrañas” no acaban de quedar muy claras de cara al SEO y a la interpretación por parte de Google y otros.

¿Cuál es mi opinión personal y basada en la experiencia? Es mejor limitarse a usar sólo el rango [a-z0-9], ni siquiera mayúsculas para evitar problemas de duplicidades.

Un mes para el Postgrado Web Analytics

Sí, el 1 de marzo comienza el Postgrado Web Analytics y, creo que debería comanzar a prepararme las clases (no, es broma, ya tengo mucho avanzado…). Hace un tiempo que no os comentaba sobre el Postgrado Web Analytics y es que por algunos problemas técnicos hemos tenido que retrasarlo un par de semanas más. Así que los datos definitivos son estos:

  • Fecha de inicio: viernes 1 de marzo de 2013
  • Duración: 18+2 semanas (las 2 son de Semana Santa)
  • Créditos: 30 créditos ECTS
  • Horario: Viernes 17h-22h y Sábados 09h-14h
  • Lugar: Campus La Salle Barcelona (presencial)
  • Información concreta: descargar PDF
  • Matrícula: 3.900,00 €uros (información: descargar PDF)
  • Becas y ayudas: descargar PDF
  • Inscripción: descargar PDF
  • Consultas: +34 932 902 419 – admissions@salleurl.edu

Desde que escribí la última entrada algunos me habéis preguntado algunas dudas que creo que os puedo resolver ya. Por ejemplo, uno de los temas es el de los profesores. Estamos acabando de cerrar algunos pero en las filas tenemos a Jaime Ferré, Edu Bayo, Jorge González, Fernando Muñoz, Rafael Jiménez, Thomas Petit, Ignasi Faus o Marc Vicente. Además hay que sumar a los profesores de La Salle y a alguno que queda por confirmar.

Con respecto al calendario de clases y demás… hay un Google Calendar del PWA en la que, si os vais a marzo podréis comenzar a ver las clases. En la mayoría está puesto el profesor que las va a dar. Es un calendario por días, de forma que es un poco el programa más o menos detallado de los temas que se van a tratar. Si alguien tiene alguna consulta más detallada sobre el programa me lo podéis hacer por correo o directamente lo podéis consultar en la Salle (al correo o teléfono que os dejé antes) que os atenderán y darán todo lujo de detalles.

¿Por qué vale la pena hacer el Postgrado? Pues os voy a dar 3 razones: la primera porque creo que el temario y la calidad de los profesores es muy alta, cada uno en su especialidad; la segunda porque vamos a enfocarlo a un nivel muy práctico, muy real -la mayoría de los profes vendrán a explicar qué necesitan en su nivel, CEO, CTO, COO…- y porque uno de los objetivos que nos hemos propuesto es tener y usar datos reales de analítica, de forma que se trabajará día a día con lo que pasa en distintas empresas; la tercera porque es de la poca formación a la que me apuntaría yo (y a los que lo cursen, seguramente me veréis por allí bastante). Sé que este punto a lo mejor no dice mucho a mucha gente, pero los que me conocen saben que no soy muy dado a ir a charlas o formación si no es porque sé que voy a aprender algo.

Sitios web más accesibles

Aunque no es la primera vez que hablo del HTML semántico he decidido darle un repaso a todo lo que ARIA implica en el desarrollo de un sitio web. WAI-ARIA (Web Accessibility Initiative – Accessible Rich Internet Applications) son unas mejoras del HTML para mejorar la accesibilidad de los sitios web. Como ya dije en su momento, básicamente le da algo más de inteligencia semántica a los sitios.

Pero no hemos de olvidar que el propio HTML5 a diferencia de sus versiones anteriores ha incorporado que prácticamente todas sus etiquetas ya llevan incorporados ciertos elementos semánticos. Por poner un ejemplo, la etiqueta H1 ya implica un header. La cuestión es… ¿cuándo y cómo hay que usar ARIA en HTML?

La primera de las normas es bastante sencilla. Si un elemento HTML ya incluye semántica ARIA integrada, no hace falta indicarla, a menos que la queramos cambiar.

La segunda de las normas también es sencilla, aunque a mi personalmente no me gusta mucho. Es recomendable no sobre escribir las reglas ARIA de los elementos. Por poner un ejemplo:

No se debe hacer así:

<h1 role="button">botón en la cabecera</h1>

Sería mejor hacerlo así:

<h1><span role="button">botón en la cabecera</span></h1>

Aunque si lo queremos hacer óptimo, podemos usar:

<h1><button>botón en la cabecera</button></h1>

¿Qué significa esto? Pues que si por ejemplo hacemos algo de este estilo:

<h1 role=button>texto</h1>

Realmente lo que tendríamos a nivel significado es esto:

<button>texto</button>

Otro ejemplo sería el siguiente:

<button role="heading" aria-level="1">texto</button>

Que nos dejaría con algo tan simple como esto:

<h1>texto</h1>

Vale, hasta aquí nos queda claro que es importante usar el significado que viene por defecto en los diferentes elementos o la oportunidad de sobre escribir el significado de los mismos, pero… ¿qué ocurre con todo ese código “de mierda” que metemos en las páginas que en principio llevan significado de por sí, pero que realmente sólo usamos para “dar formato” a lo que queremos? Pues para este tipo de código podemos utilizar un sistema que elimina cualquier significado: el role="presentation".

Un detalle de este parámetro es que se come el significado también de cualquier etiqueta hija que incluya. Para poner un ejemplo algo “complejo” os dejo este:

<table role="presentation">
  <tr>
    <td>
      <table>
        <tr>
          <td><abbr title="Application Programming Interface">API</abbr></td>
        <tr>
      </table>
    </td>
  </tr>
</table>

Realmente, su significado “real” quedaría mucho más reducido, a esto:

<>
  <>
    <>
      <table>
        <tr>
          <td><abbr title="Application Programming Interface">API</abbr></td>
        <tr>
      </table>
    </>
  </>
</>

Personalmente, desde el punto de vista SEO este último elemento debería tener todo el sentido del mundo ya que implicaría quitarle significado a toda la basura de código que muchas veces se genera en determinados sitios web. Aún así, Bing y Google tratan ARIA de formas muy distintas y dispersas y no queda claro su funcionamiento. Después de esto, mi pensamiento es que si se hace bien y se pone el código como se debe, mal no debe hacer.

¿Cómo se oculta información? Habitualmente usamos a través de CSS el display:none o el visibility:hidden, pero esto simplemente lo que hace es no mostrarlo, pero sigue siendo “visible” desde el punto de vista de la accesibilidad. ¿Cómo eliminarlo? Pues añadiendo el aria-hidden. Hay que tener tener en cuenta que una de las novedades en HTML5 es que todos los elementos del DOM incluyen el nuevo atributo hidden, lo que significa que otra forma de ocultar contenidos se puede aplicar con un pequeño JavaScript tal que así:

<script>
  function ocultar() {
    document.getElementById('prueba').hidden = true;
  }
</script>

Existen muchos roles en el sistema, y como ya he comentado al principio la mayoría de etiquetas del HTML ya incluyen su significado semántico… pero no todos los elementos disponen de sus propios roles.

  • Cualquier elemento: como ya he comentado antes, cualquier elemento podría usar el role="presentation".
  • address: podría incorporar en caso necesario el role="contentinfo" que amplia la información del documento actual.
  • article: los navegadores aún no indican su rol por defecto, así que habría que indicarlo expresamente con role="article".
  • details: como el anterior, aún no va de serie, así que hay que indicarle el role="group".
  • dialog: otro que debería y no lo lleva de serie, con el role="dialog".
  • div, p, pre y blockquote: no tienen un rol definido por defecto, así que les podemos asignar el que nos venga en gana según necesitemos.
  • footer: es curioso que este elemento no lleve un significado implícito, por lo que si en la página hay un pie “general”, a ese en concreto se le puede asignar el role="contentinfo".
  • header: al igual que el pie, este tampoco lleva implícito nada, por lo que podríamos utilizar por ejemplo el role="banner" si es la cabecera principal.
  • main: este elemento que se está planteando par el HTML5.1 debería ir acompañado siempre del role="main".
  • nav: indica una navegación por lo que debería ir acompañado del role="navigation".
  • span: el “tag inútil” tiene una gran ventaja… al igual que el div se le puede incorporar cualquier rol.
  • table: aunque no incopora ningún significado por defecto hay dos opciones que sí que se podrían utilizar; la primera es cuando se le da uso de “diseño”, por lo que es inútil y se debería eliminar cualquier significado con el role="presentation"; en el caso de que se le de un uso de tabla pura, se le podría dar el role="grid".

A parte de estos elementos que son principalmente contenedores tenemos otros como em, strong, small, s, cite, q, dfn, abbr, time, code, var, samp, kbd, sub, sup, i, b, u, mark, ruby, rt, rp, bdi, bdo, br, wbr… que como son utilizables para dar formato no incorporan ningún tipo de significado semántico. Se les puede dar el rol que se quiera, pero personalmente no creo que sea recomendable.

Hasta ahora he comentado varios de los posibles roles que se pueden utilizar, pero la lista de roles es bastante grande…

  • alert: Un mensaje importante y con una duración en el tiempo limitada.
  • alertdialog: Un bloque que incluye un mensaje de alerta.
  • application: Todo lo contrario a un “documento”. O sea, que no es una web.
  • article: Parte de un documento que se puede tratar como un elemento independiente.
  • banner: Bloque que suele contener contenido para todo el sitio.
  • button: Sistema que reacciona tras un clic o presión.
  • checkbox: Entrada que tiene 3 posibles estados: verdadero, falso o mixto.
  • columnheader: Celda que contiene la información de una columna.
  • combobox: Un listado en el que además se pueden añadir opciones.
  • complementary: Contenido complementario al contenido principal pero que a su vez tiene significado propio.
  • contentinfo: Información relacionada al contenido principal.
  • definition: Definición de un concepto.
  • dialog: Ventana que detiene el proceso actual a la espera de que el usuario introduzca información para continuar.
  • directory: Referencia a un grupo de elementos (como si fuera un índice).
  • document: Todo el contenido de una página web.
  • form: Un formulario (y todo lo que lo acompaña).
  • grid: Como una tabla, tiene filas y columnas con celdas.
  • gridcell: Una celda.
  • group: Una lista de objetos pero que no es un directorio.
  • heading: La cabecera del contenido de una página.
  • img: Colección de elementos que forma una imagen.
  • link: Referencia que, cuando se pulsa, hace que el navegador vaya a ese recurso.
  • list: Lista de elementos no interactivos.
  • listbox: Lista de elementos interactivos con el usuario.
  • listitem: Elemento de una lista o directorio.
  • log: Zona en la que se va añadiendo información nueva dejando paso de la anterior.
  • main: Contenido principal del documento.
  • marquee: Zona en la que la información (no esencial) va cambiando.
  • math: Expresión matemática.
  • menu: Lista de opciones para un usuario.
  • menubar: Menú habitualmente siempre visible y en horizontal.
  • menuitem: Opción dentro de un menú.
  • menuitemcheckbox: Opción de un menú que tiene 3 posibles estados: verdadero, falso o mixto.
  • menuitemradio: Opción de menú que sólo permite una posibilidad a la vez.
  • navigation: Elementos que permiten la navegación por páginas externas o internas.
  • note: Bloque que añade información puntual al documento principal.
  • option: Elemento seleccionable de una lista.
  • presentation: Elemento que no debe ser accesible.
  • progressbar: Barra de progreso.
  • radio: Elementos que sólo pueden ser seleccionables una vez.
  • radiogroup: Grupo de elementos que sólo pueden ser seleccionables una vez.
  • region: Agrupación de contenidos que podrían estar en un directorio.
  • row: Fila de celdas.
  • rowgroup: Grupo de filas de celdas.
  • rowheader: Celda que contiene la información de una fila de celdas.
  • scrollbar: Barra de navegación que controla el scroll de una zona.
  • search: Bloque que agrupa elementos que permiten realizar búsquedas.
  • separator: Separador de secciones en un contenido o grupos de menús.
  • slider: Lugar de selección entre valores de un determinado rango.
  • spinbutton: Rango de opciones en los que el usuario ha de elegir.
  • status: Bloque de información para el usuario no tan importante como una alerta.
  • tab: Etiquetas que permiten al usuario una ayuda sobre el contenido.
  • tablist: Lista de “tabs”.
  • tabpanel: Contenedor de “tablist”.
  • textbox: Texto libre.
  • timer: Contador de tiempo.
  • toolbar: Colección de botones.
  • tooltip: Contenido contextual de información de un elemento.
  • tree: Lista que permite extender o contraer sus elementos.
  • treegrid: Listas por filas que permiten expandir o contraer sus elementos.
  • treeitem: Elemento de un árbol.

Ahora que tenemos todo esto sobre la mesa… Cuando hablan de la Web 3.0 ¿se refieren a esto?

HTML5 Server-Sent Events

Por si no lo sabíais el HTML5 me apasiona, principalmente no por el HTML en sí sino por todo lo que lleva a su alrededor. Y hoy toca hablar de los eventos Server-Sent. Básicamente este sistema lo que permite es que el navegador reciba información de forma automática de una fuente de datos sin necesidad de recargar la página.

El funcionamiento es tan sencillo como indicar la URL desde la que se cargarán los datos y esperar a que los datos vayan apareciendo por pantalla. Como datos a tener en cuenta es que esto no funciona en Internet Explorer (ni en la versión 10) aunque sí que lo hace en Firefox 6 y Chrome. Personalmente a mi en Chrome no em acaba de funcionar, intuyo, por un problema con saltos de línea y similares.

Y es que la fuente de datos ha de enviar los textos comenzando por data: y finalizando por un salto de línea o End Of Line, algo que parece que no acaba de dar el peso en todos sitios.

El ejemplo que he preparado (descargar) básicamente muestra por pantalla números aleatorios… aunque se puede cargar prácticamente cualquier cosa.

El único inconveniente es que no he visto en la documentación la forma de cambiar la frecuencia con la que el navegador llama para la carga de los datos. Aún así, gracias a esto nos evitaremos el uso de iframes o de peticiones AJAX.

Piensa en asíncrono

Sin duda una de las mejoras del HTML5 es la posibilidad de cargar determinados elementos de forma asíncrona en la página. Y es que si tus usuarios utilizan navegadores de versiones superiores a Firefox 3.6, IE 10, Chrome 2, Safari 5, iOS 5 o Android 3 dispones de la posibilidad de hacerlo fácil:

<script async src="http://example.com/javascript.js"></script>

La carga de los scripts se puede hacer de muchas formas… la más sencilla, por ejemplo si es de un recurso propio, se puede hacer de esta forma:

<script>
  var resource = document.createElement('script');
  resource.src = "http://example.com/javascript.js";
  var script = document.getElementsByTagName('script')[0];
  script.parentNode.insertBefore(resource, script);
</script>

O también de esta forma… ambas son similares:

<script>
  (function(d, t) {
    var g = d.createElement(t),
    s = d.getElementsByTagName(t)[0];
    g.src = 'http://example.com/javascript.js';
    s.parentNode.insertBefore(g, s);
  }(document, 'script'));
</script>

Esta es una forma que permite la carga aunque no es del todo efectiva ya que no siempre se carga asíncronamente. Para ello, sobretodo si es de scripts externos se puede usar algo más así:

<script>
  (function(){
    var a = document.createElement('script');
    a.type = 'text/javascript';
    a.async = true;
    a.src = 'http://example.com/javascript.js';
    (document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(a);
  })();
</script>

Ahora que ya sabemos cargar los scripts de forma sencilla y asíncrona… ¿por qué no cargar algunos scripts “famosos” de forma sencilla y sin que afecte negativamente a tu sitio web?

El código de Facebook:

<div id="fb-root"></div>
<script>
  (function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s);
    js.id = id;
    js.src = "http://connect.facebook.net/es_ES/all.js#xfbml=1";
    fjs.parentNode.insertBefore(js, fjs);
  }(document, 'script', 'facebook-jssdk'));
</script>

El código de Twitter:

<a href="https://twitter.com/share" class="twitter-share-button">Twitear</a>
<script>
  !function(d,s,id) { 
    var js,fjs = d.getElementsByTagName(s)[0];
    if(!d.getElementById(id)) { 
      js = d.createElement(s);
      js.id = id;
      js.src = "http://platform.twitter.com/widgets.js";
      fjs.parentNode.insertBefore(js,fjs);
    }
  } (document,"script","twitter-wjs");
</script>

El código de Google+:

<g:plusone annotation="inline"></g:plusone>
<script type="text/javascript">
  (function() {
    var po = document.createElement('script');
    po.type = 'text/javascript';
    po.async = true;
    po.src = 'http://apis.google.com/js/plusone.js';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(po, s);
  })();
</script>

Pero… ¿no sería más sencillo mantener un único código para todo? La solución es bastante sencilla, ya que al fin y al cabo en todos los casos se carga de la misma forma…

<script>
  (function(doc, script) {
    var js, fjs = doc.getElementsByTagName(script)[0], add = function(url, id) {
      if (doc.getElementById(id)) {
        return;
      }
      js = doc.createElement(script);
      js.src = url;
      id && (js.id = id);
      fjs.parentNode.insertBefore(js, fjs);
    };
    add('http://www.google-analytics.com/ga.js', 'ga');
    add('http://apis.google.com/js/plusone.js');
    add('http://connect.facebook.net/es_ES/all.js', 'facebook-jssdk');
    add('http://platform.twitter.com/widgets.js', 'twitter-wjs');
  } (document, 'script'));
</script>

¡Ahora a reprogramar!