DHDataHọc
TheoryLesson 7/88 min read+10 XP

Tính năng và adoption

Bạn sẽ học được

  • Đo mức độ sử dụng một tính năng đúng cách.
  • Phân biệt độ phủ (reach) và độ sâu (depth).
  • Tính tỷ lệ chấp nhận theo thời gian kể từ khi ra mắt.
  • Kiểm tra một tính năng có gắn với retention tốt hơn không.
  • Chọn tính năng đáng đầu tư bằng ma trận phủ × giữ chân.

Khái niệm cốt lõi

Tính năng chỉ có giá trị khi có người dùng nó. Câu hỏi thường gặp — "tính năng mới có được dùng không?" — cần trả lời bằng ba con số, không phải một:

Câu hỏiChỉ số
Bao nhiêu người từng dùng?Độ phủ (reach)
Dùng thường xuyên đến mức nào?Tần suất
Dùng sâu đến đâu?Độ sâu (depth)

Một tính năng có 60% người dùng thử một lần rồi bỏ là thất bại. Một tính năng có 8% người dùng nhưng họ dùng hằng ngày có thể là tính năng cốt lõi. Chỉ báo cáo "60% đã dùng" là báo cáo thiếu.

Tỷ lệ chấp nhận

code
WITH nguoi_hoat_dong AS (
  SELECT DISTINCT user_id
  FROM events
  WHERE occurred_at >= CURRENT_DATE - INTERVAL '30 days'
),
nguoi_dung_tinh_nang AS (
  SELECT DISTINCT user_id
  FROM events
  WHERE event_name = 'report_exported'
    AND occurred_at >= CURRENT_DATE - INTERVAL '30 days'
)
SELECT
  (SELECT COUNT(*) FROM nguoi_dung_tinh_nang) AS so_nguoi_dung,
  (SELECT COUNT(*) FROM nguoi_hoat_dong) AS so_nguoi_hoat_dong,
  ROUND(100.0 * (SELECT COUNT(*) FROM nguoi_dung_tinh_nang)
        / NULLIF((SELECT COUNT(*) FROM nguoi_hoat_dong), 0), 1) AS ty_le_pct;

Ba quyết định định nghĩa trong truy vấn này:

  1. Mẫu số: người dùng hoạt động trong kỳ, không phải toàn bộ người dùng đã đăng ký.
  2. Tử số: người dùng đã dùng tính năng ít nhất một lần trong kỳ.
  3. Kỳ: 30 ngày là hợp lý; tính năng dùng theo mùa cần kỳ dài hơn.

Đổi mẫu số từ "người hoạt động" sang "toàn bộ tài khoản" làm tỷ lệ tụt mạnh và không phản ánh đúng. Ghi rõ mẫu số mỗi lần báo cáo.

Độ phủ và độ sâu

code
SELECT
  COUNT(*) FILTER (WHERE so_lan >= 1)  AS tung_dung,
  COUNT(*) FILTER (WHERE so_lan >= 3)  AS dung_deu,
  COUNT(*) FILTER (WHERE so_lan >= 10) AS dung_sau,
  ROUND(AVG(so_lan), 1) AS trung_binh_lan
FROM (
  SELECT user_id, COUNT(*) AS so_lan
  FROM events
  WHERE event_name = 'report_exported'
    AND occurred_at >= CURRENT_DATE - INTERVAL '30 days'
  GROUP BY 1
) t;

Ba mức này cho thấy hình dạng sử dụng: thử một lần (1+), dùng đều (3+), dùng sâu (10+). Nếu "từng dùng" cao nhưng "dùng đều" thấp, vấn đề nằm ở giá trị lặp lại của tính năng, không phải ở khám phá.

Tỷ lệ chấp nhận theo thời gian

Sau khi ra mắt, đo tỷ lệ người dùng mới chấp nhận trong 1, 7, 30 ngày đầu:

code
WITH nguoi_moi AS (
  SELECT user_id, MIN(created_at) AS ngay_dang_ky
  FROM users
  WHERE created_at >= CURRENT_DATE - INTERVAL '90 days'
  GROUP BY 1
),
lan_dau_dung AS (
  SELECT user_id, MIN(occurred_at) AS lan_dau
  FROM events
  WHERE event_name = 'report_exported'
  GROUP BY 1
)
SELECT
  date_trunc('month', n.ngay_dang_ky)::date AS thang,
  COUNT(*) AS so_nguoi_moi,
  COUNT(*) FILTER (WHERE l.lan_dau <= n.ngay_dang_ky + INTERVAL '1 day')   AS trong_1_ngay,
  COUNT(*) FILTER (WHERE l.lan_dau <= n.ngay_dang_ky + INTERVAL '7 days')  AS trong_7_ngay,
  COUNT(*) FILTER (WHERE l.lan_dau <= n.ngay_dang_ky + INTERVAL '30 days') AS trong_30_ngay
FROM nguoi_moi n
LEFT JOIN lan_dau_dung l USING (user_id)
GROUP BY 1
ORDER BY 1;

Cách đọc: nếu tỷ lệ 1 ngày thấp nhưng 30 ngày cao, người dùng cần thời gian mới tìm ra tính năng — cải thiện khám phá sẽ có ích. Nếu cả ba đều thấp, vấn đề nằm ở bản thân tính năng.

Nhớ rằng cohort tháng gần nhất chưa đủ 30 ngày; đánh dấu ô chưa đủ dữ liệu.

Tính năng có gắn với retention không

Đây là câu hỏi khó nhất và cũng dễ trả lời sai nhất. Cách làm cơ bản: so sánh retention giữa nhóm dùng tính năng và nhóm không dùng, trong cùng cohort.

code
WITH cohort AS (
  SELECT user_id, date_trunc('week', created_at) AS tuan
  FROM users
  WHERE created_at >= CURRENT_DATE - INTERVAL '120 days'
),
su_dung AS (
  SELECT DISTINCT user_id
  FROM events
  WHERE event_name = 'report_exported'
    AND occurred_at <= created_at + INTERVAL '7 days'
),
quay_lai AS (
  SELECT DISTINCT user_id
  FROM events
  WHERE occurred_at >= CURRENT_DATE - INTERVAL '28 days'
)
SELECT
  c.tuan,
  COUNT(*) FILTER (WHERE s.user_id IS NOT NULL) AS dung_tinh_nang,
  COUNT(*) FILTER (WHERE s.user_id IS NOT NULL AND q.user_id IS NOT NULL) AS dung_va_quay_lai,
  ROUND(100.0 * COUNT(*) FILTER (WHERE s.user_id IS NOT NULL AND q.user_id IS NOT NULL)
        / NULLIF(COUNT(*) FILTER (WHERE s.user_id IS NOT NULL), 0), 1) AS retention_dung_pct,
  COUNT(*) FILTER (WHERE s.user_id IS NULL) AS khong_dung,
  COUNT(*) FILTER (WHERE s.user_id IS NULL AND q.user_id IS NOT NULL) AS khong_dung_quay_lai,
  ROUND(100.0 * COUNT(*) FILTER (WHERE s.user_id IS NULL AND q.user_id IS NOT NULL)
        / NULLIF(COUNT(*) FILTER (WHERE s.user_id IS NULL), 0), 1) AS retention_khong_dung_pct
FROM cohort c
LEFT JOIN su_dung s USING (user_id)
LEFT JOIN quay_lai q USING (user_id)
GROUP BY 1
ORDER BY 1;

Cách đọc: nếu nhóm dùng tính năng có retention cao hơn rõ rệt và nhất quán qua nhiều cohort, tính năng có thể là động lực giữ chân. Nếu chênh lệch chỉ ở một cohort, đó là nhiễu.

Cảnh báo quan trọng: đây là tương quan, không phải nhân quả. Người dùng gắn bó sẵn có xu hướng thử nhiều tính năng hơn — tính năng không nhất thiết gây ra việc quay lại. Muốn chứng minh nhân quả, cần thử nghiệm: đẩy mạnh khám phá tính năng cho một nhóm ngẫu nhiên rồi so retention.

Ma trận phủ × giữ chân

Đặt từng tính năng lên hai trục:

code
              Giữ chân cao
                    ▲
     Tính năng     │   Tính năng
     ngách         │   cốt lõi
     (giữ nhóm     │   (đầu tư,
      nhỏ)          │    bảo vệ)
  ──────────────────┼──────────────────►  Độ phủ
     Tính năng     │   Tính năng
     cần xem lại   │   phổ thông
     hoặc bỏ       │   (giữ ổn định)
                    │

Bốn góc phần tư dẫn tới bốn quyết định khác nhau:

  • Phủ cao, giữ chân cao: tính năng cốt lõi — bảo vệ chất lượng, đừng làm hỏng.
  • Phủ cao, giữ chân thấp: phổ thông nhưng không tạo gắn bó — giữ ổn định, không cần đầu tư thêm.
  • Phủ thấp, giữ chân cao: ngách có giá trị — cân nhắc mở rộng khám phá.
  • Phủ thấp, giữ chân thấp: xem lại hoặc loại bỏ — mỗi tính năng còn chi phí bảo trì.

Lỗi thường gặp khi đo tính năng

  • Đếm sự kiện thay vì người: COUNT(*) cho ra số lần, không phải số người.
  • Đổi mẫu số: so sánh giữa các kỳ với mẫu số khác nhau.
  • Gộp nhiều tính năng vào một sự kiện: không tách được cái nào hoạt động.
  • Bỏ qua người mới: tính năng dùng sau 30 ngày mới quen bị đánh giá thấp.
  • Kết luận nhân quả từ tương quan: như phần trên.
  • Đo tính năng nội bộ: sự kiện do hệ thống bắn, không phải người dùng.

Thực hành

  1. Tính tỷ lệ chấp nhận của một tính năng trong 30 ngày.
  2. Tính ba mức: từng dùng, dùng đều, dùng sâu.
  3. Tính tỷ lệ chấp nhận trong 1/7/30 ngày theo cohort đăng ký.
  4. So sánh retention giữa nhóm dùng và không dùng.
  5. Đặt ba tính năng lên ma trận phủ × giữ chân và đề xuất hành động.

Lỗi thường gặp

Triệu chứngNguyên nhânCách sửa
Tỷ lệ chấp nhận 100%Mẫu số chỉ gồm người đã dùngDùng người hoạt động làm mẫu số
Tỷ lệ thấp bất thườngMẫu số gồm cả tài khoản bỏ hoangChốt mẫu số người hoạt động
Tính năng "thành công" nhưng retention không tăngChỉ đo lần đầuĐo thêm tần suất và độ sâu
So sánh giữa các tháng lệchĐổi định nghĩaGhi định nghĩa vào metric spec
Kết luận tính năng giữ chânTương quanThử nghiệm ngẫu nhiên
Không tách được tính năngGộp sự kiệnTách sự kiện và thuộc tính

Tóm tắt

  • Đo tính năng bằng ba con số: phủ, tần suất, độ sâu.
  • Mẫu số là người dùng hoạt động; ghi rõ trong mọi báo cáo.
  • Tỷ lệ chấp nhận 1/7/30 ngày cho biết vấn đề nằm ở khám phá hay giá trị.
  • So sánh retention theo nhóm dùng/không dùng chỉ là tương quan.
  • Ma trận phủ × giữ chân giúp quyết định đầu tư, giữ ổn định hay loại bỏ.

Use ← → to move between lessons