Đưa form website về bảng khách hàng bằng n8n
Bài thực hành cho website đã có form đăng ký: đưa dữ liệu về bảng khách qua node Webhook, chặn spam bằng CAPTCHA có xác minh phía máy chủ, xin đồng ý đúng cách và chỉ lưu những gì cần. Đối chiếu tài liệu chính thức của n8n (bản 2.44.4), Cloudflare, Google và Luật Bảo vệ dữ liệu cá nhân ngày 20–21/10/2026.
Khách điền form, thông tin nằm im trong hộp thư
Website có form "Đăng ký tư vấn". Mỗi lần khách gửi, một email về hộp thư chung; nhân viên chép tay sang bảng tính, lúc nhớ lúc quên, khách thật lẫn giữa thư rác từ bot. (Tình huống minh hoạ.)
Bài này nối form có sẵn vào bảng khách bằng n8n: bot rác bị chặn trước khi chạm tới bảng, mỗi dòng có bằng chứng khách đã đồng ý cho bạn liên hệ.
Đưa form website về bảng khách bằng n8n là gì?
Đưa form website về bảng khách bằng n8n là đổi địa chỉ nhận của form thành Production URL của node Webhook, để n8n xác minh CAPTCHA, kiểm tra ô đồng ý, ghi một dòng vào Google Sheets rồi đưa khách tới trang cảm ơn.
- Form trên websiteÔ đồng ý, ô ẩn bẫy bot, widget CAPTCHA
- WebhookNhận POST, lọc sớm bằng Only Run If
- HTTP RequestGọi Siteverify xác minh token CAPTCHA
- IfCAPTCHA hợp lệ và khách đã tích ô đồng ý?
- Google SheetsAppend or Update Row theo số điện thoại
- Respond to WebhookRedirect tới trang cảm ơn
Nếu bạn chưa có website, dùng n8n Form Trigger như trong workflow đầu tiên sẽ nhanh hơn.
Chuẩn bị
- n8n chạy qua HTTPS (Cloud hoặc tự cài theo hướng dẫn cài n8n trên VPS).
- Quyền sửa mã HTML của form trên website.
- Một widget Cloudflare Turnstile (lấy Site key và Secret key trong trang quản trị Cloudflare). Dùng Google reCAPTCHA cũng được, cách làm tương tự, xem cuối Bước 3.
- Một Google Sheet có dòng tiêu đề như mẫu dưới. n8n coi dòng 1 là tiêu đề.
- Trang "Cảm ơn" và trang chính sách dữ liệu: bạn là ai, thu gì, để làm gì, lưu bao lâu, rút lại đồng ý thế nào.
thoi_gian | ho_ten | so_dien_thoai | nhu_cau | dong_y_tu_van | dong_y_nhan_tin | phien_ban_dong_y | trang_thaiKhông có cột ngày sinh, địa chỉ, số giấy tờ: form tư vấn không cần thì không thu.
Nguồn: Google Sheets – dòng tiêu đề · Turnstile – widget
Bước 1. Sửa form: ô đồng ý, ô ẩn và widget CAPTCHA
Mẫu dưới là form HTML tối giản (ví dụ minh hoạ). Dùng trình dựng trang khác thì giữ giao diện, chỉ cần: gửi tới Production URL, tên trường như mẫu, hai ô đồng ý tách riêng, có widget CAPTCHA.
<form action="<Production URL của node Webhook>" method="POST">
<label>Họ tên <input name="ho_ten" required></label>
<label>Số điện thoại <input name="so_dien_thoai" type="tel" required></label>
<label>Bạn cần tư vấn gì? <textarea name="nhu_cau"></textarea></label>
<!-- Ô ẩn bẫy bot (kỹ thuật thường dùng, không có tiêu chuẩn chính thức) -->
<div style="position:absolute;left:-5000px" aria-hidden="true">
<input name="website" tabindex="-1" autocomplete="off">
</div>
<label><input type="checkbox" name="dong_y_tu_van" value="co" required>
Tôi đồng ý để <Tên công ty> dùng họ tên, số điện thoại và nhu cầu tôi cung cấp để liên hệ tư vấn. <a href="<link chính sách dữ liệu>">Chi tiết</a></label>
<label><input type="checkbox" name="dong_y_nhan_tin" value="co">
(Không bắt buộc) Tôi đồng ý nhận tin giới thiệu sản phẩm qua <kênh>, tối đa <tần suất>; từ chối bất kỳ lúc nào.</label>
<input type="hidden" name="phien_ban_dong_y" value="<mã phiên bản lời đồng ý, vd DY-2026-10>">
<div class="cf-turnstile" data-sitekey="<Site key của Turnstile>"></div>
<button type="submit">Gửi đăng ký</button>
</form>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>- Hai ô đồng ý tách riêng, không đánh dấu sẵn. Luật 91/2025/QH15 (Điều 9) yêu cầu đồng ý tự nguyện, biết rõ loại dữ liệu, mục đích, bên xử lý, quyền của khách, theo từng mục đích, không buộc đồng ý mục đích khác. Vì vậy ô nhận tin giới thiệu là không bắt buộc; Điều 28 yêu cầu khách biết rõ nội dung, phương thức, tần suất.
- Mã phiên bản lời đồng ý giúp bạn biết khách đã đồng ý với câu chữ nào khi sau này sửa lời đồng ý.
- Ô ẩn
website: người thật không thấy nên để trống; bot điền mọi ô thì bị lọc. Đây là kỹ thuật thường dùng, không có nguồn chính thức, chỉ là lớp phụ. - Widget Turnstile nằm trong thẻ form sẽ tự thêm ô ẩn
cf-turnstile-responsechứa token khi khách gửi.
Nguồn: Turnstile – script, cf-turnstile-response · Luật 91/2025/QH15 – Điều 9, 28
Bước 2. Node Webhook: nhận dữ liệu và lọc sớm
- Tạo workflow, thêm Webhook. HTTP Method: POST. Path: giữ chuỗi ngẫu nhiên mặc định để khó đoán.
- Respond: Using 'Respond to Webhook' Node.
- Options → Ignore Bots: bật, để bỏ qua trình xem trước liên kết và bot thu thập web.
- Options → Only Run If: dán biểu thức dưới đây. Yêu cầu có ô ẩn bị điền, hoặc thiếu token CAPTCHA, nhận mã 200 nhưng không tạo execution, nên không tốn lượt chạy của gói.
- Bấm Listen for test event (Test URL nghe trong 120 giây), tạm đặt Test URL vào form, gửi thử bằng dữ liệu giả. Dữ liệu hiện ở OUTPUT, các trường nằm trong
body.
{{ !$json.body.website && !!$json.body['cf-turnstile-response'] }}Website gửi form bằng JavaScript (fetch) thì đặt Options → Allowed Origins (CORS) là tên miền website thay cho mặc định *.
Nguồn: Webhook – Only Run If, Ignore Bots, CORS · Test URL 120 giây
Bước 3. Xác minh CAPTCHA phía máy chủ
Theo Cloudflare, chỉ hiện widget trên trình duyệt là không đủ: phải gọi API Siteverify cho từng token. Token hết hạn sau 300 giây và chỉ xác minh được một lần. Để Secret key không nằm lộ trong node, cất nó vào credential:
- Vào Credentials → tạo credential loại Custom Auth (nhóm credential chung của HTTP Request), dán JSON dưới đây với Secret key thật. Khi lưu, đặt Allowed HTTP Request Domains chỉ cho
challenges.cloudflare.comnếu ô này có. - Thêm HTTP Request sau Webhook, cấu hình như khối thứ hai.
- Chạy thử: OUTPUT phải có
success: truevàhostnameđúng tên miền website của bạn.
{
"body": {
"secret": "<Secret key của Turnstile>"
}
}Method: POST
URL: https://challenges.cloudflare.com/turnstile/v0/siteverify
Authentication: Generic Credential Type → Custom Auth → (credential vừa tạo)
Send Body: bật · Body Content Type: JSON · Specify Body: Using Fields Below
Name: response
Value: {{ $('Webhook').item.json.body['cf-turnstile-response'] }}Tham số remoteip (IP khách) là tuỳ chọn; không gửi thì khỏi xử lý thêm dữ liệu cá nhân. Lỗi timeout-or-duplicate: token đã dùng hoặc quá hạn.
Dùng Google reCAPTCHA: POST tới https://www.google.com/recaptcha/api/siteverify với secret, response (token ở trường g-recaptcha-response, hiệu lực hai phút, xác minh một lần). Google ghi đây là tham số POST, không nói nhận JSON, nên chọn Body Content Type Form Urlencoded và dùng credential Custom Auth riêng (domain www.google.com). Đầu trang xác minh này hiện ghi đã ngưng dùng (deprecated), trỏ sang Google Cloud Fraud Defense: đọc tài liệu hiện hành trước khi chọn. Với cả hai, chạy thử bằng Test URL và xem OUTPUT để chắc khoá bí mật được gộp đúng vào yêu cầu.
Nguồn: Turnstile – server-side validation · reCAPTCHA – verify · HTTP Request credentials – Custom Auth · Credentials – Allowed domains
Bước 4. Rẽ nhánh hợp lệ hay từ chối
Thêm If với hai điều kiện, nối bằng AND:
{{ $json.success }}loại Boolean, is true (kết quả Siteverify).{{ $('Webhook').item.json.body.dong_y_tu_van }}loại String, is equal toco. Ô đồng ý có thuộc tínhrequiredtrên trình duyệt, nhưng bot có thể gửi thẳng tới webhook, nên phải kiểm tra lại ở n8n.
Nhánh false: thêm Respond to Webhook, Respond With Redirect về trang form kèm thông báo chung "Gửi chưa thành công, vui lòng thử lại". Không đưa họ tên hay số điện thoại lên đường dẫn chuyển hướng.
Nguồn: If node · Respond to Webhook – Redirect
Bước 5. Ghi vào Google Sheets, chống trùng
- Nhánh true: thêm Google Sheets, thao tác Append or Update Row (có thì cập nhật, chưa có thì thêm).
- Credential: OAuth2, đăng nhập tài khoản Google công việc sở hữu bảng.
- Chọn Document, Sheet. Column to Match On:
so_dien_thoai, để khách gửi lại không tạo dòng trùng. - Mapping Column Mode: Map Each Column Manually. Chỉ ghép những cột trong bảng: kéo từ
bodycủa Webhook;thoi_gianđiền{{ $now.toISO() }};trang_thaiđiềnmoi. Token CAPTCHA và ô ẩn không có cột nên không bao giờ bị lưu. - Settings của node: bật Retry On Fail.
Google Sheets API cho 60 lượt ghi mỗi phút mỗi người dùng trong một dự án (300 cho cả dự án), dư cho form tư vấn. Khách gửi lại thì dòng cũ bị ghi đè, kể cả thời điểm đồng ý; cần giữ lịch sử thì thêm trang tính "Nhật ký đồng ý" dùng Append Row.
Nguồn: Append or Update Row, Column to Match On · Sheets API limits · OAuth 2.0 – Testing 7 ngày · Google credentials · Retry On Fail
Bước 6. Trả lời trình duyệt, rồi Publish
- Sau Google Sheets, thêm Respond to Webhook, Respond With Redirect, Redirect URL là trang cảm ơn, ví dụ
https://<website>/cam-on/. Website gửi bằng JavaScript thì chọn JSON, trả{"ok": true}rồi tự hiện lời cảm ơn. - Không trả HTML: từ n8n 1.103.0, HTML trả qua webhook bị bọc trong iframe hộp cát, JavaScript và liên kết tương đối không chạy.
- Bấm Publish. Đổi địa chỉ form trên website sang Production URL. Từ giờ dữ liệu chạy thật không hiện trên bảng vẽ, xem ở tab Executions.
- Báo sale ngay: nối node Telegram cuối nhánh true như bot Telegram báo cáo.
Theo tài liệu n8n, nếu workflow lỗi trước khi tới Respond to Webhook, trình duyệt nhận mã 500; nếu workflow kết thúc mà không đi qua node này, trả mã 200 kèm thông báo mặc định. Trên n8n Cloud, webhook không trả lời trong 100 giây sẽ báo lỗi 524.
Nguồn: Respond to Webhook – Redirect, 500, iframe · Production URL, Executions · Webhook – common issues
Kiểm tra đã chạy đúng
- Gửi form thật bằng dữ liệu giả: sang trang cảm ơn, bảng có đúng một dòng mới,
trang_thailàmoi. - Gửi lại cùng số điện thoại: dòng cũ được cập nhật, không thêm dòng.
- Gửi thẳng tới webhook mà không có ô đồng ý tư vấn: không có dòng nào được ghi.
- Điền ô ẩn
website: tab Executions không có lượt chạy mới. - Gửi lại token CAPTCHA đã dùng: Siteverify trả
success: false, chuyển về trang báo lỗi chung. - Mở bảng: không có cột token, không có IP, không có dữ liệu thừa.
Lỗi thường gặp
| Hiện tượng | Nguyên nhân thường gặp | Cách xử lý |
|---|---|---|
| Gửi form báo không tìm thấy webhook | Chưa Publish, hoặc form vẫn dùng Test URL đã hết 120 giây | Publish, dùng Production URL |
| Trình duyệt báo lỗi CORS | Website gửi bằng fetch, chưa khai báo tên miền | Đặt Allowed Origins (CORS) là tên miền website |
Siteverify luôn success: false | Sai Secret key, thiếu token, hoặc token đã dùng/quá hạn | Xem error-codes; kiểm tra credential và tên trường |
| Lỗi 500 sau khi gửi | Node trước Respond to Webhook bị lỗi | Xem Executions; thường do credential Google hoặc tên cột |
| Credential Google ngừng chạy sau một tuần | Ứng dụng OAuth ở trạng thái Testing | Phát hành ứng dụng OAuth rồi kết nối lại |
| Lệch cột trong bảng | Đổi tên cột sau khi cấu hình | Chọn lại Mapping Column Mode để tải lại tên cột |
Nguồn: Webhook – test/production · Turnstile – error codes · Google Sheets – common issues
An toàn và chính sách
- Bằng chứng đồng ý: mỗi dòng có thời điểm, ô đã tích và mã phiên bản lời đồng ý. Luật 91/2025/QH15 yêu cầu đồng ý thể hiện được dưới dạng in, sao chép được, và ghi rõ im lặng không phải là đồng ý. Khách có quyền rút lại đồng ý (Điều 10): trang chính sách cần nói cách rút, và bạn cần một cột hoặc trạng thái để dừng liên hệ.
- Dùng dữ liệu form để gửi SMS hay email quảng cáo: Nghị định 91/2020/NĐ-CP yêu cầu đồng ý trước và lưu thông tin đăng ký, từ chối tối thiểu một năm. Quy định từng kênh xem email tự động đúng quy định và bám đuổi khách đúng chính sách.
- Dữ liệu tối thiểu: chỉ cột cần cho tư vấn; chia sẻ bảng đúng người.
- Lịch sử chạy cũng chứa dữ liệu khách: bản tự cài mặc định dọn execution cũ hơn 14 ngày; có thể tắt lưu lượt chạy thành công trong Workflow Settings.
- Khóa bí mật chỉ nằm trong Credentials; không dán vào node Code, ghi chú workflow hay nhóm chat.
- Giới hạn tần suất gửi vào webhook: tài liệu n8n không có tính năng này; nếu cần, làm ở reverse proxy hoặc CDN.
- Phần quy định trong bài là tóm tắt để vận hành, không phải tư vấn pháp lý.
Nguồn: Bộ Công an – Luật 91/2025 hiệu lực 01/01/2026 · Luật 91/2025/QH15 – văn bản · Nghị định 91/2020/NĐ-CP · Biến môi trường executions · Workflow settings
Muốn được tư vấn cách áp dụng n8n cho quy trình của doanh nghiệp, bạn có thể đăng ký Tư vấn 1-1 hoặc Coaching 1-1; chi phí báo sau buổi tư vấn.
Đọc tiếp: Đưa lead TikTok về hệ thống →
Câu hỏi thường gặp
Đã có n8n Form Trigger, sao còn dùng Webhook?
n8n Form Trigger tự sinh trang form, hợp khi bạn chưa có website hoặc cần form nhanh, xem bài workflow đầu tiên. Khi website đã có form theo giao diện thương hiệu, Webhook cho bạn giữ nguyên form đó và chỉ đổi nơi nhận dữ liệu.
Chỉ dùng ô ẩn (honeypot) để chặn spam có đủ không?
Không nên dựa vào một lớp. Ô ẩn là kỹ thuật thường dùng nhưng không có tiêu chuẩn chính thức và không chặn được bot chủ đích. Lớp chắc chắn hơn là CAPTCHA có xác minh phía máy chủ: Cloudflare ghi rõ widget phía trình duyệt là không đủ, phải gọi Siteverify cho từng token.
Có được đánh dấu sẵn ô đồng ý để khách đỡ phải bấm không?
Không. Luật Bảo vệ dữ liệu cá nhân 91/2025/QH15 yêu cầu sự đồng ý tự nguyện, rõ ràng, theo từng mục đích, và nêu rõ sự im lặng hoặc không phản hồi không được coi là đồng ý. Ô đồng ý phải để trống cho khách tự chọn.
Có nên lưu địa chỉ IP của người gửi form không?
Chỉ lưu khi có mục đích rõ. Tham số địa chỉ IP khi gọi Siteverify là tuỳ chọn ở cả Turnstile và reCAPTCHA, nên bạn có thể không gửi và không lưu. Nguyên tắc dữ liệu tối thiểu giúp giảm rủi ro khi bảng tính bị chia sẻ nhầm.
Vì sao gửi form xong bị lỗi 500?
Theo tài liệu n8n, khi workflow lỗi trước lúc tới node Respond to Webhook, webhook trả mã 500. Mở tab Executions xem node nào lỗi, thường là credential Google hết hạn hoặc tên cột trong bảng bị đổi.
Tài liệu liên quan
- n8n · AI Agentn8n là gì? Tự động hoá quy trình kết hợp AI cho doanh nghiệpn8n là gì: công cụ tự động hoá quy trình nối Facebook, Google Sheets, Telegram, CRM thành workflow, chèn được bước AI. Cloud hay tự cài, giấy phép, giới hạn.
- n8n · AI AgentLàm chatbot Facebook Messenger bằng n8n: webhook, chữ ký, Send API, cửa sổ 24 giờLàm chatbot Facebook Messenger bằng n8n: xác minh webhook, kiểm chữ ký X-Hub-Signature-256, trả 200 trong 5 giây, gửi qua Send API, cửa sổ 24 giờ, App Review.
- n8n · AI Agentn8n Cloud hay tự cài: chi phí, gói và giấy phép cần biếtn8n Cloud hay tự cài: bảng gói Cloud bằng EUR theo lượt chạy, bản Community miễn phí và chi phí thật khi tự cài, giấy phép fair-code, chọn theo 5 tình huống.
- n8n · AI AgentKết nối Zalo OA với n8n: webhook 2 giây, token 25 giờ, tin Tư vấn miễn phí 48 giờKết nối Zalo OA với n8n từng bước: webhook trả 200 trong 2 giây, làm mới access token 25 giờ, gửi tin Tư vấn qua API, khung 48 giờ miễn phí và giới hạn 7 ngày.
Xem tất cả tài liệu hướng dẫn →
Đăng ký tư vấn 1:1
Chuyên gia Aduca cùng bạn xem quy trình hiện tại, chọn việc nên giao cho AI Agent trước và cách kiểm soát rủi ro.
Nguồn tham khảo
- n8n Docs – Webhook node
- n8n Docs – Webhook: Test URL và Production URL
- n8n Docs – Respond to Webhook
- n8n Docs – HTTP Request credentials (Custom Auth)
- n8n Docs – Google Sheets: Sheet operations
- Cloudflare Docs – Turnstile: xác minh phía máy chủ
- Cloudflare Docs – Turnstile: nhúng widget
- Google – reCAPTCHA: Verifying the user's response
- Google – Giới hạn Google Sheets API
- Bộ Công an – Luật Bảo vệ dữ liệu cá nhân 91/2025/QH15
Lịch sử cập nhật
- 21/10/2026 — Bản đầu.
Miễn trừ trách nhiệm
Bài viết thuộc chuỗi kiến thức của Công ty Cổ phần Giáo dục Aduca, chia sẻ miễn phí cho mục đích học tập. Thông tin kỹ thuật đối chiếu với tài liệu chính thức của các dự án và nền tảng tại ngày cập nhật (có ghi nguồn); phần nhận định là quan điểm của Aduca. OpenClaw, Hermes Agent, Claude (thương hiệu của Anthropic), ChatGPT (thương hiệu của OpenAI), n8n (thương hiệu của n8n GmbH), các phần mềm chạy model và các model AI mở (Ollama, LM Studio, Qwen, Gemma, gpt-oss…), Obsidian, Notion, phương pháp Building a Second Brain (Tiago Forte) cùng các phần mềm, dịch vụ nêu trong bài thuộc về chủ sở hữu tương ứng, không thuộc Aduca; Aduca không phải đối tác chính thức của các công ty này. Tính năng, gói và giá có thể thay đổi bất cứ lúc nào – hãy kiểm tra trang chính thức trước khi mua. Kết quả áp dụng phụ thuộc quy trình, dữ liệu và con người của từng doanh nghiệp; bài viết không cam kết doanh thu hay hiệu quả cụ thể. © 2026 Aduca — được trích dẫn khi ghi rõ nguồn aduca.vn.