Настройка триггера снижения цены на просмотренный товар 1С-Битрикс
Пользователь посмотрел товар несколько раз и не купил — явный сигнал интереса. Автоматическое снижение цены через 24-48 часов после просмотра или добавление персонального купона конвертирует таких пользователей лучше стандартных email-рассылок. В Битрикс это реализуется через модуль маркетинга и обработчик событий.
Фиксация просмотров
Просмотры товара пишутся в таблицу HL-блока. Стандартный модуль статистики (b_stat_page_event) не подходит — нужна связь конкретного пользователя с конкретным товаром:
// /local/lib/Tracking/ProductViewTracker.php
namespace Local\Tracking;
class ProductViewTracker
{
public static function track(int $userId, int $productId): void
{
if ($userId <= 0) return; // только авторизованных
$conn = \Bitrix\Main\Application::getConnection();
// Upsert: обновляем счётчик и дату последнего просмотра
$conn->queryExecute("
INSERT INTO b_uts_product_view
(UF_USER_ID, UF_PRODUCT_ID, UF_VIEW_COUNT, UF_LAST_VIEW, UF_TRIGGER_SENT)
VALUES
({$userId}, {$productId}, 1, NOW(), 'N')
ON DUPLICATE KEY UPDATE
UF_VIEW_COUNT = UF_VIEW_COUNT + 1,
UF_LAST_VIEW = NOW()
");
}
}
Вызывать в компоненте карточки товара, в result_modifier.php:
// /local/templates/.default/components/bitrix/catalog.element/main/result_modifier.php
global $USER;
if ($USER->IsAuthorized()) {
\Local\Tracking\ProductViewTracker::track(
(int)$USER->GetID(),
(int)$arResult['ID']
);
}
Агент-триггер
Агент запускается раз в час, ищет пользователей с подходящими условиями и применяет скидку:
namespace Local\Marketing;
class PriceDropTriggerAgent
{
public static function run(): string
{
$conn = \Bitrix\Main\Application::getConnection();
// Товары, просмотренные 2+ раз, без покупки, 24+ часов назад
$candidates = $conn->query("
SELECT pv.UF_USER_ID, pv.UF_PRODUCT_ID, pv.UF_VIEW_COUNT
FROM b_uts_product_view pv
LEFT JOIN b_sale_basket sb
ON sb.USER_ID = pv.UF_USER_ID
AND sb.PRODUCT_ID = pv.UF_PRODUCT_ID
AND sb.ORDER_ID IS NOT NULL
WHERE pv.UF_VIEW_COUNT >= 2
AND pv.UF_LAST_VIEW < DATE_SUB(NOW(), INTERVAL 24 HOUR)
AND pv.UF_TRIGGER_SENT = 'N'
AND sb.ID IS NULL
LIMIT 50
");
while ($row = $candidates->fetch()) {
self::applyDiscount($row['UF_USER_ID'], $row['UF_PRODUCT_ID']);
// Помечаем, чтобы не применять повторно
$conn->queryExecute("
UPDATE b_uts_product_view
SET UF_TRIGGER_SENT = 'Y'
WHERE UF_USER_ID = {$row['UF_USER_ID']}
AND UF_PRODUCT_ID = {$row['UF_PRODUCT_ID']}
");
}
return '\Local\Marketing\PriceDropTriggerAgent::run();';
}
private static function applyDiscount(int $userId, int $productId): void
{
// Создаём персональный купон через модуль маркетинга
$couponCode = 'VIEW_' . strtoupper(substr(md5($userId . $productId . time()), 0, 8));
\CCatalogDiscountCoupon::Add([
'DISCOUNT_ID' => VIEWED_PRODUCT_DISCOUNT_ID, // ID заранее созданной скидки 10%
'CODE' => $couponCode,
'ONE_TIME' => 'Y', // одноразовый
'ACTIVE' => 'Y',
'ACTIVE_FROM' => new \Bitrix\Main\Type\DateTime(),
'ACTIVE_TO' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time() + 86400 * 3),
'MAX_USE' => 1,
]);
// Привязываем купон к пользователю через HL-блок
PersonalCouponRepository::save($userId, $productId, $couponCode);
// Email пользователю
self::sendEmail($userId, $productId, $couponCode);
}
}
Скидка через модуль маркетинга
Базовая скидка создаётся один раз через административный интерфейс (Маркетинг → Скидки) или через API:
\CCatalogDiscount::Add([
'NAME' => 'Персональная скидка на просмотренный товар',
'LID' => SITE_ID,
'ACTIVE' => 'Y',
'VALUE' => 10, // скидка 10%
'VALUE_TYPE' => 'P',
'COUPON_TYPE' => 'U', // только с купоном
'SORT' => 300,
'PRIORITY' => 1,
]);
Идентификатор этой скидки прописывается в константу VIEWED_PRODUCT_DISCOUNT_ID.
Срок жизни данных
Записи о просмотрах чистятся агентом раз в неделю: удаляем записи старше 30 дней с отправленным триггером. Таблица не разрастается до неприличных размеров.
| Конфигурация | Срок |
|---|---|
| Трекинг + агент + email + купон | 3–5 дней |
| + аналитика конверсии триггера | +2 дня |







