An AJAX Contact Form in 1C-Bitrix: Submit Without Reloading

7 min read
A contact form on a 1C-Bitrix website can be submitted through AJAX without reloading the page, saving each enquiry in an information block and notifying the website administrator at the same time.

This approach suits callback requests, service enquiries, quotation requests and similar forms.

The resulting workflow is:

  1. The user fills in the form.
  2. JavaScript sends the data through AJAX.
  3. A PHP handler validates the data.
  4. The enquiry is saved in an information block.
  5. Bitrix creates an email event and sends a notification.
  6. The user sees a success message without the page reloading.

1. Create an Information Block for Enquiries

First, create a separate information block to store user enquiries.

For example, name it:


Website Enquiries

Add the following properties to the information block:

  • NAME — the user's name;
  • PHONE — phone number;
  • EMAIL — email address;
  • PAGE — the page from which the enquiry was sent.
The message itself can be saved in the element's preview text field, so a separate property is optional.

Note the information block ID after creating it. You will need it in the PHP handler.

In the following examples, assume our information block ID is:


12

Replace it with your own information block ID in a real project.

2. Create an Email Event Type

Create an email event through which the administrator will receive new enquiry notifications.

In the Bitrix admin panel, open the email events section and create a new type.

For example:


NEW_FEEDBACK

Define the following event fields:


#NAME# - Name
#PHONE# - Phone
#EMAIL# - Email
#MESSAGE# - Message
#PAGE# - Submission page

Then create an email template and link it to the event NEW_FEEDBACK.

For example, the email body might look like this:


A new enquiry has been submitted on the website.

Name: #NAME#
Phone: #PHONE#
Email: #EMAIL#

Message:
#MESSAGE#

Page:
#PAGE#

In the recipient field, enter the address that should receive enquiries.

3. Add the HTML Form

Now create the form itself.

It can be placed directly on a page, in the website template or inside a modal window.

Example form:


<form id="feedback-form">

    <?=bitrix_sessid_post()?>

    <div class="form-group">
        <label for="feedback-name">Ваше имя</label>
        <input
            type="text"
            name="name"
            id="feedback-name"
            class="form-control"
            required
        >
    </div>

    <div class="form-group">
        <label for="feedback-phone">Телефон</label>
        <input
            type="text"
            name="phone"
            id="feedback-phone"
            class="form-control"
            required
        >
    </div>

    <div class="form-group">
        <label for="feedback-email">E-mail</label>
        <input
            type="email"
            name="email"
            id="feedback-email"
            class="form-control"
        >
    </div>

    <div class="form-group">
        <label for="feedback-message">Сообщение</label>
        <textarea
            name="message"
            id="feedback-message"
            class="form-control"
            rows="5"
        ></textarea>
    </div>

    <input
        type="hidden"
        name="page"
        id="feedback-page"
        value=""
    >

    <div class="form-group">
        <label>
            <input
                type="checkbox"
                name="agree"
                value="Y"
                required
            >
            Я согласен на обработку персональных данных
        </label>
    </div>

    <div class="feedback-result"></div>

    <button
        type="submit"
        class="feedback-submit"
    >
        Отправить
    </button>

</form>

This uses the standard HTML attributes required and type="email", allowing the browser to perform basic form validation.

The form also includes:


<?=bitrix_sessid_post()?>

This adds the Bitrix session identifier, which we will check on the server.

4. Submit the Form Through AJAX

This example uses jQuery, which is often already included in 1C-Bitrix projects.

The JavaScript intercepts form submission and sends the data to the PHP handler:


$(document).on('submit', '#feedback-form', function(e) {

    e.preventDefault();

    var $form = $(this);
    var $button = $form.find('.feedback-submit');
    var $result = $form.find('.feedback-result');

    $('#feedback-page').val(window.location.href);

    $result
        .removeClass('success error')
        .html('');

    $button.prop('disabled', true);

    $.ajax({
        url: '/local/ajax/feedback.php',
        type: 'POST',
        data: $form.serialize(),
        dataType: 'json'
    })
    .done(function(response) {

        if (response.status) {

            $result
                .addClass('success')
                .html(response.message);

            $form[0].reset();

        } else {

            $result
                .addClass('error')
                .html(response.message);
        }

    })
    .fail(function() {

        $result
            .addClass('error')
            .html('При отправке формы произошла ошибка. Попробуйте ещё раз.');

    })
    .always(function() {

        $button.prop('disabled', false);

    });

});

When the form is submitted:

  1. Default form submission is prevented using preventDefault().
  2. The current page URL is written to a hidden field.
  3. The submit button is temporarily disabled.
  4. The form data is sent to the PHP file in a POST request.
  5. A JSON response is expected from the server.
  6. The form is cleared after successful submission.
  7. The result is displayed to the user.
Disabling the button also prevents accidental repeated clicks while the AJAX request is in progress.

5. Create the PHP Form Handler

Create the file:


/local/ajax/feedback.php

Load the Bitrix core and information block module, validate the data and create a new information block element.

Example handler:


<?php

define('NO_KEEP_STATISTIC', true);
define('NO_AGENT_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS', true);

require_once(
    $_SERVER['DOCUMENT_ROOT']
    . '/bitrix/modules/main/include/prolog_before.php'
);

use Bitrix\Main\Application;
use Bitrix\Main\Loader;
use Bitrix\Main\Mail\Event;
use Bitrix\Main\Web\Json;

header('Content-Type: application/json; charset=UTF-8');

$result = [
    'status' => false,
    'message' => ''
];

try {

    if (!check_bitrix_sessid()) {
        throw new RuntimeException(
            'Сессия устарела. Обновите страницу и попробуйте ещё раз.'
        );
    }

    if (!Loader::includeModule('iblock')) {
        throw new RuntimeException(
            'Не удалось подключить модуль информационных блоков.'
        );
    }

    $request = Application::getInstance()
        ->getContext()
        ->getRequest();

    $name = trim((string)$request->getPost('name'));
    $phone = trim((string)$request->getPost('phone'));
    $email = trim((string)$request->getPost('email'));
    $message = trim((string)$request->getPost('message'));
    $page = trim((string)$request->getPost('page'));
    $agree = $request->getPost('agree');

    if ($name === '') {
        throw new RuntimeException(
            'Укажите ваше имя.'
        );
    }

    if ($phone === '') {
        throw new RuntimeException(
            'Укажите номер телефона.'
        );
    }

    if (
        $email !== ''
        && !filter_var($email, FILTER_VALIDATE_EMAIL)
    ) {
        throw new RuntimeException(
            'Укажите корректный e-mail.'
        );
    }

    if ($agree !== 'Y') {
        throw new RuntimeException(
            'Необходимо подтвердить согласие на обработку персональных данных.'
        );
    }

    $nameSafe = htmlspecialcharsbx($name);
    $phoneSafe = htmlspecialcharsbx($phone);
    $emailSafe = htmlspecialcharsbx($email);
    $messageSafe = htmlspecialcharsbx($message);
    $pageSafe = htmlspecialcharsbx($page);

    $properties = [
        'NAME' => $nameSafe,
        'PHONE' => $phoneSafe,
        'EMAIL' => $emailSafe,
        'PAGE' => $pageSafe
    ];

    $element = new CIBlockElement();

    $elementId = $element->Add([
        'IBLOCK_ID' => 12,
        'ACTIVE' => 'Y',
        'NAME' => 'Заявка от '
            . $nameSafe
            . ' '
            . date('d.m.Y H:i:s'),
        'PREVIEW_TEXT' => $messageSafe,
        'PROPERTY_VALUES' => $properties
    ]);

    if (!$elementId) {
        throw new RuntimeException(
            'Не удалось сохранить заявку: '
            . $element->LAST_ERROR
        );
    }

    Event::send([
        'EVENT_NAME' => 'NEW_FEEDBACK',
        'LID' => defined('SITE_ID') ? SITE_ID : 's1',
        'C_FIELDS' => [
            'NAME' => $nameSafe,
            'PHONE' => $phoneSafe,
            'EMAIL' => $emailSafe,
            'MESSAGE' => $messageSafe,
            'PAGE' => $pageSafe
        ]
    ]);

    $result = [
        'status' => true,
        'message' => 'Спасибо! Ваша заявка отправлена.'
    ];

} catch (Throwable $e) {

    $result = [
        'status' => false,
        'message' => $e->getMessage()
    ];

}

echo Json::encode($result);

die();

Pay attention to this line:


'IBLOCK_ID' => 12,

Specify the ID of the information block created to store enquiries.

The codes:


NAME
PHONE
EMAIL
PAGE

must match the symbolic codes of your information block properties.

6. What Does the PHP Handler Do?

The handler performs the following steps:

  1. Loads the 1C-Bitrix core.
  2. Checks the session identifier.
  3. Loads the module iblock.
  4. Retrieves POST request data.
  5. Validates required fields.
  6. Checks the email format.
  7. Checks the user's consent.
  8. Creates a new information block element.
  9. Triggers an email event.
  10. Returns the result to JavaScript as JSON.
The key response field is:


status

If the enquiry is saved successfully, its value is:


true

On error, the response contains:


false

JavaScript uses this value to show the appropriate message.

7. Send an Email Notification

The following method sends the notification:


Bitrix\Main\Mail\Event::send()

It receives the code of the email event created earlier:


'EVENT_NAME' => 'NEW_FEEDBACK'

And the data array:


'C_FIELDS' => [
    'NAME' => $nameSafe,
    'PHONE' => $phoneSafe,
    'EMAIL' => $emailSafe,
    'MESSAGE' => $messageSafe,
    'PAGE' => $pageSafe
]

The array keys must match the variables added to the email event type.

For example, the value:


'PHONE' => $phoneSafe

is available in the email template as:


#PHONE#

8. Style the Submission Result

Add simple styles for success and error messages:


.feedback-result {
    margin: 15px 0;
}

.feedback-result.success {
    color: #198754;
}

.feedback-result.error {
    color: #dc3545;
}

.feedback-submit:disabled {
    opacity: 0.6;
    cursor: default;
}

The appearance of the form can, of course, be adapted to the project's design.

9. Test the Form

After configuration, check each step:

  1. Whether the AJAX request is sent.
  2. Whether the PHP handler returns valid JSON.
  3. Whether a new information block element is created.
  4. Whether its properties are saved.
  5. Whether the email event is created.
  6. Whether the email arrives at the specified address.
If the element is created but the email does not arrive, check Bitrix email events and the server's mail delivery separately.

10. What Else Should a Production Project Include?

For a production contact form, also consider:

  • Spam and automated submission protection;
  • Request rate limiting;
  • A phone number mask or additional phone validation;
  • Error logging;
  • Input length validation;
  • A separate personal data processing policy;
  • CAPTCHA, if needed.
Do not rely solely on JavaScript validation: a request can be sent directly to the PHP handler.

Required checks must therefore also run on the server.

Summary

An AJAX contact form in 1C-Bitrix has three main parts:

  • An HTML form filled in by the user;
  • JavaScript that sends the data without reloading the page;
  • A PHP handler that validates the data, saves the enquiry and creates an email event.
This foundation is easy to adapt for callback requests, enquiries from product cards, service orders, quotation requests or other website forms.
Back to blog