Configuring Abandoned Cart Email Notifications in 1C-Bitrix
The abandoned cart email is one of the few automated messages with a 5–15% conversion rate. A message sent 1–2 hours after the user leaves the site reaches them while they still remember the product. In 1C-Bitrix, this is implemented using an agent, the main.mail module, and mail event templates.
Core Logic: When to Send
Optimal timing intervals:
- First email — after 1–2 hours. "You left items in your cart." No discount.
- Second email — after 24 hours (if no order placed). Reinforce the product's value.
- Third email — after 72 hours (optional). With a discount or reservation expiry notice.
Do not send all three emails in succession — this creates a negative experience. Stop after the first if the user opened the email, or after the second if they clicked a link.
Mail Event Template
Create a mail event type in Bitrix: Settings → Mail Events → Event Types → Add.
- Event code:
ABANDONED_CART_REMINDER - Fields:
USER_NAME,USER_EMAIL,CART_ITEMS(HTML table with products),CART_TOTAL,CART_RESTORE_URL,SITE_URL
Email template (Mail Events → Templates → Add):
Subject: #USER_NAME#, you left items in your cart
Hello, #USER_NAME#!
You didn't complete your order. Your cart contains:
#CART_ITEMS#
Total: #CART_TOTAL#
<a href="#CART_RESTORE_URL#">Return to cart</a>
Building the Email Data
class AbandonedCartMailer
{
public function send(int $userId, int $fuserId): bool
{
$user = \Bitrix\Main\UserTable::getById($userId)->fetch();
if (!$user || !$user['EMAIL']) return false;
// Check if an order has already been placed
if ($this->hasRecentOrder($userId)) return false;
// Get cart items
$basket = \Bitrix\Sale\Basket::loadItemsForFUser($fuserId, SITE_ID);
if ($basket->isEmpty()) return false;
$cartItems = $this->buildCartItemsHtml($basket);
$cartTotal = number_format($basket->getPrice(), 0, '.', ' ');
// Cart restoration URL (simply the cart URL — items are already there)
$cartUrl = SITE_SERVER_NAME . '/basket/';
\CEvent::Send('ABANDONED_CART_REMINDER', SITE_ID, [
'USER_NAME' => $user['NAME'],
'USER_EMAIL' => $user['EMAIL'],
'CART_ITEMS' => $cartItems,
'CART_TOTAL' => $cartTotal,
'CART_RESTORE_URL' => $cartUrl,
'SITE_URL' => SITE_SERVER_NAME,
]);
return true;
}
private function buildCartItemsHtml(\Bitrix\Sale\Basket $basket): string
{
$html = '<table width="100%" style="border-collapse:collapse">';
foreach ($basket as $item) {
$name = htmlspecialchars($item->getField('NAME'));
$qty = (int)$item->getField('QUANTITY');
$price = number_format($item->getPrice() * $qty, 0, '.', ' ');
$img = $this->getProductImage($item->getProductId());
$html .= "<tr>
<td width='80'><img src='{$img}' width='70' height='70'></td>
<td>{$name}<br>Qty: {$qty}</td>
<td align='right'>{$price}</td>
</tr>";
}
$html .= '</table>';
return $html;
}
private function hasRecentOrder(int $userId): bool
{
$cutoff = new \Bitrix\Main\Type\DateTime();
$cutoff->add('-24 hours');
$order = \Bitrix\Sale\Order::getList([
'filter' => ['USER_ID' => $userId, '>DATE_INSERT' => $cutoff],
'select' => ['ID'],
'limit' => 1,
])->fetch();
return (bool)$order;
}
}
Agent to Trigger the Mailing
// Agent runs every 30 minutes
function sendAbandonedCartEmails(): string
{
$mailer = new AbandonedCartMailer();
// Select carts detected 1–2 hours ago with no first email sent yet
$candidates = AbandonedCartTable::getList([
'filter' => [
'STATUS' => 'new',
'<DETECTED_AT' => new \Bitrix\Main\Type\DateTime('-1 hour'),
'>DETECTED_AT' => new \Bitrix\Main\Type\DateTime('-2 hours'),
],
'limit' => 50,
])->fetchAll();
foreach ($candidates as $row) {
$sent = $mailer->send($row['USER_ID'], $row['FUSER_ID']);
AbandonedCartTable::update($row['ID'], [
'STATUS' => $sent ? 'email_sent' : 'skipped',
'EMAIL_SENT_AT' => $sent ? new \Bitrix\Main\Type\DateTime() : null,
]);
}
return __FUNCTION__ . '();';
}
Unsubscribe and Consent Management
Under the requirements of Federal Law No. 38 "On Advertising" and GDPR, users must have the ability to opt out. Add an unsubscribe link to the email template:
<a href="#UNSUBSCRIBE_URL#">Unsubscribe from cart reminders</a>
On the Bitrix side — a handler at /local/api/cart-unsubscribe.php that sets the user field UF_NO_CART_EMAIL = Y. Check this field before sending.
Tracking Results
Add UTM parameters to the cart link in the email:
$cartUrl = SITE_SERVER_NAME . '/basket/?utm_source=email&utm_medium=abandoned_cart&utm_campaign=reminder_1h';
GA4 and Metrica will show how many users clicked through from the email and how many of them completed an order.
Timelines: email template creation, agent, sending logic — 3–5 days. With a multi-step email sequence, consent management, and reporting — 1–2 weeks.







