Optimizando Ruby on Rails para Web Vitals, parte II

Andres Martinez
Building La Haus
Published in
11 min readJun 3, 2021
Reloj de arena sobre unas piedras.
Photo by Aron Visuals on Unsplash

Esta es la segunda publicación de una tríada de artículos destinados a hablar sobre cómo optimizamos el rendimiento y la experiencia de usuario en diversas secciones de La Haus. En este artículo hablaremos sobre el proceso de ‘refactorización’ de nuestras páginas de resultados o Search Result Pages (SRPs), que son aquellas en las que listamos las publicaciones.

Recuerda que para comprender por completo este texto, es importante que tengas claros los conceptos de Web Vitals y Pagespeed que encontrarás descritos en la parte 1 de este tema.

Contexto

Tener un buen rendimiento y una excelente experiencia para nuestros usuarios se ha convertido en una obsesión, así implique tomar decisiones radicales con nuestra tecnología o con la elección de proveedores.

En noviembre de 2020, Google anunció que la experiencia de usuario sería un factor determinante para el posicionamiento de las URLs en los resultados de búsqueda y este es nuestro foco en términos de generación de tráfico orgánico.

Comparación versiones SRPs, a la derecha, versión reciente.
Comparación versiones SRPs, izquierda, versión anterior; derecha, versión reciente.

En la imagen que se encuentra en el lado izquierdo podrán ver cómo era nuestra antigua SRP, que gracias al cambio de marca, exigencias de rendimiento, mejoras en la experiencia para facilitarle a los usuarios el correcto hallazgo de lo buscado y otras variables, fue mejorada hasta obtener la versión que se encuentra en el lado derecho. Mucho mejor, ¿cierto?

Arranquemos y vamos por partes.

Primeros pasos

Captura de pantalla de inicio de proyecto
Captura de pantalla de inicio de proyecto

Este proyecto se empezó a gestar en julio del 2020. Durante las primeras semanas hubo mucho trabajo de exploración, justificación y recolección de datos, creación de prototipos que iban y venían, discusiones centradas en los usuarios y lecturas cuidadosas de los datos para tomar decisiones acertadas. Como dato curioso, nuestra analista de datos Gabriela Chamorro, encontró que para los usuarios de México es más relevante el filtro de habitaciones que el de baños, mientras que en Colombia sucedía lo contrario. Esto demuestra lo que es prioritario para las personas de cada país, como concluyó nuestro diseñador Andrés Ovalle; ¿ustedes qué piensan?

Durante las siguientes semanas hubo muchas entrevistas de usuarios con el fin de evaluar el uso de los diferentes componentes y el diseño de diversos prototipos, todo esto coordinado por nuestro product manager, Diego Morales. Desde el lado técnico participábamos activamente en la generación de ideas, pero al no tener algo concreto en términos de diseño, construíamos bocetos y discutíamos las ventajas y desventajas de las opciones que teníamos sobre la mesa. Si quieren saber cómo nace una iniciativa en La Haus, pueden leer este artículo: La historia detrás de un Initiative Critique.

Prototipos y aproximaciones iniciales del equipo de diseño usando Figma
Prototipos y aproximaciones iniciales del equipo de diseño usando Figma

Podríamos decir que tres categorías fueron necesarias para que esta iniciativa fuera exitosa: estrategia SEO, rediseño del backend y frontend, y monitoreo.

1. Estrategia SEO

Nuestra versión anterior cumplía sus propósitos. Sin embargo, debido a la forma cómo estaba estructurado el código HTML y en la que debíamos obtener la información para ser mostrada al usuario, la optimización era compleja. Por ejemplo, debíamos iterar los resultados para agregar o eliminar información después de traer nuestros resultados desde el motor de búsqueda y debíamos construir el título de las páginas en tiempo de procesamiento. Esto solo por mencionar algunos ejemplos; debido a estas razones debíamos optimizar los tiempos de respuesta y estructurar semánticamente el código HTML con reglas refinadas para dar más contexto a los “crawlers” de los buscadores. Estos esfuerzos están concentrados en dos categorías:

  1. SEO Offsite: las acciones ejecutadas en esta parte están orientadas más a la generación de contenido, al relacionamiento entre páginas o la búsqueda activa de terceros que pongan nuestros links en contenido generado por ellos. Tenemos la fortuna de contar una especialista en temas de SEO, Natalia Prieto, ella es quien elige las palabras o combinaciones que nos ayudan a obtener más visitas, tiene en el radar que metadata debería ir en algunas URLs clave con el fin de evitar canibalización de páginas, define las plantillas para utilizar en el resto de páginas y encuentra el balance entre las veces que aparece una keyword vs evitar caer en spamming.
Optimización SEO onsite para una URL específica
Optimización SEO onsite para una URL específica

2. SEO Onsite: en esta parte concentramos las acciones en modificaciones técnicas, qué tan rápido responde nuestro servidor, qué tipos de URLs se eligen para ser indexadas, cómo hacemos para enviar a los navegadores de los clientes archivos de tamaños aceptables que incluyan el código Javascript y CSS. Antes de efectuar cualquier cambio es importante tener claridad sobre qué tipos de cosas quieres medir y si las acciones o prioridades si están alineados con esos objetivos propuestos. Nuestra meta inicial era hacer que el backend tuviera unos tiempos de respuesta cercanos a los 100ms, a continuación podrán ver los tiempos del percentil cincuenta de cada semana en nuestras SRPs:

Percentil 50 tiempos de respuesta de backend para las SRPs
Percentil 50 tiempos de respuesta de backend para las SRPs desde Octubre hasta Enero

Por otro lado, habíamos configurado un proceso para que automáticamente seleccionara algunas URLs de esta categoría e hiciera un llamado al API de Lighthouse con el fin de guardar de forma sistemática la calificación del performance score, allí nos dimos cuenta que nuestro promedio rondaba el 70%, incluyendo dispositivos móviles y de escritorio (Hasta 50 es una calificación mala, desde 50 hasta 89 se define como una URL que necesita mejoras y desde 90 es excelente).

Promedio calificación “performance score” discriminado por tipo de dispositivo y país (dominio)
Promedio calificación “performance score” discriminado por tipo de dispositivo y país (dominio)
Serie de tiempo para seguimiento de calificación de performance (dispositivos móviles solamente)
Serie de tiempo para seguimiento de calificación de performance (dispositivos móviles solamente)

Un ejercicio práctico para saber qué oportunidades de mejora tienen mayor impacto sobre esta calificación es utilizar la calculadora que Google provee, allí es posible manipular los valores de las categorías que ellos utilizan para determinar la calificación.

Calculadora de rendimiento de Lighthouse.
Calculadora de rendimiento de Lighthouse.

En este punto teníamos claro que:

  • Los tiempos de respuesta del backend debían estar rondando los 100ms.
  • Debíamos mejorar nuestra posición promedio en el ranking de Google (8.6 a octubre de 2020).
  • El porcentaje de calificación de Pagespeed debía estar cerca al 90%, es importante aclarar que los esfuerzos necesarios son más exigentes en dispositivos móviles vs dispositivos de escritorio. Principalmente se debe a que las condiciones de red son diferentes y los celulares tienen menos capacidad de cómputo si son comparados con equipos de escritorio, adicional, no todas las personas tienen dispositivos de última generación.
  • No podíamos romper lo que ya funcionaba y había que tener un plan para liberar esta funcionalidad al público o devolver a la versión anterior si algo salía mal.

2. Rediseño del “backend” y “frontend”

Teniendo el panorama claro, decidimos implementar esta iniciativa durante el último trimestre del año (nuestros objetivos son definidos trimestralmente usando la metodología de OKRs). Aunque no teníamos una fecha fija, el compromiso era desplegar esta iniciativa al finalizar el año. Las primeras semanas analizamos qué código podíamos reutilizar, cuáles prácticas de otros equipos podíamos seguir, cuáles eran las limitaciones de nuestro sistema y proveedores, y cómo ajustaríamos nuestras exigencias para llegar a los objetivos planteados

Nuestro stack es relativamente simple: un monolito montado en Ruby on Rails y una base de datos relacional Aurora, las vistas se renderizan desde el servidor, Algolia como motor de búsqueda, Imgix como proveedor de imágenes y lo que más se ha modificado son las configuraciones JS que vienen por defecto proveídas por el framework web.

Backend:

Uno de los cambios críticos era modificar la forma en la que buscábamos los datos en Algolia. Si bien ofrecen librerías tanto JS y Rails, implicaba hacer una doble maquetación para cuando las personas interactuaran con los filtros, como ya teníamos estructurada la forma de acceder a los datos desde el backend, decidimos implementar nuestra propia interfaz para hacer la búsqueda y retornar el HTML; de esta forma teníamos más control y nos da más agilidad al momento de hacer cambios relacionados con el motor de búsqueda.

A mediados de octubre después de probar algunas cosas y analizar las ventajas y desventajas de cada implementación, llegamos a una versión similar a la que se refleja en el siguiente diagrama:

Diagrama inicial con ajustes de arquitectura para la nueva funcionalidad
Diagrama inicial con ajustes de arquitectura para la nueva funcionalidad

Si bien tuvimos cambios en el backend, estos fueron en estructuración del código, crear clases según los patrones de diseño de “presenter” y “builders”, además de fortalecer las cosas que queríamos “cachear” ya que es información que varía poco (Contenido estático o algunos cálculos estadísticos).

Frontend:

De forma paulatina, hemos integrado VueJS y Tailwind CSS a las secciones del sitio. Después de hablar con integrantes de otros equipos y tomar las buenas prácticas de sus implementaciones, vimos que era la oportunidad perfecta para incluirlos en este proyecto, Juan David Gómez fue la persona encargada de maquetar y añadir el código JS necesario para esta funcionalidad.

Es fácil caer en el error de mejorar el rendimiento pensando solo en los “crawlers” de los buscadores, pero va más allá, se trata de brindar una buena experiencia a la persona que está interactuando con los elementos de la página, el problema radica en que asumimos de entrada que las personas tienen equipos de última generación o tienen velocidades de descarga muy altas, al hacer esto, estamos entregando demasiada responsabilidad a los clientes (navegadores) para cargar código, manipular el DOM, instalar librerías o códigos de terceros que en teoría facilitan las cosas (ejemplo, frameworks como Bootstrap que ya traen cargados infinidad de componentes listos para ser usados).

Algo que nos ha funcionado muy bien es cargar la aplicación VueJS cuando hay un evento como scroll, touch, click, etc. usando LazyPromise, de esta forma, en la carga inicial se reduce el tiempo total de bloqueo y permite bajar los valores de métricas como LCP.

Calculadora “performance score” de Lighthouse
Calculadora “performance score” de Lighthouse

De nuevo, quiero compartir la imagen de la calculadora de rendimiento que provee Lighthouse, si el contenido más grande que se visualiza en el dispositivo se demora más de dos segundos en cargarse y si hay un tiempo de bloqueo mientras cargan librerías o código JS en el cliente de unos 500ms, significa que de entrada hay diez puntos menos en esta calificación. El “truco” es tener claro que el LCP y el TBT tienen un peso del 50% sobre la calificación total. Por otro lado, las condiciones de red y capacidad de cómputo son determinantes en la forma como fluctúan los valores. El detalle de cómo funciona el cálculo de este valor está disponible en la documentación de web.dev.

Captura pantalla de datos de simulación en Lighthouse
Captura pantalla de datos de simulación en Lighthouse

Finalmente y no menos importante, para una carga de imágenes adecuada es definir una estrategia. Nosotros usamos Imgix ya que nos permite hacer transformaciones y manejar diferentes tamaños, además, nos permite aprovechar su red de CDN distribuida geográficamente en puntos estratégicos para una carga óptima de las imágenes. Por otro lado, usamos lazyloading como estrategia para no tener que traer todas las imágenes al tiempo cuando la persona ve los elementos iniciales en su navegador.

3. Lanzamiento y resultados

El lanzamiento tuvo que ser postergado un sprint ya que debíamos corregir múltiples detalles y necesitábamos más tiempo para probar. Este lanzamiento fue progresivo, iniciamos utilizando variables de ambiente como feature flags, elegíamos URLs que poco tráfico tuvieran y analizábamos que todo se comportara como era debido.

Hicimos la demostración al finalizar el sprint y acordamos hacer el despliegue el siguiente lunes, de esta manera podríamos activar el plan de devolver los cambios al estado original si algo no salía según lo planeado, sin embargo, mientras nos tomábamos unas cervezas y hablábamos de todas las cosas positivas logradas, planteamos “por molestar” el liberar de inmediato y así, ante todos los pronósticos, lo hicimos el viernes 15 de enero a las 7 de la noche.

Imagen que describe: “Simplemente, no se hacen lanzamientos los viernes”
Imagen que describe: “Simplemente, no se hacen lanzamientos los viernes”

Inicialmente se veía todo muy bien, las métricas se veían estables, sin embargo, hubo un detalle relacionado con la paginación que hizo que tuviéramos que revisar ya que no funcionaba de manera apropiada, pudo ser resuelto en unas cuantas horas gracias al apoyo de Edgar Villamarín y quedamos satisfechos con el resultado.

Resultados

  • No cumplimos el primer objetivo que era tener la respuesta del backend alrededor de 100ms, pero lo redujimos en un 40% y hemos tenido semanas bordeando los 115–120ms, lo cual es una buena señal. Como dato curioso, el pico que se observa en Marzo de 164 ms se dio cuando implementamos la funcionalidad de filtros sugeridos que está debajo del título principal, ese es un ejemplo de como una caché no manejada de forma adecuada puede ralentizar el sistema.
Percentil 50 tiempos de respuesta de backend para las SRPs desde Octubre de 2020 hasta Mayo de 2021
Percentil 50 tiempos de respuesta de backend para las SRPs desde Octubre de 2020 hasta Mayo de 2021
  • En promedio, subimos un 20% en la calificación de rendimiento de Lighthouse y hay varias URLs en escritorio que están por encima de 95, sin embargo, en dispositivos móviles estamos alrededor de 80. Seguimos trabajando para mejorar estos valores pero hay limitantes o funcionalidades adicionales que tendríamos que reescribir para mejorar sin perder la cadencia de liberación de nuevas funcionalidades, difícil ¿eh?.
Gráfico de líneas que representa la calificación promedio agrupado por dispositivo y país.
Gráfico de líneas que representa la calificación promedio agrupado por dispositivo y país.
Tabla que representa cómo han cambiado los valores de performance score discriminado por país y dispositvo.
Tabla que representa cómo han cambiado los valores de performance score discriminado por país y dispositvo.
  • Nuestra posición promedio en Google pasó de 8.6 a 7.2 si se compara el primer trimestre de este año contra el último trimestre del 2020.
  • En términos generales, Google percibe que nuestras URLs son rápidas, tanto para dispositivos móviles como equipos de escritorio.

Conclusiones

  • El éxito de este proyecto es derivado de la excelente comunicación y articulación de diferentes equipos de trabajo, responsabilidades y alcances definidos.
  • Como compañía que se mueve en relación al resultado de los datos, es indispensable medir el estado actual de las cosas con el fin de tener información para comparar; no se trata de medir por medir, se trata de saber qué medir.
  • Conocer las limitaciones o cualidades de un lenguaje, framework o proveedor hacen la diferencia ya que permite tomar decisiones que un principio podrían no ser convenientes.
  • Saber decir “no” o tener criterio técnico para limitar el alcance de las cosas, facilita la priorización y aumenta las probabilidades de éxito al momento de liberar una funcionalidad.
  • Tener herramientas de monitoreo tanto de rendimiento como de integridad semántica y relaciones entre páginas, ayuda a tener mayor visibilidad sobre los posibles errores que puedan generarse cuando los crawlers de los buscadores estén visitando el sitio.
  • Ayuda en demasía no ignorar la complejidad algorítmica y saber hacer profiling de los lenguajes que estás usando.

Referencias

Nuestro propósito en La Haus es transformar el mercado inmobiliario con tecnología de punta, si este artículo te gustó, quieres saber algo adicional, proponer algún tema o simplemente quieres conversar o tomar un café (aunque sea virtual), siéntete libre de escribirme a andresmartinez@lahaus.com. Si quieres aplicar a alguna de nuestras posiciones abiertas en La Haus, este es link para hacerlo.

--

--