diff --git a/apps/docs/app/best-practices/contact-form/images/embed.png b/apps/docs/app/best-practices/contact-form/images/embed.png deleted file mode 100644 index 1be2dae3e1..0000000000 Binary files a/apps/docs/app/best-practices/contact-form/images/embed.png and /dev/null differ diff --git a/apps/docs/app/global/variables/images/created-variables.webp b/apps/docs/app/global/variables/images/created-variables.webp new file mode 100644 index 0000000000..4567d91598 Binary files /dev/null and b/apps/docs/app/global/variables/images/created-variables.webp differ diff --git a/apps/docs/app/global/variables/images/input-variables.webp b/apps/docs/app/global/variables/images/input-variables.webp new file mode 100644 index 0000000000..6273bfe5fc Binary files /dev/null and b/apps/docs/app/global/variables/images/input-variables.webp differ diff --git a/apps/docs/app/global/variables/images/logic-with-variables.webp b/apps/docs/app/global/variables/images/logic-with-variables.webp new file mode 100644 index 0000000000..24db41a7e3 Binary files /dev/null and b/apps/docs/app/global/variables/images/logic-with-variables.webp differ diff --git a/apps/docs/app/global/variables/images/variables-card.webp b/apps/docs/app/global/variables/images/variables-card.webp new file mode 100644 index 0000000000..c9f6c781d6 Binary files /dev/null and b/apps/docs/app/global/variables/images/variables-card.webp differ diff --git a/apps/docs/app/global/variables/images/variables-usage.webp b/apps/docs/app/global/variables/images/variables-usage.webp new file mode 100644 index 0000000000..2ff22da6ad Binary files /dev/null and b/apps/docs/app/global/variables/images/variables-usage.webp differ diff --git a/apps/docs/app/global/variables/page.mdx b/apps/docs/app/global/variables/page.mdx new file mode 100644 index 0000000000..686ad37b2a --- /dev/null +++ b/apps/docs/app/global/variables/page.mdx @@ -0,0 +1,89 @@ +import { MdxImage } from "@/components/MdxImage"; + +import CreatedVariables from "./images/created-variables.webp"; +import InputVariables from "./images/input-variables.webp"; +import LogicWithVariables from "./images/logic-with-variables.webp"; +import VariablesCard from "./images/variables-card.webp"; +import VariablesUsage from "./images/variables-usage.webp"; + +export const metadata = { + title: "Variables", + description: "Add variabeles to your surveys to transform your survey into a quiz", +}; + +# Hidden Fields + +Variables are a powerful feature in Formbricks that allows you to keep track of data variables when user fills a form. This feature is especially useful when you want to use your survey as a quiz. + +## Types of Variables + +There are two types of variables you can add to your survey: + +1. **Text**: You can add text variables to your survey to capture text data. +2. **Number**: You can add number variables to your survey to capture number data. + +## How to Add Variables + +1. Edit the survey you want to add variables to & switch to the Questions tab and scroll down to the bottom of the page. You will see a section called **Variables**. + + + +2. Now click on it to add a new variable ID. You can add as many variables as you want. You can also choose the type of variable you want to add along with the default value. + + + + + +## Use case: + +- **Quiz**: You can use variables to create a quiz. For example, you can add a variable `score` and update it every time a user answers a question. You can also use the variable for recall to show the final score to the user. + +- **Personalisation**: You can use variables to store user data and personalise the survey experience. For example, you can add a variable `full_name` and update it every time a user fills in their first name and last name. You can use the variable to personalise the survey experience by addressing the user with their full name. + +## How is it different from Hidden Fields? + +Variables are different from hidden fields in the following ways: + +1. **Setting**: Hidden fields can be set through query parameters or `formbricks.init`, but the variables can only be set either during creation or dynamically by using logic actions. +2. **Updating**: Hidden fields cannot be set again, but the value of variables can be updated while the user fills the survey. +3. **Type**: Hidden fields can only store text data, but variables can store both text and number data. + +## How to use Variables + +1. Once you have added the variables to your survey, you'll be able to access them in the logic editor. You can use the variables to create logic actions and conditions. + + + +2. You can create logic based on the variables and questions in your survey and can update the variables based on the user's response. + + + + + To know more about how to use logic in Formbricks, check out the [Conditional + Logic](/global/conditional-logic). + diff --git a/apps/docs/lib/navigation.ts b/apps/docs/lib/navigation.ts index 066a12c9ce..516b26c48b 100644 --- a/apps/docs/lib/navigation.ts +++ b/apps/docs/lib/navigation.ts @@ -54,6 +54,7 @@ export const navigation: Array = [ title: "Add Image/Video to Question", href: "/global/add-image-or-video-question", }, + { title: "Variables", href: "/global/variables" }, ], }, ], @@ -85,6 +86,7 @@ export const navigation: Array = [ title: "Add Image/Video to Question", href: "/global/add-image-or-video-question", }, + { title: "Variables", href: "/global/variables" }, ], }, ], diff --git a/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils.tsx b/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils.tsx index 639d4cb349..09db904fef 100644 --- a/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils.tsx +++ b/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils.tsx @@ -608,8 +608,10 @@ export const getMatchValueProps = ( options: groupedOptions, }; } else if (selectedVariable?.type === "number") { - const allowedQuestions = questions.filter((question) => - [TSurveyQuestionTypeEnum.Rating, TSurveyQuestionTypeEnum.NPS].includes(question.type) + const allowedQuestions = questions.filter( + (question) => + [TSurveyQuestionTypeEnum.Rating, TSurveyQuestionTypeEnum.NPS].includes(question.type) || + (question.type === TSurveyQuestionTypeEnum.OpenText && question.inputType === "number") ); const questionOptions = allowedQuestions.map((question) => { @@ -945,8 +947,10 @@ export const getActionValueOptions = ( return groupedOptions; } else if (selectedVariable.type === "number") { - const allowedQuestions = questions.filter((question) => - [TSurveyQuestionTypeEnum.Rating, TSurveyQuestionTypeEnum.NPS].includes(question.type) + const allowedQuestions = questions.filter( + (question) => + [TSurveyQuestionTypeEnum.Rating, TSurveyQuestionTypeEnum.NPS].includes(question.type) || + (question.type === TSurveyQuestionTypeEnum.OpenText && question.inputType === "number") ); const questionOptions = allowedQuestions.map((question) => { diff --git a/packages/types/surveys/types.ts b/packages/types/surveys/types.ts index bec8f0c2cf..f48a1f310e 100644 --- a/packages/types/surveys/types.ts +++ b/packages/types/surveys/types.ts @@ -1748,7 +1748,11 @@ const validateConditions = ( }); } else if (variable.type === "number") { const validQuestionTypes = [TSurveyQuestionTypeEnum.Rating, TSurveyQuestionTypeEnum.NPS]; - if (!validQuestionTypes.includes(question.type)) { + if ( + !validQuestionTypes.includes(question.type) && + question.type === TSurveyQuestionTypeEnum.OpenText && + question.inputType !== "number" + ) { issues.push({ code: z.ZodIssueCode.custom, message: `Conditional Logic: Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`, @@ -1985,7 +1989,13 @@ const validateActions = ( const allowedQuestions = [TSurveyQuestionTypeEnum.Rating, TSurveyQuestionTypeEnum.NPS]; const selectedQuestion = survey.questions.find((q) => q.id === action.value.value); - if (!selectedQuestion || !allowedQuestions.includes(selectedQuestion.type)) { + + if ( + !selectedQuestion || + (!allowedQuestions.includes(selectedQuestion.type) && + selectedQuestion.type === TSurveyQuestionTypeEnum.OpenText && + selectedQuestion.inputType !== "number") + ) { return { code: z.ZodIssueCode.custom, message: `Conditional Logic: Invalid question type for number variable in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,