Hiển thị paywall được nhắm mục tiêu AA khi khởi chạy lần đầu trong Capacitor SDK
Attribution từ Apple Ads (AA) được gửi về 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 kịp về, nên getFlow sẽ trả về kết quả theo đối tượng mặc định và người dùng đến từ Apple Ads sẽ bỏ lỡ paywall được nhắm mục tiêu theo AA. Thay vì chờ attribution về rồi mới hiển thị paywall, hãy hiển thị ngay một paywall và làm mới nó khi attribution AA được áp dụng — như vậy người dùng Apple Ads sẽ thấy đúng biến thể được nhắm mục tiêu, còn những người dùng khác không phải chờ đợi gì. AdaptyProfile.appliedAttributionSources cho bạn biết khi nào attribution AA đã được áp dụng.
Trước khi bắt đầu
Bạn cần:
- Adapty Capacitor SDK 3.17.1 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ẽ ngầm yêu cầu dữ liệu attribution từ Apple Ads và chuyển kết quả về backend của Adapty. Khi AA trở thành nguồn attribution đang hoạt động của hồ sơ người dùng, SDK sẽ gửi một AdaptyProfile đã cập nhật đến listener onLatestProfileLoad của bạn, với 'apple_search_ads' trong mảng appliedAttributionSources.
Nhờ đó, bạn có thể tải paywall theo hai bước:
- Gọi
getFlowngay lập tức. Vì chưa có attribution nào được áp dụng, Adapty sẽ xử lý yêu cầu dựa trên đối tượng mặc định, do đó người dùng thấy paywall ngay lập tức. - Khi
'apple_search_ads'xuất hiện, gọi lạigetFlow. Adapty lúc này sẽ 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, thay thế paywall trước đó.
appliedAttributionSources có thể rỗng hoặc vắng mặt. Điều đó có nghĩa là:
- Attribution của Apple Ads chưa được xử lý cho hồ sơ người dùng này, hoặc
- chưa có attribution nào được ghi nhận.
Dù thế nào, bước 1 vẫn an toàn — Adapty xử lý yêu cầu dựa trên đối tượng phù hợp với trạng thái hồ sơ hiện tại, thường là đối tượng mặc định. Bước 2 chỉ chạy khi
'apple_search_ads'xuất hiện.
Ở mọi lần khởi động tiếp theo, hồ sơ đã được cache sẵn sẽ có 'apple_search_ads' trong appliedAttributionSources, nên lần getFlow đầu tiên đã trả về paywall được phân khúc theo Apple Ads — không có lần fetch thứ hai hay thay đổi nào hiển thị ra. Luồng hai bước chỉ quan trọng ở lần khởi động đầu tiên, khi attribution vẫn đang được xử lý.
Triển khai
Hiển thị paywall ngay lập tức, sau đó lắng nghe sự kiện 'apple_search_ads' và làm mới paywall khi nhận được.
- Kích hoạt SDK. Xem Cài đặt & cấu hình Capacitor SDK.
- Tải và hiển thị paywall bằng
getFlownhư bình thường — đừng chặn luồng chờ attribution. - Đăng ký nhận cập nhật hồ sơ người dùng với
adapty.addListener('onLatestProfileLoad', …)và theo dõi'apple_search_ads'. Khi xuất hiện, tải lại paywall và hiển thị phiên bản đã cập nhật. Nếu bạn chưa thiết lập listener, xem Lắng nghe cập nhật gói đăng ký:
const listener = await adapty.addListener('onLatestProfileLoad', async ({ profile }) => {
if (!profile.appliedAttributionSources?.includes('apple_search_ads')) return;
const targeted = await adapty.getFlow({ placementId });
// present the targeted flow in place of the first one
});
// Call listener.remove() after the upgrade, or after a timeout (see below).
- Dừng lắng nghe sau một khoảng thời gian chờ. Hầu hết người dùng không có attribution từ Apple Ads, vì vậy hãy xóa listener sau một thời gian thay vì giữ nó suốt cả phiên. Hãy cấu hình paywall dự phòng cho placement đó để người dùng luôn thấy gì đó nếu yêu cầu thất bại.
Ví dụ hoàn chỉnh
onAppleAdsAttribution sẽ resolve khi attribution của Apple Ads được áp dụng, hoặc reject sau timeoutMs. Ví dụ dưới đây tải paywall ngay lập tức, sau đó tải lại khi attribution được nhận — người dùng Apple Ads sẽ thấy paywall đúng mục tiêu, và nếu attribution không bao giờ đến thì paywall đầu tiên vẫn được giữ nguyên:
const APPLE_ADS_SOURCE = 'apple_search_ads';
const placementId = 'YOUR_PLACEMENT_ID';
function hasAppleAdsAttribution(profile: AdaptyProfile): boolean {
return profile.appliedAttributionSources?.includes(APPLE_ADS_SOURCE) ?? false;
}
/**
* Resolves once Apple Ads attribution is applied to the profile.
* Rejects with a timeout error if attribution never arrives within `timeoutMs`.
* Call after `adapty.activate()`.
*/
export function onAppleAdsAttribution(timeoutMs: number): Promise<void> {
return new Promise((resolve, reject) => {
let timer: ReturnType<typeof setTimeout> | undefined;
let handle: { remove: () => void } | undefined;
const stop = () => {
clearTimeout(timer);
handle?.remove();
};
adapty
.addListener('onLatestProfileLoad', ({ profile }) => {
if (!hasAppleAdsAttribution(profile)) return;
stop();
resolve();
})
.then(listener => {
handle = listener;
});
timer = setTimeout(() => {
stop();
reject(new Error(`Apple Ads attribution timed out after ${timeoutMs}ms`));
}, timeoutMs);
});
}
let flow = await adapty.getFlow({ placementId });
onAppleAdsAttribution(30_000)
.then(() => adapty.getFlow({ placementId }))
.then(updated => {
flow = updated;
})
.catch(() => {
console.log('Apple Ads attribution or loading failed');
});
Khi khởi động lần đầu, người dùng Apple Ads có thể thấy thoáng qua paywall mặc định trước khi nó được thay thế. Nếu bạn hiển thị paywall bằng Paywall Builder, hãy cân nhắc xem việc hiển thị lại có chấp nhận được không, hoặc chỉ áp dụng cập nhật trước khi paywall được hiển thị. Hãy điều chỉnh timeoutMs theo thời gian bạn sẵn sàng chờ — attribution nếu có thường đến trong vài giây sau khi khởi động.
Nếu ứng dụng của bạn đã lắng nghe onLatestProfileLoad 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ì. adapty.addListener hỗ trợ nhiều listener độc lập, vì vậy listener này sẽ được thêm vào mà không ảnh hưởng đến các listener khác.