WordPress y Core Web Vitals - Optimización real para SEO
Google penaliza sitios lentos. Tu WordPress probablemente es lento.
El problema
Cliente con WordPress:
- LCP: 4.2s (malo, debería ser <2.5s)
- FID: 180ms (malo, debería ser <100ms)
- CLS: 0.25 (malo, debería ser <0.1)
Google Search Console mostraba “Poor Core Web Vitals”. Rankings cayendo.
Core Web Vitals explicados
LCP (Largest Contentful Paint): Tiempo hasta que el contenido principal es visible.
FID (First Input Delay): Tiempo hasta que la página responde a interacción.
CLS (Cumulative Layout Shift): Cuánto “salta” el contenido mientras carga.
Diagnóstico
# PageSpeed Insights
https://pagespeed.web.dev/
# Lighthouse en Chrome DevTools
F12 → Lighthouse → Analyze
# Web Vitals extension
Chrome Web Store → Web Vitals
Problemas encontrados:
- Imágenes sin lazy load ni dimensiones
- JavaScript bloqueante
- Fonts cargando tarde
- Sin caché de servidor
- Hosting lento
Optimización 1: Imágenes
Lazy loading nativo
// functions.php
// WordPress 5.5+ tiene lazy loading automático
// Pero asegurarse de que está habilitado:
add_filter('wp_lazy_loading_enabled', '__return_true');
Dimensiones explícitas (evita CLS)
// Asegurar que imágenes tienen width/height
add_filter('wp_get_attachment_image_attributes', function($attr, $attachment) {
if (!isset($attr['width']) || !isset($attr['height'])) {
$metadata = wp_get_attachment_metadata($attachment->ID);
if ($metadata) {
$attr['width'] = $metadata['width'];
$attr['height'] = $metadata['height'];
}
}
return $attr;
}, 10, 2);
WebP automático
# Instalar plugin: WebP Express o ShortPixel
# Convierte imágenes a WebP automáticamente
Preload de LCP image
// Preload de la imagen hero
add_action('wp_head', function() {
if (is_front_page()) {
echo '<link rel="preload" as="image" href="' . get_theme_file_uri('/images/hero.webp') . '">';
}
}, 1);
Resultado LCP: 4.2s → 2.1s
Optimización 2: JavaScript
Diferir scripts no críticos
// functions.php
add_filter('script_loader_tag', function($tag, $handle, $src) {
$defer_scripts = ['jquery-migrate', 'wp-embed', 'comment-reply'];
if (in_array($handle, $defer_scripts)) {
return str_replace(' src', ' defer src', $tag);
}
return $tag;
}, 10, 3);
Eliminar jQuery si no es necesario
// Si tu tema no necesita jQuery
add_action('wp_enqueue_scripts', function() {
if (!is_admin()) {
wp_deregister_script('jquery');
}
}, 100);
Inline critical CSS
// Inline CSS crítico para above-the-fold
add_action('wp_head', function() {
?>
<style id="critical-css">
/* CSS mínimo para renderizar above the fold */
body { margin: 0; font-family: system-ui, sans-serif; }
.header { background: #fff; padding: 1rem; }
.hero { min-height: 50vh; }
/* ... resto de CSS crítico */
</style>
<?php
}, 1);
// Cargar resto de CSS de forma asíncrona
add_filter('style_loader_tag', function($tag, $handle) {
if ($handle === 'theme-style') {
return str_replace(
"rel='stylesheet'",
"rel='preload' as='style' onload=\"this.onload=null;this.rel='stylesheet'\"",
$tag
);
}
return $tag;
}, 10, 2);
Resultado FID: 180ms → 45ms
Optimización 3: Fonts
Preconnect a Google Fonts
add_action('wp_head', function() {
echo '<link rel="preconnect" href="https://fonts.googleapis.com">';
echo '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>';
}, 1);
Font-display: swap
// Si usas Google Fonts
add_filter('style_loader_tag', function($tag, $handle) {
if (strpos($handle, 'google-fonts') !== false) {
return str_replace('&display=auto', '&display=swap', $tag);
}
return $tag;
}, 10, 2);
Self-host fonts (mejor opción)
/* style.css - Fonts locales */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2');
font-weight: 100 900;
font-display: swap;
}
Optimización 4: Caché
Page caching con WP Super Cache
// wp-config.php
define('WP_CACHE', true);
Configuración:
Settings → WP Super Cache
→ Caching: ON
→ Cache Delivery Method: Expert
→ Preload: Enable
Object caching con Redis
# Instalar Redis
sudo apt install redis-server
# Plugin: Redis Object Cache
wp plugin install redis-cache --activate
wp redis enable
// wp-config.php
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
Browser caching via .htaccess
# .htaccess
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\.(ico|pdf|jpg|jpeg|png|webp|gif|js|css|woff2)$">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>
</IfModule>
Optimización 5: Hosting
Problema
Hosting compartido barato: TTFB de 800ms.
Solución
Migrar a hosting optimizado para WordPress:
- Cloudways (DigitalOcean)
- Kinsta
- WP Engine
O usar CDN:
Cloudflare (gratis):
- CDN global
- Caché de assets
- HTTP/3
- Brotli compression
Resultado TTFB: 800ms → 120ms
Optimización 6: CLS específico
Reservar espacio para ads
.ad-container {
min-height: 250px; /* Altura del ad */
background: #f0f0f0;
}
Reservar espacio para imágenes
.image-container {
aspect-ratio: 16 / 9;
background: #f0f0f0;
}
Evitar inserción dinámica de contenido
// MAL: Insertar contenido arriba que empuja todo
document.body.insertBefore(newElement, document.body.firstChild);
// BIEN: Insertar al final o en contenedor reservado
document.getElementById('dynamic-content').appendChild(newElement);
Resultado CLS: 0.25 → 0.05
Monitoreo continuo
Google Search Console
Search Console → Core Web Vitals
→ Ver URLs con problemas
→ Monitorear mejoras
Real User Monitoring (RUM)
// Enviar métricas reales a Google Analytics
add_action('wp_footer', function() {
?>
<script>
// Web Vitals library
import {onLCP, onFID, onCLS} from 'web-vitals';
function sendToAnalytics({name, value, id}) {
gtag('event', name, {
event_category: 'Web Vitals',
value: Math.round(name === 'CLS' ? value * 1000 : value),
event_label: id,
non_interaction: true,
});
}
onLCP(sendToAnalytics);
onFID(sendToAnalytics);
onCLS(sendToAnalytics);
</script>
<?php
});
Resultados finales
| Métrica | Antes | Después | Objetivo |
|---|---|---|---|
| LCP | 4.2s | 1.8s | <2.5s ✅ |
| FID | 180ms | 45ms | <100ms ✅ |
| CLS | 0.25 | 0.05 | <0.1 ✅ |
| TTFB | 800ms | 120ms | <200ms ✅ |
Impacto SEO:
- Rankings: +15 posiciones promedio
- Tráfico orgánico: +40%
- Bounce rate: -25%
Checklist de optimización
- Lazy load en imágenes
- Dimensiones explícitas en imágenes
- Formato WebP
- Preload de LCP image
- JavaScript diferido
- Critical CSS inline
- Fonts con display:swap
- Page caching habilitado
- Object caching (Redis)
- CDN configurado
- Espacio reservado para ads
- Monitoreo RUM activo
¿Has optimizado Core Web Vitals en WordPress? ¿Qué técnicas te dieron mejores resultados?
Por Vicente José Moreno Escobar el
20 de
agosto
de
2024
Puedes disfrutar de otros artículos como éste en el archivo del sitio.