BitelioBitelio
Guides

Campos personalizados

Adjunta tus propios datos a los contactos y ponlos a trabajar en plantillas, filtros de segmento y lógica de flujos de trabajo

Además de sus campos integrados (email, subscribed, createdAt, updatedAt), cada contacto de Bitelio lleva un objeto data de forma libre. Lo que vive ahí depende enteramente de ti: nombres, niveles de plan, fechas de alta, tus propios ID de usuario — cualquier cosa que más adelante quieras tener disponible en plantillas, segmentos o condiciones de flujos de trabajo.

Esta guía recorre el ciclo de vida completo de los campos personalizados: cómo escribirlos, cómo funciona el tipado, dónde puedes usarlos y cómo retirarlos.

Establecer campos personalizados

Puedes escribir campos personalizados cada vez que se crea o actualiza un contacto:

# Vía /v1/track (crea el contacto automáticamente)
curl -X POST https://api.bitelio.com/v1/track \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "email": "ada@example.com",
    "event": "signed_up",
    "data": {
      "firstName": "Ada",
      "plan": "pro",
      "signupDate": "2026-05-06T12:00:00Z",
      "lifetimeValue": 240
    }
  }'

# Vía PATCH /contacts/:id
curl -X PATCH https://api.bitelio.com/contacts/cnt_abc123 \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{ "data": { "plan": "enterprise" } }'

Las actualizaciones a data son fusiones, no reemplazos — solo se tocan las claves presentes en tu payload, y todo lo demás queda como estaba.

Valores especiales

ValorComportamiento
PrimitivoSe guarda. Disponible para plantillas, segmentos, flujos de trabajo.
nullElimina la clave del contacto.
"" (vacío)Se ignora — no sobrescribe los datos existentes.
{ value, persistent: false }Se usa solo para este envío; no se guarda en el contacto. Útil para códigos de un solo uso (restablecimientos de contraseña, enlaces mágicos).

Cambio de agosto de 2026

Un campo no persistente se escribe como { value, persistent: false } y se referencia como {{ campo }}: la envoltura se resuelve por ti. Eso ya era así en todas partes menos en los emails, SMS y webhooks de los flujos de trabajo, donde hasta agosto de 2026 la envoltura llegaba cruda a la plantilla y lo único que se pintaba era {{ campo.value }}.

Los tres se comportan ya como el resto de la plataforma. Si escribiste {{ campo.value }} en la plantilla de un flujo como apaño, cámbialo a {{ campo }}: la forma antigua se pinta vacía y nada te avisa.

Inferencia de tipos

La primera vez que un campo aparece con un valor no nulo en cualquier parte de tu proyecto, Bitelio le asigna un tipo:

Detectado comoEjemplos
Número42, 3.14
Booleanotrue, false
FechaCadenas que coinciden con YYYY-MM-DD o YYYY-MM-DDTHH:MM:SS[.sss]Z
TextoCualquier otra cosa

Ese tipo determina la interfaz del creador de segmentos — los campos de fecha obtienen selectores de fecha, los campos numéricos obtienen entradas numéricas, y así sucesivamente — y una vez establecido se mantiene para el proyecto. Si más adelante envías un tipo distinto para la misma clave, la interfaz sigue respetando la inferencia original, aunque Bitelio seguirá guardando cualquier valor que llegue.

Los operadores sensibles a fechas (within, olderThan) solo se aplican a campos personalizados guardados como cadenas ISO 8601 completas: "2026-05-06T12:00:00Z" califica, "05/06/2026" no.

Claves reservadas

Un puñado de claves pertenecen a Bitelio y se filtran silenciosamente de todo payload data. Enviarlas no las guarda ni genera un error:

id, bitelio_id, bitelio_email, email, unsubscribeUrl, subscribeUrl, manageUrl

Los campos de contacto principales — email, subscribed, createdAt, updatedAt — también viven fuera de data. Cambiar email o subscribed requiere los campos de solicitud dedicados en lugar de data.

Una clave queda en un punto intermedio: locale. Se guarda dentro de data como cualquier otro campo personalizado, pero Bitelio también la lee para gobernar la localización.

Usar campos personalizados

En plantillas

Cualquier campo puede referenciarse por su nombre como variable de Handlebars:

<p>Hi {{firstName ?? "there"}},</p>
<p>You've been on the {{plan}} plan since {{signupDate}}.</p>

El operador ?? fallback es una extensión de Bitelio para suministrar un valor por defecto cuando el campo falta o es nulo. Los datos anidados también funcionan — un valor guardado en data.profile.tier está disponible como {{profile.tier}}.

En segmentos

En los filtros de segmento, antepone data. al nombre del campo:

{ "field": "data.plan", "operator": "equals", "value": "pro" }
{ "field": "data.lifetimeValue", "operator": "greaterThan", "value": 100 }
{ "field": "data.signupDate", "operator": "within", "value": 30, "unit": "days" }

La taxonomía completa de operadores está documentada en la página de conceptos de Segmentos.

En flujos de trabajo

Los pasos CONDITION de un flujo de trabajo usan la misma notación data.. Y con el paso UPDATE_CONTACT, un flujo de trabajo puede escribir campos personalizados mientras se ejecuta — por ejemplo, estableciendo { stage: "activated" } una vez que se ha abierto el correo de bienvenida.

Inspeccionar tus campos personalizados

Para ver cada campo que tu proyecto ha usado alguna vez — integrados y personalizados por igual — llama a GET /contacts/fields. Cada entrada informa el tipo inferido y qué fracción de contactos lleva un valor:

{
  "fields": [
    { "field": "email",        "type": "string",  "isCustom": false, "coverage": 1.0 },
    { "field": "data.plan",    "type": "string",  "isCustom": true,  "coverage": 0.62 },
    { "field": "data.signupDate", "type": "date",  "isCustom": true,  "coverage": 0.95 }
  ]
}

Esto es útil para auditar tu esquema, detectar campos que han quedado obsoletos, o poblar menús desplegables en una interfaz propia.

Para cualquier campo individual, GET /contacts/fields/:field/values lista los valores distintos que ha tomado — algo natural para un selector tipo "Filtrar por plan" en tu panel.

Limpiar campos sin usar

Los campos tienden a acumularse con el tiempo. Dos endpoints hacen que la poda sea segura:

  • GET /contacts/fields/:field/usage — informa cada segmento, campaña y flujo de trabajo que menciona el campo. Revisa esto antes de eliminar, para que nada se rompa.
  • DELETE /contacts/fields/:field — elimina el campo de todos los contactos del proyecto.

La eliminación solo afecta los datos de contacto. Los segmentos y flujos de trabajo que referenciaban el campo no se eliminan — sus condiciones sobre él simplemente nunca volverán a coincidir. Por eso existe el endpoint de uso: encuentra esas referencias primero y ordénalas.

Buenas prácticas

  • Elige nombres de campo que no vayas a renombrar. Un renombramiento repercute en cada segmento, plantilla y flujo de trabajo que mencione el campo.
  • Guarda las fechas como ISO 8601. Cualquier otro formato te deja sin acceso a los operadores de segmento sensibles a fechas.
  • Mantén los secretos fuera de data. Todo lo que hay ahí es visible en el panel y para cualquiera con acceso a la API. Para códigos de un solo uso que no deban permanecer, usa { value, persistent: false }.
  • Prefiere claves planas cuando un campo tiene muchos valores. Las rutas anidadas como data.profile.tier funcionan bien, pero son un poco más difíciles de detectar en la interfaz de segmentos.