Báo cáo lead cuối ngày tự gửi về Telegram
Mỗi tối một tin nhắn: hôm nay bao nhiêu lead, đến từ trang nào, còn bao nhiêu chưa gọi. Dựng bằng Schedule Trigger, Google Sheets và vài dòng mã.
Hai bài trước đã có chuông báo từng lead (bài 1) và bảng lưu đầy đủ (bài 2). Thứ còn thiếu là một cái nhìn tổng: cuối ngày, chủ doanh nghiệp không muốn mở Sheet đếm tay. Bài này dựng một luồng tự chạy lúc 18:00, đếm lead trong ngày theo trang nguồn, gửi một tin tóm tắt về Telegram.
Tóm tắt nhanh
- Luồng:
Schedule Trigger→Google Sheets(đọc hết dòng) →Code(lọc và đếm) →Telegram. - Đặt múi giờ cho workflow trước khi đặt giờ hẹn.
- Đếm theo khung “từ lần chốt trước đến lần chốt này”, không đếm theo ngày dương lịch, để lead buổi tối không bị rơi.
Bước 1: Đặt múi giờ trước khi đặt giờ
Đây là chỗ hỏng nhiều nhất của luồng hẹn giờ. Giờ hẹn trong n8n tính theo múi giờ của chính n8n: lấy từ cài đặt của workflow, nếu không có thì từ biến môi trường GENERIC_TIMEZONE, nếu vẫn không có thì theo giờ của máy chủ. Máy chủ thuê ở nước ngoài thường chạy giờ UTC, tức chậm hơn Việt Nam 7 tiếng.
- Mở workflow, vào Settings (cài đặt của workflow), mục Timezone, chọn
Asia/Ho_Chi_Minh. - Nếu anh chị tự cài n8n, đặt thêm
GENERIC_TIMEZONE=Asia/Ho_Chi_Minhtrong biến môi trường để mọi luồng mới đều đúng giờ từ đầu.
Bước 2: Node Schedule Trigger
Thêm node Schedule Trigger, chọn chạy theo ngày (Trigger Interval: Days), mỗi 1 ngày, giờ 18, phút 0. Muốn chỉ chạy ngày làm việc, chuyển sang chế độ biểu thức cron (cú pháp hẹn giờ kiểu Unix, gồm phút, giờ, ngày, tháng, thứ):
# 18:00 từ thứ Hai đến thứ Bảy
0 18 * * 1-6
Bước 3: Đọc toàn bộ dòng trong Sheet
Thêm node Google Sheets, thao tác đọc dòng (Get Row(s)), chọn file và trang tính lead như bài 2, không đặt bộ lọc. Mỗi dòng trong Sheet thành một item (một bản ghi) trong n8n. Với vài nghìn dòng thì cách này vẫn nhanh. Khi Sheet lớn hơn nhiều, nên tách mỗi tháng một trang tính, hoặc chuyển sang cơ sở dữ liệu.
Bước 4: Lọc khung giờ và đếm bằng node Code
Thêm node Code, ngôn ngữ JavaScript, chế độ chạy một lần cho tất cả item (Run Once for All Items). Dán đoạn sau:
// Khung đếm: từ 18:00 hôm qua đến 18:00 hôm nay (giờ Việt Nam).
// Đếm theo khung thay vì theo ngày, để lead đến lúc 20:00 vẫn vào báo cáo hôm sau.
const GIO_CHOT = 18;
const bayGio = DateTime.now().setZone('Asia/Ho_Chi_Minh');
const den = bayGio.set({ hour: GIO_CHOT, minute: 0, second: 0, millisecond: 0 });
const tu = den.minus({ days: 1 });
const trongKhung = [];
for (const item of $input.all()) {
const t = DateTime.fromFormat(String(item.json.thoi_gian || ''), 'yyyy-LL-dd HH:mm:ss',
{ zone: 'Asia/Ho_Chi_Minh' });
if (t.isValid && t >= tu && t < den) trongKhung.push(item.json);
}
// Đếm theo trang nguồn và theo trạng thái gọi
const theoTrang = {};
let chuaGoi = 0;
for (const r of trongKhung) {
const k = r.trang || '(không rõ trang)';
theoTrang[k] = (theoTrang[k] || 0) + 1;
if (!String(r.trang_thai || '').trim()) chuaGoi++;
}
const dong = Object.entries(theoTrang)
.sort((a, b) => b[1] - a[1])
.map(([trang, so]) => `• ${trang}: ${so}`);
const tin = [
`📊 Lead từ ${tu.toFormat('HH:mm dd/LL')} đến ${den.toFormat('HH:mm dd/LL')}`,
`Tổng: ${trongKhung.length}`,
`Chưa gọi: ${chuaGoi}`,
'',
...(dong.length ? dong : ['Không có lead trong khung này.'])
].join('\n');
return [{ json: { tin, tong: trongKhung.length } }];
DateTime là đối tượng của thư viện Luxon, có sẵn trong node Code, không cần cài thêm. Đoạn mã không ghi gì ngược lại Sheet, chỉ đọc và đếm.
Bước 5: Gửi về Telegram
Thêm node Telegram, thao tác gửi tin, dùng lại credential và chat id từ bài 1. Ô Text điền {{ $json.tin }}. Chạy thử một lần bằng nút thử, kiểm tin nhắn, rồi bật luồng chạy thật.
Nên giữ cả dòng “Không có lead trong khung này” thay vì bỏ qua không gửi. Một ngày không có tin nhắn thì anh chị không phân biệt được “hôm nay không có khách” với “luồng chết rồi”. Ngày nào cũng có tin, kể cả tin báo số 0, mới biết chắc hệ thống còn sống.
Hai bẫy chúng tôi đã trả giá
| Bẫy | Chuyện gì xảy ra | Cách tránh |
|---|---|---|
| Chốt sổ theo ngày dương lịch | Báo cáo 18:00 đếm “lead của hôm nay”. Lead đến từ 18:00 đến nửa đêm không thuộc báo cáo hôm nay (đã gửi) và cũng không thuộc báo cáo ngày mai (khác ngày). Lead buổi tối biến mất khỏi mọi báo cáo. | Đếm theo khung từ giờ chốt trước đến giờ chốt này, như đoạn mã ở bước 4. |
| Luồng báo cáo chết mà không ai biết | Đổi tên cột, hết hạn quyền Google, máy chủ khởi động lại: luồng lỗi, không có tin. Người nhận tưởng hôm đó vắng khách. | Luôn gửi tin kể cả khi bằng 0. Thêm một Error Workflow (luồng xử lý lỗi) để báo về Telegram khi luồng chính hỏng. |
Bẫy thứ nhất đến từ chính hệ thống báo cáo marketing nội bộ của chúng tôi: chốt số theo ngày làm lead buổi tối lọt khỏi báo cáo một thời gian dài mới phát hiện. Con số trên báo cáo trông vẫn hợp lý, nên không ai nghi.
thoi_gian có dòng ghi sai định dạng (ví dụ ai đó gõ tay), đoạn mã sẽ bỏ qua dòng đó. Muốn chắc, thêm vào tin nhắn số dòng bị bỏ qua để biết có dữ liệu bẩn.Bước tiếp theo: ba luồng đầu đã đủ một vòng nhận, lưu, báo, tổng kết. Các bài sau sẽ nối thêm email xác nhận cho khách và nhắc gọi lại lead quá hạn.
Câu hỏi thường gặp
Đặt 18:00 mà báo cáo đến lúc 1 giờ sáng là vì sao?
Giờ hẹn trong Schedule Trigger tính theo múi giờ của n8n, không phải múi giờ điện thoại của anh chị. Máy chủ đặt ở châu Âu hoặc Mỹ thì 18:00 của nó lệch hẳn với Việt Nam. Đặt múi giờ Asia/Ho_Chi_Minh trong phần cài đặt của workflow, hoặc biến môi trường GENERIC_TIMEZONE nếu tự cài.
Lead đến sau 18:00 có bị mất khỏi báo cáo không?
Không mất khỏi Sheet, nhưng sẽ không có trong báo cáo hôm đó. Nếu đếm theo đúng ngày dương lịch thì lead tối sẽ không bao giờ xuất hiện trong báo cáo nào. Cách sửa trong bài là đếm theo khung từ giờ chốt hôm trước đến giờ chốt hôm nay.
Không biết viết mã thì có làm được không?
Được, nhưng dài hơn. Có thể dùng node Filter để lọc theo ngày, node Summarize để đếm theo cột trang, rồi ghép tin nhắn bằng biểu thức. Đoạn mã trong bài gộp ba bước đó lại cho gọn và có chú thích từng dòng.
Có gửi báo cáo cho nhiều người được không?
Được. Cách đơn giản nhất là tạo một nhóm Telegram, thêm bot và những người cần nhận vào nhóm, rồi dùng chat id của nhóm. Không cần nhân bản luồng cho từng người.