Стандартный поиск WordPress ищет по всему: записям, страницам, товарам. Для магазина это неудобно: покупатель вводит «кроссовки», а первой строкой получает статью из блога «Как выбрать кроссовки для бега». Есть два способа привести поиск в порядок, и выбор между ними зависит от того, есть ли на сайте что-то кроме товаров.
Способ 1: ограничить весь поиск товарами
Если сайт — это магазин и только магазин, проще всего сказать WordPress, что в поиске участвуют лишь товары. Код добавляется в functions.php дочерней темы:
// Поиск по сайту ищет только товары
add_action( 'pre_get_posts', 'shop_search_products_only' );
function shop_search_products_only( $query ) {
if ( is_admin() || ! $query->is_main_query() || ! $query->is_search() ) {
return;
}
$query->set( 'post_type', 'product' );
}
Хук pre_get_posts срабатывает перед тем, как WordPress выполнит запрос к базе, и позволяет его изменить. Мы проверяем три условия и, если это поисковый запрос с фронтенда, подменяем тип записей на product.
Две детали, без которых код будет ломать сайт
В похожих сниппетах в интернете часто встречаются две ошибки, которые стоит знать.
Нет проверки is_main_query(). Хук pre_get_posts вызывается для каждого запроса на странице — не только для основного, но и для запросов виджетов, блоков «похожие товары», меню. Без этой проверки код вмешивался во все запросы, у которых стоит флаг поиска, и мог ломать сторонние блоки. Проверка на главный запрос — обязательная привычка при работе с этим хуком.
pre_get_posts подключён через add_filter с return $query. Это экшен, а не фильтр: объект запроса передаётся по ссылке и меняется на месте, возвращать его не нужно. Ошибки от этого не возникало — WordPress не различает механику фильтров и экшенов, — но код вводил в заблуждение.
Цена этого способа
Ограничение глобальное: после него на сайте вообще нельзя найти запись блога или страницу через поиск. Для чистого магазина это нормально. Но если у вас есть блог с полезными статьями, вы только что спрятали его от посетителей — и от той части трафика, которая приходит именно за советами, а не за покупкой.
Способ 2: отдельная форма поиска по товарам
Более аккуратный вариант — не трогать общий поиск, а дать магазину собственную форму, которая ищет только товары. Секрет в одном скрытом поле: если в поисковый запрос передаётся post_type=product, WordPress сам ограничит выдачу товарами, без всякого кода в functions.php.
<form role="search" method="get" action="<?php echo esc_url( home_url( '/' ) ); ?>">
<input type="search" name="s" placeholder="Поиск товаров" value="<?php echo get_search_query(); ?>">
<input type="hidden" name="post_type" value="product">
<button type="submit">Найти</button>
</form>
Такую форму можно поставить в шапку магазина, а обычный поиск оставить в блоге. Покупатель, набирающий запрос в магазине, получает товары; читатель блога — статьи. Никто никому не мешает.
Совсем без кода
Ровно эту форму WooCommerce предоставляет из коробки. В классических темах это виджет «Поиск товаров» (Product Search), в блочных — блок с тем же названием. Он делает то же самое: добавляет скрытое поле post_type=product. Если вам не нужно менять разметку формы, кода писать не придётся вообще — просто поставьте виджет или блок вместо стандартного поиска.
Что ещё стоит подкрутить
Поиск по артикулу. Стандартный поиск WordPress ищет по заголовку и тексту, но не по артикулу товара. Если покупатели ищут по SKU, понадобится дополнительный код или плагин — стандартными средствами это не решается.
Скрытые товары. Товары со статусом видимости «Скрыто» и товары не в наличии (если такая настройка включена) WooCommerce из поиска убирает сам, дополнительно ничего делать не нужно.
Количество результатов. В тот же обработчик pre_get_posts можно добавить $query->set( 'posts_per_page', 24 );, чтобы выдача поиска не отличалась от каталога по числу товаров на странице.
Коротко
Для чистого магазина — способ 1: пять строк с pre_get_posts, обязательно с проверкой is_main_query(). Для магазина с блогом — способ 2: отдельная форма с post_type=product или готовый виджет «Поиск товаров», а общий поиск остаётся для статей. Глобальное ограничение выглядит проще, но прячет от посетителей всё, что не товар, — решайте по составу сайта, а не по длине кода.
Частые вопросы
Хук срабатывает для каждого запроса на странице, включая виджеты и блоки «похожие товары». Без проверки код меняет все запросы с флагом поиска и может ломать сторонние блоки.
Не ограничивать поиск глобально, а сделать отдельную форму со скрытым полем post_type=product — или поставить готовый виджет/блок «Поиск товаров» от WooCommerce, который делает то же самое.
Нет. Стандартный поиск WordPress ищет по заголовку и тексту, но не по SKU. Для поиска по артикулу нужен дополнительный код или плагин.
Да. pre_get_posts действует на уровне запроса и не зависит от типа темы, а для отдельной формы в блочной теме есть блок «Поиск товаров» от WooCommerce.
Источники
- 1.pre_get_posts — WordPress Developer Referencehttps://developer.wordpress.org/reference/hooks/pre_get_posts/
- 2.WooCommerce Widgets — документация WooCommercehttps://woocommerce.com/document/woocommerce-widgets/



