Custom Code Logic
This article will show you how to add Custom Node.js Script to your survey as well as note which functions are available. All the examples provided are in ES5 syntax, but you can freely use ES6 as well.
Background
The Custom Node.js Script allows you to write JavaScript ES6 code to work with datapoints in your survey. It allows more flexibility to perform simple or complex tasks when working with respondent data. For example, you can easily take data from one grid and set those values into another grid, call an external API and then process the response, use a third-party node library for some statistical processing, etc.
Getting Started
- Click on Add Logic or Quota Page button.
- Select Custom JS Script and click on Add.
- Select your new Custom Logic page and click on </> Add Javascript.
Built-in objects available
The following objects are available in the custom Node.js code and provide convenience functions for certain actions.
- survey
- .id() - returns the current survey's ID.
- respondent
- .id() - returns the current respondent's ID.
- .data(dataPointName) - gets the given data point value and returns it.
- .data(dataPointName, value) - sets the given data point to a given value.
- page(pageNumber) - sets the respondent's current page. Can be used to skip to a different page in the survey.
- termCode(termCodeName) - terminates the respondent with the given termination code name.
Getting and Setting Respondent Data
respondent.data(dataPointName, value);
var q1 = respondent.data('Q1'); // q1 now contains the value of Q1. respondent.data('Q1', 2); // Q1 was now updated to the response with a value of 2 // Signal to the custom code engine that it should return control to the survey. done();
- Single and multi-response type questions and variables .
- Question specify values
The only exception is that you cannot override system variables:
- RESP_TOKEN
- LOCALE
- SAMPLE_SOURCE
- DEVICE_TYPE
- IS_MOBILE
- PLATFORM
var allData = respondent.data(); done();
allData would be set to:
{ "Q1": 1, "Q2_1": "I love this brand", "Q2_2": "I think it's great", "LOCALE": 1, "SAMPLE_SOURCE": 1, "IS_MOBILE": 2, "DEVICE_TYPE": 2, "PLATFORM": 14, "RESP_TOKEN": "RGF123LA", "VAR_COUNTER": 1 }
- Keep in mind that you won't have access to the META accessor :TEXT, as survey content is not available via the custom engine.
- You can't clear datapoints via the custom engine currently, only get/update their values.
- Values for multi-response questions/variables are fetched individually. If you have a text question called Q2 with two responses, the only way to access their responses is via the separate datapoints Q2_1 and Q2_2. Calling the data for Q2 will not return any values.
Terminating the respondent
respondent.termCode('DOES_NOT_QUALIFY'); // After end of execution of the custom script, the respondent will be terminated with term code DOES_NOT_QUALIFY. done();
Skipping to a page
respondent.page(31); // After the end of execution of this custom script, the respondent will be redirected to page 31. done();
Returning from your custom script
Throwing errors
throw new Error('Something I want to log here');
done(new Error('Something I want to log here'));
You will encounter the error and its content while running through your survey on test mode.
Calling an API
When you want to call an external API, for instance to automatically issue respondent rewards, or to analyze data via a third party service, you can use the request function. This is a wrapper around the NPM request library (https://www.npmjs.com/package/request) and should provide the same functionality. Furthermore, you can use the request function with either a callback, or a promise.
Callback example:
request({ url: 'https://fakesite.cmix.com', method: 'POST', json: true, body: { respondentId: respondent.id()
}, }, function (error, response, body) { if (!error) { // Do something. done(); } else { done(new Exception('Something I want to log here: ' + error)); } });
Promise example:
// Defaults to a GET request if no options are passed. request('https://fakesite.cmix.com') .then(function (body) { // Do something. done(); }) .catch(done);
IMPORTANT NOTE: To prevent abuse, external APIs have to be whitelisted. If you want to add a domain to our whitelist, contact us with the details for your use case. All CMIX APIs are whitelisted by default.
Using a third party Node.js library
External Node.js libraries are supported and are added on-demand to properly vet them. Currently the following libraries are available:
- distributions (https://www.npmjs.com/package/distributions)
var distributions = require('distributions'); var normal = distributions.Normal(1 /* mean */, 2 /* std deviation */); done();
- bluebird (https://github.com/petkaantonov/bluebird). Bluebird is included built in so you don't need to require it.
// Make two requests simultaneously and wait for both to be done before returning.
Promise
.all([
request('https://fakesite.cmix.com'), request('https://fakesite2.cmix.com')
])
.then(done)
.catch(done);
Other Examples:
// Copy data over from grid radio question Q1 to grid radio question Q2. Both questions have 5 radio sub-questions var q1Data; for (var i = 1; i <= 5; i++) { q1Data = respondent.data('Q1_' + i); respondent.data('Q2_' + i, q1Data); } done();