Розроблення модуля керування банерами для 1С-Bitrix
Банери у Bitrix традиційно зберігають в інфоблоці: картинка, посилання, дати показу. Для трьох банерів на головній — нормально. Коли банерів стає десятки, вони показуються в різних зонах сайту, потрібна ротація, обмеження за числом показів, статистика 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, Яндекс) — окремої завдання.







