Twig Templates

Compatible with Mautic 4, 5, 6, and 7.

Learn how to leverage Twig templates for customizing your Mautic experience. Twig provides a powerful yet simple syntax for adding logic directly into your Mautic assets.

Basic Example: Personalized Greeting

{% if contact.firstname %}
  <p>Hello {{ contact.firstname }}!</p>
{% else %}
  <p>Hello there!</p>
{% endif %}

{# More concise using the 'default' filter #}
<p>Welcome, {{ contact.firstname|default('Valued Customer') }}!</p>

Reusing Twig Templates

Insert one saved Twig Template within another using {twigtemplate=TEMPLATE_NAME}:

{% if contact.membership_tier == 'gold' %}
  {twigtemplate=Gold Member Offer}
{% elseif contact.membership_tier == 'silver' %}
  {twigtemplate=Silver Member Offer}
{% else %}
  {twigtemplate=Standard Welcome Offer}
{% endif %}

Dynamic Template Names

Use Twig tokens inside the template name for dynamic selection:

{twigtemplate=offer-{{ contact.membership_tier|default('standard') }}}

Installation

Step 1: Copy the plugin

Place the plugin folder in plugins/MauticTwigTemplatesBundle

Step 2: Clear cache

php bin/console cache:clear

Step 3: Reload plugins list

php bin/console mautic:plugins:reload

Step 4: Re-generate assets

php bin/console mautic:assets:generate

After installation, go to Settings > Plugins in Mautic and make sure the plugin is enabled.

Available Tokens

Contact Object (contact)

Access any contact field using its alias:

Hello {{ contact.firstname|default('there') }}!
Your email is {{ contact.email }}.
  • Custom Fields: contact.custom_field_alias
  • Tags: contact.tags (array — use {% for tag in contact.tags %})
  • Segments: contact.segments (array with id and name properties)
  • Companies: contact.companies (all companies as array)
  • Primary Company: contact.primaryCompany (primary company object, or first if none marked primary)
{% if contact.primaryCompany %}
    <p>{{ contact.primaryCompany.companyname }}</p>
    <p>{{ contact.primaryCompany.companyindustry|default('Not specified') }}</p>
{% endif %}

Form Result Tokens

  • formresult — Most recent form submission data (works when email is triggered by form action)
  • formresults — Array of all submissions for the triggering form
Thank you, {{ formresult.firstname }}! Your message: {{ formresult.message_field }}

Functions

  • getFormResults(formId, contactId, limit, page, orderBy, orderDirection) — Fetch form submissions for any form by ID
  • getFormResultsCount(formId, contactId) — Count submissions for a form
  • alreadySubmitted(formId, contactId) — Returns true when the contact already submitted the form
{% set count = getFormResultsCount(12, contact.id) %}
<p>You have submitted this form {{ count }} time(s).</p>

Hiding a form from contacts who already submitted it

alreadySubmitted(formId, contactId) returns a boolean. Leave contactId out and the currently tracked contact is used, resolved from the Mautic tracking cookie:

{% if alreadySubmitted(formId=123) %}
  <p>You have already registered. The form is no longer available for you.</p>
{% else %}
  {form=123}
{% endif %}

Pass a contact explicitly when you already have one:

{% if alreadySubmitted(123, contact.id) %}
  <p>This contact already submitted Form 123.</p>
{% endif %}

Available in emails, SMS and landing pages. Two limitations worth knowing: it only hides the form in the UI and does not prevent a server-side double submit, and it returns false when no contact can be identified — an anonymous visitor without a tracking cookie still sees the form.

Email Tokens (tokens)

When sending emails via API, pass custom tokens in the payload:

Your special code is: {{ tokens['{discount_code}']|default('No code available') }}

Snippets

Access Primary Company Details

{% if contact.primaryCompany %}
    <p>{{ contact.primaryCompany.companyname }}</p>
    <p>Industry: {{ contact.primaryCompany.companyindustry|default('Not specified') }}</p>
{% endif %}

List All Companies

{% for company in contact.companies %}
    <li>{{ company.companyname }}{% if company.is_primary == '1' %} (Primary){% endif %}</li>
{% endfor %}

Contact's Tags

{% for tag in contact.tags %}<li>{{ tag }}</li>{% endfor %}

Get Content from External URL

{% set product_data = 'https://api.yourstore.com/products/1' | get_content_from_url | json_decode %}
{% if product_data %}<p>{{ product_data.name }} — {{ product_data.price }}</p>{% endif %}

Content Segmentation

{% if contact.affinity == 'b2b' %}
<p>B2B Content</p>
{% else %}
<p>General Content</p>
{% endif %}

Time-Based Greetings

{% set currentHour = "now"|date("H") %}
{% if currentHour >= 5 and currentHour < 12 %}
    <p>Good morning, {{ contact.firstname|default('there') }}!</p>
{% elseif currentHour >= 12 and currentHour < 18 %}
    <p>Good afternoon, {{ contact.firstname|default('there') }}!</p>
{% else %}
    <p>Good evening, {{ contact.firstname|default('there') }}!</p>
{% endif %}

Fallback Values

<p>Welcome, {{ contact.firstname|default('Valued Customer') }}!</p>

Date Magic

Tomorrow is {{ "now"|date_modify('+1 day')|date("l, F jS, Y") }}
Today's date: {{ "now"|date("Y-m-d") }}

Random Selection

<p>{{ random(['Hello', 'Hi', 'Hey there']) }}, {{ contact.firstname|default('friend') }}!</p>

JSON Decode (Cart Data)

{% set cart = contact.cart_data | json_decode %}
{% if cart and cart.items is not empty %}
    {% for item in cart.items %}
      <li>{{ item.name }} — {{ item.price }}</li>
    {% endfor %}
{% endif %}

RSS Feed

{% set feed = 'https://your.rss.feed.url' | rss %}
{% for item in feed.channel.item %}
    <li><a href="{{ item.link }}">{{ item.title }}</a></li>
{% endfor %}

Forms Support

You can use data that contacts submit through Mautic forms directly in your Twig Templates.

  • {{ formresult }} — Most recent form submission (works when email triggered by form)
  • {{ formresults }} — All submissions for the triggering form
  • getFormResults(formId, contactId, limit, page, orderBy, orderDirection) — Fetch any form's submissions
  • getFormResultsCount(formId, contactId) — Count submissions

Example: Display Recent Submissions

{% set results = getFormResults(12, contact.id, 3) %}
{% for submission in results %}
  <tr>
    <td>{{ submission.dateSubmitted|date('M j, Y') }}</td>
    <td>{{ submission.firstname }}</td>
    <td>{{ submission.email }}</td>
  </tr>
{% endfor %}

Example: Registration Cap

{% set totalRegistrations = getFormResultsCount(3) %}
{% if totalRegistrations >= 10 %}
  <p>Registration is now closed.</p>
{% else %}
  {form=3}
{% endif %}

Focus Support

Use Twig Templates inside Mautic Focus Items (popups, bars, notifications) to show personalized content.

Insert {twigtemplate=...} in the content of your Focus Item. The template will be rendered using the current contact's data, and trackable URLs will be processed for Focus Item tracking.

{% if contact.points > 100 %}
  {twigtemplate=special_offer}
{% else %}
  {twigtemplate=latest_news}
{% endif %}
  • If the visitor is known (identified by Mautic tracking), their contact data is used.
  • If unknown, your template's default values or fallback logic will be used.

Custom Objects

Note: Requires the MauticCustomObjectsBundle plugin installed and active.

Use the getCustomObjectItems function to fetch data from a Custom Object:

getCustomObjectItems(alias, limit, page, orderBy, orderDirection, search, contactId)

Example: Show Recent Changelog Entries

{% set changelogs = getCustomObjectItems('changelogs', 5, 1, 'name', 'DESC') %}
{% for item in changelogs %}
    <h3>{{ item.name }}</h3>
    <div>{{ item.fields.content_alias | raw }}</div>
{% endfor %}

Example: Contact's Last Order

{% set lastOrder = getCustomObjectItems('orders', 1, 1, 'id', 'DESC', null, contact.id) %}
{% if lastOrder is not empty %}
    {% set order = lastOrder|first %}
    <p>Last order: #{{ order.name }} on {{ order.fields.date_ordered_alias }}</p>
{% endif %}

Embedding Externally

You can embed Mautic Twig Templates on your own website or share them via a direct link.

Embed with JavaScript

Paste this where you want the content on your page:

<script async defer type="text/javascript"
src="https://your-mautic.com/twig/template/{TEMPLATE_ID}/{UNIQUE_HASH}.js"></script>

Personalization is based on the visitor's Mautic tracking cookie.

Use Direct Link

Get a unique URL that displays the rendered template as a standalone HTML page — useful for previewing, iframes, or sharing:

https://your-mautic.com/twig/template/{TEMPLATE_ID}/{UNIQUE_HASH}.html

Replace your-mautic.com, {TEMPLATE_ID}, and {UNIQUE_HASH} with values from Mautic for your specific template.

API

The Twig Templates plugin extends the Mautic API for managing templates programmatically.

Note: Ensure API access is enabled in your Mautic settings and you have the necessary permissions for twigtemplates.

GET /api/twigTemplates

List all Twig Templates.

{ "twigTemplates": [{ "id": 1, "name": "Welcome Email Snippet", "template": "Hello {{ contact.firstname|default('there') }}!" }] }

GET /api/twigTemplates/{templateId}

Get a specific template by ID.

POST /api/twigTemplates/new

Create a new template.

{
  "name": "Dynamic Footer",
  "template": "<p>Copyright {{ 'now'|date('Y') }}</p>",
  "description": "Shows the current year in the footer"
}

PATCH /api/twigTemplates/{templateId}/edit

Update an existing template. Send only the fields you want to change.

DELETE /api/twigTemplates/{templateId}/delete

Permanently remove a template.