Implementing Dynamic Branching Logic in NICE CXone Studio Using ASSIGN and IF Actions
What You Will Build
- A CXone Studio flow that evaluates incoming caller attributes and assigns dynamic variables to route the conversation to specific skill groups.
- This implementation utilizes the CXone Studio visual interface and the underlying JSON configuration export.
- The tutorial covers JavaScript-like expression syntax within Studio actions and the corresponding JSON structure.
Prerequisites
- Access: NICE CXone Studio access with “Edit” permissions on Flows.
- Knowledge: Basic understanding of CXone Studio components (Triggers, Actions, Endpoints).
- Dependencies: No external SDKs are required for the Studio interface. However, if you are automating flow deployment via API, you will need the
@nice-dcv/cxone-sdkor direct HTTP access to theflowAPI endpoints. - Concept: Familiarity with CXone Data Objects (Customer, Conversation, Interaction).
Authentication Setup
For direct Studio usage, authentication is handled by your browser session in the CXone Admin console. If you are using the API to retrieve or save flow configurations (JSON), you must use OAuth 2.0.
// Example: Obtaining an OAuth Token for API-driven Flow Management
const axios = require('axios');
async function getCXoneToken(clientId, clientSecret, tenantUrl) {
const authUrl = `${tenantUrl}/api/v2/oauth2/token`;
const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
try {
const response = await axios.post(authUrl, {
grant_type: 'client_credentials'
}, {
headers: {
'Authorization': `Basic ${credentials}`,
'Content-Type': 'application/json'
}
});
return response.data.access_token;
} catch (error) {
console.error('Failed to obtain token:', error.response?.data || error.message);
throw error;
}
}
Required Scope: flow:read or flow:write if using the API to export/import flows.
Implementation
Step 1: Defining Variables with the ASSIGN Action
The ASSIGN action is the foundation of state management in a Studio flow. It allows you to capture data from the interaction, compute new values, or store intermediate results. In CXone Studio, variables are scoped to the Interaction or the Flow.
Scenario
We need to extract the area code from the caller’s phone number to determine their region.
Studio Configuration
- Add an ASSIGN action to your flow canvas.
- Set the Variable Name to
regionCode. - Set the Value Type to
String. - In the Value field, use an expression.
Expression Syntax
CXone Studio uses a JavaScript-like expression engine. You can access data objects using dot notation.
// Expression to extract the first 3 digits of the phone number
// Assuming the phone number is stored in the 'customer' object under 'phoneNumbers'
// Note: Real-world phone numbers may have formatting. This example assumes a clean string.
// Check if phone number exists and has enough digits
if (customer.phoneNumbers.length > 0) {
const phone = customer.phoneNumbers[0].number;
// Remove non-digit characters
const cleanPhone = phone.replace(/\D/g, '');
if (cleanPhone.length >= 3) {
return cleanPhone.substring(0, 3);
}
}
return '000'; // Default value
JSON Representation
If you export the flow or use the API, the ASSIGN action appears in the JSON as follows:
{
"id": "assign-region-code",
"type": "assign",
"name": "Assign Region Code",
"properties": {
"variableName": "regionCode",
"valueType": "STRING",
"value": {
"type": "expression",
"expression": "customer.phoneNumbers.length > 0 ? customer.phoneNumbers[0].number.replace(/\\D/g, '').substring(0, 3) : '000'"
}
},
"next": {
"success": "if-region-check"
}
}
Critical Note: The expression field must be a valid JavaScript snippet. Avoid side effects. The expression should return a value, not modify state directly.
Step 2: Implementing Conditional Logic with the IF Action
The IF action evaluates a boolean expression and branches the flow accordingly. It has two primary outcomes: true and false.
Scenario
Route callers from area code 212 (New York) to the “NY_Support” skill group, and all others to “General_Support”.
Studio Configuration
- Add an IF action after the
ASSIGNaction. - Set the Condition to an expression.
Expression Syntax
// Check if the assigned variable matches the target area code
flow.regionCode === '212'
JSON Representation
{
"id": "if-region-check",
"type": "if",
"name": "Check Region",
"properties": {
"condition": {
"type": "expression",
"expression": "flow.regionCode === '212'"
}
},
"next": {
"true": "route-ny",
"false": "route-general"
}
}
Best Practice: Always define a false path. If omitted, the flow may terminate unexpectedly or fall through to a default endpoint, leading to silent failures in production.
Step 3: Handling Complex Conditions and Nested Logic
Real-world routing often requires multiple conditions. You can combine checks using logical operators (&&, ||).
Scenario
Route to “VIP_Support” if the customer is tagged as vip AND the region is 212. Otherwise, proceed to standard routing.
Expression Syntax
// Check multiple conditions
customer.tags.includes('vip') && flow.regionCode === '212'
Nested IF Actions
If you need more than two branches, chain IF actions or use a SWITCH action (if available in your Studio version). Chaining IF actions is the most portable method.
{
"id": "if-vip-check",
"type": "if",
"name": "Check VIP Status",
"properties": {
"condition": {
"type": "expression",
"expression": "customer.tags.includes('vip') && flow.regionCode === '212'"
}
},
"next": {
"true": "route-vip",
"false": "if-region-check" // Fall through to previous region check
}
}
Error Handling: If customer.tags is null, includes() will throw an error. Always guard against null values.
// Safe check for null/undefined
(customer.tags && customer.tags.includes('vip')) && flow.regionCode === '212'
Step 4: Assigning Dynamic Endpoints
The final step is to use the ASSIGN action to set the endpoint variable, which Studio uses to route the conversation.
Studio Configuration
- Add an ASSIGN action.
- Set Variable Name to
endpoint. - Set Value Type to
Endpoint. - Use an expression to select the endpoint.
Expression Syntax
// Return the endpoint ID based on previous logic
// This assumes you have already determined the target skill group
if (flow.regionCode === '212') {
return 'endpoint-nyc-support'; // Replace with actual endpoint ID
} else {
return 'endpoint-general-support';
}
Alternatively, use a SWITCH action if your Studio version supports it, which maps values to endpoints directly.
Complete Working Example
Below is a complete JSON snippet representing a flow that:
- Assigns the region code.
- Checks if the region is
212. - Routes to the appropriate endpoint.
{
"id": "flow-region-routing",
"name": "Region-Based Routing",
"version": "1.0",
"steps": [
{
"id": "assign-region",
"type": "assign",
"name": "Extract Region Code",
"properties": {
"variableName": "regionCode",
"valueType": "STRING",
"value": {
"type": "expression",
"expression": "customer.phoneNumbers.length > 0 ? customer.phoneNumbers[0].number.replace(/\\D/g, '').substring(0, 3) : '000'"
}
},
"next": {
"success": "check-region"
}
},
{
"id": "check-region",
"type": "if",
"name": "Is New York Region?",
"properties": {
"condition": {
"type": "expression",
"expression": "flow.regionCode === '212'"
}
},
"next": {
"true": "assign-nyc-endpoint",
"false": "assign-general-endpoint"
}
},
{
"id": "assign-nyc-endpoint",
"type": "assign",
"name": "Set NYC Endpoint",
"properties": {
"variableName": "endpoint",
"valueType": "ENDPOINT",
"value": {
"type": "constant",
"value": "endpoint-nyc-support-id"
}
},
"next": {
"success": "transfer-call"
}
},
{
"id": "assign-general-endpoint",
"type": "assign",
"name": "Set General Endpoint",
"properties": {
"variableName": "endpoint",
"valueType": "ENDPOINT",
"value": {
"type": "constant",
"value": "endpoint-general-support-id"
}
},
"next": {
"success": "transfer-call"
}
},
{
"id": "transfer-call",
"type": "transfer",
"name": "Transfer to Agent",
"properties": {
"endpoint": "endpoint"
},
"next": {
"success": "end-flow",
"failure": "end-flow"
}
},
{
"id": "end-flow",
"type": "end",
"name": "End Flow"
}
]
}
Note: Replace endpoint-nyc-support-id and endpoint-general-support-id with actual Endpoint IDs from your CXone instance. You can find these in the Admin Console under Admin > Routing > Endpoints.
Common Errors & Debugging
Error: Expression evaluation failed: TypeError: Cannot read property 'length' of undefined
- Cause: The data object (e.g.,
customer.phoneNumbers) is null or undefined. - Fix: Add null checks in your expression.
// Incorrect
customer.phoneNumbers.length
// Correct
(customer.phoneNumbers && customer.phoneNumbers.length > 0) ? customer.phoneNumbers[0].number : ''
Error: Invalid expression syntax
- Cause: Syntax error in the JavaScript expression (e.g., missing parenthesis, incorrect operator).
- Fix: Validate the expression using a JavaScript linter or test it in a browser console. Ensure all strings are quoted and operators are correct.
Error: Endpoint not found
- Cause: The
endpointvariable is assigned an invalid ID or a non-existent endpoint. - Fix: Verify the Endpoint ID in the CXone Admin Console. Ensure the endpoint is active and available for routing.
Error: Flow execution timeout
- Cause: The flow is stuck in a loop or waiting for an action that never completes.
- Fix: Check for circular references in
nextpaths. Ensure allIFactions have bothtrueandfalsepaths defined.