How to evaluate query string parameters inside SurveyJS expressions

Introduction

In this post we extend SurveyJS so that querystring parameters can be used to control the flow of your form or survey with branching logic (aka SurveyJS’s “conditional display rules”). We will also see how query string values, or entire URLs for that matter, can be saved along with the form’s response data.

This can be useful when you are running multiple marketing campaigns and you would like to control the contents of your forms based on the URL that your respondents used to visit your forms.

What are the use cases?

There are countless use cases where this approach could be helpful, but for the purposes of this blog post we will only look at a couple of them.

Multi-product feedback survey

Let’s say your company offers a SaaS product with different modules, similar to how HubSpot has their Sales Hub, Marketing Hub, Operations Hub, and so on. When you collect product feedback you have a couple of options with their respective pros and cons:

Option 1: Separate product feedback surveys for each module

This approach provides more focus, however it becomes inconvenient for your customers if they have to fill out multiple surveys, just because they use more than one of your modules.

Option 2: A single survey that covers all modules

The problem here is that you would have to ask your customer to indicate which modules they are using. This is inconvenient and probably seems unnecessary to your customer, because they expect you to know exactly which modules they have subscribed to.

Solution

The good news is that you can have the best of both worlds. If you add some logic to your application backend to check which modules your customer has activated, you can append that information to your survey URL in the form of query string parameters.

Marketing campaigns

Some of the most commonly used query string parameters are Google’s UTM Codes, and a lot of your marketing-related links most likely already have them. Capturing them in your SurveyJS form could be very valuable from an analytics point of view. They can also help you drive the flow of the form. Webinars are very good example of how this could be useful. If you send your attendees to your product feedback survey after the webinar ended, you could also include a few questions about the webinar itself. Obviously you wouldn’t want to confuse your other respondents with those questions. Detecting the webinar campaign UTM code can be used to show those otherwise hidden questions.

How does SurveyJS’s branching logic work?

Pages, panels, questions, and cells in a SurveyJS form have a property called visibleIf. As the name suggests, the value of this property determines whether the page, panel, question, or cell it applies to, will be visible or not. Additionally, questions have two more properties: enableIf and requiredIf. Each of these three properties requires a boolean value, which can be provided dynamically in the form of an expression. Here’s a simple example, which demonstrates how to ask respondents to rate the quality of a webinar, but only if they have indicated that they attended the webinar:


{
 "pages": [
  {
   "name": "page1",
   "elements": [
    {
     "type": "text",
     "name": "name",
     "title": "What is your name (optional)"
    },
    {
     "type": "boolean",
     "name": "attendedWebinar",
     "title": "Did you attend our webinar?",
     "defaultValue": "false"
    },
    {
     "type": "rating",
     "name": "webinarRating",
     "visibleIf": "{attendedWebinar} = true",
     "title": "Please rate the webinar you just attended"
    },
    {
     "type": "radiogroup",
     "name": "operatingSystem",
     "title": "Which operating system are you using?",
     "choices": [
      "macOS",
      "Windows",
      "Linux"
     ],
     "hasOther": true
    }
   ]
  }
 ],
 "showQuestionNumbers": "off"
}

The expressions allow for a significant level of complexity due to their support of logical operators, such as AND, OR, NOT, etc. There are plenty of built-in functions for evaluating strings or even arrays of values. The framework even allows for custom functions to be registered through its API. If you would like to explore these options in more detail, please refer to the following section of the official SurveyJS docs: https://surveyjs.io/form-library/documentation/design-survey/conditional-logic

Extend SurveyJS by adding a custom function to its expression engine

As mentioned above, SurveyJS allows for custom functions to be registered. Such custom functions can be used within expressions to control the survey flow, visibility of questions, or even calculated values. For the purposes of this example we will build a simple function, which expects a name of a querystring parameter and then returns its value:


function urlParameter(paramName) {
    var urlParams = new URLSearchParams(window.location.search);
    var paramValue = urlParams.get(paramName);
    return paramValue;
}

Next, we will register the custom function with SurveyJS:


Survey.FunctionFactory
    .Instance
    .register("urlParameter", urlParameter);

Now we can update the definition of our webinar feedback questions to take advantage of the new function we introduced. We need to remove the previously used "defaultValue": "false" with "defaultValueExpression": "urlParameter('source') = 'webinar'". Here are the revised question definitions:


{
   "type": "boolean",
   "name": "attendedWebinar",
   "visibleIf": "urlParameter('source') != 'webinar'",
   "title": "Did you attend our webinar?",
   "defaultValueExpression": "urlParameter('source') = 'webinar'"
},
{
   "type": "rating",
   "name": "webinarRating",
   "visibleIf": "{attendedWebinar} = true",
   "title": "Please rate the webinar you just attended"
},

Save URL parameter values within the survey response data

In some cases you may need to actually save certain query string values within each respondent’s data. You can do that by creating a hidden text question, which can store the value, but won’t be visible to your respondents. However, by default SurveyJS excludes hidden questions from the survey response object. To change this behavior you need to add the following parameter to your survey definition:


{
    "showQuestionNumbers": "off",
    "clearInvisibleValues": "none"
}

Once you have done that, you can add a hidden question and use our new custom function in its defaultValueExpression property:


{
   "type": "text",
   "name": "urlSource",
   "visible": false,
   "defaultValueExpression": "urlParameter('source')"
}

See it in action

You can navigate to a live version of this example through each of these links to see how their querystring parameters affect the behavior of the survey.

https://endatix.com/samples/url-parameters/index.html

https://endatix.com/samples/url-parameters/index.html?source=webinar


How We Can Help

We offer expert advice on architecture, provide training for SurveyJS and the Endatix backend, and assist with development and implementation of your solution. Feel free to contact us—we're passionate about software and always happy to chat!

  Contact us