Как связать контакт и сделку со сквозной аналитикой

Scope: crm

Кто может выполнять методы:

  • для создания контакта и сделки — пользователь с правом добавлять эти объекты CRM
  • для связи сделки с контактом через contactIds — пользователь с правом читать этот контакт
  • для привязки трейса — пользователь с правом изменять созданные контакт и сделку

Выберите инструмент для разработки с AI-агентом:

  • используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
  • используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации

Сквозная аналитика связывает обращение клиента с источником перехода и посещенными страницами сайта. Эти данные хранятся в трейсе — JSON-строке, которую формирует скрипт сквозной аналитики Битрикс24.

В примере посетитель отправляет форму обратной связи. В результате в CRM сохраняются контакт, связанная с ним сделка и данные о пути клиента до обращения.

Сценарий состоит из четырех шагов.

  1. Получить трейс посетителя функцией b24Tracker.guest.getTrace()
  2. Создать контакт методом crm.item.add
  3. Создать сделку тем же методом и связать ее с контактом
  4. Привязать контакт и сделку к трейсу методом crm.tracking.trace.add

Форма на сайте публичная, поэтому вызовы REST выполняются на стороне сервера, а не в браузере: вебхук с правами на CRM нельзя раскрывать в клиентском коде. Браузер только собирает данные формы и трейс и отправляет их на бэкенд обычным POST-запросом. Бэкенд вызывает методы Битрикс24 через SDK:

Подготовьте форму и сквозную аналитику

Для выполнения примера:

  1. Создайте на внешнем сервере обработчик формы на JS, PHP или Python
  2. Установите SDK для выбранного языка: @bitrix24/b24jssdk, bitrix24/b24phpsdk или b24pysdk. Для B24PhpSDK 3.x нужен PHP 8.4 или 8.5
  3. Создайте входящий вебхук со scope crm от имени пользователя с нужными правами
  4. Установите скрипт сквозной аналитики, сформированный Битрикс24, перед закрывающим тегом </body> на всех страницах, где нужно собирать маршрут посетителя, включая страницу формы. После загрузки скрипта на странице должна быть доступна функция b24Tracker.guest.getTrace()

Для серверных JS-примеров с B24Hook нужен Node.js 20 либо 22 и выше. B24JsSDK — ES module: сохраните код в файле .mjs или добавьте "type": "module" в package.json. Эти требования не относятся к браузерному скрипту с b24Tracker.

Для примеров с b24pysdk нужен Python 3.9 или новее.

1. Получите трейс посетителя

Добавьте в форму скрытое поле TRACE. Перед отправкой формы вызовите b24Tracker.guest.getTrace() и сохраните результат в этом поле.

Функция возвращает JSON-строку и очищает накопленный трейс после чтения. Вызывайте ее один раз непосредственно перед отправкой формы.

Как использовать примеры в документации

<form id="feedback-form" method="post">
            <input type="hidden" id="form-trace" name="TRACE">
            <!-- поля формы -->
            <button type="submit">Отправить</button>
        </form>
        
        <p id="message" aria-live="polite"></p>
        
        <script>
            const form = document.getElementById('feedback-form');
            const traceInput = document.getElementById('form-trace');
            const message = document.getElementById('message');
        
            form.addEventListener('submit', function(event) {
                const tracker = window.b24Tracker && window.b24Tracker.guest;
        
                if (!tracker || typeof tracker.getTrace !== 'function') {
                    event.preventDefault();
                    message.textContent = 'Не удалось получить данные сквозной аналитики';
                    return;
                }
        
                const trace = tracker.getTrace();
        
                if (!trace) {
                    event.preventDefault();
                    message.textContent = 'Трейс сквозной аналитики пуст';
                    return;
                }
        
                traceInput.value = trace;
            });
        </script>
        

Если скрипт сквозной аналитики не загружен или не вернул трейс, пример отменяет отправку формы. Это предотвращает создание контакта и сделки без данных аналитики.

2. Создайте контакт

Вызовите crm.item.add с entityTypeId = 3 — это идентификатор типа объекта Контакт.

Передайте в fields:

  • name — имя из формы
  • lastName — фамилию из формы
  • fm — телефон контакта

Поле fm передайте массивом, потому что телефон в CRM хранится как множественное поле типа crm_multifield. Для телефона укажите:

  • typeId — тип множественного поля PHONE
  • valueType — тип значения, например WORK
  • value — номер телефона

Проверьте, какие обязательные поля настроены для контактов и сделок в вашем Битрикс24. Все обязательные поля нужно передать в соответствующий вызов crm.item.add.

// npm install @bitrix24/b24jssdk
        import { B24Hook } from '@bitrix24/b24jssdk'
        
        const $b24 = B24Hook.fromWebhookUrl('https://your-domain.bitrix24.ru/rest/1/xxxxxxxxxxxxxxxx/')
        
        // name, lastName, phone приходят из данных формы
        const contactResponse = await $b24.actions.v2.call.make({
            method: 'crm.item.add',
            params: {
                entityTypeId: 3,
                fields: {
                    name: name,
                    lastName: lastName,
                    fm: [
                        { typeId: 'PHONE', valueType: 'WORK', value: phone },
                    ],
                },
            },
            requestId: 'contact-add',
        })
        
        if (!contactResponse.isSuccess) {
            throw new Error(contactResponse.getErrorMessages().join('; '))
        }
        
        const contactId = contactResponse.getData().result.item.id
        
<?php
        // composer require bitrix24/b24phpsdk:"^3.0"
        require_once 'vendor/autoload.php';
        
        use Bitrix24\SDK\Services\ServiceBuilderFactory;
        
        $webhookUrl = 'https://your-domain.bitrix24.ru/rest/1/xxxxxxxxxxxxxxxx/';
        $b24 = ServiceBuilderFactory::createServiceBuilderFromWebhook($webhookUrl);
        
        // $name, $lastName, $phone приходят из данных формы
        $contactId = $b24->getCRMScope()->item()->add(3, [
            'name' => $name,
            'lastName' => $lastName,
            'fm' => [
                ['typeId' => 'PHONE', 'valueType' => 'WORK', 'value' => $phone],
            ],
        ])->item()->id;
        
# pip install b24pysdk
        from b24pysdk import Client, BitrixWebhook
        
        client = Client(BitrixWebhook(
            domain="your-domain.bitrix24.ru",
            webhook_token="1/xxxxxxxxxxxxxxxx",
        ))
        
        # name, last_name, phone приходят из данных формы
        bitrix_response = client.crm.item.add(
            fields={
                "name": name,
                "lastName": last_name,
                "fm": [
                    {"typeId": "PHONE", "valueType": "WORK", "value": phone},
                ],
            },
            entity_type_id=3,
        ).response
        contact_id = bitrix_response.result["item"]["id"]
        

Сокращенный ответ:

{
            "result": {
                "item": {
                    "id": 101
                }
            }
        }
        

Сохраните result.item.id. Идентификатор контакта понадобится для создания сделки и привязки трейса.

3. Создайте сделку и свяжите ее с контактом

Снова вызовите crm.item.add. Для сделки передайте entityTypeId = 2.

В поле contactIds передайте массив идентификаторов связанных контактов. В этом сценарии массив содержит contactId, полученный на предыдущем шаге.

const dealResponse = await $b24.actions.v2.call.make({
            method: 'crm.item.add',
            params: {
                entityTypeId: 2,
                fields: {
                    title: `Обращение с сайта: ${name} ${lastName}`,
                    contactIds: [contactId],
                },
            },
            requestId: 'deal-add',
        })
        
        if (!dealResponse.isSuccess) {
            throw new Error(dealResponse.getErrorMessages().join('; '))
        }
        
        const dealId = dealResponse.getData().result.item.id
        
$dealId = $b24->getCRMScope()->item()->add(2, [
            'title' => 'Обращение с сайта: ' . $name . ' ' . $lastName,
            'contactIds' => [$contactId],
        ])->item()->id;
        
bitrix_response = client.crm.item.add(
            fields={
                "title": "Обращение с сайта: %s %s" % (name, last_name),
                "contactIds": [contact_id],
            },
            entity_type_id=2,
        ).response
        deal_id = bitrix_response.result["item"]["id"]
        

Ответ имеет ту же структуру, что и при создании контакта. Сохраните result.item.id сделки. Теперь есть два идентификатора для параметра ENTITIES: contactId и dealId.

4. Привяжите объекты к трейсу

После создания контакта и сделки вызовите crm.tracking.trace.add, потому что TRACE нельзя передать напрямую в crm.item.add.

В fields метода crm.item.add можно передать UTM-поля: utmSource, utmMedium, utmCampaign, utmContent, utmTerm. Они сохраняют рекламные метки в объекте CRM, но не заменяют полный трейс с маршрутом посещения сайта.

В crm.tracking.trace.add передайте:

  • TRACE — JSON-строку из скрытого поля формы
  • ENTITIES — контакт с типом CONTACT и сделку с типом DEAL
const traceResponse = await $b24.actions.v2.call.make({
            method: 'crm.tracking.trace.add',
            params: {
                TRACE: trace,
                ENTITIES: [
                    { TYPE: 'CONTACT', ID: contactId },
                    { TYPE: 'DEAL', ID: dealId },
                ],
            },
            requestId: 'trace-add',
        })
        
        if (!traceResponse.isSuccess) {
            throw new Error(traceResponse.getErrorMessages().join('; '))
        }
        
        const traceId = traceResponse.getData().result
        
// crm.tracking.* нет среди типизированных сервисов — вызываем через ядро
        $b24->core->call('crm.tracking.trace.add', [
            'TRACE' => $trace,
            'ENTITIES' => [
                ['TYPE' => 'CONTACT', 'ID' => $contactId],
                ['TYPE' => 'DEAL', 'ID' => $dealId],
            ],
        ]);
        
trace_id = client.crm.tracking.trace.add(
            trace=trace,
            entities=[
                {"TYPE": "CONTACT", "ID": contact_id},
                {"TYPE": "DEAL", "ID": deal_id},
            ],
        ).response.result
        

Метод вернет числовой идентификатор созданного трейса. Примеры на JS и Python сохраняют его в переменной. В PHP достаточно успешного выполнения вызова: ядро SDK выбросит исключение, если REST вернет ошибку.

{
            "result": 341
        }
        

Полный пример

Ниже собран полный код сценария для каждого SDK.

// npm install express @bitrix24/b24jssdk
        import express from 'express'
        import { B24Hook } from '@bitrix24/b24jssdk'
        
        const WEBHOOK = 'https://your-domain.bitrix24.ru/rest/1/xxxxxxxxxxxxxxxx/'
        const app = express()
        app.use(express.urlencoded({ extended: true }))
        
        const PAGE = `<!DOCTYPE html>
        <html lang="ru">
        <head>
            <meta charset="UTF-8">
            <title>Обратная связь</title>
        </head>
        <body>
            <h1>Обратная связь</h1>
            <p id="message" aria-live="polite">__MESSAGE__</p>
            <form id="feedback-form" method="post">
                <input type="hidden" id="form-trace" name="TRACE">
                <label>Имя <input type="text" name="NAME" required></label>
                <label>Фамилия <input type="text" name="LAST_NAME" required></label>
                <label>Телефон <input type="tel" name="PHONE" required></label>
                <button type="submit">Отправить</button>
            </form>
            <!-- На странице должен быть установлен скрипт сквозной аналитики Битрикс24 -->
            <script>
                const form = document.getElementById('feedback-form');
                const traceInput = document.getElementById('form-trace');
                const message = document.getElementById('message');
        
                form.addEventListener('submit', function(event) {
                    const tracker = window.b24Tracker && window.b24Tracker.guest;
                    if (!tracker || typeof tracker.getTrace !== 'function') {
                        event.preventDefault();
                        message.textContent = 'Не удалось получить данные сквозной аналитики';
                        return;
                    }
        
                    const trace = tracker.getTrace();
                    if (!trace) {
                        event.preventDefault();
                        message.textContent = 'Трейс сквозной аналитики пуст';
                        return;
                    }
        
                    traceInput.value = trace;
                });
            </script>
        </body>
        </html>`
        
        const HTML_ESCAPES = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#039;',
        }
        const escapeHtml = (value) => String(value).replace(/[&<>"']/g, (char) => HTML_ESCAPES[char])
        const formPage = (message = '') => PAGE.replace('__MESSAGE__', escapeHtml(message))
        
        app.get('/', (req, res) => res.send(formPage()))
        
        app.post('/', async (req, res) => {
            const { NAME = '', LAST_NAME = '', PHONE = '', TRACE = '' } = req.body
        
            if (!NAME.trim() || !LAST_NAME.trim() || !PHONE.trim()) {
                return res.send(formPage('Заполните имя, фамилию и телефон'))
            }
            if (!TRACE.trim()) {
                return res.send(formPage('Не удалось получить трейс сквозной аналитики'))
            }
            try {
                JSON.parse(TRACE)
            } catch {
                return res.send(formPage('Трейс сквозной аналитики содержит некорректный JSON'))
            }
        
            const $b24 = B24Hook.fromWebhookUrl(WEBHOOK)
            let contactId = 0
            let dealId = 0
        
            try {
                const contactResponse = await $b24.actions.v2.call.make({
                    method: 'crm.item.add',
                    params: {
                        entityTypeId: 3,
                        fields: {
                            name: NAME,
                            lastName: LAST_NAME,
                            fm: [{ typeId: 'PHONE', valueType: 'WORK', value: PHONE }],
                        },
                    },
                    requestId: 'contact-add',
                })
                if (!contactResponse.isSuccess) {
                    return res.send(formPage('Контакт не создан: ' + contactResponse.getErrorMessages().join('; ')))
                }
                contactId = contactResponse.getData().result.item.id
        
                const dealResponse = await $b24.actions.v2.call.make({
                    method: 'crm.item.add',
                    params: {
                        entityTypeId: 2,
                        fields: {
                            title: `Обращение с сайта: ${NAME} ${LAST_NAME}`,
                            contactIds: [contactId],
                        },
                    },
                    requestId: 'deal-add',
                })
                if (!dealResponse.isSuccess) {
                    return res.send(formPage(
                        'Контакт ' + contactId + ' создан, но сделка не создана: '
                        + dealResponse.getErrorMessages().join('; ')
                    ))
                }
                dealId = dealResponse.getData().result.item.id
        
                const traceResponse = await $b24.actions.v2.call.make({
                    method: 'crm.tracking.trace.add',
                    params: {
                        TRACE,
                        ENTITIES: [
                            { TYPE: 'CONTACT', ID: contactId },
                            { TYPE: 'DEAL', ID: dealId },
                        ],
                    },
                    requestId: 'trace-add',
                })
                if (!traceResponse.isSuccess) {
                    return res.send(formPage(
                        'Контакт ' + contactId + ' и сделка ' + dealId
                        + ' созданы, но трейс не привязан: '
                        + traceResponse.getErrorMessages().join('; ')
                    ))
                }
        
                const traceId = traceResponse.getData().result
                return res.send(formPage(
                    'Контакт ' + contactId + ', сделка ' + dealId
                    + ' и трейс ' + traceId + ' созданы'
                ))
            } catch (error) {
                if (dealId > 0) {
                    return res.send(formPage(
                        'Контакт ' + contactId + ' и сделка ' + dealId
                        + ' созданы, но трейс не привязан: ' + error.message
                    ))
                }
                if (contactId > 0) {
                    return res.send(formPage(
                        'Контакт ' + contactId + ' создан, но сделка не создана: ' + error.message
                    ))
                }
                return res.send(formPage('Контакт не создан: ' + error.message))
            } finally {
                $b24.destroy()
            }
        })
        
        app.listen(3000, () => console.log('http://localhost:3000'))
        
<?php
        // composer require bitrix24/b24phpsdk:"^3.0"
        require_once 'vendor/autoload.php';
        
        use Bitrix24\SDK\Services\ServiceBuilderFactory;
        
        $message = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $name = trim((string)($_POST['NAME'] ?? ''));
            $lastName = trim((string)($_POST['LAST_NAME'] ?? ''));
            $phone = trim((string)($_POST['PHONE'] ?? ''));
            $trace = trim((string)($_POST['TRACE'] ?? ''));
        
            if ($name === '' || $lastName === '' || $phone === '') {
                $message = 'Заполните имя, фамилию и телефон';
            } elseif ($trace === '') {
                $message = 'Не удалось получить трейс сквозной аналитики';
            } else {
                json_decode($trace, true);
                if (json_last_error() !== JSON_ERROR_NONE) {
                    $message = 'Трейс сквозной аналитики содержит некорректный JSON';
                } else {
                    $webhookUrl = 'https://your-domain.bitrix24.ru/rest/1/xxxxxxxxxxxxxxxx/';
                    $b24 = ServiceBuilderFactory::createServiceBuilderFromWebhook($webhookUrl);
        
                    $contactId = 0;
                    $dealId = 0;
        
                    try {
                        $contactId = $b24->getCRMScope()->item()->add(3, [
                            'name' => $name,
                            'lastName' => $lastName,
                            'fm' => [
                                ['typeId' => 'PHONE', 'valueType' => 'WORK', 'value' => $phone],
                            ],
                        ])->item()->id;
        
                        $dealId = $b24->getCRMScope()->item()->add(2, [
                            'title' => 'Обращение с сайта: ' . $name . ' ' . $lastName,
                            'contactIds' => [$contactId],
                        ])->item()->id;
        
                        // crm.tracking.* нет среди типизированных сервисов — вызываем через ядро
                        $b24->core->call('crm.tracking.trace.add', [
                            'TRACE' => $trace,
                            'ENTITIES' => [
                                ['TYPE' => 'CONTACT', 'ID' => $contactId],
                                ['TYPE' => 'DEAL', 'ID' => $dealId],
                            ],
                        ]);
        
                        $message = 'Контакт ' . $contactId . ' и сделка ' . $dealId
                            . ' созданы и связаны со сквозной аналитикой';
                    } catch (\Throwable $error) {
                        if ($dealId > 0) {
                            $message = 'Контакт ' . $contactId . ' и сделка ' . $dealId
                                . ' созданы, но трейс не привязан: ' . $error->getMessage();
                        } elseif ($contactId > 0) {
                            $message = 'Контакт ' . $contactId
                                . ' создан, но сделка не создана: ' . $error->getMessage();
                        } else {
                            $message = 'Контакт не создан: ' . $error->getMessage();
                        }
                    }
                }
            }
        }
        ?>
        <!DOCTYPE html>
        <html lang="ru">
        <head>
            <meta charset="UTF-8">
            <title>Обратная связь</title>
        </head>
        <body>
            <h1>Обратная связь</h1>
        
            <p id="message" aria-live="polite">
                <?= htmlspecialchars($message, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>
            </p>
        
            <form id="feedback-form" method="post">
                <input type="hidden" id="form-trace" name="TRACE">
                <label>Имя <input type="text" name="NAME" required></label>
                <label>Фамилия <input type="text" name="LAST_NAME" required></label>
                <label>Телефон <input type="tel" name="PHONE" required></label>
                <button type="submit">Отправить</button>
            </form>
        
            <!-- На странице должен быть установлен скрипт сквозной аналитики Битрикс24 -->
            <script>
                const form = document.getElementById('feedback-form');
                const traceInput = document.getElementById('form-trace');
                const message = document.getElementById('message');
        
                form.addEventListener('submit', function(event) {
                    const tracker = window.b24Tracker && window.b24Tracker.guest;
                    if (!tracker || typeof tracker.getTrace !== 'function') {
                        event.preventDefault();
                        message.textContent = 'Не удалось получить данные сквозной аналитики';
                        return;
                    }
        
                    const trace = tracker.getTrace();
                    if (!trace) {
                        event.preventDefault();
                        message.textContent = 'Трейс сквозной аналитики пуст';
                        return;
                    }
        
                    traceInput.value = trace;
                });
            </script>
        </body>
        </html>
        
# pip install b24pysdk flask
        import html
        import json
        
        from flask import Flask, request
        from b24pysdk import Client, BitrixWebhook
        
        WEBHOOK_DOMAIN = "your-domain.bitrix24.ru"
        WEBHOOK_TOKEN = "1/xxxxxxxxxxxxxxxx"
        
        app = Flask(__name__)
        client = Client(BitrixWebhook(
            domain=WEBHOOK_DOMAIN,
            webhook_token=WEBHOOK_TOKEN,
        ))
        
        PAGE = """<!DOCTYPE html>
        <html lang="ru">
        <head>
            <meta charset="UTF-8">
            <title>Обратная связь</title>
        </head>
        <body>
            <h1>Обратная связь</h1>
            <p id="message" aria-live="polite">%(message)s</p>
            <form id="feedback-form" method="post">
                <input type="hidden" id="form-trace" name="TRACE">
                <label>Имя <input type="text" name="NAME" required></label>
                <label>Фамилия <input type="text" name="LAST_NAME" required></label>
                <label>Телефон <input type="tel" name="PHONE" required></label>
                <button type="submit">Отправить</button>
            </form>
            <!-- На странице должен быть установлен скрипт сквозной аналитики Битрикс24 -->
            <script>
                const form = document.getElementById('feedback-form');
                const traceInput = document.getElementById('form-trace');
                const message = document.getElementById('message');
        
                form.addEventListener('submit', function(event) {
                    const tracker = window.b24Tracker && window.b24Tracker.guest;
                    if (!tracker || typeof tracker.getTrace !== 'function') {
                        event.preventDefault();
                        message.textContent = 'Не удалось получить данные сквозной аналитики';
                        return;
                    }
        
                    const trace = tracker.getTrace();
                    if (!trace) {
                        event.preventDefault();
                        message.textContent = 'Трейс сквозной аналитики пуст';
                        return;
                    }
        
                    traceInput.value = trace;
                });
            </script>
        </body>
        </html>"""
        
        
        def form_page(message: str = "") -> str:
            return PAGE % {"message": html.escape(message)}
        
        
        @app.get("/")
        def index():
            return form_page()
        
        
        @app.post("/")
        def submit():
            name = request.form.get("NAME", "").strip()
            last_name = request.form.get("LAST_NAME", "").strip()
            phone = request.form.get("PHONE", "").strip()
            trace = request.form.get("TRACE", "").strip()
        
            if not name or not last_name or not phone:
                return form_page("Заполните имя, фамилию и телефон")
            if not trace:
                return form_page("Не удалось получить трейс сквозной аналитики")
            try:
                json.loads(trace)
            except json.JSONDecodeError:
                return form_page("Трейс сквозной аналитики содержит некорректный JSON")
        
            contact_id = 0
            deal_id = 0
        
            try:
                bitrix_response = client.crm.item.add(
                    fields={
                        "name": name,
                        "lastName": last_name,
                        "fm": [
                            {"typeId": "PHONE", "valueType": "WORK", "value": phone},
                        ],
                    },
                    entity_type_id=3,
                ).response
                contact_id = bitrix_response.result["item"]["id"]
        
                bitrix_response = client.crm.item.add(
                    fields={
                        "title": "Обращение с сайта: %s %s" % (name, last_name),
                        "contactIds": [contact_id],
                    },
                    entity_type_id=2,
                ).response
                deal_id = bitrix_response.result["item"]["id"]
        
                trace_id = client.crm.tracking.trace.add(
                    trace=trace,
                    entities=[
                        {"TYPE": "CONTACT", "ID": contact_id},
                        {"TYPE": "DEAL", "ID": deal_id},
                    ],
                ).response.result
        
                return form_page(
                    "Контакт %s, сделка %s и трейс %s созданы"
                    % (contact_id, deal_id, trace_id)
                )
            except Exception as error:
                if deal_id:
                    return form_page(
                        "Контакт %s и сделка %s созданы, но трейс не привязан: %s"
                        % (contact_id, deal_id, error)
                    )
                if contact_id:
                    return form_page(
                        "Контакт %s создан, но сделка не создана: %s" % (contact_id, error)
                    )
                return form_page("Контакт не создан: %s" % error)
        
        
        if __name__ == "__main__":
            app.run(host="0.0.0.0", port=3000)
        

Проверим результат

  1. Откройте созданный контакт в CRM и проверьте имя, фамилию и телефон
  2. Откройте созданную сделку и проверьте, что в ней указан этот контакт
  3. Убедитесь, что сообщение страницы подтверждает привязку объектов к сквозной аналитике. Для JS и Python сообщение также содержит числовой идентификатор трейса

Если в сообщении указано, что сделка не создана или трейс не привязан, сценарий завершился частично. Проверьте уже созданные объекты перед повторным запуском сценария.

Обработка ошибок

Ошибки создания контакта и сделки

Метод crm.item.add возвращает код ошибки в поле error.

error Причина Что проверить
ACCESS_DENIED Нет права добавить контакт или сделку Права пользователя, от имени которого создан вебхук
CRM_FIELD_ERROR_REQUIRED Не заполнено обязательное поле Обязательные поля контакта или сделки
CRM_FIELD_ERROR_VALUE_NOT_VALID Значение или тип поля не прошли проверку Значения и типы полей контакта или сделки, для fm — структуру элементов массива
100 Неверный тип значения множественного поля fm Что fm передано массивом элементов

Ошибки привязки трейса

Для перечисленных ниже проверок параметров TRACE, ENTITIES и прав метод crm.tracking.trace.add возвращает код ERROR_CORE в поле error. Системные REST-ошибки могут иметь другие коды. Конкретная причина ошибки приходит в поле error_description.

error_description Причина Что проверить
Parameter `TRACE` required. Не передан трейс Загрузку скрипта сквозной аналитики и скрытое поле TRACE
Can not parse JSON in parameter `TRACE`. TRACE не является корректной JSON-строкой Результат b24Tracker.guest.getTrace()
Wrong TYPE in parameter `ENTITIES`. Allowed types: COMPANY,CONTACT,DEAL,LEAD,QUOTE Передан недопустимый тип объекта Значения TYPE в массиве ENTITIES
Wrong ID in parameter `ENTITIES`. Передан пустой, нечисловой или неположительный идентификатор объекта Значения ID в массиве ENTITIES
You have no access to entity `CONTACT` with ID `123`. Нет права изменить объект из ENTITIES Права пользователя на указанный объект

В последнем сообщении CONTACT и 123 приведены для примера. Метод подставляет фактические тип и идентификатор объекта.

Вызовы выполняются последовательно и не объединены в транзакцию. Если создание сделки или привязка трейса завершились с ошибкой, ранее созданные объекты сохранятся в CRM.

Что важно учитывать

  • повторная отправка формы создаст новые контакт и сделку
  • защищайте публичную форму от автоматических отправок, например с помощью CAPTCHA и ограничения частоты запросов

Продолжите изучение