Если квиз в WordPress должен не просто показывать вопросы, а сразу выдавать результат, удобнее считать итог на сервере через REST API. Это полезно, когда логика результата сложнее пары условий в JavaScript: есть баллы, ветвления, разные наборы ответов или нужно не светить формулу в браузере.
Типичный сценарий выглядит так: пользователь отвечает на вопросы, фронтенд отправляет выбранные варианты в WordPress, сервер проверяет данные и возвращает готовый результат. Такой подход проще поддерживать, чем размазывать логику по шаблону темы и нескольким скриптам.
Когда REST API для квиза действительно нужен
Не каждый квиз требует API. Если у вас один экран с тремя кнопками и статичным текстом, достаточно обычной формы. REST API нужен, когда результат зависит от нескольких шагов и его надо считать одинаково для всех пользователей, независимо от браузера и кеша.
Сценарии, где это оправдано
- квиз с подсчетом баллов по ответам;
- ветвящийся тест, где следующий вопрос зависит от предыдущего;
- подбор услуги, тарифа или типа контента по набору признаков;
- сохранение результата в CRM или в записи WordPress;
- нужно обновлять результат без перезагрузки страницы.
Если квиз должен работать быстро и без лишней нагрузки, REST API обычно лучше, чем отправка формы на отдельную страницу с обработчиком. Но это не значит, что API всегда обязателен: для простых сценариев он добавляет лишний слой.
Диагностика проблемы: почему результат не считается или считается неправильно
Перед переделкой логики проверьте, где именно ломается цепочка. В WordPress чаще всего проблема не в самом REST API, а в данных, которые в него уходят, или в том, как фронтенд читает ответ.
Что проверить в первую очередь
- отправляются ли ответы в нужном формате;
- не режет ли кеш JSON-ответ;
- не блокирует ли запрос nonce или права доступа;
- совпадает ли структура данных на фронтенде и в PHP;
- не дублируется ли логика расчета в двух местах.
Для диагностики удобно открыть DevTools и посмотреть вкладку Network. Если запрос уходит, но приходит 400 или 403, проблема обычно в валидации, nonce или маршруте. Если приходит 200, но результат пустой, значит сервер вернул не тот формат или фронтенд ожидает другой ключ в JSON.
Пошаговое решение: свой REST endpoint для расчета результата
Ниже рабочая схема: регистрируем маршрут, принимаем массив ответов, считаем баллы и возвращаем JSON. Код можно положить в мини-плагин или в functions.php, но для живого проекта лучше отдельный плагин, чтобы не потерять логику при смене темы.
1. Регистрируем маршрут
<?php
add_action('rest_api_init', function () {
register_rest_route('quiz/v1', '/result', array(
'methods' => 'POST',
'callback' => 'wpquiz_get_result',
'permission_callback' => '__return_true',
));
});
function wpquiz_get_result( WP_REST_Request $request ) {
$answers = $request->get_param('answers');
if ( ! is_array($answers) ) {
return new WP_REST_Response(array(
'success' => false,
'message' => 'Некорректный формат ответов.',
), 400);
}
$score = 0;
foreach ( $answers as $answer ) {
$score += isset($answer['points']) ? (int) $answer['points'] : 0;
}
if ( $score >= 8 ) {
$result = array(
'title' => 'Продвинутый вариант',
'text' => 'Подходит для сложных сценариев и нескольких этапов.',
);
} elseif ( $score >= 4 ) {
$result = array(
'title' => 'Базовый вариант',
'text' => 'Хороший старт без лишней настройки.',
);
} else {
$result = array(
'title' => 'Минимальный вариант',
'text' => 'Подойдет, если нужен простой и быстрый запуск.',
);
}
return new WP_REST_Response(array(
'success' => true,
'score' => $score,
'result' => $result,
), 200);
}
Здесь намеренно используется permission_callback с открытым доступом, потому что квиз обычно должен работать для гостей. Если вы сохраняете персональные данные или пишете результат в админку, доступ нужно ограничить и добавить проверку nonce.
2. Отправляем ответы с фронтенда
На стороне JavaScript достаточно собрать ответы и отправить их через fetch. Важно не тащить в запрос лишние поля: чем проще структура, тем меньше шансов сломать совместимость.
<script>
async function sendQuizResult(answers) {
const response = await fetch('/wp-json/quiz/v1/result', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ answers })
});
const data = await response.json();
if (!response.ok || !data.success) {
throw new Error(data.message || 'Ошибка расчета результата');
}
return data;
}
const answers = [
{ id: 1, points: 2 },
{ id: 2, points: 3 },
{ id: 3, points: 4 }
];
sendQuizResult(answers)
.then((data) => {
console.log(data.result.title);
console.log(data.result.text);
})
.catch((error) => {
console.error(error.message);
});
</script>Если квиз встроен в страницу через плагин, лучше не хардкодить URL в скрипте. Передавайте его через wp_localize_script() или wp_add_inline_script(), чтобы не ловить проблемы на поддоменах, в тестовой копии и при смене структуры ссылок.
3. Передаем URL и nonce безопасно
Когда запрос должен быть защищен, nonce лучше передавать вместе с данными. Это не делает API «секретным», но защищает от случайных и автоматических запросов из чужого контекста.
<?php
add_action('wp_enqueue_scripts', function () {
wp_enqueue_script(
'wpquiz-script',
get_stylesheet_directory_uri() . '/assets/js/quiz.js',
array(),
'1.0.0',
true
);
wp_localize_script('wpquiz-script', 'wpQuizData', array(
'restUrl' => esc_url_raw( rest_url('quiz/v1/result') ),
'nonce' => wp_create_nonce('wp_rest'),
));
});
На фронтенде nonce добавляется в заголовок X-WP-Nonce. Если вы не используете авторизованные действия, можно обойтись без него, но тогда endpoint должен принимать только безопасные данные и ничего не менять в базе.
Как не сломать кеш и индексацию
У квизов часто возникает странная ситуация: страница открывается, но результат ведет себя непредсказуемо из-за кеша. Сам HTML может быть закеширован, а вот REST-запрос должен оставаться динамическим. Это нормальная схема, если кеш настроен аккуратно.
Что важно учесть
- не кешировать сам JSON-ответ на уровне CDN без необходимости;
- не вставлять в результат данные, завязанные на сессию, если они не нужны;
- не хранить в HTML уже готовый итог, если он зависит от ответов пользователя;
- не забывать закрывать страницы квиза от индексации, если они технические и не несут самостоятельной ценности.
Если вы используете плагины для технической чистки сайта, вроде Clearfy Pro, проверьте, не включены ли одновременно несколько механизмов, которые меняют поведение архивов, мета-тегов и скриптов. Иногда проблема не в REST API, а в том, что оптимизация задела нужный JS.
Проверка результата после внедрения
После настройки не ограничивайтесь визуальной проверкой в браузере. Нужно убедиться, что endpoint отвечает стабильно и возвращает ожидаемую структуру.
Чек-лист проверки
- открывается ли
/wp-json/quiz/v1/resultбез 404; - возвращает ли запрос
200при корректных данных; - возвращает ли API
400на мусорный payload; - совпадает ли итоговый балл с ручным расчетом;
- не ломается ли страница при отключенном JavaScript;
- не появляется ли лишний запрос в консоли с ошибкой CORS или nonce.
Для быстрой проверки можно отправить запрос через curl или Postman. Это помогает отделить проблему WordPress от ошибки фронтенда.
curl -X POST https://example.com/wp-json/quiz/v1/result \
-H 'Content-Type: application/json' \
-d '{"answers":[{"id":1,"points":2},{"id":2,"points":3}]}'Если ответ приходит корректный, а в интерфейсе квиза по-прежнему пусто, значит ошибка уже в JavaScript: не тот ключ в JSON, не тот селектор для вывода или не обработан промис.
Частые ошибки и как их исправить
Маршрут есть, но WordPress отдает 404
Обычно это значит, что код не загружен, маршрут зарегистрирован слишком поздно или в ссылке ошибка. Проверьте, что rest_api_init действительно срабатывает, а endpoint совпадает с тем, что отправляет фронтенд.
Ответ приходит, но результат всегда один и тот же
Частая причина — в запросе массив ответов приходит не как массив, а как строка. Тогда цикл по данным не работает как ожидается. Сначала посмотрите реальный payload в Network, потом уже правьте PHP.
Падает безопасность из-за открытого endpoint
Если квиз только считает баллы и не пишет ничего в базу, открытый доступ допустим. Но если endpoint создает запись, отправляет email или сохраняет лид, добавьте nonce, проверку прав и валидацию каждого поля через sanitize_text_field(), absint() или sanitize_email() по типу данных.
Фронтенд и сервер считают по-разному
Это происходит, когда часть логики осталась в JavaScript, а часть перенесли в PHP. Лучше оставить один источник истины: либо весь расчет на сервере, либо весь расчет на клиенте, но не смешивать без необходимости.
Плагин, код или гибрид: что выбрать для квиза
Если задача типовая, плагин квизов экономит время. Если логика нестандартная, свой endpoint дает больше контроля. На практике часто выигрывает гибрид: интерфейс и шаги делает плагин, а расчет результата — ваш код.
| Подход | Когда подходит | Компромисс |
|---|---|---|
| Плагин квизов | Быстрый запуск, стандартные сценарии | Меньше контроля над логикой и форматом ответа |
| Свой REST endpoint | Сложный расчет, интеграции, кастомные правила | Нужно поддерживать код и тестировать API |
| Гибрид | Нужен удобный интерфейс и своя логика результата | Больше точек интеграции, но проще масштабировать |
Если вы уже используете плагин квизов и хотите добавить более гибкую логику, посмотрите на Quizle. В таких сценариях удобно оставить визуальную часть плагину, а серверный расчет вынести в отдельный обработчик.
Практические советы по производительности
REST API сам по себе не делает сайт медленным. Проблемы начинаются, когда каждый шаг квиза тянет тяжелые запросы к базе или грузит лишние скрипты. Если результат можно посчитать из уже переданных ответов, не ходите в базу на каждом клике.
- не делайте отдельный запрос на каждый вопрос, если можно отправить ответы одним пакетом;
- не подключайте на страницу квиза тяжелые библиотеки без необходимости;
- не храните в ответе большие HTML-куски, если достаточно короткого текста и ID;
- проверяйте, не дублируется ли один и тот же скрипт в теме и в плагине.
Для отладки полезно временно включить логирование в WP_DEBUG_LOG и посмотреть, что реально приходит в обработчик. Это быстрее, чем гадать по поведению интерфейса.
Если вам нужен квиз как часть контентной механики, а не только как форма сбора лидов, можно сочетать его с блоками экспертного контента или подсказками в интерфейсе. Но сначала стоит добиться стабильного расчета результата и только потом усложнять сценарий.