Liquid variables in flow actions
When you're building flows in Mantle, you can use Liquid variables to make your actions dynamic and personalized. Instead of sending the same message to everyone, you can pull in customer names, subscription details, action results, and more - all automatically.
Think of Liquid variables as placeholders that get filled in with real data when your flow runs. Write {{ customer.name }} and it becomes "Acme Corp" when that customer's flow triggers. It's like mail merge, but for your entire automation system.
How Liquid variables work
Liquid variables use double curly braces to mark dynamic content. When your flow runs, Mantle replaces these variables with actual values from your customer data, previous actions, or trigger events.
Basic syntax:
{{ variable.property }}
For nested properties, use dots to navigate:
{{ customer.subscription.plan.name }}
You can also use Liquid filters and conditionals for more advanced logic:
{% if customer.hasReviewed %}Thank you for your review!{% endif %}
Customer variables
These variables give you access to information about the customer the flow is running for. Available in all flow actions.
Basic customer info
{{ customer.name }}- The customer's name{{ customer.email }}- The customer's email address{{ customer.id }}- The customer's Mantle ID{{ customer.url }}- The customer's website URL{{ customer.shopifyDomain }}- The customer's Shopify domain{{ customer.shopifyShopId }}- The customer's Shopify shop ID{{ customer.shopifyPlanName }}- The customer's Shopify plan name{{ customer.industry }}- The customer's industry{{ customer.mantleUrl }}- Direct link to the customer's profile in Mantle
Financial metrics
{{ customer.averageMonthlyRevenue }}- Average monthly revenue{{ customer.lifetimeValue }}- Lifetime value{{ customer.last30Revenue }}- Revenue from the last 30 days
Subscription details
{{ customer.subscription.plan.name }}- Current subscription plan name{{ customer.subscription.plan.amount }}- Plan amount{{ customer.subscription.plan.currencyCode }}- Currency code (e.g., "USD"){{ customer.subscription.plan.interval }}- Billing interval (e.g., "monthly", "yearly")
Reviews
Access app store review data for your customers:
{{ customer.hasReviewed }}- Whether the customer has left a review (true/false){{ customer.reviews }}- Array of all reviews from this customer{{ customer.reviews[0].rating }}- First review's star rating (1-5){{ customer.reviews[0].content }}- First review's text content{{ customer.reviews[0].date }}- First review's date (ISO format)
Example - Send a thank you when someone leaves a 5-star review:
{% if customer.reviews[0].rating == 5 %}Thanks for the amazing review, {{ customer.name }}! We're thrilled you're enjoying the app.{% endif %}
Tags and custom fields
{{ customer.tags }}- Array of customer tags{{ customer.customFields }}- Object containing all custom fields{{ customer.customFields.yourFieldName }}- Access a specific custom field
Affiliate referrals
{{ customer.affiliateReferrals }}- Array of affiliate referrals for this customer{{ customer.affiliateReferrals[0].affiliate }}- The referring affiliate's name{{ customer.affiliateReferrals[0].app }}- The app they were referred to{{ customer.affiliateReferrals[0].createdAt }}- When the referral was created
Current invoice
{{ customer.currentInvoice.status }}- Invoice status{{ customer.currentInvoice.total }}- Invoice total amount{{ customer.currentInvoice.subtotal }}- Invoice subtotal{{ customer.currentInvoice.currencyCode }}- Currency code{{ customer.currentInvoice.periodStart }}- Billing period start date{{ customer.currentInvoice.periodEnd }}- Billing period end date{{ customer.currentInvoice.hostedInvoiceUrl }}- Link to view the invoice{{ customer.currentInvoice.number }}- Invoice number
Example:
Welcome {{ customer.name }}! Your current plan is {{ customer.subscription.plan.name }}.
App variables
Information about the app the flow is running for:
{{ app.id }}- The app's Mantle ID{{ app.name }}- The app's name
App installation variables
Details about the customer's specific app installation:
{{ appInstallation.id }}- Installation ID{{ appInstallation.myshopifyDomain }}- The myshopify.com domain{{ appInstallation.platformId }}- Platform-specific installation ID{{ appInstallation.averageMonthlyRevenue }}- Average monthly revenue for this installation{{ appInstallation.lifetimeValue }}- Lifetime value for this installation{{ appInstallation.last30Revenue }}- Last 30 days revenue{{ appInstallation.last30BilledUsage }}- Last 30 days billed usage{{ appInstallation.customFields }}- App-installation-specific custom fields
Usage event variables
When your flow is triggered by a usage event, you can access details about that event:
{{ usageEvent.id }}- The event's unique ID{{ usageEvent.name }}- The name of the usage event{{ usageEvent.timestamp }}- When the event occurred{{ usageEvent.properties }}- Any properties attached to the event{{ usageEvent.properties.yourProperty }}- Access a specific event property
Example:
Customer {{ customer.name }} just triggered {{ usageEvent.name }} at {{ usageEvent.timestamp }}
Uninstall event variables
When a customer uninstalls your app, you can access details about the uninstall:
{{ uninstall.reason }}- The reason they provided (in original language){{ uninstall.reasonCode }}- The primary reason code{{ uninstall.reasonCodes }}- Array of all reason codes selected{{ uninstall.reasonEnglish }}- The reason translated to English{{ uninstall.reasonLanguage }}- The original language of the reason{{ uninstall.description }}- Additional description (in original language){{ uninstall.descriptionEnglish }}- Description translated to English{{ uninstall.descriptionLanguage }}- The original language of the description{{ uninstall.secondsSinceLastInstall }}- Seconds since their most recent install{{ uninstall.secondsSinceFirstInstall }}- Seconds since their first ever install
Example:
{{ customer.name }} uninstalled after {{ uninstall.secondsSinceLastInstall | divided_by: 86400 }} days. Reason: {{ uninstall.reasonEnglish }}
Invoice event variables
When your flow is triggered by an invoice event (payment succeeded, failed, etc.):
{{ invoice.status }}- Invoice status (paid, failed, etc.){{ invoice.total }}- Total amount{{ invoice.subtotal }}- Subtotal amount{{ invoice.currencyCode }}- Currency code{{ invoice.periodStart }}- Billing period start{{ invoice.periodEnd }}- Billing period end{{ invoice.hostedInvoiceUrl }}- Link to view the invoice{{ invoice.number }}- Invoice number{{ invoice.failureCode }}- Payment failure code (if failed){{ invoice.failureMessage }}- Payment failure message (if failed)
Ticket variables
When your flow is triggered by a support ticket event:
Basic ticket info
{{ ticket.id }}- The ticket's unique ID{{ ticket.subject }}- The ticket subject line{{ ticket.subjectOrBody }}- Subject if available, otherwise first message content{{ ticket.status }}- Current status (open, pending, closed, etc.){{ ticket.priority }}- Ticket priority{{ ticket.tags }}- Array of ticket tags{{ ticket.mantleUrl }}- Link to the ticket in Mantle{{ ticket.messageCount }}- Total number of messages
Customer/contact info
{{ ticket.customerName }}- Name of the customer or contact{{ ticket.customerEmail }}- Email of the customer or contact{{ ticket.customer.id }}- Customer ID (if ticket is from a customer){{ ticket.contact.id }}- Contact ID (if ticket is from a contact)
Assignment info
{{ ticket.assignedToName }}- Name of the assigned agent{{ ticket.assignedTo.user.email }}- Email of the assigned agent{{ ticket.assignedTeamName }}- Name of the assigned team
Messages
{{ ticket.lastMessage.content }}- Content of the most recent message{{ ticket.lastMessage.occurredAt }}- When the last message was sent{{ ticket.lastCustomerMessage.content }}- Content of the customer's last message{{ ticket.customerMessages }}- Array of all customer messages{{ ticket.message.content }}- The specific message that triggered the flow (for message_received triggers)
Contact variables
When your flow is triggered by a contact event:
{{ contact.id }}- Contact ID{{ contact.name }}- Contact's full name{{ contact.email }}- Contact's email{{ contact.phone }}- Contact's phone number{{ contact.jobTitle }}- Contact's job title{{ contact.tags }}- Array of contact tags{{ contact.notes }}- Notes about the contact{{ contact.source }}- How the contact was acquired{{ contact.lifecycleStage }}- Contact's lifecycle stage{{ contact.locale }}- Contact's locale{{ contact.language }}- Contact's language{{ contact.mantleUrl }}- Link to the contact in Mantle{{ contact.customers }}- Array of customers associated with this contact{{ contact.customerCount }}- Number of associated customers
Deal variables
When your flow is triggered by a deal event:
{{ deal.id }}- Deal ID{{ deal.name }}- Deal name{{ deal.amount }}- Deal amount{{ deal.amountCurrencyCode }}- Currency code{{ deal.stage }}- Current deal stage{{ deal.mantleUrl }}- Link to the deal in Mantle{{ deal.customer.name }}- Associated customer's name{{ deal.customer.email }}- Associated customer's email{{ deal.createdAt }}- When the deal was created{{ deal.closingAt }}- Expected closing date{{ deal.closedAt }}- Actual closing date
Task variables
When your flow is triggered by a task event:
{{ task.id }}- Task ID{{ task.title }}- Task title{{ task.description }}- Task description{{ task.status }}- Task status{{ task.priority }}- Task priority{{ task.dueDate }}- Task due date{{ task.mantleUrl }}- Link to the task in Mantle{{ task.customer.name }}- Associated customer's name{{ task.assignee.name }}- Assigned user's name{{ task.assignee.email }}- Assigned user's email{{ task.deal.name }}- Associated deal name (if any)
Affiliate variables
When your flow is triggered by an affiliate event:
Basic affiliate info
{{ affiliate.id }}- Affiliate ID{{ affiliate.name }}- Affiliate's name{{ affiliate.email }}- Affiliate's email{{ affiliate.mantleUrl }}- Link to the affiliate in Mantle{{ affiliate.outstandingCommission }}- Unpaid commission amount{{ affiliate.totalCommission }}- Total commission earned{{ affiliate.referralCount }}- Number of referrals{{ affiliate.totalSales }}- Total sales generated
Payout info
{{ affiliate.hasPendingPayouts }}- Whether there are pending payouts (true/false){{ affiliate.pendingPayouts }}- Array of pending payouts{{ affiliate.pendingPayouts[0].amount }}- Payout amount{{ affiliate.pendingPayouts[0].status }}- Payout status
Referral event (when triggered by a referral)
{{ referral.id }}- Referral ID{{ referral.date }}- When the referral occurred{{ referral.customer.name }}- Referred customer's name{{ referral.customer.email }}- Referred customer's email{{ referral.program.name }}- Affiliate program name
Liquid filters
Mantle supports standard Liquid filters plus some custom ones:
Formatting filters
{{ customer.lifetimeValue | money }}- Format as currency (e.g., "$1,234.56"){{ count | number_with_delimiter }}- Add thousand separators (e.g., "1,234"){{ content | html_to_markdown }}- Convert HTML to Markdown
Date filters
{{ customer.createdAt | time_since: "days" }}- Days since the date{{ date | date: "%B %d, %Y" }}- Format date (e.g., "January 15, 2024")
Array filters
{{ customer.tags | join: ", " }}- Join array items with separator{{ customer.reviews | size }}- Count of items in array{{ customer.reviews | first }}- First item in array{{ customer.reviews | last }}- Last item in array
Previous action outputs
When a flow step is triggered by a previous action completing (using the "flow action completed" trigger), you can access the results of those previous actions. This is incredibly powerful - you can use data from one action to inform the next.
Why this matters: Let's say you send an HTTP request to an API and get back a user ID. With previous action outputs, you can use that user ID in your next step - maybe to send a Slack notification or update a custom field. No manual copying, no hardcoding - just seamless automation.
Accessing previous actions
You can reference previous actions by index. Actions are ordered by when they were created (matching the order you see in the UI):
{{ previousActions[0].outputs.success }}
{{ previousActions[1].outputs.response }}
Standard output structure
All action outputs follow a consistent structure:
{{ previousActions[0].outputs.success }}- Whether the action succeeded (true/false){{ previousActions[0].outputs.response }}- The response data (varies by action type){{ previousActions[0].outputs.statusCode }}- HTTP status code (for HTTP requests){{ previousActions[0].outputs.error }}- Error details (null if successful)
Action-specific outputs
Different action types return different data. Here's what you can access for each:
Tag Customer / Untag Customer
{{ previousActions[0].outputs.success }}- Whether tags were added/removed{{ previousActions[0].outputs.tags }}- Array of tags that were added/removed
Example:
Tags added: {{ previousActions[0].outputs.tags | join: ", " }}
Send HTTP Request
HTTP request actions are where things get really interesting. When you send a request to an API, you get back a response - and you can use that response data in your next steps.
Standard HTTP request outputs
{{ previousActions[0].outputs.success }}- Whether the request succeeded{{ previousActions[0].outputs.statusCode }}- HTTP status code (200, 404, 500, etc.){{ previousActions[0].outputs.response }}- The response body (automatically parsed as JSON if the API returns JSON, otherwise kept as text){{ previousActions[0].outputs.error }}- Error details if the request failed
Example with JSON response:
API returned: {{ previousActions[0].outputs.response | json }}
User ID: {{ previousActions[0].outputs.response.userId }}
Example with error handling:
{% if previousActions[0].outputs.success %}Success! Status: {{ previousActions[0].outputs.statusCode }}{% else %}Error: {{ previousActions[0].outputs.error.message }}{% endif %}
Dynamic schemas for HTTP requests
Here's where HTTP requests get really powerful. You can define a response schema that describes what your API returns. This does two things:
Makes it easier to access nested data in your liquid templates
Generates condition options automatically in the flow builder
How to set it up:
In your flow, select an HTTP request action
Click "Configure Response Schema"
Define a JSON Schema that matches your API's response structure
Example schema:
Let's say your API returns something like this:
{ "userId": "123", "status": "active", "metadata": { "createdAt": "2024-01-01" } }
You'd define a schema like this:
Then in your liquid templates, you can access nested properties easily:
User ID: {{ previousActions[0].outputs.response.userId }}
Status: {{ previousActions[0].outputs.response.status }}
Created: {{ previousActions[0].outputs.response.metadata.createdAt }}
Using enums: If your schema includes enum values (like the status field above), those will show up as dropdown options in the condition builder. So instead of typing "active", you can just select it from a list.
Nested objects: Your schema can be as deep as you need. If your API returns nested objects or arrays, define them in your schema and access them with dot notation:
{{ previousActions[0].outputs.response.user.profile.name }}
Tips and best practices
Always check for success - Use
{% if previousActions[0].outputs.success %}before accessing response dataUse filters for arrays - Join arrays with
{{ tags | join: ", " }}to make them readableDefine schemas for APIs - If you're calling an API repeatedly, define a response schema to make your templates cleaner
Test your variables - Use the flow preview to see what values your variables will have before publishing
Handle errors gracefully - Always include error handling in your templates
Use the money filter - Format currency values with
{{ amount | money }}for cleaner output
Liquid variables turn your flows from static automations into dynamic, personalized experiences. Start simple with customer names and emails, then layer in previous action outputs as your flows get more complex. The more you use them, the more powerful your automations become.