Báo cáo cho 100+ khách hàng với một mô hình ngữ nghĩa
Một kỹ sư BI trình bày thiết kế hệ thống báo cáo điều khiển bằng cấu hình: một bảng dữ liệu chung, một danh mục chỉ số và vài dòng cấu hình cho mỗi khách hàng, giúp giảm khoảng 70% thời gian dựng dashboard và phục vụ hơn 100 khách hàng bằng cùng một mẫu báo cáo.

Nếu bạn phải làm báo cáo cho nhiều đối tượng, rất có thể bạn đã từng dựng đi dựng lại cùng một báo cáo. Agency dựng một báo cáo cho mỗi khách hàng, công ty tư vấn dựng một báo cáo cho mỗi hợp đồng, còn các nhóm phân tích nội bộ dựng một báo cáo cho mỗi đơn vị kinh doanh, thương hiệu hay thị trường. Mỗi bản sao ban đầu đều là phản ứng hợp lý trước một khác biệt có thật, nhưng rồi mỗi bản sao lại trở thành thêm một nơi để định nghĩa chỉ số trú ngụ.
Bài viết dưới đây trình bày một thiết kế cho tình huống khó hơn: hàng trăm khách hàng không liên quan đến nhau cùng dùng chung một mô hình. Họ gọi các chỉ số bằng tên riêng, gửi dữ liệu riêng và giữ lịch riêng, và không ai được phép thay đổi mô hình chung vì nhu cầu của riêng mình.
Sơ đồ tổng quan hệ thống báo cáo điều khiển bằng cấu hình
Xuất phát từ một agency truyền thông
Thiết kế này được xây dựng trong nhóm phân tích của một agency chuyên mua quảng cáo podcast, radio, YouTube và các kênh truyền thông khác cho khách hàng. Khoảng mười chuyên viên phân tích, mỗi người phụ trách từ tám đến hai mươi tài khoản, mỗi tài khoản có báo cáo riêng. Kế hoạch mở rộng duy nhất là tuyển thêm một chuyên viên cho mỗi mười khách hàng mới.
Thay vào đó, nhóm chuyển sang một mô hình dữ liệu, một danh mục chỉ số (metric catalog), một mẫu báo cáo và một bản ghi cấu hình ngắn cho mỗi khách hàng. Cùng một mẫu báo cáo cuối cùng phục vụ hơn 100 khách hàng.
Mô hình cố định và "hạt" của dữ liệu
Trường hợp đơn giản nhất: mười khách hàng đều theo dõi CPA (cost per acquisition – chi phí trên mỗi lượt chuyển đổi), bằng chi phí chia cho số chuyển đổi. Mười báo cáo với mười công thức CPA sẽ ổn cho đến khi định nghĩa thay đổi và một bản sao bị bỏ sót.
Giải pháp là gom dữ liệu của mọi khách hàng vào một bảng duy nhất, với cùng các cột và cùng mức chi tiết: ngày, khách hàng, chiến dịch, kênh, chi phí, lượt hiển thị, phiên, chuyển đổi, doanh thu. Đây là một bảng sự kiện (fact table) ở trung tâm của mô hình chiều, mỗi dòng là một khách hàng, chiến dịch, kênh và ngày. Mức chi tiết cố định đó chính là hạt (grain) – quyết định đầu tiên trong bất kỳ hệ thống báo cáo mới nào.
Bảng sự kiện chỉ chứa các thước đo cộng được (additive measures). Khách hàng, chiến dịch, kênh và ngày là các chiều. Cấu hình riêng của từng khách hàng nằm ngoài mô hình.
CPA giờ chỉ được định nghĩa đúng một lần: sum(spend) / nullif(sum(conversions), 0). Khách hàng trở thành một bộ lọc – trong hệ thống cũ, script tải dữ liệu của mẫu báo cáo chỉ cần một mệnh đề where client = ..., đổi giá trị đó là mọi biểu đồ và nhãn chuyển sang khách hàng khác.
Cùng phép tính, khác tên gọi
Vấn đề đầu tiên xuất hiện trước cả khi có khách hàng thứ mười: khách hàng đồng ý với nhau về phép tính thường xuyên hơn nhiều so với cách gọi. CPA của người này là CPO (cost per order) của người kia. Lượng truy cập của người này là "sessions", của người kia là "visits". Cùng một con số doanh thu chia chi phí, người gọi là ROAS, người gọi là ROI.
Chiều ngược lại cũng có: "acquisition" với một khách hàng nghĩa là đơn hàng hoàn tất, với khách khác là bắt đầu thanh toán, với khách thứ ba là một lượt truy cập. Nếu tên gọi nằm bên trong công thức, mỗi lần đổi tên lại sinh ra một chỉ số mới và các bản sao ngày càng lệch nhau.
Vì vậy cần tách đôi: định nghĩa nằm một lần trong danh mục, tên gọi nằm trong cấu hình của khách hàng. Khi tiếp nhận khách mới, mỗi KPI nhận hai câu hỏi: bạn tính chỉ số này thế nào, và bạn gọi nó là gì? Câu trả lời đầu được ánh xạ vào một định nghĩa có sẵn, hoặc trở thành định nghĩa mới dùng chung một lần cho tất cả. Câu trả lời thứ hai trở thành nhãn.
Ví dụ cấu hình của một khách hàng:
brewbox:
name: BrewBox Coffee Subscription
week_start: monday
conversion: Trial
kpi_types: [cpa]
sends: [spend, impressions, sessions, conversions]
labels: {sessions: Visits}
Báo cáo của BrewBox hiển thị "Cost per Trial" và "Visits" trên cùng đoạn SQL mà mọi khách hàng khác nhận. Kết quả chính của khách hàng – dùng thử, cài đặt hay đơn hàng – đều rơi vào một cột conversions chung, và bản ghi cấu hình cung cấp tên gọi.
Đây là chỗ thiết kế này khác một lớp chỉ số (metrics layer) thông thường: metrics layer cho mỗi chỉ số một tên, còn hệ thống này cho mỗi chỉ số một ý nghĩa và bao nhiêu tên tùy số khách hàng.
Khách hàng theo dõi KPI khác nhau thì sao?
Khách hàng thứ mười một là một cửa hàng online, chỉ theo dõi ROAS. Dựng thêm báo cáo thứ hai sẽ lại khởi động vòng lặp sao chép.
Giải pháp là mẫu báo cáo không đặt tên chỉ số: mẫu yêu cầu "KPI 1" đến "KPI N", và cấu hình của từng khách hàng quyết định cái gì lấp vào mỗi ô. Danh mục gom các chỉ số thành nhóm mẫu theo mục tiêu: mẫu CPA gồm chi phí, chuyển đổi, CPA, phiên và tỷ lệ chuyển đổi; mẫu ROAS gồm chi phí, doanh thu, ROAS, chuyển đổi và giá trị đơn hàng trung bình.
Một khách hàng chọn một hoặc nhiều mẫu, và một đoạn mã nhỏ gọi là resolver – nằm giữa mẫu báo cáo và cơ sở dữ liệu – hợp nhất các mẫu theo thứ tự và loại bỏ trùng lặp. Các ô không dùng đến không hiện ra dưới dạng cột trống: mỗi cột KPI trong công cụ BI mang điều kiện "hiện cột nếu" đọc theo cấu hình khách hàng.
Cách một báo cáo khách hàng được resolve
Khách hàng gửi dữ liệu khác nhau
Đây là vấn đề khó nhất trên thực tế và ít được bàn đến nhất.
Bên thứ ba không nắm dữ liệu của khách hàng. Chi phí và lượt hiển thị đến từ sổ đặt hàng của chính bên mua, nên khách hàng nào cũng có. Dữ liệu hiệu suất thì do khách hàng cung cấp và họ tự quyết định gửi gì: người chỉ gửi đơn hàng, người gửi đơn hàng, phiên và doanh thu, có ứng dụng có lượt cài đặt nhưng không có phiên web.
Mẫu CPA gồm tỷ lệ chuyển đổi, tức chuyển đổi chia cho phiên. Khách hàng không có phiên thì nên hiển thị gì? Số 0 là sai, vì 0 nghĩa là đã đo và thấy bằng 0. Thông báo lỗi cũng không có chỗ trên báo cáo cho khách hàng.
Cách giải quyết gồm hai khai báo. Mỗi chỉ số khai báo nó được tạo thành từ gì:
# semantic/metrics.yaml (rút gọn: bỏ định dạng hiển thị và chiều)
base:
spend: {column: spend}
sessions: {column: sessions}
conversions: {column: conversions}
revenue: {column: revenue}
ratio:
cpa: {label: "Cost per {conversion}", num: spend, den: conversions}
cvr: {label: "Conversion rate", num: conversions, den: sessions}
roas: {label: "ROAS", num: revenue, den: spend}
aov: {label: "Average order value", num: revenue, den: conversions}
Mỗi khách hàng khai báo những gì mình gửi, chính là dòng sends trong bản ghi của BrewBox. Resolver đối chiếu từng chỉ số mong muốn với danh sách đó. Chỉ số được hỗ trợ nhận một ô; các chỉ số còn lại bị bỏ ra ngoài, và báo cáo nói rõ lý do:
Not shown
- Sessions: needs sessions, which this client does not send.
- Conversion rate: needs sessions, which this client does not send.
Khi khách hỏi vì sao thiếu tỷ lệ chuyển đổi, câu trả lời nằm ngay trên trang và chỉ về phía dữ liệu, không phải phía chuyên viên phân tích. Nó còn biến lời phàn nàn thành đề nghị: gửi phiên lên là tỷ lệ chuyển đổi xuất hiện, không cần báo cáo mới hay thay đổi mã nguồn.
Bẫy tỷ lệ: lưu phần, không lưu tỷ lệ
Bảng sự kiện không có cột CPA, ROAS hay tỷ lệ chuyển đổi. Đây là quy tắc cần giữ nhất nếu phải vứt bỏ mọi thứ khác: lưu các phần, không bao giờ lưu tỷ lệ.
Xét ví dụ: thứ Hai chi 1.000 đô, 50 chuyển đổi, CPA 20 đô; thứ Ba chi 1.000 đô, 10 chuyển đổi, CPA 100 đô. Lấy trung bình hai CPA ngày ra 60 đô. Chia tổng chi cho tổng chuyển đổi ra 33,33 đô – đây mới là CPA thực của chiến dịch. Mọi tỷ lệ đều được tính là sum(tử số) / sum(mẫu số) sau khi nhóm, ở bất kỳ mức nào báo cáo yêu cầu: ngày, tuần, kênh hay cả quý. Cả họ câu hỏi "vì sao số tuần không khớp số ngày" biến mất.
Dữ liệu đến với hạt khác
Gần như mọi nguồn dữ liệu đều khớp hạt này. Khi một nguồn không khớp, ví dụ nhà cung cấp radio gửi tổng theo tuần, nguồn đó có bảng sự kiện riêng trên cùng các chiều; báo cáo cuộn bảng theo ngày lên theo tuần và kết hợp hai bảng ở hạt thô hơn, đồng thời ghi rõ không đi chi tiết hơn tuần.
Hai quy tắc giữ sự trung thực: không bao giờ rải một tổng tuần xuống các ngày, vì như vậy là bịa ra chi tiết không ai đo được; và nguồn dữ liệu tuần có tuần bắt đầu khác tuần của khách hàng sẽ làm hỏng lượt build, vì không truy vấn nào căn lại được những tổng đó mà không phải đoán. Các thước đo không cộng được, trên hết là reach duy nhất, nằm hoàn toàn ngoài khuôn mẫu và phải tính từ nguồn ở mức được yêu cầu.
Danh mục chỉ số và cấu hình khách hàng
Kết quả trong thực tế
Dựng dashboard cho khách hàng trở thành một thay đổi cấu hình, và thời gian dựng giảm khoảng 70%, từ vài giờ xuống vài phút. Công việc báo cáo hằng tuần giảm khoảng một phần ba. Cùng một mẫu phục vụ hơn 100 khách hàng.
Hai hiệu ứng quan trọng không kém thời gian tiết kiệm. Các định nghĩa thôi trôi dạt, và gần như bất kỳ chuyên viên phân tích nào cũng tiếp nhận được gần như mọi tài khoản, vì mọi thứ riêng của tài khoản đều được ghi lại trong bản ghi cấu hình. Và vì bản ghi là một bảng, nó nối được với dữ liệu hiệu suất – những câu hỏi trước đây phụ thuộc vào trí nhớ, như khách hàng trong một ngành nào đó có theo dõi đơn hàng hay không và chiến dịch của họ bão hòa nhanh ra sao, giờ chỉ là một bộ lọc trên cấu hình kèm một truy vấn.
Góc nhìn
Với các nhóm kỹ sư và doanh nghiệp Việt Nam làm báo cáo cho nhiều khách hàng – agency quảng cáo, công ty outsource, hay nhóm dữ liệu phục vụ nhiều thương hiệu và thị trường – bài học cốt lõi là tách rõ hai phần: cái chung (hạt dữ liệu, công thức chỉ số) đặt trong một mô hình và một danh mục, còn cái riêng (tên gọi, KPI được chọn, dữ liệu gửi lên, lịch tuần) đặt trong một bản ghi cấu hình nhỏ. Cấu hình nên được quản lý như sản phẩm: có kiểm tra hợp lệ, có người chịu trách nhiệm và có lịch sử thay đổi, lý tưởng là nằm trong hệ thống quản lý phiên bản.
Hai quy tắc kỹ thuật đáng mang về ngay là lưu các phần thay vì lưu tỷ lệ, và khai báo rõ mỗi chỉ số cần đầu vào nào để hệ thống tự kiểm tra dữ liệu đầu vào. Với nhóm nhỏ, một bảng sự kiện, một tệp danh mục chỉ số và một bản ghi cấu hình cho mỗi khách hàng đã mang lại phần lớn lợi ích; với nhóm lớn, có thể cân nhắc các lớp ngữ nghĩa thương mại trưởng thành, nhưng phần khó vẫn như cũ: chọn hạt dữ liệu, khai báo thành phần chỉ số và minh bạch về những gì từng khách hàng thực sự gửi lên.
Nguồn: towardsdatascience.com · Quy trình biên tập
Bài viết liên quan

Công nghệ
BrightBean Studio: Giải pháp quản lý mạng xã hội mã nguồn mở, tự triển khai cho Agency và SMB
13 tháng 4, 2026

Phần mềm
Cách Thu Hút Khách Hàng Mà Không Cần Gửi Tin Nhắn Lạnh: Hệ Thống Thực Tiễn Có Thể Áp Dụng Ngay
08 tháng 4, 2026

Công nghệ
Biến kho hàng thành tài sản thông minh: Ứng dụng AI dự báo nhu cầu nhập hàng tự động
05 tháng 4, 2026