
При работе с Bitrix24 понадобилось сохранить адрес из Google Maps в стандартное поле Address у лида. Не просто строку, а полноценный адрес: с координатами, разбивкой на части и корректной работой всей CRM-логики.
REST API рассматривался первым, но быстро стало ясно, что в этом сценарии неудобен. Нужно было переносить адрес между сущностями Bitrix24, сохраняя связи с модулем location. REST такого контроля не даёт.
При этом в Bitrix24 уже есть стандартное поле address, связанное с Google Maps и модулем location. Оно умеет хранить координаты и структуру адреса, но в документации нет описания, как правильно заполнять его через код.
В статье разберу практический кейс: как сохранить адрес из Google Geocode во внутренние сущности Bitrix24 без REST API и без пользовательского интерфейса.
Почему стандартное поле Address сложно заполнить из кода
На первый взгляд поле Address в Bitrix24 выглядит готовым к использованию. Оно уже связано с Google Maps, умеет хранить координаты и красиво отображается в интерфейсе.
Но стоит попробовать заполнить его из кода, и начинаются сюрпризы. Простая запись текстового значения даёт только визуальный эффект. Адрес показывается, но связи с модулем location нет. Координаты не сохраняются. Структура адреса разваливается. Внутренние связи либо отсутствуют, либо выглядят странно.
Дело в том, что Address — это не одно поле. Это набор связанных сущностей и таблиц. Если заполнить их не полностью или не в том порядке, адрес перестаёт быть «живым». Он не участвует в логике CRM, его нельзя безопасно переносить между сущностями и использовать повторно.
При этом официальная документация никак не помогает. Там просто нет описания, каки�� сущности трогать и в какой последовательности, если нужен полноценный адрес, а не просто текст.
Как на самом деле хранится адрес в Bitrix24
Поле Address — это связка нескольких сущностей. При корректном сохранении они выглядят примерно так:

b_location— хранитexternalIdиз Google Geocode и координатыb_location_address— основная сущность адресаb_location_addr_fld— разбивка адреса на частиb_location_addr_link— связь адреса с сущностьюb_crm_addr— связь адреса с CRM
Если не создать все эти записи, поле Address работает только наполовину. Простая запись строки не создаёт адрес в понимании Bitrix24.
Что нужно получить в итоге
С самого начала было важно понять, какой результат считается правильным. Речь шла не просто о заполненном поле, а о полноценной интеграции с модулем location и CRM-логикой.
В итоге адрес должен:
хранить
latitudeиlongitudeиз Google Geocodeбыть связан с локацией и её родителями
иметь разбивку на компоненты
спокойно переноситься между сущностями Bitrix24
работать как стандартное поле
Addressв карточке лида
И важный момент: после сохранения адрес должен без ограничений редактироваться через интерфейс, так же, как если бы его ввёл пользователь вручную.
Какие сущности участвуют в сохранении адреса
Для этого используется внутреннее API модулей location и CRM. По факту задействованы три ключевые сущности.
1. Bitrix\Location\Entity\Location
Location хранит информацию о самой локации. Здесь лежат источник данных, внешний идентификатор, координаты и тип.
При работе с Google Maps сюда передаются:
externalIdиз Google Geocodeисточник (
GOOGLE)тип локации
координаты
язык
Пример инициализации:
$location = (new Location())
->setExternalId(...)
->setLatitude(...)
->setLongitude(...);2. Разбивка адреса на части (fieldsCollection)
Компоненты адреса Bitrix24 хранит в виде числовых типов. Их нужно маппить вручную.
Пример соответствия компонентов Google и типов Bitrix24:
protected const LOCATION_FIELD_MAP = [
'postal_code' => 50,
'country' => 100,
'administrative_area_level_1' => 200,
'administrative_area_level_2' => 210,
'locality' => 310,
'route' => 340,
'street_number' => 400,
'full_address' => 410,
];
$location->setFieldValue($itemType, $itemValue);Эти данные попадают в таблицу b_location_addr_fld и формируют структурированный адрес.
3. Bitrix\Location\Entity\Address
Address связывает локацию, координаты и компоненты адреса. Именно эта сущность делает адрес полноценным.
При создании:
задаются координаты
указывается
Locationзаполняются компоненты
создаётся связь с CRM
Пример:
$address = (new Address())
->setLatitude(...)
->setLongitude(...)
->setLocation(...);
$address->addLink('1.1.' . $leadId, 'CRM_LEAD_ADDRESS');
foreach ($fieldCollection as $itemType => $itemValue) {
$address->setFieldValue($itemType, $itemValue);
}4. CRM-сущность \Bitrix\Crm\EntityAddress
На финальном шаге адрес регистрируется в CRM и привязывается к лиду.
$addressFields = [
'ADDRESS_1' => $parts['address1'],
'ADDRESS_2' => $parts['address2'],
'CITY' => $parts['city'],
'REGION' => $parts['state'],
'PROVINCE' => $parts['province'],
'POSTAL_CODE' => $parts['zip'],
'COUNTRY' => $parts['country'],
'COUNTRY_CODE' => $parts['country_code'],
'LOC_ADDR_ID' => $address->getId(),
];
\Bitrix\Crm\EntityAddress::register(
\CCrmOwnerType::Lead,
$leadId,
\Bitrix\Crm\EntityAddressType::Primary,
$addressFields
);Адрес считается сохранённым корректно только после этого шага. Если его пропустить, CRM просто не увидит адрес.
Полный пример кода лежит здесь: https://github.com/RogSC/bitrix-address-api
Получение данных из Google Geocode
Для координат и компонентов используется Google Geocode API. Важно, чтобы данные легко ложились в модель Bitrix24.
Здесь используется серверный ключ, который уже настроен в модуле location Bitrix24. Это избавляет от дублирования конфигурации.
Получение API-ключа
function getApiKey(): string
{
$sourceService = \Bitrix\Location\Service\SourceService::getInstance();
$source = $sourceService->getSource();
$config = $source->getConfig();
return $config->getValue('API_KEY_BACKEND');
}Используется тот же ключ, что и в интерфейсе CRM.
Вызов Google Geocode API
const URL = 'https://geocode.googleapis.com/v4beta/geocode/address/';
$httpClient = new \Bitrix\Main\Web\HttpClient([
'version' => '1.1',
'socketTimeout' => 30,
'streamTimeout' => 30,
'redirect' => true,
'redirectMax' => 5,
]);
$httpClient
->setHeader('Referer', 'https://crm.example.com/')
->setHeader('Content-Type', 'application/json')
->setHeader('X-Goog-Api-Key', getApiKey());
function geocodeAddress(string $address): array
{
$url = self::URL . urlencode($address);
$response = $httpClient->get($url);
return Json::decode($response);
}На выходе — координаты, placeId и компоненты адреса.
Последовательность сохранения адреса
Порядок здесь критичен. Если его нарушить, связи ломаются.
Общая схема такая:
Создать
LocationЗаписать компоненты адреса
Создать
AddressЗарегистрировать адрес в CRM
Шаг 1. Location
$location = (new Location())
->setExternalId((string)$data['externalId'])
->setSourceCode('GOOGLE')
->setType(Location\Type::ADDRESS_LINE_1)
->setName($data['name'])
->setLanguageId('en')
->setLatitude($data['latitude'])
->setLongitude($data['longitude']);Шаг 2. Компоненты адреса
foreach ($fieldCollection as $itemType => $itemValue) {
$location->setFieldValue($itemType, $itemValue);
}
$location->save();Шаг 3. Address
$address = (new Address('en')) //languageId
->setLatitude($parts['lat'])
->setLongitude($parts['lon'])
->setLocation($location);
$address->addLink('1.1.' . $leadId, 'CRM_LEAD_ADDRESS');
foreach ($fieldCollection as $itemType => $itemValue) {
$address->setFieldValue($itemType, $itemValue);
}
$address->save();Шаг 4. Регистрация в CRM
\EntityAddress::register(
\CCrmOwnerType::Lead,
$leadId,
\Bitrix\Crm\EntityAddressType::Primary,
[
'ADDRESS_1' => $parts['address1'],
'ADDRESS_2' => $parts['address2'],
'CITY' => $parts['city'],
'REGION' => $parts['state'],
'PROVINCE' => $parts['province'],
'POSTAL_CODE' => $parts['zip'],
'COUNTRY' => $parts['country'],
'COUNTRY_CODE' => $parts['country_code'],
'LOC_ADDR_ID' => $address->getId(),
]
);После этого адрес полностью работает в CRM.
Проверка результата
Проверить всё можно двумя способами: в базе и в интерфейсе.
b_location
Там появляется запись с EXTERNAL_ID, источником GOOGLE и координатами.
b_location_addr_fld
Здесь видно, что адрес реально разложен по частям, а не хранится одной строкой.
Связи с CRM
В b_crm_addr появляется связь с CRM-сущностью и LOC_ADDR_ID.
Карточка лида
В интерфейсе адрес выглядит как обычное поле Address. Его можно редактировать, Google Maps работает как обычно.

Подводные камни
Есть несколько моментов, о которых лучше знать заранее.
Зависимость от внутреннего API
Сущности не публичные. Обновления Bitrix24 могут что-то сломать.
Порядок важен
Нарушил последовательность — потерял связи.
Типы полей (b_location_addr_fld)
Ошибся в маппинге — адрес выглядит нормально, но структура не сохраняется.
ЯзыкlanguageId влияет на нормализацию адреса.
Google API
Следи за лимитами, особенно при массовой обработке.
Итоги
Поле Address в Bitrix24 — это не текст, а набор связанных сущностей. Чтобы заполнить его корректно, нужно работать с внутренним API и соблюдать порядок действий.
Этот подход позволяет сохранить адрес из Google Geocode полностью: с координатами, структурой и рабочей интеграцией с CRM. Адрес ведёт себя так же, как введённый вручную.
Решение не использует REST API и оправдано в сценариях, где важно сохранить все связи и переносить адреса между сущностями. Для простых задач REST может быть проще.
Код с минимальной реализацией лежит в репозитории: https://github.com/RogSC/bitrix-address-api
