Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Hệ thống tracking active, retention rate - Phần 2
Trước hết xin nhắc lại mục đích của bài viết này là đưa ra giải pháp build-from-scratch cho bài toán sau:
Tôi có một ứng dụng A, tôi đang liên kết với các đối tác {C_1, C_2, ..., C_n} để phát triển user cho sản phẩm. Vậy làm thế nào để tôi có thể xác định được độ hiệu quả cũng như chất lượng của tập user mỗi đối tác mang lại?
Phần trước của bài viết đã trình bày các nội dung chính sau:
- Các metrics cần đo cho bài toán
- Mô hình phân kênh và tracking data
- Mô tả cách implement trên client/server
Phần tiếp theo của bài viết tập trung trình bày một số show-case trích xuất dữ liệu phức tạp hơn. Qua đó cho bạn đọc thấy được chỉ cần kết hợp mô hình dữ liệu tracking khá đơn giản với việc sử dụng Elastic Search query linh hoạt là có thể thu được hầu hết các metrics cần thiết cho bài toán chính mà bài viết nêu ra.
Tính active user trong khoảng thời gian [start, end] và [start-1, end-1]
Cặp giá trị này thường được dùng để thể hiện số liệu trong khoảng thời gian người dùng dashboard chọn và phần trăm tăng giảm so với kì trước.
Elastic Search cho phép trả về nhiều aggregrations trong cùng query nên để tính cặp giá trị này ta chỉ cần dùng query như dưới đây.
def active_user_in_range(start_time_epoch, end_time_epoch):
q = {
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"terms": {
"action": ["FIRST_RUN", "START"]
}
},
{
"range": {
"created": {
"gte": (start_time_epoch - 86400000),
"lte": (end_time_epoch)
}
}
}
]
}
}
}
},
"aggs": {
"range_active_devices_current": {
"filter": {
"range": {
"created": {
"gt": start_time_epoch
}
}
},
"aggs": {
"unique_devices": {
"cardinality": {"field": "device_id"}
}
}
},
"range_active_devices_past": {
"filter": {
"range": {
"created": {
"lt": end_time_epoch - 86400000
}
}
},
"aggs": {
"unique_devices": {
"cardinality": {"field": "device_id"}
}
}
}
}
}
...
Tính active user mỗi ngày trong các khoảng thời gian [start, end] và [start-1, end-1]
Ta có thể dùng Histogram Aggregation cho thống kê này
def au_histogram_in_range(start_time_epoch, end_time_epoch):
past_start_time = start_time_epoch - 86400000
past_end_time = end_time_epoch - 86400000
q = {
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"terms": {
"action": ["FIRST_RUN", "START"]
}
},
{
"range": {
"created": {"gte": past_start_time, "lte": end_time_epoch}
}
}
]
}
}
}
},
"aggs": {
"range_active_devices_current": {
"filter": {
"range": {
"created": {
"gte": start_time_epoch
}
}
},
"aggs": {
"active_histogram": {
"histogram": {
"field": "created",
"interval": 86400000,
"min_doc_count": 0,
"extended_bounds": {
"min": start_time_epoch,
"max": end_time_epoch
}
},
"aggs": {
"unique": {
"cardinality": {
"field": "device_id"
}
}
}
}
}
},
"range_active_devices_past": {
"filter": {
"range": {
"created": {
"lte": past_end_time,
}
}
},
"aggs": {
"active_histogram": {
"histogram": {
"field": "created",
"interval": 86400000,
"min_doc_count": 0,
"extended_bounds": {
"min": past_start_time,
"max": past_end_time,
}
},
"aggs": {
"unique": {
"cardinality": {
"field": "device_id"
}
}
}
}
}
}
}
}
...
Với dữ liệu trên, ta có thể vẽ biểu đồ thống kê active như dưới đây
Tính số lượng user mang lại bởi đối tác C_k, cài ứng dụng vào ngày X và vẫn active sau ngày X+Y
Đây là thông số cơ sở cho các thống kê về retention rate, nó cho ta biết chất lượng cài đặt mà đối tác C_k mang lại có thực sự tốt hay không.
Việc này tương đương với việc đếm các START event sau ngày X+Y mà có FIRST_RUN rơi vào ngày X và có thông số channel_id là C_k
def count_active_users(channel_id, product_id, install_date, elapsed_days):
fr_lower = install_date
fr_upper = install_date + 86400000
c_lower = install_date + elapsed_days * 86400000
c_upper = c_lower + 86400000
q = {
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"terms": {
"action": [
"START"
]
}
},
{
"range": {
"first_run": {"gte": fr_lower, "lte": fr_upper}
}
},
{
"range": {
"created": {"gte": c_lower, "lte": c_upper}
}
}
]
}
}
}
},
"aggs": {
"active_users": {
"cardinality": {
"field": "device_id"
}
}
},
"_source": []
}
try:
active_count = es.search(index=index_name, doc_type=doc_type, body=q, search_type='count')
return active_count['aggregations']['active_users']['value']
except Exception as e:
print e
return 0
Tại sao không dùng Firebase, Fabric, Parse luôn đi?
Firebase, Fabric, Parse đều có cung cấp tính năng tracking rồi, vậy tại sao không dùng luôn đi mà lại build from scratch làm gì?
Câu trả lời nằm ở chỗ các giải pháp cloud-based nói trên có rất nhiều hạn chế cho nhu cầu phân kênh khi số lượng đối tác của bạn rất lớn (thường là không có API hoàn chỉnh và có giới hạn về số lượng custom event).
Nếu bạn đang làm hệ thống quảng cáo (người viết bài này ko làm gì liên quan đến hệ thống quảng cáo cả ), hay đang làm các ứng dụng lớn như trình duyệt Yolo Browser, UC Browser, phải làm việc với rất nhiều đối tác publishers thì việc tự xây dựng hệ thống tracking là không tránh được.
Lời kết
Bài viết đưa ra hướng implement cho một hệ thống tracking chạy được. Việc chạy như thế nào sẽ còn phụ thuộc rất nhiều vào quá trình implement cụ thể:
- Kiến trúc server-side, đặc biệt là phần thiết kế cài đặt Elastic Search
- Khai thác sâu hơn chức năng indexing/search của Elastic Search
- Tricks tối ưu phía client-side ...
Một trong những hạn chế rất lớn trong phần document trên trang chủ của Elastic Search đó là document viết các phần râu ria rất nhiều nhưng các ví dụ minh hoạ lại quá sơ sài. Theo kinh nghiệm của cá nhân người viết bài thì để khắc phục việc này ta có thể tra cứu phần REST API của Elastic Search
https://github.com/elastic/elasticsearch/tree/master/core/src/main/java/org/elasticsearch/rest




