Tích hợp AppsFlyer + RevenueCat + TikTok Ads + Meta Ads cho app subscription
Nếu bạn đang xây một mobile subscription app và muốn trả lời được câu hỏi:
Quảng cáo TikTok/Meta nào mang về install, trial và cuối cùng là paid subscriber?
Một architecture tương đối sạch là:
┌── TikTok Advanced SRN
│
Mobile App → AppsFlyer ─── Meta SRN
│ │
│ └── SKAN / AdAttributionKit (iOS)
│
└── RevenueCat
│
├── Trial Started
├── Initial Purchase
├── Trial Converted
└── Renewal
│
└────→ AppsFlyer
Trong setup này:
- AppsFlyer chịu trách nhiệm attribution.
- RevenueCat là source of truth cho subscription/revenue.
- TikTok/Meta nhận conversion postback để đo lường và optimize ads.
- SKAN xử lý privacy-preserving attribution trên iOS.
- ATT/IDFA không bắt buộc để architecture này hoạt động.
1. Hiểu vai trò của từng thành phần
AppsFlyer
AppsFlyer là MMP — Mobile Measurement Partner.
Nó đứng giữa app và các advertising network:
TikTok ──┐
Meta ────┼──→ AppsFlyer ←── App
Google ──┘
Mục đích là xác định:
Install X
↓
đến từ TikTok
↓
Campaign A
↓
Ad Group B
↓
Creative C
Sau đó gắn các event:
install
trial
purchase
revenue
vào acquisition source đó.
2. RevenueCat đóng vai trò gì?
AppsFlyer có thể nhận purchase event trực tiếp từ app, nhưng đối với subscription thì RevenueCat là nguồn đáng tin cậy hơn.
Ví dụ:
Day 0
Start 7-day trial
Day 7
Trial → Paid
Day 37
Renewal
Day 67
Renewal
User không cần mở app vào Day 37 hoặc Day 67.
RevenueCat vẫn biết transaction xảy ra và có thể gửi server-to-server sang AppsFlyer.
RevenueCat chính thức hỗ trợ gửi trial conversion, purchase và renewal sang AppsFlyer, kể cả khi app không mở. (RevenueCat)
Architecture:
App Store / Play Store
↓
RevenueCat
↓
AppsFlyer
↓
TikTok / Meta / ...
Đừng track purchase hai lần
Nếu đã dùng:
RevenueCat → AppsFlyer
thì không nên đồng thời làm:
await Purchases.purchasePackage(pkg);
// DON'T do this as a duplicate revenue event
appsFlyer.logEvent("af_purchase", {
af_revenue: 29.99,
af_currency: "USD"
});
Nếu không:
Purchase
├── App → AppsFlyer
└── RevenueCat → AppsFlyer
↓
2 purchases ❌
RevenueCat cũng yêu cầu remove client-side revenue tracking khi sử dụng AppsFlyer integration. (RevenueCat)
3. Cài AppsFlyer vào Expo React Native
Ví dụ:
npx expo install react-native-appsflyer
Với Expo development build/EAS, AppsFlyer là native module nên sau khi thêm plugin cần build native app lại.
Ví dụ:
eas build --platform ios
preferAppsFlyerBackupRules đôi khi xuất hiện trong Expo config:
[
"react-native-appsflyer",
{
"preferAppsFlyerBackupRules": true
}
]
Option này liên quan đến Android backup/data extraction rules, không phải:
- ATT
- IDFA
- SKAN
- iOS attribution
Nếu chỉ quan tâm iOS thì nó không phải phần quan trọng của integration.
4. Khởi tạo AppsFlyer
Conceptually:
import appsFlyer from "react-native-appsflyer";
appsFlyer.initSdk(
{
devKey: "YOUR_APPSFLYER_DEV_KEY",
appId: "YOUR_APPLE_APP_ID",
isDebug: __DEV__,
onInstallConversionDataListener: true,
onDeepLinkListener: true,
timeToWaitForATTUserAuthorization: 0
},
result => {
console.log("AppsFlyer initialized", result);
},
error => {
console.error(error);
}
);
Nếu không request ATT thì không cần AppsFlyer chờ ATT response.
5. Kết nối AppsFlyer với RevenueCat
Đây là bước rất quan trọng.
RevenueCat cần biết:
RevenueCat customer X
=
AppsFlyer installation Y
RevenueCat yêu cầu:
$appsflyerId
cho AppsFlyer integration.
Các identifier khác như:
$idfa
$gpsAdId
$idfv
$ip
giúp cải thiện attribution matching nhưng $appsflyerId mới là required identifier. (RevenueCat)
Flow:
AppsFlyer
↓
getAppsFlyerUID()
↓
RevenueCat
↓
$appsflyerId
Ví dụ React Native:
appsFlyer.getAppsFlyerUID((error, uid) => {
if (error || !uid) return;
Purchases.setAttributes({
$appsflyerId: uid
});
});
Phải thực hiện:
Configure RevenueCat
↓
Set AppsFlyer ID
↓
User purchase
chứ không nên đợi tới sau purchase mới set ID.
RevenueCat yêu cầu attribution attributes được set sau khi Purchases SDK configure và trước purchase đầu tiên. (RevenueCat)
6. RevenueCat → AppsFlyer
Trong RevenueCat:
Project
→ Integrations
→ AppsFlyer
Điền AppsFlyer developer key.
RevenueCat cho phép sử dụng default event names.
Ví dụ:
Initial purchase
→ rc_initial_purchase_event
Trial started
→ rc_trial_started_event
Trial converted
→ rc_trial_converted_event
Trial cancelled
→ rc_trial_cancelled_event
Renewal
→ rc_renewal_event
Cancellation
→ rc_cancellation_event
RevenueCat cũng hỗ trợ sandbox events nếu cấu hình sandbox API/developer key tương ứng. (RevenueCat)
7. App có cả Trial và Direct Purchase thì map thế nào?
Giả sử app hỗ trợ cả:
A. 7-day trial → paid
B. Buy subscription immediately
Ba event acquisition quan trọng nhất là:
rc_trial_started_event
rc_trial_converted_event
rc_initial_purchase_event
Flow Trial:
Start Trial
↓
rc_trial_started_event
↓
StartTrial
7 days later
↓
Trial converts
↓
rc_trial_converted_event
↓
Subscribe
Flow direct purchase:
Buy Now
↓
rc_initial_purchase_event
↓
Subscribe
Do đó khi gửi sang ad network:
| AppsFlyer event | Advertising event |
|---|---|
rc_trial_started_event |
StartTrial |
rc_trial_converted_event |
Subscribe |
rc_initial_purchase_event |
Subscribe |
Không nên map:
rc_renewal_event → Subscribe
nếu mục đích của Subscribe là acquisition conversion.
Nếu làm vậy:
User subscribes
→ Subscribe #1
Month 2 renew
→ Subscribe #2
Month 3 renew
→ Subscribe #3
sẽ khiến acquisition conversion bị phình lên.
Renewal vẫn rất hữu ích cho:
Revenue
LTV
ROAS
Cohort analysis
nhưng nó không phải một new subscriber.
8. Tại sao AppsFlyer dropdown ban đầu chỉ có vài events?
Ví dụ AppsFlyer chỉ hiện:
af_complete_registration
af_skad_revenue
af_app_opened
Điều này không có nghĩa AppsFlyer chỉ hỗ trợ ba event.
Thông thường AppsFlyer UI ưu tiên những event mà nó đã nhận.
Nếu RevenueCat chưa gửi:
rc_trial_started_event
thì event có thể chưa xuất hiện trong dropdown.
Ở những UI cho phép Add item, có thể manually add exact event name:
rc_trial_started_event
rc_trial_converted_event
rc_initial_purchase_event
Tên phải match chính xác với RevenueCat.
9. TikTok SAN là gì?
TikTok hiện dùng Advanced SRN/SAN integration với AppsFlyer. AppsFlyer liệt kê TikTok for Business Advanced SRN cùng các self-reporting network như Meta, Google Ads, Apple Ads và Snapchat. (AppsFlyer Support)
SAN có thể hiểu đơn giản là:
TikTok có first-party advertising interaction data của chính TikTok và tham gia trực tiếp vào attribution flow với AppsFlyer.
Ví dụ:
User sees TikTok Ad #123
↓
User clicks
↓
App Store
↓
Install
↓
AppsFlyer
↕
TikTok Advanced SRN
TikTok biết:
Campaign
Ad Group
Creative
click/view
...
vì những interactions này xảy ra trên TikTok.
AppsFlyer sau đó đóng vai trò MMP để tổng hợp attribution/reporting giữa nhiều media sources.
10. Kết nối AppsFlyer với TikTok Ads
Trong TikTok Ads Manager:
Tools
→ Events
→ Connect data source
→ App
Chọn:
Mobile Measurement Partner
→ AppsFlyer
→ TikTok for Business
Sau đó trong AppsFlyer:
Collaborate
→ Partner Marketplace / Active Integrations
→ TikTok for Business
Enable integration.
Map subscription events
Map:
rc_trial_started_event
→ StartTrial
rc_trial_converted_event
→ Subscribe
rc_initial_purchase_event
→ Subscribe
Flow cuối cùng:
TikTok Ad
↓
Install
↓
AppsFlyer
↑
RevenueCat
↓
Trial / Purchase
↓
AppsFlyer
↓
TikTok
TikTok có thể sử dụng conversion signal để optimize campaign cho deeper events thay vì chỉ install.
11. Meta có SAN/SRN tương tự không?
Có.
AppsFlyer classify Meta Ads là SRN — Self-Reporting Network. (AppsFlyer Support)
Concept:
Facebook / Instagram Ad
↓
App Store
↓
Install
↓
AppsFlyer
↕
Meta SRN
Vì vậy Meta không hoạt động giống một ad network thông thường chỉ dựa trên attribution tracking link.
12. Tạo Meta App
Trong Meta for Developers:
My Apps
→ Create App
Khi Meta hỏi use case, nếu mục tiêu là chạy mobile app ads, chọn:
Create & manage app ads with Meta Ads Manager
Không cần chọn:
Marketing API
trừ khi muốn tự viết software để programmatically quản lý campaign.
Cũng không cần:
Facebook Login
chỉ để làm attribution.
AppsFlyer xác nhận Facebook Login và Facebook SDK không bắt buộc để thực hiện Meta mobile attribution qua AppsFlyer. (AppsFlyer Support)
13. Kết nối Meta với AppsFlyer
Sau khi tạo Meta App, lấy:
Facebook / Meta App ID
Trong AppsFlyer:
Collaborate
→ Active Integrations
→ Meta ads
Bật integration và nhập Meta App ID.
Sau đó bật:
In-app event postbacks
Map:
rc_trial_started_event
→ StartTrial
rc_trial_converted_event
→ Subscribe
rc_initial_purchase_event
→ Subscribe
AppsFlyer yêu cầu SKAN conversion events phải được map sang Meta event tương ứng nếu muốn Meta sử dụng chúng để optimize; nếu không, Meta có thể chỉ nhận install measurement. (AppsFlyer Support)
14. Events Manager: phải chọn đúng app
Meta Events Manager có thể chứa nhiều loại data source:
Website → Meta Pixel
App → Facebook SDK / MMP
Dataset
Nếu đang setup một app mới, đừng chọn dataset của app khác chỉ vì nó đã có sẵn.
Ví dụ:
Lịch Ta
📱 Facebook SDK
FitFo
📱 MMP
Nếu đang setup FitFo thì phải sử dụng data source/app của FitFo.
Không reuse App ID/dataset của Lịch Ta.
15. SKAN là gì?
SKAdNetwork — SKAN — là privacy-preserving attribution framework của Apple.
Nó hoạt động mà không cần IDFA và không cần ATT consent. (AppsFlyer Support)
Concept:
Ad
↓
Install
↓
Apple SKAN
↓
privacy-safe postback
↓
Ad network / AppsFlyer
Điểm quan trọng:
SKAN ≠ SAN
SAN/SRN
TikTok/Meta ↔ AppsFlyer
Network sử dụng first-party advertising data và integration với MMP.
SKAN
Apple
↓
privacy-preserving attribution
Hai hệ thống có thể cùng tồn tại:
┌── TikTok Advanced SRN
TikTok campaign ─┤
└── Apple SKAN
↓
AppsFlyer
16. Có phải tự code SKAN không?
Nếu dùng AppsFlyer SKAN solution thì phần lớn là không.
AppsFlyer nói rõ với SKAN solution:
- dùng AppsFlyer SDK hiện tại;
- không cần thay đổi app logic riêng cho SKAN;
- gửi in-app events bình thường;
- AppsFlyer SDK xử lý conversion value;
- không cần đăng ký một process SKAN đặc biệt trong App Store. (AppsFlyer Support)
Do đó không cần tự làm kiểu:
SKAdNetwork.updatePostbackConversionValue(...)
nếu AppsFlyer đang là SDK quản lý conversion value.
17. SKAN Conversion Studio
Trong AppsFlyer:
Settings
→ SKAN Conversion Studio
SKAN 4+ có ba measurement windows:
Window 1
1–2 days
Window 2
3–7 days
Window 3
8–35 days
AppsFlyer xác nhận ba measurement periods này trong SKAN solution. (AppsFlyer Support)
Điều này rất quan trọng với subscription app.
Ví dụ app có:
7-day trial
thì:
Window 1
Install
↓
Trial Started
trong khi:
Window 2 / later
Trial
↓
Paid subscription
có thể xảy ra nhiều ngày sau.
Do đó không nên thiết kế SKAN schema chỉ quanh immediate revenue.
18. Revenue measurement trong SKAN
Nếu Conversion Studio hỏi:
Revenue source
○ Overall revenue
○ In-app event
đừng chọn rc_trial_started_event làm revenue source.
Trial started không phải revenue.
Nếu muốn đo tổng purchase revenue thì:
Overall revenue
thường hợp lý hơn.
Còn:
Trial Started
Subscription
là conversion behavior/event measurement.
Đây là hai khái niệm khác nhau.
19. Meta + SKAN interoperability
Meta có thêm một integration quan trọng.
AppsFlyer ↔ Meta có thể chia sẻ SKAN conversion-value schema:
AppsFlyer
│
│ CV schema
▼
Meta
Meta
│
│ decoded SKAN data
▼
AppsFlyer
AppsFlyer cho biết khi interoperability được enable:
- AppsFlyer SDK quản lý conversion values;
- Meta chia sẻ SKAN postback data cho AppsFlyer;
- AppsFlyer chia sẻ CV schema với Meta. (AppsFlyer Support)
Trong AppsFlyer:
Collaborate
→ Active Integrations
→ Meta ads
→ SKAN
Login Meta account có quyền phù hợp.
Sau đó AppsFlyer có thể hiện:
Waiting for sync
và sau khi sync:
Data was pulled successfully
AppsFlyer cho biết dữ liệu SKAN Meta được đồng bộ theo chu kỳ, không nhất thiết xuất hiện ngay lập tức. (AppsFlyer Support)
20. MMP Connection URL cho Meta
AppsFlyer cung cấp MMP Connection URL cho Meta SKAN integration.
Trong Meta Events Manager:
App
→ Settings
→ Configure events
→ Import from Partner App
Paste AppsFlyer MMP Connection URL.
Mục đích:
AppsFlyer CV schema
↓
Meta
Sau lần connection đầu tiên, khi thay đổi measurement settings trong AppsFlyer, không cần paste URL lại. AppsFlyer cho biết Meta có thể mất tới khoảng 24 giờ để nhận measurement configuration mới. (AppsFlyer Support)
21. Có cần ATT không?
Không phải chỉ vì cài AppsFlyer.
SKAN hoạt động:
without IDFA
without ATT consent
theo AppsFlyer. (AppsFlyer Support)
Nếu không request ATT:
ATT permission ❌
IDFA ❌
AppsFlyer ID ✅
SKAN ✅
RevenueCat ✅
TikTok/Meta MMP ✅
Nếu user cho ATT:
ATT Allow
↓
IDFA available
↓
deterministic/device-level matching tốt hơn
RevenueCat cũng coi $idfa là recommended chứ không phải required cho AppsFlyer integration. (RevenueCat)
Do đó với một indie app mới, có thể bắt đầu mà không show ATT prompt, rồi chỉ thêm ATT nếu có use case rõ ràng cho IDFA-based tracking.
22. TestFlight và sandbox
Nếu test bằng TestFlight + RevenueCat sandbox, một check rất hữu ích là RevenueCat customer attributes phải có:
$appsflyerId = ...
Nếu thấy giá trị này, connection:
AppsFlyer SDK
↓
AppsFlyer UID
↓
RevenueCat
đã hoạt động.
Nhưng:
RevenueCat has AppsFlyer ID
không đồng nghĩa:
RevenueCat has already sent a subscription event to AppsFlyer
Muốn event xuất hiện phải thực sự xảy ra lifecycle event:
Trial Started
Purchase
Trial Converted
Renewal
...
RevenueCat cũng hỗ trợ sandbox event delivery khi sandbox credentials được cấu hình. (RevenueCat)
TestFlight/sandbox chủ yếu hữu ích để verify:
RevenueCat
↓
AppsFlyer S2S
Nó không phải full production SKAN campaign attribution test.
23. Android: Google Play Data Safety
Đây là phần rất dễ bỏ sót.
Sau khi thêm AppsFlyer SDK vào Android, Google Play Data Safety declaration có thể cần thay đổi.
Google yêu cầu developer khai báo cả dữ liệu được third-party SDK collect/share, không chỉ code do developer tự viết.
AppsFlyer Android SDK mặc định collect Google Advertising ID — GAID đối với app trên Google Play. (AppsFlyer Support)
GAID thuộc nhóm:
Device or other IDs
Do đó nếu Data Safety trước đây khai:
Device or other IDs
Collected: No
thì sau khi thêm AppsFlyer cần review lại.
AppsFlyer Data Safety guidance nói Android SDK mặc định collect GAID và nếu app gửi in-app events thì App activity cũng có thể cần được khai báo tùy configuration. (AppsFlyer Support)
24. Collected và Shared không giống nhau
Google Play phân biệt:
Collected
và:
Shared
AppsFlyer có thể hoạt động như service provider xử lý dữ liệu thay developer.
Nhưng nếu AppsFlyer được cấu hình gửi data tới advertising partners thông qua:
postbacks
SRNs
audiences
AppsFlyer cảnh báo việc đó có thể được Google xem là sharing, và developer phải đánh giá declaration dựa trên configuration thực tế. (AppsFlyer Support)
Ví dụ architecture:
App
↓
AppsFlyer
↓
├── TikTok
└── Meta
khác về Data Safety implications so với:
App
↓
AppsFlyer only
Do đó không nên copy một Data Safety template chung cho mọi app.
25. Device or other IDs trên Android
Với AppsFlyer Android mặc định:
GAID
↓
Device or other IDs
AppsFlyer xác nhận GAID được tự động collect trên Google Play apps từ SDK v4.8.0 trở đi. (AppsFlyer Support)
Nếu muốn disable advertising identifiers, AppsFlyer cung cấp privacy-preserving configuration để làm điều đó.
Nhưng nếu mục tiêu của việc cài AppsFlyer là:
TikTok Ads attribution
+
Meta Ads attribution
thì việc tắt GAID cần được cân nhắc kỹ vì nó làm mất một deterministic attribution signal hữu ích trên Android.
26. Architecture cuối cùng
Một setup gọn cho subscription app chạy cả TikTok và Meta:
┌─────────────────────┐
│ TikTok Ads │
│ Advanced SRN │
└─────────▲───────────┘
│
│ postbacks
│
┌──────────────┐ ┌────────┴─────────┐
│ │ │ │
│ Mobile App ├─────────►│ AppsFlyer │
│ │ │ │
└──────┬───────┘ └────────▲─────────┘
│ │
│ │ S2S
▼ │
┌──────────────┐ │
│ RevenueCat ├───────────────────┘
└──────────────┘
│
│
│ subscription truth
▼
┌────────────────────┐
│ App Store / Google │
│ Play │
└────────────────────┘
AppsFlyer
│
├──────────────► Meta SRN
│
└──────────────► SKAN / Apple attribution
RevenueCat events:
rc_trial_started_event
↓
StartTrial
rc_trial_converted_event
↓
Subscribe
rc_initial_purchase_event
↓
Subscribe
rc_renewal_event
↓
Revenue/LTV
↓
NOT a new Subscribe conversion
27. Recommended implementation order
Đừng setup mọi dashboard cùng lúc. Làm theo thứ tự này sẽ dễ debug hơn:
1. Install AppsFlyer SDK
↓
2. Verify app opens/install in AppsFlyer
↓
3. Install/configure RevenueCat
↓
4. Pass $appsflyerId → RevenueCat
↓
5. Configure RevenueCat → AppsFlyer
↓
6. Test trial/purchase
↓
7. Verify rc_* events reach AppsFlyer
↓
8. Connect TikTok Advanced SRN
↓
9. Map Trial/Subscribe events
↓
10. Connect Meta SRN
↓
11. Map Trial/Subscribe events
↓
12. Configure SKAN Conversion Studio
↓
13. Configure Meta SKAN interoperability
↓
14. Update Google Play Data Safety
↓
15. Launch campaigns
Đây cũng là thứ tự dễ troubleshoot nhất: mỗi layer được verify trước khi thêm layer tiếp theo.
28. Checklist trước khi chạy ads
App
- AppsFlyer SDK initialized.
- RevenueCat SDK initialized.
- AppsFlyer UID được set thành RevenueCat
$appsflyerId. - Không duplicate client-side purchase tracking.
RevenueCat
- AppsFlyer integration enabled.
- Developer/S2S credentials đúng.
- Trial event configured.
- Initial purchase configured.
- Trial conversion configured.
- Sandbox credentials configured nếu muốn test sandbox delivery.
TikTok
- TikTok for Business Advanced SRN connected.
rc_trial_started_event → StartTrial.rc_trial_converted_event → Subscribe.rc_initial_purchase_event → Subscribe.
Meta
- Meta App riêng cho đúng mobile app.
- Meta App ID connected với AppsFlyer.
- Meta in-app event postbacks enabled.
- Trial/Subscribe events mapped.
- Meta SKAN interoperability configured nếu chạy iOS SKAN campaigns.
iOS
- AppsFlyer SKAN measurement enabled.
- Conversion schema phù hợp với trial duration.
- ATT chỉ thêm nếu thực sự cần IDFA.
Android
- Review Google Play Data Safety.
- Review
Device or other IDs. - Review
App activity. - Review
CollectedvsShareddựa trên AppsFlyer partner/postback configuration.
Kết luận
Điểm quan trọng nhất là đừng coi AppsFlyer, RevenueCat, TikTok/Meta và SKAN là bốn hệ thống làm cùng một việc.
Mỗi cái giải quyết một layer:
RevenueCat
= chuyện gì xảy ra với subscription?
AppsFlyer
= subscriber đó đến từ đâu?
TikTok / Meta SRN
= quảng cáo/campaign/creative nào tạo ra user đó?
SKAN
= Apple cho phép đo attribution thế nào khi không có IDFA?
ATT
= app có được quyền truy cập IDFA/tracking hay không?
Khi tách đúng trách nhiệm, architecture trở nên khá đơn giản:
Ad
↓
Install
↓
AppsFlyer attribution
↓
RevenueCat subscription lifecycle
↓
AppsFlyer
↓
Ad network conversion postback
↓
Campaign optimization
Đối với subscription app có cả free trial và direct purchase, ba acquisition signals quan trọng nhất thường là:
Trial Started
Direct Subscription
Trial → Paid Conversion
RevenueCat giữ subscription truth, AppsFlyer giữ attribution truth, còn TikTok/Meta sử dụng những signal đó để tìm thêm user có khả năng trở thành subscriber.