Setting up number substitution by traffic sources in 1C-Bitrix

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
    1212
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    815
  • 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
    565
  • 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
    657
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    980

Configuration of Phone Number Substitution by Traffic Sources in 1C-Bitrix

A marketer wants to know how many calls come from Yandex.Direct vs. organic. If the site has one phone number, this is impossible without call tracking. Phone number substitution (dynamic number insertion) — replacing the displayed number depending on the traffic source.

bitrix.seo Module and UTM Parameters

Bitrix does not have built-in call tracking. Integration is implemented in two ways: through external services (CoMagic, Calltouch, Roistat) with their JavaScript code, or through your own implementation based on sessions and UTM parameters.

For your own implementation, the traffic source is read from $_GET on first visit and saved to the session. Parameter set: utm_source, utm_medium, utm_campaign for paid traffic; gclid for Google Ads; yclid for Yandex.Direct; fbclid for Facebook.

Handler to save traffic source to session:

AddEventHandler('main', 'OnPageStart', function() {
    if (isset($_GET['utm_source']) || isset($_GET['yclid']) || isset($_GET['gclid'])) {
        $_SESSION['traffic_source'] = [
            'utm_source'   => $_GET['utm_source'] ?? '',
            'utm_medium'   => $_GET['utm_medium'] ?? '',
            'utm_campaign' => $_GET['utm_campaign'] ?? '',
            'yclid'        => $_GET['yclid'] ?? '',
            'gclid'        => $_GET['gclid'] ?? '',
            'referrer'     => $_SERVER['HTTP_REFERER'] ?? '',
            'timestamp'    => time(),
        ];
    }
    if (!isset($_SESSION['traffic_source'])) {
        $_SESSION['traffic_source'] = [
            'referrer' => $_SERVER['HTTP_REFERER'] ?? '',
            'direct'   => true,
        ];
    }
});

Traffic Source to Phone Number Mapping

For each traffic source, a separate phone number is assigned. The mapping is stored in a custom table or in component settings. Table structure:

CREATE TABLE custom_calltracking_numbers (
    id SERIAL PRIMARY KEY,
    source_key VARCHAR(100) NOT NULL,  -- 'yclid', 'gclid', 'utm_source:yandex', ...
    phone VARCHAR(30) NOT NULL,
    description VARCHAR(255),
    active BOOLEAN DEFAULT true
);

Logic for selecting a phone number:

function getPhoneByTrafficSource(array $source): string {
    $default = '+375 (17) 000-00-00';

    if (!empty($source['yclid'])) {
        return getPhoneFromDb('yclid');
    }
    if (!empty($source['gclid'])) {
        return getPhoneFromDb('gclid');
    }
    if (!empty($source['utm_source'])) {
        return getPhoneFromDb('utm_source:' . $source['utm_source']) ?: $default;
    }
    if (!empty($source['referrer'])) {
        $host = parse_url($source['referrer'], PHP_URL_HOST);
        return getPhoneFromDb('referrer:' . $host) ?: $default;
    }

    return $default;
}

Phone Number Substitution in Site Template

The phone number in the template (/bitrix/templates/[template]/header.php) is replaced with a function call instead of hardcode:

$phone = getPhoneByTrafficSource($_SESSION['traffic_source'] ?? []);
echo '<a href="tel:' . preg_replace('/\D/', '', $phone) . '">' . $phone . '</a>';

To substitute phone numbers in already formatted HTML (if the template is not under your control) — use the OnEndBufferContent event handler:

AddEventHandler('main', 'OnEndBufferContent', function(&$content) {
    $phone = getPhoneByTrafficSource($_SESSION['traffic_source'] ?? []);
    $content = str_replace('+375 (17) 000-00-00', $phone, $content);
});

Passing Traffic Source to Order

When placing an order, the traffic source is passed to order properties or the COMMENTS field. This allows you to see in CRM where each purchase came from.

AddEventHandler('sale', 'OnSaleOrderBeforeSaved', function(\Bitrix\Main\Event $event) {
    $order = $event->getParameter('ENTITY');
    $source = $_SESSION['traffic_source'] ?? [];

    $comment = $order->getField('USER_DESCRIPTION');
    $sourceStr = json_encode($source, JSON_UNESCAPED_UNICODE);
    $order->setField('MANAGER_NOTES', 'Source: ' . $sourceStr);
});

Call Statistics

For complete analysis, it's necessary to record not just phone number display, but actual calls. External call tracking services provide a webhook on incoming call — it can be processed and recorded in a custom table with binding to USER_ID if the user is authorized, or to a session identifier.