Procesar datos de flows en React Native SDK
Cuando un usuario escribe en un campo de texto, responde un cuestionario o activa un interruptor en un flow, el SDK pasa el valor a tu app a través de su callback de análisis.
Las apps suelen usar esos datos para:
- Registrar usuarios en tu propio backend: Toma el correo electrónico y el nombre que el usuario introdujo en tu onboarding, y crea su cuenta cuando el flow se cierre.
- Guardar respuestas y preferencias: Registra lo que eligió el usuario para que tu app pueda usarlo más adelante — por ejemplo, escríbelo en su perfil de Adapty como atributos personalizados.
- Personalizar flows futuros: Guarda las respuestas del cuestionario como atributos personalizados y luego apunta a un placement posterior para que cada segmento vea un flow distinto, o un paywall diferente dentro de él.
- Enviar datos a plataformas de analítica de terceros: Reenvía las respuestas a Amplitude, Mixpanel o cualquier plataforma de analítica de producto que utilices.
Las entradas y los grupos seleccionables reportan sus valores automáticamente. Para distinguirlos en tu código, asigna a cada entrada un Element ID significativo y a cada grupo seleccionable un Group ID en el builder.
Antes de empezar
Necesitas:
- Adapty SDK v4 o posterior: Los callbacks de flow no existen en versiones anteriores.
- Un flow creado en el Flow & Paywall Builder: Solo los flows reportan valores de entrada a través de este callback.
- Una versión de flow publicada recientemente: Un flow solo reporta valores de entrada si lo publicaste después de que esta función estuviera disponible. Si no llega nada a tu app, publica una nueva versión del flow e inténtalo de nuevo.
Recibir valores de entrada
Los valores de entrada llegan al mismo handler que cualquier otro evento de analítica de un flow, bajo el nombre de evento flow_user_input. Registra onAnalytics junto con el resto de handlers de eventos del flow:
const unsubscribe = view.setEventHandlers({
onAnalytics(name, params) {
handleFlowInput(name, params);
return false; // keep the flow open
},
});
El callback onAnalytics entrega todos los eventos de analítica de un flow, incluidas las vistas de pantalla.
- El parámetro
namecontiene el nombre del evento. Para filtrar los eventos de entrada del usuario, comparanameconflow_user_input. - El parámetro
element_typeindica la categoría del elemento. - El valor de la entrada se almacena en distintos parámetros según el tipo de elemento:
- Los campos de texto, selectores y toggles guardan la entrada del usuario en
value - Los grupos seleccionables reportan las opciones activas en
item_idseitem_titles
- Los campos de texto, selectores y toggles guardan la entrada del usuario en
function handleFlowInput(name, params) {
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;
switch (params.element_type) {
case 'text_input':
case 'email_input':
case 'number_input':
case 'phone_input': {
const text = params.value;
break;
}
case 'date_picker':
case 'time_picker':
case 'date_time_picker': {
// Unix time in milliseconds.
const date = new Date(params.value);
break;
}
case 'single_choice': {
const optionId = params.item_ids[0];
break;
}
case 'multi_choice': {
const optionIds = params.item_ids;
break;
}
case 'toggle': {
const isOn = params.value;
break;
}
}
}
Para confirmar que el callback se ejecuta, interactúa con el input en una versión de prueba de tu propia app. Si tu callback handler no recibe ningún evento, revisa los prerequisitos. Asegúrate de que el flow fue publicado después de que esta función estuviera disponible.
Cuando tu app recibe el input
El valor predeterminado de entrada o selección nunca llega a tu aplicación a través de este callback. Si un usuario acepta la opción marcada como Set as default y continúa, no se dispara ningún evento. No interpretes la ausencia del evento como “sin respuesta”: el usuario simplemente dejó el valor predeterminado tal como estaba.
Los siguientes elementos disparan este evento:
- Campos de texto, email, número y teléfono
- Selectores de fecha, hora y fecha-hora
- Grupos seleccionables de opción única y múltiple, y toggles
Los siguientes no lo hacen:
- Campos de contraseña, selecciones de productos y cambios de pestaña
- Inputs dentro de un elemento Header, que se comparte entre pantallas
- Grupos seleccionables con IDs de opción duplicados o faltantes, o con un ID de grupo reutilizado en otra pantalla. Ese tipo de grupo no envía nada en absoluto, en lugar de enviar parte de la respuesta.
El evento se dispara cuando:
- Un campo pierde el foco. Un campo vaciado reporta una cadena vacía; un campo que el usuario nunca editó no reporta nada. Un marcador de posición no es un valor. Si el usuario vuelve al campo, lo edita y lo abandona de nuevo, se genera un segundo evento.
- El usuario cierra un selector tras elegir un nuevo valor. Cerrarlo sin cambios no reporta nada.
- El usuario pulsa una opción o un toggle. Un evento de opción múltiple lista todas las opciones seleccionadas, por lo que deseleccionar la última envía dos arrays vacíos.
El evento no se dispara cuando:
- El usuario escribe. No hay flujo de pulsaciones de teclas, solo el valor que tiene el campo cuando pierde el foco.
- El usuario envía o cierra el flow. Un valor que aún se está editando en ese momento puede perderse; la sección de limitaciones de entrega explica cómo diseñar la última pantalla teniendo esto en cuenta.
- Se establece un valor sin interacción del usuario. Una opción marcada como Set as default se preselecciona al abrirse la pantalla, y una acción Set Variable puede seleccionar una opción o rellenar un input a partir de otra interacción. Ninguna de las dos envía un evento; un input prerrellenado solo se reporta una vez que el usuario lo edita.
Qué recibes
El callback entrega dos eventos. Filtra por name para mostrar únicamente los eventos flow_user_input. El payload JSON de respuesta tiene este aspecto:
{
"name": "flow_user_input",
"instanceId": "scr_registration",
"isBackendEvent": false,
"isCustomerEvent": true,
"element_id": "email",
"element_type": "email_input",
"value": "jane@example.com"
}
| Parámetro | Descripción |
|---|---|
name | flow_user_input para eventos de entrada, flow_screen_showed para vistas de pantalla. |
instanceId | El ID de la pantalla del input. Los IDs de elemento son únicos dentro de una pantalla, no en todo el flow. Si tu flow tiene inputs en más de una pantalla, combina instanceId con element_id al filtrar eventos. |
element_id | El Element ID del input, o el Group ID del grupo seleccionable. |
element_type | El tipo de elemento que envió el evento. Determina cuál de los parámetros siguientes contiene el valor del input. |
value | Solo campos de texto, selectores y toggles. El valor del input: una cadena para campos de texto, un entero para selectores, un booleano para toggles. |
item_ids | Solo grupos seleccionables de elección única y múltiple. Los Element IDs de las opciones seleccionadas, en el orden en que aparecen en el builder. Una entrada para un grupo de elección única; cualquier número para un grupo de elección múltiple. |
item_titles | Solo grupos seleccionables de elección única y múltiple. Los títulos de las opciones listadas en item_ids, en el mismo orden. Nunca está vacío: una opción sin título informa su ID en su lugar. |
isCustomerEvent | Indicador de utilidad, siempre true para este evento. Marca los eventos que el SDK entrega a tu callback. Resulta útil si un mismo handler reenvía todos los eventos del flow a tu sistema de análisis y filtras por este indicador en lugar de por name. |
isBackendEvent | Indicador de utilidad, siempre false para este evento. Marca los eventos que Adapty también registra para su propio análisis. false confirma que lo que los usuarios introducen llega a tu app y solo a ella — Adapty no lo recibe ni lo almacena. |
Lo que reporta cada elemento:
| En el builder | element_type | Parámetro que almacena el valor | Qué contiene |
|---|---|---|---|
| Input de Texto, Número, Número de teléfono | text_input, number_input, phone_input | value | La cadena literal que escribió el usuario. Los números llegan como cadenas, no como tipos numéricos. |
| Input de E-mail | email_input | value | La cadena literal que escribió el usuario, aunque no haya superado la validación de formato del builder. Valídala en tu lado antes de usarla. |
| Input de Contraseña | ninguno | ninguno | No envía ningún evento. |
| Input de Fecha | date_picker | value | Tiempo Unix en milisegundos, como entero, a medianoche local de la fecha seleccionada. |
| Input de Hora | time_picker | value | Tiempo Unix en milisegundos, como entero, redondeado hacia abajo al minuto. |
| Input de Fecha y hora | date_picker y time_picker | value | Dos elementos, un selector de fecha y un selector de hora. Cada uno envía su propio evento. |
| Input cambiado a Fecha y hora en el desplegable Type | date_time_picker | value | Tiempo Unix en milisegundos, como entero, redondeado hacia abajo al minuto. |
| Grupo de elección única | single_choice | item_ids, item_titles | Dos arrays. item_ids: un array con el Element ID de la opción seleccionada. item_titles: un array con el título de esa opción. |
| Grupo de elección múltiple | multi_choice | item_ids, item_titles | Dos arrays. item_ids: los Element IDs de todas las opciones seleccionadas, en el orden en que aparecen en el builder. item_titles: sus títulos, en el mismo orden. Ambos arrays están vacíos cuando no hay nada seleccionado. |
| Grupo de Toggle | toggle | value | Un booleano. |
Para bifurcar según una respuesta, compara item_ids, no item_titles. El título es derivado: el Element Title de la opción si lo definiste, si no su texto en tu idioma predeterminado, y si no su Element ID. Un usuario que vio el flow en otro idioma vio un texto diferente.
Ejemplos de eventos
Estos ejemplos muestran las propiedades disponibles en cada evento, con valores ilustrativos en los comentarios.
Entrada de texto, correo electrónico, número y teléfono (Haz clic para expandir)
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)
} Selectores de fecha, hora y fecha-hora (Click to expand)
onAnalytics(name, params) {
params.element_id; // 'birthday'
params.element_type; // 'date_picker'
params.value; // 645408000000 (Unix milliseconds — 1990-06-15, local midnight)
} Single choice (Click to expand)
onAnalytics(name, params) {
params.element_id; // 'experience'
params.element_type; // 'single_choice'
params.item_ids; // ['pro']
params.item_titles; // ['I train professionally']
} Multi choice (Haz clic para expandir)
onAnalytics(name, params) {
params.element_id; // 'interests'
params.element_type; // 'multi_choice'
params.item_ids; // ['sports', 'music']
params.item_titles; // ['Sports', 'Music']
} Toggle (Haz clic para expandir)
onAnalytics(name, params) {
params.element_id; // 'reminders'
params.element_type; // 'toggle'
params.value; // true (boolean)
} Entrega y limitaciones
Los flows envían valores sin procesar: direcciones de correo electrónico, números de teléfono y cualquier otra cosa que el usuario escriba. Trata todo lo que entregue el callback de analíticas como datos personales y no los almacenes en ningún lugar donde no guardarías el correo electrónico de un usuario.
- El último valor prevalece: recibes un evento por campo con el valor con el que el usuario se quedó, no una secuencia tecla a tecla. Si edita un campo, solo llega la última versión.
- Sin garantía de envío: los valores te llegan a medida que el usuario avanza por el flow, y puede salir en cualquier momento. Espera a que el flow se cierre antes de considerar un conjunto de respuestas como completo.
- Entrega de mejor esfuerzo: si un usuario cierra el flow o minimiza la app mientras un campo tiene el foco o un selector está abierto, ese valor puede perderse.
Para que el valor del último campo sea fiable, termina el flow con una pantalla que no tenga entradas ni selectores, y cierra el flow mediante una acción explícita del usuario en lugar de hacerlo automáticamente al aparecer esa pantalla. Pasar a la pantalla final quita el foco del campo anterior, que es lo que envía su valor.
Guarda cada valor de entrada tal como lo recibe tu handler y envía el conjunto completo cuando el flow se cierre. Para detectar ese momento, registra un handler onDisappeared junto a onAnalytics. Se ejecuta cuando la vista del flow se descarta, tanto si el usuario completó el flow como si lo cerró a mitad.
Casos de uso
Registrar usuarios en tu backend
Recopila los valores según van llegando y envíalos cuando el flow se cierre, para que una sola solicitud contenga el conjunto completo de respuestas.
El flow desaparece tanto si el usuario lo completó como si lo abandonó a mitad. Comprueba que tienes los campos necesarios antes de llamar a tu backend.
El flow no puede mostrar errores de tu backend. El valor de retorno del handler solo cierra la vista del flow, y el SDK no tiene ningún método que envíe datos a un flow en ejecución. Si el registro falla, por ejemplo porque el email ya está en uso, muestra el error en tu propia UI después de que el flow se cierre.
const flowAnswers = {};
const unsubscribe = view.setEventHandlers({
onAnalytics(name, params) {
if (name === 'flow_user_input' && typeof params.value === 'string') {
flowAnswers[params.element_id] = params.value;
}
return false;
},
onDisappeared() {
if (flowAnswers.email) {
// Send flowAnswers to your backend here to create the account.
}
return false;
},
});
Enriquece los perfiles de usuario con datos
Para vincular lo que un usuario ha introducido a su perfil y evitar pedirle los mismos datos dos veces, actualiza el perfil de usuario a medida que lleguen los valores.
Por ejemplo, si tu flow tiene un campo de texto con el ID de elemento name y un campo de email con el ID de elemento email:
function handleFlowInput(name, params) {
if (name !== 'flow_user_input') return;
if (typeof params.value !== 'string') return;
const profileParams = {};
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
});
}
Personalizar flows que aparecen más adelante
Las respuestas del cuestionario también pueden decidir qué ve un usuario en un placement posterior — un flow diferente, o un paywall distinto dentro de él.
Por ejemplo, pregunta a los usuarios sobre su experiencia con el deporte en tu flow de onboarding y luego muestra a cada grupo su propio flow con diferentes productos y textos.
- Añade un cuestionario a tu flow. Dale al grupo seleccionable el ID de grupo
experience, y a cada opción un ID de elemento significativo. - Gestiona las respuestas y establece atributos personalizados para el usuario.
function handleFlowInput(name, params) {
if (name !== 'flow_user_input') return;
if (params.element_id !== 'experience') return;
adapty
.updateProfile({
// Set the custom attribute 'experience' to the option the user selected
// (beginner, amateur, or pro).
codableCustomAttributes: { experience: params.item_ids[0] },
})
.catch(error => {
// handle the error
});
}
- Crea un segmento para cada valor de atributo personalizado.
- Crea un placement y añade una audiencia para cada segmento.
- Muestra el flow de ese placement en tu app.