Capacitor SDKでフローのデータを処理する
ユーザーがフローの入力フィールドに入力したり、クイズに答えたり、トグルを切り替えたりすると、SDKはその値をアナリティクスコールバックを通じてアプリに渡します。
アプリがそのデータを活用する主なユースケースは次のとおりです:
- ユーザーを自社バックエンドに登録する: オンボーディングフローでユーザーが入力したメールアドレスと名前を受け取り、フローが閉じたタイミングでアカウントを作成します。
- 回答や設定を保存する: ユーザーが選択した内容を記録し、アプリが後でそれを活用できるようにします — たとえば、カスタム属性としてAdapty プロファイルに書き込むことができます。
- 今後のフローをカスタマイズする: クイズの回答をカスタム属性として保存し、後のプレースメントをターゲティングすることで、セグメントごとに異なるフローや、その中の異なるペイウォールを表示できます。
- サードパーティの分析プラットフォームに連携する: 回答を Amplitude、Mixpanel、またはお使いのプロダクト分析ツールに転送します。
インプットとセレクタブルグループは、値を自動的に報告します。コード内でインプットを区別するために、ビルダーで各インプットに意味のある Element ID を、各セレクタブルグループに Group ID を設定してください。
始める前に
以下が必要です:
- Adapty SDK v4以降: フローのコールバックは以前のバージョンには存在しません。
- フロー&ペイウォールビルダーで作成されたフロー: コールバックを通じて入力値を報告するのはフローのみです。
- 最近公開されたフローのバージョン: フローがこの機能が利用可能になった後に公開された場合にのみ、入力値を報告します。アプリに何も届かない場合は、フローの新しいバージョンを公開して再試行してください。
入力値を受け取る
入力値は、フローからの他のすべてのアナリティクスイベントと同じハンドラーに、イベント名 flow_user_input として届きます。他のフローイベントハンドラーと一緒に onAnalytics を登録してください。
view.setEventHandlers({
onAnalytics(name, params) {
handleFlowInput(name, params);
return false; // keep the flow open
},
});
onAnalytics コールバックは、スクリーンビューを含む、フローからのすべてのアナリティクスイベントを受け取ります。
nameパラメーターにはイベント名が含まれます。ユーザー入力イベントをフィルタリングするには、nameをflow_user_inputと比較してください。element_typeパラメーターは要素のカテゴリを示します。- 入力値は、要素タイプに応じて異なるパラメーターに格納されます:
- テキストフィールド、ピッカー、トグルはユーザーの入力を
valueに格納します - 選択可能グループはアクティブなオプションを
item_idsとitem_titlesに報告します
- テキストフィールド、ピッカー、トグルはユーザーの入力を
function handleFlowInput(name: string, params: Record<string, unknown>) {
if (name !== 'flow_user_input') return;
// The screen the input sits on. Pair it with element_id to tell apart
// two fields that share an Element ID on different screens.
const screenId = params.instanceId as string;
switch (params.element_type) {
case 'text_input':
case 'email_input':
case 'number_input':
case 'phone_input': {
const text = params.value as string;
break;
}
case 'date_picker':
case 'time_picker':
case 'date_time_picker': {
// Unix time in milliseconds.
const date = new Date(params.value as number);
break;
}
case 'single_choice': {
const optionId = (params.item_ids as string[])[0];
break;
}
case 'multi_choice': {
const optionIds = params.item_ids as string[];
break;
}
case 'toggle': {
const isOn = params.value as boolean;
break;
}
}
}
コールバックが実行されることを確認するには、自分のアプリのテストビルドで入力を操作してください。コールバックハンドラーがイベントを受信しない場合は、前提条件を確認してください。この機能が利用可能になった後にフローが公開されていることを確認してください。
アプリがインプットを受け取るタイミング
デフォルトの入力値や選択値は、このコールバックを通じてアプリに届くことはありません。ユーザーが Set as default とマークされたオプションをそのままにして次に進んだ場合、イベントは発火しません。イベントがないことを「回答なし」と解釈しないでください — ユーザーはデフォルト値をそのままにしただけです。
以下の要素がこのイベントをトリガーします:
- テキスト、メール、数値、電話フィールド
- 日付、時刻、日時ピッカー
- 単一選択・複数選択のセレクタブルグループ、トグル
以下の要素はトリガーしません:
- パスワードフィールド、プロダクト選択、タブ切り替え
- 複数画面で共有される Header 要素内のインプット
- 重複または欠落したオプションの Element ID を持つセレクタブルグループ、あるいは別の画面で Group ID が再利用されているグループ。このようなグループは、部分的な回答ではなく、何も送信しません。
イベントがトリガーされるタイミング:
- フィールドがフォーカスを失ったとき。クリアされたフィールドは空文字列を報告し、ユーザーが一度も編集しなかったフィールドは何も報告しません。プレースホルダーは値ではありません。ユーザーがフィールドに戻って編集し、再びフォーカスを外した場合、2回目のイベントが発生します。
- ユーザーが新しい値を選択した後にピッカーを閉じたとき。値を変えずに閉じた場合は何も報告されません。
- ユーザーがオプションまたはトグルをタップしたとき。複数選択イベントはすべての選択済みオプションを列挙するため、最後の1つを選択解除すると2つの空の配列が送信されます。
イベントがトリガーされないタイミング:
- ユーザーが入力中のとき。キーストリームは存在せず、フォーカスが外れた時点でフィールドが保持している値のみが送信されます。
- ユーザーがフローを送信または閉じたとき。その時点で編集中の値は失われる可能性があります。配信の制限事項 セクションでは、最後の画面をこれに合わせて設計する方法を説明しています。
- ユーザーの操作なしに値が設定されたとき。Set as default とマークされたオプションは画面が開いたときに事前選択されており、Set Variable アクションにより別の操作からオプションを選択したり入力フィールドを埋めたりできます。どちらもイベントを送信しません。事前入力済みの入力は、ユーザーが編集した時点で初めて報告されます。
受け取る内容
コールバックは2つのイベントを配信します。name でフィルタリングして flow_user_input イベントのみを表示してください。レスポンスのJSONペイロードは次のようになります。
{
"name": "flow_user_input",
"instanceId": "scr_registration",
"isBackendEvent": false,
"isCustomerEvent": true,
"element_id": "email",
"element_type": "email_input",
"value": "jane@example.com"
}
| パラメーター | 説明 |
|---|---|
name | 入力イベントの場合は flow_user_input、画面表示の場合は flow_screen_showed。 |
instanceId | 入力要素が属する画面のID。要素IDはフロー全体ではなく、画面内で一意です。フロー内の複数の画面に入力がある場合は、イベントのフィルタリングに instanceId と element_id を組み合わせて使用してください。 |
element_id | 入力の Element ID、または選択可能なグループの Group ID。 |
element_type | イベントを送信した要素の種類。以下のパラメーターのうちどれが入力値を保持するかを決定します。 |
value | テキストフィールド、ピッカー、トグルのみ。 入力値:テキストフィールドの場合は文字列、ピッカーの場合は整数、トグルの場合はブール値。 |
item_ids | 単一選択・複数選択の選択可能グループのみ。 選択されたオプションの Element ID(ビルダーでの表示順)。単一選択グループでは1件、複数選択グループでは任意の件数。 |
item_titles | 単一選択・複数選択の選択可能グループのみ。 item_ids に記載されたオプションのタイトル(同じ順序)。空になることはありません。タイトルのないオプションはIDが代わりに報告されます。 |
isCustomerEvent | ユーティリティフラグ。このイベントでは常に true。SDKがコールバックに配信するイベントを示します。1つのハンドラーがすべてのフローイベントをアナリティクスに転送し、name ではなくこのフラグで分岐する場合に便利です。 |
isBackendEvent | ユーティリティフラグ。このイベントでは常に false。AdaptyがAdapty自身のアナリティクス用に記録するイベントを示します。false は、ユーザーが入力した内容がアプリにのみ届き、他には渡らないことを確認します。Adaptyはその内容を受信・保存しません。 |
各要素が報告する内容:
| ビルダー上の要素 | element_type | 値を格納するパラメーター | 保持する内容 |
|---|---|---|---|
| Text、Number、Phone number 入力 | text_input、number_input、phone_input | value | ユーザーが入力した生の文字列。数値も文字列として届きます(数値型ではありません)。 |
| E-mail 入力 | email_input | value | ユーザーが入力した生の文字列。ビルダーの書式バリデーションに失敗した場合も含みます。使用前にアプリ側でバリデーションしてください。 |
| Password 入力 | なし | なし | イベントを送信しません。 |
| Date 入力 | date_picker | value | 選択された日付のローカル時刻の深夜0時をUnix時間(ミリ秒、整数)で表した値。 |
| Time 入力 | time_picker | value | Unix時間(ミリ秒、整数)で、分未満を切り捨てた値。 |
| Date & Time 入力 | date_picker と time_picker | value | 日付ピッカーと時刻ピッカーの2要素。それぞれが個別のイベントを送信します。 |
| Type ドロップダウンで Date & Time に切り替えた入力 | date_time_picker | value | Unix時間(ミリ秒、整数)で、分未満を切り捨てた値。 |
| Single choice グループ | single_choice | item_ids、item_titles | 2つの配列。item_ids:選択されたオプションのElement IDを含む配列。item_titles:そのオプションのタイトルを含む配列。 |
| Multi-choice グループ | multi_choice | item_ids、item_titles | 2つの配列。item_ids:選択されたすべてのオプションのElement ID(ビルダーでの表示順)。item_titles:同じ順序でのタイトル。何も選択されていない場合、両方の配列は空になります。 |
| Toggle グループ | toggle | value | ブール値。 |
回答で分岐する場合は、item_titles ではなく item_ids で比較してください。タイトルは派生値です。設定されていればオプションの Element Title、なければデフォルトロケールのテキスト、それもなければElement IDが使用されます。別の言語でフローを閲覧したユーザーには異なるテキストが表示されます。
イベントの例
これらの例は、各イベントで利用可能なプロパティを、コメント内の説明用の値とともに示しています。
テキスト、メール、数値、電話番号の入力(クリックして展開)
onAnalytics(name, params) {
name; // 'flow_user_input'
params.name; // 'flow_user_input'
params.instanceId; // 'scr_J260KU5q'
params.isCustomerEvent; // true
params.isBackendEvent; // false
params.element_id; // 'email'
params.element_type; // 'email_input'
params.value; // 'jane@example.com' (string)
} 日付・時刻・日時ピッカー(クリックして展開)
onAnalytics(name, params) {
params.element_id; // 'birthday'
params.element_type; // 'date_picker'
params.value; // 645408000000 (Unix milliseconds — 1990-06-15, local midnight)
} 単一選択(クリックして展開)
onAnalytics(name, params) {
params.element_id; // 'experience'
params.element_type; // 'single_choice'
params.item_ids; // ['pro']
params.item_titles; // ['I train professionally']
} 複数選択(クリックして展開)
onAnalytics(name, params) {
params.element_id; // 'interests'
params.element_type; // 'multi_choice'
params.item_ids; // ['sports', 'music']
params.item_titles; // ['Sports', 'Music']
} トグル(クリックして展開)
onAnalytics(name, params) {
params.element_id; // 'reminders'
params.element_type; // 'toggle'
params.value; // true (boolean)
} 配信と制限事項
フローは生の値(メールアドレス、電話番号、ユーザーが入力したその他の情報)を送信します。アナリティクスコールバックが届けるものはすべて個人データとして扱い、メールアドレスを書き残さないような場所には保存しないでください。
- 最後の値が優先されます: フィールドごとに1つのイベントが届き、キーストロークのストリームではなくユーザーが最終的に入力した値が含まれます。フィールドを編集した場合、最後のバージョンのみが届きます。
- 送信の保証はありません: ユーザーがフローを進むにつれて値が届きますが、ユーザーはどの時点でも離脱できます。一連の回答が完成したと判断する前に、フローが閉じるのを待ってください。
- ベストエフォート方式での配信: フィールドがフォーカスされているときやピッカーが開いているときにユーザーがフローを閉じたりアプリをバックグラウンドに移動したりすると、その値が失われる場合があります。
最後のフィールドの値を確実に受け取るには、入力フィールドもピッカーもない画面でフローを終了し、その画面が表示されたときに自動的に閉じるのではなく、明示的なユーザー操作によってフローを閉じてください。最後の画面に移動すると前のフィールドからフォーカスが外れ、それが値の送信をトリガーします。
ハンドラーが受け取った入力値はそれぞれ保存しておき、フローが閉じたタイミングでまとめて送信してください。そのタイミングを捉えるには、onAnalytics と一緒に onDisappeared ハンドラーを登録します。ユーザーがフローを最後まで完了した場合も、途中で閉じた場合も、フロービューが閉じられた際に実行されます。
ユースケース
バックエンドへのユーザー登録
フローが閉じた時点で一度のリクエストに完全な回答セットを含められるよう、値が届いたタイミングで収集し、フローが閉じた後にまとめて送信してください。
フローは、ユーザーが完了した場合でも途中で離脱した場合でも表示が消えます。バックエンドを呼び出す前に、必要なフィールドが揃っているか確認してください。
フローはバックエンドのエラーを表示できません。ハンドラーの戻り値はフロービューを閉じるだけであり、SDKには実行中のフローにデータを送り込むメソッドがありません。たとえばメールアドレスがすでに使用されているなどの理由で登録に失敗した場合は、フローが閉じた後に独自のUIでエラーを表示してください。
const flowAnswers: Record<string, string> = {};
view.setEventHandlers({
onAnalytics(name, params) {
if (name === 'flow_user_input' && typeof params.value === 'string') {
flowAnswers[params.element_id as string] = params.value;
}
return false;
},
onDisappeared() {
if (flowAnswers.email) {
// Send flowAnswers to your backend here to create the account.
}
return false;
},
});
ユーザープロファイルにデータを反映する
ユーザーが入力した内容をプロファイルと紐付け、同じ情報を二度聞かないようにするには、値が入力されるたびにユーザープロファイルを更新してください。
たとえば、フローに Element ID が name のテキスト入力フィールドと、Element ID が email のメール入力フィールドがある場合:
function handleFlowInput(name: string, params: Record<string, unknown>) {
if (name !== 'flow_user_input') return;
if (typeof params.value !== 'string') return;
const profileParams: Partial<AdaptyProfileParameters> = {};
switch (params.element_id) {
case 'name':
profileParams.firstName = params.value;
break;
case 'email':
profileParams.email = params.value;
break;
default:
return;
}
adapty.updateProfile(profileParams).catch((error) => {
// handle the error
});
}
後から表示されるフローのカスタマイズ
クイズの回答によって、ユーザーがその後のプレースメントで見るもの(別のフロー、またはその中の別のペイウォール)を決めることもできます。
たとえば、オンボーディングフローでユーザーにスポーツの経験について質問し、グループごとに異なるプロダクトとコピーを持つ独自のフローを表示することができます。
function handleFlowInput(name: string, params: Record<string, unknown>) {
if (name !== 'flow_user_input') return;
if (params.element_id !== 'experience') return;
const optionId = (params.item_ids as string[])[0];
adapty
.updateProfile({
// Set the custom attribute 'experience' to the option the user selected
// (beginner, amateur, or pro).
codableCustomAttributes: { experience: optionId },
})
.catch((error) => {
// handle the error
});
}