Expressions
Expressions allow you to use JavaScript within SWML variables to transform data, perform calculations, and implement logic. Instead of static values, you can dynamically construct values based on call data, user input, and calculations.
For information about variable scopes and basic access patterns, see the Variables Reference. For template transformation functions, see the Template Functions Reference.
What are expressions?
Expressions use the ${...} syntax and support JavaScript for dynamic value construction. Any JavaScript that evaluates to a value can be used inside these delimiters. Both syntaxes work identically.
SWML uses the Google V8 JavaScript engine (version 6 and later) to evaluate expressions. For detailed JavaScript feature support, refer to the V8 documentation.
Expressions are evaluated at runtime and replaced with their computed values.
Variable access in expressions
All SWML variables are accessible within JavaScript expressions. You can reference them with or without scope prefixes:
When you access a variable without a prefix, the expression engine checks scopes in this order: vars, then envs, then call.
Using explicit prefixes like vars. or call. is recommended for clarity, especially when variable names might exist in multiple scopes.
When to use expressions vs. server-side logic
Expressions are evaluated at runtime within SWML and work well for simple transformations like formatting phone numbers or calculating totals. The question of when to use expressions versus server-side logic depends largely on your deployment model.
Serverless (dashboard-hosted) SWML
When hosting SWML directly in the SignalWire Dashboard, expressions become your primary tool for dynamic behavior.
You can use them to transform call data like extracting area codes with ${call.from.substring(0, 3)}, perform calculations such as ${vars.unit_price * parseInt(vars.quantity)}, or make simple decisions with ternary operators.
If you need complex logic in serverless mode, use the request method to fetch data from a server during call execution.
The response data becomes available as variables that you can then manipulate with expressions.
Server-based (external URL) SWML
Serving SWML from your own web server opens up more architectural options. This is where you should handle database queries, external API calls to your business systems, and any complex business logic that requires authentication or heavy data processing.
The general pattern is to do the heavy lifting server-side before generating the SWML response, then use expressions for runtime transformations. For example, you might query your database to fetch customer information, call your internal billing service to get their account status, and insert that data directly into the SWML. Then expressions handle runtime concerns like formatting that data or calculating values based on user input collected during the call.
The key principle is to use server-side logic to prepare and fetch data, then use expressions for transformations and dynamic behavior that happen during the call itself.
Common expression patterns
String operations
Transform and manipulate text using JavaScript string methods:
Common methods: substring(), toUpperCase(), toLowerCase(), trim(), replace(), split(), join()
Arithmetic and math
Perform calculations using standard JavaScript operators and Math functions:
Use operators: +, -, *, /, % and Math functions: Math.round(), Math.ceil(), Math.floor(), Math.max(), Math.min()
Conditional logic
Use ternary operators and comparisons to make decisions:
Use comparisons: ==, !=, >, <, >=, <= and logical operators: &&, ||
Array operations
Work with arrays using JavaScript array methods:
Common methods: .length, .join(), .includes(), bracket notation for access
Type conversions
Convert between strings, numbers, and booleans:
Use: parseInt(), parseFloat(), .toString(), Boolean()
Expression limitations
Expressions are designed for quick data transformations during calls. They work great for formatting strings, performing calculations, and making simple decisions, but they’re intentionally constrained to keep your calls running smoothly.
You can’t create custom functions with the function keyword or arrow syntax. Instead, rely on JavaScript’s built-in methods like string operations, Math functions, and array methods:
Loops like for and while aren’t available, but you can use array methods for most transformation needs. Methods like .map(), .filter(), and .reduce() handle common iteration patterns:
Simple property access like .length, .name, .value, etc. on arrays or strings require parentheses to evaluate correctly.
Without them, the expression is treated as a variable lookup rather than JavaScript.
Method Calls with parentheses work directly:
Expressions execute synchronously, so you can’t use async, await, or make API calls directly. For operations that need external data, use the request method to fetch data first, then transform the results with expressions.
Keep expressions under 1,024 characters and expect them to complete within 150ms. If you’re hitting these limits, it’s usually a sign that the logic belongs in your server code rather than inline in SWML.