Krypton Solid

Solución solo de CSS para el seguimiento de la interfaz de usuario

Solución solo de CSS para el seguimiento de la interfaz de usuario

La web está creciendo. Estamos creando aplicaciones que funcionan completamente en el navegador. Son receptivos; tienen toneladas de funciones y funcionan en muchos dispositivos. Disfrutamos proporcionando código de alta calidad que está bien estructurado y probado.

Pero lo que importa al final es el impacto para los clientes. ¿Están vendiendo más productos o hay más visitantes para los sitios de su campaña? Los resultados finales suelen mostrar si nuestro proyecto tiene éxito. Y confiamos en las estadísticas como herramienta de medición. Todos usamos instrumentos como Google analitico. Es una forma poderosa de recopilar datos. En este artículo, veremos un enfoque de solo CSS para realizar un seguimiento de las interacciones de la interfaz de usuario mediante Google Analytics.

Otras lecturas en SmashingMag:

El problema

Desarrollamos una aplicación que tenía que funcionar en varios dispositivos. No pudimos probar en la mayoría de ellos y decidimos que teníamos que simplificar todo. Tan simple que no había posibilidad de producir código con errores. El diseño era limpio, minimalista y no existía ninguna lógica empresarial compleja.

Era un sitio web que mostraba información sobre uno de los productos del cliente. Una de nuestras tareas era realizar un seguimiento de las visitas e interacciones de los usuarios. En la mayoría de los casos, utilizamos Google Analytics. Todo lo que teníamos que hacer era colocar un código como el siguiente ejemplo en la parte inferior de las páginas:


(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://kryptonsolid.com/wp-content/cache/busting/google-tracking/ga-876c0f150943aff8b256da31f79ac00e.js','ga');

ga('create', '......', '......');
ga('send', 'pageview');

Este fragmento fue suficiente para realizar un seguimiento de las visitas a la página, el tráfico, las sesiones, etc. Además, colocamos JavaScript donde el usuario interactúa con la página. Por ejemplo, hacer clic en un enlace, completar un campo de entrada o marcar casillas de opciones.


ga('send', 'event', 'ui-interaction', 'click', 'link clicked', 1);

Los chicos de Google manejaron estos eventos muy bien y pudimos verlos en nuestra cuenta. Sin embargo, en algún momento, el cliente informó que había dispositivos que tenían mala compatibilidad o no tenían soporte para JavaScript. Representaron aproximadamente el 2% de todos los dispositivos que visitaron el sitio. Comenzamos a buscar una solución que no involucrara JavaScript. Estábamos dispuestos a admitir que no podíamos recopilar estadísticas en estas circunstancias.

No fue tan malo, pero el cliente compartió otro problema. Nuestra pequeña aplicación iba a ser parte de una red privada. Las computadoras tenían JavaScript desactivado por razones de seguridad. Además, esta red privada era importante para el cliente. Entonces, insistió en que todavía obtengamos estadísticas en esos casos. Teníamos que proporcionar una solución adecuada, pero el problema era que solo teníamos CSS y HTML disponibles como herramientas.

La solución

Mientras buscaba una solución, estaba monitoreando el La red pestaña en las herramientas de desarrollo de Chrome cuando noté lo siguiente:

(Ver versión grande)

Al principio, pensé que no había nada inusual. El código de Google Analytics realizó pocas solicitudes HTTP para sus procesos de seguimiento. Sin embargo, la cuarta columna muestra la Content-type encabezado de la respuesta. Es una imagen. No JSON o HTML, sino una imagen. Luego comencé a leer la documentación y llegué a este Descripción general del código de seguimiento. La parte más interesante fue:

Cuando se recopila toda esta información, se envía a los servidores de Analytics en forma de una larga lista de parámetros adjunta a una solicitud de imagen GIF de un solo píxel.

Entonces, Google de hecho hizo la solicitud HTTP pero no la trivial llamada Ajax. Simplemente agrega todos los parámetros a la URL de una imagen. Después de eso, realiza una solicitud de un archivo GIF. Incluso hay un nombre para tales solicitudes: Faro. Me preguntaba por qué GA usa este enfoque. Entonces me di cuenta de que hay algunos beneficios:

  • Es simple. Inicializamos un nuevo Image objeto y aplicar un valor a su src atributo:

    new Image().src="https://www.smashingmagazine.com/stats.gif?" + parameters
    
  • Funciona en todas partes. No es necesario agregar soluciones alternativas para diferentes navegadores como lo hacemos para las solicitudes de Ajax.

  • Pequeña respuesta. Como Stoyan Stefanov dijo, la imagen GIF de 1 × 1 px podría tener solo 42 bytes.

Hice algunos clics y envié eventos a Google Analytics. Conociendo los parámetros de la solicitud, pude construir mis propias URL de imagen. Lo único que se podía hacer al final era cargar una imagen en la página. Y sí, esto fue posible con CSS puro.


background-image: url('http://www.google-analytics.com/collect?v=1&_v=j23&a=...');

Establecer el background-image La propiedad CSS obliga al navegador a cargar una imagen. Finalmente, utilizamos con éxito esta técnica para rastrear las acciones de los usuarios.

Seguimiento de las acciones del usuario

Hay varias formas de cambiar estilos según la entrada del usuario. Lo primero en lo que pensamos fue en :active pseudo clase. Esta clase coincide cuando el usuario activa un elemento. Es el tiempo entre el momento en que el usuario presiona el botón del mouse y lo suelta. En nuestro caso, esto fue perfecto para realizar un seguimiento de los clics:


input[type="button"]:active {
    background-image: url('http://www.google-analytics.com/collect?v=1&_v=j23&a=...');
}

Otra pseudoclase útil es :focus. Registramos cuántas veces los usuarios comenzaron a escribir en el formulario de contacto. Fue interesante descubrir que en aproximadamente el 10% de los casos los usuarios no enviaron el formulario.


input[name="message"]:focus {
    background-image: url('http://www.google-analytics.com/collect?v=1&_v=j23&a=...');
}

En una página, teníamos un cuestionario paso a paso. Al final, se le pidió al usuario que aceptara algunos términos y condiciones. Algunos de los visitantes no completaron ese último paso. En la primera versión del sitio, no pudimos determinar qué habían seleccionado estos usuarios en el cuestionario porque los resultados se habrían enviado una vez completado. Sin embargo, debido a que todos los pasos eran solo botones de opción, usamos el :checked pseudoclase y rastreó con éxito las selecciones:


input[value="female"]:checked {
    background-image: url('http://www.google-analytics.com/collect?v=1&_v=j23&a=...');
}

Una de las estadísticas más importantes que tuvimos que ofrecer fue sobre la diversidad de resoluciones de pantalla. Gracias a las consultas de los medios esto fue posible:


@media all and (max-width: 640px) {
    body {
        background-image: url('http://www.google-analytics.com/collect?v=1&_v=j23&a=...');
    }
}

De hecho, hay bastantes operadores lógicos que podemos usar. Podemos rastrear pantallas con una relación de aspecto específica; dispositivos en orientación horizontal; o aquellos con una resolución de 300 ppp.

Inconvenientes

El problema con este tipo de seguimiento de la interfaz de usuario de CSS es que solo obtenemos la primera aparición del evento. Por ejemplo, tome el :active ejemplo de pseudoclase. La solicitud de la imagen de fondo se activa solo una vez. Si necesitamos capturar cada clic, entonces tenemos que cambiar la URL, lo cual no es posible sin JavaScript.

Usamos el background-image propiedad para realizar las solicitudes HTTP. Sin embargo, a veces es posible que necesitemos establecer una imagen real como fondo debido al diseño de la aplicación. En tales casos, podríamos utilizar el content propiedad. Por lo general, se usa para agregar texto o íconos, pero la propiedad también acepta una imagen. Por ejemplo:


input[value="female"]:checked {
    content: url('http://www.google-analytics.com/collect?v=1&_v=j23&a=...');
}

Debido a que estamos solicitando una imagen, debemos asegurarnos de que el navegador no esté almacenando en caché el archivo. El servidor de estadísticas debe procesar la solicitud cada vez. Podríamos lograr esto proporcionando los encabezados correctos. Mira la imagen a continuación. Muestra los encabezados de respuesta enviados por Google:

Seguimiento de la interfaz de usuario con CSS
(Ver versión grande)

El envío de los siguientes encabezados garantiza que el navegador no almacenará en caché la imagen:


Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0

En algunos casos, podemos decidir escribir nuestro propio servidor de estadísticas. Esta es una nota importante que debemos tener en cuenta durante el desarrollo. Aquí hay una implementación simple basada en Node.js. Lo usamos con fines de prueba:


var fs = require('fs'),
    http = require('http'),
    url = require('url'),
    img = fs.readFileSync(__dirname + '/stat.png'),
    stats = {};

var collectStats = function(type) {
    console.log('collectStats type=" + type);
    if(!stats[type]) stats[type] = 0;
    stats[type]++;
}

http.createServer(function(req, res){
    var request = url.parse(req.url, true);
    var action = request.pathname;
    if (action == "/stat.png') {
        collectStats(request.query.type);
        res.writeHead(200, {'Content-Type': 'image/gif', 'Cache-Control': 'no-cache' });
        res.end(img, 'binary');
    } else {
        res.writeHead(200, {'Content-Type': 'text/html' });
        res.end('Stats server:<pre>' + JSON.stringify(stats) + '</pre>n');
    }
}).listen(8000, '127.0.0.1');
console.log('Server is running at http://127.0.0.1:8000');

Si guardamos el código en un archivo llamado server.js y ejecutar node server.js obtendremos un servidor escuchando en el puerto 8000. Hay dos posibles URL para realizar consultas:


* http://127.0.0.1:8000/ - shows the collected statistics
* http://127.0.0.1:8000/stat.png?type=something - collecting statistics.

Al solicitar el PNG en la segunda URL, estamos incrementando valores. El siguiente fragmento de código muestra el HTML y CSS que tenemos que colocar en el navegador:


<input type="button" value="click me"/>

input[type="button"]:active {
    background-image: url('http://127.0.0.1:8000/stat.png?type=form-submitted');
}

Finalmente, como último inconveniente tenemos que mencionar que algún software antivirus o configuraciones del navegador pueden eliminar balizas de 1 × 1px. Por lo tanto, debemos tener cuidado al elegir esta técnica y asegurarnos de proporcionar soluciones alternativas.

Resumen

CSS generalmente se considera un lenguaje para aplicar estilos a páginas web. Sin embargo, en este artículo vimos que es más que eso. También es una herramienta útil para recopilar estadísticas.

Deja un comentario