JavaScript in Omni Exporter
Omni Exporter uses JavaScript to perform dynamic manipulation of the data and to construct data formatted for the intended use. This section describes some of the idioms specific to Omni Exporter, including:
- Accessing record data
- Accessing request and response data
- Formatting date/time values
- Masking strings shown in JavaScript editors
Accessing record data
When an Omni Exporter event is being processed, the data.changedEntities object includes values of the records included in the export event. Each record includes the fields selected in the Fields used in the action property. You can see the body of the event in the Omni Exporter events screen, like this:
To access a field's value, preface the field's key name with "entity.".
This example shows how to build a JSON object containing the records and fields required by the target.
write(JSON.stringify( function() {
var jobs = [];
for(var i = 0; i < data.changedEntities.length; i++) {
var entity = data.changedEntities[i];
var job = {};
job.Subscriber = entity.e_phone;
var v = {};
job.Variables = v;
v['a_surveyid'] = entity.a_surveyid;
jobs.push(job); }
return jobs;
};
()));
Note that some fields selected in Fields included in the action can have @ or / in their name. Since @ and / are special characters in JavaScript, you need to use an alternative syntax to collect the data of these fields and include it in the request body: to access the value of these fields, use "entity['<<field name>>']". For instance: entity['attribute1/numeric_value'] or entity['e_firstname@pre'].
Accessing request and response data
The HTTP request and response data can be accessed with the http.getRequestBodyUtf8() and http.getResponseBodyUtf8() functions. These both return JSON representations of the assemblies.
This example uses both functions to collect information from the request and response assemblies, and then creates a single JSON object containing some of the information, which will then be passed to the Auto Importer.
write(JSON.stringify(function() {
var req = JSON.parse(http.getRequestBodyUtf8());
var resp = JSON.parse(http.getResponseBodyUtf8());
// An HTTP response should start with the Status-Code number, like 200 for OK.
if (typeof resp[0] === 'number') {
var response_status = 2;
var brainstorm_api_fault_code = String(resp[0]);
var brainstorm_api_fault_msg = resp[1];
} else {
var response_status = 0;
var brainstorm_api_fault_code = '';
var brainstorm_api_fault_msg = '';
}
var dateStr = formatDate(eventLastStatusChange, 'yyyy-MM-dd HH:mm:ss');
var records = [];
for (var i = 0; i < req.Jobs.length; i++) {
var jobReq = req.Jobs[i];
var vars = jobReq.Variables;
records.push({
internal_survey_id: vars.a_surveyid,
inserted: dateStr,
updated: dateStr,
input_file_id: eventId,
request_json: JSON.stringify(jobReq),
attempted_flag: 1,
response_status: response_status,
job_id: response_status == 2 ? '' : resp[i],
api_fault_code: api_fault_code,
api_fault_msg: api_fault_msg,
response_json: JSON.stringify(resp)
});
}
return records;
};
}()));
Accessing request and response raw contents
Raw HTTP request and response data can be accessed with the getRequestBodyRaw() and getResponseBodyRaw() functions. These both return the contents of the assemblies without any transformations. They can be useful when the request and response data are not strings.
Accessing request and response content types
The HTTP request and response content types can be accessed with the getRequestContentType() and getResponseContentType() functions. These both describe the format of the response and request bytes: the most common content types are application/json and application/xml.
Accessing request and response headers
The HTTP request and response headers can be accessed with the getRequestHeaders() and getResponseHeaders() functions. These both return the headers of the response and the request, such as api keys, usernames, passwords, or tokens.
It can be used to get the last modified date from the Date general HTTP header. The example below returns a string like "Tue, 25 Jul 2023 15:10:34 GMT":
var httpDate = String(http.getResponseHeaders().get('Date').get(0));
The example below creates a JavaScript Date element:
var httpDate = new Date(http.getResponseHeaders().get('Date').get(0));
The example below returns the date in a string form such as "2023-07-25T15:10:34.000Z":
var httpDate = new Date(http.getResponseHeaders().get('Date').get(0)).toISOString();
This example uses getResponseHeaders() to collect the date from the response Date header, and creates a single JSON object containing the date as a timestamp, which will then be passed to an Auto Importer.
/* HTTP Response Processing */
write(JSON.stringify(function () {
var responseStatusCode = JSON.parse(http.getResponseStatusCode());
var responseBody = JSON.parse(http.getResponseBodyUtf8());
var requestBody = JSON.parse(http.getRequestBodyUtf8());
var responseTimestamp = new Date(http.getResponseHeaders().get('Date').get(0));
var record = data.changedEntities[0];
var payload;
// Successful call
if(responseStatusCode == '200'){
payload = {
"survey_id" : record.a_surveyid,
"request_body" : JSON.stringify(requestBody),
"response_success_yn": "Yes",
"response_code": responseStatusCode,
"response_message": JSON.stringify(responseBody),
"response_timestamp": responseTimestamp
};
}
// Unsuccessful call
else {
payload = {
"survey_id" : record.a_surveyid,
"request_body" : JSON.stringify(requestBody),
"response_success_yn": "No",
"response_code": responseStatusCode,
"response_message": JSON.stringify(responseBody)
};
}
return payload;
}()));
Accessing response status code
The HTTP response status code can be accessed with the http.getResponseStatusCode() function. It returns standard HTTP codes.
This example uses this function to collect response status code from the assembly and, in the case of status code HTTP 201, it will retrieve the information to pass to Auto Importer from a different source, since 201 status code indicates that the response has no content. Then, it creates a single JSON object containing some of the information, which will then be passed to the Auto Importer.
var responseStatusCode = JSON.parse(http.getResponseStatusCode());
var requestBody = JSON.parse(http.getRequestBodyUtf8());
var responseBody='';
var id = '';
var job = {};
var errorMessage = '';
// Successful call
if (responseStatusCode == '200' || responseStatusCode == '201' || responseStatusCode == '204') {
// With a 204 there is no body to parse
if (responseStatusCode != '204'){
// Parse response from Salesforce
var responseBody = JSON.parse(http.getResponseBodyUtf8());
if (responseBody) {
id = String(responseBody.id);
}
}
var record = data.changedEntities[0];
// Build the what our Autoimporter is going to process
job = {
"medalliaId" : record.a_surveyid,
"responseStatusCode": responseStatusCode,
"requestBody": JSON.stringify(requestBody),
"responseSynced": 1,
};
} else {
var responseBody = JSON.parse(http.getResponseBodyUtf8());
if (responseBody) {
if (responseBody[0]) {
errorMessage = String(responseBody[0].message);
}
}
var record = data.changedEntities[0];
job = {
"medalliaId" : record.a_surveyid,
"requestBody":JSON.stringify(requestBody),
"responseStatusCode": responseStatusCode,
"errorMessage" : errorMessage
};
}
write(JSON.stringify([job]));
Accessing response message
The response message related to the HTTP status code can be accessed with the getResponseMessage() function. It returns a brief description of the status code.
Formatting date/time values
The formatDate() helper function formats date/time object per the string patterns described in Date and time formatting.
formatDate(datetime object, output string format)
JSON output example
This example shows how to build a JSON object containing the records and fields required by Jira to create an issue showing customer survey responses about our product documentation. Note that we use a escapeHTML() method to convert a list of HTML special characters to their entity equivalents.
write(JSON.stringify(function () {
function escapeHtml(str) {
return str ? str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
//.replace(/"/g, '"')
.replace(/'/g, ''') : str;
}
The data.changedEntities is an array of the fields selected in the Fields used in the action property above (each field is an entity). To access a field's value, preface the field's key name with "entity.". The record that we need to send to Jira is the first one in the list.
var entities = data.changedEntities;
var entity = entities[0];
var accuracy = entity.q_bp_documentation_give_feedback_accuracy_scale11;
var clarity = entity.q_bp_documentation_give_feedback_clarity_scale11;
var completeness = entity.q_bp_documentation_give_feedback_completeness_scale11;
var priority = 'Not Prioritized';
var summaryFlag = '';
var project = entity.k_doc_jira_project; // Jira project
var summary = summaryFlag + 'Doc Feedback on: '+ entity.q_bp_documentation_give_feedback_page_name_text;
Next is the body of the description of the Jira issue. This example takes values from various survey fields and puts them in a format that Jira renders as a table. The field q_bp_documentation_give_feedback_improve_page_comment captures the comments left by the user. The value of summaryFlag will be used to build the title of the Jira issue.
var message =
+ '\\\\ \n\n'
+ '\n|*OSAT*|*' + parseInt(entity.q_bp_documentation_give_feedback_osat_scale11, 10) + '*|'
+ '\n|Accuracy|' + ((accuracy === undefined || accuracy === '' || accuracy === null ) ? '---' : parseInt(accuracy, 10)) +'|'
+ '\n|Clarity|' + ((clarity === undefined || clarity === '' || clarity === null ) ? '---' : parseInt(clarity, 10)) +'|'
+ '\n|Completeness|' + ((completeness === undefined || completeness === '' || completeness === null ) ? '---' : parseInt(completeness, 10)) +'|'
+ '\n|Fix typo|' + entity.q_bp_documentation_give_feedback_typo_yn +'|'
+ '\n|Inaccurate info|' + entity.q_bp_documentation_give_feedback_inaccurate_yn +'|'
+ '\n|Missing info|' + entity.q_bp_documentation_give_feedback_missing_info_yn +'|'
+ '\n|Inaccurate info|' + entity.q_bp_documentation_give_feedback_inaccurate_yn +'|'
+ '\n|Broken image|' + entity.q_bp_documentation_give_feedback_broken_image_yn +'|'
+ '\n|Broken link|' + entity.q_bp_documentation_give_feedback_broken_link_yn +'|'
+ '\n\n\\\\ '
+ '\n{panel:title=Ideas for improvement|borderStyle=solid|titleBGColor=#EAEAEA|borderColor=#EAEAEA}' + escapeHtml(entity['q_bp_documentation_give_feedback_improve_page_comment']) + '\n{panel}'
+ '\n\n\\\\ '
+ '\n\nClick here to [View the Alert|https://instance.medallia.com/company/respInvForm.do?surveyid=' + entity.a_survey_internal_id + ']'
+ '\n\n\\\\ '
+ 'Product Documentation - Give Feedback survey ID# ' + entity.a_survey_internal_id
The fragment below is the actual JSON object that is being sent to Jira. It contains the required fields for Jira to create the issue. Particularly, the list of issue screen fields to update inside the fields object. For more information, see the Jira official documentation on how to create an issue.
return {
"fields": {
"parent": {
"key": project,
},
"priority": {
"name": "Not Prioritized",
},
"summary": summary,
"description": message,
"issuetype": {
"name": "Support Request"
},
"components":[
{
"name": "Documentation"
}
]
}
};
}()));
Masking strings shown in JavaScript editors
Omni Exporter automatically masks the values of header fields when the field name contains "password", "token", "secrets", "credential", or "authentication". Field values are masked by replacing the value with three asterisks ("***"). Similarly, any string in the JavaScript editors can be masked to hide the values similar to the field masking feature.
To mask a string, include it as the argument to the encrypt() function. When you save the specification, Omni Exporter saves the original value on the server, and replaces the function with a decrypt() function whose value is a reference to the string on the server. At run-time when the specification is processing an export, the server retrieves the original value and inserts it into the code
This illustration demonstrates the behavior:
