Задать вопрос директору
Telegram
VK
Звонок

Квиз подбора товара для интернет-магазина

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

Живое демо — блок работает прямо здесь

Код блока

<section class="vbkpt2">
  <div class="vbkpt2-wrap">
    <div class="vbkpt2-head">
      <h2 class="vbkpt2-h2">Подберём позицию за четыре вопроса</h2>
      <p class="vbkpt2-lead">Спросим, кому нужна посуда, для какой задачи и на какую сумму рассчитываете. В конце покажем позицию из каталога с ценой и обоснованием.</p>
    </div>

    <div class="vbkpt2-box">
      <div class="vbkpt2-bar" aria-hidden="true"><i id="vbkpt2-fill"></i></div>
      <div class="vbkpt2-dots" id="vbkpt2-dots"></div>
      <div class="vbkpt2-stage" id="vbkpt2-stage" aria-live="polite"></div>
      <div class="vbkpt2-foot">
        <button type="button" class="vbkpt2-back" id="vbkpt2-back" hidden>Вернуться к прошлому вопросу</button>
        <span class="vbkpt2-step" id="vbkpt2-step"></span>
      </div>
    </div>
  </div>
</section>

<style>
.vbkpt2, .vbkpt2 *, .vbkpt2 *::before, .vbkpt2 *::after { box-sizing: border-box; }
.vbkpt2 {
  --acc: #9c2b45; --acc-dark: #7d2036; --ink: #1e1c1b; --muted: #6b6561; --line: #e4e0dc; --soft: #f7f5f2;
  --f: var(--t-text-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif);
  --fh: var(--t-headline-font, var(--f));
  background: var(--soft); color: var(--ink); font-family: var(--f); padding: clamp(36px, 5vw, 84px) 20px;
}
.vbkpt2-wrap { max-width: 900px; margin: 0 auto; padding: 0 clamp(0px, 2vw, 38px); }
.vbkpt2-head { margin-bottom: clamp(20px, 2.6vw, 30px); }
.vbkpt2-h2 { font-family: var(--fh); font-size: clamp(25px, 3.2vw, 38px); line-height: 1.12; font-weight: 700;
  letter-spacing: -.02em; margin: 0 0 12px; }
.vbkpt2-lead { font-size: 16px; line-height: 1.62; color: var(--muted); margin: 0; max-width: 44em; }

.vbkpt2-box { background: #fff; border: 1px solid var(--line); border-radius: 24px; padding: clamp(22px, 3vw, 40px); }
.vbkpt2-bar { height: 3px; border-radius: 3px; background: var(--line); overflow: hidden; }
.vbkpt2-bar i { display: block; height: 100%; width: 0; border-radius: 3px; background: var(--acc);
  transition: width .4s cubic-bezier(.22,1,.36,1); }
.vbkpt2-dots { display: flex; gap: 7px; margin: 14px 0 24px; }
.vbkpt2-dot { font-size: 11.5px; letter-spacing: .04em; color: #a8a29c; }
.vbkpt2-dot--on { color: var(--acc); font-weight: 600; }

.vbkpt2-q { font-family: var(--fh); font-size: clamp(19px, 2.1vw, 25px); line-height: 1.28; font-weight: 600; margin: 0 0 20px; }
.vbkpt2-opts { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px; }
.vbkpt2-opt { display: block; width: 100%; border: 1.5px solid var(--line); margin: 0; padding: 18px 20px; appearance: none;
  font: inherit; cursor: pointer; text-align: left; border-radius: 15px; background: #fff !important; color: var(--ink) !important;
  transition: border-color .18s ease; }
.vbkpt2-opt:hover { border-color: var(--acc); }
.vbkpt2-opt b { display: block; font-size: 15.5px; font-weight: 600; margin-bottom: 5px; }
.vbkpt2-opt i { display: block; font-style: normal; font-size: 13px; line-height: 1.5; color: var(--muted); }

.vbkpt2-foot { display: flex; align-items: center; gap: 14px; margin-top: 22px; }
.vbkpt2-back { border: 0; margin: 0; padding: 0; appearance: none; background: none !important; cursor: pointer;
  font: inherit; font-size: 14px; color: var(--muted) !important; text-decoration: underline; }
.vbkpt2-back:hover { color: var(--acc) !important; }
.vbkpt2-step { margin-left: auto; font-size: 13px; color: var(--muted); }

.vbkpt2-res__tag { display: inline-block; font-size: 12px; font-weight: 600; color: var(--acc); background: var(--soft);
  border-radius: 999px; padding: 7px 14px; margin-bottom: 14px; }
.vbkpt2-res__ttl { font-family: var(--fh); font-size: clamp(22px, 2.7vw, 30px); line-height: 1.18; font-weight: 700; margin: 0 0 10px; }
.vbkpt2-res__price { font-family: var(--fh); font-size: 26px; font-weight: 700; color: var(--acc); margin: 0 0 14px; }
.vbkpt2-res__price em { font-style: normal; font-size: 14px; font-weight: 500; color: var(--muted); margin-left: 8px; }.vbkpt2-res__txt { font-size: 15.5px; line-height: 1.65; color: var(--muted); margin: 0 0 20px; max-width: 42em; }
.vbkpt2-res__facts { list-style: none; margin: 0 0 24px; padding: 0; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.vbkpt2-res__facts li { background: var(--soft); border-radius: 13px; padding: 14px 16px; }
.vbkpt2-res__facts b { display: block; font-family: var(--fh); font-size: 17px; font-weight: 700; margin-bottom: 3px; }
.vbkpt2-res__facts span { display: block; font-size: 12.5px; color: var(--muted); }
.vbkpt2-acts { display: flex; flex-wrap: wrap; gap: 10px; }
.vbkpt2-cta, .vbkpt2-cta:link, .vbkpt2-cta:visited, .vbkpt2-cta:focus { display: inline-flex; align-items: center;
  justify-content: center; min-height: 54px; padding: 0 28px; border-radius: 12px; font-size: 16px; font-weight: 600;
  background: var(--acc); color: #fff !important; text-decoration: none !important; }
.vbkpt2-cta:hover { background: var(--acc-dark); color: #fff !important; }
.vbkpt2-again { min-height: 54px; padding: 0 24px; border: 1.5px solid var(--line); margin: 0; appearance: none;
  font: inherit; font-size: 16px; cursor: pointer; border-radius: 12px; background: #fff !important; color: var(--ink) !important; }

@media (max-width: 560px) { .vbkpt2-opts { grid-template-columns: minmax(0, 1fr); } }
@media (prefers-reduced-motion: reduce) { .vbkpt2 * { transition: none !important; } }
</style>

<script>
(function () {
  /* ── ВОПРОСЫ: p — очки позициям каталога ── */
  var STEPS = [
    { q: 'Кому берёте посуду?', short: 'Для кого', opts: [
      { t: 'Себе, живу один или вдвоём', d: 'Пара кружек и тарелок', p: { zavtrak: 2, stol: 0, kastrulya: 1, banki: 1 } },
      { t: 'Семье из трёх человек и больше', d: 'Нужен запас предметов', p: { zavtrak: 0, stol: 3, kastrulya: 2, banki: 1 } },
      { t: 'В подарок', d: 'Важен вид набора', p: { zavtrak: 3, stol: 1, kastrulya: 0, banki: 1 } }
    ]},
    { q: 'Какую задачу закрываете?', short: 'Задача', opts: [
      { t: 'Завтраки и чай', d: 'Кружки и малые тарелки', p: { zavtrak: 3, stol: 1, kastrulya: 0, banki: 0 } },
      { t: 'Готовка каждый день', d: 'Кастрюли всё время в работе', p: { zavtrak: 0, stol: 0, kastrulya: 3, banki: 1 } },
      { t: 'Сервировка стола', d: 'Гости и ровный комплект', p: { zavtrak: 1, stol: 3, kastrulya: 0, banki: 0 } },
      { t: 'Порядок на полках', d: 'Крупы лежат в пакетах', p: { zavtrak: 0, stol: 0, kastrulya: 0, banki: 3 } }
    ]},
    { q: 'На какую сумму рассчитываете?', short: 'Бюджет', opts: [
      { t: 'До 3 000 ₽', d: 'Одна вещь или малый набор', p: { zavtrak: 2, stol: 0, kastrulya: 0, banki: 3 } },
      { t: 'От 3 000 до 6 000 ₽', d: 'Набор на двоих', p: { zavtrak: 3, stol: 1, kastrulya: 3, banki: 1 } },
      { t: 'Больше 6 000 ₽', d: 'Комплект на семью', p: { zavtrak: 0, stol: 3, kastrulya: 2, banki: 0 } }
    ]},
    { q: 'Что для вас важнее в посуде?', short: 'Свойство', opts: [
      { t: 'Переносит духовку и посудомойку', d: 'Машина и духовка', p: { zavtrak: 1, stol: 2, kastrulya: 3, banki: 0 } },
      { t: 'Спокойный вид и одинаковый оттенок', d: 'Всё смотрится комплектом', p: { zavtrak: 2, stol: 3, kastrulya: 0, banki: 1 } },
      { t: 'Плотная крышка и герметичность', d: 'Продукты держат аромат', p: { zavtrak: 0, stol: 0, kastrulya: 1, banki: 3 } }
    ]}
  ];

  /* ── ПОЗИЦИИ КАТАЛОГА ── */
  var GOODS = {
    zavtrak: { ttl: 'Набор для завтрака: 2 кружки и 2 тарелки', price: '3 240 ₽', old: 'вместо 3 860 ₽ поштучно', href: '#katalog-zavtrak',
      txt: 'Посуда на одного или двоих при умеренной сумме. Все четыре предмета из одной партии обжига, оттенок совпадает, коробка годится для подарка.',
      facts: [['350 мл', 'объём кружки'], ['21 см', 'диаметр тарелки'], ['1 день', 'срок сборки заказа']] },
    stol: { ttl: 'Столовый комплект «Гладь» на четыре персоны', price: '8 900 ₽', old: '16 предметов в комплекте', href: '#katalog-stol',
      txt: 'Ровный комплект на семью и гостей: тарелки трёх диаметров и салатники из одной поставки глазури. Машина и духовка ему не вредят.',
      facts: [['16 предметов', 'в одной коробке'], ['4 персоны', 'рассчитан на'], ['до 220 градусов', 'выдерживает в духовке']] },
    kastrulya: { ttl: 'Кастрюля с крышкой, сталь, 3 литра', price: '5 400 ₽', old: 'дно с тройным слоем', href: '#katalog-kastrulya',
      txt: 'Когда готовят каждый день, важнее выносливость. Дно с тройным слоем держит тепло, крышка ложится плотно, плита подойдёт любая.',
      facts: [['3 литра', 'полезный объём'], ['5 мм', 'толщина дна'], ['10 лет', 'гарантия на корпус']] },
    banki: { ttl: 'Три банки для хранения, крышки из бука', price: '2 460 ₽', old: '0,7 литра каждая', href: '#katalog-hranenie',
      txt: 'Порядок на полках держится на герметичности. Кольцо в крышке запирает запах, кофе и специи стоят рядом, а через стенку виден остаток крупы.',
      facts: [['0,7 литра', 'объём одной банки'], ['3 штуки', 'в комплекте'], ['бук', 'материал крышки']] }
  };

  var roots = document.querySelectorAll('.vbkpt2');
  for (var i = 0; i < roots.length; i++) init(roots[i]);

  function init(root) {
    if (root.__vb) return; root.__vb = 1;
    var idx = 0, score, trail;
    var stage = root.querySelector('#vbkpt2-stage'), fill = root.querySelector('#vbkpt2-fill');
    var back = root.querySelector('#vbkpt2-back'), step = root.querySelector('#vbkpt2-step');
    var dots = root.querySelector('#vbkpt2-dots');

    function reset() { idx = 0; score = { zavtrak: 0, stol: 0, kastrulya: 0, banki: 0 }; trail = []; }

    function drawDots(done) {
      var out = '';
      for (var d = 0; d < STEPS.length; d++) {
        out += '<span class="vbkpt2-dot' + (done || d <= idx ? ' vbkpt2-dot--on' : '') + '">' + STEPS[d].short + '<\/span>';
      }
      dots.innerHTML = out;
    }

    function drawStep() {
      var s = STEPS[idx];
      fill.style.width = (idx / STEPS.length * 100) + '%';
      step.textContent = 'Вопрос ' + (idx + 1) + ' из ' + STEPS.length;
      back.hidden = idx === 0;
      drawDots(false);
      var html = '<h3 class="vbkpt2-q">' + s.q + '<\/h3><div class="vbkpt2-opts">';
      for (var o = 0; o < s.opts.length; o++) {
        html += '<button type="button" class="vbkpt2-opt" data-i="' + o + '"><b>' + s.opts[o].t + '<\/b><i>' + s.opts[o].d + '<\/i><\/button>';
      }
      stage.innerHTML = html + '<\/div>';
      var btns = stage.querySelectorAll('.vbkpt2-opt');
      for (var b = 0; b < btns.length; b++) {
        btns[b].addEventListener('click', function () { choose(s.opts[parseInt(this.getAttribute('data-i'), 10)]); });
      }
    }

    function choose(opt) {
      trail.push(opt.p);
      for (var k in opt.p) { if (opt.p.hasOwnProperty(k)) score[k] += opt.p[k]; }
      idx++;
      if (idx < STEPS.length) drawStep(); else drawResult();
    }

    function drawResult() {
      fill.style.width = '100%';
      step.textContent = 'Готово';
      back.hidden = false;
      drawDots(true);
      var win = 'zavtrak', keys = ['zavtrak', 'stol', 'kastrulya', 'banki'];
      for (var k = 1; k < keys.length; k++) { if (score[keys[k]] > score[win]) win = keys[k]; }
      var g = GOODS[win], facts = '';
      for (var f = 0; f < g.facts.length; f++) {
        facts += '<li><b>' + g.facts[f][0] + '<\/b><span>' + g.facts[f][1] + '<\/span><\/li>';
      }
      stage.innerHTML = '<div class="vbkpt2-res"><span class="vbkpt2-res__tag">Подходит вам<\/span>' +
        '<h3 class="vbkpt2-res__ttl">' + g.ttl + '<\/h3>' +
        '<p class="vbkpt2-res__price">' + g.price + '<em>' + g.old + '<\/em><\/p>' +
        '<p class="vbkpt2-res__txt">' + g.txt + '<\/p>' +
        '<ul class="vbkpt2-res__facts">' + facts + '<\/ul>' +
        '<div class="vbkpt2-acts"><a class="vbkpt2-cta" href="' + g.href + '">Открыть в каталоге<\/a>' +
        '<button type="button" class="vbkpt2-again">Пройти заново<\/button><\/div><\/div>';
      var again = stage.querySelector('.vbkpt2-again');
      if (again) again.addEventListener('click', function () { reset(); drawStep(); });
    }

    back.addEventListener('click', function () {
      if (idx === 0) return;
      idx--;
      var p = trail.pop();
      if (p) { for (var k in p) { if (p.hasOwnProperty(k)) score[k] -= p[k]; } }
      drawStep();
    });

    reset();
    drawStep();
  }
})();
</script>

Вставляется целиком в блок T123 «HTML-код». Внутри уже есть стили и скрипт, подключать ничего не нужно.

Как вставить блок в Tilda

  1. Скопируйте кодКнопка «Скопировать код» выше кладёт всё содержимое в буфер обмена.
  2. Добавьте блок T123В редакторе страницы: «Библиотека блоков» → «Другое» → T123 «HTML-код».
  3. Вставьте и сохранитеНажмите «Контент», вставьте код в поле, сохраните и обновите страницу.
  4. ОпубликуйтеВ превью скрипты Tilda работают не всегда — проверяйте на опубликованной странице.

Подробная инструкция с граблями — как вставить вайб-блок в Tilda.

Что менять под себя

Где в кодеЗа что отвечает
STEPS в начале скриптавопросы, варианты ответов и очки каждому товару
GOODS в начале скриптапозиции каталога: название, цена, обоснование, три параметра
href внутри GOODSадреса карточек товара, куда ведёт кнопка результата
--acc в начале стилейцвет полосы прогресса, рамок и кнопки в результате

Квиз подбора товара: зачем он нужен

Каталог из двухсот позиций пугает человека, который зашёл выбрать подарок. Квиз сужает выбор до одной вещи за четыре шага: для кого, какая задача, какая сумма и что важнее в изделии. Ответы складываются в очки по четырём товарам, побеждает набравший больше, поэтому результат меняется даже при похожих сценариях.

Наверху идёт полоса прогресса и названия шагов, внизу ссылка на предыдущий вопрос: очки за отменённый ответ вычитаются обратно, и повтор шага не портит подсчёт. Результат показывает название позиции, цену, короткое объяснение и три параметра вроде объёма и срока сборки. Оттуда ведёт кнопка в каталог и кнопка пройти заново.

Вопросы по этому блоку

  • Допишите объект в массив STEPS: поле q для вопроса, short для подписи в полосе шагов и opts с вариантами. Полоса прогресса и счётчик считают шаги сами, править разметку не нужно.

  • Да. Добавьте ключ в GOODS и такой же ключ в очки каждого варианта ответа, а также в массив keys внутри функции подсчёта. Остальная логика работает с любым числом позиций.

  • Никуда: расчёт живёт в браузере, форм в блоке нет. Цель квиза перевести человека в каталог по ссылке из результата, поэтому подставьте туда рабочие адреса карточек.

  • Да. Код на этой странице копируется целиком, без регистрации и подписки. Указывать авторство не нужно, использовать можно в коммерческих проектах.

  • Нет. Все классы внутри имеют собственный префикс vbkpt2, поэтому не пересекаются ни со стилями Tilda, ни с другими блоками. Скрипт привязан к своему элементу и запускается один раз, даже если блок вставлен дважды.

  • Раскладка перестраивается под узкие экраны, размеры заданы через clamp, поля ввода имеют шрифт 16 пикселей — iOS не будет зумить страницу при фокусе. Отдельной мобильной версии подключать не нужно.

Другие квизы

Ещё блоки для товарных брендов

Собрать сайт целиком, а не по блокам

Дровосеки делают сайты на Tilda под ключ: структура, тексты, дизайн, вёрстка и вайб-блоки под задачи бизнеса.