Разработка модуля управления баннерами 1С-Битрикс
Баннеры в Битрикс традиционно хранят в инфоблоке: картинка, ссылка, даты показа. Для трёх баннеров на главной — нормально. Когда баннеров становится десятки, они показываются в разных зонах сайта, нужна ротация, ограничение по числу показов, статистика CTR и таргетинг по аудитории — инфоблок перестаёт справляться с задачей. Специализированный модуль даёт полноценную рекламную систему внутри сайта.
Модель данных
Модуль vendor.banners:
-
b_vendor_banner— баннеры: id, name, zone_id, image_id, image_mobile_id, url, target, alt, title, html_code (для HTML-баннеров), date_from, date_to, priority, weight (для ротации), impressions_limit, impressions_count, clicks_count, status (active/inactive/draft), targeting (JSON), created_at -
b_vendor_banner_zone— зоны размещения: id, code, name, description, width, height, max_banners, is_active -
b_vendor_banner_stat— статистика (суточные срезы): banner_id, date, impressions, clicks, ctr -
b_vendor_banner_impression— сырые данные показов (опционально, для детальной аналитики): id, banner_id, user_id, session_id, ip, user_agent, created_at
Зоны размещения
Зоны — это именованные места на сайте: header_top, sidebar_right, content_after_article, footer_banner. В шаблоне подключаем компонент:
$APPLICATION->IncludeComponent('vendor:banners.zone', '', [
'ZONE_CODE' => 'header_top',
'MAX_BANNERS' => 1, // сколько баннеров показывать одновременно
]);
Компонент выбирает активные баннеры для зоны, применяет таргетинг и ротацию, рендерит HTML.
Алгоритм выбора баннера
class BannerSelector
{
public function select(string $zoneCode, int $maxBanners): array
{
$now = new DateTime();
$zone = ZoneTable::getByCode($zoneCode);
// Получаем кандидатов: активные, в сроке, лимит не исчерпан, подходящий таргетинг
$candidates = BannerTable::getList([
'filter' => [
'ZONE_ID' => $zone['ID'],
'STATUS' => 'active',
'<=DATE_FROM' => $now,
['LOGIC' => 'OR', '>=DATE_TO' => $now, '=DATE_TO' => false],
['LOGIC' => 'OR', '=IMPRESSIONS_LIMIT' => 0, '>IMPRESSIONS_LIMIT' => new SqlExpression('IMPRESSIONS_COUNT')],
],
])->fetchAll();
// Фильтр таргетинга
$candidates = array_filter($candidates, fn($b) => $this->matchesTargeting($b));
// Взвешенная случайная выборка
return $this->weightedRandom($candidates, $maxBanners);
}
private function weightedRandom(array $items, int $count): array
{
// Реализация weighted reservoir sampling
$totalWeight = array_sum(array_column($items, 'WEIGHT'));
// ...
}
}
Таргетинг
Таргетинг хранится в JSON-поле targeting:
{
"geo": {"city_ids": [1, 15, 42]},
"user_groups": [3, 9],
"device": "mobile",
"pages": ["/catalog/", "/sale/"],
"new_visitors_only": true
}
Проверяется через TargetingChecker — аналогично оценке сегментов из модуля персонализации. Интеграция с модулем геолокации для geo таргетинга.
Подсчёт показов и кликов
Показы — инкрементируются при рендере баннера:
// В конце работы компонента
BannerTable::update($bannerId, [
'IMPRESSIONS_COUNT' => new SqlExpression('IMPRESSIONS_COUNT + 1'),
]);
StatTable::increment($bannerId, 'impressions');
Клики — через редирект-прокси:
GET /bitrix/components/vendor/banners.click/?id=42&token=abc&url=https://example.com/product/
Сервер записывает клик, проверяет токен (защита от накрутки), перенаправляет пользователя.
// Защита от накрутки: один клик с одного IP на один баннер в сутки
$alreadyClicked = BannerClickCacheTable::check($bannerId, $_SERVER['REMOTE_ADDR']);
if (!$alreadyClicked) {
BannerTable::update($bannerId, ['CLICKS_COUNT' => new SqlExpression('CLICKS_COUNT + 1')]);
StatTable::increment($bannerId, 'clicks');
BannerClickCacheTable::set($bannerId, $_SERVER['REMOTE_ADDR']);
}
HTML-баннеры
Для Rich Media и анимированных баннеров поддерживается HTML-формат. Поле html_code содержит произвольный HTML (анимация CSS, встроенное видео). Редактируется в административном интерфейсе через TinyMCE с ограничением опасных тегов.
Административный интерфейс
- Список баннеров с превью, статусом, CTR
- Форма создания/редактирования: загрузка изображений, настройка таргетинга
- Управление зонами размещения
- Статистика по баннерам: график показов/кликов, CTR, сравнение с предыдущим периодом
- Быстрая активация/деактивация
Сроки разработки
| Этап | Срок |
|---|---|
| ORM-таблицы, модель зон и баннеров | 1 день |
| Алгоритм выбора, взвешенная ротация | 1 день |
| Таргетинг, интеграция с геолокацией | 1 день |
| Подсчёт показов и кликов, защита от накрутки | 1 день |
| HTML-баннеры, редактор | 1 день |
| Статистика, графики CTR | 1 день |
| Административный интерфейс | 2 дня |
| Тестирование | 1 день |
Итого: 9 рабочих дней. Синхронизация с внешними рекламными сетями (Google DFP, Яндекс) — отдельная задача.







