Setting up automatic lead import from Facebook 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 Facebook Ads into Bitrix24

Facebook Lead Ads is one of the primary lead generation channels for B2C. Completed forms stay in Facebook Lead Center or can be exported via Webhook, but they do not automatically appear in the CRM. Manual CSV export once a day means lost response speed — and response speed matters: according to LeadResponseManagement research, the odds of reaching a lead drop tenfold after 5 minutes.

Technical mechanism

Facebook provides Lead Gen Webhooks — real-time push notifications for new leads. This is the preferred approach: latency is no more than 1–2 seconds from the moment the form is submitted.

Webhook setup:

  1. In Facebook Developers, create an app and add leads_retrieval and pages_manage_metadata permissions
  2. In the webhook settings, provide the URL and Verify Token
  3. Subscribe to the leadgen event for the target page

Facebook webhook verification (GET request):

// Initial endpoint verification
if ($_GET['hub_mode'] === 'subscribe' &&
    $_GET['hub_verify_token'] === FB_VERIFY_TOKEN) {
    echo $_GET['hub_challenge'];
    exit;
}

Processing an incoming lead (POST request):

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

// Signature verification
$signature = 'sha256=' . hash_hmac('sha256',
    file_get_contents('php://input'),
    FB_APP_SECRET
);
if ($signature !== $_SERVER['HTTP_X_HUB_SIGNATURE_256']) {
    http_response_code(403);
    exit;
}

foreach ($payload['entry'] as $entry) {
    foreach ($entry['changes'] as $change) {
        if ($change['field'] === 'leadgen') {
            $leadgenId = $change['value']['leadgen_id'];
            $formId    = $change['value']['form_id'];
            $adId      = $change['value']['ad_id'];
            $campaignId = $change['value']['campaign_id'];

            // Retrieve full lead data via Graph API
            $leadData = $this->getLeadData($leadgenId);

            // Create in Bitrix24
            $this->createBitrix24Lead($leadData, [
                'ad_id'       => $adId,
                'campaign_id' => $campaignId,
                'form_id'     => $formId,
            ]);
        }
    }
}

http_response_code(200); // Facebook requires 200 OK within 20 seconds

Retrieving lead data via Graph API

The webhook delivers only the leadgen_id. The full data must be fetched separately:

public function getLeadData(string $leadgenId): array
{
    $response = $this->fbGraph->get(
        "/{$leadgenId}?fields=field_data,created_time,ad_id,form_id",
        $this->pageAccessToken
    );

    $lead = $response->getDecodedBody();
    $fields = [];

    foreach ($lead['field_data'] as $field) {
        $fields[$field['name']] = $field['values'][0] ?? '';
    }

    return [
        'name'        => $fields['full_name']   ?? $fields['first_name'] . ' ' . $fields['last_name'],
        'phone'       => $fields['phone_number'] ?? $fields['phone'] ?? '',
        'email'       => $fields['email']        ?? '',
        'custom'      => $fields, // all form fields
        'created_at'  => $lead['created_time'],
    ];
}

Field names in Facebook Lead Ads depend on the form configuration — standard fields are named full_name, email, phone_number; custom fields have arbitrary names. The mapping must be configured for each form individually.

Creating a lead in Bitrix24

public function createBitrix24Lead(array $leadData, array $fbMeta): void
{
    $fields = [
        'TITLE'      => 'Facebook Lead Ads: ' . date('d.m.Y H:i'),
        'NAME'       => $leadData['name'],
        'PHONE'      => [['VALUE' => $leadData['phone'], 'VALUE_TYPE' => 'WORK']],
        'EMAIL'      => [['VALUE' => $leadData['email'], 'VALUE_TYPE' => 'WORK']],
        'SOURCE_ID'  => 'WEB',
        'SOURCE_DESCRIPTION' => 'Facebook Lead Ads',
        'UF_CRM_FB_AD_ID'       => $fbMeta['ad_id'],
        'UF_CRM_FB_CAMPAIGN_ID' => $fbMeta['campaign_id'],
        'UF_CRM_FB_FORM_ID'     => $fbMeta['form_id'],
        'UF_CRM_FB_LEAD_TIME'   => $leadData['created_at'],
    ];

    // Add custom form fields as a comment
    if (!empty($leadData['custom'])) {
        $customText = implode("\n", array_map(
            fn($k, $v) => "{$k}: {$v}",
            array_keys($leadData['custom']),
            array_values($leadData['custom'])
        ));
        $fields['COMMENTS'] = $customText;
    }

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

Fallback polling via API

Facebook webhooks occasionally fail to deliver (outages, timeouts). A fallback mechanism — polling every 30 minutes via GET /{page_id}/leadgen_forms/{form_id}/leads?since={timestamp}.

Scope of work

  • Creating a Facebook App, configuring leads_retrieval permissions
  • Setting up Lead Ads webhooks for pages
  • Handler development: verification, Graph API integration, field mapping
  • Custom fields in Bitrix24 for Facebook attributes
  • Deduplication by phone/email
  • Fallback polling, error logging

Timeline: 1–2 weeks including Facebook App moderation review.