В современных проектах на 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 — задача, решаемая собственным кодом с минимальными зависимостями. Такой подход позволяет полностью контролировать логику, дизайн и производительность. Используйте приведённые примеры как основу и расширяйте под конкретные нужды проекта.