wpquiz.ru wordpress WPQuiz.ru

Как сделать результат квиза через REST API в WordPress

Если квиз в 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 и посмотреть, что реально приходит в обработчик. Это быстрее, чем гадать по поведению интерфейса.

Если вам нужен квиз как часть контентной механики, а не только как форма сбора лидов, можно сочетать его с блоками экспертного контента или подсказками в интерфейсе. Но сначала стоит добиться стабильного расчета результата и только потом усложнять сценарий.

×
Прокачай свой сайт WordPress!

WordPress

-20% на премиум темы и плагины

Создай сайт своей мечты ⋙