Formatting Phone Numbers in Genesys Cloud Architect Using Expression Functions
What You Will Build
- This tutorial demonstrates how to transform a raw E.164 phone number string (e.g.,
+14155552671) into a standard US display format (e.g.,(415) 555-2671) directly within a Genesys Cloud Architect flow. - This implementation uses the native Architect Expression Editor and built-in string manipulation functions (
substring,concat,replace). - The logic is implemented entirely within the platform’s visual workflow, requiring no external API calls or custom code execution.
Prerequisites
- Access: A Genesys Cloud organization with Admin or Architect access.
- Knowledge: Basic understanding of Architect flow design (Triggers, Actions, Conditions).
- Environment: A browser with access to the Genesys Cloud Admin portal.
- Input Data: A string variable containing an E.164 formatted phone number (e.g., from a Web Chat widget, IVR input, or CRM integration).
Authentication Setup
This task does not require external authentication or OAuth tokens. It relies on the internal expression engine of the Genesys Cloud Architect platform. You must be logged into the Genesys Cloud Admin interface with sufficient permissions to edit Architect flows.
Implementation
Step 1: Understanding the Input Data Structure
Before writing the expression, you must understand the structure of the input. E.164 numbers typically follow the pattern +[CountryCode][AreaCode][PhoneNumber]. For US numbers, this is +1 followed by 10 digits.
If your input variable is {{trigger.phoneNumber}} and it contains +14155552671, the character indices are as follows:
- Index 0:
+ - Index 1:
1(Country Code) - Index 2-4:
415(Area Code) - Index 5-9:
5552671(Local Number)
Note: Genesys Cloud Architect expressions use 0-based indexing for string functions, similar to JavaScript and Python.
Step 2: Constructing the Expression Logic
We will build the expression in layers using the Architect Expression Editor. The goal is to extract the area code and the remaining seven digits, then wrap them in parentheses and hyphens.
Extracting the Area Code
We need characters at indices 2, 3, and 4. We can use the substring function.
substring(string, start, length)
// Extract Area Code (3 characters starting at index 2)
substring({{trigger.phoneNumber}}, 2, 3)
For input +14155552671, this returns "415".
Extracting the Local Number
We need the remaining 7 digits starting at index 5.
// Extract Local Number (7 characters starting at index 5)
substring({{trigger.phoneNumber}}, 5, 7)
For input +14155552671, this returns "5552671".
Formatting the Local Number
The local number needs a hyphen after the third digit (e.g., 555-2671). We can split the local number into two parts:
- First 3 digits:
substring(..., 5, 3)→"555" - Last 4 digits:
substring(..., 8, 4)→"2671"
Now we have all components:
- Area Code:
substring({{trigger.phoneNumber}}, 2, 3) - Prefix:
substring({{trigger.phoneNumber}}, 5, 3) - Line Number:
substring({{trigger.phoneNumber}}, 8, 4)
Step 3: Combining Components with Concatenation
We use the concat function to join these substrings with static characters (, ), space, and -.
concat(
"(",
substring({{trigger.phoneNumber}}, 2, 3),
") ",
substring({{trigger.phoneNumber}}, 5, 3),
"-",
substring({{trigger.phoneNumber}}, 8, 4)
)
This expression produces (415) 555-2671.
Step 4: Handling Edge Cases and Validation
Real-world data is rarely perfect. The number might not be 11 characters long, might contain spaces, or might be missing the country code. We should wrap the logic in a conditional check to ensure the input is valid before formatting.
We can check the length of the string. A valid US E.164 number is 11 characters.
if(
length({{trigger.phoneNumber}}) == 11,
concat(
"(",
substring({{trigger.phoneNumber}}, 2, 3),
") ",
substring({{trigger.phoneNumber}}, 5, 3),
"-",
substring({{trigger.phoneNumber}}, 8, 4)
),
{{trigger.phoneNumber}} // Return original if invalid
)
Step 5: Cleaning Input Data
If the input might contain non-numeric characters (like spaces or dashes from a CRM), we should clean it first. We can use replace to remove non-digits, but Architect does not have a native “remove non-numeric” regex replace. However, we can strip common characters if we know them.
A more robust approach for cleaning is to ensure the input is purely numeric before the length check. If you are receiving data from an external API, it is best to clean it before it enters the flow. If you must clean it inside Architect, you can chain replace functions:
// Remove spaces and dashes
cleanedNumber = replace(replace({{trigger.phoneNumber}}, " ", ""), "-", "")
Then apply the formatting logic to cleanedNumber.
Complete Working Example
Below is the complete expression you can copy and paste into any Architect Action that accepts an expression (e.g., “Set Variable”, “Send Email”, “Log Message”).
if(
length(replace(replace({{trigger.phoneNumber}}, " ", ""), "-", "")) == 11,
concat(
"(",
substring(replace(replace({{trigger.phoneNumber}}, " ", ""), "-", ""), 2, 3),
") ",
substring(replace(replace({{trigger.phoneNumber}}, " ", ""), "-", ""), 5, 3),
"-",
substring(replace(replace({{trigger.phoneNumber}}, " ", ""), "-", ""), 8, 4)
),
{{trigger.phoneNumber}}
)
Breakdown of the Complete Expression
replace(replace({{trigger.phoneNumber}}, " ", ""), "-", ""): Removes spaces and hyphens from the input. This is repeated three times because Architect does not support variable assignment within a single expression block in all contexts. In a “Set Variable” action, you could clean it first, then format it in a second step for readability.length(...) == 11: Checks if the cleaned number is exactly 11 digits (1 country code + 10 local digits).concat(...): If true, constructs the formatted string.{{trigger.phoneNumber}}: If false, returns the original input unchanged to prevent errors.
Alternative: Using a Set Variable Action for Readability
If the expression above is too complex for your use case, break it into two steps in the Architect flow:
Step 1: Clean and Validate
Action: Set Variable
Variable Name: cleanedPhone
Value:
replace(replace({{trigger.phoneNumber}}, " ", ""), "-", "")
Step 2: Format
Action: Set Variable
Variable Name: formattedPhone
Value:
if(
length({{flow.cleanedPhone}}) == 11,
concat(
"(",
substring({{flow.cleanedPhone}}, 2, 3),
") ",
substring({{flow.cleanedPhone}}, 5, 3),
"-",
substring({{flow.cleanedPhone}}, 8, 4)
),
{{flow.cleanedPhone}}
)
Common Errors & Debugging
Error: Invalid Character Offset
- What causes it: The
substringfunction throws an error if the start index is greater than the string length or if the length parameter exceeds the remaining characters. - How to fix it: Ensure the input string is at least 11 characters long before calling
substring. Use theif(length(...) == 11, ...)pattern shown above. - Code showing the fix:
if(length({{input}}) >= 11, substring({{input}}, 2, 3), "ERR")
Error: Expression Too Complex
- What causes it: Architect has a limit on expression complexity and length. Deeply nested
concatandreplacecalls can exceed this. - How to fix it: Break the logic into multiple “Set Variable” actions as shown in the “Alternative” section above.
- Code showing the fix:
Instead of one giant expression, use:// Action 1 flow.area = substring(flow.cleanedPhone, 2, 3) // Action 2 flow.prefix = substring(flow.cleanedPhone, 5, 3) // Action 3 flow.line = substring(flow.cleanedPhone, 8, 4) // Action 4 flow.formatted = concat("(", flow.area, ") ", flow.prefix, "-", flow.line)
Error: Non-US Numbers
- What causes it: This logic assumes a US country code (
+1) and 10-digit local number. If you pass a UK number (+44...), the indices will be incorrect. - How to fix it: Add a condition to check the country code before formatting.
- Code showing the fix:
if( substring({{flow.cleanedPhone}}, 0, 2) == "+1", // US Formatting Logic concat("(", substring({{flow.cleanedPhone}}, 2, 3), ") ..."), // Non-US: Return as-is or use different logic {{flow.phoneNumber}} )