diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/CTASummary.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/CTASummary.tsx index 76dd63b118..e2951b202a 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/CTASummary.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/CTASummary.tsx @@ -1,3 +1,5 @@ +import { InboxIcon } from "lucide-react"; + import { TSurveyQuestionSummaryCta } from "@formbricks/types/surveys"; import { ProgressBar } from "@formbricks/ui/ProgressBar"; @@ -10,12 +12,33 @@ interface CTASummaryProps { export const CTASummary = ({ questionSummary }: CTASummaryProps) => { return ( -
- +
+ +
+ + {`${questionSummary.impressionCount} Impressions`} +
+
+ + {`${questionSummary.clickCount} Clicks`} +
+ {!questionSummary.question.required && ( +
+ + {`${questionSummary.skipCount} Skips`} +
+ )} + + } + />
-

Click-through rate (CTR)

+

CTR

{convertFloatToNDecimal(questionSummary.ctr.percentage, 1)}% @@ -23,7 +46,7 @@ export const CTASummary = ({ questionSummary }: CTASummaryProps) => {

- {questionSummary.ctr.count} {questionSummary.ctr.count === 1 ? "click" : "clicks"} + {questionSummary.ctr.count} {questionSummary.ctr.count === 1 ? "Click" : "Clicks"}

diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/QuestionSummaryHeader.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/QuestionSummaryHeader.tsx index 4c974080fe..12316b7b1d 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/QuestionSummaryHeader.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/QuestionSummaryHeader.tsx @@ -6,9 +6,11 @@ import { TSurveyQuestionSummary } from "@formbricks/types/surveys"; interface HeadProps { questionSummary: TSurveyQuestionSummary; + showResponses?: boolean; + insights?: JSX.Element; } -export const QuestionSummaryHeader = ({ questionSummary }: HeadProps) => { +export const QuestionSummaryHeader = ({ questionSummary, insights, showResponses = true }: HeadProps) => { const questionType = questionTypes.find((type) => type.id === questionSummary.question.type); return ( @@ -23,10 +25,13 @@ export const QuestionSummaryHeader = ({ questionSummary }: HeadProps) => { {questionType && } {questionType ? questionType.label : "Unknown Question Type"} Question
-
- - {`${questionSummary.responseCount} Responses`} -
+ {showResponses && ( +
+ + {`${questionSummary.responseCount} Responses`} +
+ )} + {insights} {!questionSummary.question.required && (
Optional
)} diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryDropOffs.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryDropOffs.tsx index 76c2c94636..959eb7cb46 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryDropOffs.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryDropOffs.tsx @@ -25,8 +25,8 @@ export const SummaryDropOffs = ({ dropOff }: SummaryDropOffsProps) => {
-
Views
-
Drop Offs
+
Impressions
+
Drop-Offs
{dropOff.map((quesDropOff) => (
{
{quesDropOff.ttc > 0 ? (quesDropOff.ttc / 1000).toFixed(2) + "s" : "N/A"}
-
{quesDropOff.views}
+
{quesDropOff.impressions}
- {quesDropOff.dropOffCount} + {quesDropOff.dropOffCount} ({Math.round(quesDropOff.dropOffPercentage)}%)
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryMetadata.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryMetadata.tsx index 748c661190..31fc0edfc9 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryMetadata.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryMetadata.tsx @@ -1,8 +1,7 @@ import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"; import { timeSinceConditionally } from "@formbricks/lib/time"; -import { TSurveySummary } from "@formbricks/types/surveys"; -import { TSurvey } from "@formbricks/types/surveys"; +import { TSurvey, TSurveySummary } from "@formbricks/types/surveys"; import { Button } from "@formbricks/ui/Button"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@formbricks/ui/Tooltip"; @@ -71,7 +70,7 @@ export const SummaryMetadata = ({
- : displayCount} tooltipText="Number of times the survey has been viewed." @@ -89,7 +88,7 @@ export const SummaryMetadata = ({ tooltipText="Number of times the survey has been completed." /> - : dropOffCount} tooltipText="Number of times the survey has been started but not completed." @@ -110,7 +109,7 @@ export const SummaryMetadata = ({ className="w-max self-start" EndIcon={showDropOffs ? ChevronDownIcon : ChevronUpIcon} onClick={() => setShowDropOffs(!showDropOffs)}> - Analyze Drop Offs + Analyze Drop-Offs
diff --git a/apps/web/playwright/js.spec.ts b/apps/web/playwright/js.spec.ts index e60c240b61..c85642244e 100644 --- a/apps/web/playwright/js.spec.ts +++ b/apps/web/playwright/js.spec.ts @@ -117,13 +117,13 @@ test.describe("JS Package Test", async () => { // Survey should have 2 Displays await page.waitForTimeout(1000); - await expect(page.getByText("Displays2")).toBeVisible(); + await expect(page.getByText("Impressions2")).toBeVisible(); // Survey should have 1 Response await page.waitForTimeout(1000); await expect(page.getByRole("button", { name: "Responses50%" })).toBeVisible(); await expect(page.getByText("1 Responses", { exact: true }).first()).toBeVisible(); - await expect(page.getByText("Click-through rate (CTR)100%")).toBeVisible(); + await expect(page.getByText("CTR50%")).toBeVisible(); await expect(page.getByText("Somewhat disappointed100%")).toBeVisible(); await expect(page.getByText("Founder100%")).toBeVisible(); await expect(page.getByText("People who believe that PMF").first()).toBeVisible(); diff --git a/packages/lib/response/service.ts b/packages/lib/response/service.ts index 72ec2d78a2..dc09a917ba 100644 --- a/packages/lib/response/service.ts +++ b/packages/lib/response/service.ts @@ -230,7 +230,17 @@ export const createResponse = async (responseInput: TResponseInput): Promise { @@ -546,7 +546,7 @@ export const getSurveySummaryDropOff = ( if (!currQues.required) { if (!response.data[currQues.id]) { - viewsArr[currQuesIdx]++; + impressionsArr[currQuesIdx]++; if (currQuesIdx === survey.questions.length - 1 && !response.finished) { dropOffArr[currQuesIdx]++; @@ -577,11 +577,11 @@ export const getSurveySummaryDropOff = ( (currQues.required && !response.data[currQues.id]) ) { dropOffArr[currQuesIdx]++; - viewsArr[currQuesIdx]++; + impressionsArr[currQuesIdx]++; break; } - viewsArr[currQuesIdx]++; + impressionsArr[currQuesIdx]++; let nextQuesIdx = currQuesIdx + 1; const questionHasCustomLogic = currQues.logic; @@ -598,7 +598,7 @@ export const getSurveySummaryDropOff = ( if (!response.data[survey.questions[nextQuesIdx]?.id] && !response.finished) { dropOffArr[nextQuesIdx]++; - viewsArr[nextQuesIdx]++; + impressionsArr[nextQuesIdx]++; break; } @@ -613,20 +613,22 @@ export const getSurveySummaryDropOff = ( }); if (!survey.welcomeCard.enabled) { - dropOffArr[0] = displayCount - viewsArr[0]; - if (viewsArr[0] > displayCount) dropOffPercentageArr[0] = 0; + dropOffArr[0] = displayCount - impressionsArr[0]; + if (impressionsArr[0] > displayCount) dropOffPercentageArr[0] = 0; dropOffPercentageArr[0] = - viewsArr[0] - displayCount >= 0 ? 0 : ((displayCount - viewsArr[0]) / displayCount) * 100 || 0; + impressionsArr[0] - displayCount >= 0 + ? 0 + : ((displayCount - impressionsArr[0]) / displayCount) * 100 || 0; - viewsArr[0] = displayCount; + impressionsArr[0] = displayCount; } else { - dropOffPercentageArr[0] = (dropOffArr[0] / viewsArr[0]) * 100; + dropOffPercentageArr[0] = (dropOffArr[0] / impressionsArr[0]) * 100; } for (let i = 1; i < survey.questions.length; i++) { - if (viewsArr[i] !== 0) { - dropOffPercentageArr[i] = (dropOffArr[i] / viewsArr[i]) * 100; + if (impressionsArr[i] !== 0) { + dropOffPercentageArr[i] = (dropOffArr[i] / impressionsArr[i]) * 100; } } @@ -635,7 +637,7 @@ export const getSurveySummaryDropOff = ( questionId: question.id, headline: getLocalizedValue(question.headline, "default"), ttc: convertFloatTo2Decimal(totalTtc[question.id]) || 0, - views: viewsArr[index] || 0, + impressions: impressionsArr[index] || 0, dropOffCount: dropOffArr[index] || 0, dropOffPercentage: convertFloatTo2Decimal(dropOffPercentageArr[index]) || 0, }; @@ -683,12 +685,13 @@ const checkForI18n = (response: TResponse, id: string, survey: TSurvey, language export const getQuestionWiseSummary = ( survey: TSurvey, - responses: TResponse[] + responses: TResponse[], + dropOff: TSurveySummary["dropOff"] ): TSurveySummary["summary"] => { const VALUES_LIMIT = 50; let summary: TSurveySummary["summary"] = []; - survey.questions.forEach((question) => { + survey.questions.forEach((question, idx) => { switch (question.type) { case TSurveyQuestionType.OpenText: { let values: TSurveyQuestionSummaryOpenText["samples"] = []; @@ -957,15 +960,18 @@ export const getQuestionWiseSummary = ( }); const totalResponses = data.clicked + data.dismissed; + const impressions = dropOff[idx].impressions; summary.push({ type: question.type, question, + impressionCount: impressions, + clickCount: data.clicked, + skipCount: data.dismissed, responseCount: totalResponses, ctr: { count: data.clicked, - percentage: - totalResponses > 0 ? convertFloatTo2Decimal((data.clicked / totalResponses) * 100) : 0, + percentage: impressions > 0 ? convertFloatTo2Decimal((data.clicked / impressions) * 100) : 0, }, }); break; diff --git a/packages/types/surveys.ts b/packages/types/surveys.ts index 07d94c7ad1..30f42b5ec1 100644 --- a/packages/types/surveys.ts +++ b/packages/types/surveys.ts @@ -679,6 +679,9 @@ export type TSurveyQuestionSummaryNps = z.infer