Variables in macros
Every variable the macro editor offers, the store fields you can type yourself, and the filters that format dates and fill gaps.
On this page
A variable is a placeholder in double braces, such as {{ticket.customer.firstname}}. When the macro goes into a reply, each one is swapped for the value on that ticket, so "Hi {{ticket.customer.firstname}}" reaches Jordan as "Hi Jordan". A variable with nothing behind it, such as a tracking number on an order that has not shipped, comes out blank.
Add a variable#
Open the macro in Workflows > Macros.
Click in the Response box where the value should go.
Click Insert variable above the box and pick one. The menu shows each variable's name and the text it inserts.
The same menu sits above the text of an Add an internal note action, so notes can use variables too. The Preview beside the editor fills every variable from a sample ticket, which is the quickest way to check spelling and spacing.
The variables in the menu#
| In the menu | Inserts | What the customer sees |
|---|---|---|
| Customer first name | {{ticket.customer.firstname}} | The customer's first name, such as Jordan |
| Customer last name | {{ticket.customer.lastname}} | Their last name |
| Customer full name | {{ticket.customer.name}} | First and last name together |
| Customer email | {{ticket.customer.email}} | Their email address |
| Ticket number | {{ticket.id}} | The ticket's number, as shown in its address |
| Ticket subject | {{ticket.subject}} | The ticket's subject line |
| Agent first name | {{current_user.firstname}} | The first name of the agent applying the macro |
| Agent last name | {{current_user.lastname}} | That agent's last name |
| Agent full name | {{current_user.name}} | That agent's full name |
| Agent email | {{current_user.email}} | That agent's sign-in email |
| First message | {{ticket.first_message.body_text}} | The text of the first message on the ticket |
| Latest message | {{ticket.last_message.body_text}} | The text of the newest message the customer can see, skipping internal notes |
| Helpdesk name | {{ticket.account.name}} | Your helpdesk's name, such as your store name |
| Latest order number | …orders[0].name | The order number, such as #1042 |
| Latest order date | …orders[0].created_at|datetime_format("MMMM d, YYYY") | The day the order was placed, such as November 2, 2026 |
| Latest order status page | …orders[0].order_status_url | The link to Shopify's order status page |
| Latest order tracking number | …orders[0].fulfillments[0].tracking_number | The first shipment's tracking number |
| Latest order tracking link | …orders[0].fulfillments[0].tracking_url | The carrier's tracking link for that shipment |
| Latest order delivery status | …orders[0].fulfillments[0].shipment_status | The carrier's state, such as in_transit or delivered |
| Latest order shipping date | …orders[0].fulfillments[0].created_at|datetime_format("MMMM d, YYYY") | The day the first shipment was created |
| Latest order ship-to street | …orders[0].shipping_address.address1 | First line of the delivery address |
| Latest order ship-to apartment or suite | …orders[0].shipping_address.address2 | Second line of the address |
| Latest order ship-to city | …orders[0].shipping_address.city | City |
| Latest order ship-to state | …orders[0].shipping_address.province | State or province, written out |
| Latest order ship-to ZIP code | …orders[0].shipping_address.zip | ZIP or postal code |
| Latest order ship-to country | …orders[0].shipping_address.country | Country, written out |
In the table, … stands for ticket.customer.integrations.shopify, the customer's data from your store; the editor inserts the full path for you. Order variables need a connected Shopify store and read the customer's most recent order; they are blank for a customer with no orders.
If a macro with order variables goes into a reply to someone with no store orders, the agent sees a warning that the order fields are empty, so they can fill them in before sending.
Type a variable the menu does not list#
You can type any of these into the response yourself, inside double braces. As above, … stands for ticket.customer.integrations.shopify.
| Variable | What it holds |
|---|---|
ticket.channel | Where the ticket came in: email, chat, contact_form, help-center and so on |
ticket.status, ticket.priority | The ticket's status and priority |
ticket.created_datetime | When the ticket was opened (format it with datetime_format) |
ticket.assignee_user.name | The agent the ticket is assigned to |
ticket.assignee_team.name | The team the ticket is assigned to |
…customer.first_name, …customer.last_name | The name on the customer's Shopify account |
…customer.phone | The phone number on their Shopify account |
…customer.orders_count | How many orders they have placed |
…customer.total_spent | What they have spent in total, in your store's currency |
…customer.default_address.city | City of their default address (also address1, zip, province_code, country_code) |
For an order, start with …orders[0]. and add one of these. Use orders[1] for the order before the latest one.
| Add | What it holds |
|---|---|
financial_status | Payment state, such as paid, refunded or partially_refunded |
fulfillment_status | Shipping state, such as fulfilled or unfulfilled |
total_price | The order total, as a number without the currency sign |
currency | The currency code of that total, such as USD |
cancelled_at | When the order was cancelled, empty if it was not |
line_items[0].title | The first product's name; line_items[1] is the second product |
line_items[0].variant_title | That product's variant, such as a size or scent |
line_items[0].quantity | How many of it were ordered |
fulfillments[0].tracking_company | The carrier's name |
fulfillments[0].estimated_delivery_at | The carrier's delivery estimate, when Shopify has one |
refunds[0].amount | The amount of the first refund |
refunds[0].created_at | When that refund was made |
A path that leads nowhere is not an error. It prints nothing, so check new variables in the preview or on a test ticket.
Filters#
Add a filter after the path with a vertical bar.
| Filter | Example | Result |
|---|---|---|
default("…") | {{ticket.customer.firstname | default("there")}} | "there" when the ticket has no first name |
datetime_format("…") | {{…orders[0].created_at | datetime_format("MMM d")}} | Nov 2 |
upper | {{…orders[0].name | upper}} | The value in capital letters |
lower | {{ticket.customer.email | lower}} | The value in small letters |
Dates are written in your helpdesk's time zone. The pieces datetime_format understands:
| Piece | Prints | Piece | Prints |
|---|---|---|---|
YYYY / YY | 2026 / 26 | dddd / ddd | Monday / Mon |
MMMM / MMM | November / Nov | HH / H | Hour, 24-hour clock |
MM / M | Month number, with or without a leading zero | hh / h | Hour, 12-hour clock |
DD or dd / D or d | Day of the month, with or without a leading zero | mm, ss | Minutes, seconds |
A / a | AM or PM / am or pm | [text] | The text in brackets, as written |
So datetime_format("dddd, MMMM d") gives "Monday, November 2", and datetime_format("d/M/YYYY") gives "2/11/2026". Ordinal days ("2nd") are not available.
Variables in rules#
A rule's Send a reply and Add an internal note actions use the same variables, minus the four agent ones: no agent applies a rule, so the menu leaves them out. The rule acts as your helpdesk's Automation account. See Rule conditions and actions reference.
Macros written for Gorgias#
Variables copied from Gorgias macros read the same Shopify data here. A few differ:
A product in an order is
line_items[0].title, notline_items[0].name.Counting back from the newest message, as in
messages[-1], does not work. Use Latest message instead.current_user.bioand variables for BigCommerce, Magento or WooCommerce stores print nothing.
Related articles
- Create and manage macrosWrite a saved reply once, apply it from any ticket, and keep the macro list tidy with search, filters, archiving and duplicates.
- Macro actionsWhat a macro can change on a ticket when the reply goes out, how to set each action up, and what to use for jobs a macro cannot do.
- Orders beside each ticketRead a customer's Shopify orders, payment and shipping status, tracking and refunds in the ticket's side panel, and know how fresh they are.
- Rule conditions and actions referenceEvery field a rule can check, the operators each one offers, how matching works, and every action a rule can take.
Still stuck?
Write to the Growth Dept team and a person answers. Say which helpdesk you work in and what you were trying to do.