Desactivar la búsqueda de WordPress sin plugin con functions.php

El código completo para desactivar la búsqueda de WordPress sin plugin: devolver un 404 en las URL ?s=, quitar el formulario, el widget y el bloque de búsqueda, cerrar el punto de acceso REST y la variante .htaccess.

Cómo desactivar el buscador de WordPress: código o plugin
Respuesta rápida

Añade en el archivo functions.php de tu tema un filtro sobre parse_query que convierta cualquier consulta de búsqueda en un 404, un filtro get_search_form que devuelva una cadena vacía, y quita el widget y el bloque de búsqueda. El código completo, probado en WordPress 7.1, está en el artículo; no hace falta ningún plugin.

Una web de presentación de cinco páginas, un sitio de una sola página, un portfolio: la búsqueda de WordPress no sirve de nada y su formulario estorba en el tema. Peor aún, la página de resultados existe incluso sin formulario, en la dirección /?s=mot, y muestra una página vacía o una lista de contenidos que no querías destacar. Así se desactiva por completo la búsqueda de WordPress, sin plugin, con un fragmento para functions.php.

Por qué desactivar la búsqueda

  • No sirve de nada en un sitio pequeño: todo se alcanza desde el menú con un clic.
  • Genera páginas de resultados sin valor, que los robots pueden pedir con cualquier palabra, lo que malgasta recursos del servidor y crea URL basura.
  • El formulario que impone el tema a menudo no encaja en el diseño.

El código completo para functions.php

Colócalo en el archivo functions.php de tu tema hijo (o en un pequeño plugin propio, para que sobreviva a los cambios de tema). Cada bloque cierra una puerta distinta.

functions.php
<?php
/**
 * Desactiva la búsqueda de WordPress en la parte pública.
 */

// 1. Cualquier búsqueda por URL (/?s=mot o /search/mot/) se convierte en una página 404.
add_action( 'parse_query', function ( WP_Query $query ) {
    if ( is_admin() || ! $query->is_main_query() || ! $query->is_search() ) {
        return;
    }
    $query->is_search = false;
    $query->set_404();
    status_header( 404 );
    nocache_headers();
} );

// 2. El formulario de búsqueda del tema deja de mostrarse.
add_filter( 'get_search_form', '__return_empty_string' );

// 3. Se retira el widget de búsqueda clásico.
add_action( 'widgets_init', function () {
    unregister_widget( 'WP_Widget_Search' );
}, 11 );

// 4. El bloque «Buscar» del editor desaparece del menú de inserción.
add_filter( 'allowed_block_types_all', function ( $allowed ) {
    if ( ! is_array( $allowed ) ) {
        $registry = WP_Block_Type_Registry::get_instance();
        $allowed  = array_keys( $registry->get_all_registered() );
    }
    return array_values( array_diff( $allowed, [ 'core/search' ] ) );
} );

// 5. Se cierra el punto de acceso REST de búsqueda.
add_filter( 'rest_endpoints', function ( array $endpoints ) {
    unset( $endpoints['/wp/v2/search'], $endpoints['/wp/v2/search/(?P<id>[\d]+)'] );
    return $endpoints;
} );

Lo que hace cada bloque:

  1. La consulta. En parse_query, si la consulta principal es una búsqueda en la parte pública, se convierte en un 404 con set_404() y el código HTTP correspondiente. is_admin() deja intacta la búsqueda de la administración; is_main_query() evita tocar las consultas secundarias de los plugins.
  2. El formulario. get_search_form() es la función que llaman los temas para mostrar el formulario; el filtro hace que devuelva una cadena vacía.
  3. El widget de los temas clásicos.
  4. El bloque de los temas basados en bloques. El filtro recibe o bien true (todos los bloques permitidos), o bien una lista: en el primer caso se reconstruye la lista completa antes de quitar de ella core/search.
  5. La API REST. /wp-json/wp/v2/search?search=mot devuelve ahora un error rest_no_route en lugar de una lista de resultados.

Comprobar

Bastan tres peticiones, en un navegador o con curl:

bash
curl -s -o /dev/null -w "%{http_code}\n" "https://exemple.fr/?s=test"
# 404

curl -s "https://exemple.fr/wp-json/wp/v2/search?search=test" | head -c 120
# {"code":"rest_no_route","message":"No se ha encontrado ninguna ruta que coincida con la URL y el método de la solicitud."…

curl -s "https://exemple.fr/" | grep -c 'role="search"'
# 0: ya no hay formulario en la página (si el tema pasa por get_search_form)

En la administración, la búsqueda de entradas, de páginas y de medios debe seguir funcionando.

Si el tema muestra su propio formulario

Algunos temas escriben el formulario directamente en sus plantillas (header.php, searchform.php) sin pasar por get_search_form(). El filtro entonces no tiene ningún efecto sobre lo que se ve. Dos opciones: sobrescribir esa plantilla en un tema hijo, u ocultar el formulario con CSS mientras tanto:

css
.search-form,
form[role="search"] {
  display: none;
}

El CSS solo oculta: el bloqueo de /?s= por el primer bloque de PHP sigue siendo imprescindible.

Variante: redirigir ?s= en .htaccess

Si prefieres no servir un 404 y llevar al usuario a la portada, una regla de Apache lo hace antes incluso de que WordPress se ejecute. Está limitada a la raíz del sitio para no tocar la búsqueda de la administración (wp-admin/edit.php?s=…).

.htaccess
# Colocar antes del bloque # BEGIN WordPress
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)s= [NC]
RewriteRule ^$ /? [R=301,L]

El ? final vacía la cadena de consulta de la redirección. Esta regla y el código PHP no se excluyen: la primera le ahorra al servidor ejecutar WordPress y el segundo sigue siendo la protección de referencia, también para los enlaces permanentes /search/mot/.

Existe y hace lo mismo. En Gekkode, la línea editorial es no añadir un plugin para lo que un tema resuelve en treinta líneas: una dependencia menos que actualizar y un comportamiento que lees en tu propio código. Si administras varios sitios sin tema hijo, el plugin sigue siendo una opción razonable.

En la misma línea, limitar el acceso al escritorio de WordPress y migrar un sitio WordPress son otras dos operaciones que se hacen sin plugin.

Errores frecuentes

Bloquear también la búsqueda de la administración Una comprobación is_search() sin is_admin() rompe la búsqueda en las listas de entradas y de medios del escritorio. El código del artículo excluye la administración.
Quitar el formulario y olvidar la URL El formulario solo es una puerta: /?s=mot sigue estando al alcance de cualquiera que escriba la URL. Quien cierra la puerta es el filtro sobre parse_query, no la retirada del formulario.
Una redirección .htaccess en todo el sitio Una regla sobre s= sin restricción de ruta redirige también wp-admin/edit.php?s=…. Limita la regla a la raíz del sitio.
Un tema que muestra su propio formulario Si el tema no usa get_search_form(), el filtro no lo quita. Hay que modificar entonces la plantilla del tema (mejor la del hijo).

WordPress

Damien Flandrin Desarrollador web desde 2010, creador de Gekkode y de Email Impact. Cada artículo se prueba en un proyecto real antes de publicarse. Contacto
Newsletter

Las nuevas pruebas, tutoriales y proyectos, por correo.

Pruebas reproducibles, código versionado, resultados fechados. Nunca spam.