How to Build Your Own Surveys & Extend Them with Custom JavaScript

A primer on how to use your own JS functions, to augment the conditional logic and validators SurveyJS ships with.

By Prithwish Nath

August 31st, 2022

image

The biggest difference maker when it comes to maximizing ROI on a survey — whether it's market research for a new ad campaign, gauging customer satisfaction, or patient history taking — is relevance. Simply put, don't waste their time.

Your respondents shouldn't have to see questions that don't apply to them or boilerplate questions that contradict the information they've *already *provided.

This is why implementing conditional branching (better known as “skip logic”) for your surveys is critical. You need to ensure that your respondents *always *get the most relevant questions — because that's what leads to higher completion rates and a larger sample size of data for you. Plus, using conditional logic, you gain the ability to determine questions based on answers to previous questions, all of which adds up to better analytics for you, and more accurate projections and indices for your stakeholders.

SurveyJS is a free and open-source (under the MIT license) JavaScript library that not only lets you do this — but also goes one step further and allows you to extend your conditional logic and input validation with your own JavaScript code, to do things no mere survey library could do alone.

Awesome, right? Let's build our own conditions and validators — sticking entirely to vanilla JavaScript — to see just how easy this is, regardless of the framework you're using.

Custom Conditional Logic

For a non-contrived, real-world example, let's say you were designing a digital usage survey and wanted to categorize questions in a way that holds questions for PC users on one page, and mobile users on another, both being mutually exclusive in terms of visibility.

![Background image

Now, SurveyJS provides you with several built-in client-side conditional visibility options and triggers to help you implement branching and skip logic — the visibleIf, enableIf, and requiredIf properties, for example, are:

a. set in the survey schema (JSON) itself,

b. accept boolean expressions intuitively, and

c. can be applied to questions, panels, and even entire pages.

Have a look at this survey

The second question (ideal team size) would be visible** if and only if **the previous question (prior team experience) had an affirmative ‘Yes' answer.*

In the device usage survey that we're talking about now though, this built-in conditional evaluation couldn't help us without an extra starting question that asked something like, “What kind of device are you currently using?” This is extraneous, takes up time, and the respondent would probably prefer this to be auto-detected, instead.

So right now, you're probably thinking, “Well gee, sure would be nice if I could just…write a JS function that *automatically *detected whether my respondent was on a computer or a mobile device, and showed one of the two pages, conditionally.”

If you are, give yourself a pat on the back, because you can do *exactly *that.

This is *all *vanilla JavaScript, by the way. For older/unsupported web browsers, try the matchMedia() polyfill.

This is all vanilla JavaScript, by the way. For older/unsupported web browsers, try the matchMedia() polyfill.*

So that's our first step; coding a function that uses the matchMedia API to run a CSS media query, and run a matches function on the returned object that gives us a true or false value depending on whether the query matched or not— perfect for us, because of course, we **do **want boolean values for conditional logic in a survey!

Our function checks the respondent's device and returns true as long as it has at least one fine-grained pointer (aka, a mouse or touchpad). If not, well, your respondent is probably on a mobile device.

  • 💡 Edge cases exist, of course, but this is a quick and dirty way to check for device usage that doesn't need external libraries (like UAParser.js), and will serve our example just fine.

The next step for custom functions is to ‘register' them, like so.

The args for the register function are :

  • function name (a string),

  • the function itself,

  • and a boolean value to indicate whether this is an async function (in which case the library will expect a **callback **instead of a regular return statement — remember this one, we'll come back to it later!)

Finally, include the function name in your JSON schema as the condition you're checking for, and you're good to go.

And as you've already guessed, for your PC specific page, the visibleIf property needs to be “!ifMobile()” or “ifMobile() = false” instead.

And as you've already guessed, for your PC specific page, the visibleIf property needs to be “!ifMobile()” or “ifMobile() = false” instead.

Custom Input Validation — local and server-side.

Just as easily as we did custom conditionals to implement skip logic, we can do custom input validation to go above and beyond what SurveyJS provides out-of-the-box.

Before we get to the exciting bits here, let's look at a basic example of custom input validation.

This is a simple enough example that uses a regex pattern to make sure no HTML code exists within a Comment field, as a security measure to prevent potential malicious scripting attacks.

Over in App.jsx (or whichever component instantiates and renders your survey), you register this, just like we did with our functions for custom conditional logic.

Don't forget to include this function name as a validator in our JSON schema, again, just like before.

And you're good to go. This works exactly as you'd expect it to.

Now, for the fun part.

Remember how the register function had an optional boolean argument to indicate if you were registering an asynchronous function that needed a callback?

If you needed a refresher, here's the type declaration.

If you needed a refresher, here's the type declaration.

Yup, you guessed it. Next, we'll be building a custom input validator that actually calls an external, third-party REST API with fetch to validate a user-provided email address, making sure it is actually deliverable, and not simply _valid _— very useful since field regexes are merely dumb patterns, and can easily be fooled with email addresses that are bogus but *look *right, like fake@notreal.com.

We're using the EVA here, which is a nifty little public API that quickly does email verification for you, including checking for reachability, webmail status, and spam filtering.

We're using the EVA here, which is a nifty little public API that quickly does email verification for you, including checking for reachability, webmail status, and spam filtering.

Register, and include it as a validator in your JSON schema…

…and we're done! Putting it all together, here's our validation code in action.

Limitless Potential

Building surveys is hard work. Don't make it harder.

Your imagination and your data collecting capability should not be a function of the platform's tools, and should not be limited by the technical capacity of the library that you're using for said task.

This is what makes SurveyJS stand out — the ability to augment existing functionality with completely custom JavaScript code to do exactly what you want, regardless of whichever framework you happen to be using. Sure, the examples provided were built with React, but none of the custom conditional logic or input validation was React specific — we just extended SurveyJS with framework-agnostic vanilla JavaScript. The sheer number of possibilities this affords us cannot be overstated.



Continue Learning