Tracking de Instalaciones en Apps

A la hora de elegir un sistema de rastreo, uno de los trackers, hemos de tener en cuenta, entre otras cosas, qué método van a utilizar a la hora de decidir cuál es la identificación del dispositivo. Al no existir un estándar entre las distintas plataformas, dependiendo del sistema operativo o de la storepodemos tener mayor facilidad para saber qué dispositivo único (parecido a los usuarios únicos en web) tenemos delante.

Device Fingerprint

Este sistema anónimo intenta detectar una serie de eventos en los que haya una alta probabilidad de concordancia. En base a estos elementos, podemos llegar a interpretar que si una persona pulsa un anuncio y un poco después se instala una aplicación, es el mismo dispsitivo el que ha realizado dicha instalación. Algunos datos pueden ser la IP, la fecha, el navegador, etc…

Este proceso es completamente transparente para el usuario y tárda unas décimas de segundo en procesarse, por lo que es poco probable que ningún sistema cierre esta forma de trabajar. Pero esto puede generar algunos duplicados o falsas huellas, ya que se pueden generar algunas discrepancias. la fiabilidad ronda el 95%.

UDID (obsoleto), IFA e IFV

Aunque el UDID (Identificador único de dispositivo) de Apple era el sistema para saber exactamente qué dispositivo teníamos entre manos, siendo un identificador único y por tanto fiable, este sistema llegó a un proceso de falta de privacidad altamente preocupante por lo que quedó obsoleto. Para ello Apple se sacó de la manga el IFA (identificador de la publicidad) que no es permanente, no es personal y las Apps tienen acceso a él de forma libre. De una forma similar tenemos el IFV (identificador de proveedor) para detectar aquellas Apps que ya vienen con el dispositivo o son Apps que incorpora la propia operadora de serie. Hay que tener presente que este identificador sólo funciona en iOS y que está previsto que en iOS7 se incorpore una opciónd e opt-out, para que no pueda ser utilizado.

Cookie Tracking

Es un sistema planteado para Safari en iOS y es similar al de las cookies tradicionales de cualquier navegador. Este sistema básicamente lo que permitía es que, al abrir un enlace de una App desde Safari se pasaba esta cookie a la App, pero esa era su completa limitación. Actualmente no es lo que más se utilice debido a su gran limitación y a la entrada de otros navegadores en iOS.

Android Referrer

Este es, como su nombre indica, el sistema elegido por el propio Google para Android. Es una evolución de Google Analytics y básicamente permite que Google Play recoja los parámetros tradicionales (UTM) y se hagan llegar a la propia App. pero, como su nombre indica y comento, sólo es válido para Android.

OpenUDID

Esta es la aplicación que plantea la comunidad libre, de uso gratuito y que pemite el paso de este identificador entre aplicaciones, de forma que sólo se genera un único código por dispositivo. Vendría a ser la idea de sustitución del UDID. Este sistema tiene la opción de opt-out y parece ser la alternativa óptima en estos momentos.

MAC Address

La dirección MAC (Media Access Control) es la herramienta que históricamente se ha utilizado para identificar las tarjetas de red en cualquier dispositivos. Este identificador es único por hardware y en general su uso va mediante encriptación. De la misma forma que pasaba con el UDID, este identificador no se puede cambiar, por lo que aunque el 100% fiable no permite una protección de privacidad.

ODIN

El ODIN (Open Device Identifier Number) tiene la misma filosofía del OpenUDID pero con la diferencia de que se plantea como un identificador multi dispositivo, de forma que, por decirlo de alguna manera, identifica un usuario pero de forma anónima al dispositivo. Este identificador es válido en todas las plataformas (iOS, Android, Windows Mobile…) pero no está, actualmente, muy en mente de los desarrolladores, por lo que tiene un bajo uso.

Aunque estos son los sistemas abiertos o cerrados más utilizados, existen otros tantos, principalmente proporcionados por plataformas publicitarias, pero que no están profundizando tanto como lo están haciendo estos anteriormente mencionados.

Analítica móvil

Según van pasando los días en Geenapp y recibimos solicitudes de información de cómo promocionar una App en nuestra plataforma muchos desarrolladores quieren saber cómo hacemos para medir. Y ese es el elemento básico y el secreto de la promoción de cualquier App: la analítica móvil. El ejemplo claro y sencillo, para los que hayáis tenido un sitio web es el de poner siempre Google Analytics. Es quizá la forma más sencilla de medir la información de un sitio web. ¿Por qué no hacer exactamente lo mismo con una App? Sí, se puede. En Geenapp estamos integrados con las mayores plataformas de medición que además nos ayudan a, entre otras cosas, poder medir las instalaciones nuevas realizadas en la App. ¿Y cuáles son estas plataformas de analítica? Tenemos, por ejemplo, las siguientes:

Cada una de estas plataformas funciona a su manera, unos te cobran por evento, otros te dan el servicio gratis, otros te cobran por petición recibida… Lo importante es que estas herramientas te dan un panel de control en el que poder ver el uso de la App, los nuevos usuarios / instalaciones, el engagement, qué secciones de la App son las más visitadas, qué acciones son las que más utilizan los usuarios. Además, si vas a promocionar, de cualquier manera, tu App, es básico saber qué fuentes son las que te generan el mayor tráfico, conversiones, instalaciones y, en definitiva, dónde conseguir los mejores usuarios para una mayor conversión.

WordPress con Integridad Relacional

WordPress por defecto suele venir preparado para una base de datos en MySQL con su sistema de almacenamiento en myISAM. Pero este sistema no tiene integridad referencial. Esto puede llegar a implicar que la velocidad a la hora de relacionar los campos de tablas distintas no acaba de ser el que debería, y hay una posibilidad de mejorarlo con innoDB.

Con el siguiente script se puede convertir la base de datos a este sistema:

ALTER TABLE cb_commentmeta ENGINE=InnoDB;
ALTER TABLE cb_comments ENGINE=InnoDB;
ALTER TABLE cb_links ENGINE=InnoDB;
ALTER TABLE cb_options ENGINE=InnoDB;
ALTER TABLE cb_postmeta ENGINE=InnoDB;
ALTER TABLE cb_posts ENGINE=InnoDB;
ALTER TABLE cb_terms ENGINE=InnoDB;
ALTER TABLE cb_term_relationships ENGINE=InnoDB;
ALTER TABLE cb_term_taxonomy ENGINE=InnoDB;
ALTER TABLE cb_usermeta ENGINE=InnoDB;
ALTER TABLE cb_users ENGINE=InnoDB;

ALTER TABLE cb_comments ADD INDEX ( user_id ) ;
ALTER TABLE cb_links ADD INDEX ( link_owner ) ;
ALTER TABLE cb_posts ADD INDEX ( guid ) ;
ALTER TABLE cb_posts ADD INDEX ( post_date ) ;
ALTER TABLE cb_term_taxonomy ADD INDEX ( term_id ) ;
ALTER TABLE cb_term_taxonomy ADD INDEX ( parent ) ;
ALTER TABLE cb_users ADD INDEX ( user_email ) ;

UPDATE cb_term_taxonomy SET term_id=NULL WHERE term_id=0;
UPDATE cb_term_relationships SET term_taxonomy_id=NULL WHERE term_taxonomy_id=0;
UPDATE cb_term_taxonomy SET parent=NULL WHERE parent=0;
UPDATE cb_commentmeta SET comment_id=NULL WHERE comment_id=0;
UPDATE cb_links SET link_owner=NULL;
UPDATE cb_postmeta SET post_id=NULL WHERE post_id=0;
UPDATE cb_usermeta SET user_id=NULL WHERE user_id=0;
UPDATE cb_comments SET comment_post_ID=NULL WHERE comment_post_ID=0;
UPDATE cb_comments SET user_id=NULL WHERE user_id=0;
UPDATE cb_comments SET comment_parent=NULL WHERE comment_parent=0;
UPDATE cb_posts SET post_author=NULL WHERE post_author=0;

ALTER TABLE cb_term_taxonomy CHANGE term_id term_id BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE cb_term_relationships CHANGE term_taxonomy_id term_taxonomy_id BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE cb_term_taxonomy CHANGE parent parent BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE cb_commentmeta CHANGE comment_id comment_id BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE cb_links CHANGE link_owner link_owner BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE cb_postmeta CHANGE post_id post_id BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE cb_usermeta CHANGE user_id user_id BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE cb_comments CHANGE comment_post_ID comment_post_ID BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE cb_comments CHANGE user_id user_id BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE cb_comments CHANGE comment_parent comment_parent BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE cb_posts CHANGE post_author post_author BIGINT( 20 ) UNSIGNED NULL DEFAULT NULL ;

ALTER TABLE cb_links ADD FOREIGN KEY ( link_owner ) REFERENCES cb_users (ID) ON DELETE RESTRICT ON UPDATE  RESTRICT ;
ALTER TABLE cb_term_taxonomy ADD FOREIGN KEY ( term_id ) REFERENCES cb_terms (term_id) ON DELETE RESTRICT ON UPDATE  RESTRICT ;
ALTER TABLE cb_term_relationships ADD FOREIGN KEY ( term_taxonomy_id ) REFERENCES cb_term_taxonomy (term_taxonomy_id) ON DELETE RESTRICT ON UPDATE  RESTRICT ;
--ALTER TABLE cb_term_taxonomy ADD FOREIGN KEY ( parent ) REFERENCES cb_term_taxonomy (term_taxonomy_id) ON DELETE RESTRICT ON UPDATE  RESTRICT ;
ALTER TABLE cb_usermeta ADD FOREIGN KEY ( user_id ) REFERENCES cb_users (ID) ON DELETE RESTRICT ON UPDATE  RESTRICT ;
ALTER TABLE cb_postmeta ADD FOREIGN KEY ( post_id ) REFERENCES cb_posts (ID) ON DELETE RESTRICT ON UPDATE  RESTRICT ;
ALTER TABLE cb_commentmeta ADD FOREIGN KEY ( comment_id ) REFERENCES cb_comments (comment_ID) ON DELETE RESTRICT ON UPDATE  RESTRICT  ;
ALTER TABLE cb_comments ADD FOREIGN KEY ( comment_post_ID ) REFERENCES cb_posts (ID) ON DELETE RESTRICT ON UPDATE  RESTRICT ;
--ALTER TABLE cb_comments ADD FOREIGN KEY ( comment_parent ) REFERENCES cb_comments (comment_ID) ON DELETE RESTRICT ON UPDATE  RESTRICT ;
--ALTER TABLE cb_comments ADD FOREIGN KEY ( user_id ) REFERENCES cb_users (ID) ON DELETE RESTRICT ON UPDATE  RESTRICT ;

De todas formas, si aplicamos esto, debido a que WordPress no stá bien desarrollado, hay dos elementos que no se pueden relacionar, sino el sistema deja de funcionar, que son las relaciones de etiquetas con entradas, y de los comentarios.

Eso significa que las consultas marcadas como comentarios no deben ejecutarse a menos que se haga un pequeño hackeo del código fuente del propio WordPress para eliminar esta incompatibilidad.

Bloquear un robot de rastreo / buscador

Hay varias formas de bloquear la aparición de páginas en los resultados de búsqueda, pero no todas ellas sirven para lo mismo. Y todo viene porque hacemos un mal uso de las palabras [rastrear] e [indexar].

En base a todo esto hay que diferenciar varias opciones: bloquear por robots.txt, usar el meta-noindex (y su respectiva cabecera HTTP), usar el rel-nofollow

El sistema de bloqueo por robots.txt es el más restrictivo. La idea es que un robot se encuentre en una especie de pasillo y haya puertas a su alrededor. El robot sabe que hay puertas, pero en este caso estas puertas están tapiadas. El robot podría llegar a saber qué hay detrás de esas puertas porque otras puertas o gente de otros pasillos le dicen lo que hay, pero no puede entrar a comprobarlo porque para él esa puerta está tapiada. Esto, en resumen, es que si uno (o varios) elementos están bloqueados por Disallowno deben tenerse en cuenta en absoluto para nada a la hora de organizar los resultados.

El uso del meta-robots (o su cabecera HTTP, que hace exactamente lo mismo) tiene otro objetivo. Siguiendo con el ejemplo de las puertas, esta puerta está disponible para entrar, chafardear pero el robot no le puede decir a nadie lo que ha visto dentro de esa habitación. La diferencia con el punto anterior es que, en este caso el robot sí que conoce lo que hay dentro y lo puede utilizar a la hora de ordenar los resultados, pero con una condición: no le puede decir a nadie lo que hay. Esto significa que se puede rastrear el contenido, que se puede usar a tener en cuenta a la hora de generar el índice pero no puede estar en el índice. Por lo tanto, los elementos con noindexhan de estar bien pensados porque sí que afectan a SEO (aunque no se vean en los SERP).

Para acabar, con respecto al rel-nofollowme gustaría dejar claro que los robots sí que siguen estos enlaces (si quieren) y que, en este caso, son ellos los que deciden qué peso darles. Esto viene por lo que el estándar dice y no lo que Google dice:

The nofollow keyword indicates that the link is not endorsed by the original author or publisher of the page, or that the link to the referenced document was included primarily because of a commercial relationship between people affiliated with the two pages.

Como bien dice el texto, el rel-nofollowsignifica que el enlace de destino no tiene que ver con el autor original del artículo o del soporte o que se ha incluido como parte de una relación comercial entre las dos páginas. En ningún caso indica que los enlaces no se tengan que seguir.

En este último caso no se puede confundir con el meta-nofollow. En este caso sí que los robots deberían no seguir los enlaces que hay en toda esa página:

The NOFOLLOW directive only applies to links on this page. It’s entirely likely that a robot might find the same links on some other page without a NOFOLLOW (perhaps on some other site), and so still arrives at your undesired page.

Para acabar, algunos buscadores (como Google) tienen en sus herramientas para webmasters una zona en la que poder “sacar” determinadas páginas de los resultados. Hay que ener en cuenta que un buscador no puede eliminar contenidos de su índice a menos que esté bloqueado anteriormente, y esta es la razón por la que antes de eliminar nada te solicita que esté bloqueado el contenido o que de un código de error 4xx. Si se cumple esto (para que en un siguiente rastreo no se añada el contenido) se realiza un trabajo que, una vez listados los resultados de búsqueda se filtran estos contenidos que se le han indicado para que no aparezcan, aunque, se podría decir, que es “un apaño” temporal hasta la siguiente actualización del índice.

ARPANET y el origen de Internet

¿Tienes presente que “Internet” comenzó a gestarse en 1967 y que se puso “en línea” en 1969? Estas últimas semanas he tenido la oportunidad de revisar documentos oficiales y, por curiosidad, comencé a mirar la primera documentación que hubiera sobre Internet… pero, en realidad fui tirando para atrás y, al final, en el RFC 8 [ARPA Network Functional Specifications. G. Deloche. May 1969. (Status: UNKNOWN)] se habla de él…

Es curioso porque este documento no es muy sencillo de encontrar, pero buscando y buscando he conseguido una copia de ese RFC 8. Lo entretenido del documento es que no se entiende prácticamente nada y que sólo la primera página (la portada) está hecha a máquina de escribir. 7 páginas escritas y 2 de un diagrama es la base de Internet, iniciado todo por una petición del Departamento de Defensa de los USA. Gerard Deloche es el redactor de dicho documento, trabajando en UCLA, el 2º nodo de la red de redes el 21 de noviembre de 1969.

Unos años después, en diciembre de 1974, un señor llamado Vinton Cerf (este seguramente os suene algo más) publicaba la primera especificación de una cosa llamada “Internet”, el RFC 675 [Specification of Internet Transmission Control Program. December 1974. (Status: UNKNOWN)]. Que conste que el TCP se preparó antes, pero la especificación “final” apareció con ese documento. Y hay que tener en cuenta que esto sólo explica cómo transportar los paquetes, la información, pero no habla todavía de las direcciones IP; es el RFC 791 [Internet Protocol. J. Postel. September 1981. (Status: STANDARD)], entrada basada en las 6 versiones anteriores existentes del IP de DARPA.

This document specifies the DoD Standard Internet Protocol. This document is based on six earlier editions of the ARPA Internet Protocol Specification, and the present text draws heavily from them. There have been many contributors to this work both in terms of concepts and in terms of text. This edition revises aspects of addressing, error handling, option codes, and the security, precedence, compartments, and handling restriction features of the internet protocol.

Eso sí, mucho protocolo, mucho sistema de transporte pero hasta que el 1989 no se acabaron los OSI para el TCP/IP y que Tim Berners-Lee se inventase el HTML, el primer navegador (llamado WorldWideWeb) y se pusiera en marcha el primer servidor web en un Next (sí, esos ordenadores que fabricó Steve Jobs cuando lo echaron de Apple).

Además, hay un detalle que, si me paro a pensarlo fríamente es muy fuerte. Hasta 1993 el gobierno de Estados Unidos tenía como mandatario que Internet no podía tener un concepto comercial, sólo de comunicación académica, científica y gubernamental. Esto da mucho a pensar de los primeros buscadores, los primeros sitios web y que yo me comenzase a conectar en 1994 de tanto en tanto…

Hay mucha documentación en la red de redes sobre los comienzos de Internet, pero, la verdad, tras unas conversaciones con Xavier (compañero en el Postgrado Web Analytics) que colabora con el CERN, donde se cocinó y coció lo que hoy me da de comer, creo que valía la pena simplemente hacer un pequeño homenaje a todo esto tan grande que se ha creado prácticamente de la nada.

Los DNAME en las DNS

Aunque ahora mismo es tan sólo una propuesta, creo muy acertada esta nueva posible entrada de las DNS porque, sobretodo a nivel de rendimiento de WPO podría dar un salto cualitativo en cuanto a determinadas acciones que hacemos habitualmente con los dominios, más concretamente con las redirecciones. Incluso, he de añadir, para reducir el impacto de la cantidad de líneas que puede haber en los servidores DNS.

Para situarnos estoy hablando de la propuesta del RFC 6672(DNAME Redirection in the DNS) que propone incorporar una entrada nueva llamada DNAME.

Para no entrar en detalles muy raros, voy a intentar poner un caso para ver el sentido que tiene. Imaginad que tenemos dos dominios iguales, con las mismas entradas DNS. Por ejemplo [example.com] y [dominio.es]. Dado este caso, en que los dos dominios son exactamente iguales (a nivel DNS)… ¿tiene sentido mantener dos copias de las entradas DNS? ¿No sería más fácil decir que las entradas DNS de [dominio.es] son una copia de las de [example.com] y simplemente cambiando las del .com que se actualizase todo?

Pues básicamente este es el objetivo de la entrada DNAME. El ejemplo visual (los que tocáis mucho las DNS seguramente lo pilléis enseguida:

    QNAME            owner  DNAME   target         result
    ---------------- -------------- -------------- -----------------
    com.             example.com.   example.net.   <no match>
    example.com.     example.com.   example.net.   [0]
    a.example.com.   example.com.   example.net.   a.example.net.
    a.b.example.com. example.com.   example.net.   a.b.example.net.
    ab.example.com.  b.example.com. example.net.   <no match>
    foo.example.com. example.com.   example.net.   foo.example.net.
    a.x.example.com. x.example.com. example.net.   a.example.net.
    a.example.com.   example.com.   y.example.net. a.y.example.net.
    cyc.example.com. example.com.   example.com.   cyc.example.com.
    cyc.example.com. example.com.   c.example.com. cyc.c.example.com.
    shortloop.x.x.   x.             .              shortloop.x.
    shortloop.x.     x.             .              shortloop.

El objetivo es que el campo “target” sea como el sustituto del patrón que se le pasa. De esta forma, poniendo la tercera línea de ejemplo, tendríamos que, partiendo de la base de [a.example.com] el dominio sería [example.com] y el DNAME sería [example.net], si hacemos un “sustituir” de [example.net] por [example.com] nos quedaría [a.example.net].

El planteamiento, a nivel de similitud, es como un CNAME con esteroides, ya que no deja de ser como un alias, pero que además sustituye fragmentos de las entradas DNS por otras que pueden ser de otro dominio.

Un detalle interesante es que, aunque no se recomienda su uso, se podría a llegar a utilizar el “wildcard” (o sea, el [*.example.com] para sustituir grandes cantidades de entradas DNS por otras. No se recomienda el uso porque podría invalidar el DNSSEC, pero la verdad, teniendo en cuenta la poca penetración que tiene, tampoco tengo claro que, para la mayoría, sea un problema.

Aunque no deja de ser una propuesta (en mi opinión muy interesante) no tengo claro que sea algo que se vaya a implementar rápidamente. Seguramente dependerá más de los ISP que comiencen a implementar servidores que lo soporten, pero, tampoco es algo que creo que sea muy recomendable para la gran mayoría de los usuarios, ya que un pequeño error puede provocar la invalidación de las DNS. Así que, lo más probable es que para añadir una entrada de este tipo se tengan que hacer varias validaciones “automáticas” para controlar las posibles cagadas poniendo estas entradas.

Dominios reservados

¿Cuál es el dominio que no existe y que deberíamos usar siempre que hacemos referencia a una dirección URI que no existe? Pues hay varios, no os lo voy a negar, y todo depende de las necesidades que tengamos.

Y es que existe el RFC 2606 que habla de esto mismo… los Reserved Top Level DNS Names. Básicamente este documento nos informa de los 4 TLD que hay cuando queremos hacer referencia a pruebas.

  • .test: Se recomienda para probar DNS.
  • .example: Se recomienda cuando en un documento se hace referencia a alguna dirección.
  • .invalid: Se recomienda cuando se hace referencia a dominios incorrectos o errores.
  • .localhost: Este es el único que técnicamente no es del todo un error o un ejemplo, ya que se puede utilizar internamente en las DNS para hacer una autollamada o hacer uso de direcciones IP privadas sobre él.

Claro está, esto es siempre para los TLD, pero ¿qué ocurre en los segundos nivele? Vamos, en lo que normalmente conocemos como un “dominio”? Para ello el sistema es claro: example.com, example.net y example.org.

Hay otros TLD de los nuevos que, ya de base, llevan una serie de limitaciones. Por ejemplo el .INFO define el dominio [example.info] como un dominio .info reservado en este caso para la IANA. Esto mismo ocurre con los dominios .biz reservadosque excluyen el [example.biz]. En principio, el resto de dominios, como desde hace tiempo, son asignados y aprobados por IANA, ocurre lo mismo.

En el caso de los ccTLD no se especifica nada a nivel general, sino que el bloqueo de los dominios queda en manos de cada uno de los organismos. Por ejemplo, en NIC.ES, el organismo que regula los dominios “.es”, quedan prohibido según su documentación el [dominio.es]. Hay otros tantos, pero este parece ser el único que el organismo no usará (ya que aunque está prohibido, el [dominio.es] sí que lo utilizan como promoción, saltándose sus propias reglas (como decenas de veces han hecho en e pasado).

En otros casos, como por ejemplo el dominio francés .FR (y todos los que gestiona el organismo) no plantea un dominio de segundo nivel reservado para este uso. Sí que es cierto que disponen de varios dominios reservados, pero concretamente para hacerse eco de un ejemplo de uso no.

Así que a partir de ahora, si vas a escribir una entrada hablando de dominios de ejemplo, o tienes que referirte a ellos, ya sabes que has de analizar de forma diferente lo general de los dominios territoriales.

Recomendaciones de Google cuando se va a programar en HTML

Google genera mucho contenido de código abierto, y entre este se encuentra muchísmo código de programación. Pues existen una serie de guíasen las que se recomiendan determinadas formas de trabajar que pueden ser interesantes, principalmente (al menos a mi) las que hacen referencia al HTML. Me gustaría destacar algunas de las recomendaciones… que no significa que yo las use o que esté de acuerdo, pero creo que son mencionables.

Uso del protocolo

No se recomienda indicar el uso del protocolo en cuestión cuandos e llama a un objeto. A mi me gusta ponerlo, y aunque sé que en el RFC se dice que no es necesario…

<!-- No recomendado -->
<script src="http://www.example.com/example.js"></script>
<!-- Sí recomendado -->
<script src="//www.example.com/example.js"></script>

Indentación

Algo que yo suelo hacer… que el código esté bien ordenado. Para ello las “tabulaciones” se indicarán con 2 espacios (se recomienda no usar tabulaciones, aunque yo es lo que uso).

<ul>
  <li>Fantastic</li>
  <li>Great</li>
</ul>

Mayúsculas/Minúsculas

Se recomienda que todo el HTML esté en minúculas:

<!-- No recomendado -->
<A HREF="/">Home</A>
<!-- Sí recomendado -->
<img src="example.png" alt="Google">

Espacios en blanco

Es mejor no dejar espacios en blanco si no son necesarios.

<!-- No recomendado -->
<p>¿Qué? </p>
<!-- Sí recomendado -->
<p>Gracias</p>

Codificación

Esto es muy sencillo… se recomienda el uso de UTF-8 (sin BOM). Además, en las plantillas HTML se debe indicar la meta-etiqueta correspondiente:

<meta charset="utf-8">

HTML5

Se prefiere HTML5 en los documentos, con su cabecera correspondiente:

<!DOCTYPE html>

Esto también incluye el uso del MIME text/html y no de XHTML y, por ello, no hace falta cerrar las etiquetas o sea, es mejor <br> y no <br />.

Código HTML válidado

Algo de lo que siempre hay muchas discusiones… personalmente es lgo que me gusta cumplir, al menos cuando la web no tiene códigos de publicidad u otros elementos externos.

<!-- No recomendado -->
<title>Test</title>
<article>This is only a test.
<!-- Sí recomendado -->
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test</title>
<article>This is only a test.</article>

Semántica

Hay que usar el HTML según su valor inicial, esdecir, un P es un párrafo, y un A un enlace.

<!-- No recomendado -->
<div onclick="visitarRecomendados();">Recomendados</div>
<!-- Sí recomendado -->
<a href="/recomendados/">Recomendados</a>

Multimedia

Hay que proveer de contenido alternativo en el caso de uso de elementos multimedia. Por ejemplo, las imágenes deberían llevar un texto alternativo.

<!-- No recomendado -->
<img src="example.png">
<!-- Sí recomendado -->
<img src="example.png" alt="Contenido de ejemplo.">

Inter dependencia

Hay que intentar mantener diferenciado y desvinculado el código de la página, de la estructura (markup) de la presentación (styling) del comportamiento con los mismos (scripting).

Evitar entidades

Gracias al UTF-8, es casi innecesario el uso de entidades HTML (por ejemplo el &eur para representar ). Sólo hay dos excepciones habituales que son el & y el < o >.

<!-- No recomendado -->
El símbolos del Euro es: &ldquo;&eur;&rdquo;.
<!-- Sí recomendado -->
El símbolos del Euro es: “€”.

Etiquetas opcionales

Este es otro de esos puntos en los que no estoy 100% de acuerdo. Si bien es cierto qu una de las grandísimas ventajas del HTML5 es que no es necesario escribir todo el código estructurado como hasta ahora, no tengo muy claro que sea interesante de cara a la compatibilidad con todo.

<!-- No recomendado -->
<!DOCTYPE html>
<html>
  <head>
    <title>gastando bytes</title>
  </head>
  <body>
    <p>Mal.</p>
  </body>
</html>
<!-- Sí recomendado -->
<!DOCTYPE html>
<title>ahorrando bytes</title>
<p>Bien.

Atributo “type”

En cambio, esta sí que la considero del todo útil (ya que antes me arecía completamente inútil). En principio los ficheros externos a los que llamamos (por ejemplo .CC o .JS) no es necesarios indicarles el MIME al que mandamos (al fin y al cabo, los ficheros ya lo indican per sé).

<!-- No recomendado -->
<link rel="stylesheet" href="//www.google.com/css/maia.css" type="text/css">
<!-- Sí recomendado -->
<link rel="stylesheet" href="//www.google.com/css/maia.css">
<!-- No recomendado -->
<script src="//www.google.com/js/gweb/analytics/autotrack.js" type="text/javascript"></script>
<!-- Sí recomendado -->
<script src="//www.google.com/js/gweb/analytics/autotrack.js"></script>

Formateado general

Hay que usar un salto de línea para aquellos bloques, listas o tablas e indentar cada elemento hijo. Esta es otra de las recomendaciones que agradezco, porque veo programadores que han hecho mucho daño al HTML.

<blockquote>
  <p><em>prueba</em> de un texto cualquiera.</p>
</blockquote>
<ul>
  <li>José
  <li>María
  <li>Juan
</ul>
<table>
  <thead>
    <tr>
      <th scope="col">Ingresos
      <th scope="col">Gastos
  <tbody>
    <tr>
      <td>5,00 €
      <td>4,50 €
</table>

Uso de comillas

Se recomienda el uso de comillas dobles en vez de comilla simple para los atributos.

<!-- No recomendado -->
<a class='boton boton-alternativo'>Acceder</a>
<!-- Sí recomendado -->
<a class="boton boton-alternativo">Acceder</a>

También hay una serie de recomendaciones para las hojas de estilo CSS. A parte de que el CSS debería validar (algo lógico). Además, se recomeinda que el nombre de las clases sea corto y genérico. Por ejemplo, es más recomendable usar #nav que #navegacion o usar .aux que no .boton-verde.

Selectores

Además, por un tema de rendimiento (muy importante de cara al WPO) hay que intentar ir al elemento más concreto que incliur los generales. Yo principalmente lo veo claro con los ID, pero no siempre con las clases.

/* No recomendado */
ul#ejemplo {...}
div.error {...}
/* Sí recomendado */
#ejemplo {...}
.error {...}

Propiedades cortas

Algunos elementos permiten propiedades agregadas…

/* No recomendado */
border-top-style: none;
font-family: palatino, georgia, serif;
font-size: 100%;
line-height: 1.6;
padding-bottom: 2em;
padding-left: 1em;
padding-right: 1em;
padding-top: 0;
/* Sí recomendado */
border-top: 0;
font: 100%/1.6 palatino, georgia, serif;
padding: 0 1em 2em;

Valores 0

Los datos que son de valor 0 no requieren de unidades para acompañarlo. De la misma forma, si un vaor va entre -1 y 1, no es necesario indicar el 0.

margin: 0;
padding: 0;
font-size: .8em;

Hexadecimal

Hay que intentar usar los colores cuanto más cortos mejor. De esta forma, si hay colores que se pueden reducir a 3 caracteres, mejor.

/* No recomendado */
color: #eebbcc;
/* Sí recomendado */
color: #ebc;

Ordenar los elementos

Se recomienda ordenar los elementos de forma alfabética. Claro está dentro de cada elemento.

background: fuchsia;
border: 1px solid;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
color: black;
text-align: center;
text-indent: 2em;

Finalizar las declaraciones

Al final de cada uno de los elementos se recomienda finalizar con un punto y coma.

/* No recomendado */
.test {
  display: block;
  height: 100px
}
/* Sí recomendado */
.test {
  display: block;
  height: 100px;
}

Separar propiedades y valores

Siempre utilizar un espacio entre las distintas propiedades y sus valores, pero no entre el valor y el punto y coma final.

/* No recomendado */
h3 {
  font-weight:bold;
}
/* Sí recomendado */
h3 {
  font-weight: bold;
}

Selectores y declaraciones

Siempre separar cada selector en una línea distinta de otro selector. Además separara con un salto de línea cada regla.

/* No recomendado */
a:focus, a:active {
  position: relative; top: 1px;
}
/* Sí recomendado */
h1,
h2,
h3 {
  font-weight: normal;
  line-height: 1.2;
}
html {
  background: #fff;
}

body {
  margin: auto;
  width: 50%;
}

Comillas

A diferencia del HTML, en los CSS es mejor evitar las comillas, y en caso necesario (como en los nombres de tipos de letra) usar la comilla simple .

/* No recomendado */
@import url("//www.example.com/css/estilo.css");

html {
  font-family: "open sans", arial, sans-serif;
}
/* Sí recomendado */
@import url(//www.example.com/css/estilo.css);

html {
  font-family: 'open sans', arial, sans-serif;
}

En fin, son simples sugerencias de reglas, unas más aceptables que otras… pero las que Google utiliza internamente cuando tiene que liberar código al mundo mundial. Así que, si quieres ser un buen googler ya sabes lo que te toca hacer.

NoIndex del robots.txt

¿Te has preguntado si tu fichero robots.txt aparece en Google? La respuesta es que, en principio, sí, puede aparecer. Puedes hacer una prueba con una consulta similar a esta [inurl:”robots.txt”].

Es curioso que un fichero que en principio sólo deberían leer los propios rastreadores aparezca en los resultados de búsqueda y que, por norma general nadie se preocupe de evitar que se indexe… pero ¿es posible no indexar este fichero? La respuesta es simple: sí.

Para eliminar de los resultados de búsqueda este fichero robots.txttenemos dos opciones:

  • Eliminarlo desde el propio robots.txt, es decir, añadir una línea Disallow: /robots.txt.
  • Eliminarlo desde una cabecera HTTP, como X-Robots-Tag: noindex.

Personalmente recomiendo el uso de la segunda opción, ya que el hecho de aplicar un “noindex” implica que sí pueda ser leído pero no mostrado, y la primera, en algún otro buscador, podría ser que no se permitiera su lectura en una siguiente actualización.

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?