# Referencia de filtros de segmento (/es/guides/segment-filters)

Un formato de filtro aparece en tres lugares: **segmentos dinámicos**, **audiencias de campaña** con `audienceType: "FILTERED"`, y **pasos `CONDITION` dentro de flujos de trabajo**. Domínalo una vez y se traslada a todas partes.

Si prefieres empezar por los conceptos antes que por la sintaxis, lee primero la [página de conceptos de Segmentos](/es/concepts/segments).

## Cómo se estructura un filtro

Todo filtro consta de un conector de nivel superior (`AND` u `OR`) más una lista de **grupos**. Dentro de un grupo, todas las condiciones se combinan con `AND`; el conector de nivel superior combina entonces los grupos.

Un ejemplo lo hace concreto: "usuarios suscritos **y** en el plan Pro **y** (abrieron **o** hicieron clic en un correo recientemente)".

```json
{
  "logic": "AND",
  "groups": [
    {
      "filters": [
        { "field": "subscribed", "operator": "equals", "value": true },
        { "field": "data.plan",  "operator": "equals", "value": "pro" }
      ]
    },
    {
      "filters": [],
      "conditions": {
        "logic": "OR",
        "groups": [
          { "filters": [{ "field": "email.opened",  "operator": "triggeredWithin", "value": 14, "unit": "days" }] },
          { "filters": [{ "field": "email.clicked", "operator": "triggeredWithin", "value": 14, "unit": "days" }] }
        ]
      }
    }
  ]
}
```

El anidamiento funciona dando a un grupo su propio `conditions` — así es como se expresa "esto AND (aquello OR esto)" sin colapsar la lógica en un solo nivel. Cuando trabajas en el panel, el creador de segmentos ensambla todo esto visualmente.

## Campos sobre los que puedes filtrar

Cada valor de `field` lleva un prefijo de espacio de nombres que indica a Bitelio qué aspecto del contacto apunta la condición.

| Patrón de campo          | Apunta a                                                                                     | Ejemplos                         |
| ------------------------ | -------------------------------------------------------------------------------------------- | -------------------------------- |
| `email`                  | La dirección de correo del contacto                                                          | `email`                          |
| `subscribed`             | El estado de suscripción del contacto                                                        | `subscribed`                     |
| `createdAt`, `updatedAt` | Marcas de tiempo integradas del contacto                                                     | `createdAt`                      |
| `data.<path>`            | Datos personalizados del contacto — admite rutas anidadas                                    | `data.plan`, `data.profile.tier` |
| `event.<eventName>`      | Eventos personalizados rastreados vía `/v1/track`                                            | `event.signed_up`                |
| `email.<activity>`       | Interacción con el correo: `sent`, `delivered`, `opened`, `clicked`, `bounced`, `complained` | `email.opened`                   |
| `segment.<segmentId>`    | Pertenencia a otro segmento                                                                  | `segment.cuid_of_other_segment`  |

## Operadores

Qué operadores aplican depende del tipo de campo que estés filtrando.

### Campos de texto

Para `email` y cualquier `data.<key>` que contenga una cadena.

| Operador      | Qué hace                                                                              |
| ------------- | ------------------------------------------------------------------------------------- |
| `equals`      | Coincidencia exacta — ignora mayúsculas en `email`, distingue mayúsculas en `data.*`. |
| `notEquals`   | El inverso de `equals`.                                                               |
| `contains`    | Coincidencia de subcadena, ignorando mayúsculas.                                      |
| `notContains` | El inverso de `contains`.                                                             |

### Campos sí/no

Para `subscribed` y cualquier `data.<key>` que contenga `true` o `false`.

| Operador    | Qué hace                   |
| ----------- | -------------------------- |
| `equals`    | Coincide con true o false. |
| `notEquals` | El inverso.                |

### Fechas y marcas de tiempo

Para `createdAt`, `updatedAt`, y cualquier `data.<key>` que contenga una cadena de fecha ISO 8601.

| Operador                                 | Qué hace                                                                                                                    |
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `equals` / `notEquals`                   | Coincidencia de marca de tiempo. Un valor de solo fecha (`YYYY-MM-DD`) coincide en cualquier momento dentro de ese día UTC. |
| `greaterThan` / `lessThan`               | Estrictamente después / estrictamente antes.                                                                                |
| `greaterThanOrEqual` / `lessThanOrEqual` | Las versiones inclusivas.                                                                                                   |
| `within`                                 | Cae dentro de las últimas N unidades. Requiere `unit: "days" / "hours" / "minutes"`.                                        |
| `olderThan`                              | Está a más de N unidades en el pasado. Requiere `unit`.                                                                     |

En campos de fecha personalizados (`data.<key>`), `within` y `olderThan` requieren que el valor se guarde como una cadena ISO 8601 (p. ej. `"2026-05-06T12:00:00Z"`). Las marcas de tiempo Unix u otros formatos se compararán incorrectamente.

### Números

Cualquier `data.<key>` numérico admite: `equals`, `notEquals`, `greaterThan`, `lessThan`, `greaterThanOrEqual`, `lessThanOrEqual`. No interviene ningún `unit`.

### Existencia de campo

Funciona en cualquier `data.<key>`, sea cual sea su tipo de valor.

| Operador    | Qué hace                                                       |
| ----------- | -------------------------------------------------------------- |
| `exists`    | La clave está establecida en el contacto con un valor no nulo. |
| `notExists` | La clave está ausente, o explícitamente nula.                  |

### Eventos e interacción con correo

El mismo conjunto de operadores sirve tanto a `event.<eventName>` (eventos personalizados) como a `email.<activity>` (interacción con correo).

| Operador             | Qué hace                                                                                                                 |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `triggered`          | El evento ha ocurrido para este contacto al menos una vez, en cualquier momento.                                         |
| `notTriggered`       | El evento nunca ha ocurrido para este contacto.                                                                          |
| `triggeredWithin`    | Ocurrió al menos una vez dentro de las últimas N unidades. Requiere `unit`.                                              |
| `triggeredOlderThan` | Ha ocurrido, pero no dentro de las últimas N unidades. Requiere `unit`.                                                  |
| `notTriggeredWithin` | Ninguna ocurrencia en las últimas N unidades — los contactos que nunca lo dispararon también coinciden. Requiere `unit`. |

### Pertenencia a segmento

Para `segment.<segmentId>`, donde `<segmentId>` es el ID de otro segmento en tu proyecto.

| Operador             | Qué hace                                                    |
| -------------------- | ----------------------------------------------------------- |
| `memberOfSegment`    | El contacto pertenece actualmente al segmento referenciado. |
| `notMemberOfSegment` | El contacto no pertenece a él.                              |

## Referencia rápida: qué pasar con cada operador

* **Toman un `value`**: `equals`, `notEquals`, `contains`, `notContains`, `greaterThan`, `lessThan`, `greaterThanOrEqual`, `lessThanOrEqual`, `within`, `olderThan`, `triggeredWithin`, `triggeredOlderThan`, `notTriggeredWithin`.
* **Toman un `unit`** (`"days"`, `"hours"`, o `"minutes"`): `within`, `olderThan`, `triggeredWithin`, `triggeredOlderThan`, `notTriggeredWithin`.
* **No toman nada más**: `exists`, `notExists`, `triggered`, `notTriggered`, `memberOfSegment`, `notMemberOfSegment`.

## Ejemplos

### Usuarios activos en el plan Pro

Usuarios suscritos del plan Pro que abrieron o hicieron clic en algún correo en los últimos 14 días pero no han hecho clic en nada en los últimos 30 días.

```json
{
  "logic": "AND",
  "groups": [
    {
      "filters": [
        { "field": "subscribed", "operator": "equals", "value": true },
        { "field": "data.plan",  "operator": "equals", "value": "pro" }
      ]
    },
    {
      "filters": [],
      "conditions": {
        "logic": "OR",
        "groups": [
          { "filters": [{ "field": "email.opened",  "operator": "triggeredWithin", "value": 14, "unit": "days" }] },
          { "filters": [{ "field": "email.clicked", "operator": "triggeredWithin", "value": 14, "unit": "days" }] }
        ]
      }
    },
    {
      "filters": [
        { "field": "email.clicked", "operator": "notTriggeredWithin", "value": 30, "unit": "days" }
      ]
    }
  ]
}
```

### Nuevos usuarios de prueba sin una compra

Contactos suscritos creados en los últimos 7 días que aún no han disparado un evento `purchase`.

```json
{
  "logic": "AND",
  "groups": [
    {
      "filters": [
        { "field": "subscribed",     "operator": "equals",       "value": true },
        { "field": "createdAt",      "operator": "within",       "value": 7, "unit": "days" },
        { "field": "event.purchase", "operator": "notTriggered" }
      ]
    }
  ]
}
```

### Usuarios avanzados por encima de un nivel

Miembros del segmento `power-users` cuyo valor de vida útil es al menos 500.

```json
{
  "logic": "AND",
  "groups": [
    {
      "filters": [
        { "field": "segment.<powerUsersSegmentId>", "operator": "memberOfSegment" },
        { "field": "data.lifetimeValue", "operator": "greaterThanOrEqual", "value": 500 }
      ]
    }
  ]
}
```

## Relacionado

<Cards>
  <Card title="Segmentos" href="/es/concepts/segments">
    Segmentos estáticos vs dinámicos, seguimiento de membresía y eventos de entrada/salida.
  </Card>

  <Card title="Campos personalizados" href="/es/guides/custom-fields">
    Cómo se tipan y usan los campos `data.*` en filtros.
  </Card>
</Cards>
