Setting up automatic lead import from VK Ads to Bitrix24

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

Setting Up Automatic Lead Import from VK Ads into Bitrix24

VK Lead Ads is the primary lead generation tool on VKontakte for the B2C segment. Unlike Facebook, VK provides several mechanisms for receiving leads: webhooks via VK Callback API, a Leads API for polling, and direct integration through VK Mini Apps. For automatic lead delivery into Bitrix24, the webhook via Callback API is the optimal approach.

VK Callback API for lead forms

In the VKontakte community settings: "Management → API → Callback API" — add a server with the handler URL.

Server verification:

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

// Server confirmation
if ($data['type'] === 'confirmation') {
    echo VK_CONFIRMATION_STRING; // string from Callback API settings
    exit;
}

// Signature verification
if ($data['secret'] !== VK_CALLBACK_SECRET) {
    http_response_code(403);
    exit;
}

Processing a new lead (event lead_forms_new):

if ($data['type'] === 'lead_forms_new') {
    $lead = $data['object'];

    $leadId   = $lead['lead_id'];
    $formId   = $lead['form_id'];
    $groupId  = $lead['group_id'];
    $userId   = $lead['user_id'];
    $adId     = $lead['ad_id']       ?? '';
    $utmData  = $lead['utm']         ?? [];

    // Form field answers
    $answers = $lead['answers'] ?? [];
    $fields  = [];
    foreach ($answers as $answer) {
        $fields[$answer['key']] = $answer['answer'] ?? '';
    }

    // Create lead in Bitrix24
    $this->createBitrix24Lead($leadId, $formId, $fields, $utmData, $adId);

    echo 'ok'; // VK expects the string 'ok' in the response
    exit;
}

Retrieving full data via Leads API

The Callback API for lead forms delivers user answers directly in answers. To get data about the user themselves (name, phone from their profile, if permission was granted) — an additional VK API request is needed:

public function enrichLeadWithUserData(int $userId, string $accessToken): array
{
    $response = $this->vkApi->call('users.get', [
        'user_ids' => $userId,
        'fields'   => 'photo_100,city',
    ]);

    $user = $response['response'][0] ?? [];
    return [
        'first_name' => $user['first_name'] ?? '',
        'last_name'  => $user['last_name']  ?? '',
        'vk_profile' => "https://vk.com/id{$userId}",
    ];
}

Mapping VK Lead Forms fields to Bitrix24

VK uses standard keys for common fields: first, last, name, phone, email. Custom questions have arbitrary keys defined when the form was created.

public function createBitrix24Lead(
    string $vkLeadId,
    int    $formId,
    array  $fields,
    array  $utm,
    string $adId
): void {
    // Standard fields
    $name  = trim(($fields['first'] ?? '') . ' ' . ($fields['last'] ?? ''))
          ?: ($fields['name'] ?? 'VK Lead');
    $phone = $fields['phone'] ?? '';
    $email = $fields['email'] ?? '';

    $b24Fields = [
        'TITLE'             => 'VK Lead Ads: ' . date('d.m.Y H:i'),
        'NAME'              => $name,
        'PHONE'             => [['VALUE' => $phone, 'VALUE_TYPE' => 'MOBILE']],
        'EMAIL'             => [['VALUE' => $email, 'VALUE_TYPE' => 'WORK']],
        'SOURCE_ID'         => 'ADVERTISING',
        'SOURCE_DESCRIPTION' => 'VK Lead Ads',
        'UF_CRM_VK_LEAD_ID' => $vkLeadId,
        'UF_CRM_VK_FORM_ID' => $formId,
        'UF_CRM_VK_AD_ID'   => $adId,
        'UF_CRM_UTM_SOURCE'   => $utm['source']   ?? 'vk',
        'UF_CRM_UTM_CAMPAIGN' => $utm['campaign'] ?? '',
        'UF_CRM_UTM_MEDIUM'   => $utm['medium']   ?? 'cpc',
    ];

    // Custom form fields — added as a comment
    $customFields = array_diff_key($fields, array_flip(['first','last','name','phone','email']));
    if (!empty($customFields)) {
        $b24Fields['COMMENTS'] = implode("\n", array_map(
            fn($k, $v) => "{$k}: {$v}",
            array_keys($customFields),
            array_values($customFields)
        ));
    }

    $this->b24->call('crm.lead.add', [
        'FIELDS' => $b24Fields,
        'PARAMS' => ['REGISTER_SONET_EVENT' => 'Y'],
    ]);
}

Multiple communities and forms

If a company manages several VKontakte communities or uses multiple lead forms for different products, each group_id and form_id can be mapped to a specific pipeline and responsible manager in Bitrix24:

$routingConfig = [
    ['group_id' => 123456, 'form_id' => 111, 'pipeline_id' => 1, 'assigned_by' => 5],
    ['group_id' => 123456, 'form_id' => 222, 'pipeline_id' => 3, 'assigned_by' => 8],
    ['group_id' => 789012, 'form_id' => 333, 'pipeline_id' => 2, 'assigned_by' => 11],
];

The configuration is stored in a table or JSON file and can be updated without a deployment.

Deduplication and phone-based verification

VKontakte users sometimes submit the same form multiple times. Deduplication is based on vk_lead_id (unique VK ID), which is stored in a custom field. Before creating a lead:

$existing = $this->b24->call('crm.lead.list', [
    'filter' => ['UF_CRM_VK_LEAD_ID' => $vkLeadId],
]);
if (!empty($existing)) return; // already created

Scope of work

  • Callback API setup in the VKontakte community
  • Handler development: verification, field mapping, lead creation
  • Custom fields in Bitrix24 for VK attributes
  • Routing config for multiple communities/forms
  • Deduplication by vk_lead_id and phone
  • Error logging, webhook delivery monitoring

Timeline: 3–5 days for a single community. Up to 2 weeks with complex routing and multiple forms.