OnCall IVR Suite v3.3.x
OnCall IVR Developer Guide
This documentation is targeting IVR developers who are creating custom templates to be used in IVR Designer.
For details on using the IVR Designer application please read the Getting Started with the IVR Designer document.
Writing Custom IVR Templates
All Nodes and Templates in use by the system consist of two parts: a JSON part to provide the interface and parameter definitions and an XML part with the actual business code written in JavaScript with standard Microsoft .NET assemblies freely available.
A Template can contain many Nodes.
The JSON Structure
The JSON structure specifies the data input/output interface and the generic details for the nodes / templates. It is typically more complex for templates:
{
"name": "NAME_OF_TEMPLATE",
"type": "template",
"description": "Human readable description of the template.",
"attributes":
[
{"name": "id", "type": "integer", "defaultvalue": "1000"},
{"name": "attribute_1", "type": "integer", "defaultvalue": "6"},
{"name": "attribute_2", "type": "integer", "defaultvalue": "5"}
],
"parameters":
[
{"name": "template_parameter_1"},
{"name": "template_parameter_2"},
{"name": "template_parameter_3"},
],
"announcements":
[
{"name": "Announcement_A"}
],
"connections":
[
{"name": "error"},
{"name": "connection_1"},
{"name": "connection_2"}
]
}
With the exception of the id
(which is simply a unique identifier), attributes are a means to exchange data with the node or template. These could either be done by specifying literal data to them, or by referencing a flow variable (defined in the Variables panel).
Announcements declare all the announcements the node/template works with. Similarly, the Connections section specifies the different connection points to other nodes or templates when this one is finished.
The XML Structure
For the nodes, the XML is usually very simple and custom to the actual node. See the Reject Node XML for example:
<reject id="#ID#">
<next>#NEXT#</next>
</reject>
For templates it can be way more complex depending on the business requirement. The generic XML structure looks similar to this example:
<template name="NAME_OF_TEMPLATE" id="#ID#">
<constraints>
<errors AllAttributesRequired="true" NoRecursionAllowed="true" />
<warnings MinIncomingConnections="1" AllConnectionsRequired="true" AllAttributesRequired="true" />
</constraints>
<announcements>
<announcement id="Announcement_A" istts="true" interruptable="true"><![CDATA[#ANNOUNCEMENT_A#]]></announcement>
</announcements>
<parameters>
<parameter id="template_parameter_1"> <![CDATA[#TEMPLATE_PARAMETER_1#]]></parameter>
<parameter id="template_parameter_2"> <![CDATA[#TEMPLATE_PARAMETER_2#]]></parameter>
<parameter id="template_parameter_3" type="Variable" datatype="string" direction="Input"><![CDATA[#TEMPLATE_PARAMETER_3#]]></parameter>
</parameters>
<connections namedoutputs="true">
<connection name="error" destination="#ERROR#" />
<connection name="connection_1" destination="#CONNECTION_1#" />
<connection name="connection_2" destination="#CONNECTION_2#" />
</connections>
<flow>
<variables>
<variable id="Announcement_A" datatype="announcement" type="variable"><![CDATA[Announcement_A]]></variable>
</variables>
<nodes>
<!-- Script For Business Function 1 -->
<script id="100">
<connections namedoutputs="false">
<connection name="OK" destination="200"/>
</connections>
<data><![CDATA[
/* JAVASCRIPT BUSINESS LOGIC FOR SCRIPT ID = 100 */
/* IN THIS EXAMPLE, THE NEXT CONNECTION DOES NOT NEED TO BE
/* SPECIFIED EXPLICITLY, HERE. IT WILL ALWAYS BE THE NODE WITH */
/* ID 200 IN THIS TEMPLATE, A PROMPT NODE. */
]]></data>
</script>
<!-- Script For Business Function 2 -->
<script id="110">
<parameters>
<parameter id="template_parameter_1" type="variable" datatype="string" direction="input"><![CDATA[?]]></parameter>
<parameter id="script_110_parameter_1" type="variable" datatype="string" direction="output"><![CDATA[?]]></parameter>
</parameters>
<connections namedoutputs="true">
<connection exitpoint="error" name="ERROR" destination="?"/>
<connection name="OK" destination="120"/>
</connections>
<data>
<![CDATA[
try {
/* JAVASCRIPT BUSINESS LOGIC FOR SCRIPT ID = 110 */
/* IN THIS EXAMPLE, FOR NORMAL BUSINESS FLOW THE NEXT CONNECTION */
/* POINTS TO ANOTHER SCRIPT INSIDE THIS TEMPLATE: ID = 120 */
/* THIS SCRIPT NODE INSERTS BUSINESS DATA INTO THE */
/* script_110_parameter_1 PARAMETER, WHICH IS OF OUTPUT TYPE */
$$nextConnection$$ = 'OK';
} catch (error) {
/* IN CASE OF ERRORS, THE TEMPLATE STOPS, THE CONTROL FLOW */
/* PROCEEDS AT THE ERROR EXIT POINT */
$$nextConnection$$ = 'ERROR';
}
]]></data>
</script>
<!-- Script For Business Function 3 -->
<script id="120">
<parameters>
<parameter id="script_110_parameter_1" type="Variable" datatype="string" direction="input"><![CDATA[?]]></parameter>
<parameter id="template_parameter_2" type="Variable" datatype="string" direction="input"><![CDATA[?]]></parameter>
<parameter id="template_parameter_3" type="Variable" datatype="string" direction="input"><![CDATA[?]]></parameter>
</parameters>
<connections namedoutputs="true">
<connection exitpoint="error" name="error" destination="?"/>
<connection exitpoint="connection_1" name="connection_1" destination="?"/>
<connection exitpoint="connection_2" name="connection_2" destination="?"/>
<connection name="Start_From_Announcement" destination="200"/>
</connections>
<data>
<![CDATA[
try {
/* JAVASCRIPT BUSINESS LOGIC FOR SCRIPT ID = 120 */
/* FOR THE SAKE OF THIS EXAMPLE, THIS SCRIPT DEFINES THE NEXT CONNECTIONS */
/* FROM THIS TEMPLATE */
if ( /* BUSINESS CASE 1 */ ) {
$$nextConnection$$ = 'connection_1';
} else if ( /* BUSINESS CASE 2 */ ) {
$$nextConnection$$ = 'connection_2';
} else {
$$nextConnection$$ = 'Start_From_Announcement';
}
} catch (error) {
/* IN CASE OF ERRORS, THE TEMPLATE STOPS, THE CONTROL FLOW */
/* PROCEEDS AT THE ERROR EXIT POINT */
$$nextConnection$$ = 'ERROR';
}
]]>
</data>
</script>
<!-- Announcements -->
<!-- Plays Announcement_A, collecting a single digit, then jumping to node ID = 110 in the template -->
<prompt id="200">
<source type="variable"><![CDATA[Announcement_A]]></source>
<digits>1</digits>
<timeout>1</timeout>
<next>110</next>
</prompt>
</nodes>
</flow>
</template>
The above example template contains 4 nodes: 3x script nodes and an announcement node. The first node is a script (ID 100) and upon performing some business logic it jumps to another node in the template, ID 200 a Prompt node playing an announcement and collecting a digit. From then the control flow jumps to node 110 and then 120, where business logic will decide which of the template's available connections will be used.
Would any of these nodes encounter any error (see the Catch()
parts), the $$nextConnection$$
reserved variable is set to the ERROR
connection, that is specified with an exitpoint
tag so no other node in the template would be processed. Instead, the next node/template is going to be the one specified on the Error path of the template.
The template XML contains a Constraints section that governs specific operations of the template in the Stage.
Connections In A Template
Potentially containing several different nodes, templates have means to have the nodes decide whether their own connection points should be targeting another node in the same template or an exit point of the template itself.
When a node connection XML entry has an exitpoint
, it is targeting one of the template's own connection, and not one of the internal nodes. In such cases the destination
tag should be generic ("?"
). On the other hand when they don't, then the destination
tag should contain the ID of another node in the template.
Parameters In A Template
Even though the template itself can have parameters, the individual nodes can have their own separate set as well. These nodes can reference the template's parameters too.
Exchanging data between two nodes in a template is done by setting up a new parameter as output
in the data source node, passing some data to it, and referencing it as an input
type parameter in the data receiver node.
Custom Node Creator
The IVR Engine installer places the Custom Node Creator tool in the Tools
folder to modify, create or delete the JSON and XML parts of every node and template in the IVR Designer database.
Tip
You can use the Custom Node Creator to open the details of the default nodes and templates as well. Reading these might provide a better understanding on the system operation.
Warning
Custom Node Creator does not prohibit changing the default items! Changing default nodes or templates could severely affect the operation of the system or even block it entirely. Make sure you use the Custom Node Creator with caution in a production environment!
Nodes Reference
The following chapters provide insight into the various nodes.
Script Node
This is a special node not explicitly available in the Stage of the Designer. It can be edited using the Custom Node Creator tool. See the example above.
When the IVR Engine's NodeService encounters a script node in the flow, it processes it as per the following pseudo-code:
Foreach p in parameters
If p.direction=input then
If p.type = const then
Add a script variable in the scope with name = parameter.id and value = p.innertext
Elseif p.type = variable then
Add a script variable in the scope with name = parameter.id and value = flowvariables[p.innertext]
Else if p.direction=output then
Replace $$p.id$$ with p.innertext in data
Execute script
Foreach p in parameters
If p.direction = output then
value = scriptscope[p.innertext]
Flowvariables[p.value] = value
If namedconnections then
Nextnode = connections[nextConnection].destination
Else
Nextnode = connections[0].destination
For example:
<parameters>
<parameter id="msg" type="const" datatype="string" direction="input">
<![CDATA[AccountID:]]>
</parameter>
<parameter id="var1" type="variable" datatype="string" direction="input">
<![CDATA[accountid]]>
</parameter>
<parameter id="ret" type="variable" datatype="string" direction="output">
<![CDATA[scrret]]>
</parameter>
</parameters>
<data>
<![CDATA[$$ret$$ = var1 + ',' + msg]]>
</data>
Before execution, the above script code is translated to the following equivalent JS code:
msg = 'DisconnectHandler done';
var1 = flowvars['accountid'];
scrret = var1 + ',' + msg;
flowvars['scrret'] = scrret;
Start Node
The Start node is where the call treatment starts after the IVR Engine managed to identify which flow to launch for a new call.
The Start node does not answer the call, it is simply a starting point for the flow. You need to explicitly use the Answer node to 'pick up' a ringing call. This way you have the ability to perform whatever checks your business logic dictates the result of which might even affect whether you wish to answer the call or not.
If there will be TTS announcements in the flow, you can also set the TTS Engine
parameter to designate one of the available voice systems (US, German, Spanish, etc. available in Microsoft Speech system).
Note
There can only be a single Start node in the flow.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
next | integer | Unique ID of the next node. |
ttsused | true or false |
Indicates whether the TTS engine needs to be initialized for this flow or not. If at least one announcement in the flow is TTS type, then this ust be set to true and the ttsengine properly specified. |
ttsengine | string | Name of the MS TTS engine to be used. |
createtime | datetime | The date and time this node was created. |
publishtime | datetime | The date and time this flow was last published. |
author | string in XML data format | The username of the person created this flow. |
modifier | string in XML data format | The username of the person last modified this flow. |
Stop Node
A mandatory node, signaling the end of the flow.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
Answer Node
Use this to 'pick up' the call and allow the caller to engage with any prompts and listen to any announcements. In a typical flow this is usually pretty close to the Start node as you would wish to limit the amount of time the customer waits for the system to become responsive.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
next | integer | Unique ID of the next node. |
Reject Node
This node rejects a call not yet answered.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
next | integer | Unique ID of the next node. |
Dial Node
Initiates an outbound call. Can only be used with flows triggered externally by the IVR Webservice Run
method.
Note
This node can not be used to initiate an outbound call if the flow it is placed into is triggered by an inbound call.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
next | integer | Unique ID of the next node. |
error | integer | Unique ID of the next node in case an error happened (e.g. destination was busy, etc). |
noanswer | integer | Unique ID of the next node in case the destination did not answer the outbound call. |
voicemail | integer | Unique ID of the next node in case the outbound call was treated by a voicemail service. |
parameter timeout | integer | The parameter passed to the WS call containing the seconds to wait for the called party to answer. |
parameter caller | string | The parameter containing the SIPURI of the calling party. |
parameter destination | string | The parameter containing the SIPURI/TELURI to dial. |
Subflow Node
Use this node to spawn another flow from within the original flow. You supply the name of the target flow. The exit point of this node is going to be used after the subflow is done properly (or failed).
The flow called in the Subflow node should also have a Start node, and it must have at least a single Return node that will be used to stop running that flow and return to the originator flow.
Flow variables defined in the originating flow (where the Subflow node is used) are all automatically available and writeable in the subflow. After the subflow returns, the originating flow can check and use the variables it changed. Also, variables created in the subflow become available in the originating flow.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
next | integer | Unique ID of the next node after the subflow returns. |
treename | string | Name of the sub flow (tree) to start. |
Return Node
This node is used to stop and return from the subflow. In case the flow this node is used is not called from a Subflow node (but started normally), the Return node behaves as the Stop node.
Note
Even though Return can act as Stop in the above situation, they are not mutually replaceable! The Stop node can not be used as the Return node in a subflow!
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
Announce Node
Plays an associated WMA or TTS announcement. When used with a TTS announcement, the contents of variables can be uttered.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
next | integer | Unique ID of the next node. |
source type | xml or variable |
Designating where the announcement parameters are loaded from. XML means these are loaded form the node's XML part. Variable means these are loaded from an announcement type variable. Announcement variables can pass the interruptable , istts , data and parameters parameters. |
istts | true or false |
Indicates whether the data designates a WMA sound file or the TTS message to utter. |
data | string | The WMA file name or TTS message. |
parameter id | string | Unique ID of the variable used in processing the TTS phrase. |
parameter direction | always input |
Designates if variable gets updated from the node or not. |
parameter type | variable or const |
Sets the type of the parameter. |
parameter DataType | a supported datatype | The datatype of the variable containing the parameter's value. |
parameter's innerText | string | The literal value of the parameter or the name of the variable holding the value. |
Processing Announcements Parameters
For WMA type announcements the file data is downloaded and cached by the endpoint, the parameters are not processed.
The TTS type announcements can however be further configured by the above parameters. See how, with the following pseudo-code:
If (parameter is const) then
Replace $$parameterid$$ with `innerText` data
Else
myAnnouncementText = flowvariables['innertext']
Replace $$parameterid$$ with myAnnouncementText in data
Prompt Node
Plays an announcement and waits for user response. Can be used to collect free length of digits as well.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
next | integer | Unique ID of the next node. |
digits | integer | Number of digits to collect from the caller. |
terminator | string | The DTMF key (0 to 9, # or *) that breaks the user input. Can only be used with variable number of digits to collect. It can also be empty. |
timeout | integer | Seconds to wait for user input. Is reset every time the caller presses a DTMF key (except for the terminator key, if set). |
source type | xml or variable |
Designating where the announcement parameters are loaded from. XML means these are loaded form the node's XML part. Variable means these are loaded from an announcement type variable. Announcement variables can pass the interruptable , istts , data and parameters parameters. |
istts | true or false |
Indicates whether the data designates a WMA sound file or the TTS message to utter. |
data | string | The WMA file name or TTS message. |
parameter id | string | Unique ID of the variable used in processing the TTS phrase. |
parameter direction | always input |
Designates if variable gets updated from the node or not. |
parameter type | variable or const |
Sets the type of the parameter. |
parameter DataType | a supported datatype | The datatype of the variable containing the parameter's value. |
parameter's innerText | string | The literal value of the parameter or the name of the variable holding the value. |
The node sets the following flow variables:
collecteddigits
: user input including the terminator (string)collectionresult
: result of collection, 0 in case no button was pressed, 1 otherwise
PromptJump Node
Plays an announcement and collects a single DTMF key from the caller, then selects the next node based on the digit collected.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
next0 to next9, nextstar, nexthash | integer | Unique ID of the next node when the relevant digit is collected from the caller. |
timeout | integer | Seconds to wait for user input. |
error | integer | The next node in case no digit was selected within the given timeout or any error occurred during the process. |
source type | xml or variable |
Designating where the announcement parameters are loaded from. XML means these are loaded form the node's XML part. Variable means these are loaded from an announcement type variable. Announcement variables can pass the interruptable , istts , data and parameters parameters. |
istts | true or false |
Indicates whether the data designates a WMA sound file or the TTS message to utter. |
data | string | The WMA file name or TTS message. |
Transfer Node
Transfers the call to a specific destination.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
destination | string | A SIPURI or TELURI literal, or a variable containing this data where the call is to be transferred to. |
next | integer | Unique ID of the next node when the transfer is successful. |
uui | string | Additional data to be passed with the transferred call, inserted as a ;uui=data tag into the SIP TO header. Data is padded with whitespaces for its length to become dividable by 3, and then encoded with base64 to conform with SIPURI standards. |
error | integer | The next node in case no digit was selected within the given timeout or any error occurred during the process. |
maxwait | integer | Maximum time in seconds to wait in case of supervised transfer. For unattended trasfer set this parameter to -1 and unattendedtransfer endpoint service configuration to True. For attended transfer set this parameter to -1 and unattendedtransfer endpoint sevice configuration to False. For supervised transfer set maxwait parameter to a positive number. Default value is -1. |
Important
Contact Expert does not handle supervised transfers.
Collector Node
This node helps decluttering the workspace by aggregating paths targeting the same destination node into a single path and by optionally hiding it. Very useful to keep the workspace clean and self explanatory.
A collector node can have any number of inbound connections and offers a single outbound connection whose curve can also be hidden.
For further details on connection paths and Collector nodes please read the Flowchart article.
Disconnect Node
This one disconnects an ongoing call.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
next | integer | Unique ID of the next node. |
DisconnectHandler Node
This node gets control of the flow in case the caller disconnects an ongoing call, therefore this node does not accept an inbound connection.
Note
There can only be a single such node in a flow.
Property | Value | Description |
---|---|---|
id | integer | Unique ID of the node. |
next | integer | Unique ID of the next node. |
ErrorHandler Node
This node gets control in case of specific errors not being able to be caught by the nodes' own error handling. Similar to the DisconnectHandler, this one does not accept any inbound connection either.
Script Code
The following sections detail the reserved JavaScript components, collections, objects, etc. that provide call and flow specific information for the custom script inside the nodes and templates.
Headers Collection
The HEADERS[]
collection contains the key SIP headers fo the ongoing call.
For example:
var thisTO = HEADERS['TO'];
Flowvars Collection
The flowvars[]
collection contains all the variables defined for the entire flow in the Variables toolbox.
Locals Collection
The LOCALS[]
collection contains all the variables passed into the node as parameters, including any output
types.
Announcements Object
The announcements
object stores all of the announcements providing the following functionalities:
- The
create()
method is used to add a new announcement programmatically. - The
anns
property is a collection of all existing announcements. - The
parameters
property is a collection of references to variables inserted into the TTS message.
/* Creating a new announcement programmatically */
myNewAnn = announcements.create();
myNewAnn.IsTTS = True;
myNewAnn.Interruptable = False;
myNewAnn.Data = 'Please enter your account id';
/* Modifying an existing announcement programmatically */
myAnn = announcements.anns[1];
ann.Parameters['v1'].value = 123;
When modifying the announcements programmatically, keep in mind that other nodes might also use these. In order to avoid affecting other nodes or templates, it is a good practice to create a copy of the target announcement and modify that. This way the original announcement can still stay unchanged for other uses.
Logging Object
The log
JavaScript object provides logging functionality, to print into the log file of the IVR Engine NodeService component.
log.Debug("This is a log message");
The following log message severities can be used, similar to the common logger mechanisms on the market:
- Debug
- Info
- Warn
- Error
- Fatal
Toolkit Object
The toolkit
factory object provides various functionalities.
toolkit.getJSonRetriever()
Generates a new JSonRetriever
object that can be used to exchange JSON formatted data structures with remote servers (e.g. Contact Expert) through HTTP POST or GET.
var js = toolkit.getJSonRetriever();
The JSonRetriever
object offers the following methods for the above purpose:
- JObject getData(string url, int timeout)
- JObject postData(string url, int timeout, string requestData)
- JObject postData(string url, int timeout, string requestData, string contentType)
toolkit.getUrlRetriever()
Generates a new UrlRetriever
object that can be used to exchange data with remote servers through HTTP POST or GET.
var url = toolkit.getUrlRetriever();
The UrlRetriever
object offers the following methods for the above purpose:
- String getData(string url, int timeout)
- String postData(string url, int timeout, string requestData)
- String postData(string url, int timeout, string requestData, string contentType)
toolkit.getTracer()
Generates a new Tracer
object to trace messages into a separate logfile.
var trace = toolkit.getTracer();
The Tracer
object offers the following methods for the above purpose:
- Void trace(object msg)
- Void trace(object context, object msg)