Hiển thị paywall theo mục tiêu AA khi khởi chạy lần đầu trong Flutter SDK
Attribution từ Apple Ads (AA) được nhận bất đồng bộ sau khi gọi Adapty().activate(). Ở lần khởi chạy đầu tiên, dữ liệu này thường chưa có, vì vậy nếu bạn gọi getPaywall ngay lập tức, Adapty sẽ xử lý yêu cầu dựa trên đối tượng mặc định và những người dùng Apple Ads sẽ không thấy paywall được nhắm mục tiêu theo AA. Thay vì hiển thị một paywall rồi thay thế nó, hãy chờ một chút để nhận attribution từ AA trước khi hiển thị bất cứ thứ gì: hiển thị paywall đúng đối tượng nếu attribution đến trong thời gian chờ ngắn, hoặc hiển thị paywall theo đối tượng mặc định nếu không. AdaptyProfile.appliedAttributionSources cho bạn biết khi nào attribution từ AA đã được áp dụng.
Trước khi bắt đầu
Bạn cần:
- Adapty Flutter SDK 3.17.0 trở lên.
- Apple Ads đã được cấu hình cho ứng dụng trong Adapty. Xem Apple Ads.
Cách hoạt động
Sau khi gọi Adapty().activate(), SDK sẽ yêu cầu attribution từ Apple Ads ở chế độ nền và chuyển kết quả đó về backend của Adapty. Khi AA trở thành nguồn attribution đang hoạt động cho hồ sơ người dùng, SDK sẽ gửi một AdaptyProfile đã được cập nhật đến listener didUpdateProfileStream của bạn, với AdaptyAttributionSource.appleAds trong danh sách appliedAttributionSources.
Ở lần chạy đầu tiên, bạn sẽ cần xử lý hai trường hợp:
- Attribution đến trong thời gian chờ của bạn. Gọi
getPaywall— Adapty xử lý yêu cầu dựa trên đối tượng Apple Ads và trả về paywall được nhắm mục tiêu. - Thời gian chờ hết trước. Hiển thị paywall cho đối tượng mặc định thay thế, để người dùng không có attribution Apple Ads không phải chờ đợi.
getPaywallForDefaultAudiencetrả về paywall đó mà không cần chờ phân khúc.
appliedAttributionSources có thể rỗng. Điều đó có nghĩa là:
- Attribution Apple Ads chưa được xử lý cho hồ sơ người dùng này, hoặc
- không có attribution nào đến cả.
Dù thế nào,
getPaywallForDefaultAudiencevẫn an toàn để gọi — nó trả về paywall cho đối tượng mặc định bất kể trạng thái hồ sơ người dùng.
Việc chờ chỉ áp dụng cho lần khởi chạy đầu tiên. Sau khi attribution Apple Ads đã được ghi lại, nó sẽ được lưu trữ vĩnh viễn trên hồ sơ người dùng. Ở mọi lần khởi chạy tiếp theo, hồ sơ người dùng đã được cache sẵn AdaptyAttributionSource.appleAds trong appliedAttributionSources, nên đường dẫn attribution được xử lý ngay lập tức và getPaywall trả về paywall được phân khúc theo Apple Ads mà không có bất kỳ độ trễ nào.
Triển khai
Khi khởi chạy lần đầu, hãy chờ AdaptyAttributionSource.appleAds và áp dụng thời gian chờ tối đa — nếu attribution từ Apple Ads không bao giờ đến, những người dùng đó vẫn cần được xem paywall.
- Kích hoạt SDK. Xem Cài đặt & cấu hình Flutter SDK.
- Đăng ký nhận cập nhật hồ sơ người dùng với
Adapty().didUpdateProfileStream.listen(…). Nếu bạn chưa thiết lập listener, xem Lắng nghe cập nhật gói đăng ký. - Theo dõi
AdaptyAttributionSource.appleAdstrongappliedAttributionSources. Khi nó xuất hiện, tải paywall bằnggetPaywall— Adapty sẽ trả về biến thể được phân khúc theo AA:
final subscription = Adapty().didUpdateProfileStream.listen((profile) async {
if (!profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) return;
final paywall = await Adapty().getPaywall(placementId: placementId);
// present the segmented paywall, then cancel the subscription and the timer
});
didUpdateProfileStream là một broadcast stream và không replay, vì vậy hãy kiểm tra hồ sơ người dùng hiện tại một lần bằng getProfile(). Khi khởi động lại ứng dụng, attribution đã được lưu trữ sẽ không phát lại sự kiện.
4. Bắt đầu đồng hồ đếm ngược 3–5 giây song song với gói đăng ký. Nếu đồng hồ kích hoạt trước khi AdaptyAttributionSource.appleAds xuất hiện, hãy tải paywall cho đối tượng mặc định bằng getPaywallForDefaultAudience. Hiển thị paywall nào được trả về trước và hủy luồng còn lại để tránh tải paywall hai lần. Hãy cấu hình paywall dự phòng cho placement đó để người dùng không bị kẹt nếu yêu cầu mạng thất bại.
Ví dụ đầy đủ
Cách triển khai dưới đây chạy đua giữa attribution và một khoảng timeout, tải trước paywall cho đối tượng mặc định song song, và trả về paywall phù hợp. Phía gọi hàm chỉ cần await một hàm duy nhất — không cần listener hay cờ trạng thái nào ở call site:
- Nếu attribution về kịp trong
timeout, hàm trả về paywall theo phân khúc thông quagetPaywall. - Nếu
timeouthết trước, hàm trả về paywall đối tượng mặc định đã tải trước thông quagetPaywallForDefaultAudience.
/// Returns the Apple Ads-segmented paywall if attribution is applied within
/// [timeout], otherwise the default-audience paywall. Call after Adapty().activate().
Future<AdaptyPaywall> getPaywallOrDefault({
required String placementId,
required Duration timeout,
}) {
// Prefetch the default-audience paywall right away so the timeout path resolves
// without an extra network round-trip. `getPaywallForDefaultAudience` skips the
// wait for segmentation data. `..ignore()` keeps an unused prefetch from surfacing
// as an unhandled error; the error still reaches the caller if this paywall wins.
final defaultPaywall =
Adapty().getPaywallForDefaultAudience(placementId: placementId)..ignore();
final completer = Completer<AdaptyPaywall>();
late final StreamSubscription<AdaptyProfile> subscription;
late final Timer timer;
void resolve(Future<AdaptyPaywall> paywall) {
if (completer.isCompleted) return;
timer.cancel();
subscription.cancel();
completer.complete(paywall);
}
void onProfile(AdaptyProfile profile) {
if (profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) {
resolve(Adapty().getPaywall(placementId: placementId));
}
}
// Attribution path: react to profile updates as attribution is applied.
subscription = Adapty().didUpdateProfileStream.listen(onProfile);
// The stream is a broadcast stream and doesn't replay, so check the current
// profile too — on relaunches attribution is already stored and won't re-emit.
Adapty().getProfile().then(onProfile).ignore();
// Timeout path: fall back to the prefetched default-audience paywall.
timer = Timer(timeout, () => resolve(defaultPaywall));
return completer.future;
}
Gọi từ màn hình splash của bạn, sau đó hiển thị paywall khi promise được giải quyết:
try {
final paywall = await getPaywallOrDefault(
placementId: 'YOUR_PLACEMENT_ID',
timeout: const Duration(seconds: 5),
);
// present the paywall
} on AdaptyError catch (adaptyError) {
// handle the error or show a fallback paywall
} catch (e) {
// handle the error
}
Điều chỉnh timeout theo thời gian bạn muốn người dùng chờ trước khi paywall xuất hiện. Hầu hết người dùng không có attribution từ Apple Ads, nên họ sẽ chờ hết toàn bộ thời gian timeout — 3 đến 5 giây là mức cân bằng hợp lý. Attribution nếu có thường đến trong vài giây sau khi khởi động ứng dụng.
Nếu ứng dụng của bạn đã lắng nghe didUpdateProfileStream cho các mục đích khác (ví dụ: kiểm tra trạng thái gói đăng ký), bạn không cần thay đổi gì. didUpdateProfileStream là một broadcast stream, nên nó hỗ trợ nhiều listener độc lập mà không ảnh hưởng đến nhau.