# Macro substitution

> Macro substitution lets you insert variables into an app during runtime execution of Conclude apps.

Canonical HTML page: https://conclude.io/doc/developer/yaml-macros/
Last updated: 2025-08-15

---

Macro substitution lets you insert variables into an app during runtime execution,
where ${variable} will be replaced with the actual value of the variable.

Let's first look at some common cases that illustrate the use of macros.

##### Example: Set a custom channel name

```yaml
channelName: "_bug-report_${YYYY}-${MM}-${DD}-${title}"
```

If somebody reports "Database error" on November 15, the channel name of the bug report
will be  "_bug-report_2020-11-15-database_error". Conclude automatically translates space
and other illegal channel name letters to underscore.

##### Example: Invite the initiator

```yaml
members: "#requests ${initiator}"
```

This will invite the initiator (the person who submitted a request for approval) to become
a member of the ticket channel. This technique is used by the 'approval' template.

##### Example: Set a default attribute value

```yaml
  - name: conclusion
    type: text
    label: Resolution
    defaultValue: "${bug_status.label}"
    placeholder: What was the resolution?
```

The 'bug' template sets the resolution (conclusion) text to the value of the
_bug_status_ select dropdown.

<hr>

#### Macro substitution is context sensitive

Macro expansion knows the context, and the substituted value depends on the context
in which the macro is used.

For example, ${initiator} will expand to different values depending on the context:
 - As a Slack alert or message: converted to a Slack user reference.
 - In the To/Cc:  of an email: The email address of the initiator.
 - In the body text of an email: The full name of the initiator.

#### Role-based macros

| Variable             | Description                                                                        |
| :------------------- | :--------------------------------------------------------------------------------- |
| **${initiator}**     | The user who created the ticket.                                                 |
| **${owner}**         | The owner of the ticket.                                                         |
| **${members}**       | The members of the ticket.                                                       |
| **${admins}**        | The admins of the app.                                                             |
| **${superusers}**    | The superusers of the app.                                                         |

For **initiator** and **owner** you can choose how to represent the user by adding a suffix:
- **.firstname** or **.lastname** to display the first or last name.
- **.mention** to display the name like Slack shows it.
- **.email** to display the email address of the user instead of the name.

```yaml
  - name: title
    type: string
    label: Expense report
    defaultValue: "Submitted by ${initiator.firstname}"
```

#### Attribute macros

| Variable               | Description                                                                      |
| :--------------------- | :------------------------------------------------------------------------------- |
| **${attribute}**       | Expands to the attribute value. Examples:e ${title} or ${conclusion}             |
| **${attribute.label}** | Expands to the label of a select attribute. Example ${severity.label}            |

#### Date and time macros

| Variable             | Description                               |
|:---------------------|:------------------------------------------|
| **${YYYY}**          | The current year (4 digits).              |
| **${YY}**            | The current year (2 digits).              |
| **${MM}**            | The current month (01..12).               |
| **${MMM}**           | The current month (Jan..Dec).             |
| **${MMMM}**          | The current month (January..December).    |
| **${DD}**            | The current date (00..31).                |
| **${DDD}**           | The current weekday (Sun..Sat)            |
| **${DDDD}**          | The current weekday (Sunday..Saturday)    |
| **${hh}**            | The current hour (00..23).                |
| **${mm}**            | The current minute (00..59).              |
| **${ss}**            | The current second (00..59).              |
| **${date[.format]}** | The current date with an optional format. |

Date formatting uses the [Go date formatting](https://programming.guide/go/format-parse-string-time-date-example.html),
where you can use a format specification based on the reference date **Mon Jan 2 15:04:05 MST 2006**.

```yaml
  - name: body
    type: text
    label: Incident details
    defaultValue: "Received on ${date.Jan 02 2006 at 15:04 pm}"
```

#### Ticket ID, URL etc.

| Variable             | Description                                                                         |
| :------------------- |:------------------------------------------------------------------------------------|
| **${ID}**            | The ticket ID, for example i3Ht7b89.                                              |
| **${SHORT_URL}**     | The short URL of the ticket, for example https://conclude.io/id/i3Ht7b89     |
| **${URL}**           | The URL of the ticket, e.g. https://conclude.io/id/A-52aoz-521oz-4gtoz       |
| **${channel}**       | The ticket channel, for example #_incident-38                                     |

