La Ley de cookies

Consultando las cookies

La llamada Ley de cookies en España está vigente desde la aparición del Real Decreto-ley 13/2012, de 30 de marzo. La Agencia Española de Protección de Datos ha publicado una Guía sobre el uso de cookies con aspectos prácticos para la implementación. Se regula que una web podrá almacenar y recuperar datos del dispositivo del usuario siempre que éstos hayan dado su consentimiento y después de que se les haya facilitado información clara y completa sobre su utilización. Por lo tanto impone un deber de información y consentimiento para poder usar cookies y en general cualquier forma de almacenamiento de datos en el dispositivo del usuario.

En estos días he actualizado la página de aviso legal en este sitio, especialmente para actualizar lo referente a la política de cookies. En esa página encontrará la información básica que un usuario medio de este sitio debe requerir para saber cómo gestiono las cookies. Y además también encontrará información adicional sobre otros aspectos relacionados con la materia. Por lo tanto el presente tema sólo me interesa enfocarlo desde la perspectiva de la implementación de esa normativa, resumiendo a continuación un par de cosas que son básicas para entender esa implementación. Si no conoce la Ley de cookies es recomendable leer aquella página antes de seguir con este tema.

No se debe olvidar que aunque digamos cookies la legislación se refiere a dispositivos de almacenamiento y recuperación de datos en equipos terminales de los destinatarios. Por lo tanto podrían ser cookies o cualquier otra forma de almacenamiento en el dispositivo del usuario. La normativa clasifica las cookies según su finalidad. De una forma muy genérica podemos agruparlas así:

  1. Técnicas y de personalización:

    Cookies con alguna de las siguientes finalidades:

    • Permitir únicamente la comunicación entre el equipo del usuario y la red.
    • Estrictamente prestar un servicio expresamente solicitado por el usuario.

    Son cookies que sirven para facilitar la comunicación servidor-cliente y también para gestionar procesos y tareas en el cliente y que generalmente están exceptuadas del cumplimiento de la Ley de cookies. Por ejemplo, indentificar sesiones, guardar configuración regional, almacenar elementos que integran un pedido, compartir contenidos a través de redes sociales, guardar parámetros de configuración de la interfaz de usuario, etc.

  2. De análisis y publicitarias:

    Cookies para hacer un seguimiento del comportamiento del usuario en el sitio o controlar y gestionar espacios publicitarios. Estas cookies están en el ámbito de aplicación de la ley.

Veáse que en el primer grupo, cuando se trata de facilitar la comunicación o el servicio es solicitado por el usuario, las cookies generadas están exceptuadas de cumplimiento. Incluso aunque los datos sean personales, como rellenar un formulario con sus datos y enviarlo al servidor para cualquier proceso. En cambio no es claramente un servicio solicitado por el usuario llevar a cabo análisis de su comportamiento en el sitio o insertarle publicidad según sus hábitos de navegación.

La excepción de la Ley de cookies no quita que en su caso haya que aplicar el tratamiento de la protección de datos personales, especialmente con los datos especialmente protegidos reglamentados en la LOPD, Ley Orgánica 15/1999, de 13 de diciembre, de Protección de Datos de Carácter Personal.

En este sitio y hasta este momento sólo he venido aplicando cookies del primer grupo anterior. Por lo tanto no es obligatorio que implemente nada al respecto. Pero con el deseo de aprender he llevado a cabo esta implementación y, de paso, por si en un futuro agrego cookies del segundo grupo, como Google Analytics y publicidad.

En noviembre 2015 he agregado publicidad a este sitio. Por lo tanto ahora sí es necesario aplicar la Ley de Cookies.

Información y consentimiento para uso de cookies

Información y consentimiento son las palabras claves. La información podemos incluirla en una página tipo "aviso-legal" que incluya una política de cookies. La guía de la Agencia de Protección de Datos explica con detalle como hacerlo.

Pero el consentimiento, que debe ser previo al almacenamiento de una cookie del segundo grupo, es ya algo más complejo de llevar a cabo. El problema es que si las cookies no exceptuadas provienen de terceras partes, como de la publicidad o script de análisis (como Google Analytics), estos insertarán cookies nada más activarse y tras la carga de la página. Habría que detener la carga de estos componentes hasta que el usuario nos diera su consentimiento. Pero no estoy muy seguro de los problemas técnicos que esto supone. Decimos en la frase de aviso antes de ese consentimiento:

Utilizamos cookies propias y de terceros para mejorar nuestro servicio. Si continua navegando consideramos que acepta su uso. Ver más información (seguir este vínculo no supone aceptación).

Entendemos por navegar cuando el usuario hace click en cualquier parte de la página usando un vínculo o pulsando un botón, o usa el scroll para acceder a contenidos inferiores y, en definitiva, cualquier acción que suponga una interacción con la página. En ese momento se ejecutarán eventos onclick sobre <body> y onscroll sobre window llevándose a cabo el proceso de consentimiento.

Pero para cumplir con el propósito de información previo se ofrece un vínculo a la página de aviso legal que contiene más información sobre cookies. Seguir ese vínculo no dispara los eventos de aceptación. Y navegar en esa página de aviso legal tampoco lo hace. En resumen, el usuario puede informarse primero y luego puede elegir entre:

  • Abandonar el sitio y no habrán cookies instaladas.
  • Seguir navegando a otras páginas y se instalarán las cookies.
  • Bloquear cookies para todo el dominio y seguir navegando en el sitio. Le saldrá un mensaje de aviso de cookies bloqueadas y que ciertas funcionalidades no estarán disponibles.

Creo que lo anterior está en sintonía con lo que expone la Guía de la Agencia de Protección de Datos señalada más arriba. Y también lo que he podido ver que están haciendo en la mayor parte de sitios. Aunque no del todo. Porque la primera vez que entramos en muchos sitios y antes del consentimiento ya se han instalado cookies no exceptuadas. Vea la siguiente captura de un sitio de una empresa líder en su sector en España (cuyo nombre oculto pues tampoco viene al caso):

Aviso cookies de otros sitios web

Aparece el mensaje de aviso de cookies y, sin tocar ninguna parte de la página, he abierto las cookies de ese sitio, pues se encuentran en el icono de documento de la barra de direcciones del navegador Chrome. Observará que he recuadrado una de ellas. Si ahora vamos a la página de información encontraremos para que sirve esa cookie:

Información cookies de otros sitios web

Tiene en esa página de información una tabla relacionando todas las cookies que utiliza. He recortado algunas filas para no agrandar la imagen y posicionar la fila que contiene la cookie que busco. Resulta que no está excluida del deber de información y consentimiento. Pero el sitio ya la había instalado antes de empezar a navegar.

Implementación de la Ley de cookies

La implementación del aviso de cookies de entrada quedará en este sitio como esta captura de pantalla en un dispositivo de poco ancho:

Aviso cookies

Hemos de insertar ese bloque de texto con JavaScript después de que la página se haya cargado. En todas las páginas del sitio uso el window.onload para realizar una serie de tareas posteriores a la carga ejecutando la función wxG.adjudicarEventosGenerales(). Lo siguiente es un resumen de ubicación de ese código de post-carga (en el enlace que está por debajo puede encontrar el código completo):

//En un SCRIPT a pie de página

window.onload = function(){
    wxG = Wextensible.general;
    wxG.adjudicarEventosGenerales();
    ...
};

//En el archivo general.js con funciones comunes para
//todas las páginas
...
adjudicarEventosGenerales: function(omitirCssAfter,
                                    omitirComprobarCache,
                                    omitirAvisoCookies) {
    window.setTimeout(function(){
        wxG.adjudicarEventos([
            ...
        ]);
        ...
        //Carga de Css After
        if (!omitirCssAfter) {
            ...
            wxG.cargarCssAfter();
            ...
        }
        //Agrega un botón en la cabecera para agrandar ancho del html
        wxG.agregarBotonAgrandarAncho();
        ...
        //Agrega avisador ley cookies
        if (!omitirAvisoCookies) wxG.insertarAvisoCookies();
        //Comprueba si la página en caché ha sido modificada
        if (!omitirComprobarCache) wxG.comprobarCache();
    }, 1);
},
...

Ver código completo

El archivo general.js contiene todas las funciones de uso genérico para el sitio. Dentro de la función de post-carga he incluido una llamada a wxG.insertarAvisoCookies() (resaltado en amarillo en el código de la post-carga) que realizará lo siguiente:

  1. Hará una comprobación para ver si el navegador está aceptando cookies. Con document.cookie = "testck=; path=/;" intentamos guardar una cookie de prueba y luego comprobamos que ha sido almacenada con lo que sabremos si las cookies están activadas.
  2. Si las cookies no están activadas presentaremos un mensaje de que el usuario ha desactivado las cookies y que no será posible ofrecerle ciertas funcionalidades del sitio.
  3. En cambio si están activadas tenemos que comprobar si existe una cookie denominada acepta-cookies que contiene la fecha y hora de la aceptación. En el caso de que exista esa cookie es que habremos obtenido consentimiento previo y comprobaremos que la página que contiene la información de cookies no haya variado. Es decir, si modificamos la política de cookies tendremos que cancelar el consentimiento anterior y volver a solicitarlo. Si es así eliminamos la cookie de aceptación y pasaremos a ejecutar el siguiente punto. Más abajo explico como llevo a cabo esta comprobación de fechas.
  4. Si no existe la cookie acepta-cookies es porque no ha habido un consentimiento previo o bien la eliminamos en el paso anterior por cambio de política, en cuyo caso procedemos a insertar el aviso de cookies. Adjudicamos eventos onclick al <body> y onscroll al objeto window para que el usuario acepte las cookies cuando empiece a interaccionar con la página. La función que ejecuta la aceptación es wxG.aceptarCookies(). Se ejecuta para todo el <body> a excepción del vínculo que lleva a la página de información de cookies. Almacenamos la cookie acepta-cookies con la fecha del momento y fecha de caducidad un año más tarde. Finalizamos quitando las adjudicaciones de eventos onclick y onscroll pues ya no harán falta.

Es importante cancelar el consentimiento obtenido previamente cuando agreguemos nuevas cookies no exceptuadas en nuestro sitio. Si es así estamos obligados también a modificar la página de información con la política de cookies, pues ahí deben relacionarse todas las cookies que usamos y su finalidad. Una forma de llevar a cabo esto es darle una corta duración de vida a la cookie de aceptación (acepta-cookies). Por ejemplo, una semana, pues no es probable que modifiquemos la política de cookies en plazos inferiores. Así nos aseguramos de que semanalmente le aparecerá al usuario el aviso de aceptación.

Pero creo que es mejor realizar una verdadera comprobación de la versión de la página que contiene la politica de cookies. Por un lado en todas las páginas del sitio inyecto con PHP un <script> en el <head> como el siguiente:

<script>
    var wxZ = {
        a:"16-09-2014-20-02-03",
        f:"23-09-2014-21-33-04"
    };
</script>

Este objeto wxZ contiene dos fechas. Una (variable f) es la fecha y hora de última modificación del documento y nos sirve para realizar un control de versiones con revalidación desde caché. La otra fecha (variable a) es la de última modificación de la página de aviso legal que contiene la información de cookies. Estas fechas se inyectan en el servidor antes de servir la página mediante el script PHP prehjc.php.

Ahora sólo nos queda comprobar si la fecha de aceptación que tenemos almacenada en la cookie acepta-cookies es mayor que la fecha de última modificación wxZ.a de la página de información. En otro caso es que habremos modificado dicha página después de la aceptación y por tanto hay que volver a pedir el consentimiento.

Como información adicional, este apartado trata de cómo obtener con JavaScript el valor de una determinada cookie. La expresión var st = document.cookie nos devuelve una cadena de cookies (parejas nombre=valor) separadas por punto y coma. Podemos usar split para dividir esa cadena por ";" y meterla en un array. Luego iteramos por ese array y recuperamos su valor. Puede ver un ejemplo en Sesiones y cookies.

Pero ahora he decidido usar lo que expone la documentación de Mozilla Document.cookie, que es más simple que la solución del array. El código expuesto más arriba que recupera el valor de la cookie con nombre acepta-cookies es el siguiente:

var cook = document.cookie.replace(/(?:(?:^|.*;\s*)acepta\-cookies\s*\=\s*([^;]*).*$)|^.*$/, "$1");

Document.cookie es un accesor de propiedades. Cuando hacemos document.cookie = "abc=efg; path=/;..." lo que hace JavaScript es convertir el string en un única cookie, cuyo nombre-valor es el primero de los campos separados por ";" y los siguientes opcionales son otros parámetros de la cookie (dominio, caducidad, etc). Cuando hacemos var st = document.cookie lo que hace es recuperar en st la totalidad de las cookies, pero sólo parejas nombre-valor separadas por ";". Pero realmente no estamos accediendo al verdadero objeto que almacena las cookies. Como lo que recuperamos es un string, al hacer document.cookie.replace no estamos actuando sobre el almacén de cookies, sino sobre el string recuperado. Además replace no modifica el string sobre el que se aplica sino sobre la devolución (la variable cook en el código anterior).

En el patrón vemos que reemplazamos la cadena de cookies por el valor recuperado de la cookie denominada acepta-cookies. Esto lo hace el único grupo de captura ([^;]*) que hay en el patrón. Pero la parte final del patrón es la que no entiendo, la alternativa |^.*$ coincide con toda la cadena, pero no será reemplazada porque no tiene grupo de captura $1. Si elimino esta parte aparentemente funciona correctamente. No creo que sea un error del documento de Mozilla, pero no he podido entenderlo y no he encontrado más información al respecto.