What the Plugin Does
SurveyKiln adds two reusable elements to your Bubble app. No configuration, no external accounts, no code.
A full drag-and-drop survey editor. Users create questions, add conditional logic, and set the look and feel. The output is saved to your Bubble database.
Renders a completed survey as a fill-out form with validation, multi-page navigation, and a submit button. Responses are saved back to your database.
Your data never leaves your Bubble app. Survey definitions are stored as JSON in your database. Responses are stored as JSON in your database. SurveyKiln stores nothing.
27 Question Types
Installation
Installing SurveyKiln takes about 60 seconds.
Open the Plugins tab in your Bubble editor
Click Plugins in the left sidebar of your Bubble editor.
Search for SurveyKiln
Click Add plugins, search for SurveyKiln, click Install, then Done.
You're done — no API keys needed
SurveyKiln is fully client-side. No credentials, no external accounts. The SurveyKiln Builder and SurveyKiln Form elements now appear in your element picker.
Quick Start — 5 Minutes
The absolute minimum to get a working survey builder and a form in your app.
Part A — Let a user create a survey
Create a new page called survey-builder.
Drag the SurveyKiln Builder element onto the page. Set width to 100% and height to at least 800px.
Add a workflow in the Workflow tab:
Preview the page. Build a survey and click Save — it will be stored in your database.
Part B — Show the form to a respondent
Create a new page called take-survey. Set its Data type to Survey.
Drag the SurveyKiln Form element onto the page (at least 600px wide × 600px tall).
In the Form's Properties, set Survey JSON to: Current Page Survey's json_content
Add a workflow:
Done. Navigate to this page with a valid survey — the form renders automatically.
The Builder Element
Drag SurveyKiln Builder onto any page where your users should be able to create or edit surveys.
Minimum size: 900px wide × 700px tall. Set an explicit pixel height — "fit to content" will not work.
Properties
| Property | Type | Default | What it does |
|---|---|---|---|
| Survey JSON | Text | empty | Load an existing survey for editing. Pass the json_content field from your database. Leave empty to start a blank survey. |
| Show Save Button | Yes/No | Yes | Show or hide the Save button at the top of the builder. |
| Show Publish Button | Yes/No | Yes | Show or hide the Publish button at the top of the builder. |
| Primary Color | Color | #0066FF |
Accent color for buttons, active states, and interactive elements throughout the builder. |
Exposed States
States are data the element exposes to your Bubble app. Use them in conditions, text elements, or pass them to actions.
| State | Type | What it contains |
|---|---|---|
| survey_json | Text | The full survey definition as a JSON string. Updates with every change. Save this to your database. |
| is_dirty | Yes/No | yes when there are unsaved changes. Use this to show a "you have unsaved changes" warning. |
| question_count | Number | Total number of questions in the current survey. |
| page_count | Number | Total number of pages in the current survey. |
Events
| Event | When it fires |
|---|---|
| Survey Saved | The user clicks Save. Use this to write survey_json to your database. |
| Survey Published | The user clicks Publish. Use this to mark the survey as live in your database. |
| Survey Changed | Any time the user makes an edit (debounced). Fires often — use sparingly. |
Most common workflow — save a survey:
The Form Element
Drag SurveyKiln Form onto any page where respondents should fill out and submit surveys.
Minimum size: 600px wide × 500px tall. The form is internally scrollable.
Properties
| Property | Type | Default | What it does |
|---|---|---|---|
| Survey JSON Required | Text | — | The survey to render. Pass json_content from your database. The form will not display without this. |
| Read Only | Yes/No | No | Set to Yes to show a completed response without allowing edits. |
| Initial Answers | Text | empty | Pre-fill the form with answers from a saved response. Pass the response_data JSON. |
| Primary Color | Color | from survey | Override the survey's built-in color to match your app's branding. |
Exposed States
| State | Type | What it contains |
|---|---|---|
| response_json | Text | The respondent's answers as JSON. Populated after submission. Save this to your database. |
| is_complete | Yes/No | yes after the form has been successfully submitted. |
| current_page | Number | Current page number (starts at 1). Use to display "Page 2 of 5". |
| total_pages | Number | Total number of pages in the survey. |
| progress_percent | Number | A number from 0–100. Use to drive a progress bar element. |
Events
| Event | When it fires |
|---|---|
| Form Completed | The respondent clicks Submit and passes validation. Use this to save the response to your database. |
| Page Changed | The respondent navigates to a different page. Use this to update a progress bar or page counter. |
Most common workflow — save a response:
Workflow Actions
Use these to control the Builder and Form from your own workflows. Find them under Element Actions in the workflow editor.
Builder Actions
| Action | Input | What it does |
|---|---|---|
| Set Survey JSON | json (text) |
Load a survey into the builder. The builder switches to editing that survey. |
| Reset Builder | none | Clears the builder and starts a fresh blank survey. |
| Download PDF | none | Generates and downloads a PDF of the survey currently loaded in the builder. |
Form Actions
| Action | Input | What it does |
|---|---|---|
| Set Survey JSON | json (text) |
Load a different survey into the form. Resets all answers. |
| Set Answers | json (text) |
Pre-fill the form with answers from a saved response. |
| Reset Form | none | Clears all answers and returns the respondent to page 1. |
Guide: Build a Survey App
A complete walkthrough for building a survey management system where your users can create and edit surveys.
Step 1 — Set up the database
Create a Survey data type with these fields:
| Field | Type | Notes |
|---|---|---|
| title | Text | A human-readable name for the survey |
| json_content | Text (long) | The full survey definition — use "long text" as this field can be large |
| is_published | Yes/No | Whether the survey is live and accepting responses |
| created_by | User | The user who created it |
| created_at | Date | Set automatically on creation |
Step 2 — Survey list page (/surveys)
Add a Repeating Group showing all surveys for the current user.
Add an Edit button per row that navigates to /survey-builder with the survey's ID in the URL.
Add a Create New Survey button that navigates to /survey-builder with no ID.
Step 3 — Builder page (/survey-builder)
Set the page's Data type to Survey.
Add the SurveyKiln Builder element and fill the page. Set Survey JSON to Current Page Survey's json_content — when this is empty (new survey), the builder starts blank automatically.
Add the save workflow:
Guide: Display a Form to Respondents
Step 1 — Set up the database
Create a Response data type:
| Field | Type | Notes |
|---|---|---|
| survey | Survey | Which survey this response belongs to |
| response_data | Text (long) | The raw JSON response from the form |
| submitted_at | Date | When it was submitted |
| respondent | User | Who submitted it (optional — leave blank for anonymous) |
Step 2 — Take survey page (/survey)
Set the page's Data type to Survey.
Drag the SurveyKiln Form element onto the page (600–800px wide, 600px+ tall). Set Survey JSON to Current Page Survey's json_content.
Add a workflow:
Step 3 — Link users to the form
In a button's Go to page action, select the survey page and set Data to send to the Survey record you want to display.
Guide: View a Submitted Response
Display what a respondent previously submitted in read-only mode.
View response page (/response)
Set the page's Data type to Response.
Drag the SurveyKiln Form element onto the page and set these three properties:
The form renders in read-only mode showing exactly what the respondent submitted. No editing is possible.
Advanced: PDF Download
Generate a downloadable PDF of any survey directly from the builder or from a saved JSON string.
Download from the builder page
Download from a list or detail page
If you want a PDF button without showing the builder, add a hidden Builder element to the page, then load the survey into it before triggering the download:
Advanced: Pre-Fill Answers
Let users revisit and update a previous response, or show a partially completed form.
Via element properties
Set Initial Answers on the Form element to the response_data from a previously saved Response record. All prior answers will be filled in automatically.
Via a workflow action
Advanced: Custom Branding
Every survey has a built-in Primary Color set by the creator. The form uses that color for buttons, progress bars, and selection highlights.
Override the color for all forms site-wide
To make all forms match your app's brand regardless of what color the survey creator chose:
Click the SurveyKiln Form element on your canvas.
In the Properties panel, set Primary Color to your brand color (e.g. #7c3aed).
The same approach applies to the Builder — set its Primary Color property to match your app's theme.
Advanced: Multi-Page Forms & Progress Tracking
Creating pages in the builder
In the survey builder, click Add a Page in the Components pane to add a new page. There is no "Page Break" question type — pages are managed from the Components panel.
Show a page counter
Add a text element with this dynamic content:
Drive a progress bar
Add a Shape element as the background bar (e.g. 300px wide × 8px tall, gray fill).
Add a second Shape on top as the fill layer. Set its width to:
Database Setup Reference
Recommended data types and fields for a complete survey app.
Survey
| Field | Type | Description |
|---|---|---|
| title | Text | Human-readable survey name |
| json_content | Text (long) | Full survey JSON — the core data field |
| is_published | Yes/No | Whether the survey is accepting responses |
| created_by | User | Creator |
| created_at | Date | Creation timestamp |
| updated_at | Date | Last modified timestamp |
Response
| Field | Type | Description |
|---|---|---|
| survey | Survey | Which survey this belongs to |
| response_data | Text (long) | Full response JSON from SurveyKiln Form's response_json |
| submitted_at | Date | Submission timestamp |
| respondent | User | Who submitted (optional — leave blank for anonymous) |
| respondent_email | Text | Email if collected separately |
Parsing individual answers
Bubble lets you navigate JSON with the :parsed as JSON operator:
Each answer is keyed by the question's ID from the survey definition.
Quick Reference Card
Builder at a glance
Form at a glance
Minimum workflows every app needs
Troubleshooting
The Builder element is blank / not loading
- The Builder needs an explicit height in pixels. "Fit to content" will not work. Use at least 800px.
- Make sure you're on a Bubble plan that allows plugin use.
- Try a hard refresh: Ctrl+Shift+R / Cmd+Shift+R.
The Form element is blank / not loading
- Survey JSON is required. If it's empty or invalid, the form won't render. Confirm you're passing a valid json_content value from your database.
- The Survey record must exist and json_content must not be empty.
- The Form element also needs an explicit height — use at least 500px.
The survey_json state is empty
survey_json only updates after the user makes a change in the builder. If they haven't touched anything, the state may be empty even though a survey is loaded. Use the Survey Saved event instead — it fires with the JSON attached.
Changes are overwritten when I save
This happens when Survey JSON is bound to a live database field that keeps refreshing and reloading the old value. Only set Survey JSON once (on page load) and don't bind it to a data source that auto-refreshes. Use the Set Survey JSON action only when you explicitly want to reload a different survey.
The form submits but response_json is empty
- Read SurveyKiln Form's response_json inside the workflow step that runs after the Form Completed event fires.
- Confirm the workflow trigger is Form Completed — not a button click or page-load event.
The "Download PDF" action does nothing
- Confirm a SurveyKiln Builder element exists on the page (even if hidden). The PDF action requires the builder to be initialized.
- Check your browser's popup blocker — PDF downloads may be blocked for your Bubble app's domain.
The form color doesn't match my brand
Set the Primary Color property on the Form element to your brand color. See Custom Branding.
File uploads — where do files go?
File upload questions store the uploaded file as a base64 data URI inside response_data. The file is embedded directly in the JSON string. For heavy file use in production, contact support for guidance on a custom upload handler.
Still have questions?
Check the help center, explore the live demo, or send us a feature request.