<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">

<channel>
	<title>Ayuda WordPress</title>
	<atom:link href="https://ayudawp.com/feed/" rel="self" type="application/rss+xml"/>
	<link>https://ayudawp.com</link>
	<description>Recursos, temas, plugins, tutoriales en español</description>
	<lastBuildDate>Fri, 25 Sep 2026 15:15:15 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://ayudawp.com/wp-content/uploads/2026/05/cropped-ayuda-wordpress-32x32.png</url>
	<title>Ayuda WordPress</title>
	<link>https://ayudawp.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<xhtml:meta content="noindex" name="robots" xmlns:xhtml="http://www.w3.org/1999/xhtml"/><item>
		<title>Un clic para comprometer tu web, Google sujetándose el cubata y la autoprotección de Vigilante #CrónicasWordPress #DoctorWordPress</title>
		<link>https://ayudawp.com/un-clic-para-comprometer-tu-web-google-sujetandose-el-cubata-y-la-autoproteccion-de-vigilante-cronicaswordpress-doctorwordpress/</link>
					<comments>https://ayudawp.com/un-clic-para-comprometer-tu-web-google-sujetandose-el-cubata-y-la-autoproteccion-de-vigilante-cronicaswordpress-doctorwordpress/#respond</comments>
		
		<dc:creator><![CDATA[Fernando Tellado]]></dc:creator>
		<pubDate>Fri, 25 Sep 2026 15:15:15 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Vídeos]]></category>
		<category><![CDATA[#CrónicasWordPress]]></category>
		<category><![CDATA[#DoctorWordPress]]></category>
		<category><![CDATA[#TrucosWordPress]]></category>
		<guid isPermaLink="false">https://ayudawp.com/?p=160420</guid>

					<description><![CDATA[Semana cargadita la que te traigo. El lunes, en las Crónicas, hubo actualización de seguridad de WordPress, un lío muy feo con Rank Math y Google empeñado en romper lo poco que le queda sano al buscador. El miércoles, en Doctor WordPress, te enseñé por dentro la autoprotección que he metido en Vigilante 3.0, con todos los casos raros que he estado probando durante meses (que no han sido pocos).]]></description>
										<content:encoded><![CDATA[<p>Semana cargadita la que te traigo. El lunes, en las Crónicas, hubo actualización de seguridad de WordPress, un lío muy feo con Rank Math y Google empeñado en romper lo poco que le queda sano al buscador. El miércoles, en Doctor WordPress, te enseñé por dentro la autoprotección que he metido en Vigilante 3.0, con todos los casos raros que he estado probando durante meses (que no han sido pocos).</p>
<p>Te lo resumo todo aquí, por si no pudiste verlo en directo o prefieres leerlo con un café.</p>
<h2>Crónicas WordPress: WordPress 7.1.1, el lío de Rank Math y Google pisando el acelerador hacia el abismo</h2>
<h3>Seguridad: WordPress 7.1.1 y una semana de agujeros gordos</h3>
<p>WordPress 7.1.1 salió el 17 de septiembre y es, sobre todo, una versión de seguridad. Corrige 11 vulnerabilidades, además de 17 fallos en el núcleo y casi 20 en Gutenberg, entre ellos un XSS almacenado bastante serio. <strong>Si todavía no has actualizado, ya estás tardando.</strong></p>
<p>Me hizo gracia que Anthropic, la empresa de Claude, aparezca acreditada en dos de esas 11 vulnerabilidades. Ya empieza a ser lo normal, y hasta en GitHub queda reflejado cuando ha participado una IA en encontrar o arreglar algo.</p>
<p>En esta versión entra también un arreglo que reporté yo. El mapa del sitio nativo de WordPress devolvía un error 404 en las webs que no tienen entradas (solo páginas, productos y esas cosas, sin blog), cuando debería devolver un 200. Lo avisé, lo arreglaron y ha colado en la 7.1.1. Yo creo que merecía una versión grande, pero oye, entró.</p>
<p>Lo más gordo de la actualización es el cierre de Click to Shell, una cadena de ejecución remota de código. Parece un titular exagerado de web de seguridad, pero aquí es literal, porque <strong>con un solo clic en un enlace que parecía inofensivo te podían comprometer la web entera</strong>, sin necesidad de tener cuenta de usuario.</p>
<p>Y luego está lo de Rank Math, el plugin de SEO con más de 4 millones de instalaciones. Generaba automáticamente una contraseña de aplicación que les daba acceso al administrador de tu web, sin preguntarte, la enviaba a los servidores de la empresa (la misma que está detrás de WP Rocket) y no había forma de desactivarlo ni desde el propio plugin. Se denunció y lo han retirado.</p>
<p>Matt Mullenweg se ha cabreado, y esta vez con razón, así que ha pedido auditorías de seguridad obligatorias para cualquier plugin que pida acceso de administrador. Ya se está viendo cómo implementarlo. Quien dio la voz de alarma en agosto fue el desarrollador de The SEO Framework, que es competencia directa y lo que tú quieras, pero tiene razón y hay que dársela.</p>
<p>Mi opinión, aunque a nadie le importe. No puede ser que estemos hablando de un agujero que con un clic te compromete la web y que encima un plugin de SEO te abra la puerta de atrás por su cuenta. <strong>Para mí Rank Math se ha terminado.</strong> Les tenía cierto criterio como plugin de SEO, pero esto no se lo perdono ni medio.</p>
<p>Hubo más sustos:</p>
<ul>
<li><strong>The Events Calendar:</strong> el plugin de eventos más conocido, con unas 600.000 instalaciones, tenía tres vulnerabilidades de nivel 9,8 (de lo más tocho que hay) por un vector muy poco corriente, los comentarios con bloques de Gutenberg mal saneados. El atacante podía restablecer la contraseña del administrador y quedarse con tu web. Si tienes una versión anterior a la 6.17.4.1, actualiza ya.</li>
<li><strong>WooCommerce Wholesale Lead Capture:</strong> un plugin para mayoristas con unas 6.000 instalaciones que, hasta la versión 2.0.3.1, permitía subir archivos sin validar mediante AJAX y sin identificarse. Son pocas instalaciones, pero ya se han detectado muchos intentos de explotarlo, y eso sí es grave.</li>
</ul>
<p>Cerré la sección con una noticia mía, el lanzamiento de <a href="https://wordpress.org/plugins/vigilante/">Vigilante 3.0</a>. La novedad gorda es que el plugin se autoprotege, porque ¿qué hay peor que te ataquen con un plugin cualquiera? Pues que te ataquen a través del propio plugin de seguridad, que se supone que está para evitarlo. Como el miércoles dediqué el directo entero a esto, te lo cuento más abajo.</p>
<h3>Comunidad: GatherPress sustituye a Meetup, formación para periodistas y un mercado de negocios WordPress</h3>
<p>GatherPress nació en 2018, en un viaje de vuelta de una WordCamp de esos de un montón de horas, cuando alguien se preguntó por qué WordPress dependía de un servicio comercial como Meetup.com. Se subió como plugin al directorio oficial, se ha ido probando con grupos de varios países y este verano la Fundación WordPress lo ha anunciado como sustituto oficial de Meetup. Ya está en fase de pruebas en events.wordpress.org, y la fundación se ahorrará unos 200.000 dólares al año, que se dice pronto. <strong>La idea me parece cojonuda, lo que no me lo parece tanto es lo que se ha tardado en hacerle caso.</strong></p>
<p>El Colegio Profesional de Periodistas de Andalucía ha lanzado más de 100 horas de formación para sus colegiados, y he tenido el gusto de que me incluyan. Me toca impartir el bloque de inteligencia artificial para WordPress, porque WordPress sigue siendo imprescindible, pero con IA se puede mejorar muchísimo. Si eres periodista y estás colegiado en Andalucía, apúntate, que creo que para vosotros es gratis.</p>
<p>También ha aparecido <a href="https://wpacquire.com" target="_blank" rel="nofollow noopener">WP Acquire</a>, un mercado para comprar y vender negocios basados en WordPress (plugins, temas, tiendas o webs). Publicar el anuncio cuesta 50 dólares, no cobran comisión y el vendedor se queda con el 100 % de la venta. Lo veo como un síntoma de madurez del sector, así que si te planteas vender algo, échale un ojo.</p>
<h3>Desarrollo: lo que trae WordPress 7.2 y WooCommerce subiendo el listón de PHP</h3>
<p>WordPress 7.2 está previsto para diciembre de 2026, así que será la última versión del año. En seguridad trae bastante:</p>
<ul>
<li>Una especie de modo sudo (para los que venís de Linux) que te pide volver a identificarte para las acciones sensibles.</li>
<li>Una API de secretos, la Secrets API.</li>
<li>Un refuerzo de las contraseñas de aplicación, que llevaban tiempo en barbecho (y a la vista de lo de Rank Math, falta hacía).</li>
</ul>
<p>Además, el editor del sitio se podrá ampliar desde plugins con DataViews y DataForms, de lo que vamos a hablar mucho pronto. El bloque de tabla de contenidos pasa a estable, llega algún bloque nuevo que ya veremos en directo con calma y los Dashicons de toda la vida dejan paso a iconos SVG. No es para volverse loco, es una renovación, pero ya hay gente quejándose del icono nuevo, porque somos así de tocapelotas.</p>
<p>Y ojo, que <strong>nos despedimos de los temas «Twenty» después de 16 años</strong>. El nuevo tema por defecto se llamará Ipsum (como el Lorem Ipsum) y ya se puede descargar desde GitHub, que ahora todo va a GitHub (a mí no me gusta nada, pero a todo el mundo le encanta). Es minimalista, pensado para blogs, muy centrado en la accesibilidad y con varias tipografías y variaciones de estilo. Aparte saldrá otro tema, Metis, bastante más vistoso, que no vendrá integrado.</p>
<p>También se ha abierto la llamada a pruebas de DataForms para las pantallas de ajustes. Algo se va a notar a la vista, pero la mejora de verdad está en el rendimiento.</p>
<p>WooCommerce, por su parte, resucita Purple, su tema de bloques, en beta pública. Lo quitaron en julio de 2025 y ahora vuelve con muchas funciones que normalmente pedirían plugins, ya integradas en bloques. En WordPress.com ya es el tema por defecto, y no creo que tarde mucho en sustituir a Storefront como el tema que te sugiere WooCommerce al instalarlo.</p>
<p>La noticia de WooCommerce que más me preocupa es otra, porque <strong>va a subir el mínimo de PHP de la 7.4 a la 8.1</strong>, y poco después a la 8.3. Conozco montones de tiendas que siguen en PHP 7.4, no por WooCommerce ni por WordPress, sino por algún plugin concreto que casca en cuanto subes de versión. La 7.4 ya no tiene soporte ni actualizaciones de seguridad, así que o pones al día esos plugins o te quedas sin poder actualizar WooCommerce. Yo apuntaría como mínimo a la 8.2, y lo ideal sería la 8.3.</p>
<p>Y ya que hablamos de WooCommerce, me pidió mi amigo Jordan Suárez un tutorial sobre impuestos, que es de lo más cansino y raro que tiene WooCommerce, y resulta que no lo tenía. Pues ya la tienes, la <a href="[ENLAZAR:%20gu%C3%ADa%20de%20impuestos%20en%20WooCommerce]">guía para configurar los impuestos en WooCommerce</a>. Son unos 30 minutos de lectura, así que no es para leerla de un tirón, es para guardarla y tirar de ella cuando te surja una duda. Gratis, como siempre, y sin publicidad que moleste.</p>
<h3>IA: un curso gratis de Learn WordPress</h3>
<p>Esta semana había muchas noticias de IA en WordPress, pero casi todo me pareció relleno, y si a mí me aburre, a ti ni te cuento. Me quedo con una. En Learn WordPress han publicado un curso gratuito de unas 9 horas sobre la IA integrada en WordPress desde la 7.0. Tiene cuatro módulos, casi todos sobre gestión de contenidos y la integración con Claude y ChatGPT. No es nada técnico, es online y lo haces cuando quieras, así que no tiene pega.</p>
<h3>SEO: Google, sujétame el cubata</h3>
<p>Google ha descubierto, llámame loco, que si sus vistas previas con IA siguen resumiendo el contenido sin mandar clics, se puede quedar sin contenido original. Porque las IA no crean contenido original, reciclan, hacen refritos y resúmenes de lo que ya existe. Así que ahora plantea pagar a los editores cuando su contenido alimenta esas respuestas, con un programa piloto que empezará, cómo no, en Estados Unidos. Donde más sentido tendría es entre los pequeños y medianos editores, los blogueros, que somos los que de verdad alimentamos todo esto. <strong>Que paguen por el trabajo bien hecho, no con subvenciones.</strong></p>
<p>Luego vienen las alegrías de siempre:</p>
<ul>
<li><strong>Fichas de empresa en las vistas previas con IA:</strong> los perfiles de Google Business empiezan a mostrarse ahí, con un «mostrar más» que abre una conversación con más datos del negocio. O sea, que nadie visita ya ni tu ficha ni Google Maps, todo se queda dentro del modo IA. Si con las preguntas relacionadas ya se cargaban el SEO normal, ahora le toca al SEO local.</li>
<li><strong>Anuncios camuflados en el modo IA:</strong> anuncios de texto metidos entre las respuestas con una etiqueta de patrocinado. Justo lo que necesitaba el buscador para que los usuarios terminen de perderle la confianza.</li>
<li><strong>Un botón de modo IA en la página de resultados:</strong> para empujarte a salir de la búsqueda clásica, que ya tienen asumido que es un desastre.</li>
</ul>
<p>OpenAI también ha movido ficha con los agentes patrocinados de ChatGPT, conversaciones con un agente de la marca cuando ves un anuncio. Aquí voy a ser justo, porque sobre el papel van a estar bien separados de las respuestas normales y, <strong>si de verdad no mezclan lo patrocinado con lo neutral, me parece bastante más transparente que lo de Google</strong>. Hasta una buena idea, fíjate.</p>
<p>Llevo 25 años en esto y no me explico cómo Google se está cargando su propio producto. <strong>La IA no ha llegado a internet, se lo ha cargado, y Google le ha metido el turbo a la carrera hacia el abismo.</strong></p>
<h3>Europa y la EU Kids Act</h3>
<p>Para rematar, la Unión Europea está preparando la EU Kids Act, que prohibiría las redes sociales (Instagram, TikTok, YouTube) a menores de 13 años, permitiría el acceso entre los 13 y los 15 solo con supervisión de los padres, funciones limitadas y control horario, y vetaría hasta el scroll infinito.</p>
<p>Ya sé que mucha gente lo ve bien, porque hay que proteger a los niños y las plataformas abusan, y en eso no les falta razón. Pero esta es una opinión de las intensas, así que te la cuento tal cual. <strong>Las instituciones están para servirnos, no para sustituirnos.</strong> Si aceptamos que decidan a partir de qué edad y cómo usan nuestros hijos las redes, les estamos dejando hacer nuestro papel de padres, primero en esto y luego en lo que les dé la gana. Lo que hay que hacer es formar a los padres para que sean conscientes y responsables de cómo usan sus hijos las redes y la IA.</p>
<p>En el chat, Mel Gómez apuntó algo con lo que estoy muy de acuerdo, que al final la gente dejará de fiarse de la IA y pedirá referencias. Creo que volveremos a lo único que da confianza de verdad, <strong>saber quién ha escrito qué</strong>. Yo me hago responsable de lo que digo, aun a riesgo de equivocarme, y si mañana tengo que rectificar, rectifico. Por eso se está volviendo tanto a los foros y a las comunidades de nicho, y no me extrañaría que volviéramos a los blogs enlazándose entre ellos, como con aquellos blogrings de antes.</p>
<p><a href="https://www.youtube.com/watch?v=5eMtaQ706Tc">Ver el directo completo de Crónicas WordPress en YouTube</a></p>
<div class="ast-oembed-container " style="height: 100%;"><iframe title="WordPress 7.2, el nuevo tema Ipsum, EU Kids Act y Google sigue arruinando Internet con AI Overviews…" width="1600" height="900" src="https://www.youtube.com/embed/5eMtaQ706Tc?feature=oembed&amp;enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></div>
<h2>Doctor WordPress: cómo funciona la autoprotección de Vigilante 3.0</h2>
<p>Me habíais preguntado bastante por la autoprotección de Vigilante 3.0, así que le dediqué el directo entero. La idea llevaba meses rondándome la cabeza, porque <strong>si no te puedes fiar de tu plugin de seguridad, no te puedes fiar de nada de lo que te diga</strong>. Un plugin de seguridad te protege de otros plugins y de inyecciones, pero ¿quién lo protege a él?</p>
<h3>La cerradura, la caja fuerte y la fábrica</h3>
<p>Piensa en tu web como en tu casa. Un ladrón listo no revienta la puerta, que hace mucho ruido. Lo que hace es cambiarte el bombín por uno que abre con tu llave y también con la suya, como hacen con los cajeros y las tarjetas. Tú sigues entrando como siempre, no notas nada, y él entra cuando quiere. Eso es lo que tiene que detectar la autoprotección, que alguien ha tocado tu cerradura.</p>
<p>Para eso Vigilante se comprueba contra tres referencias:</p>
<ul>
<li><strong>El manifiesto:</strong> un archivo que va con el plugin y que es distinto en cada instalación. Sería la ficha grabada en el propio bombín.</li>
<li><strong>La huella en la base de datos:</strong> la tarjeta que te dio el cerrajero y que guardas en la caja fuerte. Para falsificarla no basta con entrar en casa, también hay que abrir la caja fuerte. Y cada vez que el cerrajero (el actualizador de WordPress) te cambia el bombín, te da una tarjeta nueva.</li>
<li><strong>Las sumas de verificación de WordPress.org:</strong> el registro del fabricante, que está en la fábrica y no en tu casa, así que aunque te hayan reventado la caja fuerte, eso no lo pueden tocar. Eso sí, cuando sale una versión nueva, WordPress.org tarda unas horas en actualizar ese registro.</li>
</ul>
<p>Para engañar al plugin harían falta las tres llaves, y la tercera ni siquiera está en tu casa. En el escritorio de Vigilante lo ves como «Autoprotección de Vigilante», con el número de archivos verificados y «3 de 3 referencias» si todo está bien.</p>
<h3>Los casos que te puedes encontrar</h3>
<p>En el directo fui forzando cada situación con un mu-plugin de pruebas en mi instalación local (la que rompo casi a diario). Te resumo qué verías y qué hacer en cada caso:</p>
<ul>
<li><strong>Todo correcto:</strong> tres de tres referencias, en verde, y a otra cosa.</li>
<li><strong>Verificado, pero sin sumas de WordPress.org:</strong> pasa justo después de una actualización, mientras el registro del fabricante se pone al día. Lo da por bueno y te lo explica en la comprobación de seguridad.</li>
<li><strong>Dos de tres referencias:</strong> el indicador pasa a gris. No es grave, pero te avisa.</li>
<li><strong>Una hoja de estilos, un script o una imagen modificados:</strong> aparece un aviso, porque ya no es solo una referencia, hay un archivo tocado. Muchas veces es cosa de un plugin de caché u optimización que minifica los archivos, así que excluye la carpeta de Vigilante. Si no usas ninguno, pulsa «Reparar Vigilante», que descarga una copia limpia desde WordPress.org y sustituye los archivos en un clic.</li>
<li><strong>Versión cambiada sin confirmar:</strong> el manifiesto no coincide, por ejemplo porque has actualizado a mano por FTP sin pasar por el actualizador. Si has sido tú, lo aceptas, y si no, reparas.</li>
<li><strong>Versión anterior instalada:</strong> alguien ha sustituido Vigilante por una versión más antigua, que puede tener vulnerabilidades ya corregidas. Si no has sido tú, reparar.</li>
<li><strong>Archivo de código modificado:</strong> aquí ya estamos en la zona crítica. El aviso sale en rojo en todas las pantallas importantes del administrador (menos en el editor), no se puede cerrar y la puntuación de seguridad deja de ser fiable. En el ejemplo te decía qué archivos habían tocado, el del cortafuegos y el del acceso, así que ya no te puedes fiar ni de uno ni de otro. Reparar, inmediatamente.</li>
<li><strong>Archivo inyectado:</strong> alguien ha metido un archivo nuevo en la carpeta del plugin. En la prueba se llamaba «puerta-trasera.php», pero ningún atacante lo va a llamar así, le pondrá un nombre que parezca legítimo para que no lo borres. Pide a tu hosting que mire cuándo llegó ese archivo, repara y vuelve a analizar. Y revisa la auditoría de seguridad, que es donde queda todo registrado.</li>
<li><strong>Manifiesto sustituido, borrado o dañado:</strong> han manipulado una de las llaves. Quedan las otras dos referencias, pero lo rápido es reparar desde WordPress.org, que siempre va a estar mucho mejor protegido que tu web (y que la mía).</li>
<li><strong>Tareas programadas eliminadas:</strong> este es de los más retorcidos. Vigilante hace sus comprobaciones con el cron de WordPress (la tarea de mantenimiento diario), y si alguien se las carga, el plugin sigue ahí pero no hace nada, sin análisis ni alertas. Revisa con <a href="https://wordpress.org/plugins/wp-crontrol/">WP Crontrol</a> que estén las tareas que empiezan por «vigilante_» y, si faltan, haz un análisis de seguridad completo.</li>
<li><strong>Autoprotección desactivada por código:</strong> es el último aviso que vas a recibir, porque a partir de ahí nada comprueba nada. Por lo menos te dice qué archivo lo ha desactivado, como una especie de memoria de quién te mató. Si no has sido tú, trátalo como una intrusión, borra o desactiva ese archivo (renombrarlo a .off, por ejemplo) y vuelve a comprobar.</li>
<li><strong>Todavía sin comprobar:</strong> lo normal justo después de instalar, o tras una instalación por FTP. Lanza un análisis desde la pestaña de integridad de archivos y listo.</li>
</ul>
<h3>Plugins hechos con IA: el problema son las instrucciones que no das</h3>
<p>Iván San José comentó en el chat que está creando plugins para uso propio con agentes de IA y que no hay límites. Sí que los hay, y el límite eres tú, porque luego hay que mantenerlos, actualizarlos y someterlos a revisiones que, si las haces tú solo, nunca van a ser suficientes.</p>
<p>Lo veo a diario con los clientes de mi servicio de mantenimiento. He pasado de que me pidan código a que me lo pasen, plugins hechos por alguien de marketing con ChatGPT o Claude que no sabe programar y lo da por bueno. Ninguno pasa mis comprobaciones de seguridad y de estándares de código. Y yo, que tengo mis skills bien afinadas y hago pruebas en instalaciones de test, también cometo errores.</p>
<p>Hace nada me pasaron un plugin que ya había pasado por mis skills de seguridad y aun así duplicaba pedidos en producción, porque nadie había cerrado un bucle. La IA sabe mucho de código, pero también hace cosas que no le has pedido. Si le dices que se asegure al 100 % de que un email llega, igual te lo manda por SMTP, por PHP mail y por un tercer sistema. <strong>El problema de los plugins hechos con IA no suelen ser las instrucciones que le das, sino las que no le das.</strong> Para jugar o para algo interno, adelante, pero si va a una web abierta al público, que lo revise alguien más y usa modelos buenos, de pago.</p>
<h3>Nada es invulnerable</h3>
<p>¿Significa todo esto que Vigilante es invulnerable? Ni de coña. <strong>La seguridad al 100 % no existe, y quien te diga lo contrario te está mintiendo.</strong> Vigilante, igual que otros dos plugins míos, ha tenido vulnerabilidades, unas las encontré yo y otras los usuarios. Las arreglo esa misma tarde y lo cuento, pero pasan.</p>
<p>La mayoría de los hackeos no vienen de fallos desconocidos, sino de vulnerabilidades conocidas que alguien no ha parcheado. Hay muchísimos escáneres, cada vez más con IA, tirando de bases de datos de vulnerabilidades y buscando webs con la versión afectada de un plugin. Hasta un reloj parado acierta dos veces al día. Lo bueno del código abierto es que todo es transparente y las vulnerabilidades se conocen cuando ya están corregidas. El problema es cuando se publica el parche y tú no actualizas, porque el atacante sí se ha enterado.</p>
<p>Así que lo de siempre, que es lo que más se nos olvida. <strong>Ten todo actualizado</strong>, y si puedes, Vigilante instalado, al día, con la autoprotección activa y la configuración de seguridad al máximo.</p>
<p><a href="https://www.youtube.com/watch?v=jt-1iNVnbJ0">Ver el directo completo de Doctor WordPress en YouTube</a></p>
<div class="ast-oembed-container " style="height: 100%;"><iframe title="¿Un plugin de seguridad WordPress que se auto-protege? ¿qué clase de magia negra es esta?" width="1600" height="900" src="https://www.youtube.com/embed/jt-1iNVnbJ0?feature=oembed&amp;enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></div>
<h2>Nos vemos en el próximo directo</h2>
<p>Y hasta aquí la semana. Ya lo sabes, los lunes toca Crónicas WordPress y los miércoles, Doctor WordPress, a las 19:30 (hora peninsular) <a href="https://www.youtube.com/AyudaWordPressES?sub_confirmation=1">en el canal de Ayuda WordPress</a>. Por cierto, admito invitados, así que si tienes algo interesante que contar, dímelo. Y si tienes cualquier duda de lo que he contado, o me quieres corregir en algo, te leo ahí abajo en los comentarios.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ayudawp.com/un-clic-para-comprometer-tu-web-google-sujetandose-el-cubata-y-la-autoproteccion-de-vigilante-cronicaswordpress-doctorwordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Redirección 301 o 410 al borrar contenido en WordPress: ¿cuál es mejor?</title>
		<link>https://ayudawp.com/contenido-borrado-301-410/</link>
					<comments>https://ayudawp.com/contenido-borrado-301-410/#respond</comments>
		
		<dc:creator><![CDATA[Fernando Tellado]]></dc:creator>
		<pubDate>Thu, 24 Sep 2026 06:28:21 +0000</pubDate>
				<category><![CDATA[SEO / AEO / GEO / AIO]]></category>
		<category><![CDATA[Tutoriales - Trucos]]></category>
		<category><![CDATA[WordPress.com]]></category>
		<category><![CDATA[WordPress.org]]></category>
		<category><![CDATA[301]]></category>
		<category><![CDATA[404]]></category>
		<category><![CDATA[410]]></category>
		<category><![CDATA[Avanzado]]></category>
		<category><![CDATA[Principiante]]></category>
		<category><![CDATA[redirección]]></category>
		<category><![CDATA[Redirection]]></category>
		<category><![CDATA[Soft 404]]></category>
		<category><![CDATA[Visibility]]></category>
		<guid isPermaLink="false">https://ayudawp.com/?p=160333</guid>

					<description><![CDATA[Acabas de borrar una entrada en WordPress y no sabes si esa URL necesita una redirección permanente 301, dejar un error 404 tal cual, o decirle a Google que ha desaparecido para siempre con un 410. Aquí lo vamos a ver, y con ejemplos reales.]]></description>
										<content:encoded><![CDATA[<p><strong>Acabas de borrar una entrada en WordPress</strong> y no sabes si esa URL necesita una redirección permanente 301, dejar un error 404 tal cual, o decirle a Google que ha desaparecido para siempre con un 410. Aquí lo vamos a ver, y con ejemplos reales.</p>
<p>Además, que esto es una deuda pendiente, pues esta respuesta la tenía pendiente desde hace tres años. En octubre de 2022, Javi dejó este comentario en <a href="https://ayudawp.com/redirection/" target="_blank" rel="ugc noopener">la guía de Redirection</a>, y se quedó sin contestar:</p>
<p><em>«Quiero redireccionar muchas urls antiguas a un código 410 pero me gustaría evitar sobrecargar el htaccess […] Con la opción de Importar/Exportar permite hacer redirecciones 301, pero no he sido capaz de importar en csv urls que quiero que sea 410. ¿Tienes alguna idea o sugerencia para evitar hacerlo por htaccess?»</em></p>
<p>Javi, aquí tienes la respuesta completa, y es por qué el 410 no se importa igual que el 301, cuándo te toca usarlo en vez de una redirección, y qué hacer con el resto de casos de borrado, quizás por eso incluso lo añadí a un plugin … pero no adelantemos acontecimientos.</p>
<p>¡Empezamos!</p>
<h2>El borrado de contenidos tiene tres destinos posibles, no solo uno</h2>
<p>Cuando <strong>mandas una entrada a la papelera</strong> en WordPress, la URL que deja atrás tiene tres caminos posibles:</p>
<ul>
<li><strong>301, movido permanentemente</strong>: hay un contenido real al que mandar el tráfico.</li>
<li><strong>410, contenido eliminado</strong>: no hay ni va a haber sustituto, y quieres que los buscadores lo sepan cuanto antes.</li>
<li><strong>404, no encontrado</strong>: la URL deja de existir sin nada detrás.</li>
</ul>
<p><strong>Elegir mal no es un matiz técnico menor, tiene consecuencias reales en cómo trata Google tu web</strong>,  porque un 301 mal puesto puede acabar sin pasar ningún valor, un 410 que en realidad era un cambio de URL manda a la basura enlaces y tráfico que sí querías conservar, y un 404 no deja de ser una especie de error que muestras en tu web. ¿Seguimos?</p>
<h2>Cuándo toca una redirección 301</h2>
<p>El 301 tiene sentido cuando existe un destino que <strong>responde a la misma intención de búsqueda que tenía la URL borrada</strong>, con lo que fusionas dos entradas parecidas en una sola, publicas una versión actualizada que sustituye la publicación vieja, o resuelves una canibalización de contenido uniendo dos piezas en una.</p>
<p><strong>La condición no negociable es que el destino tiene que ser relevante de verdad, no un cajón de sastre.</strong> Redirigir en bloque decenas o cientos de URLs borradas a la portada de tu web, la salida fácil de bastantes plugins por defecto, la mayoría a la portada de la web.</p>
<p>Es justo el patrón que <a href="https://www.seroundtable.com/301-pages-home-soft-404-22811.html" target="_blank" rel="nofollow noopener">Google ha señalado repetidamente</a> como <strong>soft 404</strong>. El motor de búsqueda detecta que el destino no tiene relación real con lo que se buscaba, deja de tratar esa redirección como un «movido permanentemente» de verdad y no pasa ninguna señal.</p>
<p>Esto lo hace, por ejemplo, <a href="https://ayudawp.com/redirection/" target="_blank" rel="ugc noopener">Redirection</a> por defecto, cuando envías algo a la papelera con la supervisión de URLs activada, creando automáticamente una redirección 301 a portada. Sirve para no dejar un 404 suelto de un día para otro, pero <strong>si vas a borrar contenido en cantidad conviene revisar esas redirecciones automáticas caso por caso, no dejarlas todas apuntando a portada ahí a lo loco</strong>.</p>
<p>Si lo que cambia es solo el slug o la estructura de permalinks, y no borras nada, ese caso ya lo tienes cubierto en <a href="https://ayudawp.com/wp-old-slug-redirect/" target="_blank" rel="ugc noopener">este artículo donde explico el wp_old_slug_redirect nativo</a>.</p>
<h2>Cuándo toca un 410 (esto no lo esperabas, seguro)</h2>
<p>El 410 le dice a Google algo distinto al 301, no que el contenido se ha movido, sino que <strong>ha desaparecido para siempre y no hay a dónde redirigir</strong>.</p>
<p>Esto <strong>es más útil de lo que imaginas</strong>, a mi pasó hace poco, cuando un cliente del <a href="https://servicios.ayudawp.com/producto/wordpress-hackeado/" target="_blank" rel="ugc noopener">servicio de recuperación de webs hackeadas</a> llegó con decenas de entradas inyectadas con spam SEO en japonés, un patrón clásico de infección para colarse en resultados de búsqueda ajenos a la temática de la web, y por supuesto de paso <strong>cargarse el tráfico y reputación de la web en particular y de la marca en general</strong>.</p>
<p>No había ningún contenido legítimo al que redirigir esas URLs, así que <strong>la única opción con sentido era el 410, y funcionó a la perfección</strong>, en menos de una semana habían desaparecido del índice de Google.</p>

<a href="https://ayudawp.com/contenido-borrado-301-410/serp-spam-japones-antes/" rel="nofollow"><img width="1200" height="1348" src="https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-antes-1200x1348.jpg" class="attachment-medium size-medium" alt="SERP con spam (antes)" srcset="https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-antes-1200x1348.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-antes-768x862.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-antes-1368x1536.jpg 1368w, https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-antes-1824x2048.jpg 1824w, https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-antes.jpg 1920w" sizes="(max-width: 1200px) 100vw, 1200px" decoding="async" fetchpriority="high"></a>
<a href="https://ayudawp.com/contenido-borrado-301-410/serp-spam-japones-despues/" rel="nofollow"><img width="1200" height="1496" src="https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-despues-1200x1496.jpg" class="attachment-medium size-medium" alt="SERP con spam (después)" srcset="https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-despues-1200x1496.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-despues-768x957.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-despues-1232x1536.jpg 1232w, https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-despues-1643x2048.jpg 1643w, https://ayudawp.com/wp-content/uploads/2026/09/serp-spam-japones-despues.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/contenido-borrado-301-410/spam-japones-antes/" rel="nofollow"><img width="1200" height="388" src="https://ayudawp.com/wp-content/uploads/2026/09/spam-japones-antes-1200x388.jpg" class="attachment-medium size-medium" alt="SPAM japonés (antes)" srcset="https://ayudawp.com/wp-content/uploads/2026/09/spam-japones-antes-1200x388.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/spam-japones-antes-768x248.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/spam-japones-antes-1536x497.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/spam-japones-antes.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/contenido-borrado-301-410/spam-japones-despues/" rel="nofollow"><img width="1200" height="834" src="https://ayudawp.com/wp-content/uploads/2026/09/spam-japones-despues-1200x834.jpg" class="attachment-medium size-medium" alt="SPAM japonés (después)" srcset="https://ayudawp.com/wp-content/uploads/2026/09/spam-japones-despues-1200x834.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/spam-japones-despues-768x534.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/spam-japones-despues-1536x1068.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/spam-japones-despues.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>

<p><strong>Con un 301 ese plazo no hubiese sido ni de lejos tan corto, porque redirigir spam a un contenido que no tiene nada que ver no acelera nada</strong>, en el mejor de los casos, pues Google lo trata como el soft 404 del punto anterior.</p>
<p>La documentación oficial de Google dice que trata el 404 y el 410 de forma parecida con el tiempo, pero John Mueller ha repetido varias veces que <strong>en la práctica el 410 suele caer del índice unos días antes que el 404, y en un caso de limpieza de seguridad, esos días cuentan</strong>, y se nota mucho, sobre todo en lo rápido que funciona.</p>
<p>El 410, por supuesto, <strong>también sirve para otras situaciones aparte de la seguridad</strong>, como para productos descatalogados sin sustituto o campañas, ofertas ya cerradas de forma definitiva, desposicionar contenidos y muchas otras necesidades de contenido que sabes que no va a volver ni tiene sustituto natural.</p>
<h2>¿Y si lo dejo como 404 sin más?</h2>
<p>No todas las URLs merecen gestión, eso es cierto, más o menos. Si una entrada borrada no tiene tráfico orgánico ni enlaces entrantes de valor, revisa Search Console y tu herramienta de enlaces entrantes antes de decidir, forzar una redirección ahí es trabajo que no vuelve en forma de nada.</p>
<p><strong>Un 404 limpio no penaliza tu web, es información correcta</strong> del tipo «esa URL ya no existe», otra cosa es la experiencia de cara al usuario que llega a ese punto muerto, y la imagen que puedas dar <a href="https://ayudawp.com/personalizar-la-pagina-de-error-404-no-existe/" target="_blank" rel="noopener">si no gestionas correctamente tu página de error 404</a>.</p>
<p>Luego está el asunto de los avisos y errores de la Search Console, que te van a estar recordándote siempre que tienes ahí esas posible malas experiencias para los usuarios que lleguen a tu (desaparecido) contenido y vean ese mensaje de error.</p>
<p>Tú decides, pero si me pides mi (humilde pero casi siempre acertada) opinión, sería la peor opción salvo casos muy contados.</p>
<h2>Qué herramienta usar en WordPress para cada caso</h2>
<p>Como en todo, <strong>no hay un plugin perfecto para todo, o para todas las necesidades</strong>, tienes varias opciones, todas buenas, según tu caso e incluso gusto:</p>
<ul>
<li><a href="https://wordpress.org/plugins/redirection/" target="_blank" rel="nofollow noopener">Redirection</a> sigue siendo la opción más completa si necesitas 301, 302, 307 o 308, con su asistente y su registro de errores 404. El límite es justo el que le tocó a Javi, que <strong>el importador CSV está pensado para redirecciones tipo 301, no para dar de alta un lote de 410</strong> sin tocarlas una a una o editar el <code>.htaccess</code> a mano.</li>
<li><a href="https://wordpress.org/plugins/safe-redirect-manager/" target="_blank" rel="nofollow noopener">Safe Redirect Manager</a> sí <strong>prioriza los 410, junto al 403, pero su importación por CSV solo está disponible vía WP-CLI</strong>. Si no tienes acceso a la línea de comandos en tu hosting, no te sirve para acciones por lotes.</li>
<li><a href="https://wordpress.org/plugins/native-aeo-pack/" target="_blank" rel="nofollow noopener">Visibility</a>, te <strong>permite resolver todas estas situaciones</strong> independientemente de tu servidor, sin tener que tocar <code>.htaccess</code> o similares. Genera redirecciones sugeridas cuando envías una entrada a la papelera o la borras, y puedes convertir cada una en 301 o 410 desde el propio escritorio de WordPress, con importación CSV desde Redirection y los demás plugins de SEO, para no perder lo que ya tuvieras si decides cambiarte.</li>
</ul>
<p style="color: red;"><a href="https://ayudawp.com/?attachment_id=160346" rel="nofollow"><img decoding="async" class="sombra alignnone wp-image-160346 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/redirecciones-410-contenido-spam-borrado-plugin-seo-Visibility-1200x914.jpg" alt="" width="1200" height="914" srcset="https://ayudawp.com/wp-content/uploads/2026/09/redirecciones-410-contenido-spam-borrado-plugin-seo-Visibility-1200x914.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/redirecciones-410-contenido-spam-borrado-plugin-seo-Visibility-768x585.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/redirecciones-410-contenido-spam-borrado-plugin-seo-Visibility-1536x1170.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/redirecciones-410-contenido-spam-borrado-plugin-seo-Visibility.jpg 1920w" sizes="(max-width: 1200px) 100vw, 1200px"></a></p>
<h2>Resumen para decidir rápido</h2>
<ul>
<li><strong>¿Hay destino real y relevante?</strong>: <code>301</code>.</li>
<li><strong>¿No va a haber destino nunca, sea limpieza de contenido o de seguridad?</strong>: <code>410</code>.</li>
<li><strong>¿Sin tráfico ni enlaces que lo sostengan?</strong>: <code>404</code>.</li>
</ul>
<p>Si te queda alguna duda de un caso concreto, la sección de comentarios sigue abierta, y esta vez prometo no tardar tres años en contestar.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ayudawp.com/contenido-borrado-301-410/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Aviso de garantía legal de la UE en WooCommerce (GARAN) – ¿Hay algún plugin o código que me sirva para cumplir en mi tienda?</title>
		<link>https://ayudawp.com/aviso-de-garantia-legal-de-la-ue-en-woocommerce-garan-hay-algun-plugin-o-codigo-que-me-sirva-para-cumplir-en-mi-tienda/</link>
					<comments>https://ayudawp.com/aviso-de-garantia-legal-de-la-ue-en-woocommerce-garan-hay-algun-plugin-o-codigo-que-me-sirva-para-cumplir-en-mi-tienda/#respond</comments>
		
		<dc:creator><![CDATA[Fernando Tellado]]></dc:creator>
		<pubDate>Wed, 23 Sep 2026 06:28:19 +0000</pubDate>
				<category><![CDATA[Plugins WordPress]]></category>
		<category><![CDATA[Programación + WordPress]]></category>
		<category><![CDATA[Tutoriales - Trucos]]></category>
		<category><![CDATA[WordPress.com]]></category>
		<category><![CDATA[WordPress.org]]></category>
		<category><![CDATA[Avanzado]]></category>
		<category><![CDATA[GARAN]]></category>
		<category><![CDATA[Principiante]]></category>
		<category><![CDATA[Unión Europea]]></category>
		<guid isPermaLink="false">https://ayudawp.com/?p=160384</guid>

					<description><![CDATA[Desde el 27 de septiembre de 2026, si vendes productos físicos a consumidores en la Unión Europea tienes que mostrar en tu tienda el aviso armonizado de la garantía legal, un cartel oficial de la Comisión Europea que no puedes modificar.]]></description>
										<content:encoded><![CDATA[<p>Desde el <strong>27 de septiembre de 2026</strong>, si vendes productos físicos a consumidores en la Unión Europea tienes que mostrar en tu tienda el aviso armonizado de la garantía legal, un cartel oficial de la Comisión Europea que no puedes modificar.</p>
<p>En una tienda online el cartelito tiene que ir a todo color, a la vista antes de comprar y también en el correo de confirmación del pedido, y si algún fabricante da gratis una garantía de durabilidad de más de dos años sobre todo el producto, ese producto lleva además la etiqueta <strong>GARAN</strong>.</p>
<p>Es <strong>otro requisito legal más, sí, pero de los sencillos</strong>, porque no cambia tus garantías, solo te obliga a contarlas con el mismo cartel que el resto de tiendas de Europa. Lo que es más peñazo es elegir cómo ponerlo en WooCommerce, porque en las últimas semanas han salido plugins como setas y he revisado a fondo el código de los principales, y ya te adelanto que ninguno lo hace todo bien.</p>
<p>Lo vemos enseguida, pero antes…</p>
<h2>Qué es el aviso armonizado y qué es la etiqueta GARAN</h2>
<p>El aviso armonizado es un cartel con el mismo diseño en toda la UE (solo cambia el idioma) que recuerda al consumidor sus derechos de garantía legal. <strong>Lo tienes que mostrar si vendes bienes, o sea, productos físicos, a consumidores</strong>. Si solo vendes a empresas, o lo tuyo son cursos, descargas o servicios, no te afecta.</p>
<p><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160390 size-full" src="https://ayudawp.com/wp-content/uploads/2026/09/aviso-legal-garan-ue.jpg" alt="Aviso armonizado de la UE sobre la garantía legal de conformidad, versión en español" width="903" height="1200" srcset="https://ayudawp.com/wp-content/uploads/2026/09/aviso-legal-garan-ue.jpg 903w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-legal-garan-ue-768x1021.jpg 768w" sizes="auto, (max-width: 903px) 100vw, 903px"></p>
<p>Lo que dice <strong>no es nuevo para nadie que venda en España</strong>. El aviso recuerda que la garantía legal mínima en la UE es de dos años y que algunos países tienen plazos más largos, que en segunda mano puede ser menor pero nunca de menos de un año, qué puede pedir el consumidor (reparación, sustitución, rebaja o reembolso) y qué tiene que hacer si el producto le sale mal. Incluye además un código QR que abre la página de garantías de <a href="https://europa.eu/youreurope/business/selling-in-eu/consumer-contracts-guarantees/eu-legal-guarantee-notice-and-garan-label/index_es.htm" target="_blank" rel="nofollow noopener">Your Europe</a> en su idioma. Vamos, que no cambia tu garantía, cambia cómo la cuentas.</p>
<p>La etiqueta GARAN es otra cosa. <strong>Solo hace falta si el fabricante ofrece una garantía comercial de durabilidad gratuita, de más de dos años y que cubra el producto entero</strong>. Va producto a producto, con los años, la marca y el modelo, y la prepara el fabricante. Tú, como vendedor, solo tienes que mostrarla junto a ese producto.</p>
<p><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160389 size-full" src="https://ayudawp.com/wp-content/uploads/2026/09/etiqueta-ue-GARAN.jpg" alt="Etiqueta GARAN de la UE para la garantía comercial de durabilidad" width="815" height="857" srcset="https://ayudawp.com/wp-content/uploads/2026/09/etiqueta-ue-GARAN.jpg 815w, https://ayudawp.com/wp-content/uploads/2026/09/etiqueta-ue-GARAN-768x808.jpg 768w" sizes="auto, (max-width: 815px) 100vw, 815px"></p>
<p>Ojo, que hay garantías que se le parecen y no obligan a ponerla:</p>
<ul>
<li>Los tres años de garantía legal que tenemos en España, porque son la garantía legal y ya los cubre el aviso.</li>
<li>Una garantía ampliada que ofrezcas tú como tienda, porque la GARAN solo va con las del fabricante.</li>
<li>Las ampliaciones de garantía de pago.</li>
<li>Las que solo cubren una pieza, como los típicos «10 años en el motor».</li>
</ul>
<p>La excepción es que fabriques tú lo que vendes (los muebles de tu taller, por ejemplo), porque entonces el fabricante eres tú, y si das gratis más de dos años sobre todo el producto, la GARAN te toca a ti.</p>
<p>Si no vendes productos con ese tipo de garantía del fabricante, olvídate de la GARAN y céntrate en el aviso, que es lo que afecta a todo el mundo.</p>
<h2>¿Es obligatorio en España si todavía no se ha transpuesto la directiva?</h2>
<p>Aquí hay un matiz importante y es que la obligación sale de la <a href="https://www.boe.es/buscar/doc.php?id=DOUE-L-2024-80326" target="_blank" rel="nofollow noopener">Directiva (UE) 2024/825</a>, que añadió un artículo 22 bis a la directiva de derechos de los consumidores, y el diseño exacto del aviso lo fija el <a href="https://www.boe.es/buscar/doc.php?id=DOUE-L-2025-81437" target="_blank" rel="nofollow noopener">Reglamento de Ejecución (UE) 2025/1960</a>, que se aplica desde el 27 de septiembre sin necesidad de transponerlo.</p>
<p>Pero la obligación de mostrarlo está en la directiva, y las directivas hay que pasarlas a la ley de cada país. El plazo terminó el 27 de marzo de 2026, España no lo ha hecho y el 28 de mayo <a href="https://www.cuatrecasas.com/es/global/sostenibilidad/art/novedades-sostenibilidad-segundo-trimestre-2026" target="_blank" rel="nofollow noopener">la Comisión Europea abrió procedimientos de infracción contra 20 Estados miembros</a> por este motivo, España incluida. La ley que tiene que hacerlo, la de Consumo Sostenible, sigue en tramitación.</p>
<p>¿Significa eso que te lo puedes saltar? Pues yo no lo haría, porque las administraciones ya lo dan por obligatorio, y <a href="https://www.teleprensa.com/andalucia/sevilla/junta-informa-nuevas-etiquetas-que-ofrecen-mayores-garantias-informacion-mas-clara-consumidores/202609211327272512878.html" target="_blank" rel="nofollow noopener">la Junta de Andalucía</a>, sin ir más lejos, recordó el 21 de septiembre a los comercios físicos y online que desde el día 27 tienen que usarlo. Si vendes a países que sí han hecho los deberes, como Alemania, allí te aplica su ley, y además, ponerlo te lleva solo un rato.</p>
<p>Tampoco hace falta ponerse nervioso, eso también, pues <strong>mientras no se apruebe la ley española, cómo y cuánto se sancionaría esto en España está en el aire</strong>, y en Alemania, donde ya aprobaron su ley, de lo que se habla es de requerimientos entre competidores por competencia desleal.</p>
<p>Hazlo con calma y bien hecho, y si tienes dudas sobre tu caso concreto pregunta a tu asesoría, que yo de leyes sé lo justo para no meter la pata.</p>
<h2>Y en España, ¿no eran tres años?</h2>
<p>Sí, y lo siguen siendo. Desde 2022 el <a href="https://www.boe.es/buscar/act.php?id=BOE-A-2007-20555#a120" target="_blank" rel="nofollow noopener">artículo 120.1 de la Ley General para la Defensa de los Consumidores y Usuarios</a> fija tres años de responsabilidad del vendedor para los bienes nuevos, dos para los contenidos y servicios digitales y, en segunda mano, un plazo que se puede pactar más corto pero nunca por debajo de un año.</p>
<p>Además, durante los dos primeros años se presume que el defecto ya estaba ahí al entregar el producto (<a href="https://www.boe.es/buscar/act.php?id=BOE-A-2007-20555#a121" target="_blank" rel="nofollow noopener">artículo 121</a>). El aviso dice «garantía legal mínima de dos años» porque es el mínimo europeo, y aclara que algunos países tienen plazos más largos.</p>
<p>Lo que no puedes hacer es cambiar ese dos por un tres, porque <strong>el aviso no se puede editar en absoluto</strong>, pero lo que sí puedes hacer (y te lo recomiendo) es poner al lado, fuera del cartel, una nota del tipo «En España, la garantía legal de los bienes nuevos es de tres años desde la entrega» con un enlace a la parte de tus condiciones donde lo explicas.</p>
<p>Así que si lees por ahí que ahora la garantía es de dos años, no, en España sigue siendo de tres.</p>
<h2>Qué te piden exactamente para una tienda online</h2>
<p>La Comisión publicó en abril unas <a href="https://commission.europa.eu/publications/practical-guidelines-and-high-resolution-vector-files-eu-notice-and-label-product-guarantees_en" target="_blank" rel="nofollow noopener">directrices prácticas</a> con lo que hay que hacer y lo que no. Para el aviso en una web, lo básico es esto:</p>
<ul>
<li>Usa el archivo oficial, en color, sin recortarlo, sin cambiar colores ni tipografía y sin añadirle nada.</li>
<li>Tiene que leerse bien a su tamaño normal («legible at default display size», dicen).</li>
<li>Siempre tiene que haber un enlace que se pueda pulsar y que lleve al mismo sitio que el QR.</li>
<li>Va «de forma destacada», como un recordatorio general en la web. Los ejemplos que ponen son una frase en la cabecera, en el catálogo o en la página de pago que abre el aviso al primer clic.</li>
<li>También debe ir en el correo de confirmación del pedido.</li>
</ul>
<p>«La GARAN» tiene que ir junto al producto en la ficha, justo antes de hacer el pedido y también en el correo de confirmación, y aquí sí se permite un formato reducido que se despliega al pulsarlo.</p>
<h3>¿Vale un enlace que lo despliegue o tiene que verse entero?</h3>
<p>Aquí hay debate. Las directrices de la Comisión ponen como ejemplo justo eso, una frase que abre el aviso con un clic. Pero el propio documento aclara que son opiniones preliminares de sus servicios y que solo el Tribunal de Justicia interpreta el derecho de la UE, y hay quien, como <a href="https://www.jtl-software.com/en/blog/interesting-facts/legal-guarantee-notice-with-shop-5-8" target="_blank" rel="nofollow noopener">JTL</a>, sostiene que el reglamento solo permite ese formato desplegable para la GARAN, no para el aviso.</p>
<p>Mi recomendación es sencilla. <strong>Si quieres ir sobre seguro, muéstralo entero y a la vista junto al botón de pedido</strong>. Si prefieres una página de pago más limpia, el desplegable es lo que la propia Comisión pone de ejemplo, y si dudas, que decida tu asesoría, porque el código que te dejo más abajo permite las dos cosas.</p>
<h3>Dónde descargar los archivos oficiales (y cuál usar)</h3>
<p>Todo está en la <a href="https://commission.europa.eu/publications/practical-guidelines-and-high-resolution-vector-files-eu-notice-and-label-product-guarantees_en" target="_blank" rel="nofollow noopener">página de la Comisión</a>, con el aviso en las 24 lenguas oficiales en PNG, JPG, PDF y SVG, y la plantilla de la GARAN. <strong>Para la web usa el PNG en color</strong>, que en español pesa 87 KB, frente a los 631 KB del SVG. El PDF (92 KB, con la versión en color y la de blanco y negro) es el que te conviene adjuntar al correo y el que puedes imprimir en A4 si también tienes tienda física.</p>
<p>Por cierto, el paquete de PNG no trae la versión en inglés, que solo está en SVG y PDF. Si la necesitas para la web, exporta a PNG la primera página del PDF oficial en inglés sin cambiar nada más.</p>
<h2>Plugins disponibles – Qué hacen y qué no</h2>
<p>Casi todos han salido entre mediados de agosto y septiembre y ninguno pasa de unas pocas decenas de instalaciones, salvo Germanized, que es un veterano del mercado alemán, y el mío, que ya existía para el desistimiento y añade el aviso desde la versión 2.3.0.</p>
<p>He revisado el código de cada uno en su versión de hoy, así que esto es lo que hacen, no lo que dice su ficha:</p>
<table>
<thead>
<tr>
<th>Plugin</th>
<th>Archivos oficiales sin tocar</th>
<th>Aviso junto al botón de pedido</th>
<th>Correo</th>
<th>GARAN</th>
<th>Idioma de respaldo para web en catalán, euskera o gallego</th>
</tr>
</thead>
<tbody>
<tr>
<td>Arthur Smith’s EU Guarantee Notice and GARAN Label (1.4.0)</td>
<td>Sí</td>
<td>No, arriba de la página de pago</td>
<td>Sí, con la imagen dentro del correo</td>
<td>Sí</td>
<td>Inglés (se cambia a mano)</td>
</tr>
<tr>
<td>market-it! EU Guarantee Notice for WooCommerce (1.0.0)</td>
<td>Sí, pero solo en 5 idiomas</td>
<td>Sí, en los dos checkouts</td>
<td>No</td>
<td>No</td>
<td>Inglés (se cambia a mano)</td>
</tr>
<tr>
<td>EU Warranty Ready (1.6.1)</td>
<td>Sí</td>
<td>Sí, en los dos checkouts</td>
<td>SVG que Gmail y Outlook no muestran</td>
<td>Sí</td>
<td>Inglés</td>
</tr>
<tr>
<td>BuildsByLuke Product Guarantee Notice (1.0.4)</td>
<td>Copia muy fiel, con fondo transparente</td>
<td>No (versión de pago)</td>
<td>No (versión de pago)</td>
<td>No (versión de pago)</td>
<td>Castellano</td>
</tr>
<tr>
<td>EU Legal-Guarantee Notice &amp; GARAN Durability Label (GaranLabs) (1.9.2)</td>
<td>No, recortadas y con otro azul</td>
<td>No, arriba de la página de pago</td>
<td>Sí</td>
<td>Sí, pero falla con productos variables</td>
<td>Inglés (se cambia a mano)</td>
</tr>
<tr>
<td>Germanized (4.1.3)</td>
<td>Sí</td>
<td>No en el clásico; en el de bloques, si colocas su bloque</td>
<td>PDF adjunto</td>
<td>Sí</td>
<td>Inglés</td>
</tr>
<tr>
<td>WarrantyARK (1.2.0)</td>
<td>No, recortadas y con otro azul</td>
<td>No, arriba de la página de pago</td>
<td>Sí</td>
<td>Sí, pero redondea al alza</td>
<td>Inglés (se cambia a mano)</td>
</tr>
<tr>
<td>StackedBoost (1.3.0)</td>
<td>No, lo rehace en HTML</td>
<td>No</td>
<td>Solo texto</td>
<td>Sí, rehecha</td>
<td>Inglés</td>
</tr>
<tr>
<td>EU Withdrawal and Legal Guarantee Compliance (2.3.0)</td>
<td>Sí, con el inglés convertido a PNG desde el PDF oficial</td>
<td>Sí, en los dos checkouts</td>
<td>Sí, con el PDF oficial adjunto</td>
<td>No, de momento</td>
<td>Castellano</td>
</tr>
</tbody>
</table>
<p>Cuando lo ves todo junto el panorama queda bastante claro, porque <strong>quitando EU Withdrawal and Legal Guarantee Compliance, ninguno pone el aviso junto al botón, lo manda en el correo y lo muestra en castellano en una web en catalán, euskera o gallego, todo a la vez</strong>.</p>
<p>Vamos a verlos un poco más en detalle de todos modos.</p>
<h3>Arthur Smith’s EU Guarantee Notice and GARAN Label (el más sólido)</h3>
<p><a href="https://wordpress.org/plugins/arthursmith-guarantee-notice-garan-label/" target="_blank" rel="nofollow noopener">Arthur Smith’s EU Guarantee Notice and GARAN Label</a> lleva los SVG oficiales idénticos byte a byte a los de la Comisión y mete la imagen del aviso dentro del propio correo, así que no depende de que el programa de correo cargue imágenes externas. Además valida con cuidado los datos de la GARAN y la dibuja con la tipografía oficial. <strong>En su código no he encontrado fallos de seguridad ni llamadas a servicios externos</strong>.</p>
<p>Lo que falla es la colocación y el idioma, en la página de pago pone el aviso arriba del todo, no junto al botón, y esa ubicación viene desactivada. En webs en catalán, euskera o gallego lo muestra en inglés, igual que el texto del desplegable si no lo cambias en los ajustes. Nada que no arregles en dos minutos con el complemento que te dejo más abajo.</p>
<h3>market-it! EU Guarantee Notice for WooCommerce (el más directo)</h3>
<p><a href="https://wordpress.org/plugins/market-it-eu-guarantee-notice-for-woocommerce/" target="_blank" rel="nofollow noopener">market-it!</a> hace poco, pero lo hace donde toca. Lleva el SVG oficial y <strong>pone el aviso justo encima del botón de pedido, tanto en el checkout clásico como en el de bloques</strong>. Es ligero y no se conecta con nada de fuera.</p>
<p>Eso sí, aunque anuncia las 24 lenguas solo trae cinco (alemán, español, francés, inglés y sueco), no incluye el aviso en el correo ni la GARAN y es nuevísimo, salió el 31 de agosto. Si tu web está en catalán, euskera o gallego, elige el español como idioma por defecto en sus ajustes, porque si no cae al inglés. Y para el correo puedes combinarlo con mi snippet, desactivando la parte del checkout.</p>
<h3>EU Warranty Ready (bien en el checkout, mal en el correo)</h3>
<p><a href="https://wordpress.org/plugins/eu-warranty-ready/" target="_blank" rel="nofollow noopener">EU Warranty Ready</a> también usa los SVG oficiales y también coloca el aviso justo encima del botón en los dos checkouts, con un desplegable accesible bien resuelto.</p>
<p>El problema está en el correo. Mete el aviso como una imagen SVG alojada en tu web, y <strong>ni Gmail ni Outlook de escritorio muestran imágenes SVG en los correos</strong>, así que lo más probable es que tu cliente no vea nada. Además esa parte no se puede desactivar, el plugin carga su CSS y su JavaScript en todas las páginas de la web y en catalán, euskera o gallego muestra el aviso en inglés.</p>
<h3>BuildsByLuke Product Guarantee Notice (la imagen más fiel, solo en la ficha)</h3>
<p><a href="https://wordpress.org/plugins/buildsbyluke-product-guarantee-notice-for-woocommerce/" target="_blank" rel="nofollow noopener">BuildsByLuke</a> trae una copia en PNG muy fiel del aviso y es el único que en webs en catalán, euskera o gallego muestra el aviso en castellano sin tocar nada. El código es limpio.</p>
<p>Pero <strong>la versión gratuita solo pone el aviso en la ficha de producto</strong>, porque el checkout, el correo y la GARAN son de pago. Trae además el SDK de Freemius, con su pantalla de alta al activarlo (te la puedes saltar), y sus imágenes tienen el fondo transparente, así que en un tema con fondo oscuro las zonas blancas del aviso se tiñen del color de tu web. Eso se arregla con una línea de CSS (<code>.bblgg-notice img{background:#fff}</code>).</p>
<h3>GaranLabs (parecía el más completo, pero tiene sus cosas)</h3>
<p><a href="https://wordpress.org/plugins/garanlabs-eu-guarantee-notice-durability-labels/" target="_blank" rel="nofollow noopener">EU Legal-Guarantee Notice &amp; GARAN Durability Label for WooCommerce</a>, de GaranLabs, es gratis y no tiene versión de pago. Sobre el papel es el más completo, con el aviso en la ficha, en la cabecera, en el pago y en el correo (como enlace, imagen o adjunto), la GARAN y 24 idiomas.</p>
<p>Al revisar el código de la versión 1.9.2 me he encontrado esto:</p>
<ul>
<li>Si al desactivarlo rellenas el formulario de opinión, envía el texto, la dirección de tu web y el correo del administrador a un servidor externo (Supabase), sin decirlo en el formulario. Y su ficha asegura que no envía datos a ningún sitio.</li>
<li>Sus imágenes del aviso no son las oficiales tal cual, porque están recortadas y tienen otro azul (#0049B6 en lugar del #034EA2 oficial). De hecho, son exactamente las mismas que las de WarrantyARK.</li>
<li>En la página de pago pone el aviso arriba del todo, no junto al botón.</li>
<li>La GARAN no aparece en productos variables, ni en el pago con bloques ni en los correos.</li>
<li>El formato de adjunto de la GARAN en los correos llama a una función de WordPress (<code>wp_tempnam()</code>) sin cargar el archivo que la define, así que puede provocar un error fatal cuando el pedido se hace desde la web.</li>
<li>En catalán, euskera o gallego muestra el aviso en inglés, salvo que fijes el idioma a mano.</li>
<li>En su modo de ventana emergente el aviso se abre a unos 420 píxeles de ancho, con la letra muy pequeña.</li>
</ul>
<p>El complemento del repositorio le arregla el idioma y le pone el aviso junto al botón, pero lo demás depende de que lo corrija su autor.</p>
<h3>Germanized (solo si ya lo usas)</h3>
<p><a href="https://wordpress.org/plugins/woocommerce-germanized/" target="_blank" rel="nofollow noopener">Germanized</a> es el más completo de todos y es gratis. Usa el PNG oficial, adjunta el PDF al correo, genera la GARAN admitiendo medios años y tiene un bloque propio para el checkout de bloques. Pero viene desactivado, en el checkout de bloques tienes que colocar su bloque a mano, si eliges mostrarlo en el checkout clásico lo pone después de las notas del pedido y, sobre todo, es un plugin pensado para la legislación alemana que añade y cambia muchas más cosas en tu tienda. <strong>Si ya lo usas, actívalo, y si no, no lo instales solo para esto</strong>.</p>
<h3>Los que NO te recomiendo</h3>
<ul>
<li><strong>WarrantyARK:</strong> sus imágenes del aviso son las mismas que las de GaranLabs, recortadas y con otro azul. En la GARAN redondea los meses, así que una garantía de 30 meses aparece como de 3 años, y si no rellenas la marca pone el nombre de tu tienda.</li>
<li><strong>StackedBoost:</strong> rehace el aviso en HTML en lugar de usar el archivo oficial y no pone nada en la página de pago.</li>
<li><strong>Merqivio EU Compliance:</strong> solo pone el aviso en la ficha de producto, en un único idioma y rodeado de un título y una insignia propios.</li>
<li><strong>CertaCart:</strong> no trae el aviso, solo te deja elegir una imagen de tu biblioteca de medios para mostrarla.</li>
</ul>
<h3>EU Withdrawal and Legal Guarantee Compliance</h3>
<p><a href="https://wordpress.org/plugins/eu-withdrawal-compliance/" target="_blank" rel="nofollow noopener">EU Withdrawal and Legal Guarantee Compliance</a> (antes EU Withdrawal Compliance) nació para <a href="https://ayudawp.com/desistimiento-ue-woocommerce/" target="_blank" rel="ugc noopener">la función de desistimiento obligatoria de la Directiva 2023/2673</a>, y el aviso armonizado sale de otra modificación de la misma directiva de derechos de los consumidores, así que tenía todo el sentido meterlo ahí. De hecho, en la 2.3.0 le cambié el nombre, porque el antiguo solo hablaba del desistimiento, pero si ya lo tienes instalado lo único que cambia es cómo aparece en la lista de plugins.</p>
<p>Desde esa versión 2.3.0 trae un módulo nuevo para el aviso que hace esto:</p>
<ul>
<li>Lleva dentro el PNG y el PDF oficiales en los 24 idiomas, así que no tienes que descargar ni subir nada. Como el paquete de PNG de la Comisión no trae el inglés, ese lo he convertido desde el PDF oficial, al mismo tamaño que los demás y sin tocar nada.</li>
<li>Pone el aviso justo encima del botón de pedido, en el checkout clásico y en el de bloques. Puedes elegir entre verlo completo (es lo que viene por defecto), desplegable, en una ventana por encima de la página o no ponerlo en el checkout, por si prefieres colocarlo por tu cuenta.</li>
<li>Lo incluye en los correos de confirmación al cliente con el PDF oficial adjunto, y si usas WPML o Polylang con WooCommerce, en el idioma del pedido.</li>
<li>Usa el aviso en castellano en webs en catalán, euskera, gallego, asturiano o aragonés, y con otras lenguas sin aviso oficial hace lo mismo con el idioma oficial de su país.</li>
<li>Añade la nota de los tres años con un enlace a tus condiciones cuando la tienda está en España (y la puedes forzar si vendes a España desde otro país).</li>
<li>Trae dos shortcodes para montar tu propia página de garantía legal, <code>[[ayudawp_guarantee_notice]]</code>, que pone en ella el aviso completo, y <code>[[ayudawp_guarantee_link]]</code>, que la enlaza desde el pie o desde donde quieras.</li>
<li>Solo aparece si el carrito lleva algún producto físico y deja una nota en cada pedido con el aviso que se mostró.</li>
</ul>
<p>Si lo instalas ahora, el módulo viene activado. Si ya lo tenías, al actualizar llega apagado y te sale un aviso en el escritorio con un botón para activarlo, porque no me parece bien cambiarle a nadie la página de pago sin preguntar. <strong>Si ya lo usas para el desistimiento, con actualizar y pulsar ese botón tienes las dos cosas resueltas en el mismo sitio</strong>.</p>
<p>Lo que no hace, de momento, es la GARAN ni el aviso en la ficha de producto o en la cabecera, que quedan para más adelante. Si necesitas la GARAN ya, combínalo con Arthur Smith (o con Germanized, si ya lo usas) y desactiva el aviso en ese otro para que no salga dos veces.</p>
<p>Y ojo, que el plugin pasa de ocupar poco más de medio mega a unos 5 MB por los 48 archivos oficiales que lleva dentro. Eso es lo que ocupa en tu servidor, no lo que carga la web, que solo pide la imagen del idioma que toca y solo donde se muestra el aviso. El resto de detalles, ajuste por ajuste, los tienes en <a href="https://wordpress.org/plugins/eu-withdrawal-compliance/#faq" target="_blank" rel="nofollow noopener">las preguntas frecuentes de su ficha</a>.</p>
<h2>No quiero otro plugin ¿no decías que hay un código?</h2>
<p>Si prefieres no añadir otro plugin, o si el tuyo no cubre algo, tienes los snippets en <a href="https://github.com/fernandotellado/garan" target="_blank" rel="nofollow noopener">este repositorio de GitHub</a>, con las instrucciones completas en español y en inglés. Son tres y solo tienes que usar uno:</p>
<ul>
<li><strong>El independiente</strong> (<code>ayudawp-garantia-legal.php</code>), que no necesita ningún plugin.</li>
<li><strong>El complemento para Arthur Smith</strong>, que usa el aviso del plugin y lo coloca junto al botón.</li>
<li><strong>El complemento para GaranLabs</strong>, que hace lo mismo y además le arregla el idioma.</li>
</ul>
<p>El independiente hace todo esto:</p>
<ul>
<li>Muestra el aviso oficial justo encima del botón de pedido, en el checkout clásico y en el de bloques.</li>
<li>Lo incluye en los correos de confirmación al cliente y le adjunta el PDF oficial, porque muchos programas de correo bloquean las imágenes.</li>
<li>Añade debajo la nota de los tres años con un enlace a tus condiciones, solo si tu tienda está en España.</li>
<li>Usa el aviso en castellano en webs en catalán, euskera o gallego, y en cualquier idioma que no tenga aviso oficial.</li>
<li>Solo aparece si el carrito lleva algún producto físico.</li>
<li>Deja una nota en cada pedido con el aviso que se mostró, por si algún día te lo preguntan.</li>
</ul>
<p>Tiene tres modos de mostrarlo. El completo pone el aviso a la vista, el desplegable muestra una línea que lo abre debajo y la ventana es un botón que lo abre grande por encima de la página, con el popover nativo del navegador y sin JavaScript. <strong>Si tu tema pone el resumen del pedido en una columna estrecha, como Storefront en el checkout clásico, usa la ventana</strong>, porque el aviso completo se queda por debajo de 300 píxeles de ancho y no hay quien lo lea.</p>
<p>Lo que no hace tampoco es la GARAN, que depende de los datos de cada producto, así que para eso tendrás que tirar de un plugin. Si la necesitas, instala Arthur Smith, que es el que la resuelve con más cuidado, y usa su complemento en lugar del snippet independiente. Y si tu plugin ya hace una parte (market-it!, por ejemplo, pone el aviso en el checkout pero no en el correo), en los ajustes del snippet puedes apagar lo que ya tienes y quedarte con el resto.</p>
<p>Lo he probado con WordPress 7.1.1 y WooCommerce 11.1.1, en los dos checkouts, con los temas Twenty Twenty-Five y Storefront, con HPOS (el almacenamiento de pedidos de alto rendimiento de WooCommerce) activado y desactivado, y con la web en español, catalán, euskera, gallego, alemán e inglés. Aun así, <strong>haz un pedido de prueba y mira cómo te llega el correo antes de darlo por bueno</strong>.</p>
<h2>Consejos para tiendas en España</h2>
<ul>
<li><strong>Una sección de garantía en tus condiciones:</strong> con el ancla <code>#garantia-legal</code>, en la que expliques los tres años para bienes nuevos, los dos para contenidos digitales, el plazo pactado en segunda mano, la presunción de dos años y cómo reclamar. Es a donde enlaza la nota del snippet.</li>
<li><strong>Una página «Garantía legal» enlazada desde el pie:</strong> con el aviso a tamaño completo, el enlace a Your Europe y el texto del aviso para quien use un lector de pantalla (el PDF oficial tiene capa de texto, así que puedes copiarlo de ahí). Con eso cubres también lo del recordatorio general en la web, y si usas mi plugin, sus dos shortcodes te ponen el aviso y el enlace.</li>
<li><strong>Catalán, euskera y gallego:</strong> no hay aviso oficial en esas lenguas, así que lo razonable es el castellano. Confírmalo con tu asesoría si tu tienda funciona sobre todo en una de ellas.</li>
<li><strong>Segunda mano:</strong> si pactas un plazo menor (nunca por debajo de un año), déjalo claro en la ficha y en tus condiciones, porque el aviso solo habla de la regla general.</li>
<li><strong>Tienda física:</strong> imprime el PDF en A4 como mínimo, en color o en blanco y negro, y ponlo en un sitio visible, por ejemplo junto a la caja.</li>
</ul>
<h2>¿Tengo que hacer algo antes de que entre en vigor?</h2>
<p>Si vendes productos físicos a consumidores, sí, y te lleva poco rato:</p>
<ol>
<li>Elige uno de los plugins que te he contado (el mio, por supuesto) o el snippet de código.</li>
<li>Descarga el PNG en color y el PDF oficiales en tu idioma.</li>
<li>Coloca el aviso junto al botón de pedido y en el correo de confirmación.</li>
<li>Añade la nota de los tres años y la sección de garantía en tus condiciones.</li>
<li>Si vendes productos con una garantía de durabilidad del fabricante gratuita, de más de dos años y que cubra todo el producto, añade la GARAN a esos productos.</li>
<li>Haz un pedido de prueba y abre el correo en Gmail y en Outlook.</li>
<li>Si tienes tienda física, imprime el cartel.</li>
</ol>
<p>Y hasta aquí. Qué plugin usar, o si prefieres el código, lo decides tú, y si tienes dudas, o has probado alguno de estos plugins y te ha ido distinto, me tienes ahí abajo, en la sección de comentarios.</p>
<p>Si estás poniendo al día la parte legal de tu tienda, te interesa también repasar <a href="https://ayudawp.com/desistimiento-ue-woocommerce/" target="_blank" rel="ugc noopener">la función de desistimiento obligatoria en la UE</a>, <a href="https://ayudawp.com/registro-consentimiento-cookies-formularios-pedidos/" target="_blank" rel="ugc noopener">cómo guardar el registro de consentimiento de cookies, formularios y pedidos</a>, <a href="https://ayudawp.com/rgpd-woocommerce/" target="_blank" rel="ugc noopener">el RGPD en WooCommerce</a> y <a href="https://ayudawp.com/tienda-online-wordpress-legalidad-seguridad/" target="_blank" rel="ugc noopener">los errores legales y de seguridad que ponen en riesgo una tienda online</a>.</p>
<p>Ojalá sea el último cartel obligatorio del año, aunque no me lo creo ni yo.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ayudawp.com/aviso-de-garantia-legal-de-la-ue-en-woocommerce-garan-hay-algun-plugin-o-codigo-que-me-sirva-para-cumplir-en-mi-tienda/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Tu propio sistema de actualizaciones automáticas de plugins y temas premium ¿sin pasar por WordPress.org? ¿se puede?</title>
		<link>https://ayudawp.com/actualizaciones-automaticas-plugins-temas-premium/</link>
					<comments>https://ayudawp.com/actualizaciones-automaticas-plugins-temas-premium/#respond</comments>
		
		<dc:creator><![CDATA[Fernando Tellado]]></dc:creator>
		<pubDate>Tue, 22 Sep 2026 06:28:33 +0000</pubDate>
				<category><![CDATA[Plugins WordPress]]></category>
		<category><![CDATA[Programación + WordPress]]></category>
		<category><![CDATA[Temas WordPress]]></category>
		<category><![CDATA[Tutoriales - Trucos]]></category>
		<category><![CDATA[WordPress.com]]></category>
		<category><![CDATA[WordPress.org]]></category>
		<category><![CDATA[Avanzado]]></category>
		<category><![CDATA[Experto]]></category>
		<guid isPermaLink="false">https://ayudawp.com/?p=160297</guid>

					<description><![CDATA[En este artículo te cuento como montar un sistema de actualizaciones (de plugins o temas) propio, sin librerías externas, servicios adicionales ni plugins cliente, todo nativo…]]></description>
										<content:encoded><![CDATA[<p><strong>Ofrecer un plugin fuera del directorio de WordPress.org tiene una trampa que no descubres hasta la segunda versión</strong>, y no me refiero a cobrarlo, que eso lo resuelve cualquier tienda, es actualizarlo.</p>
<p>Un plugin que no está en el repositorio oficial no tiene por defecto ningún sistema de actualizaciones, y menos automático, así que cada cliente se queda para siempre en la versión que instaló y tú <strong>acabas repartiendo zips por correo o desde tu Ecommerce, uno a uno, rezando para que los suban a mano y lo hagan bien</strong>.</p>
<p>Llevo un tiempo distribuyendo así los plugins que distribuyo desde <a href="https://plugins.ayudawp.com/" target="_blank" rel="ugc noopener">plugins.ayudawp.com</a>, que es de donde salen hoy las actualizaciones de <a href="https://intellimmerce.com/" target="_blank" rel="noopener">Intellimmerce</a> y de <a href="https://vulgatai.com/" target="_blank" rel="noopener">VulgatAI</a>, y <strong>te voy a contar el montaje entero, que se resume en una línea en la cabecera del plugin, una clase y un fichero JSON</strong>.</p>
<p>No hacen falta librerías de código de terceros, ni servicios de pago, ni cuotas, ni un plugin cliente que tengan que instalarse tus clientes. Es <strong>un mecanismo del propio WordPress</strong> y lleva funcionando desde la versión 5.8, o sea desde julio de 2021.</p>
<p>Saca papel y boli para apuntar, eso sí, que hay tres o cuatro detalles finos que, si te los saltas, hacen que el sistema falle sin que te enteres. No verías ningún error por ningún lado, simplemente no le llegará nunca una actualización a nadie, y no quieres eso ¿verdad?</p>
<h2>¿No decías que no vendes plugins premium, que todos tus plugins son gratis?</h2>
<p>Que ya os veo venir, y con razón, <strong>que sí, que llevo años repitiendo que mis plugins del directorio de WordPress.org son gratis del todo, sin versión pro</strong>, sin pantallas de «desbloquea esto» y sin funciones a medias, porque estoy hasta las narices de instalar plugins que resultan ser el escaparate de otro plugin, y tú también ¿no?. Pero voy y ahora te suelto un manual para cobrar por plugins. ¿En qué quedamos?</p>
<p>A ver, lo que me revienta no es que alguien cobre por su trabajo, faltaría más, <strong>es que te traten como el burro de la zanahoria.</strong> Subes al directorio una versión mutilada, recoges instalaciones activas y valoraciones a costa del trabajo gratis de los traductores y de la gente que se molesta en reportarte fallos, y usas todo eso de embudo para vender la versión que de verdad hace lo que promete la descripción.</p>
<p>Aquí no hay nada de eso, los más de veinte plugins que tengo en el directorio hacen lo que dicen que hacen y ninguno lleva una versión de pago, son 100% gratis, no hay versión premium adicional. Intellimmerce y VulgatAI (y otros) no han pisado el directorio nunca, se venden como lo que son desde el primer día y no hay una versión gratuita suya que capar, porque no existe. Son cosas distintas en sitios distintos, y por eso <a href="https://plugins.ayudawp.com/" target="_blank" rel="ugc noopener">lo que vendo lo vendo en su tienda</a> y lo que regalo lo regalo entero.</p>
<p>Y fíjate en que esto no es solo una postura, es la razón técnica de que hayas leído todo lo anterior. Si hiciera freemium no habría necesitado nada de este artículo, porque el plugin gratis del directorio se actualizaría solo desde wordpress.org y llevaría dentro la comprobación de licencia y el actualizador de la versión de pago, que es como lo hace media industria.</p>
<p>Todo el montaje de la cabecera, el filtro y el JSON hace falta precisamente porque los de pago no tocan el directorio. Hasta Plugin Check te lo dice a su manera dándote un error por esa cabecera. Allí dentro, o una cosa o la otra.</p>
<p>¡Hala ya! Entiendo que debía la explicación, pero lo importante es que aquí estamos para aprender.</p>
<h2>Por qué no utilizo un servidor de actualizaciones</h2>
<p>En enero te hablé aquí de <a href="https://ayudawp.com/deploy-troy/" target="_blank" rel="ugc noopener">Deploy Troy</a>, el proyecto con el que montarte tu propio repositorio de plugins. Me pareció, <strong>y me sigue pareciendo, una solución muy bien pensada</strong>. Lo probé, lo monté en un subdominio con su WordPress dedicado, y <strong>lo he acabado quitando. ¿Y te preguntarás por qué?</strong></p>
<p>No es porque sea malo el sistema, que no lo es, sino porque <strong>me sobra</strong>. Troy pide un WordPress independiente, PHP 8.4, MySQL 8.0.19, un tipo de contenido propio, un servidor y un plugin cliente instalado en la web de cada cliente. Todo eso para resolver <strong>algo que el core de WordPress ya resuelve con una cabecera y un filtro</strong>.</p>
<p>Y hay un argumento que me pesó más que los requisitos, ya me dirás si te convence, y es que quien vende plugins depende de su dominio por narices, porque ahí está la tienda, ahí está la descarga y ahí estaría cualquier validación de licencia.</p>
<p>Añadir el archivo (JSON) de actualizaciones a ese mismo dominio no supone problema alguno, de hecho Troy no te quita esa dependencia, te añade dos encima, la del segundo servidor y la de quien mantenga el proyecto. <strong>Puestos a depender de una sola persona, que sea de mí, que es lo único inevitable en este asunto.</strong></p>
<p>Dicho todo esto, si distribuyes veinte plugins a veinte mil sitios, con dependencias entre ellos, canal beta y estadísticas de uso, Troy te va a dar todo eso hecho y lo mío se te va a quedar corto, también tienes que valorarlo ¿vale?</p>
<p>Seguimos… o más bien empezamos…</p>
<h2>WordPress te permite ofrecer actualizaciones de manera nativa</h2>
<p>Ya sabes que me encanta usar todo lo que viene de serie, y más si encima es gratis. En este caso la cosa se llama <code>Update URI</code> y entró en el core en mayo de 2021 (<a href="https://make.wordpress.org/core/2021/06/29/introducing-update-uri-plugin-header-in-wordpress-5-8/" target="_blank" rel="nofollow noopener">aquí la nota de desarrollo</a>). Funciona en cuatro pasos:</p>
<ol>
<li>Tu plugin declara en su cabecera <strong>de dónde vienen sus actualizaciones</strong>.</li>
<li>Como ese dominio no es wordpress.org, la API oficial deja de ofrecer actualizaciones para ese plugin, y el core dispara en su lugar <strong>un filtro cuyo nombre sale de ese dominio</strong>, por ejemplo <code>update_plugins_plugins.ayudawp.com</code>.</li>
<li>Tu plugin contesta a ese filtro consultando <strong>un pequeño archivo JSON en tu servidor</strong>, cacheando la respuesta y devolviéndole al core qué versión hay y de dónde bajarla.</li>
<li><strong>El core de WordPress hace absolutamente todo lo demás</strong>: el aviso en la lista de plugins, el botón, la barra de progreso, la ventana de detalles y las actualizaciones automáticas si el cliente las tiene activadas.</li>
</ol>
<p>Antes de que te ilusiones de más, un matiz importante es que <strong>la cabecera no impide que la web de tu cliente le hable a wordpress.org de tu plugin.</strong></p>
<p>Si te vas a <code>wp-includes/update.php</code> y miras la función <code>wp_update_plugins()</code>, verás que el core manda la lista completa de plugins instalados a <code>api.wordpress.org</code> pase lo que pase. Lo que cambia es que la API no <em>responde</em> por el tuyo. O sea, wordpress.org sigue <em>sabiendo</em> que tu plugin existe y de en cuántas webs está (más abajo te cuento cómo taparlo, que se puede).</p>
<p>Que la API no responda por el tuyo tampoco hay que creérselo, que se comprueba fácil. En una instalación de pruebas elige una carpeta con el nombre de un plugin que sí esté en el directorio, ponle una versión vieja para que haya actualización disponible y lanza la comprobación dos veces, una sin la cabecera y otra con ella:</p>
<pre>akismet/akismet.php 3.0.0, sin Update URI  → wordpress.org ofrece la 5.7.2
akismet/akismet.php 3.0.0, con Update URI  → wordpress.org no devuelve nada</pre>
<p><strong>La API lee la cabecera que le mandas y se quita de enmedio</strong>, que es exactamente para lo que se creó.</p>
<p>Antes de WordPress 5.8, si la carpeta de tu plugin tenía un nombre que nadie había registrado todavía en el directorio, cualquiera podía registrarlo allí y sus actualizaciones acababan instalándose encima del tuyo. El fallo tiene hasta identificador propio, el CVE-2021-44223, con una puntuación de 9,8 sobre 10 y calificado de crítico.</p>
<p>Por cierto, lo mismo existe para temas desde WordPress 6.1, con el filtro <code>update_themes_{$hostname}</code>. Aquí voy a hablar de plugins, pero el mecanismo es idéntico.</p>
<p><strong>Ahora ya sí, de verdad, empezamos…</strong></p>
<h2>Cómo montar un plugin para distribuirlo con actualizaciones automáticas</h2>
<p>Parece algo pero en realidad una vez tienes hecho el primero <strong>es tremendamente sencillo, y nada exigente técnicamente, casi sorprende que sea algo tan trivial y rápido</strong>.</p>
<h3>La cabecera y la constante</h3>
<p>Esta es la única parte del plugin que WordPress mira por su cuenta, sin que tú le pidas nada, así que conviene entender bien qué lee exactamente y qué se inventa tu código.</p>
<pre>&lt;?php
/**
 * Plugin Name: Mi Plugin
 * Plugin URI:  https://miplugin.com/
 * Version:     1.0.0
 * Author:      Fernando Tellado
 * Update URI:  https://plugins.ayudawp.com/miplugin
 */

define( 'MIPLUGIN_FILE', __FILE__ );
define( 'MIPLUGIN_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );

// El mismo valor que la cabecera de arriba, y tiene que seguir siendo el mismo.
define( 'MIPLUGIN_UPDATE_URI', 'https://plugins.ayudawp.com/miplugin' );</pre>
<p>Vamos línea por línea, que cada una está ahí por un motivo.</p>
<ul>
<li><strong>La cabecera <code>Update URI</code> es la que enciende todo el mecanismo.</strong> Va dentro del bloque de comentario del fichero principal, con el resto de cabeceras del plugin, y no en un fichero aparte ni en un include. Si no está, WordPress no dispara ningún filtro y tu plugin se queda como cualquier plugin suelto al que nadie actualiza nunca.</li>
<li><strong>De esa URL, WordPress solo se queda con el dominio.</strong> La línea que lo hace es <code>wp_parse_url( sanitize_url( $plugin_data['UpdateURI'] ), PHP_URL_HOST )</code>, así que de todo lo que has escrito se guarda <code>plugins.ayudawp.com</code> y tira el resto. A ese dominio le pega delante el prefijo <code>update_plugins_</code> y ya tiene el nombre del filtro que va a disparar, que queda <code>update_plugins_plugins.ayudawp.com</code>. Sí, con puntos en medio del nombre del filtro. Queda rarísimo y es correcto.</li>
<li><strong>Esa URL no tiene por qué existir</strong>, y es la parte que más despista. WordPress no la visita jamás, no descarga nada de ahí y le da igual si devuelve un 404 o si el dominio ni siquiera resuelve. Lo único que hace es sacarle el dominio y luego guardarla tal cual como identificador de la actualización. Quien decide de dónde se baja el JSON y de dónde se baja el zip es tu código, no esta línea. Dicho lo cual, ponla apuntando a la página del plugin en vez de a algo inventado, que alguien acabará copiándola del código y siguiéndola.</li>
<li><strong>El dominio tiene que ser tuyo, no wordpress.org.</strong> Si ahí pones una dirección del directorio oficial, la API de wordpress.org vuelve a hacerse cargo del plugin y todo lo que viene después sobra. Es el interruptor que decide quién manda sobre las actualizaciones de ese plugin, y solo admite un dueño.</li>
<li><strong>La constante repite el valor de la cabecera, y no es un despiste.</strong> Tu actualizador necesita ese dominio para saber a qué filtro engancharse, y sacarlo de la cabecera en tiempo de ejecución significa cargar un fichero de <code>wp-admin</code> y llamar a <code>get_plugin_data()</code> en cada arranque, que es mucho gasto para lo poco que aporta. Una constante es gratis y está disponible desde el primer momento. <strong>El precio de esa comodidad es que el mismo valor pasa a vivir en dos sitios.</strong></li>
<li><strong>Y por eso las dos se cambian a la vez, siempre.</strong> WordPress saca el nombre del filtro de la cabecera y tu actualizador engancha ese filtro leyendo la constante. Si tocas solo una, el plugin se queda enganchado a un filtro que nadie dispara. No hay error, no hay aviso y no hay actualizaciones. Nunca más.</li>
<li><strong>Las otras dos constantes son para más adelante.</strong> <code>MIPLUGIN_PLUGIN_BASENAME</code> la va a usar el actualizador para comprobar que la pregunta que le llega es sobre este plugin y no sobre otro tuyo servido desde el mismo dominio, que es el fallo más caro de todo el montaje y lo veremos luego. Y <code>MIPLUGIN_FILE</code> le servirá para leer el nombre y el autor de su propia cabecera cuando tenga que pintar la ventana de detalles. Se definen aquí porque aquí es donde <code>__FILE__</code> vale lo que tiene que valer.</li>
</ul>
<p>Un detalle importante es que WordPress lee las cabeceras con <code>get_file_data()</code>, que carga solo los primeros 8 KB del fichero. Si tu plugin arranca con el texto entero de la licencia GPL en comentarios, o con un bloque de documentación kilométrico por delante, el <code>Update URI</code> se puede quedar fuera de esos 8 KB y WordPress no llegará a verlo.</p>
<p>El síntoma es idéntico al de la constante mal copiada, o sea ninguno, porque el plugin funciona, no da ni un error y no se actualiza jamás. Deja las cabeceras arriba del todo y te ahorras el disgusto.</p>
<p>Y avisado quedas también de que la cabecera es justo lo que hace que <a href="https://ayudawp.com/tag/plugin-check/" target="_blank" rel="noopener">Plugin Check</a> te dé un error de tipo <code>plugin_updater_detected</code>, porque wordpress.org no la admite en plugins alojados allí. Es correcto que lo dé, no es un fallo que arreglar, es el precio de haber elegido otro canal.</p>
<h3>Carpetas que tienes que preparar en tu servidor</h3>
<p>Dos carpetas en tu dominio, servidas tal cual, sin login ni nada, limpias:</p>
<pre>/updates/
    miplugin.json
    mi-otro-plugin.json
/files/
    miplugin/
        miplugin-1.0.0.zip
        miplugin-1.1.0.zip
        miplugin-1.2.0.zip
    mi-otro-plugin/
        mi-otro-plugin-2.3.0.zip
        mi-otro-plugin-2.3.1.zip</pre>
<p>Los JSON pueden ir todos sueltos en <code>updates/</code> porque <strong>hay uno por plugin y no crecen, solo los vas sustituyendo</strong>. Los zips sí, es mejor que vayan en carpeta propia porque sí se van acumulando, uno por versión publicada, y <strong>conviene no borrar los viejos</strong> para poder volver atrás si una sale malamente.</p>
<h4>No uses las descargas de WooCommerce</h4>
<p>Esto es una puntualización importante, para que no trates de ahorrarte pasos, y es que <strong>el zip no puede ser un archivo descargable de WooCommerce</strong>, no cometas ese error.</p>
<p>Quien lo descarga es el servidor de tu cliente, sin sesión y sin cookies, así que la carpeta <code>wp-content/uploads/woocommerce_uploads/</code> no vale, porque va protegida con un <code>deny from all</code> y devuelve un 403. Además, la URL de descarga de Woo, esa con <code>?download_file=</code> y <code>&amp;key=</code>, tampoco, porque es por pedido, gasta el límite de descargas del cliente y caduca.</p>
<p>Tienes que alojar los zip de tu plugin o tema en una carpeta normal y pública, servida como cualquier otro archivo.</p>
<p>Además, apunta que <strong>deberías desactivar el listado de directorios en las dos carpetas</strong>, con un <code>Options -Indexes</code> en el <code>.htaccess</code> o desde el panel de tu hosting. No es una cuestión de seguridad, que el zip es GPL, es que un listado abierto le cuenta a cualquiera tu histórico completo, o sea cuántas versiones sacas, a qué ritmo y cuándo dejaste de sacarlas. Eso es información de negocio, no de código.</p>
<p>Que la URL del zip sea pública no es un agujero, aunque a alguno le rechinen los dientes desde hace dos párrafos. El código es GPL de todas formas, y <strong>lo que protege una venta es el acceso a la tienda, al soporte y a las actualizaciones, no ofuscar una URL que cualquiera puede leer del JSON</strong> en dos segundos. Si algún día metes licencias, la validación irá en el endpoint, no en esconder el fichero.</p>
<h3>El archivo JSON con la información de las actualizaciones</h3>
<p>Este es el fichero que va en la carpeta <code>/updates</code>, con todos los campos recomendables, y está pensado para que <strong>en cada versión solo cambie el número de versión</strong>:</p>
<pre>{
  "version": "1.1.0",
  "package": "https://plugins.ayudawp.com/files/miplugin/miplugin-1.1.0.zip",
  "url": "https://miplugin.com/",
  "tested": "7.1",
  "requires": "6.5",
  "requires_php": "7.4",
  "sections": {
    "description": "Lo que hace el plugin, en dos frases.",
    "changelog": "&lt;p&gt;Changelog completo: &lt;a href=\"https://miplugin.com/changelog.txt\" target=\"_blank\" rel=\"noopener\"&gt;miplugin.com/changelog.txt&lt;/a&gt;&lt;/p&gt;"
  }
}</pre>
<table>
<tbody>
<tr>
<th>Campo</th>
<th>Obligatorio</th>
<th>Para qué sirve</th>
</tr>
<tr>
<td><code>version</code></td>
<td>Sí</td>
<td>La versión publicada. Es lo único que el core exige. Se compara con la instalada y si no es estrictamente mayor no pasa nada.</td>
</tr>
<tr>
<td><code>package</code></td>
<td>Sí</td>
<td>La URL del zip. Sin esto el cliente ve el aviso pero no puede actualizar: WordPress escribe literalmente «La actualización automática no está disponible para este plugin».</td>
</tr>
<tr>
<td><code>url</code></td>
<td>No</td>
<td>La URL que WordPress mete en el correo de aviso que manda tras una actualización automática, salga bien o falle. No sirve para el enlace de «Ver detalles», que va siempre por el <code>slug</code>.</td>
</tr>
<tr>
<td><code>tested</code>, <code>requires</code>, <code>requires_php</code></td>
<td>No</td>
<td>Lo que WordPress enseña y usa para avisar si el sitio no cumple. Solo se modifican cuando sale una versión nueva de WordPress.</td>
</tr>
<tr>
<td><code>sections</code></td>
<td>No</td>
<td>Las pestañas de la ventana de detalles. Admite HTML.</td>
</tr>
<tr>
<td><code>upgrade_notice</code></td>
<td>No</td>
<td>El aviso corto que WordPress pinta bajo el nombre del plugin en «Escritorio &gt; Actualizaciones». Casi nadie sabe que existe fuera del directorio oficial.</td>
</tr>
</tbody>
</table>
<p>Hay un campo más que no está en la tabla y que casi nadie usa, el <code>translations</code>, un array con <code>language</code> y <code>package</code> por idioma. Si repartes los ficheros de traducción por separado en vez de empaquetarlos dentro del plugin, el core también te los actualiza por esta vía. Si los llevas dentro del zip, como suele ser lo normal, ni te hace falta.</p>
<p>Y fíjate en tres ausencias, que son deliberadas.</p>
<ul>
<li><strong>No hay <code>slug</code>.</strong> El slug lo sabe el propio plugin, va en una constante de su clase, y no tiene ningún sentido mandarlo desde el servidor. Ojo, que no esté en el JSON no significa que no haga falta, porque es imprescindible y ahora verás por qué.</li>
<li><strong>No hay <code>last_updated</code>.</strong> Es un campo que habría que actualizar a mano en cada versión y que, en cuanto te lo saltes una vez, enseña una fecha falsa. Sin él WordPress simplemente no muestra esa línea, que es bastante mejor que mostrarla mal.</li>
<li><strong>El changelog es un enlace, no una lista.</strong> Copiar aquí las notas de cada versión significa escribirlas dos veces, en tu <code>changelog.txt</code> y en el JSON, y a la segunda entrega ya están desincronizadas. Con el enlace, <code>sections</code> no se toca nunca más. El <code>target="_blank"</code> de ahí dentro no es decorativo: la ventana de detalles es un iframe pequeño dentro del escritorio, y sin él el fichero de texto se abriría ahí dentro, apretujado.</li>
</ul>
<h3>El actualizador automático</h3>
<p>Se suele decir que con este sistema «no programas nada de la actualización», y es mentira, o casi. Es verdad que no programas la descarga, ni la instalación, ni la interfaz, que todo eso lo pone el core. Pero alguien tiene que escribir la clase que contesta al filtro, y esa clase tiene cuatro cosas que hacer, cada una con su truqui:</p>
<ol>
<li><strong>Engancharse</strong> al filtro que WordPress dispara para tu dominio.</li>
<li><strong>Contestar</strong> a ese filtro diciendo qué versión hay y de dónde bajarla.</li>
<li><strong>Servir la ventana de detalles</strong>, que el core no va a rellenar por ti.</li>
<li><strong>Cachear</strong> la respuesta de tu servidor, para no machacarlo ni hacer esperar al cliente.</li>
</ol>
<p>Y hay un quinto paso que no está dentro de la clase pero que decide si la clase llega a ejecutarse siquiera, que es dónde la cargas. Vamos uno por uno, y al final te dejo el fichero completo para copiarlo de una vez.</p>
<h4>Paso 1. El enganche al filtro</h4>
<p>Este es el arranque de la clase, con las tres constantes de configuración y el método que la conecta con WordPress. Es lo único que se ejecuta siempre, en cada carga de cada página del escritorio de tu cliente, así que tiene que ser barato.</p>
<pre>class Miplugin_Updater {

    const ENDPOINT  = 'https://plugins.ayudawp.com/updates/miplugin.json';
    const SLUG      = 'miplugin';
    const TRANSIENT = 'miplugin_update';

    public function hooks() {
        $host = $this-&gt;host();

        // Sin host, o publicado en WordPress.org después de todo, y en los dos
        // casos esto no debe meterse en medio.
        if ( '' === $host || false !== strpos( $host, 'wordpress.org' ) ) {
            return;
        }

        add_filter( "update_plugins_{$host}", array( $this, 'check' ), 10, 3 );
        add_filter( 'plugins_api', array( $this, 'information' ), 20, 3 );
        add_action( 'upgrader_process_complete', array( $this, 'flush' ) );

        // Entrar en Escritorio &gt; Actualizaciones es preguntar si hay algo nuevo,
        // así que ahí se tira la caché antes de que el core haga su comprobación.
        // Prioridad 5 porque el core engancha su wp_update_plugins() en la 10.
        add_action( 'load-update-core.php', array( $this, 'flush' ), 5 );
    }

    private function host() {
        if ( ! defined( 'MIPLUGIN_UPDATE_URI' ) || '' === MIPLUGIN_UPDATE_URI ) {
            return '';
        }

        $host = wp_parse_url( sanitize_url( MIPLUGIN_UPDATE_URI ), PHP_URL_HOST );

        return is_string( $host ) ? $host : '';
    }</pre>
<p>Las constantes son las tres cosas que cambias cuando adaptes esto a tu plugin. <code>ENDPOINT</code> es la URL del JSON, <code>SLUG</code> es el nombre de la carpeta del plugin y <code>TRANSIENT</code> es el nombre de la opción donde guardas la respuesta cacheada.</p>
<p>Y hay dos detalles del método <code>hooks()</code> que no son adorno.</p>
<ul>
<li><strong>La salida temprana si el dominio es wordpress.org.</strong> El día que decidas publicar el plugin en el directorio oficial, esto se aparta solo en vez de pelearse con el core.</li>
<li><strong>La prioridad 5 en <code>load-update-core.php</code>.</strong> El core engancha su <code>wp_update_plugins()</code> a esa misma acción con prioridad 10, y una caché que se limpia <em>después</em> de que te hayan preguntado no le sirve a nadie. Con el 5, la pantalla de Escritorio &gt; Actualizaciones dice siempre la verdad, y es la que hay que abrir para comprobar si algo se ha publicado.</li>
</ul>
<h4>Paso 2. La respuesta al core</h4>
<p>Ya estás enganchado, o sea que ahora te van a preguntar. Este método es el que WordPress llama cuando quiere saber si hay versión nueva, y el que decide lo que acaba viendo tu cliente en su listado de plugins.</p>
<pre>    public function check( $update, $plugin_data, $plugin_file = '' ) {
        if ( ! $this-&gt;is_this_plugin( $plugin_file, $plugin_data ) ) {
            return $update;
        }

        $remote = $this-&gt;remote();
        if ( ! is_array( $remote ) || empty( $remote['version'] ) ) {
            return $update;
        }

        $answer = array(
            'slug'    =&gt; self::SLUG,
            'version' =&gt; sanitize_text_field( (string) $remote['version'] ),
        );

        // Sin paquete no hay nada que instalar, así que se avisa de la versión
        // pero no se ofrece un botón roto.
        if ( ! empty( $remote['package'] ) ) {
            $answer['package'] = esc_url_raw( (string) $remote['package'] );
        }

        // Este es el enlace que WordPress mete en el correo de aviso tras una
        // actualización automática. Sin respaldo, que mejor sin enlace que con
        // uno que no lleve a ninguna parte.
        if ( ! empty( $remote['url'] ) ) {
            $answer['url'] = esc_url_raw( (string) $remote['url'] );
        }

        foreach ( array( 'tested', 'requires', 'requires_php', 'upgrade_notice' ) as $key ) {
            if ( ! empty( $remote[ $key ] ) ) {
                $answer[ $key ] = sanitize_text_field( (string) $remote[ $key ] );
            }
        }

        return $answer;
    }

    private function is_this_plugin( $plugin_file, $plugin_data ) {
        if ( '' !== (string) $plugin_file ) {
            return MIPLUGIN_PLUGIN_BASENAME === $plugin_file;
        }

        if ( is_array( $plugin_data ) &amp;&amp; ! empty( $plugin_data['UpdateURI'] ) ) {
            return MIPLUGIN_UPDATE_URI === $plugin_data['UpdateURI'];
        }

        return false;
    }</pre>
<ul>
<li><strong>Primera trampa, la más cara de todo el montaje y la más fácil de no ver hasta que ya te ha explotado.</strong> El filtro se llama por el dominio, no por el plugin. WordPress recorre todos los plugins instalados y lo dispara una vez por cada uno que declare ese dominio, así que el día que tengas dos plugins tuyos servidos desde el mismo sitio, los dos actualizadores van a recibir las preguntas de ambos. Un actualizador que conteste sin mirar por quién le preguntan le ofrecerá su propio zip al otro plugin, y la web del cliente acabará instalando el plugin equivocado encima de uno que estaba perfectamente sano, dejándolo desactivado y con dos carpetas en el listado. De ahí que lo primero que hace el método sea comprobar que la pregunta va con él.</li>
<li><strong>Segunda trampa, y es el detalle más sutil del artículo</strong>, porque se ve mirando lo que el método <em>no</em> hace. Fíjate en que la respuesta se devuelve siempre, haya versión nueva o no. Parece un desperdicio, ya que si el cliente tiene la última no hay nada que ofrecerle.</li>
</ul>
<p>Pues de eso depende que tus clientes puedan usar las actualizaciones automáticas. El core hace su <code>version_compare</code> y, si tu versión no es mayor, mete igualmente la respuesta en el apartado <code>no_update</code> del transitorio. Y en <code>wp-admin/includes/class-wp-plugins-list-table.php</code> la columna «Actualizaciones automáticas» solo marca ese plugin como compatible si aparece en <code>response</code> o en <code>no_update</code>.</p>
<p>Traducido a lo que ve tu cliente, <strong>si contestas siempre, ve el enlace de «Activar actualizaciones automáticas», y si contestas solo cuando hay novedad, esa columna se le queda en blanco</strong> y pierde las automáticas sin saber por qué.</p>
<h4>Paso 3. La ventana de detalles</h4>
<p>Con lo anterior ya tienes el aviso, el botón y la barra de progreso. Pero te queda un enlace suelto, el de «Ver los detalles de la versión», y ese lo tienes que atender tú.</p>
<pre>    public function information( $result, $action, $args ) {
        if ( 'plugin_information' !== $action ) {
            return $result;
        }

        if ( ! isset( $args-&gt;slug ) || self::SLUG !== $args-&gt;slug ) {
            return $result;
        }

        $remote = $this-&gt;remote();
        if ( ! is_array( $remote ) || empty( $remote['version'] ) ) {
            return $result;
        }

        if ( ! function_exists( 'get_plugin_data' ) ) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        $headers = get_plugin_data( MIPLUGIN_FILE, false, false );

        $sections = array();
        if ( ! empty( $remote['sections'] ) &amp;&amp; is_array( $remote['sections'] ) ) {
            foreach ( $remote['sections'] as $name =&gt; $content ) {
                $sections[ sanitize_key( $name ) ] = wp_kses_post( (string) $content );
            }
        }
        if ( empty( $sections['description'] ) ) {
            $sections['description'] = wp_kses_post( $headers['Description'] );
        }

        return (object) array(
            'name'          =&gt; $headers['Name'],
            'slug'          =&gt; self::SLUG,
            'version'       =&gt; sanitize_text_field( (string) $remote['version'] ),
            'author'        =&gt; $headers['Author'],
            'homepage'      =&gt; $headers['PluginURI'],
            'requires'      =&gt; ! empty( $remote['requires'] ) ? sanitize_text_field( (string) $remote['requires'] ) : $headers['RequiresWP'],
            'tested'        =&gt; ! empty( $remote['tested'] ) ? sanitize_text_field( (string) $remote['tested'] ) : '',
            'requires_php'  =&gt; ! empty( $remote['requires_php'] ) ? sanitize_text_field( (string) $remote['requires_php'] ) : $headers['RequiresPHP'],
            'download_link' =&gt; ! empty( $remote['package'] ) ? esc_url_raw( (string) $remote['package'] ) : '',
            'sections'      =&gt; $sections,
        );
    }</pre>
<p>Esto no es un extra bonito, <strong>es obligatorio</strong>, y aquí es donde te la juegas si copias un tutorial a medias.</p>
<p>Mira lo que hace el core en <code>wp-admin/includes/update.php</code>. Si tu respuesta trae <code>slug</code>, el enlace de «Ver detalles» apunta a la pantalla interna <code>plugin-install.php</code>, y esa pantalla le pregunta a wordpress.org, donde tu plugin no existe. Lo que se encuentra tu cliente es un «Plugin not found» encima de una actualización que estaba perfecta.</p>
<p>Y no puedes escaparte quitando el <code>slug</code>, aunque en el listado de plugins parezca que sí. En <code>wp-admin/update-core.php</code>, la pantalla de «Escritorio &gt; Actualizaciones» construye ese enlace usando <code>$plugin_data-&gt;update-&gt;slug</code> a pelo, sin ninguna alternativa. <strong>Sin slug, el cliente se encuentra un enlace roto</strong> justo en la pantalla donde va a mirar. <strong>Así que mandas <code>slug</code> y enganchas <code>plugins_api</code>. No hay atajo.</strong></p>
<p>Fíjate también en que el nombre, el autor y la web salen de <code>get_plugin_data()</code>, o sea de la propia cabecera del plugin y no del servidor. Así el JSON se queda corto y no tienes dos sitios que mantener sincronizados.</p>
<h4>Paso 4. La caché</h4>
<p>Los dos métodos anteriores llaman a <code>remote()</code>, que es el único de toda la clase que habla con tu servidor. Sin caché, cada carga del escritorio de cada cliente sería una petición a tu dominio, y multiplica eso por todos los que te hayan comprado el plugin.</p>
<pre>    private function remote() {
        $cached = get_transient( self::TRANSIENT );
        if ( is_array( $cached ) ) {
            return $cached;
        }
        if ( 'none' === $cached ) {
            return null;
        }

        $response = wp_remote_get(
            self::ENDPOINT,
            array(
                // Como el core, generoso por cron, donde nadie espera, y corto en
                // primer plano, donde hay alguien mirando una pantalla en blanco.
                'timeout' =&gt; wp_doing_cron() ? 30 : 5,
                'headers' =&gt; array( 'Accept' =&gt; 'application/json' ),
            )
        );

        $body = ( ! is_wp_error( $response ) &amp;&amp; 200 === (int) wp_remote_retrieve_response_code( $response ) )
            ? json_decode( wp_remote_retrieve_body( $response ), true )
            : null;

        if ( ! is_array( $body ) || empty( $body['version'] ) ) {
            set_transient( self::TRANSIENT, 'none', HOUR_IN_SECONDS );
            return null;
        }

        set_transient( self::TRANSIENT, $body, 12 * HOUR_IN_SECONDS );

        return $body;
    }

    public function flush() {
        delete_transient( self::TRANSIENT );
    }
}</pre>
<p>Hay dos duraciones distintas y las dos tienen su motivo. Doce horas cuando todo va bien, para que un escritorio muy transitado no se convierta en un servidor muy transitado. Y solo una hora cuando tu servidor no contesta, para que una caída tuya no se traduzca en una petición fallida en cada carga del escritorio de cada cliente.</p>
<p>Y sobre el <code>timeout</code>, fíjate en que no es un número fijo, y eso está copiado del core. Para su propia petición a wordpress.org, WordPress usa <code>3 + (int) ( count( $plugins ) / 10 )</code> cuando hay alguien delante, o sea cuatro o cinco segundos en una web normal, y sube a 30 cuando corre por cron. La lógica es buena y no hay razón para inventarse otra. E</p>
<p>n primer plano, cada segundo de más es un segundo que tu cliente se come mirando un listado de plugins que no carga, y por cron no hay nadie esperando y más vale aguantar que quedarse sin comprobar.</p>
<h4>Paso 5. Dónde cargas la clase</h4>
<p>La clase ya está entera, pero falta lo que decide si llega a ejecutarse. Esto va en el fichero principal del plugin y el orden importa mucho más de lo que parece.</p>
<pre>// Antes que nada. Sobre todo, antes de cualquier comprobación de dependencias.
require_once plugin_dir_path( __FILE__ ) . 'includes/class-updater.php';
( new Miplugin_Updater() )-&gt;hooks();

// Y a partir de aquí, lo que sea que necesite tu plugin para arrancar.
if ( ! class_exists( 'WooCommerce' ) ) {
    add_action( 'admin_notices', 'miplugin_aviso_dependencia' );
    return;
}</pre>
<p>Casi todos los plugins hacen alguna comprobación antes de arrancar del todo, sea que exista una dependencia, que la versión de PHP llegue o que la licencia valga. Y casi todos meten la carga entera dentro de esa comprobación, actualizador incluido.</p>
<p>El día que esa comprobación falle, y va a fallar alguna vez, tu plugin se queda activo pero deja de enganchar el filtro y no vuelve a recibir una actualización nunca. <strong>Y ese es justo el momento en el que más falta te hace poder mandar un arreglo.</strong></p>
<p>El actualizador es la pieza que no puede depender de nada, así que va la primera y fuera de cualquier retorno temprano. Cuidado también con lo que use tu clase, que si tira de una función auxiliar que cargas más abajo la has liado igual, y encima con un error fatal.</p>
<h4>La clase completa</h4>
<p>Todo lo anterior junto, listo para pegar en <code>includes/class-updater.php</code>. Son 176 líneas contando comentarios y líneas en blanco, y es todo el código que vas a escribir para esto, y te lo dejo casi hecho, así que…</p>
<pre>&lt;?php
/**
 * Actualizaciones desde el dominio propio, sin pasar por WordPress.org.
 *
 * @package Miplugin
 */

// Sin acceso directo.
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Miplugin_Updater {

    const ENDPOINT  = 'https://plugins.ayudawp.com/updates/miplugin.json';
    const SLUG      = 'miplugin';
    const TRANSIENT = 'miplugin_update';

    public function hooks() {
        $host = $this-&gt;host();

        // Sin host, o publicado en WordPress.org después de todo, y en los dos
        // casos esto no debe meterse en medio.
        if ( '' === $host || false !== strpos( $host, 'wordpress.org' ) ) {
            return;
        }

        add_filter( "update_plugins_{$host}", array( $this, 'check' ), 10, 3 );
        add_filter( 'plugins_api', array( $this, 'information' ), 20, 3 );
        add_action( 'upgrader_process_complete', array( $this, 'flush' ) );

        // Entrar en Escritorio &gt; Actualizaciones es preguntar si hay algo nuevo,
        // así que ahí se tira la caché antes de que el core haga su comprobación.
        // Prioridad 5 porque el core engancha su wp_update_plugins() en la 10.
        add_action( 'load-update-core.php', array( $this, 'flush' ), 5 );
    }

    private function host() {
        if ( ! defined( 'MIPLUGIN_UPDATE_URI' ) || '' === MIPLUGIN_UPDATE_URI ) {
            return '';
        }

        $host = wp_parse_url( sanitize_url( MIPLUGIN_UPDATE_URI ), PHP_URL_HOST );

        return is_string( $host ) ? $host : '';
    }

    public function check( $update, $plugin_data, $plugin_file = '' ) {
        if ( ! $this-&gt;is_this_plugin( $plugin_file, $plugin_data ) ) {
            return $update;
        }

        $remote = $this-&gt;remote();
        if ( ! is_array( $remote ) || empty( $remote['version'] ) ) {
            return $update;
        }

        $answer = array(
            'slug'    =&gt; self::SLUG,
            'version' =&gt; sanitize_text_field( (string) $remote['version'] ),
        );

        // Sin paquete no hay nada que instalar, así que se avisa de la versión
        // pero no se ofrece un botón roto.
        if ( ! empty( $remote['package'] ) ) {
            $answer['package'] = esc_url_raw( (string) $remote['package'] );
        }

        // Este es el enlace que WordPress mete en el correo de aviso tras una
        // actualización automática. Sin respaldo, que mejor sin enlace que con
        // uno que no lleve a ninguna parte.
        if ( ! empty( $remote['url'] ) ) {
            $answer['url'] = esc_url_raw( (string) $remote['url'] );
        }

        foreach ( array( 'tested', 'requires', 'requires_php', 'upgrade_notice' ) as $key ) {
            if ( ! empty( $remote[ $key ] ) ) {
                $answer[ $key ] = sanitize_text_field( (string) $remote[ $key ] );
            }
        }

        return $answer;
    }

    private function is_this_plugin( $plugin_file, $plugin_data ) {
        if ( '' !== (string) $plugin_file ) {
            return MIPLUGIN_PLUGIN_BASENAME === $plugin_file;
        }

        if ( is_array( $plugin_data ) &amp;&amp; ! empty( $plugin_data['UpdateURI'] ) ) {
            return MIPLUGIN_UPDATE_URI === $plugin_data['UpdateURI'];
        }

        return false;
    }

    public function information( $result, $action, $args ) {
        if ( 'plugin_information' !== $action ) {
            return $result;
        }

        if ( ! isset( $args-&gt;slug ) || self::SLUG !== $args-&gt;slug ) {
            return $result;
        }

        $remote = $this-&gt;remote();
        if ( ! is_array( $remote ) || empty( $remote['version'] ) ) {
            return $result;
        }

        if ( ! function_exists( 'get_plugin_data' ) ) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        $headers = get_plugin_data( MIPLUGIN_FILE, false, false );

        $sections = array();
        if ( ! empty( $remote['sections'] ) &amp;&amp; is_array( $remote['sections'] ) ) {
            foreach ( $remote['sections'] as $name =&gt; $content ) {
                $sections[ sanitize_key( $name ) ] = wp_kses_post( (string) $content );
            }
        }
        if ( empty( $sections['description'] ) ) {
            $sections['description'] = wp_kses_post( $headers['Description'] );
        }

        return (object) array(
            'name'          =&gt; $headers['Name'],
            'slug'          =&gt; self::SLUG,
            'version'       =&gt; sanitize_text_field( (string) $remote['version'] ),
            'author'        =&gt; $headers['Author'],
            'homepage'      =&gt; $headers['PluginURI'],
            'requires'      =&gt; ! empty( $remote['requires'] ) ? sanitize_text_field( (string) $remote['requires'] ) : $headers['RequiresWP'],
            'tested'        =&gt; ! empty( $remote['tested'] ) ? sanitize_text_field( (string) $remote['tested'] ) : '',
            'requires_php'  =&gt; ! empty( $remote['requires_php'] ) ? sanitize_text_field( (string) $remote['requires_php'] ) : $headers['RequiresPHP'],
            'download_link' =&gt; ! empty( $remote['package'] ) ? esc_url_raw( (string) $remote['package'] ) : '',
            'sections'      =&gt; $sections,
        );
    }

    private function remote() {
        $cached = get_transient( self::TRANSIENT );
        if ( is_array( $cached ) ) {
            return $cached;
        }
        if ( 'none' === $cached ) {
            return null;
        }

        $response = wp_remote_get(
            self::ENDPOINT,
            array(
                // Como el core, generoso por cron, donde nadie espera, y corto en
                // primer plano, donde hay alguien mirando una pantalla en blanco.
                'timeout' =&gt; wp_doing_cron() ? 30 : 5,
                'headers' =&gt; array( 'Accept' =&gt; 'application/json' ),
            )
        );

        $body = ( ! is_wp_error( $response ) &amp;&amp; 200 === (int) wp_remote_retrieve_response_code( $response ) )
            ? json_decode( wp_remote_retrieve_body( $response ), true )
            : null;

        if ( ! is_array( $body ) || empty( $body['version'] ) ) {
            set_transient( self::TRANSIENT, 'none', HOUR_IN_SECONDS );
            return null;
        }

        set_transient( self::TRANSIENT, $body, 12 * HOUR_IN_SECONDS );

        return $body;
    }

    public function flush() {
        delete_transient( self::TRANSIENT );
    }
}</pre>
<p>Y ya está. A partir de aquí, la descarga, la instalación, la barra de progreso, el correo de aviso y las actualizaciones automáticas las pone WordPress, exactamente igual que para cualquier plugin del directorio oficial.</p>
<h3>Qué hacer en cada nueva versión</h3>
<p>Cuatro pasos, y el orden es importante, porque si publicas el JSON antes que el zip durante unos minutos tus clientes verán una actualización que no se puede descargar. Quitando ese detalle no tiene misterios, tardas 2 minutos:</p>
<ol>
<li><strong>Empaqueta el zip, y que la carpeta de primer nivel dentro se llame como el plugin.</strong> WordPress saca el destino de la instalación del nombre de esa carpeta, no del nombre del fichero. Si comprimes tu carpeta <code>trunk/</code> tal cual, la actualización se instala en <code>wp-content/plugins/trunk/</code> y el cliente acaba con dos copias del plugin, la buena desactivada.</li>
<li><strong>Nómbralo con su versión</strong>, <code>miplugin-1.1.0.zip</code>. A WordPress le da igual cómo se llame, pero una URL fija que se sobrescribe en cada entrega puede servirse rancia desde cualquier caché, puede pillarse a medio subir por un cron que la esté descargando justo entonces, y no te deja volver atrás si una versión sale mal.</li>
<li><strong>Sube el zip</strong> a su carpeta, junto a los de las versiones anteriores, que no se borran.</li>
<li><strong>Actualiza el JSON</strong>: solo <code>version</code> y <code>package</code>, que son el mismo número escrito dos veces. El resto no se toca nunca, salvo <code>tested</code> cuando salga un WordPress nuevo.</li>
<li><strong>Repasa el <code>tested</code> en los tres sitios donde vive</strong>: la cabecera del plugin, el <code>readme.txt</code> y el JSON. De los dos primeros ya te avisa Plugin Check si se te van; del tercero no te avisa nadie, y es justo el que ve tu cliente en la ventana de detalles.</li>
</ol>
<p>Con el gestor de archivos de tu hosting o por FTP, como siempre.</p>
<h2>Cuándo lo ve el cliente</h2>
<p>Hay dos cachés en juego y conviene conocer las dos para no diagnosticar en falso. La primera es la del core, que decide cada cuánto pregunta, y está en ese <code>switch</code> de <code>wp_update_plugins()</code>:</p>
<table>
<tbody>
<tr>
<th style="text-align: left;">Dónde está el cliente</th>
<th style="text-align: left;">Cada cuánto vuelve a preguntar</th>
</tr>
<tr>
<td>Escritorio &gt; Actualizaciones</td>
<td>1 minuto</td>
</tr>
<tr>
<td>Lista de plugins</td>
<td>1 hora</td>
</tr>
<tr>
<td>Cron, en segundo plano</td>
<td>2 horas</td>
</tr>
<tr>
<td>Cualquier otra pantalla del escritorio</td>
<td>12 horas</td>
</tr>
</tbody>
</table>
<p>La segunda es la tuya, las doce horas del transitorio, con la excepción de «Escritorio &gt; Actualizaciones» que ya hemos visto. En el resto del escritorio manda tu caché.</p>
<p>Un matiz sobre esa excepción es que tú tiras tu caché, pero si el core ya preguntó hace menos de un minuto, se sale antes de llamar a tu filtro. O sea que recargar esa pantalla dos veces seguidas no fuerza una consulta nueva. Espera el minuto y vuelve.</p>
<h2>Cómo puedes comprobar que funciona a simple vista</h2>
<p>El truco clásico es subir el JSON con una <code>version</code> inventada muy alta, entrar en «Escritorio &gt; Actualizaciones», ver el aviso, pulsar «Ver detalles de la versión» para comprobar que la ventana se abre con su descripción y su <code>changelog</code>, y devolver luego el JSON a la versión real.</p>
<p>Pero hay uno mejor, más rápido y que no te obliga a tocar nada. <strong>Vete al listado de plugins y mira la columna «Actualizaciones automáticas» de tu plugin.</strong> Si ves el enlace de activarlas, tu JSON se está leyendo y todo va bien. Si la columna está en blanco, tu endpoint no está contestando. Es el mismo mecanismo del <code>no_update</code> que te contaba antes, usado al revés, y te da el diagnóstico de un vistazo.</p>
<p><a href="https://ayudawp.com/?attachment_id=160323" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160323 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/actualizaciones-automaticas-plugin-premium-1200x590.jpg" alt="" width="1200" height="590" srcset="https://ayudawp.com/wp-content/uploads/2026/09/actualizaciones-automaticas-plugin-premium-1200x590.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/actualizaciones-automaticas-plugin-premium-768x378.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/actualizaciones-automaticas-plugin-premium-1536x755.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/actualizaciones-automaticas-plugin-premium.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<h2>Cuando algo no va</h2>
<table>
<tbody>
<tr>
<th style="text-align: left;">Lo que ves</th>
<th style="text-align: left;">Lo que suele ser</th>
</tr>
<tr>
<td>No aparece ninguna actualización</td>
<td>Abre la URL del JSON en el navegador. Si pide login, da 403 o 404, o el JSON está mal formado (una coma de más basta), tu plugin no puede leerlo y se calla. Recuerda que ese fallo se cachea una hora.</td>
</tr>
<tr>
<td>Sale el aviso pero dice que la actualización automática no está disponible</td>
<td>Falta <code>package</code> en el JSON, o su URL no es pública.</td>
</tr>
<tr>
<td>Actualiza y aparecen dos copias del plugin, la buena desactivada</td>
<td>El zip no traía dentro la carpeta con el nombre del plugin. Rehaz el paquete.</td>
</tr>
<tr>
<td>«Ver detalles» da «Plugin not found»</td>
<td>Estás mandando <code>slug</code> y no has enganchado <code>plugins_api</code>.</td>
</tr>
<tr>
<td>Cambias el JSON y el sitio sigue viendo lo viejo</td>
<td>Es tu caché de doce horas. Entra en Escritorio &gt; Actualizaciones, que la tira.</td>
</tr>
<tr>
<td>La columna de actualizaciones automáticas está en blanco</td>
<td>Tu filtro no está devolviendo respuesta. O no contestas cuando la versión no es mayor, o el endpoint no responde.</td>
</tr>
<tr>
<td>Falla en una web concreta y en las demás no</td>
<td>Mira si tiene <code>WP_HTTP_BLOCK_EXTERNAL</code> en su <code>wp-config.php</code>, o un cortafuegos que bloquee salidas. También si <a href="https://ayudawp.com/wp-cron/" target="_blank" rel="ugc noopener">el cron de WordPress</a> está desactivado, aunque eso solo retrasa, no rompe.</td>
</tr>
</tbody>
</table>
<h3>Quitar la petición a wordpress.org (opcional)</h3>
<p>Volvamos a lo de antes. La cabecera evita que wordpress.org te conteste, pero no evita que la web de tu cliente le cuente que tiene tu plugin instalado. Si eso te molesta, y a mí un poco sí, se quita con un filtro más:</p>
<pre>    public function unlist( $args, $url ) {
        // Este filtro corre en todas las peticiones salientes, así que se sale pronto.
        if ( false === strpos( $url, '//api.wordpress.org/plugins/update-check' ) ) {
            return $args;
        }

        if ( empty( $args['body']['plugins'] ) ) {
            return $args;
        }

        $payload = json_decode( $args['body']['plugins'], true );
        if ( ! is_array( $payload ) || empty( $payload['plugins'] ) ) {
            return $args;
        }

        unset( $payload['plugins'][ MIPLUGIN_PLUGIN_BASENAME ] );

        // El basename viaja dos veces: como clave en `plugins` y otra vez en
        // `active`. Quitar solo la primera deja el nombre a la vista.
        if ( ! empty( $payload['active'] ) &amp;&amp; is_array( $payload['active'] ) ) {
            $payload['active'] = array_values(
                array_diff( $payload['active'], array( MIPLUGIN_PLUGIN_BASENAME ) )
            );
        }

        // Una lista vacía tiene que seguir siendo objeto o json_encode la deja en `[]`.
        $payload['plugins'] = (object) $payload['plugins'];

        $args['body']['plugins'] = wp_json_encode( $payload );

        return $args;
    }</pre>
<p>Lo enganchas con <code>add_filter( 'http_request_args', array( $this, 'unlist' ), 10, 2 );</code> y listo. Fíjate en que el método sale por la puerta ante la mínima duda y devuelve <code>$args</code> sin tocar: estás metiendo mano en una petición que usa todo el sitio, así que aquí toca ser cobarde.</p>
<p>Y hay una segunda razón para hacerlo, menos evidente y bastante más interesante que la privacidad. Vuelve a mirar la línea del core que decide si te preguntan a ti: <code>if ( ! $plugin_data['UpdateURI'] || isset( $updates-&gt;response[ $plugin_file ] ) ) { continue; }</code>. <strong>Tu filtro solo se llama si wordpress.org se ha callado.</strong> Si el directorio contestara alguna vez por la carpeta de tu plugin, a ti ni te preguntan y tu cliente se instala encima el plugin de otro.</p>
<p>Antes de que te dé un vuelco: eso es justo lo que evita la cabecera, y más arriba lo tienes comprobado con la prueba del Akismet falso. Y hay una segunda red debajo, porque el equipo de revisión de plugins lleva años moderando los slugs de plugins comerciales conocidos. Pero las dos protecciones viven en el servidor de wordpress.org, no en tu código. Quitarte de la petición cierra el asunto por tu lado sin depender de la palabra de nadie. Es un cinturón encima de unos tirantes que funcionan.</p>
<p><strong>Ojo con hacerlo a medias, que es lo que se ve por ahí.</strong> El core construye ese cuerpo con <code>compact( 'plugins', 'active' )</code>, así que el nombre de tu plugin viaja dos veces, una como clave dentro de <code>plugins</code> y otra como valor dentro de la lista <code>active</code>. Casi todas las implementaciones que he visto quitan solo la primera y dejan el nombre a la vista en la segunda.</p>
<p>Tres cosas más sobre esto. No pierdes absolutamente nada, porque wordpress.org no te iba a contestar de todas formas. Plugin Check no te lo marca, que he leído las expresiones que busca y <code>http_request_args</code> no está entre ellas. Y apúntatelo en la lista de cosas que hay que quitar el día que publiques en el directorio oficial, junto con la cabecera y la constante, porque si te lo dejas puesto wordpress.org no sabrá nunca que tienes el plugin instalado y no te llegará jamás una actualización de allí.</p>
<h3>Lo que este sistema no hace</h3>
<p>Y ahora la parte que suele faltar en los artículos de este tipo, que es donde te cuento lo que no vas a tener.</p>
<ul>
<li><strong>No hay licencias.</strong> Cualquiera con la URL del JSON se baja el zip. Como te decía, el código es GPL y eso no lo cambia ninguna ofuscación, pero si quieres una validación de verdad, el JSON deja de ser un fichero estático y pasa a ser un script en PHP que comprueba la clave antes de responder. Cuando lo montes, hazlo bien, y si la clave no vale devuelve el JSON <em>sin</em> <code>package</code>. Así el cliente ve que hay versión nueva y que su licencia no le da derecho a bajarla, en vez de no enterarse de nada.</li>
<li><strong>Tu plugin desactivado no se actualiza jamás.</strong> El filtro lo engancha tu propio plugin, y un plugin desactivado no carga. El cliente que lo desactive un día y se olvide se queda congelado sin ningún aviso. Esto sí lo resuelve un plugin cliente siempre activo como el de Troy, todo hay que decirlo.</li>
<li><strong>No tienes estadísticas de uso.</strong> Y aquí es donde me van a decir que es una carencia grave, y no lo veo. Un plugin gratuito del directorio necesita el contador de instalaciones activas porque es su única métrica. Un plugin de pago ya tiene la métrica que importa, y está en el listado de pedidos de la tienda. Saber cuántas webs consultan tu JSON no te dice nada que no te diga mejor lo que has vendido. Si algún día quieres el dato aproximado, el log de accesos de tu servidor te lo da gratis.</li>
<li><strong>No hay marcha atrás desde la interfaz.</strong> El core solo ofrece la actualización si la versión es mayor, así que si una versión sale mal, volver a la anterior significa instalar el zip viejo a mano. Por eso los zips antiguos no se borran, y por eso vale la pena tener localizado el de la última versión que iba bien antes de publicar nada.</li>
</ul>
<p><strong>Y ponle renovación automática al dominio.</strong> De ese JSON sale la URL de un zip que se instala con permisos de escritura en las webs de tus clientes, así que no es un dominio cualquiera ni es sitio para experimentos.</p>
<h2>¿Merece la pena preparar este sistema de actualizaciones?</h2>
<p>Si vendes un plugin, o dos, o cinco, y lo que quieres es que tus clientes reciban las actualizaciones igual que las de cualquier plugin del directorio, esto te lo resuelve en una tarde y no depende de nada que no controles tú. Un fichero de texto y un zip se mudan de servidor en diez minutos y no hay que mantenerlos al día con cada versión de WordPress.</p>
<p>Si necesitas licencias de verdad, canal beta, dependencias entre plugins y estadísticas anónimas, no te montes todo eso a mano, que ahí Troy o un servicio comercial te van a salir mucho más baratos en horas.</p>
<p>Yo estoy en el primer grupo, y lo único que echo de menos es no tener que subir el zip y editar el JSON a mano en cada versión. Eso lo voy a resolver con una herramienta mía de publicación, que vivirá en mi lado y no en el de nadie más. Pero <strong>ahora mismo esto funciona con el gestor de archivos del hosting y punto</strong>.</p>
<p><a href="https://ayudawp.com/?attachment_id=160322" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160322 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/aviso-actualizacion-disponible-plugin-premium-1200x611.jpg" alt="" width="1200" height="611" srcset="https://ayudawp.com/wp-content/uploads/2026/09/aviso-actualizacion-disponible-plugin-premium-1200x611.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-actualizacion-disponible-plugin-premium-768x391.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-actualizacion-disponible-plugin-premium-1536x782.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-actualizacion-disponible-plugin-premium.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<h2>¿No hay algo menos manual?</h2>
<p>Estoy en ello, ya tiene hasta nombre, y lo tengo en uso, pero de momento solo para mis cosas, aún no me atrevo a liberarlo, soy muy exagerado con estas cosas, pero todo se andará. Sí te anticipo que contempla la gestión de licencias, entre otras cosas.</p>
<hr>
<p>Pues nada, ya estaría por ahora.</p>
<p>Si te has montado algo parecido, o si has resuelto lo de las licencias de una forma que no se me haya ocurrido, me tienes ahí abajo en los comentarios, que de estas cosas se aprende más leyendo lo que hace el de al lado que leyendo la documentación.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ayudawp.com/actualizaciones-automaticas-plugins-temas-premium/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>¿Quién vigila al Vigilante? ¿sabías que ya hay un plugin de seguridad para WordPress que se/te autoprotege?</title>
		<link>https://ayudawp.com/vigilante-3/</link>
					<comments>https://ayudawp.com/vigilante-3/#respond</comments>
		
		<dc:creator><![CDATA[Fernando Tellado]]></dc:creator>
		<pubDate>Mon, 21 Sep 2026 06:28:14 +0000</pubDate>
				<category><![CDATA[Plugins WordPress]]></category>
		<category><![CDATA[WordPress.com]]></category>
		<category><![CDATA[WordPress.org]]></category>
		<category><![CDATA[Avanzado]]></category>
		<category><![CDATA[Experto]]></category>
		<category><![CDATA[Principiante]]></category>
		<category><![CDATA[Vigilante]]></category>
		<guid isPermaLink="false">https://ayudawp.com/?p=160364</guid>

					<description><![CDATA[Con la versión 3.0.0 el plugin Vigilante comprueba sus propios archivos, te cuenta qué ha encontrado y qué significa, y te ofrece arreglarlo con un botón.]]></description>
										<content:encoded><![CDATA[<p><span style="font-size: 16px;">Un plugin de seguridad vigila tu WordPress, eso lo tiene claro cualquiera que haya instalado uno. La pregunta rara es otra, que igual te suena como pregunta de toda la vida, me refiero a ¿y quién vigila al vigilante?</span></p>
<p><strong>Si alguien consigue tocar los archivos de tu plugin de seguridad te quedas sin nada</strong>, lo que tienes instalado ya no es un guardia, es un segurata sobornado que sigue con la gorra puesta y te sigue diciendo que todo está en orden, pero trabajando en la sombra para tus enemigos.</p>
<p>Con la versión 3.0.0 del plugin Vigilante esa pregunta ya tiene respuesta, pues <strong>el plugin comprueba sus propios archivos, te cuenta qué ha encontrado y qué significa, y te ofrece arreglarlo con un botón.</strong></p>
<p>Es todo igual un poco técnico, pero por lo raro, por lo novedoso, y ¡qué coño! porque me he pegado una currada del catorce y creo que es algo bueno, ni te digo siendo un plugin de seguridad totalmente gratis, pues que <strong>te animo a leer esta apasionante aventura…</strong></p>
<h2>La idea viene de lejos</h2>
<p>Esto no se me ocurrió ayer, <strong>la autoprotección está apuntada en la hoja de ruta de Vigilante desde las pruebas de la versión 2.4.0</strong>, en mayo de 2026,</p>
<p>El razonamiento de entonces sigue siendo el de ahora, que <strong>un plugin de seguridad manipulado es peor que no tener ninguno</strong>, porque no solo deja de protegerte, es que además te tranquiliza.</p>
<p>Piénsalo desde el lado del que ataca, Si alguien consigue escribir en tu servidor (una contraseña de FTP que se filtró, un plugin vulnerable, un hosting comprometido) y quiere quedarse a vivir lo primero que le interesa es que nadie se entere.</p>
<p>La forma más cómoda de que nadie se entere es <strong>dejar a ciegas al que vigila, tocando dos líneas del plugin de seguridad</strong> para que no mire donde no debe o para que no avise.</p>
<p>Si revisas el historial de cualquier plugin de seguridad, desde el más pequeño al más grande verás que suelen ser fuente de posibles vulnerabilidades, que alguien puede aprovechar, y sí, por si lo has pensado, también Vigilante ha tenido vulnerabilidades puntuales (pero como me conoces las arreglé la misma tarde)</p>
<p>Dicho esto, ya te aclaro un concepto importante, y es que <strong>la autoprotección no significa que el plugin sea impenetrable, no tiene nada que ver, la autoprotección es una capa de vigilancia adicional, no una vacuna contra cualquier posible intento de ataque</strong>.</p>
<p>Vamos al grano, que te cuento ya cómo se autoprotege Vigilante…</p>
<h2>Las 3 capas de autoprotección de Vigilante</h2>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-160378" src="https://ayudawp.com/wp-content/uploads/2026/09/vigilante-auto-protect.jpg" alt="" width="1200" height="805" srcset="https://ayudawp.com/wp-content/uploads/2026/09/vigilante-auto-protect.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/vigilante-auto-protect-768x515.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/vigilante-auto-protect-240x160.jpg 240w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></p>
<p>Para saber si sus archivos son los buenos, <strong>Vigilante no se fía de una sola fuente, se apoya en tres, y las compara entre sí</strong>.</p>
<p>Es como comprobar un contrato con tres copias, la que guarda el notario, la que va grapada al propio contrato y la foto que le hiciste con el móvil el día que lo firmaste.</p>
<ul>
<li><strong>Los checksums de WordPress.org:</strong> la huella SHA-256 (una especie de huella dactilar de cada archivo, cambias una coma y cambia la huella entera) que WordPress.org publica para cada archivo de la versión que tienes instalada. Es la referencia que está fuera de tu servidor, y por eso la que más vale.</li>
<li><strong>El archivo <code>MANIFEST.sha256</code>:</strong> va dentro del propio plugin con la huella de cada archivo que se distribuye (63 en esta versión). Sirve para comprobar sin conexión, desde la línea de comandos y en las primeras horas de cada versión, cuando WordPress.org todavía no ha publicado sus checksums.</li>
<li><strong>Una huella del manifiesto, guardada en tu base de datos:</strong> Vigilante la toma la primera vez que ve el manifiesto y solo la renueva cuando el actualizador de WordPress instala una versión nueva o cuando WordPress.org confirma esa versión. Ni siquiera la vuelve a tomar si desactivas y reactivas el plugin.</li>
</ul>
<p>¿Y para qué tres, si con la de WordPress.org ya valdría? Pues porque cada una tapa el agujero de las otras.</p>
<p><strong>Quien quiera esconder un cambio regenerando el manifiesto se choca con la huella guardada</strong>, quien borre la huella se choca con WordPress.org, y el manifiesto cubre las horas en las que WordPress.org aún no tiene nada publicado.</p>
<p><strong>Para engañar a las tres a la vez, un atacante tendría que controlar tu servidor, tu base de datos y WordPress.org</strong>, y si alguien controla WordPress.org tenemos todos un problema bastante más gordo que este.</p>
<h2>Cuándo se hacen las comprobaciones y por qué se hacen ahí</h2>
<p>Una comprobación que se lanza cuando le apetece no sirve de mucho, así que se ejecuta en los momentos en los que de verdad puede pasar algo:</p>
<ul>
<li><strong>Al empezar cada exploración de integridad de archivos</strong>, manual o programado, antes que cualquier otra cosa. Queda fuera del límite de tiempo del escaneo y no respeta tus exclusiones, porque excluir la carpeta del plugin por error no debería dejarlo a ciegas.</li>
<li><strong>Justo después de que WordPress actualice Vigilante</strong>, en esa misma petición, también si lo actualizas subiendo el zip a mano. Es el momento en el que aparecería un archivo a medio copiar o uno cambiado por el camino.</li>
<li><strong>Cuando la versión cambia por la puerta de atrás</strong> (una subida por FTP, el gestor de archivos del hosting, un despliegue o una versión anterior), en la siguiente pantalla de administración que abra un administrador o en la tarea de mantenimiento diaria.</li>
<li><strong>Una vez al día como mínimo</strong>, si nada de lo anterior ha comprobado nada en las últimas 24 horas. Aunque tengas apagado el módulo de integridad de archivos o las exploraciones programadas, porque una comprobación que depende de un ajuste que se puede apagar no es protección, es un adorno.</li>
</ul>
<p>Además también vigila sus propias tareas programadas, que es otra forma muy discreta de dejar sin vigilancia un WordPress. Te lo cuento luego.</p>
<h2>¿Qué detecta la autoprotección de Vigilante?</h2>
<p>Aquí está lo gordo de esto, de lo que me siento más orgulloso, y lo que más me apetecía contarte, porque me ha llevado meses de darle vueltas y cientos de horas de pruebas.</p>
<p>Cada posible caso lleva su nivel gravedad, qué significa (el propio plugin te lo explica con estas mismas palabras en pantalla) y qué te ofrece para arreglarlo. <strong>No hay ningún hallazgo que te deje con el susto y sin saber qué hacer.</strong></p>
<p><a href="https://ayudawp.com/?attachment_id=160369" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160369 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-cambio-ficheros-vigilante-1200x309.jpg" alt="" width="1200" height="309" srcset="https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-cambio-ficheros-vigilante-1200x309.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-cambio-ficheros-vigilante-768x198.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-cambio-ficheros-vigilante-1536x395.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-cambio-ficheros-vigilante.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<h3>Si algo modifica sus archivos</h3>
<ul>
<li><strong>Un archivo de código modificado (crítico):</strong> un PHP, un JavaScript o un archivo de datos que el plugin carga ya no coincide con el que publica WordPress.org. Algo con permiso de escritura en tu servidor lo ha cambiado, sea un atacante, un script o una edición a mano. Te ofrece repararlo.</li>
<li><strong>Una hoja de estilos o una imagen modificadas (aviso):</strong> casi siempre es un plugin de optimización o de caché, o tu propio hosting, que la reescribe al minificar o combinar archivos. Por eso es aviso y no alarma. Te dice que excluyas la carpeta <code>wp-content/plugins/vigilante</code> del optimizador y que después repares.</li>
<li><strong>Un archivo borrado (crítico):</strong> un módulo que falta deja de protegerte sin mostrar ningún error, que es justo lo peligroso. Te ofrece reponerlo reparando.</li>
<li><strong>Un archivo que no se puede leer (crítico):</strong> si no lo puede leer no lo puede comprobar, y los archivos que distribuye WordPress.org siempre se pueden leer. Reparar lo devuelve con permisos normales, y si falla te dice que se lo pidas a tu hosting.</li>
</ul>
<p>Y lo que no te va a marcar importa tanto como lo anterior. Si tu servidor cambia los saltos de línea de un archivo de texto (cosas de servidores Windows y de algunas herramientas de sincronización), eso no es una manipulación y no sale. <strong>Un aviso que salta sin motivo acaba ignorado</strong>, y un aviso ignorado es peor que no tenerlo.</p>
<h3>Si aparecen cosas que no son del plugin</h3>
<ul>
<li><strong>Un ejecutable añadido (crítico):</strong> un PHP, o cualquier archivo que el servidor web pueda ejecutar se llame como se llame (un <code>foto.php.jpg</code> también cuenta, y un <code>.htaccess</code> o un <code>.user.ini</code> también), que está en la carpeta del plugin y no es del plugin. Esconder archivos dentro de un plugin de seguridad es una forma habitual de dejar una puerta trasera. Ojo al consejo que da el propio plugin, que es de los que se agradecen: si quieres saber cómo llegó ahí, pide al hosting la fecha de creación del fichero antes de reparar, porque reparar lo borra y con él la pista.</li>
<li><strong>Un archivo extra que no es código (aviso):</strong> muchas veces es un <code>error_log</code> que escribe tu servidor, o restos de una copia de seguridad o de una sincronización. Si es un registro de errores, te sugiere abrirlo y, si los errores mencionan a Vigilant, contarlo en el foro de soporte.</li>
<li><strong>Un enlace simbólico (crítico):</strong> un archivo del plugin que en realidad es un acceso directo a otro sitio, o que apunta fuera de la carpeta. WordPress.org nunca distribuye enlaces, así que alguien lo ha puesto ahí.</li>
<li><strong>Una carpeta que no se puede revisar (crítico):</strong> no puede listar una de sus carpetas, o encuentra muchísimos más archivos de los que distribuye. Un servidor web puede ejecutar un archivo escondido en una carpeta que no se puede listar si alguien sabe su nombre, así que no se da por buena.</li>
</ul>
<h3>Si algo cambia la lista de referencia, el manifiesto</h3>
<ul>
<li><strong>Manifiesto sustituido, borrado o dañado sin actualizar (crítico):</strong> cambiar esa lista es justo lo que haría alguien para esconder cambios en el plugin. Aquí es donde la huella guardada en tu base de datos se gana el sueldo.</li>
<li><strong>Manifiesto que falta o no es válido:</strong> sigue comprobando contra WordPress.org, pero ha perdido una de sus tres referencias. Reparar lo restaura.</li>
<li><strong>Distinto de la copia de WordPress.org:</strong> los archivos cuadran con el manifiesto que trae el propio plugin, pero no con lo que WordPress.org distribuye para esa versión. En una copia de desarrollo es lo esperable, pero en una web en producción significa que el plugin entero, manifiesto incluido, ha salido de otro sitio. Es crítico si afecta a archivos que se pueden ejecutar y aviso en el resto.</li>
</ul>
<h3>Si cambia la versión por la puerta de atrás</h3>
<ul>
<li><strong>Una versión anterior instalada (aviso, con correo):</strong> alguien ha sustituido Vigilant por una versión más vieja, y las versiones viejas pueden tener fallos ya corregidos y públicos. Si no lo has hecho tú a propósito, reparar instala la versión que distribuye WordPress.org en ese momento.</li>
<li><strong>Una versión nueva que todavía no se puede confirmar (aviso, con correo):</strong> la versión ha cambiado sin pasar por el actualizador de WordPress y WordPress.org aún no ha publicado sus checksums. Si la has subido tú a mano con una copia de WordPress.org no tienes que hacer nada, porque se confirma sola en cuanto se publican (normalmente en un día). Si no has sido tú, o la copia no venía de WordPress.org, repara.</li>
</ul>
<h3>Si alguien/algo borra las tareas programadas</h3>
<p>Vigilant funciona con cinco tareas programadas propias (el mantenimiento diario, las comprobaciones de cada hora, el análisis semanal de Security Check, la comprobación de plugins cerrados en WordPress.org y el escaneo programado de integridad). Si alguien las borra, el plugin sigue instalado, sigue activo y no hace nada, que es otra forma de dejarlo a oscuras sin tocar un solo archivo.</p>
<ul>
<li><strong>Una tarea repuesta (queda en el registro):</strong> una de ellas había desaparecido y Vigilant la ha vuelto a programar. Un plugin de limpieza del cron (las tareas programadas de WordPress), restaurar una copia de la base de datos o una migración pueden provocarlo. Si no vuelve a pasar, no hay nada que hacer.</li>
<li><strong>Tareas que desaparecen una y otra vez (crítico, con correo):</strong> la misma tarea borrada de nuevo en menos de 30 días. Mientras no están no hay escaneos programados, ni comprobación diaria, ni avisos. Te sugiere buscar el plugin de limpieza que lo hace y excluir las tareas que empiezan por <code>vigilante_</code> (un plugin como WP Crontrol te las enseña), y si no encuentras la causa, tratarlo como una posible intrusión y revisar los plugins instalados hace poco y las cuentas de administrador.</li>
</ul>
<p>Las tareas que hayas apagado tú (el análisis semanal, por ejemplo) se respetan, faltaría más. Y en una red multisitio este vigilante de tareas cubre el sitio principal.</p>
<h3>Si algo intenta apagar el plugin o que silenciarlo</h3>
<p>Esta es la parte que más me gusta, porque es donde un atacante listo iría primero.</p>
<ul>
<li><strong>Apagada por código (crítico, con correo una vez al día):</strong> no hay ninguna casilla para apagar la autoprotección (luego te cuento por qué). Lo único que la apaga es un filtro en el código, y cuando alguien lo usa Vigilant te dice en todas las pantallas qué archivos lo enganchan, con nombre y ruta. Si no lo has pedido tú, trátalo como una intrusión, porque un plugin o un fragmento de código que apaga la comprobación de un plugin de seguridad está haciendo lo primero que necesita un atacante.</li>
<li><strong>Alguien le ha quitado los enganches (crítico):</strong> código que desengancha las comprobaciones que corren tras cada actualización y en cada pantalla de administración, para que el plugin siga enseñando su último resultado como si fuera de hoy. WordPress no avisa cuando alguien quita una función de un gancho, así que aquí no se puede nombrar el archivo culpable, pero en el registro queda la lista de plugins cargados en esa petición, que es la lista corta de sospechosos. Te propone desactivarlos uno a uno hasta que deje de pasar.</li>
<li><strong>Sin comprobar desde hace más de tres días (aviso):</strong> lo que ves ya no es un resultado actual. Pasa en webs que no abre nadie y sin cron funcionando, y pasa también cuando algo ha parado la comprobación sin que se note. <strong>La pantalla nunca te enseña un verde viejo como si fuera de hoy.</strong></li>
<li><strong>No ha podido comprobar nada:</strong> sin manifiesto y sin conexión con WordPress.org no tiene contra qué comparar. Te manda a «Herramientas &gt; Salud del sitio» para ver si tu servidor llega a WordPress.org, y a pedírselo al hosting si no llega.</li>
</ul>
<p><a href="https://ayudawp.com/?attachment_id=160370" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160370 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-proteccion-vigilante-apagada-codigo-1200x288.jpg" alt="" width="1200" height="288" srcset="https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-proteccion-vigilante-apagada-codigo-1200x288.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-proteccion-vigilante-apagada-codigo-768x184.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-proteccion-vigilante-apagada-codigo-1536x368.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-proteccion-vigilante-apagada-codigo.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<h3>Más información que registra aunque no sea crítica</h3>
<ul>
<li><strong>Verificado:</strong> sus archivos cuadran con las tres referencias. Es lo normal y lo que tienes que ver casi siempre.</li>
<li><strong>Verificado con dos de tres referencias:</strong> cuadran con el manifiesto y con la huella, pero WordPress.org aún no ha publicado sus checksums, cosa normal durante unas horas tras cada versión. Si dura más de dos días, revisa que tu servidor llegue a WordPress.org.</li>
<li><strong>Comprobado justo después de actualizar:</strong> WordPress lo actualizó y se revisó en esa misma petición.</li>
<li><strong>Integridad restaurada:</strong> lo que se había reportado vuelve a coincidir con lo que distribuye WordPress.org, así que queda cerrado.</li>
<li><strong>Referencia guardada:</strong> ha guardado la huella de su manifiesto en tu base de datos, que es lo que permite detectar después un manifiesto cambiado.</li>
<li><strong>Todavía sin comprobar:</strong> recién instalado. Lanza un escaneo y listo.</li>
</ul>
<p><a href="https://ayudawp.com/?attachment_id=160371" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160371 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/vigilante-autoproteccion-referencias-bien-1200x92.jpg" alt="" width="1200" height="92" srcset="https://ayudawp.com/wp-content/uploads/2026/09/vigilante-autoproteccion-referencias-bien-1200x92.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/vigilante-autoproteccion-referencias-bien-768x59.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/vigilante-autoproteccion-referencias-bien-1536x117.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/vigilante-autoproteccion-referencias-bien.jpg 1808w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<h2>¿Y yo en qué lo noto?</h2>
<p>Si todo va bien, en casi nada, y eso es lo mejor de todo, no es un problema, todo lo contrario. <strong>Lo que notas es que el día que pase algo te enteras tú, no el que ha entrado.</strong></p>
<p>Hasta ahora si alguien tocaba los archivos de tu plugin de seguridad, el plugin seguía diciendo que todo iba bien. Con Vigilante, desde la 3.0.0, eso sale en rojo y no hay que ir a buscarlo.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-160373" src="https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-plugin-vigilante-1200x747.jpg" alt="" width="1200" height="747" srcset="https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-plugin-vigilante-1200x747.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-plugin-vigilante-768x478.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-plugin-vigilante-1536x956.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/aviso-critico-plugin-vigilante.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></p>
<p>Esto es lo que ves, y dónde:</p>
<ul>
<li><strong>Una caja propia, la primera de los resultados de la exploración de integridad de archivos:</strong> con un color por estado y una fila plegable por cada caso, con los archivos afectados, qué significa y qué hacer, la primera abierta y el resto cerradas. Si todo va bien, se queda en una línea discreta con la fecha de la última comprobación.</li>
<li><strong>Un aviso que no se puede descartar:</strong> si es crítico, en todas las pantallas del escritorio de WordPress (entradas, páginas, lo que sea), y si es un aviso, solo en las de Vigilante. En los dos casos solo lo ven los administradores, que tu editora no tiene por qué llevarse el susto.</li>
<li><strong>Un contador rojo o naranja</strong> en el menú de Vigilante y en el de la herramienta de exploración de la integridad de archivos, como el de las actualizaciones pendientes.</li>
<li><strong>Una ficha en el escritorio de Vigilante</strong> con el estado y un enlace directo a la caja correspondiente.</li>
<li><strong>Las dos notas de Vigilante bajan a E</strong> (la de configuración y la de la comprobación de seguridad) con el motivo escrito. Todo lo demás que te enseña el plugin lo calcula ese mismo código, y si ese código está <em>tocado</em> <strong>el plugin no puede fingir que el resto de sus resultados son de fiar</strong>. Además la comprobación de autoprotección pasa a ser la de más peso de la categoría interna de la comprobación de seguridad.</li>
<li><strong>Una entrada en en la auditoría de seguridad</strong> que, al abrir su detalle, <strong>te dice qué ha pasado</strong> con los archivos, qué significa y qué hacer, sin perder los datos de siempre.</li>
<li><strong>Un correo propio con las alertas:</strong> luego te cuento sus reglas, que tienen su intención.</li>
</ul>
<p>Y también hay cosas que ya no ves, como por ejemplo que en los hallazgos de los archivos de Vigilante <strong>no hay botón de ignorar</strong>, ni para el administrador ni para el superadministrador de una red, porque <strong>eso no se silencia, se arregla</strong>.</p>
<p>Tampoco salen mezclados con los archivos sospechosos del escaneo normal, y el «todo correcto» de la exploración no aparece mientras la autoprotección esté en rojo o en ámbar.</p>
<p><a href="https://ayudawp.com/?attachment_id=160374" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160374 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/avisos-criticos-escritorio-vigilante-1200x817.jpg" alt="" width="1200" height="817" srcset="https://ayudawp.com/wp-content/uploads/2026/09/avisos-criticos-escritorio-vigilante-1200x817.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/avisos-criticos-escritorio-vigilante-768x523.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/avisos-criticos-escritorio-vigilante-1536x1046.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/avisos-criticos-escritorio-vigilante.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<h2>El correo de aviso</h2>
<p>La autoprotección tiene su propio aviso por correo, y <strong>no hay ningún ajuste que lo apague</strong>. No va dentro del correo de los resultados de la exploración de integridad de archivos ni dentro de las alertas de la auditoría de seguridad.</p>
<p>Esto es así porque el resto de alertas se pueden desactivar en los ajustes, y si así fuera apagar «avísame de los archivos cambiados» estaría apagando también la alarma del propio plugin, y eso no tenía ningún sentido.</p>
<ul>
<li><strong>Siempre manda correo</strong> con un hallazgo crítico, lo detecte donde lo detecte (un escaneo, la comprobación tras actualizar, un cambio de versión, el vigilante de tareas, la comprobación apagada por código o los enganches quitados).</li>
<li><strong>Avisos de versiones:</strong> una versión anterior instalada y un cambio de versión que no se puede confirmar.</li>
<li><strong>El resto de avisos se quedan en pantalla</strong>. Mandar un correo en cada exploración porque un optimizador reescribe una hoja de estilos es la forma más rápida de que nadie lea los correos.</li>
<li><strong>Una vez por cada conjunto de hallazgos:</strong> si pasa lo mismo, no te escribe otra vez, y si cambia lo que encuentra, sí.</li>
<li><strong>En una red multisitio</strong> sale una sola vez, desde el sitio principal, y llega también al correo de administración de la red.</li>
<li><strong>Sin recordatorios:</strong> Esto lo decidí a propósito, porque si no haces caso al primer correo no vas a hacer caso al quinto, y mientras el problema siga ahí la pantalla te lo sigue diciendo en cada visita.</li>
</ul>
<h2>Auto-reparaciones a un clic</h2>
<p>Dar información sin solución es media herramienta, así que cuando Vigilante encuentra sus archivos han cambiado te ofrece un botón de reparación.</p>
<p>Primero te pregunta, en una pantalla que dice exactamente qué versión va a descargar y qué va a cambiar, y después hace lo mismo que hace el actualizador de WordPress con cualquier plugin, que es descargar el paquete de WordPress.org y sustituir la carpeta.</p>
<p><a href="https://ayudawp.com/?attachment_id=160375" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160375 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/confirmacion-reparara-plugin-vigilante-1200x483.jpg" alt="" width="1200" height="483" srcset="https://ayudawp.com/wp-content/uploads/2026/09/confirmacion-reparara-plugin-vigilante-1200x483.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/confirmacion-reparara-plugin-vigilante-768x309.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/confirmacion-reparara-plugin-vigilante-1536x618.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/confirmacion-reparara-plugin-vigilante.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<ul>
<li><strong>Solo cambian los archivos:</strong> los ajustes, las tablas de la base de datos y el registro se quedan como estaban, porque no se desinstala nada ni se desactiva el plugin.</li>
<li><strong>Lo que no sea de Vigilante también se elimina:</strong> así es como desaparece un archivo inyectado.</li>
<li><strong>Instala la versión que distribuye WordPress.org en ese momento</strong>, nunca la que dicen los archivos del disco y nunca una anterior a la que tu web ya había verificado. ¿Que por qué no se fía de la versión que pone el plugin? Pues porque quien puede cambiar los archivos puede escribir también esa versión, y un reparador que se fiara de ella acabaría siendo una bajada a una versión con fallos públicos.</li>
<li><strong>La dirección del paquete la construye el propio plugin</strong> con un servidor fijo y una versión que tiene que cumplir un formato estricto. Nada de lo que llega en la petición se usa para eso.</li>
<li><strong>Comprueba otra vez al terminar</strong>, contra WordPress.org y contra el manifiesto, y te enseña el resultado.</li>
</ul>
<p>En tres casos no te ofrece el botón y te da los pasos a mano, distintos en cada uno.</p>
<p>Cuando la carpeta del plugin tiene otro nombre (el paquete siempre se instala como <code>vigilante</code> y dejarías una copia limpia al lado de la que funciona), cuando tu instalación tiene prohibido modificar archivos con <code>DISALLOW_FILE_MODS</code>, y cuando eres administrador de un subsitio en una red, donde eso le toca al superadmin.</p>
<p>Y hay algo que no te promete, y es que <strong>si quien cambió los archivos cambió también el código que los repara, ese botón es tan de fiar como el resto de la copia.</strong> La comprobación que no depende de tu servidor sigue siendo la que se hace desde fuera, y te explico cómo más abajo.</p>
<h2>No hay interruptor, para «esos» casos</h2>
<p>A ver, entiendo el argumento contrario, y tiene su parte de razón. Hay webs que no pueden conectarse con WordPress.org por política de su empresa, hay copias de desarrollo en las que no te apetece ver avisos, y a nadie le gusta un plugin que no le deja apagar sus cosas.</p>
<p>Ahora bien, piensa quién sería el usuario más fiel de una casilla que dijera «no compruebes tus propios archivos». Pues el que acaba de tocarlos.</p>
<p><strong>Una autoprotección que se apaga con una casilla es una alarma de casa con el botón de apagado en la puerta de fuera.</strong> Esa casilla existió mientras desarrollaba esta versión, y la quité antes de publicarla.</p>
<p>Para el caso que te comentaba, el de la web que de verdad no puede hablar con WordPress.org, queda un filtro en el código, documentado en el <code>SECURITY.md</code> del plugin:</p>
<pre>add_filter( 'vigilante_self_integrity_enabled', '__return_false' );</pre>
<p>Y con él puesto Vigilante lo avisa como crítico en todas las pantallas, nombra los archivos que enganchan el filtro y lo apunta en el registro. <strong>Apagarlo se puede, apagarlo a escondidas no.</strong></p>
<p>Lo mismo con el código que quita los ganchos y con la comprobación que deja de ejecutarse, que ya te conté más arriba. Nada de esto impide que un código que corre dentro de WordPress anule al plugin (eso no lo puede impedir nadie), pero sí impide que la pantalla diga «verificado» mientras pasa.</p>
<h2>Lo que no hace la autoprotección de Vigilante</h2>
<p>Si solo te cuento lo bueno esto sería propaganda, y ya imaginas que para el precio que cobro por el plugin (cero euros) no me da para <em>publi</em>.</p>
<p>De qué no te protege la autoprotección:</p>
<ul>
<li><strong>Detecta manipulación, no fallos de programación:</strong> Si el código publicado de Vigilante tuviera un fallo, que son cosas que pasan porque nadie es perfecto, ni siquiera yo, esta comprobación no lo vería, porque los archivos serían exactamente los publicados. Eso se cubre de otra forma, con la auditoría de cada versión que te cuento al final.</li>
<li><strong>Quien puede escribir en tu base de datos</strong> puede sustituir la huella guardada, como con cualquier plugin de seguridad. Lo que ya no puede es apagar la comprobación, porque no hay ningún ajuste que la apague.</li>
<li><strong>Quien puede escribir en la carpeta del plugin</strong> puede editar también el código que comprueba. La única referencia fuera de su alcance son los checksums de WordPress.org, y por eso la comprobación de verdad es la que se hace desde fuera.</li>
<li><strong>Las primeras horas de cada versión</strong> sale con dos de tres referencias, hasta que WordPress.org publica sus checksums.</li>
<li><strong>El <code>readme.txt</code> y el <code>changelog.txt</code> no están en el manifiesto</strong>, porque WordPress.org permite actualizar el <code>readme</code> de una versión publicada sin sacar otra. Los checksums de WordPress.org sí los incluyen.</li>
<li><strong>En multisitio</strong> cada sitio guarda su resultado, pero el correo sale solo del sitio principal y el vigilante de tareas cubre ese sitio.</li>
<li><strong>Si despliegas con Git, Composer o una herramienta de sincronización</strong>, reparar desde WordPress.org se deshace con el siguiente <code>commit</code>, así que el arreglo va en tu despliegue.</li>
<li><strong>No revisa tus otros plugins ni tu tema:</strong> Eso es trabajo de la escaneo de integridad de archivos que ya tienes de siempre, no de la autoprotección.</li>
</ul>
<h2>Cómo comprobarlo por tu cuenta</h2>
<p>Maneras con las que puedes poner a prueba la autoprotección de Vigilante:</p>
<ol>
<li><strong>En el propio WordPress:</strong> la pestaña de integridad de archivos y la comprobación «Autoprotección de Vigilante» de la auditoría de seguridad.</li>
<li><strong>Contra el manifiesto que viaja con el plugin</strong>, desde la carpeta <code>wp-content/plugins/vigilante</code>: <code>sha256sum -c --strict MANIFEST.sha256</code> en Linux o <code>shasum -a 256 -c --strict MANIFEST.sha256</code> en macOS. Ojo, que esto no ve un archivo añadido a la carpeta.</li>
<li><strong>Contra WordPress.org, con WP-CLI:</strong> <code>wp plugin verify-checksums vigilante</code>.</li>
<li><strong>El manifiesto contra WordPress.org:</strong> <code>php wp-content/plugins/vigilante/bin/verify-manifest.php --wporg</code>, que además avisa de cualquier archivo añadido y devuelve un código de salida distinto para cada problema.</li>
<li><strong>Desde fuera del servidor</strong>, que es la que de verdad vale, descargando el plugin de WordPress.org, o haz un <code>svn export</code> del tag de la versión, y compáralo tú.</li>
</ol>
<p>Y te recuerdo que <strong>un servidor comprometido puede mentir sobre sus propios archivos</strong>, y lo que hay fuera de él no, por eso las 3 capas, no es infalible pero lo intenta.</p>
<h2>Cómo se comprueba cada versión de Vigilante</h2>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-160377" src="https://ayudawp.com/wp-content/uploads/2026/09/vigilant-auto-protect.jpg" alt="" width="1200" height="800" srcset="https://ayudawp.com/wp-content/uploads/2026/09/vigilant-auto-protect.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/vigilant-auto-protect-768x512.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/vigilant-auto-protect-240x160.jpg 240w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></p>
<p>Antes de publicar cualquier versión de Vigilante, el plugin pasa por un conjunto fijo de comprobaciones, y sus cifras quedan escritas en la entrada de esa versión en el <code>changelog.txt</code>.</p>
<p>Entre esas cifras están tienes todo esto:</p>
<ul>
<li>Prueba del escapado de JavaScript</li>
<li>Inventario de cada punto de entrada con su comprobación de permisos</li>
<li>Un detector de accciones peligrosas en PHP y en JavaScript</li>
<li>Revisión completa de Plugin Check</li>
<li>Una comprobación de coherencia de versiones y notas</li>
<li>Pruebas de regresión permanentes en un sitio normal y en una red multisitio, incluida la prueba de cada vulnerabilidad ya publicada, para que no vuelva a colarse.</li>
</ul>
<p>Para esta versión en concreto, la lógica de autoprotección pasó por diez rondas de revisión a ciegas, hechas por sesiones que no habían escrito el cambio (las seis últimas sin nada de gravedad alta ni media), y la parte que se ve en pantalla, con la reparación, por dos rondas más que encontraron un fallo de gravedad media cada una, arreglado y con su prueba.</p>
<p>Además,<strong> introduje a propósito 71 fallos en copias del código</strong> (una comprobación que se salta, una condición al revés, un aviso que deja de enviarse) para comprobar que las pruebas los cazan, y las pruebas los cazaron todos menos uno, que está documentado como equivalente porque no cambia nada que se pueda observar.</p>
<p>Y luego, el <code>MANIFEST.sha256</code> se genera el último de todo, cuando lo demás está cerrado.</p>
<p>Por supuesto, nada de esto sustituye a que lo compruebes tú, es simplemente para que sepas todo lo que hay detrás de las cifras del registro de cambios, para quien quiera mirarlas, y por si tenías curiosidad por si me tomo esto en serio o no.</p>
<h2>¿Tengo que hacer algo?</h2>
<p>No, lo de siempre:</p>
<ol>
<li>Actualiza a la 3.0.0 como cualquier otra versión, si no lo has hecho ya. La primera comprobación se hace sola.</li>
<li>Si usas un plugin de optimización que minimiza o combina archivos, excluye la carpeta <code>wp-content/plugins/vigilante</code>, que así te ahorras avisos de hojas de estilos reescritas.</li>
<li>Si tienes un plugin de limpieza del cron, excluye las tareas que empiezan por <code>vigilante_</code>.</li>
<li>Echa un vistazo a la pestaña de integridad de archivos. Lo normal es que diga «verificado», y si lo actualizas en las primeras horas, con dos de tres referencias hasta que WordPress.org publique sus checksums.</li>
</ol>
<p>A partir de ahí, si encuentras un problema de seguridad en Vigilante, escribe a <strong>security@ayudawp.com</strong> y tendrás respuesta en menos de 72 horas.</p>
<p>El detalle completo de todo lo que te he contado, incluido lo que no cubre, está en el archivo <code>SECURITY.md</code> que viaja con el plugin, y Vigilante lo tienes en el <a href="https://es.wordpress.org/plugins/vigilante/">directorio oficial de plugins de WordPress.org</a>, gratis y sin versión de pago.</p>
<p>Si quieres profundizar en la seguridad de WordPress <a href="https://ayudawp.com/categoria/seguridad/">tienes decenas de artículos en el blog</a>, y para lo demás, incluso para debatir si una autoprotección debería poder apagarse, me tienes ahí abajo, en la sección de comentarios.</p>
<p>Y ojalá no tengas que ver nunca esa caja en rojo.</p>
<p>Si quieres ver además cómo monté esta autoprotección aquí te dejo un vídeo que he publicado en el canal de YouTube de Ayuda WordPress donde lo explico:</p>
<div class="ast-oembed-container " style="height: 100%;"><iframe loading="lazy" title="¿Un plugin de seguridad WordPress que se auto-protege? ¿qué clase de magia negra es esta?" width="1600" height="900" src="https://www.youtube.com/embed/jt-1iNVnbJ0?start=14&amp;feature=oembed&amp;enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></div>
]]></content:encoded>
					
					<wfw:commentRss>https://ayudawp.com/vigilante-3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WordPress 7.1.1 al caer, el culebrón de Automattic y qué puñetas son los llms.txt #CrónicasWordPress #DoctorWordPress</title>
		<link>https://ayudawp.com/wordpress-7-1-1-al-caer-el-culebron-de-automattic-y-que-punetas-son-los-llms-txt-cronicaswordpress-doctorwordpress/</link>
					<comments>https://ayudawp.com/wordpress-7-1-1-al-caer-el-culebron-de-automattic-y-que-punetas-son-los-llms-txt-cronicaswordpress-doctorwordpress/#respond</comments>
		
		<dc:creator><![CDATA[Fernando Tellado]]></dc:creator>
		<pubDate>Fri, 18 Sep 2026 17:59:58 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Vídeos]]></category>
		<category><![CDATA[#CrónicasWordPress]]></category>
		<category><![CDATA[#DoctorWordPress]]></category>
		<category><![CDATA[#TrucosWordPress]]></category>
		<guid isPermaLink="false">https://ayudawp.com/?p=160359</guid>

					<description><![CDATA[Esta semana las Crónicas me salieron con un día de retraso, y no porque faltara tema, que de eso andamos sobrados, sino por movidas mías. Pero cumplo, que para eso estoy. Así que aquí tienes el repaso de lo que conté en las Crónicas WordPress y de lo que enseñé el miércoles en el Doctor WordPress, por si te los perdiste en directo o los quieres repasar con calma.]]></description>
										<content:encoded><![CDATA[<p>Esta semana las Crónicas me salieron con un día de retraso, y no porque faltara tema, que de eso andamos sobrados, sino por movidas mías. Pero cumplo, que para eso estoy. Así que aquí tienes el repaso de lo que conté en las <strong>Crónicas WordPress</strong> y de lo que enseñé el miércoles en el <strong>Doctor WordPress</strong>, por si te los perdiste en directo o los quieres repasar con calma.</p>
<h2>Crónicas WordPress: revisiones con IA, WordPress 7.1.1 al caer y el culebrón de Automattic</h2>
<h3>Seguridad: la IA ya te revisa los plugins (y yo fui el conejillo de indias)</h3>
<p>Lo más gordo en seguridad es que WordPress.org ha activado un sistema de revisión automática con IA y Jetpack Scan que analiza cada plugin que subes. Y ojo, porque <strong>no revisa solo cuando lo subes por primera vez, también en cada actualización</strong>.</p>
<p>Lo anunció David Pérez esta semana, aunque funciona desde el 5 de junio. Busca patrones de código peligroso (salidas sin escapar, falta de comprobaciones nonce, inyecciones SQL y demás), te calcula una puntuación de riesgo y, si te pasas, te bloquea la actualización y te manda un correo para que lo arregles.</p>
<p>Y aquí te hablo con conocimiento de causa, porque fui conejillo de indias sin comerlo ni beberlo. Justo cuando arrancó todo subí unas actualizaciones de Vigilante y me llovieron los avisos. Falsos positivos había, y alguna posible vulnerabilidad cogida con pinzas también, que un administrador abriendo una ventana de popup dispare una alarma es hilar muy fino.</p>
<p>El equipo de plugins, majísimos y rapidísimos atendiéndome, todo hay que decirlo. Pero me tiré un fin de semana a base de actualización tras actualización solo para contestar al automatismo, y cada respuesta me devolvía el mismo falso positivo más tres cosas nuevas.</p>
<p>Que quede claro, <strong>la idea me parece estupenda</strong>. Llevo años avisando de que hay muchas comprobaciones al subir un plugin y bastantes menos en las actualizaciones, que es justo por donde se cuelan los problemas, así que esto viene a tapar ese agujero. Lo único que pido es que <strong>metan estas mismas comprobaciones en el Plugin Check</strong>, la herramienta oficial que muchos pasamos antes de subir nada, para no llevarnos la sorpresa de que una te diga que está todo bien y otra, en paralelo, que está mal.</p>
<p>En vulnerabilidades de la semana, Wordfence detectó una inyección SQL sin autenticar en rtMedia, un plugin de galerías con miles de sitios expuestos. De estas salen todos los días, es lo normal, y en mi propio Vigilante me detectaron una que arreglé esa misma tarde. También hubo un fallo de autorización en un complemento de PixelYourSite para Easy Digital Downloads. Estos plugins que te inyectan píxeles y scripts de terceros son de los que <strong>yo prohíbo a mis clientes sin pestañear</strong>, porque te saltan capas de seguridad de tu propio WordPress.</p>
<p>Y te conté el caso de un «beg bounty», que no es lo mismo que un bug bounty. El bug bounty es el programa serio de recompensas por encontrar fallos, el que tienen Wordfence, Patchstack y compañía. El beg bounty es el primo pesado, alguien que te escribe directamente, sin programa que valga, para «avisarte» de una supuesta vulnerabilidad inflada y, al terminar el mensaje, pedirte una recompensa. Me llegó uno y lo desmenucé en el blog para que sepas <a href="https://ayudawp.com/beg-bounty/">distinguir un aviso de verdad de un sablazo con corbata</a>.</p>
<h3>Comunidad y desarrollo: WordPress 7.1.1 y un WooCommerce que se queda corto</h3>
<p>En comunidad ya se ha anunciado el equipo que va a llevar WordPress 7.2, con Mullenweg otra vez como líder de versión (que da para un rato, y lo dejo para el final). Habrá tema nuevo por defecto, previsto para 2027, aunque cada vez le veo menos sentido a los temas por defecto.</p>
<p>Pero antes que la 7.2 llega la 7.1.1, que ya está en versión candidata y sale esta misma semana. Corrige un montón de fallos, y <strong>uno me toca de cerca porque lo reporté yo</strong>: el mapa del sitio nativo de WordPress devolvía un 404 en webs sin entradas de blog, algo que pillé con mi plugin Visibility, que gestiona justo eso. Mi ticket ya está asignado a esta versión, así que queda arreglado.</p>
<p>En WooCommerce 11.1 hay dos cosas. Una buena, que por fin han consolidado la galería de imágenes por variación, para que al elegir una variación te cambie la galería, algo la mar de práctico. Y una a medias, porque han metido el derecho de desistimiento electrónico pero se queda muy corto, no cubre ni de lejos lo que exige la normativa europea y ellos mismos reconocen que no garantiza el cumplimiento. <strong>No entiendo para qué se meten en ese jardín</strong> cuando ya hay plugins que lo cubren, como <a href="https://es.wordpress.org/plugins/eu-withdrawal-compliance/">el mío</a>, que es 100% gratis y lo tienes en el repositorio.</p>
<p>Y en mi terreno he actualizado uno de mis plugins más veteranos. El antiguo No Gutenberg pasa a llamarse <a href="https://ayudawp.com/si-gutenberg/">Sí Gutenberg</a> (versión 2.2.0), y no es un capricho de nombre, es un cambio de enfoque. Antes desactivaba Gutenberg del todo y ahora te deja elegir. Puedes quitar el editor de bloques solo en las entradas y dejarlo en las páginas, decidirlo por tipo de contenido o por nivel de usuario, restaurar la pantalla de widgets clásicos y alguna cosa más. Porque <strong>yo nunca he odiado el editor de bloques</strong>, por mucho que se diga. Lo que siempre he defendido es que los bloques tienen sentido como maquetador para las páginas, no como editor para las entradas de blog, que no necesitan tanto artificio.</p>
<h3>IA y SEO: spam con IA, el cero clics y qué plugin de SEO pesa menos</h3>
<p>Enrique Dans avisaba del spam de comentarios hecho con IA, que ya se está saltando a Akismet. Hay bots que cogen contenido y lo pasan por un modelo de lenguaje para generar comentarios que cuelan en un montón de sitios, se habla de cientos de miles de dominios atacados. A mí el volumen me da igual, lo que preocupa es la calidad, que esquiva los filtros de siempre. Y <strong>mi antispam favorito sigue siendo el que ya trae WordPress de serie</strong>, marcar en los ajustes de comentarios que cada uno se apruebe a mano. No hay otro mejor, y encima te ahorras el plugin.</p>
<p>En SEO, un estudio sobre 19 millones de consultas en inglés dice que el bloque de «la gente también pregunta» de Google ya lo responde la IA casi en su totalidad, un 97% la primera semana de septiembre frente al 86% de agosto. O sea, <strong>cero clics como norma</strong>, la IA te contesta ahí mismo y no queda enlace que rascar.</p>
<p>Y cerré con una comparativa mía bastante a lo bruto sobre <a href="https://ayudawp.com/plugin-seo-ligero/">qué plugin de SEO pesa menos y consume menos recursos</a>. Te resumo lo que salió: SEO Framework es el más ligero en varias cosas, hay que ser justos; Rank Math me ha decepcionado y ahora mismo es una bestia parda en consumo; Yoast, en cambio, se ha puesto las pilas y ha aligerado bastante. Mi Visibility no mete tablas propias en la base de datos, tira de las nativas y luego limpia, y llega a hacer menos consultas que WordPress a pelo. Tienes el análisis completo, con el CSV para que lo compruebes sin trampa ni cartón.</p>
<h3>El culebrón: apartan a Mullenweg de Automattic (y a los tres días, de vuelta)</h3>
<p>Y llegamos al culebrón de la semana, del mes y casi del año. El consejo de administración de Automattic apartó a Matt Mullenweg como CEO y nombró en su lugar, como interino, a su director financiero, Mark Davis. Tres días después, Mullenweg anunciaba por Slack que había recuperado el control, y la cuenta del CEO interino se desactivó por arte de birlibirloque. Él apunta a que detrás de la maniobra estaría Silver Lake, el fondo que está tras WP Engine, aunque eso es una acusación suya que no ha confirmado nadie.</p>
<p>Lo bueno, y esto es importante, es que <strong>todo esto afecta a Automattic, la empresa, no a WordPress.org, el proyecto</strong>. De hecho, en paralelo se nombró a Mary Hubbard directora ejecutiva del proyecto WordPress, que es como debería ser. La empresa por un lado y el proyecto por otro.</p>
<p>¿Mi opinión, que a nadie le importa pero te la doy? Que Mullenweg no debería ser CEO, pero eso tendría que decidirlo él, dejar la empresa en otras manos y dedicarse al proyecto WordPress, hacer un Linus Torvalds. Y sobre todo, que <strong>las cosas no se hacen así, tengas o no tengas razón</strong>. Ya avisé de que esto duraría poco, como pasó con Steve Jobs o con Sam Altman en OpenAI, que al final acaban volviendo. Matt, tómate unas vacaciones de verdad, que te apreciamos, pero deja las peleas con WP Engine en casa.</p>
<p>Tienes las Crónicas WordPress completas aquí: <a href="https://www.youtube.com/watch?v=W2Nn-0h20SE">Seguridad, WordPress 7.1.1, WooCommerce y el culebrón de Automattic – #CrónicasWordPress</a>.</p>
<div class="ast-oembed-container " style="height: 100%;"><iframe loading="lazy" title="100% de resultados que se comen las AI Overviews, la crisis de Automattic con Matt Mullenweg y más…" width="1600" height="900" src="https://www.youtube.com/embed/W2Nn-0h20SE?feature=oembed&amp;enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></div>
<h2>Doctor WordPress: qué son los llms.txt y para qué sirven (si es que sirven)</h2>
<p>En el Doctor de esta semana me metí con una pregunta que me hacéis mucho, qué son los famosos archivos <strong>llms.txt</strong> y <strong>llms-full.txt</strong>, esos que ves por ahí y que yo llevo tiempo sirviendo en mis plugins.</p>
<h3>Qué son y quién se los inventó</h3>
<p>Un llms.txt es, ni más ni menos, un archivo de texto en formato Markdown que le dice a los agentes de IA cuál es el contenido de tu web y cómo está estructurado. La idea la propuso Jeremy Howard, va ya por la versión 2 (de agosto de 2026) y funciona como <strong>una especie de índice limpio de tu sitio pensado para que los modelos de lenguaje se lo lean rápido</strong>. El llms.txt es el listado, y el llms-full.txt va más allá y sirve el contenido completo de cada página, o un extracto, según lo configures.</p>
<p>¿Que por qué en Markdown? Pues porque es el formato que mejor leen estos modelos, muy limpio y ligero (y, por cierto, WordPress también entiende Markdown, tanto en el editor de bloques como en el clásico).</p>
<h3>¿Sirve de algo? ¿Lo lee alguien?</h3>
<p>Google dice que no los tiene en cuenta, que para eso está el robots.txt y el mapa del sitio. Y es verdad que <strong>el llms.txt no sustituye a ninguno de los dos</strong>, cada cosa va a lo suyo y siguen conviviendo. Pero la adopción no para de crecer, Wix genera uno para cada sitio y cada vez más plugins lo incorporan.</p>
<p>Te cuento lo que veo yo con datos reales, midiendo Ayuda WordPress con mi plugin Vigía. A día de hoy, la página que más visitan los bots de IA cuando descubren tu web sigue siendo el mapa del sitio, y a partir de ahí se lo leen todo, sistemáticos, página por página (más que indexar, almacenan, como bibliotecarios que lo guardan todo sin priorizar hasta que alguien pregunta). Pero últimamente <strong>ya los veo buscar y leerse el llms.txt</strong>, y si encuentran el llms-full, también. Como pesa menos y se lee más rápido que un mapa del sitio, apostaría a que esa tendencia va a más.</p>
<h3>Cómo lo montas en WordPress sin instalar un plugin solo para esto</h3>
<p>Aquí va mi consejo principal, el que quiero que te lleves. <strong>No instales un plugin específico solo para generar el llms.txt</strong>. Es un puñetero archivo de texto, hay cientos de plugins que hacen solo eso y no merece la pena. Lo suyo es que lo genere el plugin de SEO que ya tengas, porque muchos ya lo hacen (y alguno, como All in One SEO, te lo guardaba para la versión premium, que ya me contarás en qué cabeza cabe cobrar por un fichero de texto).</p>
<p>En el directo lo enseñé con mis dos plugins, los dos gratis del todo. Vigía es de analítica y control de visibilidad ante las IA, y te genera el llms.txt, te gestiona el robots.txt, te bloquea rastreadores y te da estadísticas de qué bots de IA visitan tu web y cuánto. Y Visibility es un plugin de SEO completo y gratuito. Cuando tienes los dos, <strong>se coordinan solos para no duplicarte los archivos</strong>, que Vigía se aparta y deja que Visibility lleve la voz cantante, y así no acabas con dos llms.txt peleándose.</p>
<p>Y quédate con esto. Si quieres un llms.txt, tira del plugin de SEO que ya uses, y si es Visibility mejor, que es gratis del todo, en vez de instalar uno específico para la tontería. Y si no lo quieres, tampoco pasa nada, que nadie te obliga. No es un estándar oficial, pero es una propuesta que se adopta cada vez más, así que no la pierdas de vista.</p>
<p>Tienes el Doctor WordPress completo aquí: <a href="https://www.youtube.com/watch?v=6ASIeLkB1GI">Qué son los archivos llms.txt y llms-full.txt y cómo crearlos en WordPress – #DoctorWordPress</a>.</p>
<div class="ast-oembed-container " style="height: 100%;"><iframe loading="lazy" title="LLMS.txt y LLMS-FULL.txt ¿Qué son esos archivos de IA? ¿Sirven de algo?¿Cómo se crean en WordPress?" width="1600" height="900" src="https://www.youtube.com/embed/6ASIeLkB1GI?feature=oembed&amp;enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></div>
<h2>Nos vemos en el próximo directo</h2>
<p>Y hasta aquí la semana. Ya lo sabes, los lunes toca Crónicas WordPress y los miércoles, Doctor WordPress, a las 19:30 (hora peninsular) <a href="https://www.youtube.com/AyudaWordPressES?sub_confirmation=1" rel="nofollow">en el canal de Ayuda WordPress</a>. Si tienes cualquier duda de lo que he contado, o me quieres corregir en algo, te leo ahí abajo en los comentarios.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ayudawp.com/wordpress-7-1-1-al-caer-el-culebron-de-automattic-y-que-punetas-son-los-llms-txt-cronicaswordpress-doctorwordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Auditoría SEO / GEO (online y gratis) para webs WordPress</title>
		<link>https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/</link>
					<comments>https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/#comments</comments>
		
		<dc:creator><![CDATA[Fernando Tellado]]></dc:creator>
		<pubDate>Thu, 17 Sep 2026 06:28:12 +0000</pubDate>
				<category><![CDATA[SEO / AEO / GEO / AIO]]></category>
		<category><![CDATA[WordPress.com]]></category>
		<category><![CDATA[WordPress.org]]></category>
		<category><![CDATA[AI Share & Summarize]]></category>
		<category><![CDATA[Content Signals]]></category>
		<category><![CDATA[DietPress]]></category>
		<category><![CDATA[Principiante]]></category>
		<category><![CDATA[VigIA]]></category>
		<category><![CDATA[Visibility]]></category>
		<guid isPermaLink="false">https://ayudawp.com/?p=160201</guid>

					<description><![CDATA[Ya tienes una auditoría SEO y GEO gratis para tu web WordPress. Más de 40 comprobaciones, sin registro ni email, sin pagar. Y si quieres un análisis más completo, cerca de 100 comprobaciones, lo pides, también gratis.]]></description>
										<content:encoded><![CDATA[<p>Ya tienes una <strong>auditoría SEO gratis para tu web WordPress</strong> en <a href="https://herramientas.ayudawp.com/auditoria-seo/">herramientas.ayudawp.com/auditoria-seo/</a>. Metes la URL del sitio que quieras auditar, esperas un minuto y sale un informe con más de 40 comprobaciones, sin registrarte y sin dejar tu email, sin pagar nada. Y si quieres el análisis completo, con cerca de 100 comprobaciones, me lo pides desde el propio informe y te lo hago yo, también gratis.</p>
<p>Llevo años diciendo que las herramientas de auditoría SEO gratuitas que hay por ahí sirven para bien poco, pero ¿esta sirve de algo?, pues aunque no lo sepas ya estás disfrutando de ella ¿no te lo crees?, lee… que hay una historia detrás…</p>
<h2>El cliente que echó a su empresa de SEO…</h2>
<p>Esto empezó en una reunión de mentoría con un cliente del <a href="https://mantenimiento.ayudawp.com/">servicio de mantenimiento</a>. Las hacemos con todos al entrar, y luego siempre que hagan falta, porque una de las cosas que más nos agradecen los clientes es justo esa. que <strong>no solo mantenemos webs, también echamos una mano para que la web funcione mejor</strong>, y eso incluye seguridad, rendimiento y SEO, sin coste añadido salvo tareas muy especiales.</p>
<p>En esa primera reunión le pasé el informe inicial que hacemos siempre, y ahí, entre las cosas a mejorar, se veía a la legua que <strong>la empresa de SEO que tenía contratada le hacía entre poco y nada</strong>. Nosotros no somos una empresa de SEO, es verdad, pero los básicos de descubrimiento e indexación los miramos igual, y ayudamos a mejorarlos, y esos básicos cantaban por sí solos, para mal. El cliente lo vio y me pidió un informe más a fondo.</p>
<p><strong>No me dedico al SEO</strong>, no hago ese servicio como tal, pero llevo más de 20 años trabajando en Internet, he contratado a unos cuantos SEO para mis propias empresas, he leído una montaña de informes ajenos, he analizado un montón de webs y he hecho mucho SEO de contenidos durante años. Y creo que algo de idea tengo al respecto, de hecho llevo viviendo de ello bastante tiempo, y eso se parece a un currículum ¿no?.</p>
<p>Así que me puse, analicé su web al completo y le preparé un informe en profundidad. <strong>Al día siguiente echó a su empresa de SEO y me pidió que le lleváramos nosotros el servicio.</strong></p>
<p>Que conste que <strong>hay empresas de SEO buenísimas</strong> y no va de eso la cosa, sino de que su empresa llevaba meses pagando sin que nadie le enseñara un informe que se sirviese de algo, ni compromiso alguno, ni trabajos que significasen algo medible, y <strong>en cuanto vio cosas que se podían hacer, explicadas, y un plan de acción, tuvo claro lo que estaba pasando</strong>.</p>
<p>Por supuesto, le entregué el informe para que hiciese con él lo que quisiera, incluso ofrecerlo sin restricciones a la empresa de SEO, pero <strong>parece ser que llevar meses pagando por nada le abrió un poco los ojos</strong>, y bueno, estamos en ello, ayudándole a corregir errores de años y a mejorar el descubrimiento e indexación de su web (tienda online en realidad).</p>
<p>Luego, como soy como soy, se me quedó la idea dando vueltas y me dije «…<em><strong>si un informe bien hecho vale para eso, ¿por qué no puede tenerlo cualquiera?</strong></em>…». Pues eso he montado y te presento hoy.</p>
<p>La parte que se puede automatizar, online y a voluntad para todo el mundo, y luego, la parte que exige criterio, valoración razonada, a veces incluso datos internos de la web, esa si quieres te la hago yo, también gratis y sin compromiso ninguno. La pides y encantado de la vida.</p>
<h2>Auditoría SEO y GEO exprés: 43 comprobaciones gratis en un minuto</h2>
<p>Metes la dirección de tu web y esperas. No hay registro, no hay correo, no hay «déjanos tu email para ver el resultado». Sale el informe y ya está, lo puedes descargar en PDF, imprimirlo, o compartirlo en tus redes sociales, mandártelo por email (con URL única y privada personalizada).</p>
<p>Está aquí: <a href="https://herramientas.ayudawp.com/auditoria-seo/">herramientas.ayudawp.com/auditoria-seo/</a></p>
<p>Lo que hace en un minuto o menos:</p>
<ul>
<li>Se lee tu <code>robots.txt</code> entero y te dice si hay grupos duplicados, erratas o bloqueos que se pisan con el <code>noindex</code>.</li>
<li>Rastrea el índice de sitemaps y hasta 3.000 URLs, y te cuenta qué hay dentro, cuánto está sin fecha de modificación y cuántas direcciones no tienen ningún valor de búsqueda.</li>
<li>Abre diez páginas de verdad, repartidas entre los tipos de contenido que publicas, con el agente de Googlebot, y mide lo que se encuentra el rastreador de verdad y no lo que se encuentra en la portada cacheada.</li>
<li>Valida los datos estructurados de esas páginas, mira las cabeceras del servidor, comprueba las señales para agentes de IA y cronometra la respuesta.</li>
</ul>
<p>Son <strong>43 comprobaciones con veredicto</strong>, cada una con su explicación de qué se juega tu negocio en ella, qué hacer para arreglarla y, cuando toca, con qué plugin.</p>
<p><a href="https://ayudawp.com/?attachment_id=160231" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160231 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-express-gratis-resultado-1200x2658.jpg" alt="" width="1200" height="2658" srcset="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-express-gratis-resultado-1200x2658.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-express-gratis-resultado-768x1701.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-express-gratis-resultado-693x1536.jpg 693w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-express-gratis-resultado-925x2048.jpg 925w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-express-gratis-resultado.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<h3>Lo que no hace la auditoría exprés</h3>
<p>Todas las herramientas gratuitas de este tipo tienen el mismo problema, y es que te dejan con la duda. Sale una nota de 78 sobre 100 y tú te quedas mirando la pantalla pensando «vale, ¿y el 22 que falta?». Nunca te dicen si el 22 es porque tu web tiene fallos o porque la herramienta no ha mirado ahí.</p>
<p>Aquí no, <strong>al final de cada bloque tienes la lista de lo que esa herramienta no mira</strong>, con nombre, apellidos y por qué le importa a tu negocio.</p>
<p>Son <strong>55 comprobaciones que se llaman por su nombre y se declaran fuera</strong>. Cosas como el censo de directivas de indexación de todas las URLs, el árbol completo de categorías con sus conflictos padre-hija, o el cruce con la cobertura real de tu Search Console.</p>
<p><a href="https://ayudawp.com/?attachment_id=160233" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160233 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/hallazgos-auditoria-seo-para-pedir-analisis-a-fondo-1200x716.jpg" alt="" width="1200" height="716" srcset="https://ayudawp.com/wp-content/uploads/2026/09/hallazgos-auditoria-seo-para-pedir-analisis-a-fondo-1200x716.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/hallazgos-auditoria-seo-para-pedir-analisis-a-fondo-768x458.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/hallazgos-auditoria-seo-para-pedir-analisis-a-fondo-1536x916.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/hallazgos-auditoria-seo-para-pedir-analisis-a-fondo.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<p>No es un truco de venta, es que <strong>me niego a que la herramienta prometa cosas que no hace</strong>. Si mira diez páginas, dice que mira diez páginas, si necesita tu Search Console para responder algo, lo dice en esa misma tarjeta.</p>
<h2>Auditoría SEO y GEO a fondo: 100 comprobaciones, también gratis</h2>
<p>Aquí es donde la cosa se pone interesante. Debajo de cada bloque del informe exprés hay un botón para pedir la auditoría completa, y el formulario ya lleva dentro lo que se ha encontrado, así que no tienes que explicarme nada.</p>
<p><a href="https://ayudawp.com/?attachment_id=160234" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160234 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/formulario-pedir-auditoria-seo-a-fondo-gratis-1200x569.jpg" alt="" width="1200" height="569" srcset="https://ayudawp.com/wp-content/uploads/2026/09/formulario-pedir-auditoria-seo-a-fondo-gratis-1200x569.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/formulario-pedir-auditoria-seo-a-fondo-gratis-768x364.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/formulario-pedir-auditoria-seo-a-fondo-gratis-1536x729.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/formulario-pedir-auditoria-seo-a-fondo-gratis.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<p>La a fondo son <strong>98 comprobaciones</strong> en lugar de 43, la hago yo con las herramientas internas que usamos para nuestros clientes, y sale un informe en PDF de treinta y tantas páginas con resumen ejecutivo, hallazgos ordenados por lo que más rinde al arreglarse y anexos con las direcciones concretas.</p>

<a href="https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/auditoria-seo-geo-a-fondo-salud/" rel="nofollow"><img width="1200" height="1354" src="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-salud-1200x1354.jpg" class="attachment-medium size-medium" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-salud-1200x1354.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-salud-768x866.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-salud-1362x1536.jpg 1362w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-salud-1815x2048.jpg 1815w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-salud.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/auditoria-seo-geo-a-fondo-resumen-ejecutivo/" rel="nofollow"><img width="1200" height="921" src="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-resumen-ejecutivo-1200x921.jpg" class="attachment-medium size-medium" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-resumen-ejecutivo-1200x921.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-resumen-ejecutivo-768x589.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-resumen-ejecutivo-1536x1178.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-resumen-ejecutivo.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/auditoria-seo-geo-a-fondo-hallazgos/" rel="nofollow"><img width="1200" height="1196" src="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-hallazgos-1200x1196.jpg" class="attachment-medium size-medium" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-hallazgos-1200x1196.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-hallazgos-150x150.jpg 150w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-hallazgos-768x766.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-hallazgos-1536x1531.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-hallazgos.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/auditoria-seo-geo-a-fondo-alcance/" rel="nofollow"><img width="1200" height="651" src="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-alcance-1200x651.jpg" class="attachment-medium size-medium" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-alcance-1200x651.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-alcance-768x416.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-alcance-1536x833.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-alcance.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/auditoria-seo-geo-a-fondo-que-implica/" rel="nofollow"><img width="1200" height="716" src="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-implica-1200x716.jpg" class="attachment-medium size-medium" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-implica-1200x716.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-implica-768x458.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-implica-1536x917.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-implica.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/auditoria-seo-geo-a-fondo-que-medir-soluciones/" rel="nofollow"><img width="1200" height="1631" src="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-medir-soluciones-1200x1631.jpg" class="attachment-medium size-medium" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-medir-soluciones-1200x1631.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-medir-soluciones-768x1044.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-medir-soluciones-1130x1536.jpg 1130w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-medir-soluciones-1507x2048.jpg 1507w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-que-medir-soluciones.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/auditoria-seo-geo-a-fondo-plan-accion-fase-1/" rel="nofollow"><img width="1200" height="1748" src="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-1-1200x1748.jpg" class="attachment-medium size-medium" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-1-1200x1748.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-1-768x1118.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-1-1055x1536.jpg 1055w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-1-1406x2048.jpg 1406w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-1.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/auditoria-seo-geo-a-fondo-plan-accion-fase-2-y-3/" rel="nofollow"><img width="1200" height="1361" src="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-2-y-3-1200x1361.jpg" class="attachment-medium size-medium" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-2-y-3-1200x1361.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-2-y-3-768x871.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-2-y-3-1354x1536.jpg 1354w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-2-y-3-1805x2048.jpg 1805w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-plan-accion-fase-2-y-3.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/auditoria-seo-geo-a-fondo-anexos/" rel="nofollow"><img width="1200" height="1206" src="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-anexos-1200x1206.jpg" class="attachment-medium size-medium" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-anexos-1200x1206.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-anexos-150x150.jpg 150w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-anexos-768x772.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-anexos-1528x1536.jpg 1528w, https://ayudawp.com/wp-content/uploads/2026/09/auditoria-seo-geo-a-fondo-anexos.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px" loading="lazy" decoding="async" fetchpriority="low"></a>

<h3>Seguro que aquí ya me pides pasta o algo ¿no?</h3>
<p><strong>¡Que nooo, que ya te he dicho que ambas auditorías son gratis!</strong></p>
<p>Pero ocho de esas 98 comprobaciones no se pueden hacer desde fuera ni queriendo, porque son datos que solo tienes tú:</p>
<ul>
<li>Informe exportado de tu Search Console, que es lo único que dice qué URLs están descubiertas sin indexar y por qué motivo exacto.</li>
<li>Exportación de redirecciones del plugin Redirection, o de lo que uses para gestionar redirecciones, para repasar las cadenas y los bucles que se van acumulando solos.</li>
<li>Exportación de la configuración de tu plugin SEO, sea Yoast, Rank Math, AIOSEO o SEOPress, que es donde suele estar el interruptor que lo explica todo o casi.</li>
</ul>
<p>Si no me los das, no pasa nada, el informe sale igual y esas ocho aparecen diciendo que no se han podido comprobar. <strong>Lo que no voy a hacer nunca es rellenar un hueco con una suposición y presentártelo como un hallazgo ¿vale?.</strong></p>
<h2>¿Y si lo quiero arreglar yo por mi cuenta?</h2>
<p>Claro, pues lo arreglas y ya está, que para eso cada comprobación del informe te dice qué hacer. Y donde hace falta un plugin la herramienta te recomienda los mejores, y <strong>solo te lo recomienda cuando esa comprobación te ha salido mal</strong>. Si esa parte de tu web está bien no te aparece ningún plugin, ni te lo menciono, ni te doy la brasa, solo información.</p>
<p>Los plugins que vas a ver que recomiendo según lo que necesites son cuatro, los cuatro desarrollados por mi, los cuatro gratis y los cuatro en el repositorio oficial de WordPress.org sin versión premium, completos:</p>
<ul>
<li><strong><a href="https://es.wordpress.org/plugins/native-aeo-pack/">Visibility</a></strong>, para casi todo lo de descubrimiento e indexación: el sitemap nativo, el robots.txt virtual, las etiquetas Open Graph y los datos estructurados tipo por tipo de contenido, todo desde un mismo sitio.</li>
<li><strong><a href="https://es.wordpress.org/plugins/vigia/">VigIA</a></strong>, para la parte de IA: te genera el llms.txt, lo mantiene al día y te enseña qué bots están pasando de verdad por tu web y qué se llevan.</li>
<li><strong><a href="https://es.wordpress.org/plugins/wpo-tweaks/">DietPress</a></strong>, para cuando lo que sale en rojo es el tiempo de respuesta, el peso del HTML o los cuarenta ficheros que carga la portada.</li>
<li><strong><a href="https://es.wordpress.org/plugins/ai-content-signals/">AI Content Signals</a></strong>, para declarar en el robots.txt si tu contenido se puede usar para entrenar modelos, para buscar o para responder.</li>
</ul>
<p>Y si lo que te preocupa es la parte de IA, el bloque correspondiente de la auditoría enlaza a nuestro <a href="https://herramientas.ayudawp.com/ai-visibility/">analizador de visibilidad IA</a>, que también es gratis y va más a fondo en eso concreto. De ahí sale la quinta recomendación, <strong><a href="https://es.wordpress.org/plugins/ai-share-summarize/" target="_blank" rel="nofollow noopener">Share Buttons &amp; AI-powered Summaries</a></strong>, que te pone botones para compartir tu contenido en redes y también en las IAs.</p>
<p>Lo segundo suena raro hasta que caes en que <strong>cada vez que alguien le pasa tu artículo a ChatGPT o a Claude estás metiendo tu web en una conversación donde antes no estabas</strong>, y de ahí salen menciones.</p>
<p>Y por supuesto, <strong>buena parte de lo que salga en el informe lo resuelve también el plugin SEO que ya tengas puesto</strong>, sea Yoast, Rank Math, AIOSEO o SEOPress. Si ya tienes uno mira ahí primero antes de instalar nada. Sumar plugins por sumar no arregla nada, y lo he dicho unas cuantas veces por aquí, y sí, los míos son mejores, y gratis del todo, pero vamos, que lo bueno es que hay para elegir.</p>
<h2>En serio, ¿ por qué es gratis?</h2>
<p>Me dedico, entre otras cosas, al <a href="https://mantenimiento.ayudawp.com/">mantenimiento de webs WordPress</a> y a resolverle problemas de seguridad, rendimiento y posicionamiento a quien los tiene, que para eso está <a href="https://servicios.ayudawp.com/">servicios.ayudawp.com</a>.</p>
<p><strong>La auditoría es lo que hago igualmente cuando entra un cliente nuevo</strong>, así que hacértela sin cobrar me cuesta un rato de trabajo y me sirve para dos cosas:</p>
<ul>
<li>Que puedas ver cómo trabajamos por si algún día te animas a colaborar con nosotros.</li>
<li>Para que, si quieres, nos encarguemos de ejecutar el plan, y sepas exactamente qué estás delegando.</li>
</ul>
<p>Pero eso es una posibilidad, no te comprometes a nada, como te he dicho es totalmente gratis. Si te llevas el informe y lo arreglas todo tú, me parece perfecto y no te voy a perseguir con correos.</p>
<p>Por otro lado, si el informe no te convence, tampoco vas a contratar, así que el filtro funciona en las dos direcciones. De paso te llevas un montón de información valiosa de tu web, y no has soltado ni un euro, .</p>
<h2>Qué cosas tiene la vida, y es que por si no lo sabías„ esta herramienta ya te ha ayudado antes incluso de conocerla</h2>
<p>Mientras montaba la herramienta de informes de auditoría se me quedó una comprobación en rojo en mis propios subdominios, diciendo que el mapa del sitio respondía con un 404. Y yo mirándolo en el navegador, viendo el XML perfecto, pensando que la herramienta estaba mal.</p>
<p>Pues no estaba mal. Resulta que <strong>WordPress sirve el sitemap nativo con código 404 cuando el sitio no tiene ninguna entrada publicada</strong>, porque pinta el XML sin fijar su propio estado y hereda el de la consulta principal. En el navegador se ve perfecto y en Search Console figura como no leído, así que a efectos de descubrimiento es como no tener sitemap.</p>
<p>Está reportado en el Trac de WordPress con el <a href="https://core.trac.wordpress.org/ticket/65945" rel="noopener">ticket #65945</a>, y te lo cuento con detalle en <a href="https://ayudawp.com/404-wp-sitemap-xml/">por qué tu <code>wp-sitemap.xml</code> devuelve un 404 y cómo arreglarlo</a>. No sé si la solución estará en WordPress 7.1.1 o en la 7.2, pero <strong>está en camino y arreglará un problemón de SEO que tenía WordPress y que la auditoría detectó</strong>, sin pretenderlo.</p>
<p>Eso es exactamente <strong>el tipo de cosa que no ves mirando tu web, que ninguna herramienta de semáforos te va a decir, y que te está costando indexación</strong> desde hace meses. Pues mira tú por donde, <strong>una auditoría SEO gratuita lo ha detectado, y es algo de lo que se van a beneficiar todos los usuarios de WordPress</strong>, antes incluso de estar disponible la herramienta.</p>
<h2>¿Tiene algún límite la auditoría SEO exprés?</h2>
<p>Alguno, básicamente para que no me tiren abajo el servidor y poco más, te lo resumo:</p>
<ul>
<li>Se pueden analizar cinco dominios distintos al día desde la misma conexión. Es para que nadie use esto de rastreador gratuito, y si necesitas más, pídeme la a fondo y listo.</li>
<li>El informe exprés se guarda seis meses con un enlace propio, así que lo puedes compartir con quien lleve tu web sin que caduque a los dos días, pero tampoco lo guardes para «un año de estos», pues además ya no servirá de nada.</li>
<li>La muestra que realiza la auditoría exprés son diez páginas, no es el sitio entero y en ningún momento te digo que lo sea, pero te sorprenderá lo que vas a aprender de ello.</li>
</ul>
<p>Que recuerde nada más, eso es lo único. Bueno, y que son 43 comprobaciones, si quieres muchas más pide la auditoría a fondo, también gratis.</p>
<h2>¿Por dónde empiezo para auditar gratis el SEO de mi web?</h2>
<p>Pues lo que yo haría, en este orden:</p>
<ol>
<li style="list-style-type: none;">
<ol>
<li>Pasar la exprés a tu web y leerte el bloque que sale abierto, que es el que tiene el problema más gordo.</li>
<li>Arreglar por tu cuenta lo que puedas, que si hace falta plugin te dice cuál y son todos gratis.</li>
<li>Bajar hasta el final de cada bloque y mirar la lista de lo que no se ha comprobado, porque ahí suele estar lo que llevas tiempo sin revisar.</li>
<li>Si algo de eso te preocupa pedir la a fondo desde el mismo informe. Tardo lo que tarde, dependiendo de la demanda, pero llega.</li>
</ol>
</li>
</ol>
<p>Y si la pasas y te sale algo que no entiendes, o que crees que está mal medido, me tienes ahí abajo en los comentarios. La herramienta lleva semanas cambiando precisamente porque la he ido probando contra webs reales y me he ido encontrando fallos míos por el camino, así que cualquier cosa rara que veas me interesa de verdad, que cuantos más análisis mejor para ir mejorando los informes.</p>
<p>Tú prueba, que no cuesta nada, de verdad.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ayudawp.com/auditoria-seo-geo-online-gratis-wordpress/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Impuestos en WooCommerce: guía de cómo YO conseguí configurarlos bien</title>
		<link>https://ayudawp.com/configurar-impuestos-woocommerce/</link>
					<comments>https://ayudawp.com/configurar-impuestos-woocommerce/#comments</comments>
		
		<dc:creator><![CDATA[Fernando Tellado]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 06:28:14 +0000</pubDate>
				<category><![CDATA[Tutoriales - Trucos]]></category>
		<category><![CDATA[WordPress.com]]></category>
		<category><![CDATA[WordPress.org]]></category>
		<category><![CDATA[IVA]]></category>
		<category><![CDATA[Principiante]]></category>
		<category><![CDATA[WooCommerce]]></category>
		<guid isPermaLink="false">https://ayudawp.com/?p=160068</guid>

					<description><![CDATA[En esta guía sobre cómo configurar impuestos en WooCommerce explico de manera ordenada y sencilla qué hace cada ajuste, qué cambia según lo que elijas y qué puede fallar.]]></description>
										<content:encoded><![CDATA[<p>La pantalla de <strong>impuestos de WooCommerce</strong> da más quebraderos de cabeza de los que debería, y no es por la cantidad de opciones, que tampoco son tantas, sino porque unas dependen de otras y algunas viven en pantallas distintas.</p>
<p>En esta guía he tratado de explicar de manera ordenada y sencilla <strong>qué hace cada ajuste importante, qué cambia según lo que elijas y dónde está el fallo cuando los precios no salen como esperabas</strong>.</p>
<p>Todo lo que tienes en este artículo es configuración de WooCommerce tal cual viene de serie, sin plugins adicionales. Y lo siento, no soy asesor fiscal, esto explica cómo funciona el software, pero no qué tienes que cobrar ni cuándo, así que para las dudas fiscales habla con tu gestoría.</p>
<p>El grueso del artículo cubre lo que necesita cualquier tienda española que venda a consumidor final dentro de España. Luego, al final, hay un bloque de casos especiales (recargo de equivalencia, retenciones de autónomos, Canarias, ventas a la Unión Europea, productos digitales) que solo tienes que leer si te afecta.</p>
<h2>Activa los impuestos ¿a que se te había olvidado?</h2>
<p>Si acabas de instalar WooCommerce puede que ni siquiera veas la pestaña de impuestos, y no es que se haya perdido. Está desactivada por defecto.</p>
<p>Vete a «<strong>WooCommerce &gt; Ajustes &gt; General</strong>», busca la sección de impuestos y marca la casilla «<strong>Activar tasas de impuestos y sus cálculos</strong>». En cuanto guardes te aparece una pestaña nueva llamada «<strong>Impuesto</strong>» arriba, junto al resto.</p>
<p><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160207 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/activar-impuestos-woocommerce-1200x274.jpg" alt="" width="1200" height="274" srcset="https://ayudawp.com/wp-content/uploads/2026/09/activar-impuestos-woocommerce-1200x274.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/activar-impuestos-woocommerce-768x175.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/activar-impuestos-woocommerce-1536x350.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/activar-impuestos-woocommerce.jpg 1570w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></p>
<p>Parecerá una bobada pero es la duda que más se repite en los foros de soporte y se resuelve en dos clics. ¿Ya?, pues empezamos.</p>
<h2>Precios con impuestos incluidos o sin ellos, la decisión que más cuesta deshacer</h2>
<p>El <strong>primer ajuste de la pestaña de impuestos</strong> es también el que más te va a condicionar, porque <strong>afecta a cómo introduces todos los precios de todos tus productos</strong>.</p>
<p>Tienes dos opciones, o introduces los precios con los impuestos ya incluidos, y WooCommerce calcula hacia atrás cuánto de ese precio es base y cuánto impuesto, o introduces los precios sin impuestos y WooCommerce los suma luego.</p>
<p><a href="https://ayudawp.com/?attachment_id=160214" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160214 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tasas-impuestos-1200x779.jpg" alt="" width="1200" height="779" srcset="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tasas-impuestos-1200x779.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tasas-impuestos-768x499.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tasas-impuestos-1536x998.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tasas-impuestos.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<p>Con números se ve mejor, lo vemos. Imagina un producto que quieres que le cueste al cliente <strong>9,99 €</strong> con el IVA general del 21 % incluido.</p>
<ul>
<li>Si eliges <strong>precios con impuestos incluidos</strong>, escribes 9,99 € en la ficha del producto y WooCommerce descompone ese importe en 8,26 € de base imponible y 1,73 € de IVA.</li>
<li>Si eliges <strong>precios sin impuestos</strong>, escribes 8,26 € en la ficha del producto y WooCommerce le suma el 21 % hasta llegar a esos mismos 9,99 €.</li>
</ul>
<p>El resultado final es el mismo, pero el número que tú tecleas es distinto, y ahí es donde te puedes liar tú, y liar a tus clientes como te líes ¿vaya lío, no?</p>
<p><strong>Si cambias esta opción cuando ya tienes el catálogo cargado, todos tus precios cambian de golpe</strong> y en la dirección contraria a la que esperas, porque los 9,99 € que habías metido pensando que llevaban IVA pasan a ser una base a la que ahora se le suma un 21 % encima, y el producto se le queda al cliente en 12,09 €.</p>
<p>Para una tienda que vende a consumidor final en España lo habitual es trabajar con precios con impuestos incluidos, porque es lo que el cliente espera ver y porque la ley de consumo obliga a mostrar el precio final. Si vendes a profesionales y tu catálogo va sin IVA, la otra opción tiene más sentido.</p>
<p>Y luego está la comodidad, la otra derivada, porque si te decides por poner en tus productos los precios con impuestos incluidos y un día el gobierno te cambia el IVA (por ejemplo) te toca modificar todos los precios uno a uno, variaciones incluidas, mientras que si elegiste crearlos con el precio antes de impuestos solo tendrías que cambiar el impuesto en los ajustes de impuestos. Valóralo también ¿vale?</p>
<p>Ya te dije que esto es un poco lioso, así que <strong>dale una pensada antes de decidirte, pero sobre todo haz pruebas siempre</strong> tras cualquier cambio, y hazlas como cliente, y completas.</p>
<h2>En base a qué ubicación se calculan los impuestos</h2>
<p>Este es el punto donde se atasca prácticamente todo el mundo, yo incluido, que lo tengo que pensar siempre un par de veces, y es que el síntoma es siempre el mismo, impuestos que no salen, o salen mal o cambian de repente.</p>
<p>La causa <strong>está repartida entre dos pantallas distintas que además no están ni siquiera cerca</strong>. Intuitivo ¿eh?</p>
<h3>Las tres opciones de cálculo</h3>
<p>En la pestaña de ajustes de impuestos (<strong>Impuesto</strong>) tienes un desplegable con tres posibilidades:</p>
<ul>
<li><strong>Dirección de envío del cliente</strong>: es la opción por defecto y aplica el impuesto que corresponda al sitio adonde va el paquete.</li>
<li><strong>Dirección de facturación del cliente</strong>: aplica el impuesto del sitio que el cliente haya puesto como dirección de facturación, aunque el envío vaya a otro lado.</li>
<li><strong>Dirección base de la tienda</strong>: aplica siempre tu impuesto, el de donde tú estás, el de la dirección a la que configuraste tu tienda, sin mirar dónde está el cliente.</li>
</ul>
<p><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160209 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-calcular-impuesto-basado-en-1200x349.jpg" alt="" width="1200" height="349" srcset="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-calcular-impuesto-basado-en-1200x349.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-calcular-impuesto-basado-en-768x223.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-calcular-impuesto-basado-en.jpg 1384w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></p>
<p><strong>Las dos primeras solo funcionan bien cuando el cliente ha rellenado ese dato</strong>, con lo cual no hacen ningún cálculo mientras el visitante está mirando la tienda sin haber puesto todavía una dirección. Y ahí es donde entra la segunda pantalla de la que te hablaba antes.</p>
<h3>Qué pasa con los impuestos antes de que el cliente diga dónde vive, y la madre que los parió a todos los que diseñan los ajustes de WooCommerce que, por supuesto, no tienen que vivir con ello</h3>
<p>El desplegable anterior decide qué dirección usar <em>una vez que WooCommerce la conoce</em>, pero <strong>mientras el visitante simplemente está curioseando productos WooCommerce no tiene ni idea de dónde está</strong>, ni por supuesto qué impuestos mostrar, así que necesita partir de alguna suposición.</p>
<p><strong>Esa suposición se configura en un sitio completamente distinto</strong>, en «<strong>WooCommerce &gt; Ajustes &gt; General &gt; Ubicación del cliente por defecto</strong>», y es <strong>la causa real de la mayoría de los problemas de impuestos</strong> que la gente atribuye al ajuste anterior.</p>
<p><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160210 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ubicacion-cliente-por-defecto-1200x390.jpg" alt="" width="1200" height="390" srcset="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ubicacion-cliente-por-defecto-1200x390.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ubicacion-cliente-por-defecto-768x249.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ubicacion-cliente-por-defecto.jpg 1330w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></p>
<p>Las opciones que tienes ahí y qué provoca cada una:</p>
<ul>
<li><strong>Sin ubicación por defecto</strong>: WooCommerce no supone nada, así que hasta que el visitante no dé una dirección es fácil que no se muestre ningún impuesto en la ficha de producto. Este es el famoso «<strong>no me sale el IVA en la tienda</strong>».</li>
<li><strong>País/región de la tienda</strong>: da por hecho que el visitante está donde estás tú hasta que diga lo contrario. Es la que menos sorpresas da si vendes sobre todo en España.</li>
<li><strong>Geolocalizar</strong>: detecta el país del visitante por su IP desde el primer momento. Ojo con esta si tienes caché de página, porque si el servidor está sirviendo la misma página guardada a todo el mundo, la detección puede no reflejarse.</li>
<li><strong>Geolocalizar (compatible con caché de página)</strong>: hace lo mismo pero resolviendo la detección por otra vía para que la caché no se la coma. Es la que hay que usar si quieres geolocalizar y tienes caché, que en un hosting decente la tienes seguro.</li>
</ul>
<p>Con esto ya puedes explicarte el síntoma más desesperante de todos, <strong>que en la ficha de producto veas un precio y al llegar al carrito o al finalizar la compra te salga otro distinto</strong>. Pasa cuando la ubicación que WooCommerce estaba suponiendo no coincide con la dirección real que el cliente acaba metiendo, y entonces recalcula.</p>
<p>Para la mayoría de tiendas españolas <strong>la pareja de ajustes que menos incidencias da</strong> es dejar la ubicación por defecto en <strong>País/región de la tienda</strong> y el cálculo en <strong>Dirección de envío del cliente</strong>. Con esta configuración <strong>el visitante ve desde el primer momento un precio con el IVA español, y si resulta que compra desde otro sitio, se recalcula al meter la dirección</strong>.</p>

<a href="https://ayudawp.com/configurar-impuestos-woocommerce/woocommerce-calcular-impuesto-direccion-envio-cliente/" rel="nofollow"><img width="1344" height="136" src="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-calcular-impuesto-direccion-envio-cliente.jpg" class="attachment-large size-large" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-calcular-impuesto-direccion-envio-cliente.jpg 1344w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-calcular-impuesto-direccion-envio-cliente-1200x121.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-calcular-impuesto-direccion-envio-cliente-768x78.jpg 768w" sizes="auto, (max-width: 1344px) 100vw, 1344px" loading="lazy" decoding="async" fetchpriority="low"></a>
<a href="https://ayudawp.com/configurar-impuestos-woocommerce/woocommerce-ubicacion-defecto-cliente-pais-region-tienda/" rel="nofollow"><img width="1334" height="146" src="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ubicacion-defecto-cliente-pais-region-tienda.jpg" class="attachment-large size-large" alt="" srcset="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ubicacion-defecto-cliente-pais-region-tienda.jpg 1334w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ubicacion-defecto-cliente-pais-region-tienda-1200x131.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ubicacion-defecto-cliente-pais-region-tienda-768x84.jpg 768w" sizes="auto, (max-width: 1334px) 100vw, 1334px" loading="lazy" decoding="async" fetchpriority="low"></a>

<h2>Clases de impuesto, una etiqueta para agrupar productos</h2>
<p>WooCommerce trae tres clases de impuesto de fábrica, que son <strong>Estándar</strong>, <strong>Tasa reducida</strong> y <strong>Tasa cero</strong>. Cada clase tiene su propia tabla de tasas independiente, y cada producto se asigna a una de ellas desde su ficha, en la pestaña general de los datos del producto.</p>
<p><a href="https://ayudawp.com/?attachment_id=160214" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160214 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tasas-impuestos-1200x779.jpg" alt="" width="1200" height="779" srcset="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tasas-impuestos-1200x779.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tasas-impuestos-768x499.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tasas-impuestos-1536x998.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tasas-impuestos.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<p>Puedes añadir las clases que necesites escribiéndolas en el campo correspondiente de la pantalla de opciones, una por línea. En cuanto guardes te aparecen como subpestañas nuevas en la parte de arriba, junto a las que ya había, y cada una con su tabla vacía esperando a que le metas tasas.</p>
<p><strong>Para una tienda española normal no necesitas crear ninguna clase adicional</strong>, porque los tres tipos de IVA que existen encajan directamente en las tres que ya vienen. El general va en Estándar, el reducido en Tasa reducida y el superreducido lo puedes meter en Tasa cero renombrándola mentalmente, o crear una clase nueva llamada Superreducido si prefieres tenerlo claro al mirar la ficha de un producto.</p>
<h2>La tabla de tasas de impuestos, columna por columna</h2>
<p>Aquí es donde se define de verdad qué se cobra. Entras en cualquiera de las clases, pulsas en insertar fila y rellenas las columnas.</p>
<p><a href="https://ayudawp.com/?attachment_id=160218" rel="nofollow"><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160218 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tabla-tasas-impuestos-empresa-peninsula-espana-1200x728.jpg" alt="" width="1200" height="728" srcset="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tabla-tasas-impuestos-empresa-peninsula-espana-1200x728.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tabla-tasas-impuestos-empresa-peninsula-espana-768x466.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tabla-tasas-impuestos-empresa-peninsula-espana-1536x932.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-tabla-tasas-impuestos-empresa-peninsula-espana.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></a></p>
<h3>Las columnas de siempre</h3>
<ul>
<li><strong>Código de país</strong>: dos letras en mayúsculas, <code>ES</code> para España. Un asterisco significa todos los países.</li>
<li><strong>Código de provincia</strong>: igual, con asterisco para todas. Si solo vendes en península y Baleares, con el asterisco lo tienes resuelto.</li>
<li><strong>Código postal</strong>: admite varios separados por punto y coma, comodines con asterisco al final (<code>07*</code> coge todos los que empiecen por 07) y rangos numéricos con tres puntos (<code>07000...07999</code>). Lo que no puedes es mezclar las dos técnicas, porque <strong>un comodín dentro de un rango numérico no funciona</strong>.</li>
<li><strong>Ciudad</strong>: lista separada por punto y coma y coincidencia exacta, o sea que si el cliente escribe el nombre de otra manera no coincide. Poco fiable, mejor usar códigos postales.</li>
<li><strong>Tasa %</strong>: el número, con punto decimal si lleva decimales. Para el 21 % se escribe <code>21.0000</code>.</li>
<li><strong>Nombre del impuesto</strong>: el texto que verá el cliente si tienes activado el desglose. Aquí pon IVA, o lo que toque.</li>
</ul>
<h3>¿Qué es eso de la prioridad?</h3>
<p>La prioridad <strong>es un número que le pones a cada fila</strong>, y la forma más fácil de entenderla es pensar en <strong>turnos</strong>.</p>
<p>WooCommerce va por turnos empezando por el número más bajo. En cada turno mira todas las filas que llevan ese número, se queda con la primera que encaje con la venta, la cobra y pasa al turno siguiente. Cuando ya no quedan filas, se acabó.</p>
<p>De ahí salen las dos únicas cosas que tienes que recordar:</p>
<ul>
<li><strong>Dos filas con el mismo número</strong>: compiten entre ellas y solo se cobra una.</li>
<li><strong>Dos filas con números distintos</strong>: se cobran las dos, una detrás de otra.</li>
</ul>
<p>Y ahora los dos casos reales donde esto te va a pasar de verdad.</p>
<p><strong>Cuando quieres que solo se aplique una</strong>, que es lo normal. Imagina que tienes una fila para todo el país con el IVA del 21 % y otra para Las Palmas al 0 %, porque a Canarias no le repercutes IVA. Un cliente de Las Palmas encaja con las dos, así que las dos tienen que llevar <strong>la misma prioridad, el 1</strong>. Así solo hay un turno, se cobra una sola fila y en paz.</p>
<p>Si por despiste le pusieras a la fila de Canarias la prioridad 2, pasaría esto: en el turno 1 se le cobra el 21 % de la fila general y en el turno 2 se le cobra el 0 % de la fila canaria, que no suma nada. Resultado, el cliente de Las Palmas paga el 21 % de IVA que precisamente querías ahorrarle, porque <strong>una fila al 0 % no anula a la anterior, simplemente no suma nada</strong>.</p>
<p><strong>Cuando quieres que se apliquen las dos</strong>, que es el caso del recargo de equivalencia. Aquí es justo al revés, porque necesitas cobrar el IVA y encima el recargo. La fila del IVA al 21 % va con prioridad 1 y la del recargo al 5,2 % con prioridad 2. Sobre una base de 100 € se cobran 21 € en el primer turno y 5,20 € en el segundo, así que el cliente paga 126,20 €.</p>
<p>Si les pusieras a las dos la prioridad 1 competirían entre ellas, se cobraría solo la primera y te faltarían esos 5,20 € en cada pedido.</p>
<p><strong>Y si tu tienda no está en ninguno de esos dos casos</strong>, o sea si solo cobras IVA español y punto, pon un 1 en todas las filas y olvídate del asunto.</p>
<h3>¿Compuesto? Ojo con esta casilla, que cambia precios sin avisar</h3>
<p>Esta casilla decide una sola cosa, <strong>si ese impuesto se calcula sobre el precio del producto o sobre el precio del producto con el impuesto anterior ya sumado encima</strong>. Dicho a lo bruto, marcarla es cobrar impuesto del impuesto.</p>
<p>Se ve clarísimo otra vez con el recargo de equivalencia, que es el único caso español en el que vas a tener dos filas conviviendo. Partimos de una base de 100 €, IVA del 21 % y recargo del 5,2 %:</p>
<ul>
<li><strong>Sin compuesto</strong>, que es lo correcto: el recargo se calcula sobre los 100 € de base, o sea 5,20 €. El cliente paga 126,20 €.</li>
<li><strong>Con compuesto</strong>, que es el error: el recargo se calcula sobre 121 €, o sea 6,29 €. El cliente paga 127,29 €.</li>
</ul>
<p>Un euro y pico de diferencia en un pedido de 100 €, que en uno de 1.000 € se convierte en casi 11 € que le estás cobrando de más a tu cliente sin que ni él ni tú os hayáis enterado. <strong>En España esta casilla se queda sin marcar</strong>, porque tanto el IVA como el recargo se calculan sobre la misma base.</p>
<h3>La casilla de envío</h3>
<p>Decide si esa tasa se cobra también sobre los gastos de envío, además de sobre los productos. Con un ejemplo se ve en un segundo, pedido de 100 € con 5 € de gastos de envío e IVA del 21 %:</p>
<ul>
<li><strong>Casilla marcada</strong>: el 21 % se calcula sobre 105 €, o sea 22,05 € de IVA. El cliente paga 127,05 €.</li>
<li><strong>Casilla sin marcar</strong>: el 21 % se calcula solo sobre los 100 € de los productos, o sea 21 €, y el envío se va limpio. El cliente paga 126 €.</li>
</ul>
<p>Lo normal es tenerla marcada en tus filas de IVA, porque el transporte también lleva IVA. Se deja sin marcar en casos concretos, como la fila del recargo de equivalencia, que grava el producto y no el porte.</p>
<p>Y aunque parezca una casilla inofensiva tiene más mala leche de la que aparenta, porque se coordina con otro ajuste que está en otra parte de la pantalla y ahí es donde se puede liar parda. Te lo cuento un poco más abajo, en su propia sección.</p>
<h3>Los tipos de IVA que hay que dar de alta</h3>
<p>Actualmente los tipos de IVA que hay en España son estos:</p>
<ul>
<li><strong>General, 21 %</strong>: todo lo que no esté expresamente en las dos listas siguientes. Si no sabes qué tipo aplicarle a algo, casi seguro que es este.</li>
<li><strong>Reducido, 10 %</strong>: alimentación en general, hostelería, transporte de viajeros y vivienda, entre otros.</li>
<li><strong>Superreducido, 4 %</strong>: pan común, leche, huevos, frutas y verduras naturales, aceite de oliva (que se quedó aquí de forma permanente desde el 1 de enero de 2025), libros, periódicos y medicamentos de uso humano.</li>
</ul>
<p>Hay una cuarta situación que no es un tipo sino una exención, y conviene no confundirla. La enseñanza reglada, la sanidad o algunos servicios financieros no llevan IVA porque están exentos, que no es lo mismo que estar al 0 %, y tiene consecuencias en el derecho a deducir de quien presta el servicio. Si vendes algo de esto, consúltalo con tu asesoría antes de meterlo en la tabla.</p>
<p>Los listados de productos por tipo se retocan de vez en cuando, así que si vendes algo que no tengas clarísimo, échale un vistazo a la <a href="https://sede.agenciatributaria.gob.es/" target="_blank" rel="nofollow noopener">web de la Agencia Tributaria</a> antes de dar por buena una tasa.</p>
<h3>Importar, exportar y borrar tasas</h3>
<p>Al pie de cada tabla de tasas de impuestos tienes botones para importar y exportar en CSV, muy útiles si mantienes un entorno de pruebas y otro de producción, o si gestionas varias tiendas parecidas.</p>
<p>El CSV lleva diez columnas en este orden: país, estado, código postal, ciudad, tasa, nombre del impuesto, prioridad, compuesto, envío y clase de impuesto. En vez de construirlo a mano, <strong>crea una fila cualquiera desde la interfaz y exporta</strong>, así tienes la plantilla exacta y solo tienes que rellenarla.</p>
<p>Para borrar, seleccionas las filas que quieras (con mayúsculas o con la tecla de comando para elegir varias) y pulsas en eliminar. Si lo que quieres es empezar de cero, en <strong>WooCommerce &gt; Estado &gt; Herramientas</strong> tienes una herramienta para eliminar todas las tasas de impuesto de golpe. Eso sí, <strong>esa acción no se puede deshacer</strong>, así que úsala solo si vas a rehacer la configuración entera.</p>
<h2>Los precios que ve el cliente y el aviso que sale cuando algo no cuadra</h2>
<p>Un poco más abajo en la misma pantalla de ajustes de los impuestos hay dos desplegables que deciden qué ve el cliente, y son independientes entre sí.</p>
<ul>
<li><strong>Mostrar los precios en la tienda</strong>: con impuestos incluidos o sin ellos.</li>
<li><strong>Mostrar los precios en el carrito y al finalizar la compra</strong>: lo mismo, pero puede ser distinto del anterior.</li>
</ul>
<p>Que sean independientes tiene sentido en algunos casos, por ejemplo en una tienda para profesionales que muestra el catálogo sin IVA pero luego desglosa en el carrito. Lo que no tiene sentido es que no cuadren sin querer.</p>
<p>Cuando la combinación de estos dos desplegables con el ajuste de precios con impuestos incluidos no es coherente, <strong>WooCommerce te muestra un aviso en la propia pantalla advirtiendo de que esa mezcla puede provocar descuadres de céntimos por redondeo</strong>, con un botón para igualar los tres de golpe.</p>
<p><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160220 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-aviso-problemas-redondeo-impuestos-ajustes-impuestos-1200x734.jpg" alt="" width="1200" height="734" srcset="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-aviso-problemas-redondeo-impuestos-ajustes-impuestos-1200x734.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-aviso-problemas-redondeo-impuestos-ajustes-impuestos-768x470.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-aviso-problemas-redondeo-impuestos-ajustes-impuestos.jpg 1376w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></p>
<p>Si te sale ese aviso hazle caso, porque lo que viene después son clientes preguntándote por qué el total no les sale.</p>
<h2>El impuesto de los gastos de envío, con sus casos especiales</h2>
<p>Los gastos de envío también llevan impuesto, y decidir cuál es más enrevesado de lo que parece porque intervienen dos cosas a la vez.</p>
<h3>El desplegable de clase de impuesto de envío</h3>
<p>En la misma pantalla de opciones tienes un desplegable para la clase de impuesto que se aplica al envío, con estas posibilidades:</p>
<ul>
<li><strong>Basado en los artículos del carrito</strong>: es la opción por defecto y hereda la clase de los productos que lleve el pedido.</li>
<li><strong>Estándar</strong>, <strong>Tasa reducida</strong>, <strong>Tasa cero</strong> o cualquier clase que hayas creado: fuerza siempre esa, pase lo que pase.</li>
</ul>
<p><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160221 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ajusets-impuesto-por-envio-1200x429.jpg" alt="" width="1200" height="429" srcset="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ajusets-impuesto-por-envio-1200x429.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ajusets-impuesto-por-envio-768x275.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ajusets-impuesto-por-envio-1536x550.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-ajusets-impuesto-por-envio.jpg 1582w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></p>
<h3>¿Y qué pasa cuando el carrito mezcla productos de clases distintas?</h3>
<p>Aquí está la regla que hay que saberse de memoria, porque no es intuitiva que se diga. Si dejas la opción por defecto y el pedido lleva productos de varias clases, <strong>manda la clase Estándar en cuanto haya al menos un producto que la use</strong>, sea o no el tipo más alto de los que lleva el carrito. Y <strong>si no hay ningún producto en Estándar se usa la primera clase adicional que aparezca</strong> en tu lista de clases.</p>
<p>Un ejemplo de los que pasan todos los días. Un pedido con un libro al 4 % y una camiseta al 21 %, más 5 € de gastos de envío. Como la camiseta está en la clase Estándar, <strong>el envío tributa al 21 %</strong>, así que el cliente paga 5 € más 1,05 € de IVA por el transporte, y no los 0,20 € que saldrían si se aplicara el tipo del libro.</p>
<p>De esa regla sale un truco útil, y es que <strong>si necesitas que el envío tribute siempre a una clase adicional concreta cuando no haya productos estándar</strong> de por medio, esa clase tiene que ir la primera de la lista, porque es la que WooCommerce coge en ese caso.</p>
<h3>La casilla de envío de cada tasa</h3>
<p>Y ahora la parte que descoloca, y es que el hecho de elegir una clase en ese desplegable no basta, porque <strong>quien decide de verdad si se cobra impuesto por el envío es la casilla de envío de cada fila de la tabla de tasas</strong>.</p>
<p>El error típico es cuando seleccionas <strong>Tasa reducida</strong> en el desplegable pensando que así el envío irá al 10 %, pero resulta que la fila del 10 % en la tabla no tiene marcada la casilla de envío. El resultado no es que el envío vaya al 10 %, es que <strong>el envío no lleva impuesto ninguno</strong>. Las dos cosas tienen que ir coordinadas o el resultado te dará disgustos.</p>
<p>Para el caso normal deja el desplegable en la opción por defecto basada en los artículos del carrito y asegúrate de que la fila del IVA general tiene marcada la casilla de envío. Con eso cubres casi todas las combinaciones sin sustos.</p>
<h2>Redondeo: cuándo es importante y cuándo da igual</h2>
<p>Hay una <strong>casilla para redondear el impuesto a nivel de subtotal en vez de hacerlo línea a línea</strong>. Por defecto viene desmarcada, así que WooCommerce redondea el impuesto de cada línea de producto por separado y luego suma.</p>
<p><strong>La diferencia solo se nota en pedidos con muchas líneas y tasas con decimales</strong>, donde cada redondeo por línea puede arrastrar medio céntimo arriba o abajo y al sumarlos todos aparece un descuadre de uno o dos céntimos frente a calcular el impuesto una sola vez sobre el total ya sumado.</p>
<p>Con tres artículos no vas a notar nada, pero con un pedido mayorista de cuarenta líneas puede que sí, y entonces marcar esta casilla te ahorra la conversación de los céntimos con el cliente y con la asesoría. <strong>Si tu asesoría te pide que los importes cuadren al céntimo con su programa, prueba a marcarla</strong>, porque muchos programas de contabilidad calculan sobre el subtotal.</p>
<h2>El sufijo de precio, para enseñar los dos importes a la vez</h2>
<p>Es un campo de texto libre que se pinta detrás del precio en toda la tienda, y acepta dos comodines que WooCommerce sustituye por el importe correspondiente.</p>
<ul>
<li><code>{price_including_tax}</code>: el precio con impuestos.</li>
<li><code>{price_excluding_tax}</code>: el precio sin impuestos.</li>
</ul>
<p>Con esto puedes montar cosas como <strong>IVA incluido</strong> a secas, o algo más completo tipo <code>{price_excluding_tax} + IVA</code> si tu tienda <strong>muestra precios finales pero quieres que se vea la base</strong>. La utilidad más habitual es al revés, en tiendas para profesionales que enseñan precios sin IVA y necesitan dejar claro cuál es el importe final.</p>
<p>Un detalle que despista, <strong>en los productos variables el sufijo no aparece hasta que el cliente elige una variación</strong>, porque hasta ese momento WooCommerce no sabe qué precio tiene que calcular.</p>
<h2>El total de impuestos: ¿único o detallado?</h2>
<p>El último ajuste de la pantalla decide cómo se ve el impuesto en el carrito y al finalizar la compra.</p>
<ul>
<li><strong>Como un total único</strong>: una sola línea que pone «Impuestos» y suma todo lo que haya.</li>
<li><strong>Detallado</strong>: una línea por cada tasa, con el nombre que le hayas puesto en la columna correspondiente de la tabla.</li>
</ul>
<h3>Qué conviene poner</h3>
<p>Si toda tu tienda va con un único tipo de IVA, el total único queda más limpio y es perfectamente correcto. En cuanto puedes tener dos tipos en el mismo pedido, o dos impuestos a la vez como pasa con el recargo de equivalencia, <strong>el desglosado te ahorra problemas</strong> porque el cliente ve en pantalla lo mismo que se va a encontrar luego en la factura.</p>
<h3>¿Qué es lo obligatorio por ley?</h3>
<p>Aquí conviene no mezclar dos cosas distintas. <strong>Este ajuste afecta a la pantalla de compra, que es experiencia de usuario, y no a la factura</strong>, que es otra historia.</p>
<p>La obligación de verdad está en el Reglamento de facturación, el <a href="https://www.boe.es/buscar/act.php?id=BOE-A-2012-14696" target="_blank" rel="nofollow noopener">Real Decreto 1619/2012</a>, cuyo artículo 6 exige que la factura indique el tipo aplicado y la cuota por separado, y que <strong>cuando una misma factura tenga operaciones a distintos tipos de IVA se desglose también la base imponible que corresponde a cada uno</strong>.</p>
<p>Eso afecta al documento de factura, que WooCommerce por sí solo no genera, así que <strong>activar el desglose en el carrito no equivale a cumplir con Hacienda</strong>. Es una buena práctica de transparencia y evita que la pantalla de compra y la factura se contradigan, pero la factura la tendrás que emitir con tu programa de facturación o con un plugin dedicado.</p>
<h2>Por qué a veces los ajustes de WooCommerce salen en gris, inactivos</h2>
<p>Si abres la pantalla y la ves distinta a lo que te estoy contando, con la mitad de las opciones desactivadas y sin poder tocarlas, probablemente tengas activado el cálculo automático de impuestos.</p>
<p>Cuando ese cálculo automático está activo WooCommerce deja de hacerte caso a la tabla manual porque los tipos los decide un servicio externo según la dirección del cliente. <strong>Para poder seguir los pasos de esta guía tienes que desactivarlo</strong>, y entonces recuperas el control de la tabla de tasas.</p>
<h2>Los informes de impuestos</h2>
<p>En <strong>WooCommerce &gt; Análisis &gt; Impuestos</strong> tienes el resumen de lo recaudado, con filtro por fechas y desglose por cada tasa que tengas configurada.</p>
<p><img loading="lazy" decoding="async" class="sombra alignnone wp-image-160224 size-medium" src="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-analisis-impuestos-1200x701.jpg" alt="" width="1200" height="701" srcset="https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-analisis-impuestos-1200x701.jpg 1200w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-analisis-impuestos-768x448.jpg 768w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-analisis-impuestos-1536x897.jpg 1536w, https://ayudawp.com/wp-content/uploads/2026/09/woocommerce-analisis-impuestos.jpg 1920w" sizes="auto, (max-width: 1200px) 100vw, 1200px"></p>
<p>Es lo que le vas a pasar a tu gestoría cada trimestre, y de paso es la comprobación más rápida de si la configuración está bien hecha, porque si ves tasas que no esperabas o importes raros, algo has liado en la tabla.</p>
<h2>Repaso rápido para no dejarte nada</h2>
<p>El orden en el que conviene tomar las decisiones, por si quieres ir marcando:</p>
<ol>
<li>Activar los impuestos en los ajustes generales.</li>
<li>Decidir si introduces los precios con impuestos incluidos o sin ellos, antes de cargar el catálogo.</li>
<li>Poner la ubicación del cliente por defecto en Ajustes generales.</li>
<li>Elegir según qué dirección se calculan los impuestos.</li>
<li>Dar de alta las tasas de los tipos que necesites, con su nombre y su prioridad.</li>
<li>Coordinar la clase de impuesto del envío con la casilla de envío de la tasa que corresponda.</li>
<li>Ajustar el redondeo y cómo se muestran precios y totales.</li>
<li>Hacer un pedido de prueba y comprobar que los números salen donde tienen que salir.</li>
</ol>
<p>Y los fallos que más se repiten, para que los tengas fichados:</p>
<ul>
<li>Cambiar lo de precios con impuestos incluidos cuando el catálogo ya está cargado, y no revisar qué le ha pasado al margen.</li>
<li>Dejar la ubicación del cliente por defecto sin poner y volverse loco buscando por qué no sale el IVA en la tienda.</li>
<li>Marcar la casilla de compuesto pensando que sirve para relacionar dos impuestos que en realidad van sobre la misma base.</li>
<li>Elegir una clase de impuesto para el envío sin comprobar que esa tasa tiene marcada la casilla de envío.</li>
<li>Poner la misma prioridad a dos tasas que tenían que aplicarse las dos a la vez.</li>
</ul>
<h2>Los casos especiales: IRPF, recargo de equivalencia, otros impuestos y envíos, productos digitales, etc.</h2>
<p>Hasta aquí lo que necesita una tienda española que vende a consumidor final dentro de España. Lo que viene ahora solo te hace falta si estás en alguno de estos supuestos, así que ve directo al tuyo.</p>
<h3>Vendes a comerciantes minoristas, recargo de equivalencia</h3>
<p>El recargo de equivalencia <strong>es un régimen especial de IVA obligatorio para comerciantes minoristas</strong> que sean personas físicas o comunidades de bienes y que vendan productos sin transformar al consumidor final. Si tus clientes son de ese perfil, tienes que facturarles el IVA más un recargo adicional.</p>
<p>Lo básico:</p>
<ul>
<li>Los tipos vigentes en 2026 son 5,2 % para los productos que van al 21 %, 1,4 % para los que van al 10 % y 0,5 % para los del 4 %.</li>
<li>En la tabla de tasas se monta con dos filas del mismo país y prioridades distintas, una para el IVA y otra para el recargo, como te contaba en la sección de prioridad.</li>
<li>La fila del recargo no se marca como compuesta, porque va sobre la misma base que el IVA.</li>
<li>Tampoco se le suele marcar la casilla de envío, porque el recargo grava el producto y no el transporte.</li>
<li>Con el desglose de totales activado, para que en el pedido se vean el IVA y el recargo como conceptos separados.</li>
</ul>
<p>Y aquí está el límite de lo que WooCommerce hace solo, porque <strong>la tabla de tasas funciona por zonas geográficas y no distingue qué tipo de cliente está comprando</strong>, que es justo lo que necesitas para decidir si aplicas el recargo o no. Esa parte te la conté en su momento con la solución por rol de usuario en <a href="https://ayudawp.com/recargo-equivalencia-woocommerce/" target="_blank" rel="ugc noopener">el artículo dedicado al recargo de equivalencia en WooCommerce</a>.</p>
<h3>Eres autónomo y tienes que retener IRPF</h3>
<p>Si eres autónomo dado de alta en una actividad profesional y le vendes a otros profesionales o a empresas, en esas facturas hay que restar la retención del IRPF.</p>
<p>Lo básico:</p>
<ul>
<li>El tipo general de retención es el 15 %, con un reducido del 7 % para nuevos autónomos durante el año de alta y los dos siguientes.</li>
<li>Solo aplica en actividades profesionales, las de las secciones segunda y tercera del impuesto de actividades económicas, no en las empresariales de la sección primera.</li>
<li>Nunca se le retiene a un particular, solo a empresas y profesionales.</li>
<li>La retención se calcula sobre la base imponible, y el IVA también, así que el IVA no cambia por el hecho de que haya retención.</li>
</ul>
<p><strong>Esto no se puede montar solo con la tabla de tasas de WooCommerce</strong>, porque todas sus columnas son geográficas y ninguna distingue qué tipo de cliente está comprando, que es justo lo que decide si hay retención o no. Lo tienes desarrollado, con los requisitos que debe cumplir cualquier solución y las opciones que hay según tu caso, en <a href="https://ayudawp.com/woocommerce-irpf-autonomos/" target="_blank" rel="ugc noopener">el artículo sobre la retención de IRPF en WooCommerce</a>.</p>
<h3>Envías a Canarias, Ceuta o Melilla desde la península</h3>
<p>Estos territorios están fuera del ámbito de aplicación del IVA español, así que la venta desde la península hacia allí es una <strong>exportación exenta</strong>. Y de ahí sale lo que más confunde, y es que tú no cobras absolutamente ningún impuesto en esa venta.</p>
<p>Ni IVA, que no aplica, ni tampoco el IGIC canario o el IPSI de Ceuta y Melilla, porque esos <strong>los liquida el cliente en destino</strong> cuando el transportista o Correos le entrega el paquete, junto con los gastos de gestión que le cobren por el trámite.</p>
<p>En la tabla de tasas se refleja con cuatro filas al 0 %, una por cada provincia implicada, usando los códigos de provincia que espera WooCommerce:</p>
<ul>
<li><code>ES</code> / <code>GC</code> / <code>0.0000</code> para Las Palmas.</li>
<li><code>ES</code> / <code>TF</code> / <code>0.0000</code> para Santa Cruz de Tenerife.</li>
<li><code>ES</code> / <code>CE</code> / <code>0.0000</code> para Ceuta.</li>
<li><code>ES</code> / <code>ML</code> / <code>0.0000</code> para Melilla.</li>
</ul>
<p>Si prefieres tirar de códigos postales, el equivalente es <code>35*</code> y <code>38*</code> para Canarias, <code>51*</code> para Ceuta y <code>52*</code> para Melilla. Y acuérdate de marcarles la casilla de envío, porque tampoco se repercute impuesto sobre el transporte de una operación exenta.</p>
<p>Hay un detalle que tienes que comprobar tú y no dar por hecho, y es que si tu fila del IVA general lleva un asterisco en la columna de provincia, esa fila también encaja con un cliente de Las Palmas, así que las dos compiten.</p>
<p>Como solo se aplica una tasa por prioridad, coloca las filas específicas por encima de la general arrastrándolas en la tabla y <strong>haz un pedido de prueba con una dirección canaria para ver cuál gana de verdad</strong>. Son cinco minutos y te ahorran facturar mal durante meses.</p>
<p>Y un aviso que va más allá de los impuestos, porque un envío a estos destinos puede llevar trámites de aduana según el producto y su valor. Eso condiciona también cómo montes las zonas de envío, y es de las cosas que conviene consultar con tu gestoría antes de abrir la venta a estos territorios.</p>
<h3>Tu tienda está en Canarias</h3>
<p>Aquí la película es la contraria, porque <strong>sí repercutes IGIC</strong> en tus ventas dentro del archipiélago, y no IVA. La buena noticia es que la mecánica de WooCommerce es exactamente la misma que te he contado en todo el artículo, solo cambian los números que metes en las tasas.</p>
<p>Los tipos vigentes en 2026 son estos:</p>
<ul>
<li><strong>0 %</strong>: pan, leche, huevos, harinas, frutas, verduras, agua, libros, periódicos, medicamentos de uso humano y vivienda de protección oficial.</li>
<li><strong>3 %</strong>: transporte de viajeros, hostelería y reparaciones de vivienda, entre otros.</li>
<li><strong>7 %</strong>: el tipo general, o sea todo lo que no encaje en ningún otro. Es el equivalente al 21 % peninsular.</li>
<li><strong>9,5 %</strong>: perfumería, joyería por debajo de 400 € y embarcaciones de hasta nueve metros.</li>
<li><strong>15 %</strong>: artículos considerados suntuarios, como vehículos de lujo, embarcaciones grandes o joyas por encima de 400 €.</li>
<li><strong>20 %</strong>: labores del tabaco rubio.</li>
</ul>
<p>Desde 2026 hay además un tipo específico del 1 % para el petróleo y sus derivados, así que si vendes algo de eso no lo metas en el general por costumbre.</p>
<p><strong>Un matiz que despista es que el tipo cero del IGIC no es lo mismo que una operación exenta</strong>. A tipo cero repercutes un 0 % pero conservas el derecho a deducir el IGIC que hayas soportado, mientras que en una operación exenta no deduces.</p>
<p>Para WooCommerce da igual porque en los dos casos la fila va a cero, pero para tu modelo 420 la diferencia es grande, así que no las mezcles en la misma clase de impuesto si quieres tener los números claros al cerrar el trimestre.</p>
<p>Si además vendes a la península desde Canarias, esa venta es una exportación igual que en el caso anterior, así que necesitas una fila al 0 % para el resto de provincias españolas. Lo que no puedes hacer es facturarle IGIC a un cliente peninsular, que es el error más típico de quien monta la tienda desde el archipiélago.</p>
<p>Los tipos y qué producto va en cada uno los actualiza la Agencia Tributaria Canaria, así que consúltalo ahí antes de dar por buena ninguna tasa, que estos tipos se retocan más a menudo que los peninsulares.</p>
<h3>Tu tienda está en Ceuta o Melilla</h3>
<p>Aquí <strong>no hay ni IVA ni IGIC sino IPSI</strong>, con tipos que van del 0,5 % al 10 % según la actividad. La particularidad es que <strong>cada ciudad tiene su propia ordenanza fiscal</strong>, así que no existe una tabla común que te sirva para las dos y tienes que mirar la de tu ciudad para saber qué tipo le corresponde a cada cosa que vendes.</p>
<p>El montaje en WooCommerce no tiene misterio una vez sabes los tipos, es dar de alta las tasas en las clases correspondientes igual que en cualquier otro caso.</p>
<h3>Vendes a particulares de otros países de la Unión Europea</h3>
<p>Mientras tus ventas a consumidores de otros países de la Unión Europea no pasen de 10.000 € al año en conjunto (no por país, sumando todos), <strong>sigues aplicando el IVA español y lo declaras en tu modelo 303</strong> de siempre.</p>
<p>Cuando pasas ese umbral cambia la película porque tienes que aplicar el IVA del país de cada cliente. Sería así:</p>
<ul>
<li>Te das de alta en el régimen de ventanilla única con el modelo 035 en la sede de la Agencia Tributaria.</li>
<li>Declaras todas esas ventas juntas con el modelo 369 trimestral, y la Agencia reparte a cada país lo suyo.</li>
<li>Una vez dado de alta, el 369 se presenta cada trimestre aunque no hayas vendido nada en ese periodo.</li>
<li>Hay otro régimen distinto, la ventanilla única de importación, para mercancía que viene de fuera de la Unión Europea por debajo de 150 €. No lo confundas con el anterior.</li>
<li>Si le vendes a una empresa de otro país con número de operador intracomunitario válido, la operación va sin IVA por inversión del sujeto pasivo, que es otro supuesto diferente.</li>
</ul>
<p>Montar los tipos de veintitantos países a mano en la tabla de tasas es posible pero es un suplicio de mantener, porque los tipos cambian y te enteras tarde. Para esto sí merece la pena un plugin que traiga los tipos actualizados y te controle el umbral. La parte de darte de alta y presentar los modelos no te la quita ningún plugin, eso sigue siendo cosa tuya y de tu asesoría.</p>
<h3>Vendes productos digitales</h3>
<p>Descargas, cursos, software y en general cualquier servicio prestado por vía electrónica tienen su propia regla desde 2015, y es que <strong>el IVA se calcula según dónde esté el cliente, no según dónde estés tú</strong>, sin umbral que valga para los consumidores de la Unión Europea.</p>
<p>Cómo se monta en WooCommerce:</p>
<ul>
<li>Creas una clase de impuesto adicional, por ejemplo llamada Bienes digitales.</li>
<li>Le cargas en esa clase los tipos de IVA de cada país miembro.</li>
<li>Asignas esa clase a tus productos digitales desde la ficha de cada uno, o en lote desde el listado de productos con la edición rápida.</li>
<li>Compruebas que el cálculo por dirección está en la del cliente y no en la de la tienda, porque si no, nada de esto sirve.</li>
</ul>
<p>Y hay una obligación que no es de WooCommerce pero que te afecta, y es que tienes que <strong>conservar pruebas de dónde estaba el cliente</strong>, normalmente su dirección de facturación y la dirección IP desde la que compró. Aquí también te viene bien un plugin de los que geolocalizan y guardan esa evidencia, porque hacerlo a mano no es viable.</p>
<h3>Y la factura, que es otra guerra</h3>
<p>Que los impuestos salgan bien en pantalla no significa que la factura salga bien, y esto cada día se pone más serio, más con la entrada en vigor del sistema de facturación verificable, obligatorio desde enero de 2027 para sociedades y desde julio de 2027 para autónomos.</p>
<p>No cambia nada de lo que has configurado aquí, porque afecta a cómo se genera y se conserva la factura, no a cómo se calcula el IVA. Lo tienes explicado en <a href="https://ayudawp.com/verifactu-woocommerce/" target="_blank" rel="ugc noopener">la guía de Verifactu en WooCommerce</a>.</p>
<p>Con los impuestos resueltos, <strong>lo siguiente que toca es configurar los envíos</strong>, que merecen su propia ración de rarezas y tienen guía aparte.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ayudawp.com/configurar-impuestos-woocommerce/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>SMTP en WordPress «sin plugins»</title>
		<link>https://ayudawp.com/smtp-wordpress-sin-plugins/</link>
					<comments>https://ayudawp.com/smtp-wordpress-sin-plugins/#respond</comments>
		
		<dc:creator><![CDATA[Fernando Tellado]]></dc:creator>
		<pubDate>Tue, 15 Sep 2026 06:28:05 +0000</pubDate>
				<category><![CDATA[Programación + WordPress]]></category>
		<category><![CDATA[Tutoriales - Trucos]]></category>
		<category><![CDATA[WordPress.com]]></category>
		<category><![CDATA[WordPress.org]]></category>
		<category><![CDATA[Avanzado]]></category>
		<category><![CDATA[Experto]]></category>
		<category><![CDATA[Functions]]></category>
		<category><![CDATA[SMTP]]></category>
		<category><![CDATA[wp-config.php]]></category>
		<guid isPermaLink="false">https://ayudawp.com/?p=160109</guid>

					<description><![CDATA[¿A que lo has pensado?, reconócelo, ya tengo veinte plugins, ¿en serio necesito otro plugin solo para mandar correos desde WordPress?
La respuesta es que sí se puede…]]></description>
										<content:encoded><![CDATA[<p>¿A que lo has pensado?, reconócelo, <strong>ya tengo veinte plugins, ¿en serio necesito otro plugin solo para mandar correos desde WordPress?</strong></p>
<p>La respuesta es que <strong>sí se puede</strong>, y en realidad no es tan complicado, tiene sus cosas, pero poderse se puede, y te lo explico ya mismo, pero igual la duda esté mal planteada de origen.</p>
<h2>En realidad eso de «sin plugin» no es tan así</h2>
<p>El código que configura el SMTP tiene que <em>vivir</em> en algún sitio, y solo hay tres:</p>
<ul>
<li><strong>El <code>functions.php</code> del tema</strong>, que es la peor opción de las tres, porque el día que cambies de tema tu web deja de mandar correos y nadie va a relacionar una cosa con la otra.</li>
<li><strong>Un plugin propio</strong>, que evidentemente es un plugin.</li>
<li><strong>Un mu-plugin</strong>, en <code>wp-content/mu-plugins/</code>, que también es un plugin, solo que se activa siempre y no aparece con un botón de desactivar en el escritorio.</li>
</ul>
<p>Así que <strong>lo que en realidad estás pensando es si puedes montar el SMTP sin instalar un plugin del directorio</strong>, y eso sí, con un archivo tuyo de veinte líneas.</p>
<p>Que sea un <code>mu-plugin</code> no es un tecnicismo tonto, es precisamente la ventaja, porque no se desactiva por error ni se pierde al tocar el tema.</p>
<h2>Pues no, resulta que no existe eso de configurar SMTP desde wp-config.php</h2>
<p>Meter las credenciales en <code>wp-config.php</code> está muy bien y es lo que vas a ver en el código de un poco más abajo de este artículo, pero por sí solas esas constantes no hacen absolutamente nada, porque <strong>WordPress no las lee, nunca ha tenido ajustes SMTP nativos</strong>.</p>
<p>La propuesta de añadirlos existe, es el <a href="https://core.trac.wordpress.org/ticket/29069" target="_blank" rel="nofollow noopener">ticket 29069 de Trac</a>, abierto en 2014 y cerrado como <code>wontfix</code> en 2019, con dos argumentos:</p>
<ol>
<li>WordPress va de decisiones y no de opciones, y esto es territorio de plugins.</li>
<li>Como <code>wp_mail()</code> es una función reemplazable, si un plugin la sustituye esas constantes dejarían de hacer efecto sin que nadie se enterase, lo que sería un infierno de depurar.</li>
</ol>
<p>Lo que hay que hacer, entonces, es engancharse donde el núcleo de WordPress sí lo permite.</p>
<h2>Esto sí está en WordPress: PHPMailer</h2>
<p>WordPress trae <code>PHPMailer</code> incluido, y esa librería sirve SMTP de serie. Lo único que falta es decirle cómo, y para eso hay cuatro puntos de enganche:</p>
<ul>
<li><code>phpmailer_init</code>: se dispara justo después de crear el objeto PHPMailer y te lo pasa por referencia, así que puedes configurarlo a tu gusto. Existe desde WordPress 2.2.</li>
<li><code>pre_wp_mail</code>: cortocircuita <code>wp_mail()</code> entero, de modo que puedes mandar el correo como te dé la gana y devolver si salió bien. Está desde WordPress 5.7.</li>
<li><code>wp_mail_succeeded</code>: salta cuando el envío se ha procesado sin errores y te entrega destinatario, asunto, mensaje, cabeceras y adjuntos. Desde WordPress 5.9.</li>
<li><code>wp_mail_failed</code>: te entrega el objeto de error cuando el envío falla, que es la única forma de enterarte de lo que pasó.</li>
</ul>
<p><strong>Con el primero montas el envío,  con los dos últimos te haces tu propio registro de correos</strong>, que es lo que la mayoría de plugins te cobra.</p>
<h2>SMTP en WordPress «sin plugins» en 2 pasos</h2>
<p>Empezamos con las credenciales, en <code>wp-config.php</code>, por encima de la línea que dice que dejes de añadir cosas. Ponlas ahí y no en el mu-plugin, que luego los archivos de código acaban en un repositorio o en un correo de soporte y las contraseñas viajan con ellos.</p>
<pre>define( 'AYUDAWP_SMTP_HOST', 'smtp.TUPROVEEDOR.com' );
define( 'AYUDAWP_SMTP_PORT', 587 );
define( 'AYUDAWP_SMTP_SECURE', 'tls' );
define( 'AYUDAWP_SMTP_USER', 'NOMBRE@TUDOMINIO' );
define( 'AYUDAWP_SMTP_PASS', 'PON_AQUI_TU_CLAVE' );
define( 'AYUDAWP_SMTP_FROM', 'NOMBRE@TUDOMINIO.com' );
define( 'AYUDAWP_SMTP_FROM_NAME', 'Nombre del remitente o de tu web' );</pre>
<p><strong>De dónde sale cada uno de esos valores</strong></p>
<p>Lo de <code>clave_ SMTP_</code> significa una cosa distinta según dónde tengas el correo:</p>
<ul>
<li><strong>Correo del dominio en tu propio hosting</strong>: El servidor te lo da el panel de tu alojamiento web, normalmente algo del estilo <code>mail.tudominio.com</code>, el usuario es la dirección completa del buzón y la contraseña es esa misma que pusiste al crear la cuenta de correo.</li>
<li><strong>Gmail o Google Workspace:</strong> El servidor suele ser <code>smtp.gmail.com</code>, el usuario es tu dirección completa y la contraseña es una contraseña de aplicación de Google, normalmente de dieciséis caracteres, que se generan en la sección de seguridad de tu cuenta y que necesitan la verificación en dos pasos activada. La contraseña normal de Google no vale desde hace años.</li>
<li><strong>Un servicio transaccional</strong>: del tipo Brevo, Mailgun o SMTP2GO. Cada uno tiene su pantalla de credenciales SMTP donde te genera un usuario y una clave específicos para esto, que no son los que usas para entrar en el servicio. Ahí también te dan el servidor y el puerto a utilizar.</li>
<li><strong>Microsoft 365 u Outlook</strong>: Aquí no te doy valores porque no te lo recomiendo, que la identificación básica cada vez funciona menos, y en las cuentas personales ya ni está. Esto lo explico en otro momento.</li>
</ul>
<p>Por cierto, importante, <strong>las contraseñas de aplicación de WordPress no sirven para esto</strong>, esas se utilizan para que una aplicación externa se identifique en la REST API o XML-RPC de tu web.</p>
<p>Son cosa de entrada, no de salida, y si las pegas en la constante de la contraseña el servidor de correo te va a rechazar sin contemplaciones. Si te interesa el tema lo explico en <a href="https://ayudawp.com/application-passwords/" target="_blank" rel="ugc noopener">este artículo sobre las contraseñas de aplicación de WordPress</a>.</p>
<p>Por ir terminando con los detalles, el hecho de que Google llame igual a las suyas es una coincidencia desafortunada que confunde a medio mundo, pero son dos cosas que no tienen nada que ver.</p>
<p>No me enrollo más y dicho esto <strong>ya tocaría ponernos con el mu-plugin</strong>. Creas la carpeta <code>wp-content/mu-plugins/</code> si no la tienes, y dentro un archivo llamado, por ejemplo, <code>ayudawp-smtp.php</code>:</p>
<pre>&lt;?php
/**
 * Plugin Name: SMTP para WordPress
 * Plugin URI: https://plugins.ayudawp.com
 * Description: Envía los correos de WordPress usando un servidor SMTP con identificación.
 * Version: 1.0.0
 * Author: Fernando Tellado
 * Author URI: https://tellado.es 
 * License: GPL-2.0-or-later
 */

defined( 'ABSPATH' ) || exit;

/**
 * Configure PHPMailer para usar SMTP.
 * Las credenciales van como constantes en wp-config.php, no las metas aquí.
 */
function ayudawp_smtp_config( $phpmailer ) {

	// Salida silenciosa si el sitio aún no se ha configurado
	if ( ! defined( 'AYUDAWP_SMTP_HOST' ) || ! defined( 'AYUDAWP_SMTP_PASS' ) ) {
		return;
	}

	$phpmailer-&gt;isSMTP();
	$phpmailer-&gt;Host       = AYUDAWP_SMTP_HOST;
	$phpmailer-&gt;Port       = AYUDAWP_SMTP_PORT;
	$phpmailer-&gt;SMTPAuth   = true;
	$phpmailer-&gt;SMTPSecure = AYUDAWP_SMTP_SECURE;
	$phpmailer-&gt;Username   = AYUDAWP_SMTP_USER;
	$phpmailer-&gt;Password   = AYUDAWP_SMTP_PASS;

	// 30 segundos es más que suficiente. Con el valor por defecto la solicitud se quedaría bloqueada durante varios minutos
	$phpmailer-&gt;Timeout = 30;
}
add_action( 'phpmailer_init', 'ayudawp_smtp_config' );

/**
 * La dirección del remitente debe pertenecer al dominio autorizado (coincidencia SPF/DKIM)
 */
function ayudawp_smtp_from( $from ) {
	return defined( 'AYUDAWP_SMTP_FROM' ) ? AYUDAWP_SMTP_FROM : $from;
}
add_filter( 'wp_mail_from', 'ayudawp_smtp_from' );

function ayudawp_smtp_from_name( $name ) {
	return defined( 'AYUDAWP_SMTP_FROM_NAME' ) ? AYUDAWP_SMTP_FROM_NAME : $name;
}
add_filter( 'wp_mail_from_name', 'ayudawp_smtp_from_name' );</pre>
<p>Ya está, eso es todo. En cuanto subes el archivo está activo, los mu-plugins no hace falta activarlos, y si tienes ya añadidos tus datos al <code>wp-config.php</code> como en el primer paso ya lo tienes.</p>
<h3>Valores que podrían darte algo de guerra</h3>
<p>El puerto y el cifrado se confunden constantemente porque van emparejados:</p>
<ul>
<li>El 587 va con <code>tls</code>, que arranca en claro y sube a cifrado con STARTTLS, y es el que deberías usar.</li>
<li>El 465 va con <code>ssl</code>, cifrado desde el primer byte, y sigue funcionando en todas partes.</li>
<li>El 25 no lo uses para esto, está pensado para el tráfico entre servidores y lo tiene bloqueado medio internet.</li>
</ul>
<p>Con el remitente mejor los dos filtros del ejemplo que tocar <code>$phpmailer-&gt;From</code> a pelo, porque así lo respeta cualquier otro plugin que mande correos.</p>
<p>Y si alguna vez tienes que llamar a <code>setFrom()</code>, pásale <code>false</code> como tercer parámetro para que PHPMailer no te pise la cabecera <code>Sender</code>, que hay servidores que rechazan el mensaje por eso.</p>
<h2>Todo en un archivo, si no quieres tocar wp-config.php</h2>
<p>Hay quien no quiere andar tocando <code>wp-config.php</code>, y lo entiendo, que es el archivo donde un despiste te deja la web en blanco. Así que aquí tienes la misma cosa en un solo archivo, con las credenciales dentro y un bloque de ajustes arriba que es lo único que hay que editar.</p>
<p>Eso sí, sustituye a los dos anteriores, no los mezcles, o usas los 2 pasos de antes o este archivo completo.</p>
<pre>&lt;?php
/**
 * Plugin Name: SMTP para WordPress
 * Plugin URI: https://plugins.ayudawp.com
 * Description: Envía los correos de WordPress usando un servidor SMTP con identificación.
 * Version: 1.0.0
 * Author: Fernando Tellado
 * Author URI: https://tellado.es
 * License: GPL-2.0-or-later
 */

defined( 'ABSPATH' ) || exit;

/**
 * Ajustes SMTP. Este es el único bloque que tienes que modificar
 *
 * host      Servidor de correo saliente, te lo da tu proveedor de mail
 * port      587 con 'tls', o 465 con 'ssl'
 * secure    Debe coincidir con el puerto de arriba
 * user      Normalmente la dirección de email
 * pass      La contraseña SMTP de la dirección de email
 * from      Dirección de email del remitente. Debe pertenecer al dominio autorizado
 * from_name Nombre del remitente mostrado en los correos enviados
 */
function ayudawp_smtp_settings() {

	return array(
		'host'      =&gt; 'smtp.TUPROVEEDOR.com',
		'port'      =&gt; 587,
		'secure'    =&gt; 'tls',
		'user'      =&gt; 'NOMBRE@TUDOMINIO.com',
		'pass'      =&gt; 'PON_AQUI_TU_CLAVE',
		'from'      =&gt; 'NOMBRE@TUDOMINIO.com',
		'from_name' =&gt; 'Nombre del remitente o de tu web',
	);
}

/**
 * Configura PHPMailer para que use SMTP
 */
function ayudawp_smtp_config( $phpmailer ) {

	$config = ayudawp_smtp_settings();

	// No hace nada hasta que los ajustes de arriba se hayan completado
	if ( empty( $config['host'] ) || 'PON_AQUI_TU_CLAVE' === $config['pass'] ) {
		return;
	}

	$phpmailer-&gt;isSMTP();
	$phpmailer-&gt;Host       = $config['host'];
	$phpmailer-&gt;Port       = (int) $config['port'];
	$phpmailer-&gt;SMTPAuth   = true;
	$phpmailer-&gt;SMTPSecure = $config['secure'];
	$phpmailer-&gt;Username   = $config['user'];
	$phpmailer-&gt;Password   = $config['pass'];

	// 30 segundos es más que suficiente. Con el valor por defecto la solicitud se quedaría bloqueada durante varios minutos.
	$phpmailer-&gt;Timeout = 30;
}
add_action( 'phpmailer_init', 'ayudawp_smtp_config' );

/**
 * La dirección del remitente debe pertenecer al dominio autorizado (coincidencia SPF/DKIM)
 */
function ayudawp_smtp_from( $from ) {

	$config = ayudawp_smtp_settings();

	return ! empty( $config['from'] ) ? $config['from'] : $from;
}
add_filter( 'wp_mail_from', 'ayudawp_smtp_from' );

function ayudawp_smtp_from_name( $name ) {

	$config = ayudawp_smtp_settings();

	return ! empty( $config['from_name'] ) ? $config['from_name'] : $name;
}
add_filter( 'wp_mail_from_name', 'ayudawp_smtp_from_name' );</pre>
<p>Fíjate en el condicional del principio, que no está de adorno. <strong>Mientras la clave siga siendo el texto de ejemplo, el mu-plugin no hace nada y WordPress manda como siempre</strong>, así que si subes el archivo y se te olvida rellenarlo no rompes el envío, simplemente sigue como estaba.</p>
<p>Y ahora un aviso, o recordatorio, como prefieras, y es que meter la clave aquí es más cómodo pero también menos seguro, por un motivo muy concreto.</p>
<p>Los archivos dentro de <code>mu-plugins</code> están dentro de <code>wp-content</code>, que es una carpeta pública, y <strong>el día que el servidor deje de procesar PHP por lo que sea, este archivo se sirve como texto plano con tu contraseña dentro</strong>.</p>
<p>Con <code>wp-config.php</code> puede pasar lo mismo, pero con la diferencia de que casi todos los hosting traen una regla en el servidor que bloquea ese archivo por su nombre, o incluso la puedes añadir tú usando <a href="https://ayudawp.com/tag/vigilante/" target="_blank" rel="noopener">Vigilante</a>, y para tu mu-plugin no la trae nadie.</p>
<p>Si te vas por este camino dedícale un minuto a poner esa regla tú, si no la añade tu hosting o no usas Vigilante (a quién se le ocurre). Creas un archivo llamado <code>.htaccess</code> dentro de <code>wp-content/mu-plugins/</code> con estas tres líneas:</p>
<pre>&lt;FilesMatch "\.php$"&gt;
Require all denied
&lt;/FilesMatch&gt;</pre>
<p>Con Nginx eso no vale y hay que pedírselo a tu proveedor, o mirar si su panel te deja bloquear el acceso directo a esa carpeta. Y en cualquiera de los dos casos, acuérdate de que la clave viaja en las copias de seguridad, así que si le pasas un respaldo a alguien le estás pasando también la contraseña del correo.</p>
<h2>Tu propio registro de correos, sin base de datos ni plugins de pago</h2>
<p>Esta es la parte que hace que merezca (más) la pena todo lo anterior, porque <strong>el registro de envíos es justo lo que casi todos los plugins de SMTP guardan para la versión de pago, y montarlo son unas pocas líneas más</strong>.</p>
<p>La idea es simple, enganchas <code>wp_mail_succeeded</code> y <code>wp_mail_failed</code>, y escribes una línea por envío en un archivo de texto. Nada de tablas, nada de tipos de contenido personalizados, nada que engorde la base de datos.</p>
<p>Eso sí, lo que te propongo lleva un par de decisiones de diseño que no son caprichos. Por un lado verás que <strong>el archivo empieza por una instrucción de salida de PHP para que nadie pueda leerlo desde el navegador</strong> aunque adivine la ruta, y <strong>no guardo el cuerpo de los mensajes</strong>, solo destinatario, asunto y resultado.</p>
<p>Esto lo he definido así porque un registro de correos completo es un almacén de datos personales con todo lo que eso implica en cuanto al RGPD.</p>
<pre>/**
 * Registro minimalista de registro de correos. Sin base de datos ni pantalla de ajustes
 * Escribe una línea por mensaje a un archivo protegido dentro de wp-content
 */
function ayudawp_mail_log_file() {
	return WP_CONTENT_DIR . '/ayudawp-mail-log.php';
}

/**
 * Añade una entrada al registro, rotando el archivo cuando crezca demasiado
 * Nunca se almacenan los contenidos del mensaje, solo los metadatos
 */
function ayudawp_mail_log_write( $status, $to, $subject, $detail = '' ) {

	$file = ayudawp_mail_log_file();
	// El carácter de salida impide que el archivo se pueda leer a través de HTTP
	$header = "&lt;?php exit; ?&gt;\n";

	if ( ! file_exists( $file ) ) {
		file_put_contents( $file, $header );
	}

	clearstatcache( true, $file );

	// Rota cuando llegue a los 2 MB, manteniendo solo un archivo previo
	if ( filesize( $file ) &gt; 2 * MB_IN_BYTES ) {
		rename( $file, $file . '.old' );
		file_put_contents( $file, $header );
	}

	$line = sprintf(
		"[%s] %s | para: %s | asunto: %s%s\n",
		current_time( 'mysql' ),
		$status,
		is_array( $to ) ? implode( ', ', $to ) : $to,
		$subject,
		'' !== $detail ? ' | ' . $detail : ''
	);

	file_put_contents( $file, $line, FILE_APPEND | LOCK_EX );
}

/**
 * Registra mensajes que PHPMailer procesó sin errores
 */
function ayudawp_mail_log_success( $mail_data ) {
	ayudawp_mail_log_write( 'OK  ', $mail_data['to'], $mail_data['subject'] );
}
add_action( 'wp_mail_succeeded', 'ayudawp_mail_log_success' );

/**
 * Registra juntos los fallos con el motivo que los provocó
 */
function ayudawp_mail_log_failure( $error ) {

	$data = $error-&gt;get_error_data();

	ayudawp_mail_log_write(
		'KO',
		isset( $data['to'] ) ? $data['to'] : 'desconocido',
		isset( $data['subject'] ) ? $data['subject'] : 'desconocido',
		$error-&gt;get_error_message()
	);
}
add_action( 'wp_mail_failed', 'ayudawp_mail_log_failure' );</pre>
<p>El resultado es un archivo que puedes abrir con el gestor de archivos del hosting o un cliente FTP, y que se lee de un vistazo:</p>
<pre>[2026-08-11 09:14:22] OK   | para: cliente@example.com | asunto: Tu pedido #1482
[2026-08-11 09:31:07] KO | para: otro@example.com | asunto: Restablecer contraseña | SMTP connect() failed.</pre>
<p>Un par de avisos sobre este código.</p>
<ul>
<li>El gancho de éxito significa que el mensaje salió sin errores, <strong>no significa que haya llegado a la bandeja de nadie</strong>, eso lo avisa el propio núcleo en su documentación.</li>
<li>Si algún día conviertes esto en un plugin para el directorio oficial, la escritura de archivos hay que hacerla con la API de sistema de archivos de WordPress, que aquí he ido directo para no triplicar el código de un ejemplo.</li>
</ul>
<h2>Cuando el puerto está cerrado el camino es HTTPS</h2>
<p>Bastantes hosting bloquean las conexiones salientes por los puertos de correo, y lo hacen por un buen motivo, para que una web comprometida no acabe convertida en una máquina de spam.</p>
<p>Si te toca uno de esos alojamientos entonces SMTP no es una opción y no lo va a ser por mucho que insistas.</p>
<p>La salida es mandar por la API del proveedor, que viaja por HTTPS y no la bloquea nadie. Y aquí es donde entra <code>pre_wp_mail</code>, que cortocircuita el envío entero:</p>
<pre>/**
 * Envía los correos de WordPress usando un proveedor con API HTTP en vez de SMTP
 * Devolver un valor no nulo frena wp_mail()
 */
function ayudawp_mail_via_api( $short_circuit, $atts ) {

	if ( ! defined( 'AYUDAWP_MAIL_API_KEY' ) ) {
		return $short_circuit; // Deja que WordPress lo gestione como siempre
	}

	$to = is_array( $atts['to'] ) ? $atts['to'] : array( $atts['to'] );

	$response = wp_remote_post(
		'https://api.TUPROVEEDOR.com/v1/send',
		array(
			'timeout' =&gt; 15,
			'headers' =&gt; array(
				'Authorization' =&gt; 'Bearer ' . AYUDAWP_MAIL_API_KEY,
				'Content-Type'  =&gt; 'application/json',
			),
			'body'    =&gt; wp_json_encode(
				array(
					'from'    =&gt; AYUDAWP_SMTP_FROM,
					'to'      =&gt; $to,
					'subject' =&gt; $atts['subject'],
					'html'    =&gt; $atts['message'],
				)
			),
		)
	);

	if ( is_wp_error( $response ) ) {
		ayudawp_mail_log_write( 'KO', $to, $atts['subject'], $response-&gt;get_error_message() );
		return false;
	}

	$sent = ( 200 === wp_remote_retrieve_response_code( $response ) );
	ayudawp_mail_log_write( $sent ? 'OK  ' : 'FALLO', $to, $atts['subject'] );

	return $sent;
}
add_filter( 'pre_wp_mail', 'ayudawp_mail_via_api', 10, 2 );</pre>
<p>Ese código es una base de partida, pues cada proveedor tiene su formato, así que la estructura del cuerpo la sacas de su documentación.</p>
<p>Fíjate en que aquí llamo al registro a mano, porque al cortocircuitar <code>wp_mail()</code> los ganchos de éxito y de fallo del núcleo ya no se disparan.</p>
<p>Y ojo con lo demás, <strong>si cortocircuitas <code>wp_mail()</code> te quedas tú al mando de todo</strong>, incluidos los adjuntos, las cabeceras personalizadas y el juego de caracteres, que en el ejemplo no están contemplados.</p>
<p>Para una web que solo manda avisos de texto va sobrado, para una tienda con facturas adjuntas necesitas bastante más código.</p>
<h2>¿Funciona?</h2>
<p>No te fíes de que no salte ningún error, eso no significa nada. Pide un restablecimiento de contraseña desde la pantalla de acceso con un usuario cuyo correo esté en otro proveedor, y mira la bandeja y el spam.</p>
<p>Si no llega, abre el archivo de registro, que ahí tienes el motivo. Y si quieres además el detalle en el log de PHP, activa la depuración en <code>wp-config.php</code>:</p>
<pre>define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );</pre>
<p>Los mensajes suelen ser explícitos. Si dice que la autorización ha fallado revisa usuario y contraseña. Si dice que no puede conectar o que la conexión se ha rechazado el problema es el puerto, y ahí no hay código que valga.</p>
<h2>Lo que sigues sin tener</h2>
<p>Con lo de arriba tienes envío verificado y registro de correos, que es el 80% de lo que dan los plugins, pero te falta lo siguiente:</p>
<ul>
<li><strong>El botón de prueba</strong>: que parece una tontería hasta que estás cambiando de proveedor un viernes por la tarde.</li>
<li><strong>La conexión de reserva</strong>: para que si el proveedor principal se cae entre el segundo sin que se pierda nada.</li>
<li><strong>Los reintentos y la cola</strong>: que evitan que un pico de envíos te ralentice la web.</li>
<li><strong>La pantalla de consulta</strong>: porque leer un archivo de texto por FTP no es lo mismo que filtrar en una tabla del escritorio.</li>
</ul>
<p>Y hay un caso donde directamente no compensa y es <strong>si tu correo está en Gmail o en Microsoft y quieres usar OAuth, olvídate de hacerlo a mano</strong>, porque necesitas una librería externa, gestionar tokens y renovarlos. Ahí un plugin te lo resuelve con dos clics y tú tardarías muchas horas en tener algo peor.</p>
<h2>Entonces, ¿código o plugin?</h2>
<p>Mi criterio después de bastantes webs de cliente es que si la web la mantienes tú, va por control de versiones y el correo es de dominio propio contra un servidor que controlas, el mu-plugin es perfecto y además no te añade tablas ni panel de ajustes.</p>
<p>Si la web la va a tocar otra persona, si el correo va por Gmail o Microsoft, o si es una tienda donde perder un aviso de pedido cuesta dinero, instala un plugin con registro incluido en la versión gratuita. Los tienes comparados en <a href="https://ayudawp.com/wordpress-no-manda-emails/" target="_blank" rel="ugc noopener">WordPress no manda emails, y casi nunca es culpa de WordPress</a>, que además cubre la parte de SPF, DKIM y DMARC, sin la cual todo esto sirve de poco.</p>
<p>Si le das una vuelta al código y lo mejoras, cuéntamelo en los comentarios, que estas cosas se afinan entre todos.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ayudawp.com/smtp-wordpress-sin-plugins/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Passkeys en WordPress</title>
		<link>https://ayudawp.com/passkeys/</link>
					<comments>https://ayudawp.com/passkeys/#respond</comments>
		
		<dc:creator><![CDATA[Fernando Tellado]]></dc:creator>
		<pubDate>Mon, 14 Sep 2026 06:28:16 +0000</pubDate>
				<category><![CDATA[Seguridad WordPress]]></category>
		<category><![CDATA[Tutoriales - Trucos]]></category>
		<category><![CDATA[WordPress.com]]></category>
		<category><![CDATA[WordPress.org]]></category>
		<category><![CDATA[Avanzado]]></category>
		<category><![CDATA[passkey]]></category>
		<category><![CDATA[Vigilante]]></category>
		<guid isPermaLink="false">https://ayudawp.com/?p=160117</guid>

					<description><![CDATA[Vaya, por fin un artículo que te cuenta todo sobre las passkeys, y además explicado en detalle y con una guía sencilla para usuarios de WordPress.]]></description>
										<content:encoded><![CDATA[<p>Cuando entras en una web con una <code>passkey</code>, tu navegador mete el dominio dentro de lo que firma. Eso significa que <strong>una web falsa montada en otro dominio no puede reproducir esa firma</strong> ni poniéndose en medio de la conversación, y <strong>ahí se acaba el <em>phishing</em></strong>, que llevamos veinte años intentando parchear con avisos, con formación a los usuarios y con esconder la pantalla de acceso.</p>
<p>¿Suena bien, a que sí?, porque es lo único que importa de verdad de este asunto, y porque casi todo lo demás sobre passkeys se queda en lo bonito de entrar con la huella, y <strong>lo de la huella es la parte cómoda, no la parte importante.</strong></p>
<p>Pero hay una segunda mitad de la historia que es la de verdad importante, que es la que <strong>te puede dejar fuera de tu propia web o darte una falsa sensación de seguridad</strong>. ¿Te animas?, es una historia apasionante, y de rabiosa actualidad.</p>
<h2>Qué es una passkey, y sobre todo qué no es</h2>
<p>Una passkey es <strong>un par de claves criptográficas</strong>. La privada se queda en tu dispositivo o en tu gestor de contraseñas y no sale de ahí nunca, y la pública se guarda en la web donde te identificas.</p>
<p>Cuando entras, la web te manda un desafío, tu dispositivo lo firma con la clave privada después de comprobar que eres tú (huella, cara o PIN), y la web verifica la firma con la clave pública que ya tenía.</p>
<p><strong>Lo que se guarda en tu servidor son claves públicas, o sea, información que no sirve para entrar en ningún sitio.</strong></p>
<p>Si mañana te roban la base de datos entera el atacante se lleva un puñado de claves públicas y un rato de trabajo perdido. Compara eso con lo que pasa cuando se filtra una tabla de contraseñas.</p>
<p>Y aquí viene la parte más confusa, donde a veces nos liamos, porque «<strong>acceso sin contraseña</strong>» se ha convertido en un cajón donde cabe cualquier cosa.</p>
<p>Estos son los 4 métodos de acceso sin contraseña que solemos confundir, para tenerlo claro antes de empezar:</p>
<table>
<tbody>
<tr>
<th style="text-align: left;">Método</th>
<th style="text-align: left;">Qué puede robarse</th>
<th style="text-align: left;">Si te clonan el dominio</th>
<th style="text-align: left;">De qué depende</th>
</tr>
<tr>
<td>Contraseña</td>
<td>La contraseña entera, y sirve en cualquier sitio donde la repitas</td>
<td>Caes</td>
<td>De tu memoria y de tu gestor</td>
</tr>
<tr>
<td>Enlace o código por email</td>
<td>El enlace o el código, mientras no caduque</td>
<td>Caes</td>
<td>De tu correo, entero</td>
</tr>
<tr>
<td>Código con aplicación (TOTP)</td>
<td>El código del momento, y también el secreto inicial</td>
<td>Caes, si te lo piden en la web falsa</td>
<td>De tu móvil y de tus códigos de respaldo</td>
</tr>
<tr>
<td>Passkey</td>
<td>Nada utilizable</td>
<td>No caes</td>
<td>De tu dispositivo o de tu cuenta de sincronización</td>
</tr>
</tbody>
</table>
<p>Fíjate en <strong>la columna del dominio clonado</strong>, porque es la única en la que la <code>passkey</code> juega en otra liga.</p>
<p>El código de seis dígitos de tu aplicación de autorización es un secreto compartido que tú tecleas, así que si te lo tecleas en la web del malo, se lo has dado.</p>
<p><strong>La passkey no la tecleas, la firma tu dispositivo, y tu dispositivo comprueba el dominio antes de firmar</strong>.</p>
<p>Si quieres repasar los otros dos métodos con calma, tengo escrito sobre <a href="https://ayudawp.com/2fa-wordpress/" target="_blank" rel="ugc noopener">la identificación de dos factores en WordPress</a> y sobre <a href="https://ayudawp.com/acceder-wordpress-sin-contrasena/" target="_blank" rel="ugc noopener">el acceso mediante enlace mágico</a>, que sigue teniendo sentido para lo que tiene es, para la comodidad.</p>
<h2>El phishing se acabó</h2>
<p>Ya te he dicho lo bueno, así que toca la letra pequeña, porque <strong>la passkey blinda la puerta, no toda la casa.</strong> Estas cosas te siguen pudiendo pasar exactamente igual:</p>
<ul>
<li>Que te roben la cookie de sesión una vez has entrado, con malware o con un <code>cross-site scripting</code>: La passkey se usa en el momento de identificarte, y a partir de ahí eres una sesión abierta como cualquier otra. Si sospechas que ha pasado, lo que echa a todo el mundo fuera de golpe es renovar las claves de seguridad del <code>wp-config.php</code>, tal como cuento en la guía para <a href="https://ayudawp.com/limpiar-wordpress-hackeado-infectado/" target="_blank" rel="ugc noopener">limpiar y recuperar un WordPress hackeado</a>.</li>
<li>Que tengas el equipo comprometido: Si el malo está dentro de tu ordenador, ya has perdido y da igual cómo entres.</li>
<li>Que te ataquen por el método de respaldo: Si dejas la contraseña activa, y vas a dejarla, el phishing simplemente irá a por la contraseña, que es lo que hacen los atacantes desde siempre, ir por donde menos cuesta.</li>
<li>Que te secuestren el correo y usen el «¿Has olvidado tu contraseña?», que sigue ahí, funcionando como el primer día.</li>
</ul>
<p>Nada de esto es un argumento contra las passkeys, ojo, es un argumento contra venderlas como si fueran un campo de fuerza. Sirven para lo que sirven, y lo que hacen lo hacen mejor que ninguna otra cosa que tengamos.</p>
<h2>Quién las usa ya, y quién ha ido más lejos</h2>
<p>Google, Apple y Microsoft las ofrecen por defecto en sus cuentas personales, y ahí es donde la mayoría de la gente tiene ya una passkey sin haberse dado cuenta.</p>
<p>La FIDO Alliance, que es quien está detrás del estándar, publicó en mayo su informe anual y calcula unos <strong>5.000 millones de passkeys en uso en el mundo, con un 75 % de personas que tienen al menos una activada y un 49 % que las usa habitualmente</strong> cuando la web se lo permite.</p>
<p>Un aviso de rigor sobre esas cifras es que la muestra es de diez países, y España no está entre ellos, así que sirven para ver la tendencia, no para calcular cuántos de tus clientes van a saber qué hacer cuando les salga el aviso.</p>
<p>El caso que mejor muestra hasta dónde llega esto es el de OpenAI, que ha sacado un modo de seguridad reforzada para las cuentas de ChatGPT en el que la contraseña se desactiva, hay que registrar dos credenciales entre passkeys y llaves físicas, y se elimina la recuperación por correo y por SMS.</p>
<p>La frase que hay que subrayar de su documentación es que <strong>una vez lo activas, ni siquiera su soporte puede devolverte la cuenta</strong>. No todo iba a ser bonito, las IAs, ya sabes.</p>
<p>Ahí tienes la ventaja y el peligro en la misma frase, y por eso este artículo dedica más espacio a la recuperación que al registro.</p>
<p>Y por si te queda lejos, dos ejemplos que te tocan de cerca. Tu cuenta de WordPress.org admite llaves de seguridad desde la pestaña de cuenta y seguridad de tu perfil, y WordPress.com también las admite como verificación de acceso.</p>
<p>O sea que el proyecto usa passkeys para proteger a la gente que hace WordPress, mientras que <strong>el núcleo de WordPress sigue sin traer nada de esto para tu web</strong>. Ni en la versión actual ni en las siguientes, que no mencionan <code>WebAuthn</code> por ningún lado.</p>
<h2>Los dos modelos de Passkey ¿cuál es el que nos interesa?</h2>
<p>Esto es quizás lo que más te va a seguir de todo lo que llevo escrito, así que céntrate un poquito, que te toca decidir.</p>
<h3>Passkey como sistema de acceso en dos pasos</h3>
<p>Metes usuario y contraseña como siempre, y en la pantalla siguiente, en vez del código de seis dígitos, firmas con la huella o con la llave. La contraseña sigue funcionando como red de seguridad.</p>
<p>Es el modo conservador, es el que menos soporte genera y es donde vas a acabar tú, casi seguro. Ganas el fin del phishing y te quitas de encima el baile del código de seis dígitos, que es lo que odia todo el mundo de la verificación en dos pasos.</p>
<h3>Passkey como acceso completo</h3>
<p>No hay contraseña. Pones el nombre de usuario, o ni eso, firmas y estás dentro. Es el modo que cambia de verdad el modelo de amenaza, y también el que te obliga a tener un plan de recuperación de adulto.</p>
<h3>La mezcla perfecta</h3>
<p>Y luego está esto, que es donde casi todo la mayoría nos equivocamos, incluido yo, por supuesto, cuando empecé a darle vueltas al asunto.</p>
<p>El phishing se acabó el primer día con el modo de doble verificación, pero el tener que completar credenciales no se acaba hasta que apagas la contraseña. Y esto no es porque la passkey no sea buena, sino porque mientras la contraseña siga siendo una credencial válida el atacante sigue pudiendo probar pares de usuario y contraseña contra tu web.</p>
<p>Aunque no se complete el acceso porque falta la passkey, obtiene lo que de verdad busca, que es confirmar que ese par funciona para ir luego a probarlo al correo de esa persona, o a su banco, o a los otros quince sitios donde repite contraseña.</p>
<p>Esto significa que <strong>en el modo de doble verificación en dos pasos tu web deja de ser la puerta por la que entran, pero sigue siendo quién les dice si la llave que tienen es buena o no</strong>.</p>
<p>Por eso la secuencia sensata es esta, y por eso el modo sin contraseña tiene que ir siempre acompañado de dos credenciales registradas y de códigos de respaldo guardados fuera del ordenador.</p>
<p>No es prudencia histérica, es que el día que quitas la contraseña te quedas sin alternativa.</p>
<h3>Un paso o dos, y por qué no hace falta pedir también el código</h3>
<p><strong>Una passkey que exige verificación</strong> de usuario (huella, cara o PIN antes de firmar) ya <strong>son dos pasos por sí sola</strong>: algo que tienes, que es el dispositivo o la credencial, y algo que eres o que sabes, que es lo que desbloquea la firma.</p>
<p><strong>Pedir además el código de seis dígitos es pedir dos veces lo mismo.</strong> Si la credencial no lleva verificación de usuario entonces sí es un solo factor y no debería contar como doble verificación.</p>
<p>Y ahora otro matiz que tiene consecuencias prácticas gordas.</p>
<h3>¿Passkey sincronizada o atada al dispositivo?</h3>
<p>Hay dos tipos de passkey:</p>
<ul>
<li><strong>Sincronizada</strong>: está en tu llavero de iCloud, en el gestor de Google o en el gestor que uses, y aparece sola en todos tus dispositivos.</li>
<li><strong>Atada al dispositivo</strong>: esta nace y muere en el dispositivo donde la creaste, y ese es el caso de una llave física tipo YubiKey o de Windows Hello.</li>
</ul>
<p>La diferencia es relevante por dos motivos. El primero es de seguridad, porque en una passkey sincronizada, el «algo que tienes» ya no es el móvil, es la cuenta que sincroniza. Quien te comprometa esa cuenta tiene tus passkeys en todas partes.</p>
<p>Esto tiene matices, porque las passkeys de iCloud van cifradas de extremo a extremo y sacarlas de ahí exige la cuenta más el código del dispositivo, así que el listón está bastante más alto que robar una contraseña. Pero el factor de posesión se ha desplazado del cacharro a la cuenta, y eso es un cambio de verdad.</p>
<p>El segundo motivo es de recuperación, y de ese hablamos más abajo porque cambia por completo el consejo que te tengo que dar.</p>
<p>El detalle práctico es que <strong>ni el navegador ni el sistema operativo te dicen qué tipo de passkey estás creando.</strong> La propia credencial lo declara en la ceremonia mediante dos indicadores técnicos, y esa es la única forma fiable de saberlo.</p>
<p>Fíjate hasta qué punto está la cosa revuelta, que a día de hoy, Windows Hello genera credenciales atadas al dispositivo mientras que la sincronización en Windows llega por el gestor del navegador, por encima del sistema de autorización del sistema.</p>
<p>Y hasta Chrome en Windows puede guardarte la passkey en Windows Hello aunque tú creyeras estar creando una passkey sincronizada de Google.</p>
<p>O sea que el usuario ni lo elige ni lo sabe. Guarda esta idea para el final del artículo, que lo vamos a repasar.</p>
<h2>Las puertas que la passkey no cierra en WordPress</h2>
<p>WordPress no tiene una puerta de entrada, tiene varias, y la passkey protege la pantalla de acceso, nada más. Mientras la contraseña siga siendo válida, hay dos caminos que autorizan sin pasar por esa pantalla y se saltan tu passkey del todo:</p>
<ul>
<li><strong>XML-RPC:</strong> Si lo tienes activo, acepta usuario y contraseña directamente. Es la puerta que llevan años usando para los ataques de fuerza bruta masivos, precisamente porque no pasa por el formulario.</li>
<li><strong>Las contraseñas de aplicación:</strong> Son una funcionalidad del propio WordPress, muy útil, que permite autenticarse contra la API REST con una credencial que el usuario genera desde su perfil. No pasa por la pantalla de acceso, no pasa por la doble verificación y no pasa por tu passkey.</li>
</ul>
<p>Y quedan dos caminos más que no son un fallo de nadie pero que hay que tener en la cabeza, que son el restablecimiento de contraseña por correo, que sigue siendo una vía de vuelta perfectamente válida para quien controle el buzón, y los accesos del hosting, que con el gestor de archivos o con phpMyAdmin entran sin preguntarle nada a WordPress.</p>
<p>La conclusión práctica, y perdona que sea pesado, es que <strong>el modo de verificación en dos pasos solo es tan fuerte como esos dos interruptores.</strong></p>
<p>Si activas passkeys y dejas XML-RPC abierto y las contraseñas de aplicación campando a sus anchas, has puesto una puerta blindada en una casa con la ventana del patio abierta.</p>
<p>Lo bueno es que cerrarlas es fácil, porque casi todos los plugins de seguridad decentes lo traen. <a href="https://wordpress.org/plugins/wordfence/" target="_blank" rel="nofollow noopener">Wordfence</a> tiene control de XML-RPC, y en el mío, <a href="https://es.wordpress.org/plugins/vigilante/" target="_blank" rel="nofollow noopener">Vigilante</a>, tienes el bloqueo de XML-RPC y la restricción de la API REST en tres modos, además del modo bajo ataque para cuando la cosa se pone fea.</p>
<p>Si no usas ninguno de estos plugins de seguridad, al menos comprueba que el tuyo tanga ambas cosas antes de ponerte con las passkeys, porque el orden importa.</p>
<h2>Sin plugin no hay passkeys, y no es por pereza</h2>
<p>Te lo digo claro para que no pierdas la tarde buscando: no hay forma razonable de tener passkeys en WordPress sin un plugin.</p>
<p>Hace falta JavaScript en la pantalla de acceso para lanzar la ceremonia del navegador, dos rutas nuevas en el servidor para el registro y para la firma, una tabla donde guardar las claves públicas y sus indicadores, y la verificación criptográfica de cada firma. Todo eso junto es un plugin, lo llames como lo llames y lo pongas donde lo pongas.</p>
<p>Las dos alternativas que puede que encuentres por ahí o te cuente tu IA favorita no valen.</p>
<ul>
<li>Meterlo en el <code>functions.php</code> del tema es la peor idea posible, porque el día que cambies de tema te quedas fuera de tu propia web con la ceremonia a medias.</li>
<li>Delegar la identificación en un proveedor externo te ata a un servicio de pago que se queda con tus usuarios, que es justo lo contrario de lo que buscas si has llegado hasta aquí.</li>
</ul>
<p>Lo que sí puedes exigirle a un plugin es que la verificación se haga en tu servidor, sin librerías externas ni llamadas a terceros. Eso es perfectamente posible, y es lo que separa un plugin honesto de un intermediario disfrazado de plugin.</p>
<h2>Qué plugin WordPress usar según lo que necesites</h2>
<p>No pongo versiones ni fechas a propósito, porque esto se mueve rápido y un artículo con números concretos nace caducado. Comprueba siempre el estado actual en la ficha de cada uno.</p>
<h3>Wordfence</h3>
<p>Es la opción por volumen, con varios millones de instalaciones, y ha incorporado passkeys tanto en la versión gratuita como en la de pago, para cualquier perfil de usuario y con integración de WooCommerce para las pantallas de cuenta de cliente.</p>
<p>Su propia documentación avisa de que la compatibilidad para multisitio es limitado por ahora, y más abajo te explico por qué eso no es dejadez suya.</p>
<p>Si ya usas Wordfence no busques más y quédate donde ahí. Si te lo estás planteando por las passkeys, ten en cuenta que te llevas el cortafuegos y el escáner en el mismo paquete, para bien y para mal. Te reconozco que no es santo de mi devoción, y creé Vigilante precisamente por ello, pero es de justicia reconocer sus virtudes (por pocas que sean).</p>
<h3>WP 2FA, de Melapress</h3>
<p>Trae passkeys en la versión gratuita, con lo que a mí me parece su mejor baza, que son las políticas por perfil de usuario con periodo de gracia.</p>
<p>Si tienes que sacar adelante una web con quince editores y no puedes ir uno por uno pidiéndoles por favor que se configuren el acceso, esto es lo que quieres. El asistente de configuración está bien pensado para gente que no es técnica.</p>
<h3>El plugin oficial Two Factor, y su extensión</h3>
<p><a href="https://wordpress.org/plugins/two-factor/" target="_blank" rel="nofollow noopener">Two Factor</a> es el plugin de doble factor de WordPress.org, lo mantiene gente del núcleo, tiene cien mil instalaciones y es una maravilla para TOTP, correo y códigos de respaldo.</p>
<p><strong>Pero no trae passkeys</strong>, es más, la compatibilidad con las llaves de seguridad antiguas la ha quitado porque los navegadores dejaron de admitir aquel estándar, así que ahora mismo va menos servido que antes en ese apartado.</p>
<p>Para tener passkeys necesitas instalar además <a href="https://wordpress.org/plugins/two-factor-provider-webauthn/" target="_blank" rel="nofollow noopener">el complemento WebAuthn</a>, que es de un desarrollador externo, tiene mil instalaciones y exige una versión de PHP más alta que la que pide el propio WordPress. Funciona bien, que conste, y quien lo mantiene sabe lo que hace.</p>
<p>Pero que la solución oficial para passkeys en WordPress sea «instálate estos dos y cruza los dedos» dice bastante de por dónde va la prioridad del proyecto en este asunto. La propuesta de código para meter WebAuthn dentro del plugin oficial lleva años abierta.</p>
<p>Mi consejo es que si ya tienes Two Factor montado y funcionando, añadir el complemento es el camino menos lioso, pero si empiezas de cero hay opciones más completas y mejor resueltas.</p>
<h3>Secure Passkeys y WP-WebAuthn</h3>
<p>Los dos son plugins dedicados solo a esto, sin cortafuegos ni escáner ni nada más, y ahí está su gracia.</p>
<p>Secure Passkeys tiene el autorrelleno, que es el detalle que de verdad hace que la experiencia sea buena, porque la passkey te aparece sola al pinchar en el campo de usuario sin tener que darle a ningún botón.</p>
<p>WP-WebAuthn permite el acceso sin escribir siquiera el nombre de usuario, aunque su soporte para multisitio sigue estando en pruebas y necesita extensiones de PHP que no todos los alojamientos compartidos traen puestas.</p>
<p>Si tu web ya tiene una suite de seguridad, no metas un segundo plugin que toque el acceso.</p>
<h3>Vigilante (próximamente)</h3>
<p>Y ahora el mío, con el aviso por delante para que nadie se lleve un chasco, porque <strong>Vigilante (aún) no ofrece passkeys.</strong></p>
<p>Ofrece verificación en dos pasos con aplicación de autenticación y con códigos por correo, con dispositivos de confianza y con obligación por perfil de usuario, así que si lo instalas ahora mismo buscando passkeys te vas a quedar con las ganas. Están apuntadas en la lista de tareas, eso sí.</p>
<p>Te cuento lo que va a llevar, y sobre todo por qué, porque el criterio te sirve para juzgar a los otros cuatro aunque al final acabes con cualquiera de ellos:</p>
<ul>
<li><strong>En dos tiempos:</strong> Primero la passkey como segundo factor, aprovechando entero el andamiaje del doble factor que ya está montado (pantalla intermedia, gestión en el perfil, dispositivos de confianza, perfiles obligados y periodo de gracia). Después el acceso sin contraseña, que es donde está todo lo caro y lo delicado.</li>
<li><strong>Una passkey con verificación de usuario cuenta como doble factor, y no se pide el código encima:</strong> Si la credencial no lleva verificación de usuario, entonces no cuenta y sigue haciendo falta el segundo paso.</li>
<li><strong>Aviso en la propia pantalla al activar el método:</strong> Te dirá si tienes XML-RPC o las contraseñas de aplicación abiertos, que es exactamente el agujero del que hemos hablado más arriba. De poco sirve que el plugin traiga los interruptores si no te avisa de que los tienes en la posición equivocada justo cuando importa.</li>
<li><strong>Cada credencial, etiquetada como sincronizada o atada al dispositivo</strong> en la lista del perfil: Esa información viene ya en la propia ceremonia, así que enseñarla no cuesta nada y te deja decidir a ti en lugar de decidir por ti.</li>
<li><strong>La contraseña sigue activa por defecto</strong>, y el modo solo passkey es opcional: Exigiendo tener dos credenciales registradas y reutiliza los códigos de respaldo que ya conoces. El administrador único no se queda fuera, por diseño.</li>
<li><strong>Nada de servicios externos ni de cuentas de terceros:</strong> La firma se verifica en tu propio servidor, sin librerías externas ni llamadas a nadie, y lo que se guarda en tu base de datos son claves públicas.</li>
</ul>
<p>Esto último no es un adorno, y por eso lo pongo aquí y no en la ficha del plugin. Tu verás, yo solo te aviso, si un plugin de passkeys te pide crear una cuenta en algún sitio, lo que te está vendiendo no es una passkey, es un intermediario.</p>
<h2>Qué necesita tu web para poder usar passkeys</h2>
<p>Seguro que cumples, pero esta es la lista, para que no te lleves decepciones.</p>
<ul>
<li><strong>HTTPS, obligatorio:</strong> Y no es una recomendación mía, es que el navegador no ejecuta la ceremonia en una web sin certificado. La única excepción es <code>localhost</code>, para que los que desarrollamos podamos hacer pruebas.</li>
<li><strong>Un dominio estable:</strong> Las credenciales se atan al dominio, así que el día que cambies de dominio todas las passkeys registradas dejan de valer y todo el mundo tiene que registrarlas otra vez. Si tienes una migración de dominio a medio plazo, haz la migración primero y las passkeys después.</li>
<li><strong>Extensiones de PHP, según el plugin:</strong> Algunos piden extensiones concretas para la parte criptográfica, y en alojamiento compartido de gama baja no siempre están activadas. Si el plugin te da error al registrar la primera credencial, mira eso antes de volverte loco.</li>
<li><strong>Multisitio, el punto flojo:</strong> Como la credencial se ata al dominio, en una red de subdominios una passkey registrada en una web de la red no sirve en las demás. La forma de arreglarlo pasa por atar la identidad de la red al dominio padre en lugar de al de cada web, y hay plugins que ya lo hacen usando la constante <code>COOKIE_DOMAIN</code> si la tienes definida. En una red de subdirectorios el problema no existe porque el dominio es el mismo para todas. Si administras multisitio, prueba esto en un clon antes de tocar la red buena.</li>
</ul>
<p><strong>Los entornos de pruebas se comportan distinto</strong>, porque el dominio es otro. Las passkeys que registres en el clon no te valen en producción, y al revés tampoco.</p>
<h2>Cómo añadir passkeys en WordPress de manera segura y paso a paso</h2>
<p>El orden de estos pasos no es decorativo, cada uno depende del anterior:</p>
<ol>
<li>Cierra XML-RPC y revisa las contraseñas de aplicación existentes antes de tocar nada del acceso. Si no haces esto lo demás no sirve de nada.</li>
<li>Empieza por ti y por el resto de administradores, nunca por los usuarios. Y hazlo un día laborable por la mañana, no un viernes a las ocho de la tarde.</li>
<li>Registra dos credenciales por persona desde el primer momento, no una. La segunda es la que te salva.</li>
<li>Genera los códigos de respaldo y guárdalos fuera del ordenador, en el gestor de contraseñas o en papel dentro de un cajón, que sigue siendo un sitio estupendo.</li>
<li>Prueba la recuperación de verdad, con una cuenta de prueba a la que le quites el acceso a propósito. Un plan de recuperación sin probar no es un plan, es una intención.</li>
<li>Solo entonces amplía al resto del equipo, con periodo de gracia si tu plugin lo permite.</li>
<li>Y el modo sin contraseña, al final del todo, cuando lleves semanas con lo anterior rodado y sepas que todo el mundo tiene sus dos credenciales.</li>
</ol>
<p>Sobre las políticas más estrictas, tipo obligar a los administradores a usar solo credenciales atadas al dispositivo, mi consejo es que no lo hagas salvo que sepas muy bien lo que estás montando.</p>
<p>El coste de esa política no es igual para todos: quien administre desde Windows la cumple gratis con Windows Hello, y quien administre desde un Mac o un iPhone se ve obligado a comprar una llave física.</p>
<p><strong>Un mismo requisito que trata distinto a dos personas del mismo equipo es un generador de tickets de soporte, no una medida de seguridad.</strong> Y como decíamos antes, una política que depende de algo que la persona no elige conscientemente genera soporte, no seguridad.</p>
<p>Añade que todo esto depende del comportamiento del autenticador del sistema operativo, que puede cambiar con una actualización que ni has pedido ni controlas. Atar tu política de acceso a eso es construir sobre arena.</p>
<h2>¿Y si algo sale mal?</h2>
<p>Y aquí es donde el tipo de passkey que tenga cada uno lo cambia todo. Hay dos planes de recuperación distintos, no uno.</p>
<ul>
<li><strong>Si la passkey es sincronizada</strong>, la pérdida del móvil no es una catástrofe, porque la credencial sigue en el llavero de tu cuenta y aparecerá sola en el aparato nuevo en cuanto inicies sesión. Tu riesgo real no es perder el trasto, es perder el acceso a la cuenta que sincroniza. O sea que lo que hay que proteger con uñas y dientes es esa cuenta, no el teléfono.</li>
<li><strong>Si la passkey está atada al dispositivo</strong>, y hablo de llaves físicas o de Windows Hello, el día que se rompe el portátil o se pierde la llave esa credencial ha muerto y no vuelve. Por eso lo de registrar dos, y por eso lo de que la segunda esté en otro trasto distinto y no en el mismo.</li>
</ul>
<p>Los tres escenarios que te puedes encontrar:</p>
<ul>
<li><strong>Cambio de ecosistema</strong>, del iPhone al Android o al revés: Las passkeys sincronizadas no cruzan de un llavero a otro con la alegría que a uno le gustaría, así que planifica el cambio antes de venderte el móvil viejo.</li>
<li><strong>El editor que se marcha:</strong> Sus passkeys viven en sus dispositivos, así que tú no puedes borrárselas del bolsillo. Lo que sí puedes es eliminar las credenciales registradas desde el perfil de usuario en tu web, que es lo que corta el acceso de verdad. Ponlo en tu proceso de baja de personal, junto a lo de siempre.</li>
<li><strong>El administrador único:</strong> Si eres el único administrador de tu web, no actives nunca el modo sin contraseña sin tener dos credenciales y los códigos de respaldo comprobados. Y si aun así te quedas fuera, siempre queda desactivar el plugin renombrando su carpeta desde el gestor de archivos de tu hosting, que es la salida de emergencia de toda la vida.</li>
</ul>
<h2>Preguntas rápidas</h2>
<ul>
<li><strong>¿Las passkeys sustituyen al doble factor?</strong> Si llevan verificación de usuario, sí, porque ya son dos pasos por sí solas. No hace falta pedir además el código de la aplicación.</li>
<li><strong>¿Puedo usar passkeys y seguir teniendo contraseña?</strong> Sí, y es lo normal y lo recomendable mientras te acostumbras. Ten claro que así el relleno de credenciales contra tu web sigue siendo posible.</li>
<li><strong>¿Funcionan en el móvil?</strong> Sí, y de hecho es donde mejor van, porque la huella o la cara están ahí mismo.</li>
<li><strong>¿Y si mis usuarios no tienen lector de huella?</strong> Sirve el PIN del dispositivo, y sirve una llave física por USB. Nadie se queda fuera por no tener biometría.</li>
<li><strong>¿Sirven para los clientes de mi tienda?</strong> Sí, hay plugins que las llevan a las pantallas de cuenta de WooCommerce. Piensa antes en el coste de soporte, porque tus clientes no son tu equipo y la mitad no sabe qué es un llavero de iCloud.</li>
<li><strong>¿Y si tengo la web en un alojamiento compartido normalito?</strong> Casi seguro que funciona. Comprueba que tienes HTTPS y mira los requisitos de extensiones del plugin que elijas.</li>
<li><strong>¿Puedo obligar a que todos los administradores usen passkeys?</strong> Sí, los plugins con políticas por perfil lo permiten. Da un periodo de gracia y avisa antes, que si no te llueven los correos.</li>
</ul>
<h2>Por dónde empezar desde ya</h2>
<p>Antes de tocar tu web, haz el ensayo con red entrando en tu perfil de <a href="https://make.wordpress.org/meta/handbook/tutorials-guides/configuring-two-factor-authentication/" target="_blank" rel="nofollow noopener">WordPress.org</a>, ahí ve a la pestaña de cuenta y seguridad, y registra una llave de seguridad. Se tarda medio minuto, es gratis y vas a entender en la práctica todo lo que te he contado aquí mucho mejor que leyéndolo otra vez.</p>
<p>Después, y ya en tu web, el primer paso no es instalar nada, es ir a comprobar si tienes XML-RPC abierto y qué contraseñas de aplicación hay creadas por ahí. Eso es lo que decide si tus passkeys van a servir para algo o van a ser un adorno caro.</p>
<p>Y si te has quedado con ganas de más sobre cómo se defiende el acceso a tu WordPress, tengo el <a href="https://ayudawp.com/fuerza-bruta/" target="_blank" rel="ugc noopener">plan de batalla contra los ataques de fuerza bruta</a>, que es la capa de debajo de todo esto.</p>
<p>Ahora te toca a ti decidir en qué modo te quedas, si en el cómodo o en el valiente. Y si te lanzas al segundo, cuéntamelo en los comentarios, que me interesa mucho saber cuánta gente se atreve a apagar la contraseña de verdad.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ayudawp.com/passkeys/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>