# Expressions

Inside `{{ ... }}` you can do more than insert a value — you can calculate, compare or pick text based on a condition:

```
{{ $age >= 18 ? "Welcome!" : "Access from age 18" }}
10% off: ${{ $price * 0.9 }}
{{ upper(first_name) ~ ", hello!" }}
```

## What an expression is made of

| What | How to write it | Example |
|---|---|---|
| Contact variable | `$name` | `$city` |
| Variable with spaces in its name | `var("name")` | `var("Client name")` |
| Contact data | name without `$` | `first_name`, `phone` |
| Global variable | `global("name")` | `global("Rate (USD)")` |
| Text | in quotes `"..."` or `'...'` | `"Good afternoon"` |
| Number | digits, decimal part after a dot | `10`, `0.9` |
| Boolean | `true`, `false` | |
| Empty value | `null` | |
| Function | `name(arguments)` | `round($price, 2)` |

Nothing is replaced inside quotes: `{{ "price $a" }}` outputs `price $a`.

## Arithmetic

| Operator | Operation | Example | Result |
|---|---|---|---|
| `+` | addition | `{{ 2 + 3 }}` | `5` |
| `-` | subtraction | `{{ 10 - 4 }}` | `6` |
| `*` | multiplication | `{{ 3 * 4 }}` | `12` |
| `/` | division | `{{ 10 / 4 }}` | `2.5` |
| `%` | remainder | `{{ 10 % 3 }}` | `1` |
| `**` | power | `{{ 2 ** 10 }}` | `1024` |

Parentheses change the order of operations: `{{ ($price + $delivery) * 2 }}`.

Decimals are shown without extra digits: `{{ 0.1 + 0.2 }}` gives `0.3`. To round, use [`round`](03-functions.md#math); to format with separators, use [`number_format`](03-functions.md#text).

## Comparisons

| Operator | Meaning |
|---|---|
| `==` | equal |
| `!=` | not equal |
| `>`, `>=` | greater than, greater than or equal |
| `<`, `<=` | less than, less than or equal |

If both sides are numbers — even written as text, like variable values — they are compared as numbers: `"10" > 9` is true.

A comparison on its own outputs `true` or `false`: `{{ $age >= 18 }}`.

## Logic

| Operator | Meaning |
|---|---|
| `and` or `&&` | and |
| `or` or `\|\|` | or |
| `not` or `!` | not |

```
{{ $age >= 18 and $city == "London" ? "Visit our office" : "We work online" }}
```

## Condition

`condition ? if_yes : if_no` — picks one of two options:

```
{{ $points >= 100 ? "You've earned a gift" : (100 - $points) ~ " points to go for a gift" }}
```

The short form `value ?: fallback` outputs the value if it isn't empty, otherwise the fallback:

```
Hello, {{ first_name ?: "friend" }}!
```

## Fallback for missing data

`value ?? fallback` — if there is no value at all (the contact has no phone number, the variable isn't set), the fallback is inserted:

```
Phone: {{ phone ?? "not provided" }}
```

## Working with text

| Operator | Operation | Example |
|---|---|---|
| `~` | join text | `{{ first_name ~ " " ~ last_name }}` |
| `contains` | contains | `{{ $answer contains "yes" ? "Great!" : "Too bad" }}` |
| `starts with` | starts with | `{{ phone starts with "+44" ? "UK" : "Another country" }}` |
| `ends with` | ends with | `{{ email ends with "@gmail.com" }}` |
| `in` | is in a list | `{{ $city in ["London", "Manchester"] ? "Delivery available" : "Pickup only" }}` |
| `not in` | is not in a list | `{{ $plan not in ["pro", "business"] }}` |

`contains`, `starts with` and `ends with` are case-sensitive. To ignore case, convert the text to one case: `{{ lower($answer) contains "yes" }}`.

## Functions inside expressions

Functions can be nested and combined with operators:

```
{{ capitalize(lower(var("Client name"))) }}
{{ round(($price + $delivery) * 0.9, 2) }}
${{ number_format(global("Rate (USD)") * $total, 2) }}
```

See the [function reference](https://support.watbot.org/chatbots/templates/functions) for the full list.

## What you can't do

Expressions have no loops, no assignments and no access to the platform's internal data — only operators and functions from the reference. See [Errors and limits](https://support.watbot.org/chatbots/templates/errors) for details.
