Настройка единого профиля клиента на 1С-Битрикс
Клиент делает заказ через сайт под одним email, потом звонит в колл-центр и называет другой телефон, затем заходит с мобильного приложения как гость. В итоге в базе три разных «клиента», а менеджер не видит полной истории. Это классическая проблема дублирования профилей, которую решает единый профиль клиента — Customer Data Profile — в связке с модулем sale и CRM Битрикс24.
Как хранятся данные пользователя в Битрикс
Ядро оперирует двумя независимыми сущностями: пользователь (b_user) и покупатель (b_sale_person_type + b_sale_order_user). При анонимном заказе создаётся запись в b_sale_order с USER_ID = 0 и контактными данными в полях b_sale_order_props_value. При регистрации или авторизации заказы привязываются к конкретному USER_ID, но связь «гостевые заказы → зарегистрированный пользователь» не строится автоматически.
Дополнительно: если на проекте подключён модуль crm, каждый заказ через событие OnSaleOrderSaved создаёт или обновляет сущность CCrmContact и CCrmDeal. Дублирование на уровне b_user немедленно порождает дублирование контактов в CRM.
Механизм слияния профилей
Единый профиль строится через три компонента:
1. Идентификация по детерминированным полям. Email и телефон — основные ключи слияния. В таблице b_user поля EMAIL и PERSONAL_PHONE должны быть уникальными (индекс UQ_USER_EMAIL). Проблема в том, что по умолчанию Битрикс не запрещает двух пользователей с одинаковым телефоном, если тот хранится в пользовательских свойствах через b_user_field.
2. Слияние через API пользователей. При обнаружении дубля вызывается CUser::Merge() — метод переносит все заказы, подписки, бонусные баллы на мастер-аккаунт и деактивирует дубль. Важно предварительно проверить зависимые таблицы: b_sale_order, b_sale_fuser, b_rating_vote, b_forum_user, b_subscribe_subscriber.
// Слияние: все данные дубля переходят к мастер-пользователю
$result = CUser::Merge($masterUserId, $duplicateUserId);
if (!$result) {
// Логируем причину — чаще всего конфликт полей UNIQUE в b_user
$GLOBALS['APPLICATION']->GetException();
}
3. Таблица b_sale_fuser (fake user). Это ключевая таблица для анонимных сессий. Каждый гость получает запись в b_sale_fuser с USER_ID = NULL. При авторизации метод CSaleUser::DoAutoLogin() должен связать FUSER_ID с реальным USER_ID. Если этот шаг пропущен — корзина и незавершённые заказы остаются «подвешенными» и не попадают в профиль.
Пользовательские поля как источник проблем
Дополнительные атрибуты клиента (дата рождения, пол, предпочтения) хранятся в b_uts_user — автоматически создаваемая таблица для пользовательских полей (UserTypeEntity с ENTITY_ID = 'USER'). При слиянии CUser::Merge() эти данные не переносятся автоматически — метод копирует только поля основной таблицы b_user. Нужно вручную перенести значения из b_uts_user до вызова слияния.
Привязка гостевых действий после авторизации
Стандартный обработчик OnAfterUserAuthorize срабатывает при каждом входе. В нём удобно реализовать:
AddEventHandler('main', 'OnAfterUserAuthorize', function($fields) {
if ($fields['USER_ID'] > 0) {
// Переносим корзину гостя на авторизованного пользователя
$fuserId = CSaleUser::GetAnonymousUserID();
CSaleBasket::TransferBasket($fuserId, $fields['USER_ID']);
// Привязываем просмотры истории (b_catalog_viewed)
// Переносим отложенные товары (b_sale_basket с LID = 'Y')
}
});
Что настраиваем
- Аудит таблицы
b_userна дубли по email и телефону с поиском черезGROUP BY+HAVING COUNT(*) > 1 - Скрипт дедупликации с приоритезацией мастер-аккаунта (по дате регистрации или количеству заказов)
- Перенос данных из
b_uts_user,b_sale_order,b_sale_fuserпри слиянии - Обработчик
OnAfterUserAuthorizeдля связывания гостевых действий с профилем - Настройка уникальных индексов на телефон, если он хранится в
b_user_field - Интеграция с CRM: дедупликация
CCrmContactпоPHONEчерезCCrmContactHelper::FindDuplicate()







