diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/WhenToSendCard.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/WhenToSendCard.tsx
index aab2b5d0d5..c0baf76dbf 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/WhenToSendCard.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/WhenToSendCard.tsx
@@ -40,9 +40,11 @@ export default function WhenToSendCard({
const [isAddEventModalOpen, setAddEventModalOpen] = useState(false);
const [activeIndex, setActiveIndex] = useState(null);
const [actionClasses, setActionClasses] = useState(propActionClasses);
+ const [randomizerToggle, setRandomizerToggle] = useState(localSurvey.displayPercentage ? true : false);
const { isViewer } = getAccessFlags(membershipRole);
const autoClose = localSurvey.autoClose !== null;
+ const delay = localSurvey.delay !== 0;
const addTriggerEvent = useCallback(() => {
const updatedSurvey = { ...localSurvey };
@@ -71,7 +73,7 @@ export default function WhenToSendCard({
setLocalSurvey(updatedSurvey);
};
- const handleCheckMark = () => {
+ const handleAutoCloseToggle = () => {
if (autoClose) {
const updatedSurvey = { ...localSurvey, autoClose: null };
setLocalSurvey(updatedSurvey);
@@ -81,6 +83,27 @@ export default function WhenToSendCard({
}
};
+ const handleDelayToggle = () => {
+ if (delay) {
+ const updatedSurvey = { ...localSurvey, delay: 0 };
+ setLocalSurvey(updatedSurvey);
+ } else {
+ const updatedSurvey = { ...localSurvey, delay: 5 };
+ setLocalSurvey(updatedSurvey);
+ }
+ };
+
+ const handleDisplayPercentageToggle = () => {
+ if (localSurvey.displayPercentage) {
+ const updatedSurvey = { ...localSurvey, displayPercentage: null };
+ setLocalSurvey(updatedSurvey);
+ } else {
+ const updatedSurvey = { ...localSurvey, displayPercentage: 50 };
+ setLocalSurvey(updatedSurvey);
+ }
+ setRandomizerToggle(!randomizerToggle);
+ };
+
const handleInputSeconds = (e: any) => {
let value = parseInt(e.target.value);
@@ -96,6 +119,11 @@ export default function WhenToSendCard({
setLocalSurvey(updatedSurvey);
};
+ const handleRandomizerInput = (e) => {
+ const updatedSurvey = { ...localSurvey, displayPercentage: parseInt(e.target.value) };
+ setLocalSurvey(updatedSurvey);
+ };
+
useEffect(() => {
if (isAddEventModalOpen) return;
if (activeIndex !== null) {
@@ -155,8 +183,9 @@ export default function WhenToSendCard({
-
-
+
+
+
{!isAddEventModalOpen &&
localSurvey.triggers?.map((triggerEventClass, idx) => (
@@ -209,7 +238,14 @@ export default function WhenToSendCard({
-
+
+
-
-
+
@@ -252,6 +287,30 @@ export default function WhenToSendCard({
+
+
+
+
+ Show to {localSurvey.displayPercentage}% of targeted users
+
+
+
+
+
{
+ const randomNum = Math.floor(Math.random() * 100) + 1;
+ return randomNum <= displayPercentage;
+};
+
export const trackAction = async (
name: string,
properties: TJsActionInput["properties"] = {}
@@ -64,6 +69,14 @@ export const trackAction = async (
export const triggerSurvey = async (actionName: string, activeSurveys: TSurvey[]): Promise => {
for (const survey of activeSurveys) {
+ // Check if the survey should be displayed based on displayPercentage
+ if (survey.displayPercentage) {
+ const shouldDisplaySurvey = shouldDisplayBasedOnPercentage(survey.displayPercentage);
+ if (!shouldDisplaySurvey) {
+ logger.debug("Survey display skipped based on displayPercentage.");
+ continue;
+ }
+ }
for (const trigger of survey.triggers) {
if (trigger === actionName) {
logger.debug(`Formbricks: survey ${survey.id} triggered by action "${actionName}"`);
diff --git a/packages/lib/survey/service.ts b/packages/lib/survey/service.ts
index dbee579647..caeb778040 100644
--- a/packages/lib/survey/service.ts
+++ b/packages/lib/survey/service.ts
@@ -41,6 +41,7 @@ export const selectSurvey = {
autoClose: true,
closeOnDate: true,
delay: true,
+ displayPercentage: true,
autoComplete: true,
verifyEmail: true,
redirectUrl: true,
diff --git a/packages/lib/survey/tests/survey.mock.ts b/packages/lib/survey/tests/survey.mock.ts
index d0ed5caedc..07f034440b 100644
--- a/packages/lib/survey/tests/survey.mock.ts
+++ b/packages/lib/survey/tests/survey.mock.ts
@@ -135,6 +135,7 @@ export const mockSurveyOutput: SurveyMock = {
productOverwrites: null,
singleUse: null,
styling: null,
+ displayPercentage: null,
pin: null,
resultShareKey: null,
...baseSurveyProperties,
@@ -157,6 +158,7 @@ export const updateSurveyInput: TSurvey = {
productOverwrites: null,
styling: null,
singleUse: null,
+ displayPercentage: null,
pin: null,
resultShareKey: null,
...commonMockProperties,
diff --git a/packages/types/surveys.ts b/packages/types/surveys.ts
index 8785a4a9e4..32f56c8c60 100644
--- a/packages/types/surveys.ts
+++ b/packages/types/surveys.ts
@@ -435,6 +435,7 @@ export const ZSurvey = z.object({
verifyEmail: ZSurveyVerifyEmail.nullable(),
pin: z.string().nullable().optional(),
resultShareKey: z.string().nullable(),
+ displayPercentage: z.number().min(1).max(100).nullable(),
});
export const ZSurveyInput = z.object({