Cómo los formularios de admisión de los tres sitios dejan de mandar nombres de carrera en texto libre y empiezan a mandar el identificador canónico de ECORE — con la cédula y el título verificados en el mismo paso.
Hoy cada formulario manda el nombre de la carrera como texto. Maestría en
Ciberseguridad llega a Zapier como una cadena, y del otro lado nadie sabe si es
la versión híbrida o la online — son dos programas distintos, con cupo, malla y precio
distintos. Mientras el destino era Zendesk eso se resolvía leyendo el ticket. Con
Salesforce de por medio, un lead mal atribuido es un lead perdido en el embudo
equivocado.
ECORE ya publica el catálogo académico con identificadores estables. Este documento describe cómo se conecta, qué se probó con datos reales, y las decisiones que quedan abiertas.
Contra el API de producción, no contra documentación.
La credencial funciona y tiene los dos permisos que el proyecto necesita. El correo
de habilitación solo mencionaba datos:read, pero /whoami
confirma que oferta:read también está concedido — no hay nada que pedirle
al equipo de ECORE para arrancar.
El catálogo trae 128 carreras activas. Los
carrera_id son únicos en las 128 filas, así que sirven directamente como
External Id de Salesforce para hacer upsert idempotente.
| Oferta | Presencial | Online | Híbrida | Virtual | Total |
|---|---|---|---|---|---|
| Grado | 26 | 18 | 2 | — | 46 |
| Posgrado | 17 | 29 | 35 | 1 | 82 |
Dónde se gasta cuota del API y dónde no.
carrera_id, y el payload
unificado. Zapier y Zendesk siguen exactamente como están.La parte que hay que ver funcionando antes de confiar en ella.
Aquí está el hallazgo que define el diseño: 17 carreras del catálogo existen
en dos modalidades con carrera_id distinto. No son variantes de un
mismo registro; son programas separados.
| Carrera | Presencial | Online | Híbrida |
|---|---|---|---|
| Administración de Empresas | 149 | 93 | |
| Derecho | 320 | 414 | |
| Economía | 157 | 96 | |
| Marketing | 321 | 416 | |
| Sistemas Inteligentes | 31 | 233 | |
| Maestría en Ciberseguridad | 109 | 245 | |
| Maestría en Derecho Penal | 200 | 118 | |
| Maestría en Marketing Estratégico | 197 | 360 |
Son 8 de las 17; la lista completa está en el visualizador. La consecuencia es
directa: la llave del mapeo es (post, modalidad), nunca solo el
post. Un post de WordPress puede necesitar dos o tres identificadores según la
modalidad que elija el aspirante.
La mitad de los leads de Administración de Empresas entra a Salesforce apuntando al programa presencial cuando pidieron el online. El dato se ve limpio y está mal.
select se alimenta directo de ECORE,
el problema del match desaparece — el identificador viaja en el
value de la opción. El match solo hace falta en las páginas individuales
de WordPress, donde el programa lo define el post.Los nombres que devuelve ECORE no son consistentes entre sí. Tildes irregulares, la modalidad embebida en el nombre, separadores que cambian y espacios dobles:
ADMINISTRACION DE EMPRESAS - ONLINE ← sin tilde
ADMINISTRACIÓN DE EMPRESAS ← con tilde
CRIMINALISTICA - HIBRIDA ← espacio doble, sin tilde
NEGOCIOS INTERNACIONALES - HÍBRIDA ← con tilde
PSICOLOGÍA - ITINERARIO EN… ← guion (presencial)
PSICOLOGÍA, ITINERARIO EN… ← coma (online)
Por eso el normalizador corre en cinco pasos y solo se usa para autosugerir en la pantalla de mapeo, donde una persona confirma. Nunca decide solo en un envío.
nombre_carrera es un LIKE al que ECORE no le agrega
comodines. Enviar BIG DATA devuelve cero resultados; hay que mandar
%BIG DATA%. Es otra razón para resolver contra el catálogo cacheado en
lugar de consultar el API en cada envío.
Casos reales contra el catálogo de producción.
| Título en WordPress | Modalidad | Estado | Método | Resultado |
|---|---|---|---|---|
| Maestría en Big Data | — | ok | nombre_unico | 117 |
| MAESTRIA EN BIG DATA (sin tildes) | — | ok | nombre_unico | 117 |
| maestría en big data (espacios) | — | ok | nombre_unico | 117 |
| Maestría en Ciberseguridad | — | ambiguo | — | 109 ó 245 |
| Maestría en Ciberseguridad | Online | ok | nombre_y_modalidad | 109 |
| Maestría en Ciberseguridad | Híbrida | ok | nombre_y_modalidad | 245 |
| Maestría en Ciberseguridad | Presencial | no existe | — | — |
| Maestría en Derecho Penal | Online | ok | nombre_y_modalidad | 118 |
| Maestría en Derecho Penal | Presencial | ok | nombre_y_modalidad | 200 |
| Maestría en Blockchain (no existe) | — | sin match | — | — |
El normalizador absorbe tildes y espacios sin problema. Lo que no puede absorber es la falta de modalidad: ahí se detiene y lo reporta en lugar de adivinar. Ese es el comportamiento correcto — adivinar es exactamente lo que produce el dato sucio que parece limpio.
Reemplaza la pregunta autodeclarada en los cuatro formularios.
Hasta ahora el formulario de ECOTEC Online preguntaba «¿Posee un título universitario registrado en SENESCYT?» y bloqueaba si la respuesta era bachillerato. Esa pregunta desaparece: al escribir la cédula se consulta la fuente real.
La secuencia tiene una compuerta local antes de tocar el API. La validación módulo 10 rechaza cédulas mal escritas sin gastar cuota — y de paso da un mensaje de error mucho más útil que un 404.
| Estado | De dónde sale | ¿Bloquea? | Qué significa |
|---|---|---|---|
| verificado | 200 · superiores ≠ ∅ | no | Tiene título de nivel superior registrado. |
| sin_titulo | 200 · superiores = ∅ | no | Cédula válida sin título en la fuente. Puede tener título extranjero no registrado. |
| no_encontrado | 404 | no | No está en la fuente. Extranjero, o error de digitación que pasó el módulo 10. |
| cedula_invalida | módulo 10 local | sí | El único bloqueo. El dato está mal escrito y no cuesta nada detectarlo. |
| error_api | 502 · 504 | no | La fuente no responde. El formulario continúa. |
| rate_limited | throttle local | no | Demasiadas consultas desde una IP. Se envía sin validar, marcado. |
Lo único que bloquea el envío es una cédula mal formada. Todo lo demás se marca y se manda. Perder un aspirante de maestría porque la fuente de datos estaba caída cuesta más que revisar un lead marcado; y un título extranjero legítimo no aparece en SENESCYT. La elegibilidad la decide admisiones con el dato al lado, no el formulario.
/datos/civil devuelve bastante más de lo que un formulario necesita:
dirección domiciliaria con calle y número, nombres del padre y de la madre, estado
civil, cónyuge, profesión, teléfonos y correos. /datos/titulos devuelve el
historial académico completo.
El servidor filtra y solo entrega cuatro cosas al navegador: el estado, el conteo de títulos, y los tres campos que se autocompletan.
Se está consultando el registro nacional con la cédula de una persona. El checkbox de términos tiene que decirlo explícitamente. Si se devolviera el payload crudo al navegador, el formulario se convertiría en un servicio público de consulta de cédulas — de ahí el filtro del servidor, no es una precaución teórica.
La validación de título no se puede desplegar todavía.
Al probar contra la fuente real apareció un problema que cambia el plan.
/datos/titulos no responde para cédulas reales: devuelve
504 a los 25 segundos, de forma consistente en todos los intentos.
| Endpoint | Respuesta | Tiempo | Estado |
|---|---|---|---|
| /datos/civil | 200 · datos completos | 0,3 s | funciona |
| /datos/padron | 200 | 0,1 s | funciona |
| /oferta/activa | 200 · 128 carreras | 0,4 s | funciona |
| /datos/titulos | 200 · {"message":"no"} | 1,5 s | solo si no halla a la persona |
| /datos/titulos | 504 · upstream-timeout | 25 s | cédula real |
El bloqueo por título no puede ser una compuerta síncrona del formulario. Aunque el servicio se recupere, 25 segundos de espera en un campo es inviable, y hoy el resultado sería un 504 para cada aspirante de posgrado. Con la regla de fail-open eso significa que nadie quedaría bloqueado — la función existiría sin funcionar.
Cuando la fuente no encuentra a la persona, /datos/titulos responde
200 con {"message":"no"} — no el 404
que promete la documentación, y sin el objeto data.
Una implementación que siga el contrato documentado leería data.superiores
como lista vacía y clasificaría a esa persona como sin_titulo. Con el bloqueo
activo, la rechazaría — cuando lo cierto es que la fuente simplemente no la
conoce, y ese caso debe pasar.
Separar la validación del envío. El lead se manda de inmediato con
titulo_validacion_estado = pendiente, y un proceso en segundo plano
consulta los títulos y actualiza el registro en Salesforce cuando la fuente responda.
Así el formulario nunca espera 25 segundos, ningún lead se pierde por un 504, y el dato
llega igual — unos minutos después. Si además se quiere bloquear, el bloqueo lo aplica
admisiones sobre el lead ya marcado, no el formulario.
Vale reportar tres cosas: el 504 sostenido de
/datos/titulos, que el caso «no encontrado» devuelve 200 en
lugar del 404 documentado, y que los headers
RateLimit-* que la documentación promete no se envían.
Qué se agrega y por qué Zendesk no se entera.
Los cuatro plugins ya normalizan su payload contra un PAYLOAD_SCHEMA
fijo, precisamente para que Zapier vea siempre la misma firma. Los campos nuevos hay
que agregarlos a ese schema, no solo inyectarlos por el filtro — si no,
aparecen de forma intermitente y rompen el mapeo.
| Campo nuevo | Ejemplo | Para qué sirve en Salesforce |
|---|---|---|
| ecore_carrera_id | 109 | External Id del programa. Upsert idempotente. |
| ecore_malla_id | 154 | Versión de malla. Cambia con los años; el carrera_id no. |
| ecore_facultad_id | 23 | Agrupación para reportes y asignación de asesor. |
| ecore_oferta | Posgrado | Grado · Posgrado · Nivelación. |
| ecore_modalidad | Online | Lo que distingue los 17 pares duplicados. |
| ecore_carrera_nombre | MAESTRÍA EN… | Solo lectura humana. Nunca como llave. |
| ecore_match_metodo | nombre_y_modalidad | Auditoría: cómo se resolvió este lead. |
| titulo_validacion_estado | verificado | Reemplaza la pregunta autodeclarada. |
| titulo_tiene_superior | 1 | Booleano para reglas de asignación. |
| linea_negocio_std | posgrado | Discriminante único entre los cuatro plugins. |
Zapier ignora los campos que no estén mapeados en el Zap. Los ecore_*
pueden empezar a llegar hoy mismo y el flujo actual hacia Zendesk sigue idéntico, sin
tocar el Zap. Cuando llegue el conector de Salesforce, los campos ya llevan meses
llegando limpios y solo hay que mapearlos.
| Plugin | Sitio | Campo de carrera | Prefijo |
|---|---|---|---|
| ecotec-forms | ecotec.edu.ec | carrera + carrera_slug + campus | ewf_ |
| ecotec-webmaster-forms | ecoteconline.edu.ec | carrera + oferta + facultad + linea_negocio | ewf_ |
| ecotec-posgrado-forms | posgrado.ecotec.edu.ec | programa + modalidad | epf_ |
| ecotec-homologacion-forms | por confirmar | carrera + carreras_homologacion | ehf_ |
Posgrado manda programa y no manda carrera en absoluto.
Los cuatro exponen el filtro que hace falta para inyectar los campos nuevos, aunque
ehf_zapier_payload pasa un solo argumento y necesita un ajuste menor.
60 peticiones por minuto que no se pueden medir.
El límite es por API key, y hay una sola key para
ecotec.edu.ec, ecoteconline.edu.ec y
posgrado.ecotec.edu.ec. Los tres sitios comparten el mismo presupuesto.
Y hay un detalle que la documentación de ECORE no refleja:
ECORE documenta headers RateLimit-Limit,
RateLimit-Remaining y RateLimit-Reset en cada respuesta.
No los envía. Lo único que llega es x-request-id. La
cuota hay que presupuestarla, no medirla — vale la pena reportarlo al equipo de ECORE.
| Llamada | Cuándo | Defensa |
|---|---|---|
| POST /oferta/activa | 1 cada 12 h | Cache del catálogo completo. 128 carreras, sin paginación. |
| GET /datos/titulos | 1 por cédula nueva | Cache 24 h + throttle 8/10 min por IP + módulo 10 antes. |
| GET /datos/civil | igual que arriba | Misma defensa. Se puede omitir si no se autocompleta. |
Sin estas defensas, un bot en el campo de cédula agota en un minuto la cuota de toda
la institución. Los plugins ya tienen honeypot y nonce en EWF_Security, así
que es extender lo que existe.
De las 128 carreras, 80 traen un url_admissions que apunta a un
entorno que no es producción. La documentación advierte la posibilidad; los
datos la confirman.
| Host | Carreras | Usable |
|---|---|---|
| dev-admisiones.ecotec.edu.ec | 53 | no |
| demo-admisiones.ecotec.edu.ec | 27 | no |
| admisiones-nbs.ecotec.edu.ec | 39 | sí |
| null | 9 | vacío |
Si se va a redirigir aspirantes con ese campo hay que validar el host contra una lista blanca y caer a una URL propia en el resto de los casos.
Qué es esto y qué falta para producción.
Lo que está corriendo es un prototipo en Python que consulta ECORE en vivo: valida cédulas, resuelve carreras contra el catálogo real y arma el payload completo. Sirve para ver el mecanismo funcionando con datos de producción antes de escribir el plugin.
El prototipo no es el plugin. Está en Python porque la máquina de desarrollo no tiene PHP instalado. La lógica se traduce pieza por pieza; el código de producción es PHP dentro de WordPress.
| Prototipo | WordPress |
|---|---|
| ecore.Cliente | Ecore_Client sobre wp_remote_get/post |
| ecore.Catalogo | set_transient(…, 12 * HOUR_IN_SECONDS) |
| ecore.resolver() | Ecore_Mapping::resolver() |
| mapeo-carreras.json | post meta _ecore_carrera_id por (post, modalidad) |
| ecore.validar_titulo() | Ecore_Titulos + wp_ajax_nopriv con nonce |
| payload_estandar() | filtro *_zapier_payload + PAYLOAD_SCHEMA |
| .env | define('ECOTEC_ECORE_API_KEY', …) en wp-config.php |
Un archivo .env dentro de wp-content/plugins/ es
descargable por HTTP en la mayoría de configuraciones de Nginx y Apache. En producción
la key va como constante en wp-config.php, y todas las llamadas salen del
servidor.
Cerradas el 24 de agosto de 2026.
| Decisión | Resuelto | Qué implica |
|---|---|---|
| Instalaciones | 3 WordPress separados | La key va en tres wp-config.php. El mapeo vive en cada sitio. Los tres comparten los 60 req/min de la misma credencial. |
| Bloqueo sin título | Sí, en Posgrado | Solo cuando la oferta exige título. «No pudimos verificar» no bloquea: no_encontrado, error_api y rate_limited pasan marcados. Hoy inaplicable — ver el bloqueador. |
| Homologación | ecoteconline.edu.ec | Ese sitio mezcla Grado y Posgrado, así que el bloqueo depende de la carrera elegida, no del dominio. |
| Autocompletar | Sí | Nombre, apellido y provincia desde /datos/civil, que responde en 0,3 s. Solo esos tres campos salen al navegador. |
El plugin ecotec-ecore-connect en PHP: cliente, catálogo cacheado,
pantalla de mapeo y los filtros de payload. La validación de título queda diseñada
pero desactivada hasta que /datos/titulos responda.