Phân tích Cohort Retention theo kênh tiếp thị: Đánh giá hiệu quả TikTok Ads vs Facebook bằng cách phân tích tỷ lệ giữ chân theo tuần/tháng đầu tiên
Trong thế giới eCommerce, việc đo lường hiệu quả của từng kênh tiếp thị không chỉ dừng lại ở CAC (Chi phí thu hút khách hàng) hay ROAS (Lợi nhuận trên chi tiêu quảng cáo). Một chỉ số quan trọng hơn cả là tỷ lệ giữ chân (retention) – khách hàng từ kênh nào gắn bó lâu dài với thương hiệu? Theo báo cáo của Cục TMĐT Việt Nam (2024), 68% doanh nghiệp Việt sử dụng Facebook Ads và 45% sử dụng TikTok Ads, nhưng chỉ 32% trong số đó đo lường được tỷ lệ giữ chân khách hàng theo từng kênh. Điều này dẫn đến việc phân bổ ngân sách quảng cáo thiếu chính xác, lãng phí tiền bạc vào những kênh mang lại lượng người dùng “ảo” – đăng ký rồi biến mất sau vài ngày.
Bài viết này sẽ hướng dẫn chi tiết cách triển khai một hệ thống phân tích cohort retention theo kênh tiếp thị, tập trung so sánh hiệu quả giữa TikTok Ads và Facebook Ads. Bạn sẽ được cung cấp đầy đủ: workflow tổng quan, lựa chọn công nghệ, bảng chi phí, timeline, tài liệu bàn giao, rủi ro, KPI, checklist go‑live và đặc biệt là các đoạn code/config thực tế để “cầm lên làm được ngay”. Tất cả được đúc kết từ kinh nghiệm 12+ năm triển khai eCommerce quy mô 100‑1000 tỷ/tháng tại Việt Nam và Đông Nam Á.
1. Tổng quan workflow
Luồng dữ liệu từ nguồn đến báo cáo được thiết kế như sau (sử dụng Google Cloud Platform làm nền tảng chính):
+----------------+ +----------------+ +----------------+
| Facebook Ads | | TikTok Ads | | Website/App |
| API | | API | | Events |
+-------+--------+ +-------+--------+ +--------+-------+
| | |
v v v
+-------+--------------------+----------------+--------+-------+
| Cloud Scheduler |
| (Trigger daily) |
+--------------------------+---------------------------------+
|
v
+--------------------------+---------------------------------+
| Cloud Functions |
| (Python scripts to fetch data) |
+--------------------------+---------------------------------+
|
v
+--------------------------+---------------------------------+
| Cloud Storage |
| (Raw JSON/CSV files) |
+--------------------------+---------------------------------+
|
v
+--------------------------+---------------------------------+
| BigQuery |
| (Staging tables, transformations) |
+--------------------------+---------------------------------+
|
v
+--------------------------+---------------------------------+
| Scheduled Queries |
| (Cohort calculation) |
+--------------------------+---------------------------------+
|
v
+--------------------------+---------------------------------+
| Data Studio |
| (Dashboard with cohort matrix) |
+------------------------------------------------------------+
Giải thích:
- Cloud Scheduler kích hoạt hàng ngày (ví dụ 2h sáng) để chạy các Cloud Functions.
- Cloud Functions chứa mã Python gọi API của Facebook Ads và TikTok Ads, đồng thời nhận dữ liệu sự kiện từ website/app (qua GA4 hoặc Measurement Protocol) rồi lưu raw vào Cloud Storage.
- Dữ liệu từ Cloud Storage được tự động nạp vào BigQuery (có thể dùng BigQuery Data Transfer Service hoặc Cloud Functions).
- Scheduled Queries trong BigQuery (hoặc dbt) sẽ tính toán cohort retention mỗi ngày.
- Kết quả được hiển thị trên Data Studio (Looker Studio) dưới dạng bảng nhiệt (heatmap) và biểu đồ đường.
2. Lựa chọn công nghệ
Có nhiều cách để xây dựng hệ thống này. Dưới đây là so sánh 4 tech stack phổ biến:
| Tiêu chí | GCP Stack (BigQuery + Data Studio) | AWS Stack (Redshift + QuickSight) | Self‑hosted (PostgreSQL + Metabase) | SaaS (Mixpanel/Amplitude) |
|---|---|---|---|---|
| Chi phí ban đầu | Thấp (chỉ trả theo lượng dùng) | Trung bình | Cao (mua server, nhân lực) | Cao (subscription) |
| Thời gian triển khai | 2‑3 tuần | 4‑6 tuần | 6‑8 tuần | 1 tuần |
| Khả năng mở rộng | Tốt, tự động scale | Tốt, tự động scale | Hạn chế, cần nâng cấp phần cứng | Tốt, nhưng giới hạn gói |
| Bảo trì | Google lo phần infra | AWS lo phần infra | Tự lo toàn bộ | Nhà cung cấp lo |
| Tích hợp Ads API | Dễ dàng với Python | Dễ dàng với Python | Tự làm | Có sẵn connector |
| Dashboard | Data Studio miễn phí | QuickSight trả phí | Metabase miễn phí | Có sẵn |
| Phù hợp quy mô | 100‑1000 tỷ/tháng | Lớn hơn 1000 tỷ/tháng | Nhỏ, dữ liệu dưới 10GB | Mọi quy mô nhưng đắt |
⇒ Lựa chọn tối ưu: GCP Stack vì chi phí thấp, triển khai nhanh, dễ bảo trì và phù hợp với đa số doanh nghiệp vừa và nhỏ tại Việt Nam. Ngoài ra, Data Studio miễn phí, dễ sử dụng cho team Marketing.
3. Chi phí triển khai và vận hành (3 năm)
Giả định lưu lượng:
– 10 triệu sự kiện/tháng
– 100.000 người dùng mới/tháng
– Dữ liệu ads khoảng 1 GB/tháng
Bảng chi phí chi tiết (đơn vị: VND):
| Hạng mục | Năm 1 | Năm 2 | Năm 3 | Ghi chú |
|---|---|---|---|---|
| 1. Phát triển | ||||
| – Phân tích yêu cầu (10 ngày × 3.000.000) | 30.000.000 | – | – | |
| – Thiết kế hệ thống (15 ngày × 3.000.000) | 45.000.000 | – | – | |
| – Lập trình ETL (30 ngày × 3.000.000) | 90.000.000 | – | – | |
| – Lập trình Dashboard (10 ngày × 3.000.000) | 30.000.000 | – | – | |
| – Kiểm thử & fix (10 ngày × 3.000.000) | 30.000.000 | – | – | |
| Tổng phát triển | 225.000.000 | 0 | 0 | |
| 2. Vận hành & bảo trì | ||||
| – Nhân sự vận hành (0.5 FTE, 10tr/tháng) | 120.000.000 | 120.000.000 | 120.000.000 | 12 tháng × 10.000.000 |
| – Nâng cấp nhỏ (5 ngày/năm × 3.000.000) | 15.000.000 | 15.000.000 | 15.000.000 | |
| 3. Dịch vụ Cloud (GCP) | ||||
| – BigQuery (storage + query) | 6.000.000 | 6.000.000 | 6.000.000 | ~500.000/tháng (ước tính) |
| – Cloud Storage | 2.400.000 | 2.400.000 | 2.400.000 | ~200.000/tháng |
| – Cloud Functions | 3.600.000 | 3.600.000 | 3.600.000 | ~300.000/tháng |
| – Cloud Scheduler | 600.000 | 600.000 | 600.000 | ~50.000/tháng |
| – Network egress | 12.000.000 | 12.000.000 | 12.000.000 | ~1.000.000/tháng |
| – Data Studio | 0 | 0 | 0 | Miễn phí |
| Tổng chi phí hàng năm | 384.000.000 | 159.000.000 | 159.000.000 | |
| Tổng chi phí 3 năm | 702.000.000 |
Lưu ý: Chi phí trên mang tính tham khảo, có thể thay đổi tùy quy mô dữ liệu và thị trường.
4. Các bước triển khai chi tiết (Phases)
Dự án được chia thành 8 phase lớn, mỗi phase bao gồm các công việc cụ thể, người phụ trách và timeline.
Phase 1: Chuẩn bị & thu thập yêu cầu (2 tuần)
Mục tiêu: Xác định rõ KPI, nguồn dữ liệu, quyền truy cập API và thiết kế sơ bộ.
Công việc:
- Họp với bộ phận Marketing để thống nhất:
- Định nghĩa cohort: theo ngày đăng ký tài khoản hay ngày mua hàng đầu tiên? (thường chọn ngày đăng ký)
- Chu kỳ phân tích: tuần (7 ngày) hay tháng (30 ngày)? (nên dùng tuần vì phản ánh nhanh hơn)
- Khoảng thời gian theo dõi: 4 tuần, 8 tuần hay 12 tuần? (tùy ngành, thường 12 tuần)
- Các kênh cần so sánh: Facebook Ads, TikTok Ads, Organic, v.v.
- Lấy quyền truy cập:
- Facebook Business Manager: tạo App, lấy Access Token với quyền
ads_read. - TikTok Business Center: tạo App, lấy Access Token với quyền
report.read.
- Facebook Business Manager: tạo App, lấy Access Token với quyền
- Thiết lập Google Cloud Project: tạo project, kích hoạt APIs (BigQuery, Cloud Storage, Cloud Functions, Cloud Scheduler).
- Tạo service account và cấp quyền cần thiết.
- Thiết kế schema cơ sở dữ liệu cho raw events và bảng ads cost.
Người phụ trách: Business Analyst, Data Engineer, Marketing Manager.
Timeline: Tuần 1 → Tuần 2.
Dependency: Không.
Phase 2: Thu thập dữ liệu từ Ads (Facebook & TikTok) (3 tuần)
Mục tiêu: Xây dựng pipeline tự động lấy dữ liệu chiến dịch quảng cáo hàng ngày.
Công việc:
- Viết script Python sử dụng Facebook Marketing API để lấy dữ liệu chiến dịch, adset, ad với các metrics: impressions, clicks, spend, conversions (purchase). Lưu raw dạng CSV/JSON lên Cloud Storage.
- Viết script Python tương tự cho TikTok Ads API.
- Đóng gói script thành Cloud Functions, cấu hình environment variables (token, account ID).
- Thiết lập Cloud Scheduler gọi Cloud Functions mỗi ngày một lần (sau khi dữ liệu đã sẵn sàng, thường 2h sáng).
- Xây dựng cơ chế retry và cảnh báo khi fail.
Người phụ trách: Data Engineer.
Timeline: Tuần 3 → Tuần 5.
Dependency: Phase 1 hoàn thành.
Phase 3: Thu thập dữ liệu người dùng từ website/app (2 tuần)
Mục tiêu: Đảm bảo mọi sự kiện đăng ký, mua hàng, hoạt động của người dùng đều được ghi nhận kèm thông tin nguồn (UTM parameters, click ID).
Công việc:
- Triển khai Google Tag Manager (GTM) trên website/app để gửi sự kiện đến Google Analytics 4 (GA4) và đồng thời gửi raw event trực tiếp đến BigQuery thông qua Measurement Protocol hoặc Data Import.
- Cấu hình GA4 export sang BigQuery (tích hợp sẵn, dễ dàng).
- Đảm bảo mỗi event có đủ các trường:
user_id,session_id,event_timestamp,event_name, và các tham số nhưsource,medium,campaign,content,term,gclid,fbclid,ttclid. - Kiểm tra dữ liệu mẫu, xác nhận tracking đúng.
Người phụ trách: Frontend Developer, Data Engineer.
Timeline: Tuần 3 → Tuần 4 (song song với Phase 2).
Dependency: Phase 1 hoàn thành.
Phase 4: Xây dựng ETL pipeline và tính toán cohort (3 tuần)
Mục tiêu: Tạo pipeline tổng hợp dữ liệu hàng ngày, tính toán retention theo cohort và kênh.
Công việc:
- Thiết kế bảng staging và fact trong BigQuery:
raw_events: dữ liệu thô từ GA4.ads_cost: dữ liệu quảng cáo từ Facebook và TikTok.dim_campaign: thông tin chiến dịch (nếu cần).
- Viết SQL query (hoặc dbt model) để tính cohort retention. Ví dụ:
- Xác định cohort date dựa trên sự kiện
sign_upđầu tiên của mỗi user. - Tính số user còn hoạt động (có sự kiện
purchasehoặcsession_start) ở các tuần tiếp theo. - Kết hợp với thông tin kênh từ UTM parameters.
- Xác định cohort date dựa trên sự kiện
- Tạo Scheduled Query trong BigQuery chạy hàng ngày sau khi dữ liệu mới được nạp.
- Tối ưu hiệu năng: partition theo ngày, cluster theo trường thường query.
- Tích hợp dữ liệu chi phí từ ads để tính CAC và LTV (nếu cần).
Người phụ trách: Data Engineer, Data Analyst.
Timeline: Tuần 6 → Tuần 8.
Dependency: Phase 2 và Phase 3 hoàn thành.
Phase 5: Xây dựng Dashboard báo cáo (2 tuần)
Mục tiêu: Cung cấp giao diện trực quan để team Marketing theo dõi retention theo từng kênh.
Công việc:
- Kết nối Data Studio với BigQuery (sử dụng bảng cohort đã tính).
- Thiết kế dashboard:
- Cohort matrix (heatmap) hiển thị tỷ lệ giữ chân theo tuần.
- Biểu đồ đường so sánh retention của Facebook Ads và TikTok Ads.
- Bảng chi tiết chi phí, CAC, LTV.
- Filter theo thời gian, chiến dịch, nhóm quảng cáo.
- Kiểm thử với dữ liệu thực tế.
- Đào tạo sơ bộ người dùng.
Người phụ trách: Data Analyst, Marketing Specialist.
Timeline: Tuần 9 → Tuần 10.
Dependency: Phase 4 hoàn thành.
Phase 6: Kiểm thử và tối ưu (2 tuần)
Mục tiêu: Đảm bảo dữ liệu chính xác, pipeline ổn định, dashboard load nhanh.
Công việc:
- Chạy backfill dữ liệu lịch sử (3 tháng) để kiểm tra tính đúng đắn.
- So sánh kết quả với báo cáo hiện có (nếu có) hoặc với công cụ khác (Google Analytics).
- Tối ưu query: sử dụng partition, cluster, materialized view.
- Thiết lập cảnh báo (alert) khi pipeline fail (qua Cloud Monitoring + Slack/Email).
- Kiểm tra security: quyền truy cập, mã hóa dữ liệu nhạy cảm.
Người phụ trách: QA Engineer, Data Engineer.
Timeline: Tuần 11 → Tuần 12.
Dependency: Phase 5 hoàn thành.
Phase 7: Go‑live và bàn giao (1 tuần)
Mục tiêu: Đưa hệ thống vào vận hành chính thức, đào tạo đầy đủ, bàn giao tài liệu.
Công việc:
- Chuyển toàn bộ cấu hình sang môi trường production.
- Đào tạo nhóm Marketing cách sử dụng dashboard, đọc hiểu cohort.
- Bàn giao tài liệu kỹ thuật và hướng dẫn vận hành.
- Ký kết nghiệm thu.
Người phụ trách: Project Manager, Data Engineer, Data Analyst.
Timeline: Tuần 13.
Dependency: Phase 6 hoàn thành.
Phase 8: Vận hành và giám sát (liên tục)
Mục tiêu: Duy trì hệ thống, xử lý sự cố, cập nhật khi API thay đổi.
Công việc:
- Giám sát hàng ngày qua Cloud Monitoring.
- Định kỳ kiểm tra chất lượng dữ liệu (reconciliation với invoice).
- Cập nhật script khi Facebook/TikTok thay đổi API.
- Mở rộng nếu cần thêm kênh (Google Ads, Zalo, v.v.).
Người phụ trách: Data Engineer (Ops).
Timeline: Từ tuần 14 trở đi.
Dependency: Phase 7 hoàn thành.
5. Timeline tổng thể (Gantt)
Dưới đây là bảng timeline chi tiết các phase, thể hiện tuần bắt đầu và kết thúc.
| Phase | Công việc chính | Người phụ trách | Start (Tuần) | End (Tuần) | Dependency |
|---|---|---|---|---|---|
| 1 | Chuẩn bị & thu thập yêu cầu | BA, Data Engineer, Marketing | 1 | 2 | – |
| 2 | Thu thập dữ liệu từ Ads | Data Engineer | 3 | 5 | 1 |
| 3 | Thu thập dữ liệu người dùng | Frontend Dev, Data Engineer | 3 | 4 | 1 |
| 4 | Xây dựng ETL và tính toán cohort | Data Engineer, Data Analyst | 6 | 8 | 2,3 |
| 5 | Xây dựng Dashboard | Data Analyst, Marketing | 9 | 10 | 4 |
| 6 | Kiểm thử và tối ưu | QA, Data Engineer | 11 | 12 | 5 |
| 7 | Go‑live và bàn giao | PM, Data Engineer, Analyst | 13 | 13 | 6 |
| 8 | Vận hành và giám sát | Data Engineer (Ops) | 14+ | ongoing | 7 |
Lưu ý: Một số công việc có thể chạy song song để tiết kiệm thời gian.
6. Danh sách tài liệu bàn giao
Sau khi hoàn thành dự án, các tài liệu sau phải được bàn giao cho khách hàng/đội vận hành.
| STT | Tên tài liệu | Mô tả | Người viết | Ngày BG |
|---|---|---|---|---|
| 1 | Tài liệu yêu cầu nghiệp vụ (BRD) | Mô tả chi tiết yêu cầu, KPI, định nghĩa cohort, các kênh cần theo dõi. | Business Analyst | Tuần 2 |
| 2 | Tài liệu thiết kế hệ thống | Kiến trúc tổng thể, sơ đồ luồng dữ liệu, công nghệ sử dụng. | Solution Architect | Tuần 3 |
| 3 | Tài liệu cấu hình môi trường | Hướng dẫn setup GCP project, service account, IAM, APIs. | Data Engineer | Tuần 4 |
| 4 | Tài liệu hướng dẫn triển khai (Deployment Guide) | Các bước deploy Cloud Functions, Scheduled Queries, Data Studio. | Data Engineer | Tuần 8 |
| 5 | Tài liệu hướng dẫn sử dụng Dashboard | Cách đọc cohort matrix, filter dữ liệu, export báo cáo. | Data Analyst | Tuần 10 |
| 6 | Tài liệu API Integration (Facebook/TikTok) | Thông tin authentication, endpoints, cách xử lý lỗi. | Data Engineer | Tuần 5 |
| 7 | Tài liệu schema cơ sở dữ liệu | Mô tả chi tiết các bảng trong BigQuery, quan hệ, ý nghĩa trường. | Data Engineer | Tuần 6 |
| 8 | Tài liệu ETL Pipeline | Flow xử lý dữ liệu, mã nguồn, giải thích logic. | Data Engineer | Tuần 8 |
| 9 | Tài liệu kiểm thử (Test Cases & Results) | Kết quả test backfill, so sánh với dữ liệu thực tế. | QA Engineer | Tuần 12 |
| 10 | Tài liệu bảo trì (Maintenance Guide) | Các công việc định kỳ, monitoring, xử lý sự cố thường gặp. | Data Engineer (Ops) | Tuần 13 |
| 11 | Tài liệu xử lý sự cố (Troubleshooting) | Hướng dẫn debug khi pipeline fail, cách kiểm tra log. | Data Engineer (Ops) | Tuần 13 |
| 12 | Tài liệu backup & recovery | Quy trình backup dữ liệu, khôi phục khi thảm họa. | Data Engineer (Ops) | Tuần 13 |
| 13 | Tài liệu bảo mật (Security Compliance) | Các biện pháp bảo mật đã áp dụng, tuân thủ GDPR (nếu có). | Security Officer | Tuần 13 |
| 14 | Tài liệu đào tạo (Training Materials) | Slide, video hướng dẫn sử dụng cho team Marketing. | Data Analyst | Tuần 13 |
| 15 | Tài liệu chấp nhận sản phẩm (Sign‑off) | Biên bản nghiệm thu, xác nhận hoàn thành dự án. | Project Manager | Tuần 13 |
7. Rủi ro và phương án dự phòng
Dự án nào cũng tiềm ẩn rủi ro. Dưới đây là những rủi ro chính và cách giảm thiểu.
| Rủi ro | Mức độ | Phương án B | Phương án C |
|---|---|---|---|
| Thay đổi API Facebook/TikTok | Cao | Theo dõi changelog hàng tháng, thiết lập cảnh báo qua email khi API trả lỗi version. | Chuyển sang sử dụng công cụ trung gian như Supermetrics hoặc Fivetran để đảm bảo ổn định. |
| Dữ liệu tracking bị thiếu hoặc sai | Cao | Thiết lập validation tự động: so sánh số session từ GA4 với server log, cảnh báo khi chênh lệch >10%. | Bổ sung dữ liệu từ backup (raw log) và điều chỉnh tracking code. |
| Chi phí GCP vượt dự toán | Trung bình | Tối ưu query, sử dụng partition/cluster, chuyển sang flat‑rate nếu dùng nhiều. | Chuyển sang AWS Redshift Serverless hoặc tự host PostgreSQL. |
| Đội ngũ thiếu kỹ năng về GCP/BigQuery | Trung bình | Thuê consultant từ bên thứ ba hỗ trợ trong giai đoạn đầu. | Đào tạo nhanh cho nhân viên hiện có qua khóa học Google Cloud Skill Boost. |
| Thời gian triển khai chậm | Trung bình | Ưu tiên phát triển theo từng kênh (Facebook trước, TikTok sau). | Tăng cường nhân sự (thêm 1 Data Engineer) để đẩy nhanh tiến độ. |
| Bảo mật dữ liệu (lộ thông tin khách hàng) | Cao | Mã hóa dữ liệu PII, sử dụng VPC Service Controls, cấp quyền IAM tối thiểu. | Thuê dịch vụ bảo mật của Google (Cloud Security Command Center) để giám sát. |
| Pipeline fail liên tục do hết quota API | Thấp | Theo dõi quota, sử dụng retry với exponential backoff. | Nâng cấp tài khoản developer, xin tăng limit. |
8. KPI & công cụ đo lường
Để đảm bảo hệ thống hoạt động hiệu quả, chúng ta cần theo dõi các KPI sau.
| KPI | Mô tả | Công cụ đo | Ngưỡng | Tần suất |
|---|---|---|---|---|
| Độ chính xác dữ liệu | So sánh số liệu từ pipeline với báo cáo gốc (ví dụ: số purchase từ GA4) | Script so sánh trong BigQuery | Sai số < 1% | Hàng tuần |
| Thời gian xử lý ETL | Thời gian từ khi trigger đến khi dữ liệu sẵn sàng trên Data Studio | Stackdriver Logging | < 30 phút | Hàng ngày |
| Độ trễ báo cáo | Khoảng thời gian từ cuối ngày đến khi báo cáo cập nhật | Data Studio timestamp | < 2 giờ | Hàng ngày |
| Số lỗi pipeline | Số lần pipeline failed trong tháng | Cloud Monitoring | 0 | Hàng ngày |
| Tỷ lệ uptime | Thời gian hệ thống khả dụng | Uptime Robot | 99.9% | Liên tục |
| Chi phí vận hành | So với dự toán | GCP Billing Report | Không vượt quá 10% | Hàng tháng |
9. Checklist go‑live (42 items)
Trước khi đưa hệ thống vào production, cần kiểm tra kỹ lưỡng các hạng mục sau.
Nhóm Security & Compliance (9 items)
- [ ] Đã mã hóa dữ liệu nhạy cảm (PII) trong quá trình lưu trữ (BigQuery encryption at rest).
- [ ] Đã cấp quyền IAM theo nguyên tắc least privilege (chỉ service account cần thiết).
- [ ] Đã bật audit logging cho tất cả dịch vụ GCP sử dụng.
- [ ] Đã sử dụng Secret Manager để lưu trữ token Facebook/TikTok (thay vì hard‑code).
- [ ] Đã cấu hình firewall/network tags để giới hạn IP truy cập (nếu có).
- [ ] Đã tuân thủ GDPR/CCPA: có cơ chế xóa dữ liệu theo yêu cầu.
- [ ] Đã thiết lập cảnh báo khi có hoạt động bất thường (ví dụ: truy cập từ IP lạ).
- [ ] Đã vô hiệu hóa các API không sử dụng.
- [ ] Đã kiểm tra penetration test cơ bản (nếu yêu cầu).
Nhóm Performance & Scalability (9 items)
- [ ] Các bảng BigQuery đã được partition theo trường ngày (
event_timestamp,date). - [ ] Các bảng BigQuery đã được cluster theo trường thường dùng (
user_id,source). - [ ] Các query SQL đã được tối ưu (sử dụng
EXPLAINđể kiểm tra). - [ ] Đã thiết lập materialized view cho các query phức tạp (nếu cần).
- [ ] Cloud Functions được cấu hình đủ memory/timeout (256MB, 60s).
- [ ] Đã test load với dữ liệu gấp 2 lần dự kiến.
- [ ] Đã thiết lập quota và alert cho BigQuery (ví dụ: cảnh báo khi query tiêu thụ > 1TB).
- [ ] Đã bật cache cho Data Studio (giảm tải query).
- [ ] Đã thiết kế để dễ dàng mở rộng thêm kênh (Google Ads, Zalo) mà không cần thay đổi kiến trúc.
Nhóm Business & Data Accuracy (10 items)
- [ ] Đã xác nhận mapping giữa UTM parameters và kênh (ví dụ:
utm_source=facebook→ Facebook Ads). - [ ] Đã xác nhận công thức tính retention với bộ phận Marketing.
- [ ] Đã kiểm tra dữ liệu mẫu với báo cáo hiện tại (nếu có) và độ lệch < 2%.
- [ ] Đã validate dữ liệu ads với invoice từ Facebook/TikTok (tổng chi phí hàng tháng khớp).
- [ ] Đã đảm bảo timezone thống nhất (UTC+7) trên toàn hệ thống.
- [ ] Đã thiết lập cảnh báo khi dữ liệu bất thường (ví dụ: số session giảm >20% so với trung bình).
- [ ] Đã kiểm tra việc ghi nhận
user_idxuyên suốt các session (có dùng cookie hoặc login). - [ ] Đã loại trừ bot traffic (sử dụng Google Analytics filter).
- [ ] Đã xác định rõ ngưỡng “hoạt động” (ví dụ: có purchase hoặc session > 5 phút).
- [ ] Đã test với dữ liệu backfill 3 tháng và so sánh xu hướng.
Nhóm Payment & Finance (6 items)
- [ ] Đã tích hợp đầy đủ các trường chi phí từ API (spend, currency).
- [ ] Đã đối soát tổng chi phí hàng ngày với invoice (tự động hoặc bán tự động).
- [ ] Đã thiết lập cảnh báo khi chênh lệch chi phí >5%.
- [ ] Đã mã hóa thông tin thanh toán (nếu có lưu).
- [ ] Đã tuân thủ chính sách hoàn tiền (refund) nếu có.
- [ ] Đã tích hợp với hệ thống kế toán (nếu cần) qua API.
Nhóm Monitoring & Rollback (8 items)
- [ ] Đã thiết lập monitoring cho tất cả job (Cloud Functions, Scheduled Queries) qua Cloud Monitoring.
- [ ] Đã thiết lập cảnh báo qua email/Slack khi job fail.
- [ ] Đã có kịch bản rollback cho từng thành phần (vd: quay lại version cũ của Cloud Function).
- [ ] Đã có backup dữ liệu hàng ngày (BigQuery snapshot, Cloud Storage versioning).
- [ ] Đã có runbook xử lý sự cố thường gặp (ví dụ: API thay đổi, quota hết).
- [ ] Đã test rollback trên môi trường staging.
- [ ] Đã document quy trình khôi phục dữ liệu (restore từ backup).
- [ ] Đã thiết lập health check endpoint cho Cloud Functions.
Tổng cộng: 42 items. (có thể thêm vài item để đủ 42-48, nhưng 42 là đủ)
10. Code / Config thực tế
Dưới đây là các đoạn code/config mẫu để bạn có thể áp dụng ngay vào dự án.
10.1. Cấu hình IAM cho service account (gcloud commands)
# Tạo service account
gcloud iam service-accounts create cohort-sa \
--description="Service account for cohort analysis pipeline" \
--display-name="cohort-sa"
# Gán roles cần thiết
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:cohort-sa@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/bigquery.dataEditor"
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:cohort-sa@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/bigquery.jobUser"
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:cohort-sa@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/storage.objectAdmin"
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:cohort-sa@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/cloudfunctions.invoker"
10.2. Script Python lấy dữ liệu Facebook Ads (Cloud Function)
import os
import json
import datetime
from facebook_business.api import FacebookAdsApi
from facebook_business.adobjects.adaccount import AdAccount
from facebook_business.adobjects.adsinsights import AdsInsights
import pandas as pd
from google.cloud import storage
def fetch_facebook_ads(event, context):
# Config từ environment variables
app_id = os.getenv('FB_APP_ID')
app_secret = os.getenv('FB_APP_SECRET')
access_token = os.getenv('FB_ACCESS_TOKEN')
ad_account_id = os.getenv('FB_AD_ACCOUNT_ID')
FacebookAdsApi.init(app_id, app_secret, access_token)
# Lấy dữ liệu ngày hôm qua
yesterday = (datetime.datetime.now() - datetime.timedelta(days=1)).strftime('%Y-%m-%d')
params = {
'time_range': {'since': yesterday, 'until': yesterday},
'fields': [
'campaign_id','campaign_name','adset_id','adset_name','ad_id','ad_name',
'impressions','clicks','spend','actions'
],
'level': 'ad',
}
insights = AdAccount(ad_account_id).get_insights(params=params)
# Xử lý kết quả
rows = []
for insight in insights:
row = insight.export_all_data()
# Trích xuất số conversions (purchase)
conversions = 0
for action in row.get('actions', []):
if action['action_type'] == 'purchase':
conversions = int(action['value'])
row['conversions'] = conversions
rows.append(row)
# Lưu lên Cloud Storage dạng CSV
df = pd.DataFrame(rows)
client = storage.Client()
bucket = client.bucket('your-bucket-name')
blob = bucket.blob(f'facebook_ads/{yesterday}.csv')
blob.upload_from_string(df.to_csv(index=False), content_type='text/csv')
print(f"Uploaded facebook_ads/{yesterday}.csv")
10.3. Script Python lấy dữ liệu TikTok Ads (Cloud Function)
import requests
import json
import datetime
import os
from google.cloud import storage
def fetch_tiktok_ads(event, context):
# Config
access_token = os.getenv('TT_ACCESS_TOKEN')
advertiser_id = os.getenv('TT_ADVERTISER_ID')
url = "https://business-api.tiktok.com/open_api/v1.2/reports/integrated/get/"
yesterday = (datetime.datetime.now() - datetime.timedelta(days=1)).strftime('%Y-%m-%d')
payload = {
"advertiser_id": advertiser_id,
"service_type": "AUCTION",
"report_type": "BASIC",
"data_level": "AUCTION_AD",
"dimensions": ["campaign_id", "adgroup_id", "ad_id"],
"metrics": ["impressions", "clicks", "cost", "conversion"],
"start_date": yesterday,
"end_date": yesterday,
"page_size": 1000
}
headers = {
"Access-Token": access_token,
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, json=payload)
data = response.json()
if data['code'] != 0:
raise Exception(f"TikTok API error: {data['message']}")
rows = data['data']['list']
# Lưu dạng JSON lên Cloud Storage
client = storage.Client()
bucket = client.bucket('your-bucket-name')
blob = bucket.blob(f'tiktok_ads/{yesterday}.json')
blob.upload_from_string(json.dumps(rows), content_type='application/json')
print(f"Uploaded tiktok_ads/{yesterday}.json")
10.4. Docker Compose cho môi trường phát triển (Airflow, PostgreSQL, Metabase)
version: '3'
services:
postgres:
image: postgres:12
environment:
POSTGRES_USER: airflow
POSTGRES_PASSWORD: airflow
POSTGRES_DB: airflow
ports:
- "5432:5432"
airflow:
image: apache/airflow:2.3.0
environment:
AIRFLOW__CORE__EXECUTOR: LocalExecutor
AIRFLOW__CORE__SQL_ALCHEMY_CONN: postgresql+psycopg2://airflow:airflow@postgres/airflow
AIRFLOW__CORE__LOAD_EXAMPLES: 'false'
ports:
- "8080:8080"
volumes:
- ./dags:/opt/airflow/dags
command: >
bash -c "airflow db init &&
airflow users create --username admin --password admin --firstname Admin --lastname User --role Admin --email [email protected] &&
airflow webserver & airflow scheduler"
depends_on:
- postgres
metabase:
image: metabase/metabase:latest
ports:
- "3000:3000"
environment:
MB_DB_TYPE: postgres
MB_DB_DBNAME: metabase
MB_DB_PORT: 5432
MB_DB_USER: metabase
MB_DB_PASS: metabase
MB_DB_HOST: postgres-metabase
depends_on:
- postgres-metabase
postgres-metabase:
image: postgres:12
environment:
POSTGRES_USER: metabase
POSTGRES_PASSWORD: metabase
POSTGRES_DB: metabase
ports:
- "5433:5432"
10.5. Cloud Function (main.py) gọi các script fetch
import facebook_ads_fetcher
import tiktok_ads_fetcher
def scheduled_fetch(event, context):
facebook_ads_fetcher.fetch_facebook_ads(None, None)
tiktok_ads_fetcher.fetch_tiktok_ads(None, None)
print("Ads data fetched successfully.")
10.6. SQL tạo bảng raw_events trong BigQuery
CREATE TABLE IF NOT EXISTS `project_id.dataset.raw_events`
(
event_timestamp TIMESTAMP,
user_id STRING,
session_id STRING,
event_name STRING,
event_params ARRAY<STRUCT<key STRING, value STRING>>,
traffic_source STRUCT<
source STRING,
medium STRING,
campaign STRING,
content STRING,
term STRING,
gclid STRING,
fbclid STRING,
ttclid STRING
>,
device STRUCT<
category STRING,
mobile_brand_name STRING,
mobile_model_name STRING,
operating_system STRING,
browser STRING
>,
geo STRUCT<
country STRING,
region STRING,
city STRING
>
)
PARTITION BY DATE(event_timestamp)
CLUSTER BY event_name, user_id
OPTIONS(
description="Raw events from website/app"
);
10.7. SQL tạo bảng ads_cost
CREATE TABLE IF NOT EXISTS `project_id.dataset.ads_cost`
(
date DATE,
platform STRING, -- 'facebook' or 'tiktok'
campaign_id STRING,
campaign_name STRING,
adset_id STRING,
adset_name STRING,
ad_id STRING,
ad_name STRING,
impressions INT64,
clicks INT64,
spend FLOAT64,
conversions INT64
)
PARTITION BY date
CLUSTER BY platform, campaign_id
OPTIONS(
description="Daily aggregated ads data from Facebook and TikTok"
);
10.8. SQL tính cohort retention (Scheduled Query)
WITH user_first_activity AS (
SELECT
user_id,
DATE(MIN(event_timestamp)) AS cohort_date,
traffic_source.source AS source,
traffic_source.medium AS medium,
traffic_source.campaign AS campaign
FROM `project_id.dataset.raw_events`
WHERE event_name = 'sign_up' -- hoặc 'first_visit' tùy định nghĩa
GROUP BY user_id, source, medium, campaign
),
user_activity_by_week AS (
SELECT
u.user_id,
u.cohort_date,
u.source,
u.medium,
u.campaign,
DATE_DIFF(DATE(e.event_timestamp), u.cohort_date, WEEK) AS week_number
FROM `project_id.dataset.raw_events` e
JOIN user_first_activity u ON e.user_id = u.user_id
WHERE e.event_name = 'purchase' -- hoặc sự kiện thể hiện hoạt động
GROUP BY 1,2,3,4,5,6
HAVING week_number BETWEEN 0 AND 12 -- theo dõi 12 tuần
),
cohort_size AS (
SELECT
cohort_date,
source,
medium,
campaign,
COUNT(DISTINCT user_id) AS total_users
FROM user_first_activity
GROUP BY 1,2,3,4
),
retention_by_week AS (
SELECT
cohort_date,
source,
medium,
campaign,
week_number,
COUNT(DISTINCT user_id) AS retained_users
FROM user_activity_by_week
GROUP BY 1,2,3,4,5
)
SELECT
c.cohort_date,
c.source,
c.medium,
c.campaign,
r.week_number,
c.total_users,
r.retained_users,
SAFE_DIVIDE(r.retained_users, c.total_users) AS retention_rate
FROM cohort_size c
LEFT JOIN retention_by_week r
ON c.cohort_date = r.cohort_date
AND c.source = r.source
AND c.medium = r.medium
AND c.campaign = r.campaign
ORDER BY 1,5;
10.9. dbt model cho cohort (nếu dùng dbt)
-- models/cohort_retention.sql
{{ config(materialized='table') }}
with user_first_activity as (
select ...
),
...
select ...
10.10. Airflow DAG định nghĩa pipeline
from airflow import DAG
from airflow.operators.python_operator import PythonOperator
from datetime import datetime, timedelta
from my_package import fetch_facebook_ads, fetch_tiktok_ads, load_to_bq, compute_cohort
default_args = {
'owner': 'airflow',
'depends_on_past': False,
'start_date': datetime(2025, 1, 1),
'email_on_failure': True,
'email_on_retry': False,
'retries': 1,
'retry_delay': timedelta(minutes=5),
}
dag = DAG(
'cohort_analysis',
default_args=default_args,
description='Daily pipeline for cohort retention analysis',
schedule_interval='0 2 * * *', # chạy lúc 2h sáng mỗi ngày
catchup=False,
)
t1 = PythonOperator(
task_id='fetch_facebook_ads',
python_callable=fetch_facebook_ads,
dag=dag,
)
t2 = PythonOperator(
task_id='fetch_tiktok_ads',
python_callable=fetch_tiktok_ads,
dag=dag,
)
t3 = PythonOperator(
task_id='load_ads_to_bq',
python_callable=load_to_bq,
dag=dag,
)
t4 = PythonOperator(
task_id='compute_cohort',
python_callable=compute_cohort,
dag=dag,
)
[t1, t2] >> t3 >> t4
10.11. Nginx config để reverse proxy cho Metabase (nếu tự host)
server {
listen 80;
server_name metabase.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# SSL configuration omitted
}
10.12. GitHub Actions CI/CD để deploy Cloud Functions
name: Deploy to GCP
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Deploy Cloud Functions
run: |
gcloud functions deploy fetch-facebook-ads \
--runtime python39 \
--trigger-http \
--entry-point fetch_facebook_ads \
--region asia-southeast1 \
--memory 256MB \
--timeout 60s
gcloud functions deploy fetch-tiktok-ads \
--runtime python39 \
--trigger-http \
--entry-point fetch_tiktok_ads \
--region asia-southeast1 \
--memory 256MB \
--timeout 60s
gcloud functions deploy scheduled-fetch \
--runtime python39 \
--trigger-http \
--entry-point scheduled_fetch \
--region asia-southeast1 \
--memory 256MB \
--timeout 120s
10.13. Script đối soát chi phí (Python)
import pandas as pd
from google.cloud import bigquery
def reconcile_ads_spend():
client = bigquery.Client()
# Lấy tổng chi phí từ pipeline
query = """
SELECT date, platform, SUM(spend) as total_spend
FROM `project_id.dataset.ads_cost`
WHERE date BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY) AND CURRENT_DATE()
GROUP BY date, platform
"""
df_pipeline = client.query(query).to_dataframe()
# Lấy dữ liệu từ invoice (ví dụ từ CSV)
df_invoice = pd.read_csv('invoice.csv')
# Merge và so sánh
merged = pd.merge(df_pipeline, df_invoice, on=['date','platform'], suffixes=('_pipe','_inv'))
merged['diff'] = merged['total_spend_pipe'] - merged['total_spend_inv']
merged['diff_pct'] = merged['diff'] / merged['total_spend_inv'] * 100
# Cảnh báo nếu chênh lệch >5%
for idx, row in merged.iterrows():
if abs(row['diff_pct']) > 5:
send_alert(f"Spend discrepancy on {row['date']} for {row['platform']}: {row['diff_pct']:.2f}%")
print("Reconciliation completed.")
10.14. Data Studio JSON (mẫu cấu hình nguồn dữ liệu)
{
"dataSource": {
"type": "BIGQUERY",
"projectId": "your-project",
"datasetId": "your_dataset",
"tableId": "cohort_retention"
},
"filters": [
{
"fieldName": "source",
"controlType": "DROPDOWN",
"title": "Source"
}
],
"style": {
"theme": "LIGHT"
}
}
11. Công thức tính toán
Retention rate cho một cohort tại tuần thứ ( n ) được tính bằng:
[
\text{Retention Rate}_n = \frac{\text{Số người dùng hoạt động ở tuần } n}{\text{Tổng số người dùng trong cohort}} \times 100\%
]
Trong đó:
- Cohort: nhóm người dùng có cùng ngày đăng ký đầu tiên (hoặc ngày mua hàng đầu tiên).
- Người dùng hoạt động: có ít nhất một sự kiện được chọn (ví dụ: mua hàng, mở app, v.v.) trong tuần đó.
Ma trận cohort thường được biểu diễn dưới dạng:
[
C_{i,j} = \frac{R_{i,j}}{N_i}
]
với ( i ) là ngày cohort, ( j ) là số tuần sau, ( N_i ) là kích thước cohort, ( R_{i,j} ) là số người dùng còn lại ở tuần ( j ).
12. Kết luận
Phân tích cohort retention theo kênh tiếp thị là một công cụ mạnh mẽ giúp doanh nghiệp đánh giá chính xác hiệu quả dài hạn của từng kênh, đặc biệt khi so sánh TikTok Ads và Facebook Ads. Với hệ thống tự động được xây dựng trên nền tảng Google Cloud, bạn có thể triển khai nhanh chóng, chi phí hợp lý và dễ dàng mở rộng.
Key takeaways:
- Sử dụng GCP (BigQuery, Cloud Functions, Data Studio) giúp giảm thiểu chi phí vận hành và thời gian phát triển.
- Pipeline ETL đơn giản nhưng hiệu quả, dễ dàng tùy chỉnh theo nhu cầu.
- Quan trọng nhất là phải tracking đầy đủ UTM parameters và user_id xuyên suốt.
- Kiểm tra chất lượng dữ liệu thường xuyên để đảm bảo độ tin cậy của báo cáo.
Câu hỏi thảo luận: Anh em đã từng triển khai cohort analysis chưa? Có gặp khó khăn gì với TikTok Ads API không? Chia sẻ kinh nghiệm nhé!
💡 Lời khuyên từ Hải: Nếu anh em đang cần tích hợp AI nhanh vào app mà lười build từ đầu, thử ngó qua con Serimi App xem, mình thấy API bên đó khá ổn cho việc scale.
Chúc anh em triển khai thành công!
Nội dung được Hải định hướng, trợ lý AI giúp mình viết chi tiết.








