mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-21 21:50:39 -06:00
Compare commits
4 Commits
docs-quota
...
feat-redir
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a707c48d5 | ||
|
|
b48673a863 | ||
|
|
c0c35298a7 | ||
|
|
fa327736f2 |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
70
apps/docs/app/link-surveys/redirect-on-completion/page.mdx
Normal file
70
apps/docs/app/link-surveys/redirect-on-completion/page.mdx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { MdxImage } from "@/components/MdxImage";
|
||||
|
||||
import StepOne from "../pin-protected-surveys/images/StepOne.webp";
|
||||
import RedirectUrlExample from "./images/RedirectUrlExample.webp";
|
||||
import StepTwo from "./images/StepTwo.webp";
|
||||
|
||||
export const metadata = {
|
||||
title: "Redirect on survey completion",
|
||||
description:
|
||||
"Automatically redirect users to a specified URL upon completing a survey. Enhance user flow and engagement by seamlessly guiding respondents to the next step.",
|
||||
};
|
||||
|
||||
# Redirect on survey completion
|
||||
|
||||
Automatically redirect users to a specified URL upon completing a survey. Enhance user flow and engagement by seamlessly guiding respondents to the next step. There are two ways of achieving it:
|
||||
|
||||
1. Static Url Redirection
|
||||
2. Dynamic Url Redirection
|
||||
|
||||
## **Staic Url Redirection**
|
||||
|
||||
This is usefull when you want to redirect all the survey respondents to the same url.
|
||||
|
||||
### **Steps to Set Up Staic Url Redirection**
|
||||
|
||||
1. **Open Settings in Survey Editor**: Navigate to your survey in the survey editor where you wish to enable redirection (make sure its a link survey)
|
||||
2. **Select Response Options**: Find and select **`Response Options`** to access settings related to survey responses.
|
||||
<MdxImage
|
||||
src={StepOne}
|
||||
alt="Choose Response option"
|
||||
quality="100"
|
||||
className="max-w-full rounded-lg sm:max-w-3xl "
|
||||
/>
|
||||
3. **Enable Redirect on completion**: Find the option for **`Redirect on completion`** and activate it. You will be prompted
|
||||
to enter a url to which respondents would be redirected to.
|
||||
<MdxImage
|
||||
src={StepTwo}
|
||||
alt="Choose Redirect on Completion"
|
||||
quality="100"
|
||||
className="max-w-full rounded-lg sm:max-w-3xl "
|
||||
/>
|
||||
|
||||
## **Dynamic Url Redirection**
|
||||
|
||||
This is usefull when you want to redirect different respondents to different Urls
|
||||
|
||||
### **Steps to Set Up Dynamic Url Redirection**
|
||||
|
||||
1. **Append redirectUrl param to survey link**: Before sending the survey link to the respondent, append **`redirectUrl=<you-redirect-url-here>`** to the survey link
|
||||
|
||||
<MdxImage
|
||||
src={RedirectUrlExample}
|
||||
alt="Redirect Url example"
|
||||
quality="100"
|
||||
className="max-w-full rounded-lg sm:max-w-3xl "
|
||||
/>
|
||||
|
||||
<Note>
|
||||
In cases where both static and dynamic redirect URLs are configured, dynamic redirect URL would be given a
|
||||
higher priority
|
||||
</Note>{" "}
|
||||
|
||||
### **Benefits of Redirect on completion**
|
||||
|
||||
- **Increased Engagement**: Direct users to relevant content or next actions, such as additional surveys, or promotional offers.
|
||||
- **Customization and Personalization**: Use dynamic redirection to provide personalized experiences based on user responses, enhancing relevance and engagement.
|
||||
|
||||
## **Conclusion**
|
||||
|
||||
Implementing redirect on survey completion is a powerful feature that enhances user flow and engagement by guiding respondents to the next step seamlessly. Whether using static or dynamic URL redirection, this capability provides numerous benefits, including improved user experience, increased engagement, and enhanced tracking and analytics. By integrating redirection into your surveys, you can automate workflows, personalize user journeys, and ultimately achieve better outcomes from your survey initiatives.
|
||||
@@ -91,6 +91,7 @@ export const navigation: Array<NavGroup> = [
|
||||
{ title: "Verify Email before Survey", href: "/link-surveys/verify-email-before-survey" },
|
||||
{ title: "PIN Protected Surveys", href: "/link-surveys/pin-protected-surveys" },
|
||||
{ title: "Partial Submissions", href: "/global/partial-submissions" },
|
||||
{ title: "Redirect on Completion", href: "/link-surveys/redirect-on-completion" },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useMemo, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
import { MatchType, testURLmatch } from "@formbricks/lib/utils/testUrlMatch";
|
||||
import { MatchType, testURLmatch } from "@formbricks/lib/utils/url";
|
||||
import { TActionClass, TActionClassInput, TActionClassNoCodeConfig } from "@formbricks/types/actionClasses";
|
||||
import { TSurvey } from "@formbricks/types/surveys";
|
||||
import { CssSelector, InnerHtmlSelector, PageUrlSelector } from "@formbricks/ui/Actions";
|
||||
|
||||
@@ -4,6 +4,7 @@ import { toast } from "react-hot-toast";
|
||||
|
||||
import { extractLanguageCodes, getLocalizedValue } from "@formbricks/lib/i18n/utils";
|
||||
import { checkForEmptyFallBackValue } from "@formbricks/lib/utils/recall";
|
||||
import { isValidUrl } from "@formbricks/lib/utils/url";
|
||||
import { ZSegmentFilters } from "@formbricks/types/segment";
|
||||
import {
|
||||
TI18nString,
|
||||
@@ -189,15 +190,6 @@ export const isCardValid = (
|
||||
);
|
||||
};
|
||||
|
||||
export const isValidUrl = (string: string): boolean => {
|
||||
try {
|
||||
new URL(string);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Function to validate question ID and Hidden field Id
|
||||
export const validateId = (
|
||||
type: "Hidden field" | "Question",
|
||||
@@ -227,6 +219,7 @@ export const validateId = (
|
||||
"hidden",
|
||||
"verifiedEmail",
|
||||
"multiLanguage",
|
||||
"redirectUrl",
|
||||
];
|
||||
if (forbiddenIds.includes(field)) {
|
||||
toast.error(`${type} Id not allowed.`);
|
||||
@@ -408,11 +401,7 @@ export const isSurveyValid = (
|
||||
}
|
||||
|
||||
// Checking the validity of redirection URLs to ensure they are properly formatted.
|
||||
if (
|
||||
survey.redirectUrl &&
|
||||
!survey.redirectUrl.includes("https://") &&
|
||||
!survey.redirectUrl.includes("http://")
|
||||
) {
|
||||
if (survey.redirectUrl && !isValidUrl(survey.redirectUrl)) {
|
||||
toast.error("Please enter a valid URL for redirecting respondents.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useForm } from "react-hook-form";
|
||||
import { toast } from "react-hot-toast";
|
||||
|
||||
import { getAccessFlags } from "@formbricks/lib/membership/utils";
|
||||
import { testURLmatch } from "@formbricks/lib/utils/testUrlMatch";
|
||||
import { testURLmatch } from "@formbricks/lib/utils/url";
|
||||
import {
|
||||
TActionClass,
|
||||
TActionClassInput,
|
||||
|
||||
@@ -15,6 +15,7 @@ import { createPerson, getPersonByUserId } from "@formbricks/lib/person/service"
|
||||
import { getProductByEnvironmentId } from "@formbricks/lib/product/service";
|
||||
import { getResponseBySingleUseId, getResponseCountBySurveyId } from "@formbricks/lib/response/service";
|
||||
import { getSurvey } from "@formbricks/lib/survey/service";
|
||||
import { isValidUrl } from "@formbricks/lib/utils/url";
|
||||
import { ZId } from "@formbricks/types/environment";
|
||||
import { TResponse } from "@formbricks/types/responses";
|
||||
import { MediaBackground } from "@formbricks/ui/MediaBackground";
|
||||
@@ -30,6 +31,7 @@ interface LinkSurveyPageProps {
|
||||
userId?: string;
|
||||
verify?: string;
|
||||
lang?: string;
|
||||
redirectUrl?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -47,16 +49,24 @@ const Page = async ({ params, searchParams }: LinkSurveyPageProps) => {
|
||||
if (!validId.success) {
|
||||
notFound();
|
||||
}
|
||||
const survey = await getSurvey(params.surveyId);
|
||||
const surveyPrisma = await getSurvey(params.surveyId);
|
||||
|
||||
const suId = searchParams.suId;
|
||||
const langParam = searchParams.lang; //can either be language code or alias
|
||||
const isSingleUseSurvey = survey?.singleUse?.enabled;
|
||||
const isSingleUseSurveyEncrypted = survey?.singleUse?.isEncrypted;
|
||||
const redirectUrl =
|
||||
searchParams.redirectUrl && isValidUrl(searchParams.redirectUrl) ? searchParams.redirectUrl : undefined;
|
||||
const survey = structuredClone(surveyPrisma);
|
||||
|
||||
if (!survey || survey.type !== "link" || survey.status === "draft") {
|
||||
notFound();
|
||||
}
|
||||
const isSingleUseSurveyEncrypted = survey.singleUse?.isEncrypted;
|
||||
const isSingleUseSurvey = survey.singleUse?.enabled;
|
||||
|
||||
if (redirectUrl) {
|
||||
// if redirectUrl exist in params and if its valid, we overwrite the redirect url of survey
|
||||
survey.redirectUrl = redirectUrl;
|
||||
}
|
||||
|
||||
const organization = await getOrganizationByEnvironmentId(survey?.environmentId);
|
||||
if (!organization) {
|
||||
|
||||
@@ -18,3 +18,18 @@ export const testURLmatch = (testUrl: string, pageUrlValue: string, pageUrlRule:
|
||||
throw new Error("Invalid match type");
|
||||
}
|
||||
};
|
||||
|
||||
export const isValidUrl = (inputUrl: string): boolean => {
|
||||
try {
|
||||
// URL object will automatically URL-encode the input
|
||||
const url = new URL(inputUrl);
|
||||
|
||||
// Check if the protocol is HTTPS
|
||||
if (url.protocol !== "https:") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user