Người dùng và số liệu
Analytics event là một phần của yêu cầu
Tính năng không có analytics event là tính năng không biết có ai dùng không. Danh sách event phải nằm trong acceptance criteria, không phải gắn thêm sau khi code xong.
Nội dung bài
Thuật ngữ trong bài (14)
- acceptance criteria · tiêu chí nghiệm thu
- definition of done · định nghĩa hoàn thành
- build · bản dựng
- code review · soát mã
- Play Console · trang quản trị Google Play
- release · bản phát hành
- dashboard · bảng theo dõi
- low-end · máy cấu hình thấp
- analytics · đo hành vi người dùng
- baseline · mốc nền
- funnel · phễu chuyển đổi
- OTP · mã dùng một lần
- session · phiên đăng nhập
- token · khóa truy cập
Vì sao gắn sau thì đã muộn
Tính năng release xong, hai tuần sau chủ sản phẩm hỏi: bao nhiêu người dùng nó, họ rớt ở bước nào? Không ai trả lời được. Gắn event lúc đó thì phải chờ thêm một release, rồi chờ thêm hai tuần có dữ liệu — tổng cộng hơn một tháng để biết một điều lẽ ra đã biết ngay từ ngày đầu.
Chi phí gắn event lúc viết code: khoảng mười lăm phút. Chi phí gắn sau: một tháng không nhìn thấy gì, cộng một release nữa.
Vì vậy event nằm trong acceptance criteria, cùng hạng với các tiêu chí chức năng khác.
Quy tắc đặt tên
snake_case, theo dạng đối tượng_hành động, thì quá khứ cho việc đã xảy ra:
order_payment_started
order_payment_succeeded
order_payment_failed
chat_message_sent
task_created
Tên đặt rồi thì không đổi. Đổi tên event là cắt đôi chuỗi dữ liệu lịch sử, và các biểu đồ cũ sẽ im lặng trở nên sai. Cần thay đổi thì thêm event mới và ngừng dùng event cũ.
Mỗi luồng cần tối thiểu năm event
Ít hơn năm thì không dựng được funnel, mà không có funnel thì không biết user rớt ở đâu.
| Event | Bắn khi nào |
|---|---|
<luồng>_screen_opened | Màn hình mở ra |
<luồng>_started | User bắt đầu thao tác thật |
<luồng>_succeeded | Hoàn tất, có xác nhận từ server |
<luồng>_failed | Thất bại — kèm mã lỗi, đây là event quan trọng nhất |
<luồng>_cancelled | User chủ động bỏ giữa chừng |
Tách failed khỏi cancelled là bắt buộc. Gộp hai cái làm một thì không phân biệt được "app
hỏng" với "user đổi ý" — hai kết luận dẫn tới hai hành động hoàn toàn khác nhau.
Thuộc tính đi kèm
Bắt buộc có ở mọi event:
- App version và build number
- Platform và OS version
- Device model và lớp RAM
- Session id
- Thời điểm, theo giờ máy chủ khi có thể
App version là thuộc tính quan trọng nhất: không cắt được theo version thì không so sánh được release mới với release cũ, và dashboard trở nên vô dụng đúng lúc cần nhất.
Device model đứng ngay sau. Tỷ lệ crash 0,3% không nói được điều gì cho tới khi biết nó rải đều hay dồn hết vào một dòng máy — hai trường hợp đó dẫn tới hai hành động khác nhau. Lớp RAM đi kèm vì performance budget đặt mốc trên máy low-end: thiếu lớp RAM thì mốc đó không kiểm được trên dữ liệu thật, chỉ kiểm được trên máy trong tay đội. Hai trường này cũng là chỗ nối giữa danh sách máy đội đang có và phân bố thiết bị của user thật từ Play Console và App Store Connect.
Cấm gửi trong event, không có ngoại lệ:
- Nội dung tin nhắn, nội dung công việc
- Thông tin định danh cá nhân: số điện thoại, email, địa chỉ
- Số thẻ, mã OTP, token
- Toàn bộ payload của request
Lý do kép: rủi ro riêng tư, và nghĩa vụ khai báo dữ liệu trên store — xem Security baseline và privacy. Một event lỡ gửi dữ liệu cá nhân sẽ khiến khai báo Data Safety của app thành sai, và đó là loại sai có hậu quả pháp lý.
Funnel đọc được
Đây là thứ mà năm event ở trên tạo ra:
| Bước | Số phiên | Còn lại |
|---|---|---|
order_payment_screen_opened | 10.000 | 100% |
order_payment_started | 8.400 | 84% |
order_payment_succeeded | 5.500 | 55% |
order_payment_failed | 2.600 | 26% |
order_payment_cancelled | 300 | 3% |
Bảng này đọc ra ngay: 26% thất bại là bất thường, và vì failed có kèm mã lỗi nên bước tiếp theo
là xem mã nào chiếm đa số. Không có event thì cùng tình huống đó chỉ hiện ra dưới dạng "doanh số
tháng này thấp".
Đưa vào quy trình
| Chặng | Yêu cầu |
|---|---|
| Definition of Ready | Hạng mục có luồng user thì phải liệt kê danh sách event trong acceptance criteria |
| Code review | Tên event đúng quy ước, không gửi thuộc tính bị cấm |
| Definition of Done | Đã kiểm chứng event bắn đúng trên build thật, không chỉ đúng trong code |
| Sau release | Funnel của luồng mới được xem trong buổi soát hằng tuần đầu tiên |
Dòng thứ ba hay bị bỏ. Event viết trong code mà không kiểm chứng trên build thật thì tỷ lệ sai khá cao: bắn nhầm chỗ, bắn hai lần, hoặc không bắn vì bị chặn ở lớp cấu hình.
Giới hạn
- Đừng đo tất cả. Mỗi event là chi phí bảo trì, chi phí lưu trữ và một rủi ro riêng tư. Chỉ đo thứ sẽ dẫn tới quyết định.
- Event đo được cái gì đã xảy ra, không đo được vì sao. Vì sao thì phải hỏi user — xem Quality metrics cho ranh giới giữa hai loại câu hỏi này.
- Dữ liệu analytics luôn có sai số: chặn quảng cáo, mất mạng, app bị kill trước khi gửi. Dùng nó để so sánh tương đối giữa các version, đừng dùng làm con số tuyệt đối để đối chiếu với kế toán.

