Manual feedback event capture

Contents

If you are not building a React app or otherwise need more control (such as a completely custom followup UI), you can capture user feedback events manually.

In summary, you'll emit these events with $ai_trace_id properties:

  1. Emit a survey shown event when a user sees your survey
  2. Emit a survey sent event as a user answers questions, making sure the final event carries every answer collected so far

Step 1: Track impressions

While not required, we recommend emitting survey shown events when a user sees your survey. This enables two things:

  1. Accuracy when viewing all metrics in Surveys
  2. Heads-up messages within LLM traces that indicate a user saw a survey, but did not respond
LLM trace survey impression with no response

survey shown events must have the following properties:

PropertyDescription
$survey_idYour survey ID
$ai_trace_idYour generated trace ID

Note: we do not yet support an easy way to check whether a user has responded to a given survey/trace combination. Because of this, without your own persistent tracking, you may end up with duplicate survey shown events.

Duplicate events will not impact your ability to view responses per trace, but will skew impression & response rate metrics on your Survey overview.

Step 2: Collect responses

For a multi-question survey, send one survey sent event per question as answers come in, and give every event the same $survey_submission_id. Mark the last event with $survey_completed: true.

Important: PostHog displays the completed event as the response for a submission, so that final event must include every answer collected so far, not just the current question's. If an earlier question's $survey_response_{questionId} property is missing from the completed event, that answer won't show up in the response or the question breakdown. The example below shows the pattern.

survey sent events may have the following properties (* = required):

PropertyDescription
$survey_id *Your survey ID
$survey_response_{questionId} *A question's response value, where {questionId} is that question's ID. Include one property per answered question. On the completed event, include every response collected in the submission.
$ai_trace_id *ID for the trace corresponding to this survey
$survey_submission_idA unique ID you generate to link a submission's events together. Reuse the same value across every event in the submission.
$survey_completedBoolean for whether this is the final event in the submission. The completed event is the one PostHog displays, so it must carry every answer.

To get survey question IDs, you have two options:

  1. Go to Surveys, find your survey, and check the Overview tab. This will show the full survey object, including each question's ID.
  2. Call the PostHog SDK's getSurveys method to retrieve your survey, then extract the question IDs from the response.

To learn more about the properties available for survey events, or how to use the getSurveys method, see Implementing custom surveys.

Example

An example sequence for a thumbs up/down survey with a followup may look like this:

typescript
const traceId = 'your-generated-trace-id'
const surveyId = 'your-survey-id'
// (Optional) Track when the survey is shown to the user
posthog.capture('survey shown', {
$survey_id: surveyId,
$ai_trace_id: traceId,
})
// Generate a unique ID to link `survey sent` events into a single user feedback event
const submissionId = crypto.randomUUID()
// User clicked "thumbs down"
posthog.capture('survey sent', {
$survey_id: surveyId,
[`$survey_response_${firstQuestionId}`]: 2, // 1 = thumbs up, 2 = thumbs down
$ai_trace_id: traceId,
$survey_submission_id: submissionId,
$survey_completed: false,
})
// User submitted follow-up text after the "thumbs down" response.
// This is the completed event, so it re-sends the thumbs response
// alongside the follow-up text, so the thumbs rating still shows.
posthog.capture('survey sent', {
$survey_id: surveyId,
[`$survey_response_${firstQuestionId}`]: 2, // re-send the thumbs response
[`$survey_response_${secondQuestionId}`]: 'the AI hallucinated hedgehogs everywhere',
$ai_trace_id: traceId,
$survey_submission_id: submissionId, // must match the previous event's $survey_submission_id
$survey_completed: true,
})

Still have questions?

Was this page useful?