Integration of 1C-Bitrix with Comagic

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

1C-Bitrix Integration with CoMagic

CoMagic is a Russian end-to-end analytics and call tracking platform. Architecturally it differs from Callibri through a more granular session model: each visit is broken down into touchpoints, and the full interaction chain leading to a conversion is available via the API. For Bitrix integration this means the ability to pass not just utm_source to a deal, but the complete customer journey. The second key component is outbound calls via CoMagic SIP telephony directly from the CRM record.

What We Integrate

The standard scope for a complete integration:

  1. CoMagic webhook → create a lead in Bitrix CRM on a targeted call
  2. Pass visitor_id from the CoMagic cookie when submitting forms
  3. CoMagic Data API → enrich the lead with session data
  4. Click-to-call widget in Bitrix CRM (outbound call via CoMagic SIP)

CoMagic API: Authorization and Basic Calls

CoMagic uses JSON-RPC 2.0 over HTTPS. Authorization is via login/password; the response returns an access_token.

namespace Local\CoMagic;

class ApiClient
{
    private string $baseUrl = 'https://dataapi.comagic.ru/v2.0';
    private ?string $accessToken = null;
    private string $login;
    private string $password;

    public function __construct(string $login, string $password)
    {
        $this->login    = $login;
        $this->password = $password;
    }

    public function call(string $method, array $params = []): array
    {
        if (!$this->accessToken) {
            $this->authenticate();
        }

        $payload = [
            'jsonrpc' => '2.0',
            'id'      => uniqid('cm_', true),
            'method'  => $method,
            'params'  => array_merge(['access_token' => $this->accessToken], $params),
        ];

        $ch = curl_init($this->baseUrl);
        curl_setopt_array($ch, [
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => json_encode($payload),
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
            CURLOPT_TIMEOUT        => 10,
        ]);

        $response = json_decode(curl_exec($ch), true);
        curl_close($ch);

        if (isset($response['error'])) {
            throw new \RuntimeException('CoMagic API error: ' . $response['error']['message']);
        }

        return $response['result'] ?? [];
    }

    private function authenticate(): void
    {
        $payload = [
            'jsonrpc' => '2.0',
            'id'      => 'auth',
            'method'  => 'login.user',
            'params'  => ['login' => $this->login, 'password' => $this->password],
        ];

        $ch = curl_init($this->baseUrl);
        curl_setopt_array($ch, [
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => json_encode($payload),
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        ]);

        $result = json_decode(curl_exec($ch), true);
        curl_close($ch);

        $this->accessToken = $result['result']['data']['access_token']
            ?? throw new \RuntimeException('CoMagic auth failed');
    }
}

Webhook: Handling an Inbound Call

CoMagic supports event notifications via a callback URL. In settings: Integrations → Webhook. Event type — call_session_completed.

// /local/api/comagic-webhook.php
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');

$data = json_decode(file_get_contents('php://input'), true);

// CoMagic signs the payload via HMAC-SHA256
$signature = $_SERVER['HTTP_X_COMAGIC_SIGNATURE'] ?? '';
$secret    = \Bitrix\Main\Config\Option::get('local.comagic', 'webhook_secret');
$expected  = hash_hmac('sha256', file_get_contents('php://input'), $secret);

if (!hash_equals($expected, $signature)) {
    http_response_code(403);
    exit;
}

$event = $data['event_type'] ?? '';

if ($event === 'call_session_completed') {
    $processor = new \Local\CoMagic\CallProcessor();
    $processor->handle($data['call_session']);
}

http_response_code(200);

Call Handler: Creating/Updating a Lead

namespace Local\CoMagic;

class CallProcessor
{
    public function handle(array $session): void
    {
        // Only create leads for targeted calls
        if (($session['is_lost_call'] ?? false) && ($session['duration_total'] ?? 0) < 10) {
            return;
        }

        $phone = $this->normalizePhone($session['visitor_phone_number'] ?? '');
        if (!$phone) {
            return;
        }

        $existingLeadId = $this->findRecentLead($phone);

        $fields = [
            'TITLE'           => 'CoMagic call: ' . $phone,
            'PHONE'           => [['VALUE' => $phone, 'VALUE_TYPE' => 'WORK']],
            'SOURCE_ID'       => 'CALL',
            'STATUS_ID'       => 'NEW',
            'UF_COMAGIC_ID'   => (string)($session['id'] ?? ''),
            'UF_UTM_SOURCE'   => $session['utm_source'] ?? '',
            'UF_UTM_MEDIUM'   => $session['utm_medium'] ?? '',
            'UF_UTM_CAMPAIGN' => $session['utm_campaign'] ?? '',
            'UF_UTM_CONTENT'  => $session['utm_content'] ?? '',
            'UF_UTM_TERM'     => $session['utm_term'] ?? '',
            'COMMENTS'        => $this->buildComment($session),
        ];

        $lead = new \CCrmLead(false);

        if ($existingLeadId) {
            $lead->Update($existingLeadId, $fields, true);
        } else {
            $lead->Add($fields, true);
        }
    }

    private function buildComment(array $session): string
    {
        return implode("\n", [
            'CoMagic Session ID: ' . ($session['id'] ?? ''),
            'Operator: ' . ($session['employee_full_name'] ?? '—'),
            'Duration: ' . ($session['duration_total'] ?? 0) . ' sec.',
            'Traffic type: ' . ($session['traffic_type'] ?? '—'),
            'Entry page: ' . ($session['site_domain_url'] ?? '—'),
            'Tags: ' . implode(', ', $session['tags'] ?? []),
        ]);
    }
}

Fetching Visit Data by visitor_id

CoMagic sets a comagic_visitor cookie containing the visit identifier. This allows the server to query full session data — pages visited, channels, time on site.

// Server-side lead enricher with CoMagic session data
class VisitorEnricher
{
    private ApiClient $api;

    public function enrichLead(int $leadId, string $visitorId): void
    {
        try {
            $result = $this->api->call('visitors.get_visitor_info', [
                'visitor_id' => $visitorId,
                'date_from'  => date('Y-m-d', strtotime('-1 day')),
                'date_till'  => date('Y-m-d'),
            ]);

            $visitor = $result['data'][0] ?? null;
            if (!$visitor) {
                return;
            }

            $updateFields = [
                'UF_CM_VISITOR_ID'     => $visitorId,
                'UF_CM_SESSION_COUNT'  => (int)($visitor['sessions_count'] ?? 0),
                'UF_CM_FIRST_SOURCE'   => $visitor['first_session']['utm_source'] ?? '',
                'UF_CM_LAST_SOURCE'    => $visitor['last_session']['utm_source'] ?? '',
            ];

            $lead = new \CCrmLead(false);
            $lead->Update($leadId, $updateFields, true);

        } catch (\RuntimeException $e) {
            \CEventLog::Add([
                'SEVERITY'      => 'WARNING',
                'AUDIT_TYPE_ID' => 'COMAGIC_ENRICH_FAIL',
                'MODULE_ID'     => 'local.comagic',
                'DESCRIPTION'   => $e->getMessage(),
            ]);
        }
    }
}

Click-to-Call from the CRM Record

CoMagic SIP allows initiating an outbound call via API. In Bitrix, this is implemented through a custom UI handler in the lead/deal record.

// REST handler for AJAX requests from the CRM record
public function initiateCall(int $leadId, string $operatorLogin): array
{
    $lead   = \CCrmLead::GetByID($leadId);
    $phones = \CCrmFieldMulti::GetList(
        [],
        ['ENTITY_ID' => 'LEAD', 'ELEMENT_ID' => $leadId, 'TYPE_ID' => 'PHONE']
    );

    $phoneRow = $phones->Fetch();
    if (!$phoneRow) {
        return ['success' => false, 'error' => 'No phone'];
    }

    $result = $this->api->call('calls.make_call', [
        'virtual_phone_number' => \Bitrix\Main\Config\Option::get('local.comagic', 'virtual_number'),
        'operator_login'       => $operatorLogin,
        'destination_number'   => $phoneRow['VALUE'],
    ]);

    return ['success' => true, 'call_id' => $result['data']['call_session_id'] ?? null];
}

Custom Fields Reference

Code Attached to Type Source
UF_COMAGIC_ID Lead string Webhook
UF_CM_VISITOR_ID Lead string Cookie
UF_CM_SESSION_COUNT Lead integer Data API
UF_CM_FIRST_SOURCE Lead string Data API
UF_CM_LAST_SOURCE Lead string Data API
UF_UTM_SOURCE..TERM Lead, Deal string Webhook / API

Scope of Work

  • Module local.comagic: API client, event processors, logger
  • Webhook endpoint with HMAC signature verification
  • Lead creation/update in CRM from calls and chats
  • JS form interception to pass visitor_id
  • Server-side session data enrichment via Data API
  • (Optional) Click-to-call from the CRM record
  • Dashboard: "CoMagic" tab in the lead record with touchpoint history

Timelines: basic integration (webhook → lead + UTM) — 1–2 weeks. Full multi-touch attribution, click-to-call, and data dashboard — 4–6 weeks.