¿Se puede cumplir con el RGPD? – Parte 1: Cookies

Se puede cumplir con el RGPD en materia de cookies de forma estricta

Paso 4: Condicionando el contenido que genera las cookies

Ahora viene la parte mas divertida. El plugin como tal no puede bloquear mas cookies que la que él mismo genera, sin embargo te provee de las herramientas para que tu lo hagas y para que tu web se comporte de acuerdo a la opción elegida por el usuario.

No hay una forma única de supeditar la generación de una cookie a la elección del usuario. En cada caso habrá que buscar una solución específica.

A continuación te presento cómo lo hace mi web. Los casos recogidos no son todas las opciones posibles, pero si son casos bastante habituales y te darán una buena idea de los recursos disponibles.

Cómo bloquear las cookies de Google Analytics

El plugin está especialmente desarrollado para solucionar casos como este, así que la forma de hacerlo es bastante sencilla.

Simplemente lleva el scpript de analytics a la pestaña de Cookies de terceros del plugin e insértalo en una de las tres secciones (head en mi caso). Y evidentemente, elimínalo de donde lo tengas ahora.

El script para Google Analytics configurado para que esté condicionado a que el usuario acepte las cookies de terceros
El script para Google Analytics configurado para que esté condicionado a que el usuario acepte las cookies de terceros.

Si en tu web este script lo genera un plugin, debes desactivar el plugin. Y si no tienes idea de cómo generar el script de analytics sin el plugin, te recomiendo que leas ahora el artículo Lo Esencial de Google Analytics.

Cómo bloquear las cookies de los comentarios de WordPress

Estas cookies están dentro de la categoría de cookies adicionales (en mi caso en particular). WordPress permite definir programáticamente si se generan o no estas cookies, así que para condicionarlo a la acción que haya elegido el usuario tendremos que meter algo de código en nuestra web.

Este tipo de código se incluye en el módulo functions.php de tu tema o en tu plugin privado.

// Disable comments cookies if not accepted by user.
if ( function_exists( 'gdpr_cookie_is_accepted' ) ) {
  if ( !gdpr_cookie_is_accepted( 'advanced' ) ) {
    remove_action( 'set_comment_cookies', 'wp_set_comment_cookies' );
  }
}  

Hay otra opción que consiste directamente en deshabilitar los comentarios de la entrada si no se han aceptado las cookies correspondientes. A mi personalmente me parece innecesario llegar a esos extremos, dado que las cookies no son mas que una ayuda al usuario para evitarle volver a tener que introducir sus datos en el siguiente comentario. No obstante tu eliges.

El código para hacerlo está extraído de los ejemplos que nos da el plugin en la pestaña de Ayuda, ganchos, filtros y shortcodes (si lo usase en mi web debería cambiar 'thirdparty' por 'advanced'):

// Force reload required because of PHP functions
add_action( 'gdpr_force_reload', '__return_true' );
// Custom Scripts based on front-end language
add_action('comments_open', function( $comments_open ){
  if ( function_exists( 'gdpr_cookie_is_accepted' ) ) :
    // supported types: 'strict', 'thirdparty', 'advanced' 
    if ( gdpr_cookie_is_accepted( 'thirdparty' ) ) :
      return $comments_open;
    else :
      return false;
    endif;
  endif;
  return $comments_open;
});

Cómo bloquear scripts generados por nuestros plugins

Es el caso del servicio reCAPTCHA que viene generado por el plugin Contact Form 7.

Te propongo una solución que no implica tocar el código del plugin (y que por tanto es mantenible a largo plazo). Incluye este fragmento de código en el módulo functions.php de tu tema o en tu plugin privado:

function my_theme_recaptcha_dequeue_script() {
  if ( function_exists( 'gdpr_cookie_is_accepted' ) ) {
    /* supported types: 'strict', 'thirdparty', 'advanced' */
    if ( !gdpr_cookie_is_accepted( 'thirdparty' ) ) {
  	  wp_dequeue_script( 'google-recaptcha' );
    } 
  }
}
add_action( 'wp_print_scripts', 'my_theme_recaptcha_dequeue_script', 100 );

Este código lo que hace es desencolar el script google-recaptcha (encolado por /wp-content/plugins/contact-form-7/modules/recaptcha.php) en caso de que el usuario no haya aceptado las cookies de terceros.

La últimas sentencia permite asegurarse que nuestro código se ejecutará cuando ya todos los scripts hayan sido puestos en la cola.

Cómo bloquear las cookies de los videos de YouTube embebidos

Afortunadamente hay una forma de incrustar un video de Youtube sin que se generen cookies. Si en la URL de tu video en vez de www.youtube.com usas www.youtube-nocookie.com, el video incrustado no generará cookies.

¿Fácil verdad?

Una posible solución es que escrapees tu web buscando las URLS de los vídeos de YouTube y que las modifiques a la versión sin cookies, pero esto presenta varios problemas:

  • Significa un esfuerzo considerable. Especialmente si tu web es grande.
  • No todos los usuarios rechazarán el uso de cookies, por lo que en muchos casos estarías poniendo la tirita antes de la herida.
  • A la larga acabarás incluyendo una URL sin modificar y esa publicación no será capaz de filtrar las cookies en caso necesario.

Lo que hago en mi web es usar las posibilidades de filtrado de WordPress para actuar selectivamente sobre los contenidos embebidos.

function my_youtube_no_cookies_replacement( $html ) {
  $html = str_replace('www.youtube.com/', 'www.youtube-nocookie.com/', $html);
  $html = str_replace('youtube.com/', 'www.youtube-nocookie.com/', $html);
  $html = str_replace('youtu.be/', 'www.youtube-nocookie.com/', $html);
  
  return $html;
}

function my_theme_embed_handler_oembed_youtube($html, $url, $attr, $post_ID) {
  if ( strpos($url, 'youtube.com') !== false || strpos($url, 'youtu.be') !== false ) {
    if ( function_exists( 'gdpr_cookie_is_accepted' ) ) {
	  if ( !gdpr_cookie_is_accepted( 'thirdparty' ) ) {
        $html = my_youtube_no_cookies_replacement( $html );
	  }
	}
  }
  return $html;
}
add_filter('embed_oembed_html', 'my_theme_embed_handler_oembed_youtube', 10, 4);

Este filtro actúa sobre el HTML generado para contenidos incrustados (tu pones una URL en tu entrada y WordPress genera el código gracias a oEmbed).

Detecta si la URL embebida es un video de YouTube, y en caso afirmativo mira tu elección sobre cookies. Si no admites cookies de terceros transforma el código generado para que las URLS hagan referencia a la versión sin cookies de YouTube (esto lo hace la funcion my_youtube_no_cookies_replacement()).

Cómo bloquear las cookies con videos de YouTube vía shortcode

Lo anterior funciona para el contenido embebido, pero desafortunadamente hay mas opciones para generar contenido incrustado de vídeos. Una opción muy común son los shortcodes.

La solución que implemento sirve para cualquier shortcode (ajustando el nombre), pero en mi caso lo hago para los shortcodes de vídeo del plugin Shortcodes Ultimate, un popular complemento de los tiempos en los que no teníamos Gutemberg.

function my_theme_su_youtube_shortcodes($output, $tag, $attr) {
  if ( $tag === 'su_youtube' || $tag === 'su_youtube_advanced' ) {
    if ( function_exists( 'gdpr_cookie_is_accepted' ) ) {
	  if ( !gdpr_cookie_is_accepted( 'thirdparty' ) ) {
        $output = my_youtube_no_cookies_replacement( $output );
	  }
	}
  }
  return $output;
}
add_filter('do_shortcode_tag', 'my_theme_su_youtube_shortcodes', 10, 3);

La línea 103 indica sobre qué shortcodes se aplica este filtro. Por lo demás se usa la misma función que antes para modificar las URLS solo en el caso de que el usuario no acepte cookies de terceros.

Cómo bloquear las cookies de los iframe

Los videos son quizá el tipo de contenido embebido mas usado, pero no es el único. En mi caso también incrusto en una publicación una lista de reproducción de Soptify.

Spotify no tiene una versión sin cookies, así que ¿qué hacemos si el usuario no admite cookies de terceros? No queda otra opción que bloquear el contenido y mostrar un aviso en su lugar.

Las webs usan cookies de terceros, especialmente a través de las redes sociales
Las webs usan cookies de terceros, especialmente a través de las redes sociales.

El siguiente fragmento de código se encarga de bloquear cualquier iframe (la forma de incrustar contenido de otra web) si el usuario no ha aceptado las cookies de terceros. Los iframes de videos de Youtube no se bloquean, dado que disponemos de la opción de la URL sin cookies:

function filter_the_content_in_the_main_loop( $content ) {
  // Check if we're inside the main loop in a single post page.
  if ( is_single() && in_the_loop() && is_main_query() ) {
    if ( function_exists( 'gdpr_cookie_is_accepted' ) ) {
	  if ( !gdpr_cookie_is_accepted( 'thirdparty' ) ) {
		  $pattern = '/<iframe.*src=\"(?!https:\/\/www\.youtube\-nocookie\.com).*\".*><\/iframe>/isU';
		  $replacement = '<div style="border:2px solid black;margin:20px;padding:20px;text-align:center;">
		                  <p><strong><i class="fas fa-hand-paper"></i> Contenido de terceros bloqueado <i class="fas fa-hand-paper"></i></strong></p>
		                  <p><em>El contenido original no puede ser mostrado debido a que eligió no aceptar cookies de terceros.</em></p>
						  <p><a href="/#gdpr_cookie_modal">Revisar mi elección.</a></p>
						  </div>';
		  $content = preg_replace($pattern, $replacement, $content);
	  }
	}
  }
   
  return $content;
}
add_filter( 'the_content', 'filter_the_content_in_the_main_loop', 100, 1 );

La bonita expresión regular de la línea 119

/<iframe.*src=\"(?!https:\/\/www\.youtube\-nocookie\.com).*\".*><\/iframe>/isU

se encarga de localizar cada uno de los bloques <iframe ...</iframe> de tu entrada que no hagan referencia a https://www.youtube-nocookie.com (los filtros anteriores ya habría actuado) y los sustituye por este mensaje:

Contenido de terceros bloqueado

El contenido original no puede ser mostrado debido a que eligió no aceptar cookies de terceros.

Revisar mi elección.

La transformación se hace únicamente en el caso de que el usuario no haya aceptado las cookies de terceros.

Consulta la ayuda del plugin GDPR Cookie Compliance para aprender sobre recursos disponibles para bloquear cookies de otras fuentes
Consulta la ayuda del plugin GDPR Cookie Compliance para aprender sobre recursos disponibles para bloquear cookies de otras fuentes.

Siendo estrictamente estrictos

Tengo malas noticias: A pesar de que hemos usado la URL nocookie de YouTube para evitar que nos envíe sus cookies cuando éstas no son aceptadas –y realmente no se nos envían cookies– siendo estrictamente estrictos deberíamos bloquear los vídeos de YouTube puesto que aunque no sea en forma de cookies siguen dejando trazas en tu ordenador. Trazas que por su uso son idénticas a las cookies aunque no se llamen así.

Las cookies son un recursos usados desde siempre para que una aplicación web pueda almacenar información en el ordenador del cliente. Presentan dos problemas:

  • que deben ser enviadas en cada petición
  • que tienen un tamaño máximo de 4KB

Para evitar estos problemas, desde hace tiempo existe la posibilidad de almacenar información en dos contenedores mas:

  • window.localStorage
  • window.sessionStorage

Sin entrar en grandes detalles su principal diferencia es la persistencia, siendo localStorage el que ofrece almacenamiento a mas largo plazo.

www.youtube-nocookie.com hace uso de estos almacenamientos para enviar identificadores únicos de usuario y por tanto pueden trazar tu visita de la misma forma que si estuviesen usando cookies.

La versión nocookie de YouTube en realidad te traza exactamente igual que la versión estándar
La versión nocookie de YouTube en realidad te traza exactamente igual que la versión estándar.

Por tanto siendo estrictamente estrictos no deberíamos mostrar videos de YouTube si el usuario ha optado por no aceptar cookies de terceros.

Desde el punto de vista de los cambios en el código se reduce a modificar la expresión regular de la línea 119 por esta:

/<iframe.*>.*<\/iframe>/isU

con la finalidad de que todos los iframe sean bloqueados.

Si optamos por este tratamiento, tampoco sería necesario incluir los filtros que convierten las URLS de YouTube en la versión sin cookies, dado que en cualquier caso serán bloqueados.