- Guías
- Feedback (CSAT)
Feedback (CSAT)
Una micro-encuesta de tres tipos (emoji3, scale7, thumbs), una vez por visitante por ventana de cadencia. Viene apagada y ver resultados es Pro.
Feedback es una micro-encuesta que Espejo les muestra a tus usuarios finales. Un toque, un voto, y cae en el dashboard de Satisfaction. Es la forma más barata de preguntar “¿qué tal estuvo?” sin construir tu propia herramienta de encuestas.
Dos widgets, no los confundas
Sección titulada «Dos widgets, no los confundas»Espejo trae dos cosas distintas, y van a dos lugares distintos:
- La encuesta CSAT — la preguntita de acá abajo — es un voto. Va a Satisfaction.
- El botón “Reportar un problema” (🐞) es una grabación. Va a Recordings.
Una mide cómo se siente la gente; el otro captura qué salió mal. Se activan y se leen por separado.
Los tres tipos
Sección titulada «Los tres tipos»| Tipo | Se ve como | Sirve para |
|---|---|---|
emoji3 | tres caritas 🙁 😐 🙂 | una lectura rápida de humor |
scale7 | una escala 1–7 | un puntaje más fino, estilo NPS |
thumbs | 👍 / 👎 | un sí/no directo |
Elegís uno por proyecto. Cada voto va a la misma vista de Satisfaction.
Cómo activarla
Sección titulada «Cómo activarla»La encuesta viene apagada por defecto en todos los proyectos. Se activa en la consola:
- Abrí Project Settings → Feedback.
- Elegí el tipo —
emoji3,scale7othumbs. - Fijá
cadence_days— cuánto pasa antes de volver a preguntarle al mismo visitante.
Nada cambia en tu página; el SDK lee la config del proyecto. Un visitante ve la encuesta una vez por ventana de cadencia, y el sello de “visto” se escribe cuando aparece — no cuando responde — así que alguien que la descarta no vuelve a ser molestado hasta que la ventana da la vuelta.
Cómo apagarla desde la página
Sección titulada «Cómo apagarla desde la página»La config del proyecto es el default. Para suprimir la encuesta en una página o build puntual, poné el atributo en el script:
<script src="https://app.espejo.dev/sdk/espejo.js" data-key="pk_live_..." data-feedback="off"></script>Tu propio formulario de feedback
Sección titulada «Tu propio formulario de feedback»Cuando la encuesta tiene que seguir tu diseño, o aparecer en el momento que tú elijas, puedes dibujarla tú y mandar los votos con el SDK. Llegan al mismo dashboard de Satisfaction que los del widget. La encuesta igual tiene que estar activada en Project Settings → Feedback: ahí el proyecto elige su tipo, y un proyecto con la encuesta apagada rechaza los votos.
Apaga el widget de Espejo
Sección titulada «Apaga el widget de Espejo»Para que tus visitantes no vean dos encuestas, apaga la nuestra en las páginas
que muestran la tuya. Con npm, pasa feedback: "off" al constructor:
import { Espejo } from "@espejo/browser";
const espejo = new Espejo({ key: "pk_live_...", feedback: "off" });espejo.start();Con el script, agrega data-feedback="off", como en
Cómo apagarla desde la página. En los dos
casos solo desaparece el widget: getFeedbackConfig() y vote() siguen
funcionando.
getFeedbackConfig()
Sección titulada «getFeedbackConfig()»getFeedbackConfig(): Promise<FeedbackConfig | null>
interface FeedbackConfig { enabled: boolean; // siempre true cuando la config no es null kind: "emoji3" | "scale7" | "thumbs"; cadence_days: number; // de 1 a 365}Devuelve la config de la encuesta del proyecto, o null si está apagada.
También devuelve null si la config no se pudo cargar (sin red, un error de la
API o sin respuesta en 2 segundos). Nunca lanza un error. Úsala para decidir si
muestras tu formulario y qué pregunta dibujas. El navegador puede guardar la
respuesta en caché hasta 5 minutos, así que un cambio en la consola puede
tardar eso en llegar a una página abierta.
FeedbackConfig y FeedbackKind se exportan como tipos desde
@espejo/browser.
vote(value: number, options?: { kind?: FeedbackKind }): Promise<void>Manda un voto y se resuelve cuando la API lo acepta. value es la
respuesta cruda, un entero dentro del rango de su tipo:
| Tipo | value |
|---|---|
emoji3 | 0 (triste), 1 (neutral) o 2 (contento) |
scale7 | de 1 a 7 |
thumbs | 0 (pulgar abajo) o 1 (pulgar arriba) |
options.kind toma por defecto el tipo del proyecto. vote() también manda
el host de la página actual y tu userRef (del constructor, de
data-user-ref o de identify()), igual que el widget.
Se rechaza con un Error en estos casos:
| Caso | El mensaje empieza con |
|---|---|
| La encuesta está apagada, o su config no se pudo cargar. | Espejo: feedback is off |
value no es un entero dentro del rango del tipo. No se manda nada. | Espejo: invalid <kind> vote |
| La API contestó con un status fuera de 2xx. | ingest rejected the vote: HTTP <status>, seguido del comienzo del cuerpo de la respuesta |
Si falla la red, se rechaza con el error del propio navegador.
La cadencia la decides tú
Sección titulada «La cadencia la decides tú»vote() no aplica cadence_days ni recuerda quién ya respondió. Cuándo
preguntar, y cada cuánto, lo decide tu código. La config te da el
cadence_days del proyecto por si quieres seguirlo.
Un ejemplo completo
Sección titulada «Un ejemplo completo»Tres botones de emoji que aparecen solo si la encuesta está activada, y como
mucho una vez cada cadence_days por navegador.
<div id="csat" hidden> <p>¿Qué tal tu experiencia?</p> <button data-value="0">🙁</button> <button data-value="1">😐</button> <button data-value="2">🙂</button></div>import { Espejo } from "@espejo/browser";
const espejo = new Espejo({ key: "pk_live_...", feedback: "off" });espejo.start();
const LAST_ASKED = "my-app:csat-asked-at";const DAY_MS = 24 * 60 * 60 * 1000;
async function maybeAsk() { const config = await espejo.getFeedbackConfig(); if (!config || config.kind !== "emoji3") return;
const last = Number(localStorage.getItem(LAST_ASKED) ?? 0); if (Date.now() - last < config.cadence_days * DAY_MS) return; localStorage.setItem(LAST_ASKED, String(Date.now()));
const box = document.getElementById("csat")!; box.hidden = false; box.querySelectorAll<HTMLButtonElement>("button").forEach((button) => { button.addEventListener("click", async () => { box.hidden = true; try { await espejo.vote(Number(button.dataset.value)); } catch (error) { console.warn("No se guardó el voto", error); } }); });}
maybeAsk();Con el script, la misma instancia es window.espejo, con los mismos
getFeedbackConfig() y vote():
<script src="https://app.espejo.dev/sdk/espejo.js" data-key="pk_live_..." data-feedback="off"></script><script> window.espejo.getFeedbackConfig().then((config) => { if (!config) return; // Muestra tu formulario y, al hacer clic: // window.espejo.vote(2).catch((error) => console.warn(error)); });</script>window.espejo existe una vez que espejo.js se ejecutó. Cárgalo sin async
ni defer si un script inline justo después lo usa, o espera al evento load.
El endpoint HTTP
Sección titulada «El endpoint HTTP»Para un formulario que no usa el SDK. Llámalo desde el navegador del visitante.
Config: GET https://app.espejo.dev/v1/ingest/feedback-config?key=pk_live_...
siempre contesta 200 con
{ "success": true, "data": { "enabled", "kind", "cadence_days" } }. Una clave
desconocida o revocada, una cuenta desactivada y una encuesta apagada devuelven
enabled: false.
Voto: POST https://app.espejo.dev/v1/ingest/feedback
- Cabeceras:
x-espejo-key: pk_live_...ycontent-type: application/json. El navegador mandaOrigin, y tiene que ser uno de los orígenes permitidos del proyecto (un proyecto sin orígenes permitidos acepta cualquiera). Mándalo sin cookies (credentials: "omit"). - Cuerpo:
{ "kind": "emoji3", "value": 2, "page_host": "app.example.com", "user_ref": "user-123" }.kindyvalueson obligatorios, con los rangos de arriba.page_host(hasta 255 caracteres) yuser_ref(hasta 400) son strings opcionales. El cuerpo puede pesar hasta 16 KB. - Respuesta:
200con{ "success": true, "data": { "vote_id": "<32 caracteres hex>" } }.
| Status | Mensaje | Causa |
|---|---|---|
400 | `kind` must be one of: emoji3, scale7, thumbs. | Falta kind o no es uno de los tres. |
400 | `value` is out of range for this feedback kind. | value no es un entero dentro del rango de kind. |
403 | Missing x-espejo-key header. o Invalid ingest key. | Sin clave, o una desconocida o revocada. |
403 | This account is deactivated. Recording is off. | La cuenta está desactivada. |
403 | Origin <origin> is not allowed for this project. | El Origin no está en la lista de permitidos. |
403 | Feedback is disabled for this project. | La encuesta está apagada en Project Settings → Feedback. |
403 | This project hit its daily feedback vote cap. It resets at midnight UTC. | El proyecto llegó a 50.000 votos hoy. |
503 | Ingest is unavailable: the database is not configured. | El servicio no está disponible. |
Límites
Sección titulada «Límites»- Un voto es un número. No hay comentario de texto libre: la API no tiene un campo para eso.
- Hasta 50.000 votos por proyecto por día. El conteo se reinicia a la medianoche UTC.
- Uno de los tres tipos por proyecto, elegido en la consola.