Промокод на определённые товары в Тильде из коробки не настраивается: встроенный модуль скидок в Tilda Cart применяет код либо ко всей сумме заказа, либо не применяет вообще. За практику с Tilda-магазинами я закрывал эту задачу скриптами больше десяти раз: то нужна скидка только на одну категорию, то на конкретные артикулы, то промокод должен игнорировать товары, которые уже участвуют в акции. Разберу, как устроена корзина Tilda изнутри и какой скрипт решает задачу без переписывания сайта.
По теме статьи
Готовое решение
Ограничение применения промокода в корзине Tilda
Промокод в Tilda не действует на выбранную категорию (например, «Распродажа»). Готовый скрипт + инструкция по подключению.
от6 000 ₽
Кастомный скрипт
Когда стандартных блоков не хватает
Доработка сайтов на Тильде: скрипты для корзины, промокоды, зоны доставки, интеграции с CRM и Telegram. Простой скрипт от 3 000
от3 000 ₽
Как устроены промокоды в Tilda и почему они не различают товары
Стандартная настройка находится в панели сайта: Настройки корзины, Промокоды. Там задаётся код, тип скидки (процент, фиксированная сумма или бесплатная доставка), даты действия, лимит использований и минимальная сумма заказа. Для акции вроде «скидка 10% на весь заказ по коду NEWYEAR» с лимитом в 200 применений и сроком действия 30 дней этого достаточно, панель всё посчитает сама.
Проблема в том, что скидка считается от итоговой суммы корзины целиком. Поля «категория» или «товар» в настройках промокода нет. Если магазин продаёт и одежду, и обувь, а скидка должна работать только на одежду, стандартный промокод такое не умеет: он либо скинет процент со всей корзины, включая обувь, либо придётся вручную вычитать сумму на кассе, что для интернет-магазина не вариант, особенно если заказы идут через автоматическую отправку на оплату.
Логика скрипта: как ограничить промокод конкретными товарами
Корзина Tilda работает через глобальный объект window.tcart, в котором лежит массив tcart.products с полями каждого товара: uid, sku (артикул), name, price, amount (количество). Отдельного поля «категория» в этом объекте обычно нет, поэтому категорию я определяю либо по префиксу артикула (например, все товары раздела «Одежда» имеют артикулы вида CLTH-101), либо по дополнительному текстовому полю товара, которое заполняется в панели Tilda и попадает в разметку карточки.
При изменении состава корзины Tilda генерирует события обновления, на которые можно подписаться и пересчитать скидку не от полной суммы, а только от суммы товаров из разрешённого списка. Схема простая: скрипт слушает изменение корзины, проходит по tcart.products, суммирует стоимость только тех позиций, чей артикул или категория входят в допустимый список, считает скидку от этой суммы и подставляет результат в поля, которые Tilda использует при отрисовке итога, вместо стандартного расчёта скидки от всей суммы.
Пример: скидка только на одну категорию товаров
document.addEventListener('tcart:updated', function () {
var allowedSku = ['CLEAR-101', 'CLEAR-102', 'CLEAR-205'];
var eligibleSum = 0;
window.tcart.products.forEach(function (product) {
if (allowedSku.indexOf(product.sku) !== -1) {
eligibleSum += product.price * product.amount;
}
});
var discount = Math.round(eligibleSum * 0.15);
window.tcart.discount = discount;
window.tcart.amount = window.tcart.amount - discount;
if (typeof tcart__reDrawCart === 'function') {
tcart__reDrawCart();
}
});
У Tilda несколько версий корзины, и событие может называться иначе, а пересчёт срабатывать через tcart__updateProductCallback вместо кастомного события. Перед тем как ставить скрипт на боевой сайт, я всегда смотрю в исходный код конкретного проекта, какая версия корзины подключена, как называются нужные хуки и в каком формате приходит артикул: с пробелами, в верхнем регистре или с дефисами внутри.
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Комбинация условий: категория, минимальная сумма, исключение акционных товаров
На практике редко нужен просто промокод на категорию. Обычно условия комбинируются:
- минимальная сумма заказа, например от 3000 ₽, до которой промокод вообще не активируется;
- исключение товаров, которые уже продаются со скидкой (у них в Tilda обычно заполнено поле старой цены
priceold, отличное отprice); - ограничение по нескольким категориям одновременно, если магазин делит товары по разделам каталога, а не только по артикулам;
- лимит на количество товаров в заказе, на которые распространяется скидка, если промокод рассчитан на пробную покупку, а не на опт.
Пример из недавнего проекта: промокод «SUMMER15» давал минус 15% только на категорию «Одежда», требовал корзину от 3000 ₽ и не срабатывал на товарах, у которых уже была указана старая цена. Такие условия пишутся внутри того же обработчика: сначала фильтр по allowedSku собирает подходящие позиции, потом отдельной проверкой сравнивается сумма этих позиций с порогом, и только после этого высчитывается сама скидка. Порядок проверок важен, потому что если считать скидку раньше проверки минимальной суммы, при удалении товара из корзины старое значение скидки может остаться висеть в интерфейсе до следующего пересчёта.
Тестирование скрипта и типичные ошибки
На доработках корзины Tilda я регулярно натыкаюсь на одни и те же грабли:
- скрипт запускается раньше, чем Tilda успевает инициализировать
tcart, и падает с ошибкой в консоли, поэтому вызов стоит оборачивать в проверкуtypeof window.tcart !== 'undefined'или дожидаться готовности корзины; - пересчёт срабатывает один раз при загрузке страницы, а не при каждом добавлении или удалении товара, поэтому обработчик нужно вешать на все события изменения корзины, а не только на
DOMContentLoaded; - на мобильном Safari корзина иногда подтягивается из кэша, и старая скидка «залипает» от предыдущей сессии, поэтому состояние скидки стоит сбрасывать при каждом событии обновления;
- скидка не отображается отдельной строкой в блоке товара, только в итоговой сумме, из-за чего покупатели пишут в поддержку, что промокод не сработал, хотя сумма посчитана верно, поэтому лучше выводить строку вида «Скидка по промокоду: ‑450 ₽» рядом с итогом;
- письмо с подтверждением заказа собирается Tilda по своему шаблону и может показать сумму без учёта кастомной скидки, если скидка не передана в те же переменные, что использует шаблон письма.
Проверяю каждый сценарий вручную: добавляю в корзину нужные товары, применяю код, смотрю на итог в интерфейсе, потом оформляю тестовый заказ до конца и сверяю сумму в письме и в панели заказов Tilda. Без этого шага легко пропустить расхождение между тем, что видно в корзине, и тем, что реально уходит в заказ.
Почему проверку нельзя оставлять только на клиенте
JS-скрипт в корзине решает задачу для честного покупателя, но выполняется в браузере, а значит любой человек с открытой консолью разработчика может вручную поменять значение window.tcart.discount и применить скидку ко всей корзине перед отправкой заказа. Для интернет-магазина с реальными оборотами это не гипотетический риск, а конкретная дыра в скидочной логике.
Рабочая схема защиты: Tilda отправляет вебхук при создании заказа, и на сервере, напрямую или через сценарий в n8n, повторно проверяются товары в заказе, их сумма и условия промокода, прежде чем сформировать ссылку на оплату через T‑Bank или передать заказ в СДЭК на доставку. Если проверка не сходится с тем, что видел клиент в браузере, заказ уходит в статус «на проверке» вместо автоматического списания, а в telegram-бот на aiogram, который я обычно подключаю для таких магазинов, падает уведомление менеджеру: какой заказ, какой промокод и что именно не сошлось. Такую интеграцию промокода с CRM и приёмом оплаты я обычно делаю отдельным блоком поверх клиентского скрипта, а не вместо него.
Сравнение: Tilda, WooCommerce и кастомные решения
| Платформа | Ограничение промокода по товару из коробки | Нужен кастомный скрипт | Серверная проверка перед оплатой |
|---|---|---|---|
| Tilda | Нет, скидка считается от всей корзины | Да, JS в блоке корзины | Да, отдельным вебхуком |
| WooCommerce | Да, купоны привязываются к товару или категории в настройках | Обычно не нужен | Частично, через хуки WooCommerce |
| Самописный магазин на React и Laravel | Полностью гибко, логика пишется под задачу | Да, это часть бэкенда, а не надстройка | Да, изначально на сервере |
Разница объясняется устройством платформ: WooCommerce изначально построен вокруг гибкой системы купонов с привязкой к товару, категории и даже пользователю, потому что это движок для интернет-магазинов, а Tilda в первую очередь конструктор сайтов, где корзина появилась как надстройка. У сторонних студий разработки доработка корзины Tilda под ограниченный промокод на рынке стоит по-разному в зависимости от сложности условий, обычно от 15 000 до 40 000 ₽. У меня простая доработка с одной категорией и одним типом скидки стоит от 3 000 ₽, а комплексная интеграция с проверкой на сервере, CRM и эквайрингом от 40 000 ₽.
Частые вопросы
Можно ли ограничить промокод на товары в Тильде без программиста?
Встроенными настройками нет. Срок действия и лимит использований задаёшь в панели без кода, а фильтр по конкретным товарам или категориям, как и минимальная сумма заказа, добавляется только скриптом в блоке корзины.
Промокод продолжит работать после того, как я поменяю дизайн блока корзины?
Если меняется верстка блока корзины, витрины каталога или Zero Block, структура товаров и события могут отличаться, и скрипт стоит проверить заново на конкретной версии блока. Это отдельная задача, которая не входит в стоимость исходной доработки.
Как проверить, что промокод не применяется к товарам не из списка?
Добавляю в корзину и товар из разрешённого списка, и товар вне списка, применяю код и сверяю, что скидка посчиталась только от суммы первого. Дополнительно открываю консоль разработчика и вывожу window.tcart.products вместе с посчитанной скидкой, чтобы убедиться в правильном списке артикулов.
Можно совместить ограничение по товарам с минимальной суммой заказа?
Да, это просто ещё одно условие в том же обработчике: сначала фильтруется список товаров, подходящих под промокод, потом от их суммы проверяется порог, например от 3000 ₽, и только тогда скидка применяется к корзине.