Разработка функционала обратного отсчета (таймер акции) 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка функционала обратного отсчета (таймер акции) 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка функционала обратного отсчёта (таймер акции) 1С-Битрикс

Акция без дедлайна — это не акция, а постоянная скидка. Таймер обратного отсчёта создаёт ощущение ограниченности предложения и подталкивает к решению. Но в Битрикс нет штатного компонента обратного отсчёта. Стандартный механизм скидок умеет задавать период действия, а вот визуальный таймер на фронте — задача для кастомной разработки. Разберём, как связать таймер с реальными правилами скидок, чтобы дата окончания бралась из базы, а не была захардкожена в шаблоне.

Источник данных: откуда брать дату окончания

Таймер должен показывать реальный срок акции, а не декоративные цифры. В Битрикс даты акций хранятся в нескольких местах:

Скидки каталога — таблица b_catalog_discount, поля ACTIVE_FROM и ACTIVE_TO. Получаем через \Bitrix\Catalog\DiscountTable::getList() с фильтром ACTIVE = Y и ACTIVE_TO > NOW().

Правила корзины — таблица b_sale_discount, аналогичные поля. API: \Bitrix\Sale\Internals\DiscountTable::getList().

Свойство товара — можно создать свойство инфоблока PROMO_END_DATE типа «Дата/Время» и заполнять его вручную или автоматически при привязке товара к акции.

Выбор источника зависит от сценария. Если таймер показывается на карточке товара — удобнее свойство товара или скидка каталога. Если таймер глобальный (баннер на главной) — правило корзины или отдельный инфоблок акций.

Архитектура компонента

Создаём кастомный компонент local:sale.countdown в /local/components/local/sale.countdown/. Структура стандартная:

  • class.php — логика выборки данных.
  • templates/.default/template.php — HTML-разметка.
  • templates/.default/script.js — JavaScript-логика обратного отсчёта.
  • .parameters.php — настраиваемые параметры компонента.

Параметры компонента:

Параметр Тип Описание
SOURCE_TYPE list Источник: catalog_discount, sale_discount, iblock_property
DISCOUNT_ID int ID скидки (для catalog/sale)
IBLOCK_ID int ID инфоблока (для свойства товара)
ELEMENT_ID int ID элемента (для свойства товара)
PROPERTY_CODE string Код свойства с датой окончания
DISPLAY_FORMAT list Формат: дни+часы+минуты+секунды или часы+минуты+секунды
ACTION_ON_EXPIRE list Действие по истечении: скрыть / показать сообщение
CACHE_TIME int Время кэширования

В class.php компонент получает дату окончания из выбранного источника и передаёт в шаблон timestamp:

$this->arResult['TIMESTAMP_END'] = (new \Bitrix\Main\Type\DateTime($endDate))->getTimestamp();

JavaScript: клиентский отсчёт

Таймер работает целиком на клиенте. Серверная часть отдаёт только timestamp окончания. Это принципиально: AJAX-запросы каждую секунду — нагрузка без смысла.

Ключевой момент — синхронизация времени. Клиентские часы могут отличаться от серверных. Решение: сервер передаёт не только TIMESTAMP_END, но и TIMESTAMP_SERVER — текущее серверное время. JavaScript вычисляет дельту и корректирует отсчёт:

const serverNow = parseInt(container.dataset.serverTime);
const clientNow = Math.floor(Date.now() / 1000);
const drift = serverNow - clientNow;
const remaining = endTime - (Math.floor(Date.now() / 1000) + drift);

Обновление DOM каждую секунду через setInterval — рабочий вариант. Но для множества таймеров на странице (листинг товаров с акциями) лучше один requestAnimationFrame-цикл, который обновляет все таймеры за один проход.

Действие по истечении. Когда remaining <= 0, таймер должен не просто остановиться. Варианты: скрыть блок акции, заменить кнопку «Купить со скидкой» на обычную, показать сообщение «Акция завершена». Для смены кнопки — AJAX-запрос к серверу для проверки актуальности скидки и перерендер блока цены.

Интеграция с composite-кэшем

Composite cache (автокомпозит) Битрикс кэширует HTML-страницу целиком. Таймер с серверным timestamp в HTML сломает кэш: каждый хит будет уникальным.

Решение — вынести блок таймера в динамическую область. В template.php:

$frame = new \Bitrix\Main\Page\Frame('countdown_' . $this->arParams['DISCOUNT_ID']);
$frame->begin();
// HTML таймера
$frame->end();

Внутри динамической области HTML обновляется при каждом запросе, а остальная страница отдаётся из кэша.

Альтернатива — не выводить timestamp в HTML вообще. Вместо этого хранить его в отдельном endpoint (/ajax/countdown.php), который JavaScript запрашивает один раз при загрузке. Страница кэшируется полностью, данные таймера загружаются отдельно.

Привязка к правилам скидок

Таймер сам по себе — только визуал. Он должен быть синхронизирован с реальным правилом скидки. Если менеджер продлил акцию в админке — таймер должен обновиться автоматически.

Для этого компонент при каждом сбросе кэша заново запрашивает ACTIVE_TO из таблицы скидок. Время кэширования компонента ставим небольшим — 300-600 секунд. Это компромисс между актуальностью и нагрузкой.

Дополнительно: обработчик OnAfterCatalogDiscountUpdate / OnAfterSaleDiscountUpdate для сброса кэша компонента при изменении скидки. Тегированный кэш (\Bitrix\Main\Data\TaggedCache) с тегом catalog_discount_{ID} решает задачу точечно.

Таймер на листинге товаров

Отдельная задача — показать таймеры на странице каталога, где 20-50 товаров. Каждый может иметь свою акцию с отдельным сроком. Компонент вызывается в цикле catalog.section — это множественные SQL-запросы.

Оптимизация: в class.php реализуем batch-режим. Компонент принимает массив ELEMENT_IDS, одним запросом получает все даты и возвращает массив timestamp'ов. В шаблоне catalog.section — один вызов вместо N.

Сроки реализации

Вариант Состав Срок
Простой таймер Один компонент, одна скидка, статический endpoint 3-4 дня
Полное решение Batch-режим, composite-совместимость, синхронизация с правилами, автосброс кэша 7-10 дней