在 React Native SDK 中处理用户引导事件
在使用编辑工具配置用户引导时,会生成一系列事件供应用响应。事件的处理方式取决于你使用的呈现方式:
- 模态呈现:需要设置事件处理器,统一处理所有用户引导视图的事件
- React 组件:通过组件内联回调参数直接处理事件
开始之前,请确保:
- 您已安装 Adapty React Native SDK 3.8.0 或更高版本。
- 您已创建用户引导。
- 您已将用户引导添加到版位。
如需在移动应用中控制或监听用户引导页面上发生的事件,请实现事件处理程序:
对于 React 组件,你可以通过 AdaptyOnboardingView 组件中各自的事件处理器 props 来处理事件:
function MyOnboarding({ onboarding }) {
const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => {}, []);
const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => {}, []);
const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => {}, []);
const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => {}, []);
const onStateUpdated = useCallback<OnboardingEventHandlers['onStateUpdated']>((action, meta) => {}, []);
const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => {}, []);
const onError = useCallback<OnboardingEventHandlers['onError']>((error) => {}, []);
return (
<AdaptyOnboardingView
onboarding={onboarding}
style={styles.container}
onAnalytics={onAnalytics}
onClose={onClose}
onCustom={onCustom}
onPaywall={onPaywall}
onStateUpdated={onStateUpdated}
onFinishedLoading={onFinishedLoading}
onError={onError}
/>
);
}
对于模态展示,请实现事件处理方法。
多次调用 setEventHandlers 会覆盖你提供的处理器,替换这些特定事件的默认处理器和之前设置的处理器。
const view = await createOnboardingView(onboarding);
const unsubscribe = view.setEventHandlers({
onAnalytics(event, meta) {
// 追踪分析事件
},
onClose(actionId, meta) {
// 处理关闭操作
view.dismiss();
return true;
},
onCustom(actionId, meta) {
// 处理自定义操作
},
onPaywall(actionId, meta) {
// 处理付费墙操作
},
onStateUpdated(action, meta) {
// 处理用户输入更新
},
onFinishedLoading(meta) {
// 用户引导加载完成
},
onError(error) {
// 处理加载错误
},
});
try {
await view.present();
} catch (error) {
// 处理错误
}
对于 SDK 版本 < 3.14,仅支持模态展示方式:
const view = await createOnboardingView(onboarding);
const unsubscribe = view.registerEventHandlers({
onAnalytics(event, meta) {
// 追踪分析事件
},
onClose(actionId, meta) {
// 处理关闭操作
view.dismiss();
return true;
},
onCustom(actionId, meta) {
// 处理自定义操作
},
onPaywall(actionId, meta) {
// 处理付费墙操作
},
onStateUpdated(action, meta) {
// 处理用户输入更新
},
onFinishedLoading(meta) {
// 用户引导加载完成
},
onError(error) {
// 处理加载错误
},
});
try {
await view.present();
} catch (error) {
// 处理错误
}
事件类型
以下各节介绍了您可以处理的不同类型的事件,无论您使用哪种展示方式。
处理自定义动作
在编辑工具中,你可以为按钮添加 custom 动作并为其指定一个 ID。
然后,你可以在代码中使用这个 ID,并将其作为自定义操作来处理。例如,当用户点击自定义按钮(如 Login 或 Allow notifications)时,事件处理程序会被触发,并附带与编辑工具中 Action ID 对应的 actionId 参数。你可以自定义 ID,比如 “allowNotifications”。
function MyOnboarding({ onboarding }) {
const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => {
switch (actionId) {
case 'login':
login();
break;
case 'allow_notifications':
allowNotifications();
break;
}
}, []);
return (
<AdaptyOnboardingView
onboarding={onboarding}
style={styles.container}
onCustom={onCustom}
/>
);
}
const view = await createOnboardingView(onboarding);
const unsubscribe = view.setEventHandlers({
onCustom(actionId, meta) {
switch (actionId) {
case 'login':
login();
break;
case 'allow_notifications':
allowNotifications();
break;
}
},
});
const view = await createOnboardingView(onboarding);
const unsubscribe = view.registerEventHandlers({
onCustom(actionId, meta) {
switch (actionId) {
case 'login':
login();
break;
case 'allow_notifications':
allowNotifications();
break;
}
},
});
事件示例(点击展开)
{
"actionId": "allow_notifications",
"meta": {
"onboardingId": "onboarding_123",
"screenClientId": "profile_screen",
"screenIndex": 0,
"screensTotal": 3
}
}
完成加载用户引导
当用户引导完成加载时,会触发以下事件:
function MyOnboarding({ onboarding }) {
const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => {
console.log('Onboarding loaded:', meta.onboardingId);
}, []);
return (
<AdaptyOnboardingView
onboarding={onboarding}
style={styles.container}
onFinishedLoading={onFinishedLoading}
/>
);
}
const view = await createOnboardingView(onboarding);
const unsubscribe = view.setEventHandlers({
onFinishedLoading(meta) {
console.log('Onboarding loaded:', meta.onboardingId);
},
});
const view = await createOnboardingView(onboarding);
const unsubscribe = view.registerEventHandlers({
onFinishedLoading(meta) {
console.log('Onboarding loaded:', meta.onboardingId);
},
});
事件示例(点击展开)
{
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "welcome_screen",
"screen_index": 0,
"total_screens": 4
}
}
关闭用户引导
当用户点击已分配 Close 动作的按钮时,用户引导即视为关闭。
请注意,当用户关闭用户引导时,你需要自行处理后续逻辑,例如停止显示用户引导界面。
function MyOnboarding({ onboarding, navigation }) {
const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => {
navigation.goBack();
}, [navigation]);
return (
<AdaptyOnboardingView
onboarding={onboarding}
style={styles.container}
onClose={onClose}
/>
);
}
const view = await createOnboardingView(onboarding);
const unsubscribe = view.setEventHandlers({
onClose(actionId, meta) {
await view.dismiss();
return true;
},
});
const view = await createOnboardingView(onboarding);
const unsubscribe = view.registerEventHandlers({
onClose(actionId, meta) {
await view.dismiss();
return true;
},
});
事件示例(点击展开)
{
"action_id": "close_button",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "final_screen",
"screen_index": 3,
"total_screens": 4
}
}
打开付费墙
如果想在用户引导内打开付费墙,请处理此事件。如果想在付费墙关闭后再打开新的付费墙,有一种更直接的方式——处理关闭操作,直接打开付费墙,无需依赖事件数据。
在用户引导中使用付费墙最顺畅的方式,是将操作 ID 设置为与付费墙版位 ID 相同。
function MyOnboarding({ onboarding }) {
const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => {
openPaywall(actionId);
}, []);
return (
<AdaptyOnboardingView
onboarding={onboarding}
style={styles.container}
onPaywall={onPaywall}
/>
);
}
const openPaywall = async (placementId) => {
// Implement your paywall opening logic here
};
请注意,在 iOS 上,同一时间只能显示一个视图(付费墙或用户引导)。如果你在用户引导上方展示付费墙,则无法以编程方式控制后台的用户引导。尝试关闭用户引导时,实际上会关闭付费墙,导致用户引导仍然可见。为避免此问题,请始终在展示付费墙之前先关闭用户引导视图。
const view = await createOnboardingView(onboarding);
const unsubscribe = view.setEventHandlers({
onPaywall(actionId, meta) {
view.dismiss().then(() => {
openPaywall(actionId);
});
},
});
const openPaywall = async (placementId) => {
// Implement your paywall opening logic here
};
请注意,在 iOS 上,同一时间只能显示一个视图(付费墙或用户引导)。如果在用户引导之上呈现付费墙,则无法通过代码控制后台的用户引导。此时尝试关闭用户引导,实际上会关闭付费墙,导致用户引导仍然可见。为避免此问题,请务必在呈现付费墙之前先关闭用户引导视图。
const view = await createOnboardingView(onboarding);
const unsubscribe = view.registerEventHandlers({
onPaywall(actionId, meta) {
view.dismiss().then(() => {
openPaywall(actionId);
});
},
});
const openPaywall = async (placementId) => {
// 在此处实现你的付费墙打开逻辑
};
事件示例(点击展开)
{
"action_id": "premium_offer_1",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "pricing_screen",
"screen_index": 2,
"total_screens": 4
}
}
追踪导航
在用户引导流程中,当各类导航相关事件发生时,你会收到相应的分析事件:
function MyOnboarding({ onboarding }) {
const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => {
trackEvent(event.name, meta.onboardingId);
}, []);
return (
<AdaptyOnboardingView
onboarding={onboarding}
style={styles.container}
onAnalytics={onAnalytics}
/>
);
}
const view = await createOnboardingView(onboarding);
const unsubscribe = view.setEventHandlers({
onAnalytics(event, meta) {
trackEvent(event.name, meta.onboardingId);
},
});
const view = await createOnboardingView(onboarding);
const unsubscribe = view.registerEventHandlers({
onAnalytics(event, meta) {
trackEvent(event.name, meta.onboardingId);
},
});
event 对象可以是以下类型之一:
| 类型 | 描述 |
|---|
onboardingStarted | 用户引导加载完成时触发 |
screenPresented | 任意页面显示时触发 |
screenCompleted | 页面完成时触发。包含可选字段 elementId(已完成元素的标识符)和可选字段 reply(用户的响应)。当用户执行任意操作离开当前页面时触发。 |
secondScreenPresented | 第二个页面显示时触发 |
userEmailCollected | 用户通过输入框提交邮箱时触发 |
onboardingCompleted | 用户到达 ID 为 final 的页面时触发。如需使用此事件,请为最后一个页面分配 final ID。 |
unknown | 用于任何无法识别的事件类型。包含 name(未知事件的名称)和 meta(附加元数据) |
每个事件都包含 meta 信息,具体字段如下: | |
| 字段 | 说明 |
|---|
onboardingId | 用户引导流程的唯一标识符 |
screenClientId | 当前屏幕的标识符 |
screenIndex | 当前屏幕在流程中的位置 |
screensTotal | 流程中的屏幕总数 |
事件示例(点击展开)
// onboardingStarted
{
"name": "onboarding_started",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "welcome_screen",
"screen_index": 0,
"total_screens": 4
}
}
// screenPresented
{
"name": "screen_presented",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "interests_screen",
"screen_index": 2,
"total_screens": 4
}
}
// screenCompleted
{
"name": "screen_completed",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "profile_screen",
"screen_index": 1,
"total_screens": 4
},
"params": {
"element_id": "profile_form",
"reply": "success"
}
}
// secondScreenPresented
{
"name": "second_screen_presented",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "profile_screen",
"screen_index": 1,
"total_screens": 4
}
}
// userEmailCollected
{
"name": "user_email_collected",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "profile_screen",
"screen_index": 1,
"total_screens": 4
}
}
// onboardingCompleted
{
"name": "onboarding_completed",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "final_screen",
"screen_index": 3,
"total_screens": 4
}
}