Cuando su código tiene que funcionar: cumplir con los mandatos legales

 

 

 

  • SmashingConf UX y diseño, Amberes 2024
  • ¡Registro!

  • Índice
    1. Planificándolo
    2. Implementación del lado del servidor
    3. Implementación frontal
    4. Agregar algo de chispa visual
      1. Otras lecturas

    Si nuestros sitios web no permiten a los usuarios realizar las tareas clave que deben realizar, les hemos fallado. Deberíamos hacer todo lo que esté a nuestro alcance para garantizar que nuestros sitios web funcionen incluso en los escenarios más difíciles, pero al mismo tiempo, no podemos esperar que nuestros usuarios tengan exactamente la misma experiencia en todos los navegadores y en todos los dispositivos. Debido a que ninguna de las soluciones que encontró Aaron Gustafson cumplía con la ley ni en espíritu ni en realidad, optó por implementar su propia solución sólida.

     

    Douglas Crockford declaró que los navegadores son “el entorno de ingeniería de software más hostil que se pueda imaginar”, y eso no fue una hipérbole. Garantizar que nuestros sitios web funcionen en una gran variedad de dispositivos, tamaños de pantalla y navegadores diferentes de los que dependen nuestros usuarios para acceder a la web es una tarea difícil, pero es necesaria.

    Si nuestros sitios web no permiten a los usuarios realizar las tareas clave que deben realizar, les hemos fallado. Deberíamos hacer todo lo que esté a nuestro alcance para garantizar que nuestros sitios web funcionen incluso en los escenarios más difíciles, pero al mismo tiempo, no podemos esperar que nuestros usuarios tengan exactamente la misma experiencia en todos los navegadores y en todos los dispositivos. Yahoo se dio cuenta de esto hace más de una década y lo convirtió en un concepto central en su estrategia de “ Soporte graduado para navegadores ”:

    "El soporte no significa que todos obtengan lo mismo. Esperar que dos usuarios que utilizan software de navegador diferente tengan una experiencia idéntica no acepta ni reconoce la esencia heterogénea de la Web. De hecho, exigir la misma experiencia para todos los usuarios crea una barrera artificial. a la participación. La disponibilidad y accesibilidad del contenido debe ser nuestra principal prioridad".

    ¡Y eso fue unos años antes de que se presentara el iPhone!

     

    Proporcionar vías de experiencia alternativas para nuestra funcionalidad principal debería ser una obviedad, pero cuando se trata de implementar cosas en las que preferiríamos no pensar, a menudo buscamos la solución más simple, a pesar del impacto negativo potencial que podría tener en Nuestro negocio.

    Consideremos la “ley de cookies” de la UE. Si no está familiarizado, esta ley algo polémica es una legislación de privacidad que requiere que los sitios web obtengan el consentimiento de los visitantes antes de almacenar o recuperar información de su dispositivo. La llamamos ley de cookies, pero la legislación también se aplica al almacenamiento web , IndexedDB y otras API de recuperación y almacenamiento de datos del lado del cliente.

    El cumplimiento de esta ley se logra mediante:

    1. Notificar a los usuarios que el sitio web requiere la capacidad de almacenar y leer información en su dispositivo;
    2. Proporcionar un enlace a la declaración de privacidad del sitio web, que incluye información sobre los mecanismos de almacenamiento que se utilizan y para qué se utilizan;
    3. Solicitar a los usuarios que confirmen su aceptación de este requisito.

    Si opera un sitio web dirigido a personas que viven en la UE y no lo hace, podría estar sujeto a una multa sustancial. Incluso podría exponerse a una demanda.

    Si ha tenido que lidiar con la ley de cookies de la UE antes, probablemente esté muy consciente de que hay un montón de "soluciones" disponibles para garantizar el cumplimiento. Esas comillas son totalmente intencionales porque casi todas las que encontré, incluida la proporcionada por la propia UE, han sido un archivo JavaScript directo que permite el cumplimiento. Sin embargo, si hablamos de la letra de la ley, en realidad no es así. El problema es que, por más impresionantes y completas que sean algunas de estas soluciones, nunca podemos garantizar que nuestros programas JavaScript realmente se ejecuten . Para cumplir verdaderamente con la ley al pie de la letra, debemos proporcionar una versión alternativa de la utilidad, por si acaso. La mayoría de la gente nunca lo verá, pero al menos sabemos que estamos cubiertos si algo sale mal.

    Me encontré con este pantano mientras creaba el sitio web del concurso 10k Apart . No usábamos mucho cookies en el sitio web, principalmente análisis y seguimiento de votos, pero usábamos la API de almacenamiento web para acelerar el rendimiento del sitio web y guardar los datos del formulario temporalmente mientras la gente completaba el formulario. Como el concurso estaba abierto a personas que viven en la UE, teníamos que cumplir con la ley de cookies. Y porque ninguna de las soluciones que encontré cumplía con la ley ni en espíritu ni en realidad; la notable excepción fue el complemento de la Ley de Cookies de la UE de WordPress , que funciona con y sin JavaScript, pero el sitio web del concurso no se creó en WordPress ni siquiera PHP, así que tuve que hacer algo más: opté por implementar mi propia solución sólida.

    Planificándolo

    Soy un gran admirador del uso de mapas de experiencia de interfaz (IX) para diagramar la funcionalidad. Encuentro que su naturaleza simple es fácil de entender y modificar a medida que aumento la fidelidad de una experiencia. Para esta función, comencé con un mapa IX (relativamente) simple que diagramaba lo que sucedería cuando un usuario solicita una página en el sitio web.

     

    Este mapa IX describe varias experiencias potenciales que varían según la elección del usuario y la disponibilidad de funciones. Primero analizaré el escenario ideal:

    1. Un usuario llega al sitio web por primera vez. El servidor comprueba si ha aceptado el uso de cookies y almacenamiento web pero no encuentra nada.
    2. El servidor inyecta un banner en el HTML que contiene el mensaje necesario y un formulario que, cuando se envía, confirma la aceptación.
    3. El navegador muestra la página con el banner.
    4. El usuario hace clic para aceptar el uso de cookies y almacenamiento web.
    5. JavaScript del lado del cliente establece la acceptscookie y cierra el banner.
    6. En solicitudes de páginas posteriores, el servidor lee la acceptscookie y no inyecta el código del banner. JavaScript ve la cookie y habilita la cookie y el código de almacenamiento web.

    Para la gran mayoría de los usuarios, esta es la experiencia que obtendrán, y eso es fantástico. Dicho esto, sin embargo, nunca podemos estar 100% garantizados que nuestro código JavaScript del lado del cliente se ejecutará, por lo que necesitamos un plan de respaldo. Aquí está la experiencia alternativa:

    1. Un usuario llega al sitio web por primera vez. El servidor comprueba si ha aceptado el uso de cookies y almacenamiento web pero no encuentra nada.
    2. El servidor inyecta un banner en el HTML que contiene el mensaje necesario y un formulario que, cuando se envía, confirma la aceptación.
    3. El navegador muestra la página con el banner.
    4. El usuario hace clic para aceptar el uso de cookies y almacenamiento web.
    5. El clic inicia una publicación de formulario en el servidor, que responde configurando la acceptscookie antes de redirigir al usuario a la página en la que se encontraba.
    6. En solicitudes de páginas posteriores, el servidor lee la acceptscookie y no inyecta el código del banner.
    7. Si JavaScript está disponible más adelante, verá la cookie y habilitará su cookie y código de almacenamiento web.

    Nada mal. Hay un viaje de ida y vuelta adicional al servidor, pero es rápido y, lo que es más importante, proporciona un respaldo infalible en ausencia de nuestra opción preferida basada en JavaScript. Es cierto que podría ser víctima de un problema de red, pero no hay mucho que podamos hacer para mitigarlo sin JavaScript en juego.

    Hablando de mitigar problemas de red, el sitio web del concurso 10k Apart utiliza un trabajador de servicio para realizar un almacenamiento en caché bastante agresivo; el trabajador del servicio intercepta cualquier solicitud de página y proporciona una versión en caché, si existe. Esto podría dar como resultado que los usuarios obtengan una copia de la página con el banner todavía en ella, incluso si ya aceptaron permitir las cookies. Es hora de actualizar el mapa IX.

    Esta es una de las razones por las que me gustan tanto los mapas IX: son realmente fáciles de generar y fáciles de actualizar cuando deseas agregar funciones o manejar más escenarios. Con algunos ajustes implementados, puedo tener en cuenta el escenario en el que una página obsoleta incluye el banner innecesariamente y hacer que JavaScript lo elimine.

     

    Con este plan en marcha, llegó el momento de implementarlo.

    Implementación del lado del servidor

    El backend de 10k Apart está escrito en Node.js y utiliza Express . No voy a entrar en el meollo de nuestra instalación y configuración, pero sí quiero hablar sobre cómo implementé esta característica. En primer lugar, opté por utilizar el middleware analizador de cookies de Express para permitirme obtener y configurar la cookie.

    // enable cookie-parser for Expressvar cookieParser = require('cookie-parser');app.use(cookieParser());

    Una vez configurado, creé mi propio middleware Express personalizado que interceptaría las solicitudes y verificaría la approves_cookiescookie:

    var checkCookie = function(req, res, next) { res.locals.approves_cookies = ( req.cookies['approves_cookies'] === 'yes' ); res.locals.current_url = req.url || '/'; next();};

    Este código establece una función de middleware denominada checkCookie(). Todo el middleware Express obtiene acceso a la solicitud ( req), la respuesta ( res) y la siguiente función del middleware ( next), por lo que verá que se contabilizan como los tres argumentos de esa función. Luego, dentro de la función, estoy modificando el objeto de respuesta para incluir dos variables locales ( res.locals) para capturar si la cookie ya se ha configurado ( res.locals.approves_cookies) y la URL solicitada actualmente ( res.locals.current_url). Luego, llamo a la siguiente función de middleware.

    Con esto escrito, puedo incluir este middleware en Express:

    app.use(checkCookie);

    Todas las plantillas para el sitio web son archivos Moustache y Express canaliza automáticamente res.localsesas plantillas. Sabiendo eso, creé un parcial de Moustache para manejar el banner:

    {{^approves_cookies}} div role="alert" form action="/cookies-ok" method="post" input type="hidden" name="redirect_to" value="{{current_url}}" pThis site uses cookies for analytics and to track voting. If you're interested, more details can be found in a href="{{privacy_url}}#maincookiessimilartechnologiesmodule"our cookie policy/a./p button type="submit"I'm cool with that/button /form /div{{/approves_cookies}}

    Esta plantilla utiliza una sección invertida que solo representa divcuándo approves_cookieses falso. Dentro de ese marcado, también puede ver cómo current_urlse canaliza a un elemento oculto inputpara indicar dónde se debe redirigir a un usuario si se utiliza el método de formulario para configurar la cookie. Recordaste: la alternativa. Korean Beauty

    Hablando de respaldo, dado que tenemos uno, también debemos manejarlo en el lado del servidor. Aquí está el código de Node.js para eso:

    var affirmCookies = function (req, res) { if ( ! req.cookies['approves_cookies'] ) { res.cookie('approves_cookies', 'yes', { secure: true, maxAge: ( 365 * 24 * 60 * 60 ) // 1 year }); } res.redirect(req.body.redirect_to);};app.post('/cookies-ok', affirmCookies);

    Esto garantiza que si se envía el formulario, Express responderá configurando la approves_cookiescookie (si aún no está configurada) y luego redirigiendo al usuario a la página en la que se encontraba. En conjunto, esto nos brinda una experiencia básica sólida para cada usuario.

     

    Ahora bien, vale la pena señalar que nada de este código le será útil si sus proyectos no involucran la pila específica con la que estaba trabajando en este proyecto (Node.js, Express, Moustache). Dicho esto, la lógica que he descrito aquí y en el mapa IX es portátil a prácticamente cualquier lenguaje o marco que conozca y ame.

    Bien, cambiemos de marcha y hagamos algo de magia en la parte delantera.

    Implementación frontal

    Cuando JavaScript esté disponible y ejecutándose correctamente, querremos aprovecharlo al máximo, pero no tiene sentido ejecutar ningún código en el banner si no existe, así que lo primero es lo primero: debo comprobarlo para ver si el banner está parejo en la página.

    var $cookie_banner = document.getElementById('cookie-banner');if ( $cookie_banner ){ // actual code will go here}

    Para optimizar la lógica de la aplicación, agregaré otro condicional para verificar la accepts_cookiescookie. Sé por mi segundo pase en el mapa IX que existe una posibilidad remota de que mi trabajador de servicio muestre el banner incluso si la acceptscookie existe, por lo que verificar la cookie con anticipación me permite ejecutar solo el bit de JavaScript que elimina el banner. Pero antes de pasar a todo eso, crearé una función a la que puedo llamar en cualquiera de mis códigos para informarme si el usuario aceptó permitirme utilizar cookies:

    function cookiesApproved(){ return document.cookie.indexOf('approves_cookies') -1;}

    Necesito esta verificación en varios lugares de mi JavaScript, por lo que tiene sentido dividirla en una función separada. Ahora, revisemos mi lógica de manejo de banners:

    var $cookie_banner = document.getElementById('cookie-banner');if ( $cookie_banner ){ // banner exists but cookie is set if ( cookiesApproved() ) { // hide the banner immediately! } // cookie has not been set else { // add the logic to set the cookie // and close the banner }}

    Configurar cookies en JavaScript es un poco complicado porque es necesario configurarlas como una cadena, pero no es demasiado espantoso. Dividí el proceso en su propia función para poder configurarlo como un controlador de eventos en el formulario:

    function approveCookies( e ) { // prevent the form from submitting e.preventDefault(); var cookie, // placeholder for the cookie expires = new Date(); // start building expiry date // expire in one year expires.setFullYear( expires.getFullYear() + 1 ); // build the cookie cookie = [ 'approves_cookies=yes', 'expires=' + expires.toUTCString(), 'domain=' + window.location.hostname, window.location.protocol == 'https:' ? 'secure' : '' ]; // set it document.cookie = cookie.join('; '); // close up the banner closeCookieBanner(); // return return false;};// find the form inside the bannervar $form = $cookie_banner.getElementsByTagName('form')[0];// hijack the submit event$form.addEventListener( 'submit', approveCookies, false );

    Los comentarios en el código deberían dejarlo bastante claro, pero por si acaso, esto es lo que estoy haciendo:

     

    1. Secuestra el evento de envío del formulario ( e) y cancela su acción predeterminada usando e.preventDefault().
    2. Utilice el Dateobjeto para construir una fecha dentro de un año.
    3. Reúna los bits de la cookie, incluido el approves_cookiesvalor, la fecha de caducidad, el dominio al que está vinculada la cookie y si la cookie debe ser segura (para poder realizar pruebas localmente).
    4. Establezca document.cookieigual a la cadena de galletas ensamblada.
    5. Active un método separado — closeCookieBanner()— para cerrar el banner (que cubriré en un momento).

    Con eso en su lugar, puedo definir closeCookieBanner()cómo manejar, bueno, cerrar el banner. En realidad, hay dos casos en los que necesito esta funcionalidad: después de configurar la cookie (como acabamos de ver) y si el trabajador del servicio muestra una página obsoleta que todavía tiene el banner. Aunque cada uno requiere aproximadamente la misma funcionalidad, quiero hacer que la versión de limpieza de páginas obsoletas sea un poco más agresiva. Aquí está el código:

    function closeCookieBanner( immediate ) { // How fast to close? Animation takes .5s var close_speed = immediate ? 0 : 600; // remove window.setTimeout(function(){ $cookie_banner.parentNode.removeChild( $cookie_banner ); // remove the DOM reference $cookie_banner = null; }, close_speed); // animate closed if ( ! immediate ) { $cookie_banner.className = 'closing'; }}

    Esta función toma un único argumento opcional. Si se pasa true(o algo "veraz" ), el banner se elimina inmediatamente de la página (y se elimina su referencia). Si no se pasa ningún argumento, eso no sucede durante 0,6 segundos, que es 0,1 segundos después de que finaliza la animación (llegaremos a la animación en un momento). El classcambio desencadena esa animación.

    Ya vio una instancia de esta función a la que se hace referencia en el bloque de código anterior. Aquí está en la rama de plantilla almacenada en caché del condicional que viste antes:

    …// banner exists but cookie is setif ( cookiesApproved() ){ // close immediately closeCookieBanner( true );}…

    Agregar algo de chispa visual

    Como mencioné las animaciones, también analizaré el CSS que estoy usando para el componente del banner de cookies. Como la mayoría de las implementaciones de avisos de cookies, opté por un banner visual de ancho completo. En pantallas pequeñas, quería que el banner apareciera encima del contenido y lo empujara hacia abajo en la página. En pantallas más grandes, opté por colocarlo en la parte superior de la ventana gráfica porque no obstruiría la lectura casi en el mismo grado que lo haría en una pantalla pequeña. Lograr esto implicó muy poco código:

    #cookie-banner { background: #000; color: #fff; font-size: .875rem; text-align: center;}@media (min-width: 60em) { #cookie-banner { position: fixed; top: 0; left: 0; right: 0; z-index: 1000; }}

    Al utilizar los estilos predeterminados del navegador, el banner de cookies ya se muestra block, por lo que realmente no tuve que hacer mucho más que establecer algunos estilos y colores de texto básicos. Para la pantalla grande (la versión de “pantalla completa” tiene 60 ems), la coloco en la parte superior de la pantalla usando position: fixed, con un topdesplazamiento de 0. Configurar sus desplazamientos lefty garantiza que siempre ocupará todo el ancho de la ventana gráfica. También lo puse bastante alto para que quede encima de todo lo demás en la pila.right0z-index

     

    Aquí está el resultado:

    publicó una fantástica descripción general de cómo hacer la transición de valores hacia y desdeauto hace unos años. En resumen, anime max-heighten su lugar. Lo único que debe tener en cuenta es que el tamaño del valor distinto de cero max-heighthacia y desde el cual está realizando la transición debe ser mayor que su máximo, y también afectará directamente la velocidad de la animación. Encontré que 20 ems son más que adecuados para este caso de uso, pero su proyecto puede requerir un valor diferente.

    También vale la pena señalar que utilicé display: nonela conclusión de mi cookie-banner-reverseanimación (la de cierre) para garantizar que el banner se vuelva inaccesible para los usuarios de tecnología de asistencia, como lectores de pantalla. Probablemente sea innecesario, pero lo hice como medida de seguridad en caso de que algo suceda y JavaScript no elimine el banner del DOM.

    Conectarlo requirió sólo algunos ajustes menores al CSS:

    #cookie-banner { … box-sizing: border-box; overflow: hidden; animation: cookie-banner 1s 1s linear forwards;}#cookie-banner.closing { animation: cookie-banner-reverse .5s linear forwards;}

    Esto asignó las dos animaciones a los dos estados diferentes del banner: el estado de apertura y reposo, cookie-bannerse ejecuta durante un segundo después de un retraso de un segundo; el estado de cierre cookie-banner-reversedura sólo medio segundo sin demora. Estoy usando una clase de closing, configurada mediante JavaScript que mostré anteriormente, para activar el cambio de estado. Solo para completar, señalaré que este código también estabiliza las dimensiones del banner box-sizing: border-boxy evita que el contenido se salga del banner usando overflow: hidden.

    Un último ajuste de CSS y listo. En pantallas pequeñas, dejo un margen entre el aviso de cookies ( #cookie-banner) y el encabezado de la página ( .banner). Quiero que eso desaparezca cuando el banner colapse, incluso si el aviso de cookies no se elimina del DOM. Puedo lograr eso con un selector de hermanos adyacentes:

    #cookie-banner + .banner { transition: margin-top .5s;}#cookie-banner.closing + .banner { margin-top: 0;}

    Vale la pena señalar que estoy configurando el margen superior en cada elemento menos en el primero, usando el inteligente selector de “ búho lobotomizado ” de Heydon Pickering. Entonces, la transición de margin-topon .bannerserá de un valor específico (en mi caso, 1.375 rem) a 0. Con este código implementado, el margen superior colapsará durante el mismo tiempo que el utilizado para la animación de cierre del banner de cookies y será activado por la misma adición de clase.

    . Si es "bueno tener" la característica, es posible que pueda salirse con la suya, pero probablemente no sea una buena idea jugar rápido y sin restricciones con un mandato legal como este. Tomarse unos minutos para dar un paso atrás y explorar cómo se puede implementar la función con un mínimo esfuerzo en todos los frentes dará sus frutos en el futuro. Créeme .

    Otras lecturas

    • Cómo el marketing cambió la programación orientada a objetos en JavaScript
    • Una introducción a la componibilidad de pila completa
    • Las nuevas unidades de ventana gráfica CSS no resuelven el problema clásico de la barra de desplazamiento
    • Zona de juegos de WordPress: desde la instalación en 5 minutos hasta la puesta en marcha instantánea

    (rb, vf, il, al, mrn)Explora más en

    • Codificación
    • javascript
    • Técnicas





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Cuando su código tiene que funcionar: cumplir con los mandatos legales

    Cuando su código tiene que funcionar: cumplir con los mandatos legales

    SmashingConf UX y diseño, Amberes 2024 ¡Registro! Índice Planificándolo

    programar

    es

    https://aprendeprogramando.es/static/images/programar-cuando-su-codigo-tiene-que-funcionar-cumplir-con-los-mandatos-legales-910-0.jpg

    2024-05-20

     

    Cuando su código tiene que funcionar: cumplir con los mandatos legales
    Cuando su código tiene que funcionar: cumplir con los mandatos legales

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20