Cómo hacer que tu web cargue rápido, sin pagar un centavo

Por Santos Jaimes · ·

Hay dos tipos de sitios web: los que cargan antes de que sueltes el dedo del mouse, y los que te dan tiempo de ir a la cocina, prepararte un café y volver a ver si ya apareció el menú.

Si tu sitio es del segundo tipo, tranquilo. Casi todo lo que hace lento a un sitio es reparable, gratis, y sin contratar a un gurú que cobra por hora lo que tú cobras por día. Vamos a ver tres cosas: qué técnicas mueven de verdad la aguja, qué directivas meter en el .htaccess (con el código listo para copiar), y cómo optimizar imágenes sin pagar ningún servicio.

Conejillo de indias: Little Italy Kitchen, restaurante italiano en LoDo, Denver. Horno de leña, pasta a mano, y una web con fotos de lasaña de 6 megabytes cada una.

Por qué importa la velocidad (y por qué no es magia)

Primero, bajemos las expectativas a un nivel sano. La velocidad es un factor de ranking, confirmado públicamente desde 2010, pero es un factor menor. Nadie llega al primer puesto solo por cargar rápido, así como nadie gana un concurso de cocina solo porque llegó temprano.

La forma correcta de pensarlo: cuando tu página y la de tu competidor están casi empatadas en todo lo demás, ser materialmente más rápido puede ser el empujón. Y además — esto es lo que de verdad importa — las páginas rápidas dan mejor experiencia y aumentan las conversiones.

Traducido a español de restaurante: si alguien busca dónde cenar desde el celular, parado en una esquina con hambre y 12% de batería, tu sitio tiene aproximadamente un segundo para mostrar algo útil antes de que esa persona se vaya al competidor.

Los tres números que Google mira: Core Web Vitals

MétricaQué mideMeta ("bueno")
LCP
Largest Contentful Paint
Cuánto tarda en aparecer el bloque de contenido principal ≤ 2,5 segundos
INP
Interaction to Next Paint
Cuánto tarda la página en responder cuando el usuario hace clic o toca algo ≤ 200 milisegundos
CLS
Cumulative Layout Shift
Cuánto se mueve el contenido mientras carga (lo que te hace pulsar el botón equivocado) ≤ 0,1
⚠️ Ojo con los libros viejos. Si lees material de SEO publicado antes de 2024, vas a ver mencionada la métrica FID (First Input Delay). Esa métrica murió: Google la reemplazó oficialmente por INP el 12 de marzo de 2024. La diferencia es que FID solo medía el retraso de la primera interacción, mientras que INP evalúa todas las interacciones durante la visita completa. Ya no basta con que el primer clic sea rápido: ahora tienen que serlo todos.

Un detalle técnico que vale oro: las tres métricas se miden en el percentil 75 de tus usuarios reales. No basta con que te cargue rápido a ti, en tu laptop, con fibra óptica. Tiene que cargarle rápido al 75% de quienes te visitan, incluido el turista con señal 3G intermitente.

Primero mide, después toca

Regla de oro: no optimices a ciegas. Antes de tocar código:

  • PageSpeed Insights: te da datos de campo (usuarios reales, del conjunto CrUX) y datos de laboratorio, más sugerencias concretas.
  • Lighthouse: integrado en Chrome DevTools. Puedes pulsar cada fila del informe para ver exactamente qué recurso causa el problema.
  • GTmetrix: su pestaña "Structure" tiene una auditoría de LCP que te dice qué elemento específico frena la carga. Y el "waterfall", que muestra en qué orden carga todo.
  • WebPageTest y Pingdom: más opciones de laboratorio.
  • Search Console: informe de Core Web Vitals con datos reales de tu sitio.

Las técnicas que realmente aceleran un sitio

El hosting: donde casi todos pierden la batalla

En un hosting compartido, tu sitio pelea por recursos con otros sitios del mismo servidor. Y a veces esos vecinos corren scripts pesados a toda hora. Es cocinar en una cocina comunitaria donde alguien siempre está usando las cuatro hornillas.

Si GTmetrix te dice que todos tus elementos están optimizados pero el servidor sigue lento, el problema es el hosting y ninguna directiva te va a salvar. El salto a un VPS suele ser el cambio que más se nota.

Menos scripts de terceros

Cada vez que agregas Analytics, un pixel, un chat en vivo, un widget de reseñas, un mapa embebido y un botón de reservas, tu página tiene que hablar con un servidor remoto distinto cada vez que carga.

Uno solo no hace daño. Pero como advierte The Art of SEO: si tienes tres o más programas de analítica o seguimiento, probablemente tienes demasiados. Little Italy Kitchen no necesita cuatro herramientas de mapas de calor para saber que la gente pulsa "Ver el menú".

Código limpio: minificar CSS y JavaScript

Minificar es quitarle al código los espacios, saltos de línea y comentarios que sirven para que un humano lo lea pero que la máquina no necesita. Y hay un beneficio menos obvio: cuando validas tu HTML y CSS, reduces las veces que el navegador tiene que adivinar qué querías renderizar, lo que reduce el tiempo de render.

👈 Advertencia que poca gente menciona: optimizar demasiado agresivamente para esto puede empeorar tu CLS. PageSpeed Insights te empuja fuerte a eliminar CSS y JS que bloquean el render, y si te pasas de la raya, tu página termina saltando como conejo mientras carga. Equilibrio, no fanatismo.

Caché, CDN y base de datos

Cachear es guardar una versión ya "cocinada" de tus páginas para no reconstruirlas cada vez. Si usas un CMS, revisa que su caché esté activada — en algunas plataformas hay que encenderla explícitamente — y revisa el impacto de cada extensión instalada, porque muchas son las culpables de la lentitud.

Un truco viejo pero efectivo si tienes una portada computacionalmente pesada: generas un snapshot estático con wget, lo guardas como index.html, y programas un cron que lo repita para mantenerlo fresco.

wget --output-document=index.html http://www.littleitalykitchen.com/index.php

Sobre el CDN: copia tu contenido a servidores repartidos por el mundo. Little Italy Kitchen está en Denver, pero recibe turistas que investigan restaurantes antes de viajar, desde Tokio o Madrid. Y hay planes gratuitos que incluyen CDN, compresión Brotli, minificación y certificado SSL: para un sitio pequeño-mediano sobra.

Y la base de datos: si lleva años funcionando, los registros se fragmentan y el rendimiento baja. Desfragmentarla puede acelerarla notablemente.

El archivo .htaccess: el interruptor pequeño que hace mucho

El .htaccess permite cambiar la configuración de Apache directorio por directorio. Controla el directorio donde está y todos sus subdirectorios, y normalmente vive en la raíz.

Cuatro advertencias que te ahorran un infarto

  1. Haz una copia de respaldo antes de modificarlo.
  2. Un carácter mal puede tumbar tu sitio. Literalmente puede dejarlo fuera de línea hasta que corrijas el error.
  3. Guárdalo con saltos de línea UNIX. Si tu editor usa formato Windows, salen errores raros.
  4. Es un archivo oculto. Activa "ver archivos ocultos" en tu FTP y asegúrate de que no existe uno ya, para no sobrescribirlo.

Y una nota: cada directiva va envuelta en un <IfModule>. Así, si tu hosting no tiene ese módulo activado, el servidor ignora el bloque en lugar de reventar con un error 500.

Compresión gzip (la más rentable de todas)

Comprime el contenido antes de enviarlo al navegador. En texto plano, HTML, CSS y JavaScript el ahorro puede ser del 60% al 80%.

<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/plain text/xml
  AddOutputFilterByType DEFLATE text/css text/javascript
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE application/json
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE font/ttf font/otf font/eot

  # Navegadores antiguos con bugs conocidos
  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4\.0[678] no-gzip
  BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

  <IfModule mod_headers.c>
    Header append Vary User-Agent
  </IfModule>
</IfModule>

Importante: fíjate que NO comprimimos JPG, PNG, WebP, MP4 ni ZIP. Esos ya vienen comprimidos; volver a comprimirlos gasta CPU y no ahorra nada. Es meter una maleta cerrada dentro de otra maleta. Las fuentes .woff2 también quedan fuera por lo mismo.

Si tu servidor no tiene mod_deflate, hay alternativa desde PHP:

<?php ob_start("ob_gzhandler"); ?>

O más fácil todavía, en el php.ini de tu raíz:

zlib.output_compression=on

Brotli (el gzip del siglo XXI)

Comprime entre 15% y 20% mejor que gzip. Si tu hosting lo tiene, actívalo; si no, el bloque se ignora:

<IfModule mod_brotli.c>
  AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml
  AddOutputFilterByType BROTLI_COMPRESS text/css text/javascript
  AddOutputFilterByType BROTLI_COMPRESS application/javascript
  AddOutputFilterByType BROTLI_COMPRESS application/json
  AddOutputFilterByType BROTLI_COMPRESS image/svg+xml
</IfModule>

Puedes tener los dos bloques a la vez. El servidor negocia con el navegador y usa el mejor que ambos soporten.

Caché del navegador con mod_expires

Le dice al navegador: "el logo no ha cambiado desde 2019, no me lo vuelvas a pedir". Para usuarios recurrentes, la segunda visita se vuelve casi instantánea.

<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 1 month"

  # HTML: nunca cachear agresivamente, cambia seguido
  ExpiresByType text/html "access plus 0 seconds"

  # Datos que cambian
  ExpiresByType application/json "access plus 0 seconds"
  ExpiresByType application/xml "access plus 0 seconds"

  # Imágenes: un año
  ExpiresByType image/jpeg "access plus 1 year"
  ExpiresByType image/png "access plus 1 year"
  ExpiresByType image/webp "access plus 1 year"
  ExpiresByType image/avif "access plus 1 year"
  ExpiresByType image/svg+xml "access plus 1 year"
  ExpiresByType image/x-icon "access plus 1 year"

  # CSS y JavaScript
  ExpiresByType text/css "access plus 1 year"
  ExpiresByType application/javascript "access plus 1 year"

  # Fuentes
  ExpiresByType font/woff2 "access plus 1 year"
  ExpiresByType font/woff "access plus 1 year"
</IfModule>
⚠️ El detalle crítico que rompe sitios. Si cacheas tu CSS por un año y luego cambias el diseño, los usuarios recurrentes verán el diseño viejo hasta que se les venza la caché. La solución se llama cache busting: cambia el nombre del archivo cuando cambies el contenido.
<!-- Mal: el navegador no sabe que cambió -->
<link rel="stylesheet" href="/css/estilo.css">

<!-- Bien: cambias el número y lo trata como archivo nuevo -->
<link rel="stylesheet" href="/css/estilo.css?v=7">

<!-- Mejor todavía -->
<link rel="stylesheet" href="/css/estilo.a83f2c.css">

Cache-Control, Keep-Alive y ETags

mod_expires es la versión clásica; Cache-Control es la moderna y más precisa. Puedes usar ambas. El immutable le dice al navegador que ni se moleste en preguntar si el archivo cambió.

<IfModule mod_headers.c>
  # Recursos estáticos con nombre versionado: cachear a lo bestia
  <FilesMatch "\.(jpg|jpeg|png|gif|webp|avif|svg|ico|css|js|woff2|woff)$">
    Header set Cache-Control "public, max-age=31536000, immutable"
  </FilesMatch>

  # HTML: siempre revalidar
  <FilesMatch "\.(html|htm|php)$">
    Header set Cache-Control "no-cache, must-revalidate, max-age=0"
  </FilesMatch>

  # Keep-Alive: reutiliza la conexión en vez de abrir una por archivo
  Header set Connection keep-alive

  # ETags: redundantes si ya tienes Expires y Cache-Control,
  # y en servidores múltiples rompen la caché
  Header unset ETag
</IfModule>
FileETag None

Canonicalización en un solo salto (HTTPS + www)

Aquí hay una trampa de velocidad que casi nadie ve. Muchos sitios tienen una regla que redirige HTTP a HTTPS y otra separada que redirige sin-www a con-www. Resultado: dos redirecciones encadenadas antes de ver nada. Cada una es un viaje completo de ida y vuelta al servidor.

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /

  RewriteCond %{HTTPS} off [OR]
  RewriteCond %{HTTP_HOST} !^www\. [NC]
  RewriteRule ^(.*)$ https://www.littleitalykitchen.com/$1 [R=301,L]
</IfModule>

El RewriteBase / solo se usa en .htaccess, no en la configuración del servidor. Y el signo de exclamación al inicio de una expresión regular significa "no". Si prefieres la versión sin www, invierte la lógica: lo importante es elegir un sistema y ser fiel a él.

Más sobre redirecciones 301 aquí

Servir WebP automáticamente (la joya de la corona)

Mi directiva favorita. La idea: guardas dos versiones de cada imagen (pizza.jpg y pizza.webp), dejas tu HTML tal cual con el .jpg, y el servidor entrega el WebP automáticamente a los navegadores que lo soportan.

<IfModule mod_rewrite.c>
  RewriteEngine On

  # ¿El navegador acepta WebP?
  RewriteCond %{HTTP_ACCEPT} image/webp
  # ¿La petición es de un JPG o PNG?
  RewriteCond %{REQUEST_FILENAME} (.+)\.(jpe?g|png)$
  # ¿Existe la versión .webp del mismo archivo?
  RewriteCond %1\.webp -f
  # Entonces sirve el .webp
  RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=REQUEST_image,L]
</IfModule>

<IfModule mod_headers.c>
  Header append Vary Accept env=REQUEST_image
</IfModule>

<IfModule mod_mime.c>
  AddType image/webp .webp
  AddType image/avif .avif
</IfModule>

El Vary: Accept es obligatorio: avisa a las cachés intermedias y CDNs que el contenido de esa URL cambia según el navegador. Sin él, un proxy podría cachear el WebP y servírselo a un navegador que no lo soporta, y ahí sí se arma el desastre.

Protección contra hotlinking

Si otro sitio pone tus fotos directamente en su página, tú pagas el ancho de banda y ellos se llevan las visitas.

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP_REFERER} !^$
  RewriteCond %{HTTP_REFERER} !^https?://(www\.)?littleitalykitchen\.com [NC]
  RewriteCond %{HTTP_REFERER} !^https?://(www\.)?google\. [NC]
  RewriteCond %{HTTP_REFERER} !^https?://(www\.)?bing\.com [NC]
  RewriteCond %{HTTP_REFERER} !^https?://(www\.)?facebook\.com [NC]
  RewriteCond %{HTTP_REFERER} !^https?://(www\.)?instagram\.com [NC]
  RewriteRule \.(jpg|jpeg|png|gif|webp|avif)$ - [F,NC]
</IfModule>
⚠️ Cuidado aquí. Si bloqueas todo sin excepciones, puedes impedir que Google muestre tus imágenes en Google Images. The Art of SEO advierte exactamente esto: hay administradores que desactivan la visualización desde otros dominios y eso causa problemas si quieres aparecer en búsqueda de imágenes. Por eso las excepciones para buscadores y redes.

El .htaccess completo, ordenado

Pégalo, cambia el dominio, súbelo, y prueba tu sitio inmediatamente:

# ==========================================================
# LITTLE ITALY KITCHEN - .htaccess optimizado
# ==========================================================

# ---------- 1. REDIRECCIONES (van primero) ----------
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /

  RewriteCond %{HTTPS} off [OR]
  RewriteCond %{HTTP_HOST} !^www\. [NC]
  RewriteRule ^(.*)$ https://www.littleitalykitchen.com/$1 [R=301,L]

  # WebP automático
  RewriteCond %{HTTP_ACCEPT} image/webp
  RewriteCond %{REQUEST_FILENAME} (.+)\.(jpe?g|png)$
  RewriteCond %1\.webp -f
  RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=REQUEST_image,L]
</IfModule>

# ---------- 2. TIPOS MIME ----------
<IfModule mod_mime.c>
  AddType image/webp .webp
  AddType image/avif .avif
  AddType font/woff2 .woff2
</IfModule>

# ---------- 3. COMPRESIÓN ----------
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
  AddOutputFilterByType DEFLATE text/javascript application/javascript
  AddOutputFilterByType DEFLATE application/json application/xml
  AddOutputFilterByType DEFLATE application/rss+xml image/svg+xml
</IfModule>

<IfModule mod_brotli.c>
  AddOutputFilterByType BROTLI_COMPRESS text/html text/css
  AddOutputFilterByType BROTLI_COMPRESS application/javascript
  AddOutputFilterByType BROTLI_COMPRESS application/json image/svg+xml
</IfModule>

# ---------- 4. CACHÉ ----------
<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 1 month"
  ExpiresByType text/html "access plus 0 seconds"
  ExpiresByType image/jpeg "access plus 1 year"
  ExpiresByType image/png "access plus 1 year"
  ExpiresByType image/webp "access plus 1 year"
  ExpiresByType image/avif "access plus 1 year"
  ExpiresByType image/svg+xml "access plus 1 year"
  ExpiresByType text/css "access plus 1 year"
  ExpiresByType application/javascript "access plus 1 year"
  ExpiresByType font/woff2 "access plus 1 year"
</IfModule>

# ---------- 5. HEADERS ----------
<IfModule mod_headers.c>
  Header append Vary Accept env=REQUEST_image
  Header set Connection keep-alive
  Header unset ETag

  <FilesMatch "\.(jpg|jpeg|png|webp|avif|svg|ico|css|js|woff2)$">
    Header set Cache-Control "public, max-age=31536000, immutable"
  </FilesMatch>
</IfModule>
FileETag None

# ---------- 6. VARIOS ----------
Options -Indexes
ErrorDocument 404 /404.html
ServerSignature Off

Deja una línea en blanco al final del archivo: el servidor lo lee línea por línea y necesita ese retorno de carro para saber que terminaste.

Lo del 404 no es solo estética: si tu sitio usa lenguajes del lado del servidor, los errores crípticos que muestra por defecto son precisamente lo que el buscador va a indexar en vez de tu contenido.

Imágenes rápidas sin pagar un servicio

Aquí está el verdadero botín. Según HTTP Archive, las imágenes representan en promedio el 21% del peso total de una página. En un sitio de restaurante, con galerías de platos, ese porcentaje se dispara fácil al 60% o 70%.

Y ojo: el LCP suele ser precisamente una imagen. Si arreglas tus imágenes, arreglas tu LCP. Es la relación esfuerzo/beneficio más alta de todo el SEO técnico.

Elige el formato correcto

FormatoCuándo usarlo
JPEGFotografías. Puedes ajustar el nivel de calidad para equilibrar peso y apariencia
PNGCapturas, logos, transparencias. Mejor calidad, archivo más pesado
WebPEl estándar actual. Compresión con o sin pérdida; pesa entre 25% y 35% menos que un JPEG equivalente
AVIFTodavía más eficiente que WebP. Soportado por los navegadores modernos
SVGLogos, iconos, ilustraciones planas. Es texto, escala infinitamente y no pesa nada

Advertencia curiosa: cuidado si usas imágenes .jpg dentro de un SVG en línea, porque los sistemas de Google no pueden indexar eso.

Flujo recomendado: trabaja los originales en PNG o JPEG de alta calidad y conviértelos a WebP (y opcionalmente AVIF) para publicar. Guarda siempre los originales; nunca comprimas encima del único archivo que tienes.

Comprime antes de subir (herramientas 100% gratis)

En el navegador: Squoosh, hecho por Google, funciona local y no sube tus archivos a ningún lado; tiene comparador lado a lado y exporta a WebP y AVIF. De escritorio: GIMP, que exporta a WebP directamente.

Y en línea de comandos, que es donde te ahorras horas:

# Instalar las herramientas (Debian/Ubuntu)
sudo apt install webp imagemagick jpegoptim optipng

# Convertir una imagen a WebP con calidad 80
cwebp -q 80 margherita.jpg -o margherita.webp

# Convertir TODA una carpeta de golpe
for f in *.jpg; do cwebp -q 80 "$f" -o "${f%.jpg}.webp"; done
for f in *.png; do cwebp -q 80 "$f" -o "${f%.png}.webp"; done

# Redimensionar a 1600px de ancho máximo y quitar metadatos EXIF
mogrify -resize '1600x>' -quality 82 -strip *.jpg

# Optimizar JPEG sin cambiar de formato
jpegoptim --strip-all --max=82 *.jpg

# Optimizar PNG
optipng -o5 *.png

Ese -strip no es cosmético: quita los metadatos EXIF (modelo de cámara, GPS, fecha) que pueden pesar decenas de kilobytes por foto y que a nadie le sirven en la web.

Un script de tres líneas te procesa las 200 fotos del menú mientras te tomas un espresso. Resultado típico: una foto de 4,2 MB salida del celular termina pesando 180 KB, y se ve exactamente igual en pantalla.

No subas imágenes más grandes de lo que se van a mostrar

El error número uno y el más fácil de arreglar. Si tu página muestra la foto en un contenedor de 800 píxeles, no subas una imagen de 4000 y la reduzcas con CSS.

La razón es que cambiar el tamaño de visualización no reduce el tamaño del archivo que se envía, a veces por conexiones de bajo ancho de banda, al dispositivo móvil de una persona. El navegador descarga los 4 MB completos y luego los encoge. Es pedir una pizza familiar para comerte una porción.

Regla práctica: sube al doble del tamaño de visualización (por las pantallas retina) y ni un píxel más. Y si quieres ofrecer imágenes muy grandes, ponlas en una página aparte con un thumbnail que enlace: así solo esperan la carga los usuarios que de verdad quieren verlas.

Siempre pon width y height

La optimización más barata que existe: dos atributos. Permiten al navegador reservar el espacio de la imagen antes de que cargue el CSS, lo que evita que la página salte. Y ese salto es exactamente lo que mide el CLS.

<!-- Mal: el navegador no sabe cuánto espacio reservar -->
<img src="lasagna.webp" alt="Lasaña">

<!-- Bien -->
<img src="lasagna.webp" width="800" height="600" alt="Lasaña de la casa">

Si usas AMP o PWAs, además, definir las dimensiones es obligatorio.

Imágenes responsivas: srcset y picture

El objetivo es que el navegador descargue la versión adecuada al dispositivo. Quien ve el menú desde un móvil no debería descargar la misma imagen que alguien en un monitor 4K.

Opción 1: srcset con sizes, la más simple:

<img srcset="pizza-480.webp 480w,
             pizza-800.webp 800w,
             pizza-1600.webp 1600w"
     sizes="(max-width: 600px) 100vw,
            800px"
     src="pizza-800.webp"
     width="800" height="600"
     alt="Pizza margherita saliendo del horno de leña">

Opción 2: el elemento <picture>, cuando quieres servir formatos distintos. Puede contener múltiples <source>, y debe incluir un <img> como respaldo para navegadores viejos:

<picture>
  <source type="image/avif"
          srcset="tiramisu-800.avif 800w, tiramisu-1600.avif 1600w"
          sizes="(max-width: 600px) 100vw, 800px">
  <source type="image/webp"
          srcset="tiramisu-800.webp 800w, tiramisu-1600.webp 1600w"
          sizes="(max-width: 600px) 100vw, 800px">
  <img src="tiramisu-800.jpg"
       width="800" height="600"
       alt="Tiramisú casero de Little Italy Kitchen en LoDo, Denver">
</picture>

El navegador elige de arriba hacia abajo: si soporta AVIF usa AVIF; si no, WebP; si no, el JPEG del <img>. Nadie se queda sin ver la foto.

Para artículos y blogs, Google recomienda incluir imágenes de alta resolución en tres proporciones: 1×1, 4×3 y 16×9. Y esto también aplica a varios tipos de schema, incluido LocalBusiness, Recipe, Product y Event: exactamente los que necesita un restaurante.

Más sobre datos estructurados y Schema aquí

Lazy loading (con una advertencia importante)

Hace que las imágenes de más abajo no se descarguen hasta que el usuario haga scroll. Hoy es nativo, sin JavaScript:

<img src="cannoli.webp" width="600" height="400"
     alt="Cannoli siciliano" loading="lazy" decoding="async">
⚠️ The Art of SEO es explícito: hay que tener cuidado con la entrega asíncrona de imágenes donde AJAX o JavaScript las cargan después de los elementos principales. Eso puede retrasar la absorción por parte de Google, o incluso resultar en que Google no indexe las imágenes en absoluto. El loading="lazy" nativo es seguro; los que dan problemas son los scripts caseros o los plugins que reemplazan el src con placeholders. Para mitigar el riesgo, usa sitemaps de imágenes.

Y ahora el error que cometen 9 de cada 10 sitios: poner loading="lazy" en la imagen principal del banner. Esa es justamente tu elemento LCP. Ponerle lazy es como decirle al mesero "tráeme el plato principal solo cuando yo lo pida específicamente". Para esa imagen, haz lo contrario:

<!-- La imagen hero: prioridad máxima, sin lazy -->
<img src="hero-restaurante.webp" width="1600" height="900"
     alt="Interior de Little Italy Kitchen en el barrio LoDo de Denver"
     loading="eager" fetchpriority="high" decoding="async">

Y si quieres exprimir el último segundo, precárgala desde el <head>:

<link rel="preload" as="image" href="/img/hero-restaurante.webp"
      fetchpriority="high">

Bonus: nombres de archivo, alt y sitemap

Ya que estás procesando todo, aprovecha para renombrar bien. Google reveló que usa la ruta y el nombre del archivo para rankear imágenes. En vez de tirar todo en una carpeta genérica, estructura subcarpetas por categorías temáticas:

Mal:  /media/IMG_20240815_193042.jpg
Bien: /platos/pastas/lasagna-bolognesa-horno-lena.webp

Y el alt, siempre. Google lo usa para determinar cuál es la mejor imagen que puede devolver ante una consulta, y además es un requisito de accesibilidad para quienes no pueden ver las imágenes.

<!-- Inútil -->
<img src="pizza.webp" alt="pizza">

<!-- Útil -->
<img src="pizza.webp" alt="Pizza margherita en horno de leña de Little Italy Kitchen, Denver">

Regla de proporción: alt breve para imágenes pequeñas, más largo para imágenes grandes. Como guía general, no debería pasar de 12 palabras.

Por último, tener tus imágenes en un sitemap de imágenes aumenta enormemente las probabilidades de que se rastreen e indexen. Y revisa que tu robots.txt no esté bloqueando los directorios de imágenes: sería una pena hacer todo este trabajo y descubrir que tenías un Disallow: /img/ de hace tres años.

Ah, y un consejo final: no uses las mismas fotos de stock que usa todo el mundo. Toma tus propias fotos. Además del beneficio SEO, ningún banco de imágenes tiene la lasaña de tu cocina.

Plan de acción para una sola tarde

Si Little Italy Kitchen tuviera libre la tarde entre el almuerzo y la cena, este sería el orden.

Primera hora: medir

  1. Corre PageSpeed Insights en tu home, tu página de menú y una de plato.
  2. Anota tu LCP, INP y CLS actuales. Guarda una captura para comparar después.
  3. Identifica cuál es tu elemento LCP (spoiler: probablemente la foto del banner).

Segunda hora: imágenes

  1. Descarga todas tus imágenes por FTP.
  2. Corre mogrify para redimensionar a máximo 1600px y quitar EXIF.
  3. Corre cwebp para generar las versiones WebP.
  4. Renombra las que tengan nombres tipo IMG_4823.jpg.
  5. Sube todo: los JPG optimizados y los WebP.

Tercera hora: .htaccess

  1. Descarga y respalda tu .htaccess actual.
  2. Pega el bloque completo, cambiando el dominio.
  3. Súbelo y prueba el sitio de inmediato. Si algo se rompió, restaura el respaldo.

Cuarta hora: HTML

  1. Agrega width y height a cada <img>.
  2. Pon loading="lazy" a todas las imágenes menos la del banner.
  3. A la del banner, ponle fetchpriority="high" y un preload.
  4. Escribe alt descriptivos donde falten.

Al final: volver a medir

Corre PageSpeed Insights otra vez y compara. Los datos de campo — los de usuarios reales — tardan unos 28 días en actualizarse, así que ten paciencia con esos. Los de laboratorio cambian de inmediato.

Cierre

La velocidad web no es un problema de dinero, es un problema de atención al detalle. Casi todo lo que hace lento a un sitio típico — imágenes gigantes sin comprimir, cero caché, cero compresión, quince scripts de terceros — se arregla con herramientas gratuitas y una tarde de trabajo.

Y lo mejor: a diferencia del link building o del contenido, esto es determinista. Comprimes una imagen de 4 MB a 180 KB y esa mejora existe, es real, es medible, y no depende de que a un algoritmo le caigas bien.

Ahora ve a revisar cuánto pesa la foto de tu página principal. Te va a sorprender.

📚 ¿Quieres el mapa completo del terreno? Todo sobre SEO en una página.

Bibliografía

  1. theartofseo.txtThe Art of SEO (Enge, Spencer, Stricchiola). Capítulo 7, "Developing an SEO-Friendly Website": Core Web Vitals y LCP (pp. 358–360), el riesgo de empeorar el CLS al eliminar recursos que bloquean el render (pp. 358–359), herramientas de medición (pp. 366–367), configuración de servidor y compresión gzip (p. 368), caché y elección de plataforma (p. 368), CDNs y desfragmentación de base de datos (p. 369), scripts de terceros y el límite de tres herramientas de analítica (pp. 369–370), RewriteBase, negación en expresiones regulares y uso del 301 (pp. 289–293). Capítulo 12, "Vertical, Local, and Mobile SEO": nombres de archivo y atributo alt (pp. 596–598), advertencia sobre lazy loading asíncrono y sitemaps de imágenes (p. 597), elemento <picture> con respaldo, proporciones 1×1, 4×3 y 16×9, tipos de schema asociados, y advertencia sobre hotlinking y robots.txt bloqueando imágenes (p. 598).
  2. seoallinone.txtSEO All-in-One For Dummies (Clay, Esparza). Libro 4, Capítulo 3, "Page Experience Update", pp. 255–256: Core Web Vitals, cómo arreglar LCP y CLS, eliminación de recursos que bloquean el render, hosting como cuello de botella, caché del navegador y auditoría de LCP y waterfall en GTmetrix. Libro 5, "Creating Content", pp. 329–330: longitud del atributo alt (guía de 12 palabras), por qué redimensionar con CSS no reduce el archivo enviado, y la recomendación de poner las imágenes muy grandes en página aparte con thumbnail. Libro 7, "Optimizing the Foundations": factores de velocidad y compresión gzip (pp. 519–520), .htaccess y sus advertencias sobre archivo oculto, formato UNIX, línea final y riesgo de tumbar el sitio (pp. 563–567), y mod_rewrite (p. 583).
  3. SEOWarrior.txtSEO Warrior (John I. Jerkovic). Capítulo 8, "Search Engine Traps": trampas de rendimiento del sitio, beneficios de la compresión del servidor web, la alternativa por PHP con ob_gzhandler y la configuración de zlib.output_compression, la técnica del snapshot estático con wget y cron, y la advertencia sobre páginas de error crípticas que terminan indexadas.
  4. SEJ_On-Page-SEO_eBook_Final_2021A.pdfThe Complete Guide to On-Page SEO (Search Engine Journal), pp. 210–226: los doce consejos de optimización de imágenes. Elección de formato y la advertencia sobre JPG dentro de SVG en línea (p. 211), compresión y el dato de HTTP Archive sobre el 21% del peso de página (p. 212), imágenes propias frente a stock (pp. 214–215), nombres de archivo y estructura de carpetas como factor de ranking (pp. 216, 220), texto alt y su requisito de accesibilidad (pp. 218–219), width y height contra el CLS y su obligatoriedad en AMP y PWAs (p. 222), imágenes responsivas con srcset y el formato del atributo (p. 223), y sitemaps de imágenes (p. 224).
  5. SEJ_LocalSEO-Feb2022.pdfLocal SEO: The Definitive Guide (Search Engine Journal), p. 75: codificación HTML y CSS de alta calidad y su efecto en reducir el tiempo de renderizado.
  6. Search-Engine-Optimization-SEO-Secrets.txtSEO Secrets (Danny Dover), p. 358: errores comunes de canonicalización y redirecciones 301 en Apache; informe de tiempo de descarga de páginas.
  7. Inbound_Marketing_and_SEO_Insights_from_the_Moz_Blog.pdf — p. 279: informes de velocidad del sitio en analítica y su relación con conversiones y posiciones.
  8. Google Search Central / web.dev — Anuncio oficial del reemplazo de First Input Delay (FID) por Interaction to Next Paint (INP) como Core Web Vital, efectivo el 12 de marzo de 2024. Fuente consultada en línea, ya que este cambio es posterior a la publicación de todos los libros citados arriba.

Agregar comentario

* Información requerida
1000
Arrastrar y soltar imágenes (max 3)
What is the opposite word of weak?
Imagen captcha

Comentarios

Sin comentarios aún. ¡Sé el primero!