Inicio / Artículos

Flujos de trabajo para profesores de instrumentos con PostHog autocapture y eventos personalizados

Capa de captura automática PostHog, eventos de resultado, reproducción de sesiones y líneas de tiempo personales para que los productos de enseñanza asistidos por IA midan las tareas completadas, y no solo los clics.

Editor: REACTAPP.TOP4 min de lectura1031 palabras

Fuentes: **Instrumenting User Behaviour on KaushalSaathi with PostHog**

KaushalSaathi es una plataforma educativa centrada en la inteligencia artificial dirigida a profesores. Puede redactar planes de lección, guiar un modo de enseñanza en múltiples pasos, organizar horarios y ofrecer chats de tutoría. Dado que gran parte del valor del producto se obtiene a través de la generación asíncrona en lugar de simples desplazamientos entre páginas, la estrategia de medición tuvo que considerar las tareas completadas como señales de primera categoría, y no solo los clics y los cambios de ruta.

Implementar funciones sin observar su uso real es una trampa común. La existencia de pantallas adicionales no implica necesariamente mejores resultados. Antes de añadir una nueva funcionalidad, un equipo necesita pruebas de qué elementos ya utilizan los educadores, dónde se detienen y qué interfaces nunca abren. La observabilidad del comportamiento convierte las decisiones sobre el producto de una suposición en decisiones basadas en datos reales. Ese es el problema que se abordó con PostHog: ¿cómo utilizan realmente los profesores el producto que ya existe?

Autocapture como línea de base gratuita

Autocapture abarca las actividades a nivel DOM sin necesidad de configuraciones personalizadas: clics, $pageview, $pageleave y los límites de sesión. Al utilizar este proveedor incondicionalmente y considerar que la falta de una clave API equivale a un apagado, el desarrollo local y las ramas creadas por colaboradores quedan exentos de la necesidad de configurar cuentas o de incluir ramas if (enabled) dispersas por todo el código:

const POSTHOG_KEY = import.meta.env.VITE_POSTHOG_KEY ?? "phc_disabled_no_key_set";
const ENABLED = POSTHOG_KEY !== "phc_disabled_no_key_set";
<PostHogProvider
apiKey={POSTHOG_KEY}
options={{
api_host: POSTHOG_HOST,
autocapture: ENABLED,
capture_pageview: ENABLED,
session_recording: { maskAllInputs: true },
loaded: (ph) => { if (!ENABLED) ph.opt_out_capturing(); },
}}

Autocapture indica dónde navegó alguien, pero no indica qué terminó de hacer. Un manejador de clics en el DOM nunca detecta que se haya completado una tarea asíncrona, como la generación de un plan de lecciones, el final de un período en Modo Enseñanza o la exportación exitosa de un PDF. Ninguna de estas acciones genera un clic en el DOM al que se pueda conectar, por lo que, por diseño, Autocapture no puede detectarlas. Esa brecha es precisamente la razón por la cual existe una segunda capa.

Eventos personalizados que se convierten en métricas

Los resultados significativos se emiten como eventos personalizados a través de un wrapper sencillo de tres funciones. Cada llamada verifica posthog.__loaded, por lo que el resto de la aplicación nunca realiza comprobaciones de valor nulo en los datos analíticos ni se preocupa por si la captura está activa:

export function captureEvent(name: string, props?: Record<string, unknown>) {
if (!posthog.__loaded) return;
posthog.capture(name, props);
}

Dos convenciones garantizan que esos eventos sigan siendo útiles en consultas posteriores.

Emite el evento al tener éxito, no al intentarlo. La captura se ejecuta en la ruta de éxito asíncrona, no dentro del manejador del botón, por lo que los gráficos reflejan el trabajo completado:

const plan = await generateLessonPlan(payload); // resolves only on success
captureEvent("lesson_plan_generated", {
grade: plan.grade, sector: plan.sector, language: plan.language,
});

Asocia propiedades que servirán como dimensiones de desglose. Campos como grade, language, sector y periodNumber se transmiten junto con el evento en el momento de su emisión. Dentro de PostHog se convierten en filtros y desgloses sin necesidad de realizar otra pasada de instrumentación; un solo evento puede responder a preguntas como “generaciones por grado”, “por idioma” o “por sector”.

La función clave es identifyUser, que se ejecuta una vez desde el hook de autenticación después de que el inicio de sesión tenga éxito. Esa llamada relaciona el identificador anónimo temporal con la cuenta autenticada y agrega campos relacionados con los roles de la persona, lo que significa que las capturas y grabaciones posteriores heredarán la misma atribución:

posthog.identify(user.id,
{ role: user.role, grade: user.grade, school: user.school });
// on logout: posthog.reset() ← must run before the redirect, or events leak to the next id

El orden de las llamadas al cerrar sesión es importante. Redirigir antes de ejecutar reset() en un dispositivo compartido puede hacer que la siguiente sesión quede marcada con la identidad anterior. Primero restablezca los datos y luego continúe navegando.

Cada evento aporta entonces una información guardada. La forma habitual de hacerlo es contar los eventos, desglosados por nombre de la persona:

  • lesson_plan_generated en toda la ventana, agrupado por hora, genera una serie temporal que muestra cuándo ocurrieron los eventos, además de una tabla detallada con resultados clasificados que indica quién los realizó. Esta única vista permite identificar a los usuarios más activos, las inscripciones inactivas y la concentración del uso. El límite por defecto de filas en el desglose es 25; aumentémoslo a 50 cuando sea importante analizar la parte más extensa de los datos.
  • chat_message_sent limitado al día de ayer y agrupado por hora reutiliza el mismo evento pero con un rango más reducido; por ejemplo, un pico por la tarde alrededor de las 15:00 asociado a un único profesor.

La misma definición de evento, pero con un rango de fechas y desglose diferentes. Una nueva pregunta se convierte en una nueva vista guardada, no en nuevo código de aplicación.

Reproducción de sesiones para entender el “porqué”

Las estadísticas explican qué y cuán a menudo, pero no por qué. La grabación permanece activa por defecto con maskAllInputs: true, ya que los profesores ingresan información personal identificable de estudiantes y escuelas. Los clics, la navegación, el nivel de desplazamiento y las pausas siguen siendo visibles; los valores ingresados se enmascaran al capturarlos.

Situciones en las que la reproducción vale la pena:

  • Localización de fugas en el proceso. Cuando lesson_plan_generated se activa pero pdf_exported no para un grupo, las estadísticas indican la fuga y la reproducción muestra el paso exacto de exportación donde las personas abandonan el proceso.
  • Fallas silenciosas en múltiples pasos. El Modo de enseñanza puede fallar sin generar señales visibles; los usuarios simplemente dejan de usarlo. La reproducción permite distinguir entre un estado de interfaz dañado, una etiqueta confusa o una generación lenta que provoca el tiempo de espera.

Lineales de actividad por persona

Una vez que la identificación vincula las capturas y reproducciones a una cuenta, la pantalla de usuario de PostHog muestra una línea de tiempo para ese educador: qué eventos se activaron, qué funciones abrió y qué sesiones se almacenaron. Los usos prácticos incluyen verificar que después de un registration_completed reciente haya un primer lesson_plan_generated (para evaluar el proceso de adaptación), abrir la línea de tiempo de un usuario con alto volumen de uso antes de diseñar soluciones según su trayectoria, o reconstruir un error reportado a partir de la sesión exacta en lugar de depender de la memoria.

Combinando las capas

Autocapture proporciona una señal de referencia sin costo adicional. Los eventos y métricas personalizados convierten los resultados de las funcionalidades en series temporales clasificadas y segmentadas por propiedad. La reproducción de sesiones ofrece detalles causales detrás de las formas en los gráficos. Las líneas de tiempo de las personas permiten hacer zoom desde el nivel general hasta un único educador. Juntos, estos elementos son suficientes para decidir qué desarrollar a partir del comportamiento observado y no a partir de suposiciones sobre cómo “debería” usarse el producto.