Hardening, rendimiento y SEO de WordPress: lo que de verdad mueve la aguja en 2026
No existe una guía definitiva de WordPress. Quien le venda una, le está vendiendo un listicle. Lo que sigue es una checklist de profesional con los cambios que mueven la aguja en proyectos reales de cliente en wppoland.com, ordenada en tres planos que se entrelazan más de lo que admiten la mayoría de artículos: hardening, peso de página y cómo motores de búsqueda y LLMs realmente parsean el resultado.
El patrón es casi siempre el mismo. Un sitio español llega con un cementerio de plugins, una tabla wp_options sin auditar, tres plugins SEO peleándose por la etiqueta <title>, y un /wp-login.php que recibe 200 POSTs por minuto desde IPs residenciales rotativas. Nada de esto se arregla con una checklist genérica. Se arregla sabiendo qué constantes en wp-config.php, qué reglas de Cloudflare y qué decisiones de schema devuelven tiempo y rankings, y qué es teatro de cumplimiento.
Lo que este post no es
No es documentación de referencia exhaustiva. El documento canónico de hardening vive en wordpress.org/documentation/article/hardening-wordpress/ y es más completo que cualquier post de blog. Lo que este post añade es opinión: qué subconjunto de esos controles vale la pena implementar primero, en qué orden, y dónde el típico artículo de “best practices” salta calladamente el detalle doloroso, por ejemplo el plazo de 72 horas de la AEPD para notificar una brecha de datos según el RGPD Art. 33 y la LOPDGDD.
Si gestiona un sitio escaparate en hosting compartido, la mitad de las recomendaciones de abajo es excesiva. Si gestiona un WooCommerce con precios para B2B autenticado e integración Bizum o Redsys, la mitad es lo mínimo.
Hardening que se paga solo
La mayoría de incidentes WordPress que he limpiado se reducen a una de tres cosas: un plugin viejo con CVE conocida, una contraseña de admin reutilizada de un servicio filtrado, o un endpoint XML-RPC o REST abierto a enumeración. Casi nada se debe a un plugin de seguridad ausente. La implicación: hardening es sobre todo configuración, y un puñado de constantes en wp-config.php hacen más por el modelo de amenaza que cualquier suite “todo en uno”.
El bloque wp-config.php que pongo en cada instalación
define( 'DISALLOW_FILE_EDIT', true );
define( 'DISALLOW_FILE_MODS', true );
define( 'FORCE_SSL_ADMIN', true );
define( 'WP_AUTO_UPDATE_CORE', 'minor' );
define( 'AUTOMATIC_UPDATER_DISABLED', false );
define( 'WP_POST_REVISIONS', 5 );
define( 'EMPTY_TRASH_DAYS', 7 );
DISALLOW_FILE_EDIT retira el editor de código del escritorio, y es la reducción de radio de explosión más útil que existe. DISALLOW_FILE_MODS va más lejos y bloquea instalaciones y actualizaciones de plugins y temas desde el escritorio por completo; combínelo con un pipeline de despliegue que actualice vía WP-CLI o Composer. FORCE_SSL_ADMIN evita el caso vergonzoso de que alguien acceda brevemente a http:// admin y filtre una cookie de sesión. Los límites de revisiones y papelera no son seguridad en sí, pero impiden que wp_posts y wp_postmeta se conviertan en la query lenta que enmascara un incidente real.
Application passwords, 2FA y una salida CLI
Application passwords se activaron por defecto en WordPress 5.6 y casi nadie las audita. Ejecute wp user application-password list <user> para cada administrador en cada revisión trimestral. Revoque todo lo que no se corresponda con una integración documentada. Trate cualquier application password ligada a un usuario con manage_options como equivalente a la credencial principal de ese usuario.
Para 2FA, el plugin Two-Factor sigue siendo la opción más limpia, pero configúrelo dando por hecho que un teléfono se acabará perdiendo. Documente la ruta de recuperación: SSH al servidor y wp user meta delete <id> _two_factor_* para eliminar el segundo factor, después rote la contraseña inmediatamente. Si se salta este paso, dejará al cliente fuera de su propia producción en un momento que siempre es inoportuno, típicamente la tarde antes del Black Friday o de subir el modelo Verifactu a la AEAT.
Saque la pelea contra brute force fuera de PHP
PHP es el peor sitio para gestionar un flood en /wp-login.php. Cuando wp-login.php decide que una petición es mala, ya ha quemado CPU haciendo bootstrap de WordPress. El rate limit pertenece una capa más arriba.
En Cloudflare, una regla de Rate Limiting que permita diez POSTs a /wp-login.php cada diez minutos por IP, combinada con un managed challenge para la misma ruta desde geografías fuera de la UE si su público es regional, elimina más del 95% del tráfico de credential stuffing sin tocar el origin. Si su stack corre ModSecurity (común en Webempresa, Raiola Networks, Dinahosting y SiteGround Iberia), OWASP Core Rule Set en paranoia level 1 con xmlrpc.php bloqueado de raíz es la base. Paranoia 2 empieza a generar falsos positivos sobre el JSON de bloques Gutenberg, así que no salte sin probar el editor en staging.
AEPD, RGPD y el registro de consentimientos
Un punto que las guías anglófonas saltan: el RGPD Art. 33 obliga a notificar a la AEPD en 72 horas tras una brecha de datos, y sin un log de consentimientos que sobreviva a una limpieza de incidente queda sin prueba documental. Mantenga una tabla wp_consent_log separada de wp_options, con timestamp, IP hasheada y versión de política. Para hardening de pagos Bizum y Redsys, el callback debe validar la firma HMAC contra la clave de comercio; sin eso un atacante puede falsificar una confirmación de pago y marcar un pedido como pagado sin que el cliente complete el cargo. Si emite facturas certificadas conforme a Verifactu o TicketBAI, separe la pasarela de facturación del frontend en un Worker dedicado para evitar que un compromiso del tema afecte la integridad de los registros de la AEAT.
Permisos de archivos, en breve
Directorios 755, archivos 644, wp-config.php 440 o 400 y propiedad del usuario bajo el que corre PHP-FPM, no root. Si su hosting insiste en 777 en algún sitio, cambie de hosting. No estamos en 2008.
SEO que sobrevive al contacto con la realidad
La conversación sobre SEO en WordPress lleva una década atrancada en permalinks y alt text. Ambos siguen importando, pero no son lo que separa a un sitio que rankea de uno que no en 2026. Las cuatro cosas que veo mover rankings en sitios de cliente: un grafo Schema.org coherente, un plugin SEO configurado para una sola tarea en lugar de pelearse con otro, hreflang hecho correctamente para builds multilingüe, y una sitemap con prioridades alineadas con lo que importa al negocio.
Schema como grafo, no como checklist
La mayoría de plugins SEO emiten una lista plana de bloques JSON-LD desconectados: una Organization aquí, un Article allá, un BreadcrumbList que no referencia ninguno. Motores de búsqueda y LLMs premian un grafo conectado: Article cuyo author es una Person cuyo worksFor es la Organization cuyo logo referencia el WebSite. Tanto Yoast como Rank Math soportan esto a través de sus filtros; el trabajo está en definir el grafo una vez y alimentar tanto las páginas de usuario como los crawlers de LLM con un set consistente de referencias @id. Si los campos about y mentions del front-matter ya tienen URLs de Wikidata, la mitad del trabajo está hecho.
Para tiendas españolas con facturación certificada Verifactu o TicketBAI, una schema Invoice ligada a la Organization por @id aporta tracción adicional en AI Overviews ante consultas sobre procedimiento ante la AEAT.
Yoast vs Rank Math: elija uno y desactive el otro por completo
El patrón de colisión más habitual son dos plugins SEO ambos escribiendo <title> y <meta name="description">, donde gana el que corre último, pero ambos dejan su schema en <head>. Síntoma: BreadcrumbList duplicado, WebPage duplicada, bloques Article en conflicto. Google fusiona lo que puede y descarta el resto, pero la señal queda turbia. Elija uno, desactive el otro, después revise el HTML renderizado por schema obsoleta cacheada en object cache o page cache. Vacíe ambos tras la migración.
Rank Math suele ganar en flexibilidad de schema, Yoast en el análisis opinado de contenido que los autores leen de verdad. Ninguno importa más que la consistencia de usar uno solo.
Hreflang para los builds en seis idiomas
Si gestiona un sitio multilingüe (típico en España: ES más CA o GL para mercados regionales, ES más EN para exportación), hreflang es la diferencia entre que Google sirva la versión es-ES a lectores españoles y que sirva la es-MX a un cliente que después reboté por el formato del IVA. Las anotaciones deben ser recíprocas (cada alternate debe listar todos los demás incluyéndose a sí mismo), apuntar a URLs canónicas e incluir x-default. Plugins lo manejan, pero verifique en Search Console bajo International Targeting; los errores silenciosos de hreflang tras un cambio de slug son comunes.
Prioridades de sitemap, default de WordPress vs lo que quiere
El core entrega /wp-sitemap.xml, suficiente para sitios pequeños e insuficiente para todo lo demás porque no permite ponderar ni excluir. Yoast y Rank Math publican /sitemap_index.xml con índices separados por post type, y eso es lo que quiere. El movimiento no obvio: excluya el post type attachment de la sitemap salvo que la mediateca sea el producto. URLs de attachment generadas por subidas de imagen no necesitan estar en el índice de Google; diluyen el crawl budget en sitios grandes y producen soft 404 de thin content en sitios pequeños.
Rendimiento: dónde se va el tiempo de verdad
La mayoría de tickets “WordPress va lento” que abro acaban siendo una de cuatro cosas, más o menos en este orden: wp_options autoload hinchado, una fuente externa en el camino crítico, una imagen hero sobredimensionada sin fetchpriority, y un plugin de cache entregando la cache key incorrecta para usuarios autenticados. El hosting importa, pero rara vez es el cuello de botella si las cuatro anteriores están mal.
Pode primero el autoload de wp_options
Es el cambio de rendimiento con más palanca en WordPress, y casi nadie lo corre de forma planificada. Cada page load lanza SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes', y en un sitio que ha acumulado cinco años de detritus de plugins esa query puede devolver tres o cuatro megabytes. Sesenta a ochenta por ciento de esas filas son típicamente transients dejados por plugins desinstalados o settings que no tenían nada que estar en autoload.
wp db query "SELECT option_name, LENGTH(option_value) AS size FROM wp_options WHERE autoload='yes' ORDER BY size DESC LIMIT 30"
Todo lo que pase de 100KB y no esté en uso activo se vuelve candidato. wp option set <name> --autoload=no para cosas que quiere conservar pero rara vez lee; filas huérfanas de plugins, borrar directamente. En una intervención reciente sobre WooCommerce para una tienda madrileña, una sola pasada bajó el TTFB de 880ms a 310ms sin tocar código.
Object cache, no solo page cache
Page caching resuelve el caso del visitante anónimo. Object caching resuelve el usuario autenticado, WooCommerce y los pantallazos de admin, que es donde vive el camino de conversión real. Redis vía el módulo PECL oficial más el plugin Redis Object Cache es la respuesta aburrida y correcta.
Verifique que está trabajando: wp redis status debe mostrar hit ratio por encima del 90% en un sitio caliente. Por debajo, o la política de eviction está mal (allkeys-lru es la correcta) o algo está llamando a wp_cache_flush() con más agresividad de la cuenta.
Cloudflare: Page Rules vs Workers para /wp-json
Para HTML estático, basta una Cache Rule que cachee (http.host eq "ejemplo.es" and not http.request.uri.path contains "/wp-admin" and not http.cookie contains "wordpress_logged_in_") durante una hora. El caso difícil es /wp-json para sitios headless o parcialmente headless. Page Rules no varía limpiamente sobre headers de autenticación, así que si está cacheando el REST API para tráfico anónimo, hágalo en un Worker que haga bypass explícito sobre Authorization y Cookie: wordpress_logged_in_* y respete Cache-Control: private. La cantidad de sitios que entregan datos de usuario autenticado a anónimos porque cachearon /wp-json/wp/v2/users en el edge es deprimente.
Imágenes: lazy por defecto, eager donde cuenta
WordPress 5.5+ añade loading="lazy" automáticamente, lo que es correcto para todo bajo el fold y erróneo para el elemento LCP. La imagen hero de una landing debe llevar fetchpriority="high" y explícitamente loading="eager". La implementación más simple es un pequeño filtro sobre wp_get_attachment_image_attributes que invierta ambos atributos cuando el ID del attachment coincide con la featured image y el contexto es la plantilla singular.
AVIF primero, WebP fallback, JPEG solo como último recurso. Sirva desde el mismo origin si puede; cross-origin image fetches siguen costando un TLS handshake incluso en HTTP/3.
Critical CSS y la cuestión de las fuentes
Inline el CSS above-the-fold para la home y cualquier landing de tráfico alto. Critters o los extractors basados en Penthouse lo hacen bien; para WordPress en concreto, un Cloudflare Worker que inyecte el critical CSS extraído en <head> y diferir el stylesheet completo es el camino de menor resistencia si no controla la build pipeline.
Para fuentes: self-host. font-display: swap no es negociable. Un único subset WOFF2 de 30KB suele batir lo que Google Fonts pueda servir, y elimina un DNS lookup de tercero del camino crítico. Para sitios españoles el subset latin-ext debe cubrir á, é, ó, ñ, ¿ y ¡; sin eso el primer paint muestra un fallback con huecos glíficos.
Qué hacer mañana por la mañana
Si esta lista resulta abrumadora, el orden en que la trabajaría en un proyecto real:
- Suelte el bloque de constantes en
wp-config.phpy verifique que el editor del escritorio ha desaparecido. - Corra la query de autoload en
wp_optionsy pode todo lo que pase de 100KB y no justifique su peso. - Audite las application passwords con
wp user application-password listpara cada administrador. - Empuje el rate limiting de
/wp-login.phpa Cloudflare. - Elija un plugin SEO, desactive el otro, después revise el HTML renderizado en busca de schema huérfana.
- Arregle la imagen LCP con
fetchpriority="high"y haga self-host de las fuentes. - Confirme que el log de consentimientos RGPD vive fuera de
wp_optionsy tiene formato exportable para solicitudes de acceso AEPD.
La lista completa de arriba es un sprint, no una tarde. Quien venda un arreglo de una hora para los cuatro planos, está vendiendo un listicle.
Recursos relacionados
- Desarrollo WordPress profesional - Implementación de mejores prácticas
- Mantenimiento WordPress - Soporte continuo para su sitio
- Optimización de velocidad - Core Web Vitals perfectos
- Auditoria de seguridad - Protección empresarial
- SEO, GEO y AEO - Visibilidad en motores de búsqueda y búsqueda por IA


