Skip to content

Completion Behavior

Completion behavior controls what respondents see or where they go after the form is submitted. Use root survey properties for the normal completion flow and triggers when the form should finish early.

Use showCompletePage and completedHtml for the default post-submit screen.

{
"showCompletePage": true,
"completedHtml": "<h3>Thanks, {firstName}.</h3><p>We received your request for {projectName}.</p>"
}

completedHtml is localizable and supports dynamic text placeholders.

Use completedHtmlOnCondition when different respondents should see different completion messages. The first matching item can override completedHtml.

{
"completedHtml": "<h3>Thanks for your response.</h3>",
"completedHtmlOnCondition": [
{
"expression": "{eligible} = 'No'",
"html": "<h3>Thanks for your time.</h3><p>You do not meet the current eligibility criteria.</p>"
},
{
"expression": "{scorePercent} >= 80",
"html": "<h3>Passed</h3><p>Your score was {score}/{totalScore}.</p>"
}
]
}

Use navigateToUrl to redirect all respondents after completion. Use navigateToUrlOnCondition for conditional redirects.

{
"navigateToUrl": "https://example.com/thanks",
"navigateToUrlOnCondition": [
{
"expression": "{eligible} = 'No'",
"url": "https://example.com/not-eligible"
},
{
"expression": "{plan} = 'enterprise'",
"url": "https://example.com/sales"
}
]
}

Use a root complete trigger when a respondent should finish before reaching the last page, such as a screen-out flow.

{
"triggers": [
{
"type": "complete",
"expression": "{eligible} = 'No'"
}
]
}

Prefer visibleIf and requiredIf for local branching. Use a complete trigger when the desired action is to submit or end the survey.

Use showPreviewBeforeComplete to show an answer preview before final submission. Use previewMode to choose whether the preview includes all questions or only answered questions. Customize button captions with previewText, editText, and completeText where needed.

{
"showPreviewBeforeComplete": true,
"previewMode": "answeredQuestions",
"previewText": "Review answers",
"editText": "Edit answers",
"completeText": "Submit"
}

Formspace sets these variables when a response is submitted:

Variable Value
{responseNumber} The response’s number within the form, such as 42.
{score} Points scored. Quizzes only.
{totalScore} Points available. {maxScore} is the same value. Quizzes only.
{scorePercent} The score as a percentage from 0 to 100. Quizzes only.

In text, {correctAnswers} and {incorrectAnswers} also show a quiz’s answer counts.

The variables are empty while the respondent fills in the form. They have values on the thank-you page and in redirect URLs, in the dashboard’s response view and editor, in My Submissions, and in response PDFs. Use them in completion HTML, redirect URLs, HTML questions, conditions, and calculated values:

{
"calculatedValues": [{ "name": "reference", "expression": "'REF-' + {responseNumber}" }],
"elements": [
{
"type": "html",
"name": "referenceBlock",
"visibleIf": "{responseNumber} notempty",
"html": "<p>Reference: {reference}</p>"
}
],
"completedHtml": "<h3>Thanks! Your reference is {reference}.</h3>",
"navigateToUrl": "https://example.com/thanks?ref={responseNumber}"
}

To keep a value made from these variables with the response, use an expression question. It is saved with the response’s number and score, so it is a column in the submissions table and exports, and webhooks and integrations receive it:

{
"completedHtml": "<h3>Your score: {score}/{totalScore} ({scorePercent}%)</h3>",
"elements": [
{
"type": "expression",
"name": "result",
"title": "Result",
"visibleIf": "{scorePercent} notempty",
"expression": "iif({scorePercent} >= 70, 'Pass', 'Fail')"
}
]
}
  • Show content that uses these variables with visibleIf: "{responseNumber} notempty" (or {scorePercent} notempty), so it appears only once the response is submitted. A placeholder without a value shows as written, such as {responseNumber}.
  • Everything the form makes from these variables (calculated values, expression questions, setValueIf/setValueExpression/resetValueIf rules and setvalue/copyvalue/runexpression triggers) is worked out from the submitted answers once, when the response is saved, and the thank-you page and redirect URL show the same values. Viewing or editing a saved response, and its PDF, show what was saved without running those rules and triggers again.
  • A calculated value with includeIntoResult is also saved, and sent to webhooks and integrations, but has no column in the submissions table or exports.
  • Don’t use these variables in validators or requiredIf: the respondent can’t satisfy them before submitting.
  • Questions and calculated values can’t use the name responseNumber, and quizzes can’t use the quiz variable names either.
  • Submitted values under these names, such as from a prefilled link, are ignored when the response is saved. Forms that aren’t quizzes keep values named like the quiz variables, such as a prefilled score.
  • Response numbers count up within each form, so showing one tells respondents roughly how many responses the form has had.

On forms that respondents sign in to (email verified, organization or invite-only access), Formspace sets these variables as soon as the respondent has signed in:

Variable Value
{respondentEmail} The respondent’s verified email address.
{respondentName} The name from the respondent’s Microsoft or Google sign-in. Empty for email code sign-ins.

Both are empty for anonymous respondents. Use them in default values, conditions, HTML, calculated values and completion HTML:

{
"completedHtml": "<h3>Thanks, {respondentName}!</h3>",
"elements": [
{
"type": "text",
"name": "email",
"title": "Email",
"inputType": "email",
"defaultValueExpression": "{respondentEmail}",
"enableIf": "{respondentEmail} empty"
},
{ "type": "text", "name": "name", "title": "Name", "defaultValueExpression": "{respondentName}" },
{
"type": "text",
"name": "phone",
"title": "Phone",
"visibleIf": "{respondentEmail} empty"
}
]
}
  • defaultValueExpression fills in an empty answer only: saved progress, prefilled links and anything the respondent already typed are kept.
  • enableIf: "{respondentEmail} empty" makes the email read-only once it’s known, and leaves it editable on anonymous forms. It doesn’t stop a respondent sending a different value, but every response also records the verified email itself, in the submissions table’s Email column.
  • Empty variables show as nothing in text, so Thanks, {respondentName}! reads Thanks, ! when the name isn’t known. Use iif({respondentName} notempty, ...) or a visibleIf condition to word it differently.
  • Rules and triggers that react to these variables, such as setValueIf, a runexpression trigger or a trigger on a calculated value made from them, run once, when the form first gets them. Saving, grading, resuming or showing the response doesn’t run them again, and quizzes grade the questions the respondent’s details showed them.
  • Internal-use questions aren’t in the respondent’s form, so their default values never apply (the designer hides them), and setValueIf and setValueExpression run as the team edits the response but can’t be relied on when it’s submitted. To record the respondent’s details in an internal field, use an internal Expression question, such as { "type": "expression", "name": "submittedBy", "expression": "{respondentEmail}", "formspaceInternal": true }. It’s worked out as the response is submitted and saved with it.
  • Resumed progress keeps its answers, and questions without one get their defaults, so a question added since the progress was saved is filled in. A default the respondent cleared is filled in again.
  • The dashboard, My Submissions and response PDFs show a response with the email and name it was submitted with. The builder’s Preview uses your own email and name, unless respondents stay anonymous.
  • Questions and calculated values can’t use the names respondentEmail and respondentName, and submitted values under these names are ignored.
  • Use Dynamic Text and Answer Piping when completion copy should include submitted answers.
  • Use Localizable Strings for multilingual completion messages and button labels.
  • Use Trigger for early completion rules.
  • Avoid redirects when the respondent should see Formspace’s confirmation, saved-state, or quiz result page.