1C-Bitrix Integration with Google reCAPTCHA
Form spam — a contact form receives 500 bot submissions per day, the sales team drowns in noise, the CRM fills up with garbage. The standard Bitrix CAPTCHA module (bitrix:main.captcha) uses its own implementation, which modern bots bypass with ease. Google reCAPTCHA v3 solves the problem without any frustrating challenges for the user.
reCAPTCHA v2 vs v3
v2 — the user ticks a checkbox or solves a challenge (select traffic lights). Rendered as an explicit widget. Protection is reliable but degrades UX.
v3 — invisible verification that returns a score from 0.0 (bot) to 1.0 (human). Does not interrupt the user. Recommended threshold: score >= 0.5. Logic: when score < 0.5, you can display v2 as an additional check or block the submission entirely.
Registering keys
In the Google reCAPTCHA console (https://www.google.com/recaptcha/admin) register your domain and obtain two keys:
- Site key — public, inserted into the frontend.
-
Secret key — private, used for server-side verification. Store in
COptionor.env, never in code.
Frontend integration
In the site template <head>:
<script src="https://www.google.com/recaptcha/api.js?render=SITE_KEY"></script>
Before submitting the form, obtain a token:
grecaptcha.ready(function() {
grecaptcha.execute('SITE_KEY', {action: 'submit'}).then(function(token) {
document.getElementById('g-recaptcha-response').value = token;
document.getElementById('feedback-form').submit();
});
});
The hidden field g-recaptcha-response is sent to the server together with the form data.
Server-side verification in Bitrix
In the form handler (before writing to the database or sending to the CRM):
function verifyRecaptcha(string $token): bool {
$secretKey = COption::GetOptionString('site', 'recaptcha_secret');
$http = new \Bitrix\Main\Web\HttpClient();
$response = $http->post('https://www.google.com/recaptcha/api/siteverify', [
'secret' => $secretKey,
'response' => $token,
'remoteip' => $_SERVER['REMOTE_ADDR'],
]);
$result = json_decode($response, true);
return $result['success'] === true && ($result['score'] ?? 0) >= 0.5;
}
// In the form handler:
$token = $_POST['g-recaptcha-response'] ?? '';
if (empty($token) || !verifyRecaptcha($token)) {
// Log the spam attempt, return an error
$APPLICATION->ThrowException('Verification failed. Please try again.');
return;
}
Integration with standard Bitrix components
For the bitrix:main.feedback component — override the component template in /bitrix/templates/[template]/components/bitrix/main.feedback/[variant]/. Add the hidden field and JS code in template.php. In result_modifier.php, verify the token and set the $arResult['CAPTCHA_PASSED'] variable.
For custom Ajax forms — verification is performed in the controller or component handler before any data operations.
Logging and analysis of blocked attempts
Write blocked attempts to a table via \Bitrix\Main\Application::getConnection()->query():
CREATE TABLE IF NOT EXISTS b_spam_log (
ID int AUTO_INCREMENT PRIMARY KEY,
DATE_CREATE datetime,
IP varchar(45),
SCORE float,
FORM_ID varchar(50),
ACTION varchar(50)
);
A week's worth of analysis reveals attack patterns — peak hours, IP ranges, targeted forms. Based on this, additional rules can be configured at the nginx level.
Case: false positives
A corporate client reported that their request form could not be submitted from the office. The cause: a corporate proxy — all traffic originating from a single IP. Google reCAPTCHA assigned low scores to such requests due to the anomalous pattern. Solution: reCAPTCHA was not applied to authenticated users (B2B cabinet) — check $USER->IsAuthorized() and skip verification.
| Task | Effort |
|---|---|
| Key registration and frontend setup | 1–2 h |
| Server-side verification for one form | 2–3 h |
| Integration across multiple forms/components | 4–6 h |
| Logging and monitoring | 2–3 h |







