FacetWP: полное руководство по фильтрам для WordPress — установка, листинги, мобильная версия

Полная практическая инструкция по FacetWP: от установки плагина до мобильных фильтров, индексации и диагностики. Годится как регламент для сотрудников на любом проекте.

Александр Лаврищев
Хотите сайт с воронкой продаж на WordPress?
Напишите мне в личку — обсудим вашу задачу.
Написать мне ВКонтакте

Для кого: для владельца проекта и для сотрудников, которые будут ставить фильтры на новых сайтах. Что даёт: после прочтения человек с нуля ставит рабочие фильтры (каталог товаров, курсов, статей, объектов) на любом WordPress-сайте, включая мобильную версию, и понимает, почему фильтры иногда «слетают» и как это лечить.

Версия материала: FacetWP 4.5, WordPress 6.8, проверено на живом проекте (каталог курсов Tutor LMS).

1. Что такое FacetWP и когда он нужен

FacetWP — плагин фильтрации контента для WordPress. Он не «ищет» по сайту, а пересобирает уже существующий список записей по выбранным условиям: рубрика, метка, цена, произвольное поле, дата, автор, наличие.

Он нужен, когда:

  • есть каталог (товары, курсы, объекты, вакансии, статьи) от 30 позиций;
  • нужно фильтровать без перезагрузки страницы;
  • нужны счётчики («Вебинары (52)») и понятная пагинация.

Он не нужен, когда:

  • список короткий и достаточно рубрик;
  • нужен полнотекстовый поиск по всему сайту (это задача поискового плагина, хотя у FacetWP есть фасет типа Search для поиска внутри листинга).

Главное преимущество: FacetWP работает через свой индекс в базе, поэтому фильтрация быстрая даже на нескольких тысячах записей.

2. Ключевые понятия

Запомнить три слова — дальше всё логично.

Фасет (Facet) — один фильтр. Например «Рубрики», «Цена», «Город», «Поиск». Каждый фасет имеет свой шорткод: .

Листинг (Listing) — сам список карточек, который фильтруется. Создаётся в конструкторе FacetWP и выводится шорткодом . Вместо листинга можно использовать существующий цикл темы, но это сложнее и ломается при обновлениях темы — на новых проектах всегда делайте листинг в конструкторе FacetWP.

Индекс (Index) — таблица wp_facetwp_index, куда плагин заранее складывает все значения всех фасетов для всех записей. Если индекс пустой или устарел — фильтры показывают ноль результатов или неверные счётчики. 90% проблем с FacetWP — это проблемы индекса.

Логика работы: пользователь щёлкает фасет → JS отправляет AJAX-запрос → FacetWP берёт из индекса ID подходящих записей → подставляет их в запрос листинга → возвращает готовый HTML карточек и новые счётчики.

3. Установка и лицензия

  1. Купить лицензию на facetwp.com (плагин платный, бесплатной версии нет).
  2. Скачать zip в личном кабинете, поставить: Плагины → Добавить новый → Загрузить плагин, активировать.
  3. Ввести ключ: Настройки → FacetWP → Settings → License.
  4. Дополнения (Add-ons) устанавливаются отдельными zip-файлами с того же кабинета. Полезные: — Flyout — выезжающая панель фильтров для мобильной версии (обязательно берите); — Conditional Logic — показывать фасет только при определённом выборе; — Range List — готовые диапазоны цен; — Map Facet — фильтр по карте.

Важно про лицензию: если ключ не активен, уже установленные дополнения продолжают работать, но обновления и поддержка недоступны. Не оставляйте проект на просроченной лицензии дольше, чем нужно — при обновлении WordPress несовместимость придётся лечить руками.

4. Шаг 1. Создаём листинг

FacetWP → Listings (Листинги) → Add new.

  1. Name — техническое имя, латиницей: courses, products, articles. Оно попадёт в шорткод.
  2. Переключатель режима: Visual (визуальный конструктор) или Dev/Advanced (PHP-шаблон). Всегда начинайте с Visual. PHP-режим берите только если карточку невозможно собрать блоками.
  3. Query — что выводим: — Post type — тип записей (post, product, courses, свой CPT); — Statuspublish; — Posts per page — сколько карточек на страницу (например 24 или 42); — Order by — сортировка (post_date DESC, menu_order ASC, meta_value_num); — дополнительные фильтры (только определённая рубрика, только с картинкой и т.д.).
  4. Layout — собираем карточку. Структура: строка (row) → колонки (col) → элементы (item). Типовая карточка каталога: — Featured image — размер medium_large, включить Link to post, CSS-класс card-thumb; — Post title — включить Link to post, класс card-title; — Post excerpt — ограничение по числу слов, класс card-desc; — при необходимости Custom field (cf/price) с префиксом/суффиксом («от », « ₽»); — кнопка: элемент Post title с текстом-заменой или элемент типа Button со ссылкой на запись.
  5. Настройки строки (row settings) — здесь живёт сетка: — Number of grid columns — количество колонок (3 для каталога курсов/товаров); — Grid gap — отступ между карточками (например 24px).
  6. Сохранить.

Проверка: на этом этапе листинг уже можно вывести шорткодом и увидеть карточки без фильтров.

5. Шаг 2. Создаём фасеты

FacetWP → Facets → Add new. Для каждого фильтра — свой фасет.

Общие поля: Label (что видит пользователь), Name (латиницей, попадёт в шорткод), Facet type (тип), Data source (откуда брать значения).

Основные типы и когда их брать

ТипЧто делаетГде применять
Checkboxesгалочки, множественный выборрубрики, метки, бренды
Radioодин вариант«кому подходит», статус
Dropdownсписокгорода, категории с длинным списком
Searchпоиск внутри листингастрока «Поиск по каталогу»
Slider / Number rangeдиапазонцена, площадь, длительность
Date rangeпериодсобытия, архив
Pagerпагинациявсегда в каталоге
Sortсмена сортировки«сначала новые / дешевле»
Resetсброс всех фильтроввсегда
Hierarchyвложенные рубрикибольшие каталоги

Важные настройки фасета

  • Data sourceTaxonomies / Категории, Custom fields / cf/price, Posts / post_title. Для ACF-поля выбирайте его в списке cf/имя_поля.
  • Behavior (AND / OR) — как складываются галочки внутри одного фасета. OR — «или то, или то» (обычно нужен для рубрик), AND — «и то, и то» (для характеристик).
  • Show counts — показывать число результатов у каждого варианта. Включайте: это резко повышает удобство.
  • Hide when empty — скрывать варианты, по которым ничего не найдено.
  • Soft limit — показать 5–8 значений и ссылку «Показать все».
  • Ghosts — показывать недоступные варианты серым (обычно выключено).
  • Sort by — порядок значений: по количеству, по алфавиту, по порядку в таксономии.

Пример реального набора для каталога обучающих продуктов:

  • course_search — Search, «Поиск по программам»;
  • course_category — Checkboxes по рубрикам, OR, счётчики включены;
  • course_tag — Checkboxes по метке «кому подходит», OR;
  • course_pager — Pager, режим Numbers, по 12 страниц в блоке;
  • course_reset — Reset, текст «Сбросить фильтры».

6. Шаг 3. Выводим всё на страницу

Создайте страницу каталога (например «Программы») и вставьте шорткоды.

[facetwp facet="course_search"]

[facetwp facet="course_category"]
[facetwp facet="course_tag"]
[facetwp facet="course_reset"]

[facetwp template="courses"]

[facetwp facet="course_pager"]

Правила, которые нарушают чаще всего:

  1. Шорткод листинга обязателен на странице. Без фасеты «не знают», что фильтровать, и молча ничего не делают.
  2. Один листинг на страницу. Два листинга FacetWP на одной странице конфликтуют.
  3. Фасеты можно ставить и до, и после листинга — порядок в вёрстке не важен для логики.
  4. Для горизонтальной панели фильтров сверху просто оберните фасеты в блок-колонки темы; отдельный сайдбар не нужен.

Если нужно фильтровать существующий цикл темы

Тогда в листинге выбирается режим Dev и в шаблоне темы у WP_Query добавляется:

$args['facetwp'] = true;

а сам цикл оборачивается в <div class="facetwp-template">. Это рабочий, но хрупкий путь: при обновлении темы или плагина каталога разметка меняется и фильтры перестают находить список. Именно так фильтры «слетают» на многих проектах. Штатный листинг FacetWP от таких обновлений не зависит — используйте его.

7. Шаг 4. Индекс

Настройки → FacetWP → Indexer → Re-index.

Как он работает:

  • индекс пересобирается автоматически при сохранении записи;
  • полная переиндексация запускается вручную кнопкой или через WP-CLI: wp facetwp index;
  • прогресс виден в панели; на больших каталогах процесс идёт частями.

Когда переиндексация обязательна:

  • после создания или изменения фасета;
  • после массового импорта записей;
  • после смены источника данных (Data source);
  • после переноса сайта на другой домен/сервер.

Полезные настройки индекса:

  • Enable indexer — должно быть включено;
  • Index all post statuses — обычно выключено (индексируем только published);
  • увеличить Indexer chunk size, если процесс падает по таймауту на shared-хостинге.

Признаки сломанного индекса: фасеты показывают «(0)» у всех значений, фильтр даёт пустой результат, счётчики не совпадают с реальностью. Лечение: Re-index, затем сброс кэша.

Страховка для больших проектов — ежедневная задача по расписанию, которая проверяет, что индекс не пустой, и при необходимости запускает переиндексацию.

8. Сетка карточек: три колонки штатно

Не пишите CSS для сетки. Это делается настройкой:

  1. FacetWP → Listings → ваш листинг;
  2. режим Visual;
  3. настройки строки: Number of grid columns = 3, Grid gap = 24.

По умолчанию конструктор добавляет один брейкпоинт: при ширине экрана 480px и меньше сетка становится одноколоночной. Если нужны промежуточные шаги (2 колонки на планшете) — только тогда добавляется CSS:

@media (max-width: 1024px) and (min-width: 481px) {
  .facetwp-template .fwpl-row { grid-template-columns: repeat(2, 1fr); }
}

Почему именно так: если сетка собрана вручную в CSS темы или в сниппете, любое отключение этого сниппета (или переезд на другую тему) ломает вид каталога, и никто потом не может найти причину. Настройка внутри листинга переживает и обновления темы, и чистку сниппетов.

Ограничение описания по строкам

Единственный уместный CSS для карточки — обрезка описания, чтобы карточки были одной высоты:

.card-desc {
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

Класс card-desc задаётся элементу в конструкторе (поле CSS class).

9. Мобильная версия

Три штатных варианта — по возрастанию удобства.

Вариант A. Просто скрыть часть фасетов

В CSS скрываете на мобильных второстепенные фасеты. Быстро, но пользователь теряет фильтры. Не рекомендуется.

Вариант B. Своя кнопка «Фильтры» со сворачиванием

Обёртка фасетов получает класс, кнопка переключает его:

<button class="filters-toggle" aria-expanded="false">Фильтры <span class="filters-count"></span></button>
<div class="filters-panel">
  [facetwp facet="course_category"]
  [facetwp facet="course_tag"]
</div>
@media (max-width: 780px) {
  .filters-panel { display: none; }
  .filters-panel.is-open { display: block; }
}
@media (min-width: 781px) { .filters-toggle { display: none; } }

Счётчик выбранных фильтров берётся из состояния FacetWP:

document.addEventListener('facetwp-loaded', function () {
  var n = 0;
  Object.values(FWP.facets || {}).forEach(function (v) { if (v && v.length) n += v.length; });
  document.querySelector('.filters-count').textContent = n ? '(' + n + ')' : '';
});

Вариант C (рекомендуемый). Дополнение Flyout

Официальное дополнение FacetWP: фильтры уезжают в выезжающую панель, на странице остаётся одна кнопка.

  1. Установить и активировать плагин FacetWP – Flyout.
  2. Настроить: Настройки → FacetWP → Flyout — какие фасеты попадают в панель, ширина, позиция (слева/справа), точка включения по ширине экрана.
  3. Кнопку открытия можно вывести своей вёрсткой, добавив класс facetwp-flyout-open:
<button class="facetwp-flyout-open" aria-haspopup="dialog">Фильтры</button>

Тонкая настройка через хуки (в дочерней теме или сниппете):

// какие фасеты показывать внутри выезжающей панели
add_filter('facetwp/flyout/facets', function ($facets) {
    unset($facets['course_search']); // поиск оставляем на самой странице
    return $facets;
});

Практические рекомендации:

  • поиск не прячьте в панель — он нужен сразу;
  • внутрь панели добавьте кнопку сброса;
  • на десктопе кнопку «Фильтры» скрывайте, панель фильтров показывайте обычным блоком.

10. Кнопка «Сбросить фильтры»

Два способа.

Штатный фасет Reset — создать фасет типа Reset и вывести шорткодом. Работает всегда, ничего программировать не нужно.

Своя кнопка — обязательно через API FacetWP, а не «очисткой URL»:

document.addEventListener('click', function (e) {
  if (!e.target.closest('.my-reset')) return;
  e.preventDefault();
  FWP.reset();            // снимает выбор и перезагружает листинг
});

Частая ошибка: обработчик кнопки живёт в сниппете/скрипте, который потом отключают, — кнопка остаётся на странице, но перестаёт работать. Держите обработчик там же, где вёрстка кнопки, или используйте штатный фасет Reset.

11. Нестандартные типы записей

Свой CPT (курсы, объекты, вакансии)

В листинге в Post type выберите свой тип. Если типа нет в списке — он зарегистрирован с public => false или exclude_from_search => true; поправьте регистрацию типа.

WooCommerce

  • Post type: product;
  • фасеты по атрибутам: Data source → Taxonomies → pa_размер и т.п.;
  • цена: фасет Slider, Data source → cf/_price;
  • наличие: фасет Checkboxes по cf/_stock_status;
  • в настройках FacetWP включите WooCommerce support.

ACF

Поля доступны как cf/имя_поля. Для repeater и flexible content индексируются вложенные ключи — при необходимости используйте хук facetwp_index_row для нормализации значений.

LMS-плагины (Tutor LMS, LearnDash)

Здесь чаще всего и возникают «слетающие фильтры»: плагин курса выводит свой цикл и свою разметку. Правильное решение — не цепляться к циклу плагина, а собрать свой листинг FacetWP по типу записей курсов. Тогда обновление LMS-плагина на фильтры не влияет.

12. Кэш, CDN и почему фильтры «слетают»

FacetWP работает через AJAX, а значит конфликтует с агрессивным кэшем и оптимизаторами.

Обязательные меры:

  1. Не кэшировать AJAX-запросы FacetWP. В кэш-плагине исключите /?fwp и админский AJAX.
  2. Не объединять и не откладывать скрипты FacetWP. В оптимизаторах (Autoptimize, LiteSpeed, WP Rocket, Perfmatters) добавьте facetwp в исключения для combine/defer/delay JS. Симптом нарушения: в консоли браузера Invalid or unexpected token, фильтры визуально есть, но не работают.
  3. Ассеты грузить всегда на странице каталога. Если тема подключает скрипты условно, добавьте:
add_filter('facetwp_load_assets', function ($load) {
    if (is_page('programs')) $load = true;
    return $load;
});
  1. Сбрасывать кэш после правок каталога и фасетов. Иначе пользователь видит старую разметку с новым JS — и ничего не работает.
  2. Осторожно с CDN-оптимизацией HTML (Cloudflare Rocket Loader, Mirage): Rocket Loader ломает FacetWP, отключайте.

Чек-лист «фильтры перестали работать после обновления»:

  • листинг в режиме Dev и зацепился за разметку темы/плагина → перевести на визуальный листинг;
  • оптимизатор снова включил объединение JS → вернуть исключение;
  • индекс пустой → Re-index;
  • сетка/кнопки жили в отключённом сниппете → перенести настройку в листинг FacetWP.

13. Диагностика: 10 проверок по порядку

  1. На странице есть шорткод листинга ? Один, а не два?
  2. Фасеты выведены правильными именами (Name, не Label)?
  3. Настройки → FacetWP → Indexer: индекс не пустой? Дата последней индексации свежая?
  4. Консоль браузера: есть ошибки JS? Invalid or unexpected token = оптимизатор портит скрипт.
  5. Вкладка Network: при клике по фильтру уходит запрос admin-ajax.php?action=facetwp_refresh и возвращает 200 с JSON?
  6. В ответе JSON есть template с карточками и settings со счётчиками?
  7. Число карточек меняется при фильтрации? Если нет — листинг не связан с запросом (режим Dev, разметка сломана).
  8. Кэш сброшен? Проверьте в приватном окне.
  9. Плагины кэша/оптимизации отключены на время теста — стало работать? Значит дело в исключениях.
  10. Мобильная версия: панель Flyout активна, кнопка открытия имеет класс facetwp-flyout-open?

Полезные хуки для отладки:

// посмотреть итоговый запрос
add_action('facetwp_query_args', function ($args) { error_log(print_r($args, true)); return $args; });

14. Чего делать нельзя

  • Нельзя строить сетку карточек и логику фильтров в CSS темы или в случайных сниппетах: при чистке проекта это исчезает, и никто не найдёт причину.
  • Нельзя дублировать листинги: два листинга на странице = неработающие фильтры.
  • Нельзя привязываться к разметке чужого плагина/темы, если можно собрать свой листинг.
  • Нельзя оставлять кастомный JS, который дублирует штатное поведение (сброс, поиск, пагинация) — используйте фасеты Reset, Search, Pager.
  • Нельзя править файлы плагина FacetWP: всё настраивается через фасеты, листинг и хуки.

15. Порядок внедрения на новом проекте

Печатный чек-лист для сотрудника.

  1. Поставить плагин, активировать лицензию.
  2. Поставить дополнение Flyout (для мобильных фильтров).
  3. Создать листинг: имя латиницей, режим Visual, тип записей, сортировка, число на странице.
  4. Собрать карточку: обложка со ссылкой, заголовок со ссылкой, описание, при необходимости цена/кнопка.
  5. В настройках строки задать Number of grid columns и Grid gap.
  6. Создать фасеты: Search, рубрики (Checkboxes, OR, счётчики), доп. признак, Pager, Reset.
  7. Создать страницу каталога и вставить шорткоды фасетов и листинга.
  8. Запустить полную переиндексацию.
  9. Настроить Flyout: какие фасеты в панели, ширина, точка включения; кнопка с классом facetwp-flyout-open.
  10. Добавить исключения в кэш и оптимизатор JS (facetwp, /?fwp), при необходимости facetwp_load_assets.
  11. Добавить CSS только на обрезку описания и оформление кнопок-фильтров.
  12. Проверить: десктоп (фильтр, поиск, сброс, пагинация), мобильный (панель, фильтр, сброс), приватное окно после сброса кэша, консоль без ошибок.
  13. Зафиксировать в документации проекта: имя листинга, имена фасетов, где лежит CSS, какие исключения добавлены в кэш.

Приложение. Шпаргалка по шорткодам и хукам

[facetwp facet="имя_фасета"]       вывод фильтра
[facetwp template="имя_листинга"]  вывод списка карточек
[facetwp counts]                   «Показано 1–12 из 99»
[facetwp selections]               плашки выбранных фильтров
[facetwp sort="имя_фасета"]        сортировка
facetwp_load_assets        // принудительно грузить скрипты
facetwp_query_args         // изменить запрос листинга
facetwp_index_row          // изменить значение при индексации
facetwp_facet_display_value// изменить подпись значения
facetwp/flyout/facets      // состав выезжающей панели
facetwp/flyout/open        // добавить своё содержимое в панель
FWP.facets                 // текущее состояние фильтров
FWP.refresh()              // перезагрузить результаты
FWP.reset()                // сбросить все фильтры
document.addEventListener('facetwp-loaded', fn)  // после каждой загрузки
wp facetwp index           # полная переиндексация из консоли
Александр Лаврищев
Хотите сайт с воронкой продаж на WordPress?
Напишите мне в личку — обсудим вашу задачу.
Написать мне ВКонтакте

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *