Skip to main content

End-of-Conversation Survey

A built-in star-rating + comment flow that triggers when the user closes the widget (or when you explicitly request it). Submissions go through the connector via the optional sendSurvey() capability.

Survey screen mode

Screenshot pending capture from the sandbox.

Configuration

Set under theme.endOfConversationSurvey. Default: enabled. Full schema: schemas/theme.schema.jsonendOfConversationSurvey.

chatStore.getState().setTheme({
endOfConversationSurvey: {
enabled: true, // default true
mode: "screen", // "screen" (overlay) | "inline" (bot card)
trigger: "onClose", // "onClose" | "manual"
maxRating: 5,
requireCommentBelow: 3, // require text when rating <= 3 (0 to disable)
kind: 1, // forwarded to SurveyPayload.kind
resetOnSubmit: true, // tear down engine + connector after submit
},
});

Modes

ModeWhat the user sees
screen (default)Full-height overlay over the chat panel — title, stars, comment, Submit / Skip.
inlineA bot-authored survey card appended to the message list.

Trigger

TriggerWhen the survey shows
onClose (default)The header's close button is intercepted. The survey appears; only after submit/skip does the widget actually close.
manualOnly when the host page dispatches a show-survey event on the widget.
document.querySelector("chat-iva")?.dispatchEvent(new CustomEvent("show-survey"));

Resetting on submit

resetOnSubmit: true (default) is the right choice for most kiosks and customer-care flows: a new visit means a new conversation. Set it to false to keep the session, history, and connection alive — useful when the survey is just a checkpoint, not an ending.

Connector contract

When the user submits, ChatEngine calls connector.sendSurvey(payload):

interface SurveyPayload {
rating: number;
comment?: string;
kind?: string | number;
}

Each built-in connector ships an opinionated default delivery format:

ConnectorWire format
DirectLineevent activity, name webchat/customerfeedback, value { rating, comment, type } where type = Number(kind ?? 1) (legacy bot-friendly).
SignalRconnection.invoke(surveyMethod, payload)surveyMethod defaults to "SendSurvey".
WebSocketJSON frame { "type": "survey", ...payload }.
SSEPOST to sendUrl, body { "type": "survey", ...payload }.
HTTPPOST to {url}/survey, body payload.
DummyLogs to console — useful for testing the UI flow.

If your connector is custom, just implement sendSurvey?(payload). Without it, the survey UI is hidden.

class MyConnector implements IConnector {
async sendSurvey(payload: SurveyPayload): Promise<void> {
await fetch("/api/feedback", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
}
}

Listening from your code

The survey emits a typed EventBus event after the connector accepts:

import { EventBus } from "@chativa/core";
EventBus.on("survey_submitted", (payload) => {
// analytics, toast, redirect, …
});