Как создать эффективный фильтрованный список в WordPress с AJAX

В современных проектах на WordPress часто возникает задача реализовать удобный и быстрый фильтрованный список записей или товаров. Пользователи хотят видеть результаты обновленными без перезагрузки страницы — и тут на помощь приходит AJAX. В этой статье подробно разберём, как создать фильтрованный список с динамическим обновлением на AJAX, используя собственный код и лучшие практики WordPress.

Почему AJAX-фильтрация важна для UX и SEO

Традиционная фильтрация с перезагрузкой страницы не всегда удобна — она замедляет работу, особенно при большом объёме данных. AJAX позволяет подгружать результаты асинхронно, делая интерфейс отзывчивым и современным. При этом важно сохранять SEO-дружественность — чтобы поисковики индексировали отдельные варианты фильтрации.

Для решения этой задачи на WordPress можно использовать либо плагины, либо собственную реализацию на AJAX и WP_Query. Ниже пример именно самостоятельной реализации с поддержкой истории браузера и SEO.

Подготовка: регистрация AJAX-обработчиков и скриптов

Начнём с регистрации AJAX-обработчика, который будет получать параметры фильтра и возвращать HTML с отфильтрованными записями.

add_action('wp_enqueue_scripts', 'wpmax_enqueue_filter_scripts');
function wpmax_enqueue_filter_scripts() {
    wp_enqueue_script('wpmax-filter-js', get_template_directory_uri() . '/js/wpmax-filter.js', ['jquery'], null, true);
    wp_localize_script('wpmax-filter-js', 'wpmaxFilter', [
        'ajaxurl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('wpmax_filter_nonce')
    ]);
}

add_action('wp_ajax_wpmax_filter_posts', 'wpmax_filter_posts_callback');
add_action('wp_ajax_nopriv_wpmax_filter_posts', 'wpmax_filter_posts_callback');

function wpmax_filter_posts_callback() {
    check_ajax_referer('wpmax_filter_nonce', 'nonce');

    $args = [
        'post_type' => 'post',
        'posts_per_page' => 10,
    ];

    // Получаем фильтры из запроса
    if (!empty($_POST['category'])) {
        $args['category_name'] = sanitize_text_field($_POST['category']);
    }

    if (!empty($_POST['search'])) {
        $args['s'] = sanitize_text_field($_POST['search']);
    }

    $query = new WP_Query($args);

    if ($query->have_posts()) {
        ob_start();
        while ($query->have_posts()) {
            $query->the_post();
            ?>
            <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
                <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
                <div><?php the_excerpt(); ?></div>
            </article>
            <?php
        }
        wp_reset_postdata();
        $content = ob_get_clean();
        wp_send_json_success(['html' => $content]);
    } else {
        wp_send_json_success(['html' => '<p>Ничего не найдено по вашему запросу.</p>']);
    }
    wp_die();
}

В этом коде мы подключаем JS-скрипт, который будет отправлять AJAX-запросы, и создаём серверный обработчик, который возвращает HTML с отфильтрованными записями.

JavaScript для отправки AJAX-запросов и обновления списка

Создайте файл js/wpmax-filter.js в теме и добавьте туда следующий код:

jQuery(document).ready(function($) {
    function wpmaxSendFilter() {
        var category = $('#wpmax-filter-category').val();
        var search = $('#wpmax-filter-search').val();

        $.ajax({
            url: wpmaxFilter.ajaxurl,
            type: 'POST',
            data: {
                action: 'wpmax_filter_posts',
                nonce: wpmaxFilter.nonce,
                category: category,
                search: search
            },
            beforeSend: function() {
                $('#wpmax-filter-results').html('<p>Загрузка...</p>');
            },
            success: function(response) {
                if (response.success) {
                    $('#wpmax-filter-results').html(response.data.html);
                    history.pushState(null, null, '?category=' + category + '&search=' + encodeURIComponent(search));
                }
            }
        });
    }

    $('#wpmax-filter-category, #wpmax-filter-search').on('change keyup', function() {
        wpmaxSendFilter();
    });

    // При загрузке страницы, если есть параметры в URL, применяем фильтр
    var params = new URLSearchParams(window.location.search);
    if(params.has('category')) {
        $('#wpmax-filter-category').val(params.get('category'));
    }
    if(params.has('search')) {
        $('#wpmax-filter-search').val(params.get('search'));
    }
    if(params.has('category') || params.has('search')) {
        wpmaxSendFilter();
    }

    // Обработка кнопки назад/вперед браузера
    window.onpopstate = function() {
        var params = new URLSearchParams(window.location.search);
        $('#wpmax-filter-category').val(params.get('category') || '');
        $('#wpmax-filter-search').val(params.get('search') || '');
        wpmaxSendFilter();
    };
});

Этот скрипт отслеживает изменения в полях фильтра, отправляет AJAX-запрос и обновляет контент. Также реализована поддержка истории браузера — при изменении фильтров меняется URL, и при навигации назад/вперёд состояние фильтра восстанавливается.

HTML-разметка для фильтра

Вставьте на нужную страницу следующий HTML-код:

<div id="wpmax-filter-controls">
    <select id="wpmax-filter-category" name="category">
        <option value="">Все категории</option>
        <?php
        $categories = get_categories();
        foreach ($categories as $cat) {
            echo '<option value="' . esc_attr($cat->slug) . '">' . esc_html($cat->name) . '</option>';
        }
        ?>
    </select>

    <input type="text" id="wpmax-filter-search" name="search" placeholder="Поиск по заголовкам" />
</div>

<div id="wpmax-filter-results">
    <!-- Здесь будут выводиться записи -->
</div>

Этот блок можно стилизовать под дизайн сайта. Он содержит выпадающий список категорий и поле поиска, которые влияют на результаты.

Расширение фильтрации: по метаданным и таксономиям

Для более сложных фильтров можно использовать кастомные таксономии и метаполя. В AJAX-обработчике достаточно добавить параметры в WP_Query:

// Фильтр по метаполю 'price'
if (!empty($_POST['price_min']) && !empty($_POST['price_max'])) {
    $args['meta_query'][] = [
        'key' => 'price',
        'value' => [intval($_POST['price_min']), intval($_POST['price_max'])],
        'type' => 'NUMERIC',
        'compare' => 'BETWEEN'
    ];
}

// Фильтр по таксономии 'product_tag'
if (!empty($_POST['tag'])) {
    $args['tax_query'][] = [
        'taxonomy' => 'product_tag',
        'field' => 'slug',
        'terms' => sanitize_text_field($_POST['tag'])
    ];
}

Соответственно, в фронтенде добавьте нужные поля и передавайте их в AJAX.

Плагины для расширенной AJAX-фильтрации

Если вы предпочитаете готовые решения, можно рассмотреть:

  • Clearfy Pro — в том числе включает оптимизации и улучшения для AJAX и фильтров.
  • WPRemark — расширенные фильтры и сортировка с AJAX для комментариев и записей.

Однако собственная реализация даёт больше гибкости и контроля.

Советы по производительности и SEO

При реализации AJAX-фильтров стоит учитывать:

  • Кэширование результатов — например, с помощью Transients API, чтобы не нагружать БД.
  • Оптимизация запросов — избегайте избыточных JOIN и используйте индексы.
  • Обновление URL и поддержка истории браузера для SEO и удобства пользователей.
  • Добавление микроразметки и правильно формируемые заголовки для улучшения индексации.

Эти советы помогут сделать фильтры быстрыми и полезными.

Итог

Создание эффективного фильтрованного списка на AJAX в WordPress — задача, решаемая собственным кодом с минимальными зависимостями. Такой подход позволяет полностью контролировать логику, дизайн и производительность. Используйте приведённые примеры как основу и расширяйте под конкретные нужды проекта.

WooCommerce: как исключить товар из поиска и каталога без удаления
28.05.2026
Как создать автоматический отчет о проблемах безопасности WordPress
21.03.2026
Как использовать хуки в WordPress для автоматизации задач
07.11.2025
WooCommerce: как настроить правила разграничения доступа к страницам и категориям товаров
05.06.2026
WooCommerce: как отключить автоматическое обновление статуса заказов
30.04.2026