Traiter les données des flows dans le SDK Android
Lorsqu’un utilisateur saisit du texte dans un champ, répond à un quiz ou active un bouton dans un flow, le SDK transmet la valeur à votre application via son callback d’analytique.
Les applications utilisent généralement ces données pour :
- Inscrire les utilisateurs sur votre propre backend : Récupérez l’adresse e-mail et le nom saisis dans votre onboarding, puis créez leur compte à la fermeture du flow.
- Enregistrer les réponses et préférences : Suivez les choix de l’utilisateur pour que votre app puisse les exploiter ensuite — par exemple, écrivez-les dans son profil Adapty en tant qu’attributs personnalisés.
- Personnaliser les flows futurs : Enregistrez les réponses au quiz comme attributs personnalisés, puis ciblez un placement ultérieur pour que chaque segment voie un flow différent, ou un paywall différent à l’intérieur.
- Alimenter des plateformes d’analyse tierces : Transmettez les réponses à Amplitude, Mixpanel ou tout autre outil d’analyse produit que vous utilisez.
Les inputs et les groupes de sélection rapportent automatiquement leurs valeurs. Pour les distinguer dans votre code, attribuez un Element ID à chaque input et un Group ID à chaque groupe de sélection dans le builder.
Avant de commencer
Vous avez besoin de :
- Adapty SDK v4 ou supérieur : Les callbacks de flow n’existent pas dans les versions antérieures.
- Un flow créé dans le Flow & Paywall Builder : Seuls les flows transmettent les valeurs d’entrée via ce callback.
- Une version de flow publiée récemment : Un flow ne transmet les valeurs d’entrée que si vous l’avez publié après que cette fonctionnalité soit devenue disponible. Si rien ne parvient à votre application, publiez une nouvelle version du flow et réessayez.
Recevoir les valeurs saisies
Les valeurs saisies parviennent au même callback que tous les autres événements analytiques d’un flow, sous le nom d’événement flow_user_input. Surchargez onAnalyticEvent sur votre écouteur d’événements de flow :
class MyFlowEventListener : AdaptyFlowDefaultEventListener() {
override fun onAnalyticEvent(
name: String,
params: Map<String, Any?>,
context: Context,
) {
handleFlowInput(name, params)
}
}
Le callback onAnalyticEvent transmet tous les événements analytiques d’un flow, y compris les vues d’écran.
- Le paramètre
namecontient le nom de l’événement. Pour filtrer les événements de saisie utilisateur, compareznameàflow_user_input. - Le paramètre
element_typeindique la catégorie de l’élément. - La valeur de la saisie est stockée dans différents paramètres selon le type d’élément :
- Les champs texte, les sélecteurs et les bascules stockent la saisie de l’utilisateur dans
value - Les groupes sélectionnables indiquent les options actives dans
item_idsetitem_titles
- Les champs texte, les sélecteurs et les bascules stockent la saisie de l’utilisateur dans
private fun handleFlowInput(name: String, params: Map<String, Any?>) {
if (name != "flow_user_input") return
val elementId = params["element_id"] as? String ?: return
// The screen the input sits on. Pair it with elementId to tell apart
// two fields that share an Element ID on different screens.
val screenId = params["instanceId"] as? String
when (params["element_type"]) {
"text_input", "email_input", "number_input", "phone_input" -> {
val text = params["value"] as? String
}
"date_picker", "time_picker", "date_time_picker" -> {
// Unix time in milliseconds. Numbers arrive as Double — read them through Number.
val millis = (params["value"] as? Number)?.toLong()
}
"single_choice" -> {
val optionId = (params["item_ids"] as? List<*>)?.firstOrNull() as? String
}
"multi_choice" -> {
val optionIds = (params["item_ids"] as? List<*>)?.filterIsInstance<String>()
}
"toggle" -> {
val isOn = params["value"] as? Boolean
}
}
}
Pour confirmer que le callback se déclenche, interagissez avec le champ de saisie dans une version de test de votre application. Si votre gestionnaire de callback ne reçoit pas d’événement, vérifiez les prérequis. Assurez-vous que le flow a bien été publié après que cette fonctionnalité est devenue disponible.
Quand votre application reçoit les données d’entrée
La valeur saisie ou sélectionnée par défaut n’est jamais transmise à votre application via ce callback. Si un utilisateur accepte l’option marquée Set as default et continue, aucun événement ne se déclenche. Ne considérez pas l’absence d’événement comme « aucune réponse » — l’utilisateur a simplement conservé la valeur par défaut.
Les éléments suivants déclenchent cet événement :
- Champs texte, e-mail, numérique et téléphone
- Sélecteurs de date, d’heure et de date-heure
- Groupes sélectionnables à choix unique et à choix multiple, et bascules
Les éléments suivants ne le déclenchent pas :
- Champs de mot de passe, sélections de produits et changements d’onglet
- Les saisies à l’intérieur d’un élément Header, partagé entre les écrans
- Les groupes sélectionnables avec des identifiants d’élément dupliqués ou manquants, ou dont l’identifiant de groupe est réutilisé sur un autre écran. Un tel groupe n’envoie rien du tout, plutôt qu’une réponse partielle.
L’événement se déclenche lorsque :
- Un champ perd le focus. Un champ vidé signale une chaîne vide ; un champ que l’utilisateur n’a jamais modifié ne signale rien. Un espace réservé n’est pas une valeur. Si l’utilisateur revient sur le champ, le modifie et le quitte à nouveau, un second événement est émis.
- L’utilisateur ferme un sélecteur après avoir choisi une nouvelle valeur. Le fermer sans modification ne signale rien.
- L’utilisateur appuie sur une option ou une bascule. Un événement à choix multiple liste toutes les options sélectionnées ; désélectionner la dernière envoie donc deux tableaux vides.
L’événement ne se déclenche pas lorsque :
- L’utilisateur saisit du texte. Il n’y a pas de flux de frappes clavier, seulement la valeur que contient le champ au moment où il perd le focus.
- L’utilisateur soumet ou ferme le flow. Une valeur encore en cours de saisie à cet instant peut être perdue ; la section limites de livraison explique comment concevoir le dernier écran en tenant compte de cela.
- Une valeur est définie sans interaction de l’utilisateur. Une option marquée Set as default est présélectionnée à l’ouverture de l’écran, et une action Set Variable peut sélectionner une option ou remplir un champ depuis une autre interaction. Aucune des deux n’envoie d’événement ; une saisie préremplie n’est signalée que lorsque l’utilisateur la modifie.
Ce que vous recevez
Le callback transmet deux événements. Filtrez par name pour n’afficher que les événements flow_user_input. La charge utile JSON de la réponse ressemble à ceci :
{
"name": "flow_user_input",
"instanceId": "scr_registration",
"isBackendEvent": false,
"isCustomerEvent": true,
"element_id": "email",
"element_type": "email_input",
"value": "jane@example.com"
}
| Paramètre | Description |
|---|---|
name | flow_user_input pour les événements de saisie, flow_screen_showed pour les affichages d’écran. |
instanceId | L’ID de l’écran contenant le champ de saisie. Les IDs d’éléments sont uniques au sein d’un écran, pas dans l’ensemble du flow. Si votre flow comporte des champs de saisie sur plusieurs écrans, combinez instanceId avec element_id pour filtrer les événements. |
element_id | L’Element ID du champ de saisie, ou le Group ID du groupe sélectionnable. |
element_type | Le type d’élément qui a envoyé l’événement. Il détermine lequel des paramètres ci-dessous contient la valeur saisie. |
value | Champs texte, sélecteurs et bascules uniquement. La valeur saisie : une chaîne pour les champs texte, un entier pour les sélecteurs, un booléen pour les bascules. |
item_ids | Groupes sélectionnables à choix unique et à choix multiple uniquement. Les Element IDs des options sélectionnées, dans l’ordre d’apparition des options dans le builder. Une entrée pour un groupe à choix unique ; un nombre quelconque pour un groupe à choix multiple. |
item_titles | Groupes sélectionnables à choix unique et à choix multiple uniquement. Les titres des options listées dans item_ids, dans le même ordre. Jamais vide : une option sans titre renvoie son ID à la place. |
isCustomerEvent | Indicateur utilitaire, toujours true pour cet événement. Il identifie les événements que le SDK transmet à votre callback. Utile si un seul handler transfère tous les événements du flow vers vos analytics et que vous filtrez sur cet indicateur plutôt que sur name. |
isBackendEvent | Indicateur utilitaire, toujours false pour cet événement. Il identifie les événements qu’Adapty enregistre également pour ses propres analytics. false confirme que ce que les utilisateurs saisissent ne parvient qu’à votre application — Adapty ne le reçoit pas et ne le stocke pas. |
Ce que chaque élément remonte :
| Dans le builder | element_type | Paramètre contenant la valeur | Ce qu’il contient |
|---|---|---|---|
| Champ Texte, Nombre, Numéro de téléphone | text_input, number_input, phone_input | value | La chaîne brute saisie par l’utilisateur. Les nombres arrivent sous forme de chaînes, et non de types numériques. |
| Champ E-mail | email_input | value | La chaîne brute saisie par l’utilisateur, même si elle n’a pas passé la validation de format du builder. Validez-la de votre côté avant de l’utiliser. |
| Champ Mot de passe | aucun | aucun | N’envoie aucun événement. |
| Champ Date | date_picker | value | Horodatage Unix en millisecondes, sous forme d’entier, à minuit heure locale de la date sélectionnée. |
| Champ Heure | time_picker | value | Horodatage Unix en millisecondes, sous forme d’entier, arrondi à la minute inférieure. |
| Champ Date et heure | date_picker et time_picker | value | Deux éléments : un sélecteur de date et un sélecteur d’heure. Chacun envoie son propre événement. |
| Champ passé en mode Date et heure dans le menu déroulant Type | date_time_picker | value | Horodatage Unix en millisecondes, sous forme d’entier, arrondi à la minute inférieure. |
| Groupe à choix unique | single_choice | item_ids, item_titles | Deux tableaux. item_ids : un tableau contenant l’Element ID de l’option sélectionnée. item_titles : un tableau contenant le titre de cette option. |
| Groupe à choix multiple | multi_choice | item_ids, item_titles | Deux tableaux. item_ids : les Element IDs de toutes les options sélectionnées, dans l’ordre d’apparition dans le builder. item_titles : leurs titres, dans le même ordre. Les deux tableaux sont vides si rien n’est sélectionné. |
| Groupe Bascule | toggle | value | Un booléen. |
Pour brancher votre logique selon une réponse, comparez item_ids, pas item_titles. Un titre est dérivé : l’Element Title de l’option si vous en avez défini un, sinon son texte dans votre langue par défaut, sinon son Element ID. Un utilisateur ayant consulté le flow dans une autre langue a vu un texte différent.
Exemples d’événements
Ces exemples présentent les propriétés disponibles pour chaque événement, avec des valeurs illustratives en commentaires.
Text, email, number, and phone input (Click to expand)
override fun onAnalyticEvent(name: String, params: Map<String, Any?>, context: Context) {
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)
} Sélecteurs de date, heure et date-heure (Cliquez pour développer)
override fun onAnalyticEvent(name: String, params: Map<String, Any?>, context: Context) {
params["element_id"] // "birthday"
params["element_type"] // "date_picker"
params["value"] // 6.45408E11 (Double — Unix milliseconds, 1990-06-15, local midnight)
} Choix unique (Cliquer pour développer)
override fun onAnalyticEvent(name: String, params: Map<String, Any?>, context: Context) {
params["element_id"] // "experience"
params["element_type"] // "single_choice"
params["item_ids"] // ["pro"] (List<String>)
params["item_titles"] // ["I train professionally"]
} Multi choice (Click to expand)
override fun onAnalyticEvent(name: String, params: Map<String, Any?>, context: Context) {
params["element_id"] // "interests"
params["element_type"] // "multi_choice"
params["item_ids"] // ["sports", "music"] (List<String>)
params["item_titles"] // ["Sports", "Music"]
} Toggle (Click to expand)
override fun onAnalyticEvent(name: String, params: Map<String, Any?>, context: Context) {
params["element_id"] // "reminders"
params["element_type"] // "toggle"
params["value"] // true (Boolean)
} Livraison et limitations
Les flows transmettent les valeurs brutes — adresses e-mail, numéros de téléphone et tout ce qu’un utilisateur saisit. Traitez tout ce que le callback analytics vous fournit comme des données personnelles, et ne les écrivez nulle part où vous n’écririez pas l’adresse e-mail d’un utilisateur.
- La dernière valeur gagne : Vous recevez un événement par champ, portant la valeur sur laquelle l’utilisateur s’est arrêté plutôt qu’un flux touche par touche. S’il modifie un champ, seule la dernière version vous parvient.
- Aucune garantie d’envoi : Les valeurs vous parviennent au fur et à mesure que les utilisateurs avancent dans le flow, et un utilisateur peut partir à tout moment. Attendez que le flow se ferme avant de considérer un ensemble de réponses comme complet.
- Distribution au mieux : Si un utilisateur ferme le flow ou réduit l’application pendant qu’un champ est encore actif ou qu’un sélecteur est encore ouvert, cette valeur peut être perdue.
Pour que la valeur du dernier champ soit fiable, terminez le flow par un écran sans champs de saisie ni sélecteurs, et fermez le flow depuis une action explicite de l’utilisateur plutôt qu’automatiquement à l’apparition de cet écran. Passer à l’écran final retire le focus du champ précédent, ce qui déclenche l’envoi de sa valeur.
Stockez chaque valeur d’entrée au fur et à mesure que votre listener la reçoit, puis envoyez l’ensemble complet lorsque le flow se ferme. Pour intercepter ce moment, surchargez onFlowClosed dans votre AdaptyFlowEventListener. Cette méthode s’exécute lorsque la vue du flow est fermée, que l’utilisateur ait terminé le flow ou l’ait fermé en cours de route.
Cas d’utilisation
Enregistrer les utilisateurs sur votre backend
Collectez les valeurs au fur et à mesure qu’elles arrivent et envoyez-les en une seule fois à la fermeture du flow, afin qu’une seule requête contienne l’ensemble complet des réponses.
Le flow se ferme que l’utilisateur l’ait terminé ou abandonné en cours de route. Vérifiez que les champs dont vous avez besoin sont bien renseignés avant d’appeler votre backend.
Le flow ne peut pas afficher les erreurs provenant de votre backend. Le callback n’a pas de valeur de retour, et le SDK ne dispose d’aucune méthode permettant d’envoyer des données dans un flow en cours d’exécution. Si l’inscription échoue, par exemple parce que l’adresse e-mail est déjà utilisée, affichez l’erreur dans votre propre interface utilisateur après la fermeture du flow.
class MyFlowEventListener : AdaptyFlowDefaultEventListener() {
private val flowAnswers = mutableMapOf<String, String>()
override fun onAnalyticEvent(
name: String,
params: Map<String, Any?>,
context: Context,
) {
if (name != "flow_user_input") return
val elementId = params["element_id"] as? String ?: return
val value = params["value"] as? String ?: return
flowAnswers[elementId] = value
}
override fun onFlowClosed() {
if (!flowAnswers.containsKey("email")) return
// Send flowAnswers to your backend here to create the account.
flowAnswers.clear()
}
}
Enrichir les profils utilisateurs avec des données
Pour associer les informations saisies par un utilisateur à son profil et éviter de lui poser deux fois les mêmes questions, mettez à jour le profil utilisateur au fur et à mesure que les valeurs arrivent.
Par exemple, si votre flow comporte un champ texte avec l’ID d’élément name et un champ email avec l’ID d’élément email :
private fun handleFlowInput(name: String, params: Map<String, Any?>) {
if (name != "flow_user_input") return
val elementId = params["element_id"] as? String ?: return
val value = params["value"] as? String ?: return
val builder = AdaptyProfileParameters.Builder()
when (elementId) {
"name" -> builder.withFirstName(value)
"email" -> builder.withEmail(value)
else -> return
}
Adapty.updateProfile(builder.build()) { error ->
if (error != null) {
// handle the error
}
}
}
Personnaliser les flows affichés ultérieurement
Les réponses au quiz peuvent aussi déterminer ce qu’un utilisateur voit à un placement ultérieur — un flow différent, ou un paywall différent à l’intérieur de celui-ci.
Par exemple, interrogez les utilisateurs sur leur pratique sportive dans votre flow d’onboarding, puis montrez à chaque groupe son propre flow avec des produits et des textes différents.
- Ajoutez un quiz à votre flow. Donnez au groupe sélectionnable l’ID de groupe
experience, et à chaque option un ID d’élément significatif. - Gérez les réponses et définissez des attributs personnalisés pour l’utilisateur.
private fun handleFlowInput(name: String, params: Map<String, Any?>) {
if (name != "flow_user_input") return
if (params["element_id"] != "experience") return
val optionId = (params["item_ids"] as? List<*>)?.firstOrNull() as? String ?: return
val builder = AdaptyProfileParameters.Builder()
// Set the custom attribute 'experience' to the option the user selected
// (beginner, amateur, or pro).
builder.withCustomAttribute("experience", optionId)
Adapty.updateProfile(builder.build()) { error ->
if (error != null) {
// handle the error
}
}
}
- Créez un segment pour chaque valeur d’attribut personnalisé.
- Créez un placement et ajoutez une audience pour chaque segment.
- Affichez le flow correspondant à ce placement dans votre application.