Tổng quan
- Máy chủ website gửi từng lượt điền form tới CRM từ phía server (PHP, Node …). Mỗi lượt gửi hợp lệ tạo một lead, giao cho người phụ trách của form và gửi thông báo cho họ.
- Mỗi form có mã form và khoá bí mật do quản trị CRM cung cấp. Form chuyển từ Bitrix24 dùng mã
bitrix-<ID form Bitrix>và khoá chính là mã bảo mậtseccủa form Bitrix đó.
Không đặt khoá trong HTML/JavaScript gửi xuống trình duyệt. Ai có khoá đều tạo được lead.
Endpoint
POSThttps://form.crm.ezcloud.vn/api/v1/public/lead-forms/{mã form}/submissions
| Header | Giá trị |
|---|---|
Authorization | Bearer <khoá form> |
Content-Type | application/json |
Nội dung gửi
{
"name": "Nguyễn Văn An",
"email": "an@example.com",
"phone": "0912345678",
"message": "Khách sạn 20 phòng ở Đà Nẵng",
"pageUrl": "https://ezcloud.vn/dang-ky-dung-thu?utm_source=google",
"utm": { "source": "google", "medium": "cpc", "campaign": "brand", "content": "", "term": "" },
"fields": { "Số phòng": "20" },
"submissionId": "wp-6721f0c3a1b2"
}
| Trường | Kiểu | Mô tả |
|---|---|---|
name | chuỗi ≤ 200 | Họ tên khách. Tiêu đề lead = tiền tố của form + họ tên. |
email | chuỗi ≤ 200 | Bắt buộc có ít nhất một trong hai. |
phone | chuỗi ≤ 50 | |
message | chuỗi ≤ 5000 | Lời nhắn / ghi chú của khách. |
pageUrl | chuỗi ≤ 2000 | Trang khách điền form (kèm tham số quảng cáo nếu có). |
utm | object | source, medium, campaign, content, term — đều tuỳ chọn. |
fields | object chuỗi → chuỗi | Các trường khác của form; hiện nguyên văn trên lead. |
submissionId | chuỗi ≤ 100 | Mã lượt gửi do website tự sinh. Gửi lại cùng mã (khi retry) không tạo lead thứ hai. |
Phản hồi
| HTTP | Nội dung | Ý nghĩa |
|---|---|---|
| 201 | {"status":"created","submissionId":123} | Đã tạo lead. |
| 201 | {"status":"duplicate","submissionId":123} | submissionId này đã được nhận trước đó. |
| 401 | INVALID_FORM_KEY | Sai mã form hoặc khoá. |
| 403 | FORM_INACTIVE | Form đang tắt trên CRM. |
| 422 | VALIDATION_FAILED | Dữ liệu không hợp lệ (thiếu email/SĐT, quá dài …). Không retry. |
| 429 | Gửi quá nhanh; thử lại sau ít giây. |
Giới hạn: 64 KB mỗi request, khoảng 60 lượt/phút mỗi form. Nên đặt timeout ~8 giây và retry 1 lần khi lỗi mạng / 5xx / 429, dùng cùng submissionId.
Thử bằng curl
curl -sS https://form.crm.ezcloud.vn/api/v1/public/lead-forms/bitrix-21/submissions \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"name":"Test CRM","email":"test@ezcloud.vn","pageUrl":"https://ezcloud.vn/test"}'
WordPress + Elementor Pro
1. Thêm cấu hình vào wp-config.php:
define('EZCRM_FORM_URL', 'https://form.crm.ezcloud.vn/api/v1/public/lead-forms');
// giá trị trường ẩn bitrix_form => [mã form CRM, khoá]
// giữ nguyên ID form và mã sec đang dùng với Bitrix: mã CRM = 'bitrix-<ID>', khoá = sec
define('EZCRM_FORMS', [
'form_dang_ky_dung_thu' => ['bitrix-21', '<sec form Bitrix 21>'],
'popup_dang_ky_dung_thu' => ['bitrix-15', '<sec form Bitrix 15>'],
]);
2. Tạo file wp-content/mu-plugins/ezcrm-lead-form.php. Đoạn mã đọc các trường Elementor đang có (form_name, popup_header_phone, bitrix_form, current_url, utm_* …), không cần sửa form:
<?php
/** Gửi lead từ form Elementor sang ezCloud CRM (https://form.crm.ezcloud.vn/). */
add_action('elementor_pro/forms/new_record', function ($record, $handler) {
if (!defined('EZCRM_FORMS') || !defined('EZCRM_FORM_URL')) return;
$raw = $record->get('fields');
$f = [];
foreach ($raw as $id => $field) $f[$id] = trim((string) ($field['value'] ?? ''));
$target = EZCRM_FORMS[$f['bitrix_form'] ?? ''] ?? null;
if (!$target) return; // form không gửi CRM
[$code, $key] = $target;
// Lấy giá trị đầu tiên khác rỗng theo hậu tố id trường: form_name, popup_header_name, popup_name, name …
$pick = function (string $suffix) use ($f) {
foreach ($f as $id => $v) if ($v !== '' && ($id === $suffix || str_ends_with($id, '_' . $suffix))) return $v;
return null;
};
$known = ['bitrix_form', 'current_url', 'utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
$extra = [];
foreach ($raw as $id => $field) {
$v = $f[$id];
if ($v === '' || in_array($id, $known, true) || preg_match('/(^|_)(name|email|phone)$/', $id)) continue;
$extra[$field['title'] ?: $id] = $v;
}
$body = [
'name' => $pick('name'),
'email' => $pick('email'),
'phone' => $pick('phone'),
'pageUrl' => $f['current_url'] ?? null,
'utm' => [
'source' => $f['utm_source'] ?? null, 'medium' => $f['utm_medium'] ?? null,
'campaign' => $f['utm_campaign'] ?? null, 'content' => $f['utm_content'] ?? null,
'term' => $f['utm_term'] ?? null,
],
'fields' => (object) $extra,
'submissionId' => 'wp-' . wp_generate_uuid4(),
];
$args = [
'timeout' => 8,
'headers' => ['Authorization' => 'Bearer ' . $key, 'Content-Type' => 'application/json'],
'body' => wp_json_encode($body),
];
$url = EZCRM_FORM_URL . '/' . rawurlencode($code) . '/submissions';
for ($try = 1; $try <= 2; $try++) { // retry an toàn nhờ submissionId
$res = wp_remote_post($url, $args);
$status = is_wp_error($res) ? 0 : wp_remote_retrieve_response_code($res);
if ($status >= 200 && $status < 300) return;
if ($status >= 400 && $status < 500 && $status !== 429) break; // lỗi dữ liệu/khoá: không retry
}
error_log('[ezcrm] gửi lead lỗi ' . $code . ': ' . (is_wp_error($res) ? $res->get_error_message() : $status . ' ' . wp_remote_retrieve_body($res)));
}, 10, 2);
Khi bật đoạn mã này, tắt đoạn mã đang gửi sang Bitrix24 (crm.site.form.fill) để không tạo lead trùng. Để EZCRM_FORMS rỗng ([]) là tạm ngừng gửi.