Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng công ty của bạn vừa chi 500 triệu đồng cho một chiến dịch quảng cáo Tết trên TikTok để kéo người dùng tải app. Ba tuần sau, đội marketing họp khẩn: dashboard Firebase báo tỷ lệ chuyển đổi từ "mở app" sang "hoàn tất mua hàng" chỉ có 2%, thấp thảm hại. Cả team hoảng loạn, chuẩn bị cắt ngân sách, đổ lỗi cho creative. Nhưng rồi một bạn QA phát hiện ra sự thật: sự kiện purchase_completed bị gắn nhầm — nó chỉ bắn (fire) khi người dùng bấm nút "Xác nhận" ở màn hình cuối, nhưng trên iOS phiên bản 2.4 nút đó gọi sai callback nên event không bao giờ được gửi đi. Doanh số thật vẫn tốt; chỉ có dữ liệu là sai. Chiến dịch suýt bị giết oan vì một con số dối trá.
Đây chính là lý do Mobile Analytics & Event QA tồn tại. Trong thế giới sản phẩm số hiện đại, gần như mọi quyết định — từ ưu tiên tính năng, phân bổ ngân sách, đến đánh giá A/B test — đều dựa trên dữ liệu hành vi người dùng thu thập qua các "sự kiện" (event) bắn từ app. Nếu dữ liệu này sai, mọi quyết định phía trên nó đều sai theo. Người ta hay nói "garbage in, garbage out". Là QA, bạn là tuyến phòng thủ cuối cùng đảm bảo rằng những con số mà ban lãnh đạo nhìn vào phản ánh đúng thực tế. Đây là một mảng testing ít được dạy bài bản nhưng cực kỳ giá trị — và làm tốt nó sẽ khiến bạn nổi bật giữa đám đông QA chỉ biết kiểm thử UI.
Khái niệm cốt lõi
Analytics event là gì?
Một analytics event là một bản ghi mô tả một hành động hoặc trạng thái xảy ra trong app, được app gửi lên máy chủ phân tích. Mỗi event thường gồm ba phần:
- Tên event (event name): ví dụ
screen_view,add_to_cart,checkout_started. - Thuộc tính (properties/parameters): cặp key-value mô tả ngữ cảnh, ví dụ
product_id: "SP1234",price: 299000,currency: "VND". - User/session context: thông tin về người dùng và phiên, như
user_id,device_model,app_version,platform.
membership_tier: "gold" hay city: "Ha Noi", dùng để phân khúc (segment) khi phân tích.Các công cụ phổ biến ở Việt Nam
Trong bối cảnh Việt Nam và Đông Nam Á, bạn sẽ thường xuyên gặp những công cụ sau:
- Firebase Analytics (Google): miễn phí, tích hợp sẵn trong hệ sinh thái Firebase, là lựa chọn mặc định của phần lớn startup Việt. Mạnh về event cơ bản và liên kết với Crashlytics, Remote Config. Nhược điểm: giao diện phân tích funnel/cohort không sâu bằng công cụ chuyên biệt, và có độ trễ báo cáo (thường vài giờ).
- Mixpanel: rất mạnh về event-rich analysis — cho phép định nghĩa nhiều event và thuộc tính chi tiết, phân tích hành vi tinh vi. Nhiều công ty product-led ở VN dùng cho phân tích sâu.
- Amplitude: tập trung vào funnel (phễu chuyển đổi) và cohort (nhóm người dùng theo thời gian), rất được ưa chuộng bởi các đội growth. Giao diện trực quan cho việc dựng phễu nhiều bước.
- AppsFlyer / Adjust: đây là các MMP (Mobile Measurement Partner), chuyên đo lường attribution — tức xác định người dùng đến từ nguồn quảng cáo nào. Cực kỳ phổ biến ở VN cho các app thương mại điện tử và game vì gắn với chi tiêu ads. (Attribution sâu là chủ đề của Bài 47, ở đây ta chỉ đề cập ở mức nó cũng nhận event.)
Tracking plan — "hợp đồng" của event
Trái tim của Analytics QA là tracking plan (hay analytics spec / taxonomy). Đây là tài liệu — thường là một Google Sheet hoặc file trong công cụ như Avo, Iteratively — liệt kê chính xác:
- Mỗi event tên là gì, gửi khi nào (trigger).
- Có những thuộc tính nào, kiểu dữ liệu ra sao (string, number, boolean), bắt buộc hay tùy chọn.
- Giá trị hợp lệ (ví dụ
payment_methodchỉ được làmomo,zalopay,card,cod).
Vì sao analytics QA khó?
Khác với test UI (nhìn thấy được) hay test API (có response rõ ràng), analytics event là thứ vô hình — nó âm thầm bắn đi trong nền. Bạn không thể "nhìn" nó bằng mắt thường. Phải dùng công cụ chuyên biệt (DebugView, Charles Proxy, logcat...) để "soi" các event đang được gửi. Đây là điểm khiến nhiều QA bỏ qua mảng này, và cũng là lý do dữ liệu analytics ở rất nhiều công ty đầy lỗi mà không ai biết.
Tình huống thực tế
Tình huống 1: Sự kiện mua hàng bị bắn hai lần ở Tiki-clone
Một sàn thương mại điện tử (gọi là ShopViet) phát hiện báo cáo doanh thu trong Amplitude cao hơn doanh thu thật trong hệ thống backend khoảng 18%. Team growth dùng con số Amplitude để tính ROAS (return on ad spend) và đang định tăng mạnh ngân sách vì "quảng cáo hiệu quả".
QA vào cuộc, mở DebugView của Firebase và bật Charles Proxy, thực hiện một giao dịch mua thử. Kết quả: event purchase bắn hai lần trong vòng 300ms. Nguyên nhân: màn hình xác nhận đơn hàng có gắn tracking trong hàm onResume() của Activity, và trên Android khi người dùng quay lại từ màn hình thanh toán, onResume() được gọi lại lần nữa. Kết quả là mỗi đơn hàng bị đếm gần hai lần trong nhiều trường hợp.
Bài học: Analytics QA phải kiểm tra không chỉ "event có bắn không" mà còn "event có bắn đúng SỐ LẦN không". Duplicate event là một trong những lỗi phổ biến và nguy hiểm nhất vì nó thổi phồng mọi chỉ số. Đặc biệt cảnh giác với event gắn vào lifecycle callback (onResume, viewDidAppear) — chúng dễ bị gọi lại.
Tình huống 2: Thiếu thuộc tính khiến phễu thanh toán "mù"
Một ví điện tử fintech (gọi là PayNhanh) muốn phân tích tại sao người dùng bỏ giữa chừng khi nạp tiền. Họ dựng funnel trong Amplitude: topup_started → topup_method_selected → topup_confirmed → topup_success. Nhưng khi phân tích, họ không thể trả lời được câu hỏi "phương thức nạp nào (MoMo, ngân hàng, thẻ) bị bỏ nhiều nhất?" vì event topup_method_selected không kèm thuộc tính method.
QA đã bỏ sót điều này vì trong lần test trước, họ chỉ kiểm tra event có xuất hiện đúng tên, không đối chiếu đủ danh sách thuộc tính bắt buộc trong tracking plan. Việc bổ sung method phải chờ tới sprint sau và mất thêm hai tuần dữ liệu quý giá trong đúng mùa cao điểm.
Bài học: Event bắn đúng tên nhưng thiếu thuộc tính quan trọng thì cũng như không — dữ liệu mất chiều phân tích. QA phải đối chiếu từng thuộc tính với tracking plan, không chỉ tên event. Một event nghèo thuộc tính là một cơ hội phân tích bị đánh mất vĩnh viễn cho khoảng thời gian đó.
Tình huống 3: PII lọt vào event gây rủi ro pháp lý
Một app đặt xe ở Đông Nam Á vô tình gửi số điện thoại và email người dùng dưới dạng plaintext trong thuộc tính của event ride_completed, do lập trình viên tiện tay gắn cả object user vào tham số. Dữ liệu này chảy vào Firebase và Amplitude — các bên thứ ba. Khi công ty tiến hành audit tuân thủ (compliance), họ phát hiện đã vi phạm chính sách bảo mật của chính mình và tiềm ẩn vi phạm quy định bảo vệ dữ liệu cá nhân (như Nghị định 13/2023 về bảo vệ dữ liệu cá nhân ở Việt Nam).
Bài học: Analytics QA còn có trách nhiệm về quyền riêng tư (privacy). Cần kiểm tra rằng không có PII (Personally Identifiable Information — số điện thoại, email, CMND/CCCD, địa chỉ chính xác) bị gửi trong event trừ khi đã được ẩn danh/băm (hash) và được phép. Đây là loại lỗi âm thầm nhưng hậu quả pháp lý và uy tín rất lớn.
Hướng dẫn từng bước
Đây là quy trình thực chiến để QA một tính năng có gắn analytics:
Bước 1 — Lấy tracking plan làm chuẩn. Trước khi test, mở tracking plan cho tính năng bạn phụ trách. Liệt kê tất cả event kỳ vọng, trigger của chúng, và bảng thuộc tính (tên, kiểu, bắt buộc/tùy chọn, giá trị hợp lệ). Nếu không có tracking plan, hãy làm việc với PM/analyst để tạo tối thiểu một bản cho phạm vi bạn test.
Bước 2 — Chuẩn bị công cụ quan sát. Tùy nền tảng và công cụ:
- Firebase: bật DebugView bằng lệnh
adb shell setprop debug.firebase.analytics.app <package_name>(Android) hoặc thêm arg-FIRDebugEnabled(iOS). DebugView hiển thị event gần như realtime. - Chặn network: dùng Charles Proxy hoặc mitmproxy để bắt các request HTTP gửi tới
app-measurement.com(Firebase),api.mixpanel.com,api2.amplitude.com... Đây là cách "chân lý" nhất vì bạn thấy đúng payload gửi đi. - Android logcat: lọc theo tag
FA(Firebase Analytics) để xem event trong log.
- Event có bắn không?
- Có bắn đúng một lần không (trừ khi thiết kế cho phép nhiều)?
- Tên event có khớp chính xác (kể cả chữ hoa/thường, dấu gạch dưới)?
- Đủ các thuộc tính bắt buộc chưa?
- Kiểu dữ liệu đúng chưa (
pricephải là số299000chứ không phải chuỗi"299.000đ")? - Giá trị nằm trong danh sách hợp lệ chưa (
currencyphải là"VND"chứ không phải"vnd"hay"đồng")? - Có PII lọt vào không?
- Xoay ngang màn hình, tắt/mở lại app giữa chừng — event có bị bắn lặp không?
- Mất mạng khi thao tác — event có được lưu lại và gửi sau khi có mạng (offline queue) không, hay mất luôn?
- Thao tác nhanh liên tục (double-tap) — có tạo event trùng không?
Bước 7 — Ghi nhận và báo cáo. Lập bảng kết quả: event nào PASS, FAIL, hoặc thiếu. Với lỗi analytics, hãy đính kèm ảnh chụp payload thật (từ Charles/DebugView) — bằng chứng cụ thể giúp dev sửa nhanh và tránh tranh cãi.
Lỗi thường gặp & mẹo
Lỗi thường gặp:
- Chỉ test "event có bắn không", bỏ qua thuộc tính và số lần. Đây là lỗi phổ biến nhất. Event đúng tên nhưng sai thuộc tính hoặc bị duplicate vẫn làm hỏng dữ liệu.
- Không có/không dùng tracking plan. Test analytics mà không có chuẩn đối chiếu thì chỉ là cảm tính. Bạn sẽ bỏ sót event thiếu và không phát hiện được lệch chuẩn.
- Quên test hai nền tảng riêng biệt. iOS và Android thường có code tracking riêng. Rất hay gặp cảnh event đúng trên Android nhưng sai/thiếu trên iOS (như tình huống mở đầu). Luôn test cả hai.
- Nhầm giữa debug data và production data. Event bắn ở chế độ debug thường bị lọc riêng và không vào báo cáo chính. Ngược lại, đừng làm bẩn dữ liệu production bằng các phiên test — dùng tài khoản test hoặc thuộc tính
environment: "test"để lọc. - Bỏ qua chuẩn hóa tên (naming convention). Trộn lẫn
snake_casevàcamelCase, hay đặtAddToCartchỗ nàyadd_to_cartchỗ kia, khiến dữ liệu bị phân mảnh — analyst tưởng là hai event khác nhau.
- Dùng Charles Proxy làm "nguồn chân lý". Khi DebugView và log mâu thuẫn, payload HTTP thật trên proxy là bằng chứng cuối cùng về cái gì thực sự được gửi đi.
- Tạo checklist tái sử dụng. Với mỗi event, dùng một mẫu kiểm tra cố định (bắn/đúng số lần/tên/thuộc tính/PII). Điều này biến công việc mơ hồ thành có hệ thống.
- Kết bạn với data analyst. Họ là người tiêu thụ dữ liệu bạn kiểm; họ biết chỉ số nào quan trọng nhất và có thể phát hiện lệch chuẩn từ phía dashboard mà bạn không thấy từ client.
- Nghĩ tới tự động hóa dần. Với các event quan trọng, có thể viết assertion trong test Appium/Espresso để kiểm tra event bắn ra (đọc từ log hoặc mock endpoint), biến analytics QA thành một phần của regression.
Bài tập thực hành
- Dựng tracking plan mini. Chọn một app bạn hay dùng (ví dụ Shopee, Grab, hoặc một app tự phát triển). Viết tracking plan cho luồng "thêm sản phẩm vào giỏ → thanh toán": liệt kê 4–6 event kỳ vọng, trigger, và bảng thuộc tính (tên, kiểu, bắt buộc/tùy chọn) cho mỗi event.
- Soi event thật. Cài Firebase DebugView (hoặc dùng Charles Proxy trên một app demo có Firebase). Thực hiện vài thao tác và ghi lại: event nào bắn ra, kèm những thuộc tính gì. Đối chiếu với tracking plan bạn vừa viết — có event nào thiếu, thừa, hay sai kiểu dữ liệu không?
- Săn lỗi duplicate. Với app demo, thử xoay màn hình, tắt/mở lại app, hoặc double-tap nút thao tác. Quan sát xem có event nào bị bắn lặp không. Ghi lại kịch bản tái hiện.
- Kiểm tra PII. Rà soát payload của 3 event bất kỳ và kiểm tra xem có thuộc tính nào chứa email, số điện thoại, hoặc thông tin định danh cá nhân dạng plaintext không. Viết một bug report giả định nếu phát hiện.
Tóm tắt
Analytics & Event QA là việc đảm bảo các sự kiện hành vi mà app gửi lên các công cụ như Firebase, Mixpanel, Amplitude, AppsFlyer phản ánh đúng những gì người dùng thực sự làm — vì mọi quyết định sản phẩm và ngân sách đều dựa trên dữ liệu này. Nền tảng của công việc là tracking plan đóng vai trò hợp đồng để đối chiếu. QA giỏi không chỉ kiểm "event có bắn không" mà kiểm cả số lần bắn (tránh duplicate), độ đầy đủ và đúng kiểu của thuộc tính, sự đồng nhất giữa iOS và Android, và không rò rỉ PII. Công cụ chính là Firebase DebugView, Charles Proxy/mitmproxy và logcat để "soi" thứ vô hình đó. Ba tình huống thực tế — event mua hàng bị đếm hai lần, phễu thanh toán "mù" vì thiếu thuộc tính, và PII lọt ra ngoài — cho thấy hậu quả rất thật: quyết định sai, mất cơ hội phân tích, và rủi ro pháp lý. Làm tốt mảng này, bạn không chỉ bảo vệ chất lượng app mà còn bảo vệ chính la bàn ra quyết định của cả công ty.