Creating surveys

To create a new survey, go to the surveys tab in the PostHog app, and click on the New survey button in the top right. This opens the survey wizard where you can choose from popular survey templates, create a survey using PostHog AI, or open the full editor for more control.

After choosing a template, you are brought to a form where you can complete the details of your new survey:

Create a survey

PostHog AI and surveys

PostHog AI, PostHog's AI-powered assistant, can help you create surveys quickly using natural language. PostHog AI understands different question types and can:

  • Generate complete surveys based on your research goals
  • Suggest appropriate question types (freeform text, rating scales, multiple choice, etc.)
  • Help you set up display conditions and targeting
  • Recommend survey templates for common use cases

You can ask PostHog AI things like:

  • "Create an NPS survey for my mobile app users"
  • "Build a product satisfaction survey with rating questions"
  • "Help me create a survey to understand why users churn"
  • "Generate a post-purchase feedback survey"

To get started, click "PostHog AI" in the top right corner of the PostHog app and describe what kind of survey you want to create.

Note: PostHog AI is currently in beta, so you may encounter occasional issues. We appreciate any feedback you can share to help us improve!

Creating a new survey

Here's a breakdown of each field in the form:

Presentation

There are three options for displaying a survey:

  1. Popover: Use PostHog's prebuilt user interfaces to show surveys as a popover in the bottom corner of the screen.

  2. API: Implement your own survey UI and use PostHog to handle display logic, capturing results, and analytics.

  3. Feedback button: Set up a survey based on your own custom button or our prebuilt feedback tab.

  4. Hosted surveys: Create a survey accessible via an external link or embedded in an iframe, hosted by PostHog. Responses are anonymous by default, unless you use the distinct_id query parameter, which enables you to link responses to respondents.

Survey presentation types

Popover, API, and feedback button surveys are considered in-app surveys, meaning they are displayed directly in your application using our SDKs. Hosted surveys are displayed via an external URLs, hosted by PostHog.

Identifying respondents on hosted surveys

In-app surveys automatically link responses to users when you identify users in your app.

Hosted surveys require manual user linking since they're accessed via external URLs. To connect survey responses to specific users, add the distinct_id query parameter to your survey URL:

https://us.posthog.com/external_surveys/your-survey-id?distinct_id=user123

Important: Use the exact same distinct_id value that you pass to posthog.identify() in your application. This ensures survey responses appear in the correct user's profile.

Without the parameter, responses are collected anonymously and cannot be linked to users. With the parameter, responses are attributed to the specified user, enabling you to see survey data alongside other user events and properties.

Adding event properties to hosted survey responses

When directing users to a hosted survey, you can add event properties using URL parameters. These parameters are automatically captured on the survey sent event.

https://us.posthog.com/external_surveys/your-survey-id?order_id=12345

The types for custom properties are automatically inferred with this logic, in this order:

  • Numeric: matches regex /^-?\d+(\.\d+)?$/ (integer or decimal)
  • Boolean: exact strings "true" and "false"
  • String: everything else

Pre-filling survey responses via URL

You can pre-fill survey answers using URL parameters, which is especially useful for creating one-click survey links in emails. This feature works with single choice, multiple choice, and rating questions.

Basic syntax:

https://us.posthog.com/external_surveys/your-survey-id?distinct_id=user123&q0=2&q1=8
  • q{N} = question index (0-based, e.g., q0 for the first question, q1 for the second)
  • Value = choice index (for single/multiple choice) or rating number

Examples:

Single choice question:

# Pre-select the 3rd choice (index 2) for the first question
?distinct_id=user123&q0=2

Rating question:

# Pre-fill a rating of 9 out of 10
?distinct_id=user123&q0=9

Multiple choice question:

# Pre-select choices at index 0 and 2 (use repeated parameters)
?distinct_id=user123&q0=0&q0=2

Multiple questions:

# Pre-fill first question (choice 3) and second question (rating 8)
?distinct_id=user123&q0=3&q1=8

Auto-submit (one-click surveys):

Note: As of posthog-js@1.302.0, the auto_submit URL param, along with the autoSubmitIfComplete and autoSubmitDelay SDK configuration params, have been deprecated.

Survey questions that are pre-filled will be skipped (not shown to the user) if they are set to "Automatically submit on selection". Additionally, if partial responses are enabled for your survey, these responses will be recorded automatically on page load.

Here's how it works:

  • User clicks link to open survey page
  • Starting at the first question, we automatically advance through questions which are both prefilled and set to automatically submit on selection
  • If partial responses are enabled for your survey, responses are immediately stored for the questions we skipped
  • We always start the survey at the first non-prefilled question, regardless of whether some questions in the middle are pre-filled

Additional notes:

  • If all questions are pre-filled, the user will only see a confirmation message ("Thanks! Your response was recorded")
  • If some questions in the middle of your survey are pre-filled, regardless of whether the question is set to auto-submit on selection, the user will still see the pre-selected response, and may change it

Example: one-click NPS with optional follow-up Say you want to send an email with a "one-click" NPS survey that includes an optional follow-up question.

Create your survey with the following configuration:

  1. Create your first question as a Rating question, with "Automatically submit on selection" enabled
  2. Create a second question as Freeform text
  3. Ensure partial responses are enabled (Completion conditions > Response collection > Any question)

Now you can send your survey link with the NPS question pre-filled, like this:

# pre-fill the first question (index 0) with the value 8
{survey_url}?q0=8

Important notes:

  • Question indices are 0-based (first question is q0, second is q1, etc.)
  • Choice indices are also 0-based (first choice is 0, second is 1, etc.)
  • Invalid indices are silently ignored
  • Pre-filling only works with choice and rating questions (not open text)

Embedding hosted surveys in iframes

You can embed hosted surveys directly on a page using an iframe. This is useful if you're working in a no-code site builder, or otherwise want to display a survey inline without creating an API survey.

To create an embedded survey:

  1. Create a hosted survey - select Hosted Survey as the presentation type
  2. Enable Allow embedding in iframes in the survey settings
  3. Save and launch your survey
  4. On the overview page, click Copy embed code to get the HTML snippet
  5. Paste the code snippet wherever you like - done!

Here's an example with Framer:

Notes:

  • Person identification: If the PostHog SDK is enabled on your site, the default embed code will automatically attach the Person's distinct ID (via window.posthog.get_distinct_id()) to all embedded survey responses. Otherwise, the responses will be anonymous.
  • URL pre-fill: URL pre-filling is supported with embedded surveys, you'll just need to update your embed code to include the pre-fill query params.
  • Embed customization: The default embed code provides automatic height adjustment and minimal styling. For more control, you can create your own iframe using the hosted survey's URL + ?embed=true. Example:
https://us.posthog.com/external_surveys/my-survey-id/?embed=true

Steps

Steps is where you set up your question(s), label, choice(s), description, button text, and confirmation message. You must subscribe to surveys to add multiple questions.

You can also add conditional logic to display certain questions.

Tip: The description supports HTML, so you can do things like add images with an <img> tag.

PostHog supports multiple question types which are all available for both popover and API display modes.

TypePreview
Freeform textOpen text survey
Link/NotificationLink survey
Rating emojiEmoji rating survey
Rating - numberNumber rating survey
Single choice selectSingle choice select survey
Multiple choice selectMultiple choice survey

Customization

Customization enables you to change the look, feel, and timing of your popover survey:

  • The color of the background, border, and buttons.
  • The position of the popover at the bottom of the screen.
  • The placeholder text.
  • The visibility of the PostHog branding.
  • Whether to shuffle the order of the choices and questions.
  • The delay (in seconds) before the survey appears on the page.
  • Whether the confirmation message auto disappears after 5 seconds.
Delay survey customization

For hosted surveys, you can only customize colors and placeholders.

Display conditions

Display conditions are not available for hosted surveys. Any user who visits the link is shown the survey, as long as it is launched and still collecting responses.

This specifies the conditions a user must meet to be shown an in-app survey. A user must meet ALL the conditions to be eligible.

You can display your survey to specific users based on:

  • Linked feature flag: Whether a user has a specific feature flag enabled. For example, if you're rolling out a new landing page using a feature flag new-landing-page, you can gather feedback only from users who have that flag enabled. This is also a way to show surveys to cohorts (but it must be a non-behavioral one).

  • URL targeting: Show when URL either contains a string, exactly matches a string, or matches a regex. When using exact matching, trailing slashes are stripped before comparison. The URL targeting is evaluated against window.location.href.

  • Device types targeting: Show when the device type either contains a string, exactly matches a string or matches a regex. The device type targeting is evaluated by parsing the userAgent on the client-side, possible values are: Desktop, Mobile, Tablet, Console, and Wearable. You can also target device types using Person and group properties (Latest or Initial Device type), but these properties aren't immediately available on the first page load for unidentified persons. Only available from posthog-js version 1.214.0 forward.

  • Selector matches: Whether a specific element exists or appears on the page with the specified class name or ID. For example, you can display a survey with #my-button or .my-button selector. This is useful for showing a survey after a user action.

  • Wait period: Hide surveys from users who have seen any survey in the last X days. A user who completes a survey is never shown the same survey again, even if no wait period is set (but there are exceptions to this rule).

  • Person and group properties: If you are capturing identified events, you can display a survey to users who have specific person or group properties. For example, you can target a survey to users who have a property is_paying=true. This also includes a percentage rollout option. The person and group properties are evaluated with internal feature flags.

  • User sends events: Display a survey to users who have sent a specific event during their session.

Display conditions

Completion conditions

This enables you to stop your survey once you receive a specific number of responses. Note that because it takes time for PostHog to process responses, this is a rough guideline. Your survey might receive slightly more responses than you set. The completion conditions properties are evaluated with internal feature flags.

Repeating surveys

By default, surveys are shown once to each user until they either dismiss it or complete it. After that, they won't see the survey again. However, there are a few exceptions.

Event-triggered surveys

For surveys triggered by a specific event, you can configure the survey to repeat if the event is sent again. If you select the option Every time the event is sent, the survey is shown again for each event.

If you want to trigger a survey on a specific event, but only show it once per user, select the Just once option.

Survey triggered by events under display conditions

Completion conditions

Under completion conditions, there are two scheduling options that make a survey show again after a user has already answered or dismissed it:

  • Repeat on a schedule
  • Every time the display conditions are met

Repeat on a schedule

Repeating on a schedule is useful for collecting feedback from the same users on a regular basis, like a quarterly NPS survey or a monthly satisfaction check-in. You configure it with two values: how many times to show the survey, and how many days each cycle lasts. For example, show up to 3 times total, once every 30 days.

In the guided survey creation flow, this is the "How often should this survey show?" step: picking Every month, Every 3 months, or Every year sets the cycle length to 30, 90, or 365 days, and "Show up to N times in total" sets the number of repetitions. The full editor lets you set a custom number of days.

Repeating surveys

When you launch the survey, PostHog splits its lifetime into back-to-back windows called iterations, counted from the survey's launch date. In the example above, that's 3 iterations of 30 days each. Every user shares the same iteration calendar:

  • Within an iteration, eligible users keep seeing the survey until they submit or dismiss it. After that, they aren't shown it again during that iteration.
  • When the next iteration starts, everyone becomes eligible again, including users who responded in the previous one. Each user can respond at most once per iteration.

For example, a survey launched on January 1st, set to show up to 3 times, once every 30 days:

IterationWindow (approximate)What happens
1Jan 1 to Jan 30All targeted users are eligible. Once a user submits or dismisses, they're done for this iteration
2Jan 31 to Mar 1Everyone becomes eligible again, including users who responded in iteration 1
3Mar 2 to Mar 31Everyone becomes eligible again. This is the last iteration

Each response includes the $survey_iteration and $survey_iteration_start_date properties, so you can filter or break down results by iteration. This is handy for tracking how scores change over time, like comparing this quarter's NPS to last quarter's.

A few things to keep in mind:

  • The schedule is anchored to the survey's launch date, not to each user's last response. All users move to the next iteration at the same time. This means the gap an individual user experiences between showings can be much shorter than the repeat interval: a user who responds near the end of an iteration becomes eligible again as soon as the next one starts. In the example above, a user who responds on January 29 can see the survey again on January 31, just two days later.
  • Dismissing counts as answering. A user who dismisses the survey won't see it again until the next iteration, same as a user who submitted a response.
  • Iteration boundaries are approximate. PostHog processes iteration changes a few times per day, so a new iteration can begin a few hours after its scheduled start.
  • Users must still match your display conditions each time the survey becomes eligible to show again.

If you want per-user spacing instead, like "don't show this user a survey more than once every 30 days, no matter the calendar," use Every time the display conditions are met combined with the Wait period display condition. Note that the wait period applies across all your surveys: it hides the survey from users who have seen any survey within that period, not just this one.

Every time the display conditions are met

For this option, the survey is shown again every time the display conditions are met.

The main use case for this is for Feedback button surveys. This enables the survey to show up every time the user clicks the feedback button.

This can also be combined with the Wait period display condition. If you select this option and set a wait period of 30 days, the survey is only shown again if the user hasn't seen any surveys in the last 30 days. This is useful for getting regular feature feedback on a per-user cadence.

Launching your survey

Once you've set up your survey, click "Save as draft" to save your survey. This enables you to review any changes before launching. Then, when you're ready to launch, click the "Launch" button.

If you've created a popover survey, your survey will begin showing immediately to users matching your display conditions.

If you've created an API survey, you'll need to add your custom survey code before launching.

When you launch a hosted survey, you'll get a link you can share with your users. You can also copy it by clicking Copy URL.

Copy survey link

How PostHog handles partial survey responses

You can enable partial responses in the "Completion conditions" section of the survey. This option is enabled by default for all new surveys. Please note that partial responses require posthog-js version 1.240.0 or higher and are currently only supported in posthog-js library.

If partial responses are disabled, PostHog sends a single survey sent event. This event is triggered once the user answers the last question of the survey. It contains all the user's responses. The $survey_completed property in this event will be true.

When partial responses are enabled (default behavior for new surveys): If partial responses are enabled, PostHog tracks user progress as follows:

  1. Initial Response: The first survey sent event is triggered as soon as the user answers at least one question. This initial event includes the answer(s) provided up to that point. The $survey_completed property in this event will be false.
  2. Subsequent Responses: For each additional question the user answers, another survey sent event is captured. Each of these events will contain all responses submitted by the user for that survey instance up to that point, and $survey_completed will remain false.
  3. Full Completion: When the user fully completes and submits the survey, a final survey sent event is sent. This event will again include all their answers, and the $survey_completed property will now be true.

The $survey_submission_id: All survey sent events triggered during a single user's attempt to complete a survey (whether partial or complete) share the same unique $survey_submission_id.

Billing for partial responses: We charge based on unique survey submissions, not individual survey sent events. Therefore, you are charged only once per unique $survey_submission_id. For example, if your survey has 5 questions and a user answers 3 of them (triggering multiple survey sent events with $survey_completed: false), you will still be charged for only one survey response, as all those events will share the same $survey_submission_id.

The survey abandoned event: When a user answers at least one question but navigates away or closes the page before completing all questions, PostHog automatically captures a survey abandoned event. This event includes the $survey_id property identifying the survey. It's different from survey dismissed, which fires when a user explicitly closes the survey without answering.

You can use the survey abandoned event in insights to measure drop-off rates and identify which surveys users start but don't finish.

Community questions

Was this page useful?

Questions about this page? or post a community question.