How to Create a Theme for Mautic

Are you worried your marketing efforts aren't standing out because of the limitations of Mautic's default themes? Make a difference by creating a unique Mautic theme. Discover how in our comprehensive guide.

In the dynamic world of digital marketing, customization is key. Being able to shape your marketing tools according to your specific needs can make the difference between a good campaign and a great one.

This is especially true when it comes to email marketing, where the way your message is presented can significantly impact its effectiveness.

That's why creating a custom theme for Mautic is crucial. This article aims to guide you step-by-step through the process of creating your own Mautic themes, allowing you to take full control over the look and feel of your Mautic instances.

What is a Mautic Theme?

A Mautic theme is a collection of files (including HTML, CSS, and images) that determines the overall aesthetic and layout of your Mautic instance. A theme defines how your emails, landing pages, and forms appear to your users.

While Mautic comes with a set of default themes, creating a custom theme allows you to align the visual presentation of your Mautic content with your brand identity. It also enables you to add specific functionality or layout structures that the default themes may not provide.

What Can You Style with Mautic Templates?

Mautic templates allow you to style and customize various aspects of your marketing automation efforts. Here's a list of what you can style using these templates:

  • Messages: Messages templates in Mautic are primarily used as the landing page for system messages displayed to a contact. For instance, when a contact unsubscribes or resubscribes to your system's emails (like newsletters), they are shown a system message. The look and feel of this message can be customized using Mautic's Messages templates.
  • Emails: Mautic's Email templates serve as the foundation when creating a new email. These templates provide the basic outline for the email you're about to compose, allowing you to customize the overall layout and design to match your branding and campaign requirements.
  • Landing pages: Similarly, Page templates are used as the base when creating a new landing page. These templates can be tailored to create a cohesive look and feel across all your landing pages, ensuring consistency in your branding and user experience.
  • Forms: Mautic also provides templates for forms. These templates are used to embed and render forms when they are visited directly or via an iframe. The styling of the form, including its layout and design elements, can be modified to match your branding or to meet specific campaign goals.
  • Mautic Core: Overriding core view templates in Mautic allows you to change practically everything. As discussed in the previous section, you can customize any view's template in Mautic, including core elements like the login page.

Knowing the possibilities on what to style the question of how to do it remains.

Crafting a Mautic Theme: The Process

The process of creating a Mautic theme is pretty straightforward. It primarily involves three fundamental steps:

  1. Creating the Theme Bundle: The first step towards crafting your Mautic theme is to create the theme "bundle". That is: you need to create the folder structure.
  2. Generating the Theme's Configuration File: The second step involves creating the configuration file for your theme. This file essentially tells Mautic about your theme, including its name, author, and version, and also defines the types of content your theme supports (such as messages, emails, forms, and pages).
  3. Creating the Actual Templates: The final step is to construct the actual templates for your theme. These include the templates for messages, emails, forms, landing pages, or any core content you wish to support or override.

Creating a Mautic Theme

So, let's create a new Mautic Theme. We'll name it MyTheme.

  • MAUTICROOT referrs to the base directory of your Mautic installation.
  • If you installed Mautic via Composer: Keep in mind that the public parts of Mautic are within the MAUTICROOT/docroot folder.

Create the Theme Bundle

  • Change into the MAUTICROOT/themes folder.
  • Create a new folder with the name mytheme.
  • Create an empty file config.json. This will hold your theme's configuration.
  • Create a folder named html. It will hold the template files.
  • Create the folders assets for images, styles for CSS files and js for JavaScript files.

Now you should have this basic outline:

mytheme
├── config.json
├── assets
├── html
├── js
└── styles

Create the Configuration File

The configuration file defines key parameters. It is a concise file, though, and easy to create. Paste this content into the config.json file:

{
  "name": "MyTheme",
  "author": "Tobias",
  "authorUrl": "https://mauticroundup.com",
  "features": [
    "email",
    "form",
    "page"
  ],
  "builder": ["legacy", "grapesjsbuilder"]
}

Mautic will recognize your new theme after creating this file. If you create a new email or landing page you should be able to select your theme—which is empty, of course.

Let's break down the various components of the configuration file:

Breakdown of the Configuration Keys

  • name, author and authorUrl are pretty self-explanatory. Those are used in the theme manager to make your theme recognizable. name is also used everywhere where you can choose a theme, i.e. the landing page or email builder.
  • features: This field is important. It is an array (i.e. collection) of strings (i.e. text) that informs Mautic about the features your theme supports. The currently recognized values are "email", "form", and "page" for emails, forms and landing pages.
  • builder: This field is an array of strings declaring which builder(s) the theme supports. Mautic uses it's legacy editor by default. So, you want to include to grapesjsbuilder if you want to use GrapesJS.

A Word About Theme features

You may ask yourself why you need to set the features explicitly.

Let's say you want two different layouts for landing pages. One very simple for newsletter signups and one sophisticated for products.

Mautic supports only one template for emails or pages per theme. So, you'd need to create a theme myNewsletterSignUpForms and a theme myProductPromotionLandingPages.

As both themes only define landing page templates they'd clutter the template chooser for emails. Hence, you can stop Mautic from displaying the themes in your email builder.

Create Twig Templates

Mautic uses Twig as templating framework/language.

Twig is the templating engine created by Symfony. You can find more info about it on their website.

The Message Template: html/message.html.twig

A key template in a Mautic theme is the message.twig.html template. This template is primarily used for displaying system messages to contacts, such as notifications regarding their subscription status.

You should definitively implement this file in your main theme.

Mautic passes two important variables to this theme: message and content.

  • The message variable contains the system message Mautic wants to display to the contact. message could be a variety of notifications like "You have been unsubscribed...", "Thank you for subscribing...", and so forth.
  • The content variable is optional. It only holds data if a form is associated with an email, such as an unsubscribe form. When a contact opts to unsubscribe from your email list, for instance, this variable might contain the HTML for the unsubscribe form that the contact needs to complete.

Create the message.html.twig file in the MAUTICROOT/themes/mytheme/html/ folder.

A simple bootstrap powered message template could look like this:

<!DOCTYPE html>
<html class="h-100">

<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Message from My Site!</title>

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">

</head>

<body class="d-flex h-100 text-center text-bg-dark">

    <div class="d-flex w-100 h-100 p-3 mx-auto flex-column" style="max-width: 42em;">
        <header class="mb-auto">
            <div>
                <h3 class="float-md-start mb-0">My Site</h3>

            </div>
        </header>

        <main class="px-3">
            <h1>
                {{ message|raw }}
            </h1>
            {% if content is defined %}
            <div class="lead">
                {{ content|raw }}
            </div>
            {% endif %}
        </main>

        <footer class="mt-auto text-white-50">
            <p>
                <a href="#" class="text-white">Imprint</a>
                &nbsp;|&nbsp;
                <a href="#" class="text-white">Privacy Policy</a>

            </p>
        </footer>
    </div>

</body>

</html>
message.html.twig

The Landing Page Template: html/page.html.twig

The page.twig.html template in Mautic defines the base template when creating a new landing page and can include advanced HTML for optimal browser compatibility and functionality.

Let's delve into the specific placeholders and variables of the page.twig.html template:

💡
What's the difference between placeholders and variables?
Variables are used by Twig. They get replaced when the template is applied. That means, when you select (or change) a page's theme at its creation.
Placeholder are exactly that. They are pieces of text, you can use everywhere in your page. Even in the builder. They get replaced by Mautic every time the form gets displayed to a visitor.
Twig Variables and Functions
  • page: This gives you access to the Mautic\PageBundle\Entity\Page entity object. In simpler words. This is the PHP object that describes your page. You can inspect it at MAUTICRapp/bundles/PageBundle/Entity/Page.php
  • {{outputHeadDeclarations()}}, {{outputScripts('bodyOpen')}}, and {{outputScripts('bodyClose')}}: These Mautic/Twig functions are used to add styles, scripts, or other tags to specific parts of the HTML and allow Mautic to dynamically inject additional content into your landing page, such as CSS styles or JavaScript scripts. Specifically:
  • {{outputHeadDeclarations()}} is used to add tags right before the </head> tag.
  • {{outputScripts('bodyOpen')}} is used to add tags right after the opening <body> tag.
  • {{outputScripts('bodyClose')}} is used to add tags right before the closing </body> tag.
⚠️
As said, the Twig template will get rendered once and creation time. After that the contents the variables and functions above provide become static. For anything dynamic you need to rely on placeholders.
(I'm not 100% sure, this is true for the outputHeadDeclarations and outputScripts functions, but given how the rendering works it is quite possible that they become static, too.)
Placeholder

Landing pages offer a range of placeholders, you can use:

  • {pagelink=PAGEID}: Outputs the URL to a landing page. Use the page id to link to it.
  • {dwc=ID}: Renders one of Mautic's Dynamic Web Content. Use its id to reference it.
  • {pagetitle}: This variable is set in the landing page builder (Title setting). You can (and should) use it for the HTML page title, and populate the <title> tag of the landing page with it. The page title is important for both SEO and user experience, providing a concise description of the page's content. You can also use it for an directly visible <h1> tag.
  • {pagemetadescription}: This variable is also set in the landing page builder and contains the HTML meta description tag. The meta description is a brief summary of the page content, which search engines often display in search results. A well-crafted meta description can improve the click-through rate from search results to your landing page.
  • {sharebuttons}: This will add Facebook, Twitter, and LinkedIn share buttons. You'd need to configure and active the pre-shipped Twitter/Facebook/LinedIn Plugin. I haven't tested it really.
  • {langbar}: This renders a list of links to translated variations of your landing page. If you have a landing page in English and a German or French translation/variation of it you'd get links to these pages.

In case you know the old page builder with it's slots mechanism: You don't need to define slots anymore. GrapesJS is pretty good at recognizing blocks that you'd edit.

Here's a simple bootstrap powered landing page template. Just paste the code and start editing with GrapesJS.

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    {% if page is defined %}
    <title>{pagetitle}</title>
    <meta name="description" content="{pagemetadescription}">
    {% endif %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
    {{ outputHeadDeclarations() }}
</head>

<body>
    {{ outputScripts('bodyOpen') }}
    <main>
        <div class="container py-4">
            <div class="p-5 mb-4 bg-body-tertiary rounded-3">
                <div class="container-fluid py-5">
                    <h1 class="display-5 fw-bold">Hey there!</h1>
                    <p class="col-md-8 fs-4">
                        Becoming a contact is better than being just a lead.
                        Join this great newsletter and become truly knowledgeable.
                    </p>
                    <button class="btn btn-primary btn-lg" type="button">Sign me up</button>
                </div>
            </div>
            <footer class="pt-3 mt-4 text-body-secondary border-top">
                &copy; 2023
            </footer>
        </div>
    </main>
    {{ outputScripts('bodyClose') }}
</body>

</html>
html/page.html.twig

The Form Template: html/form.html.twig

The form.html.twig is utilized whenever a form is accessed directly via https://mautic.mysite.com/form/ID, which embeds the form in a landing page or when form is embedded into a third-party page using the iframe method.

  • message: This variable typically contains system messages related to the form, such as confirmation messages or error messages. For example, after a user submits a form, the message variable might contain a thank you message or an error message if there was a problem with the submission.
  • content: The content variable contains the actual form fields and buttons. This is where the main content of your form goes, including text fields, checkboxes, dropdowns, submit buttons, and everything else.
  • header: This variable is used for the form's header, providing a title or introductory text for the form. This could include the purpose of the form, instructions for completing it, or any other relevant information.
💡
This is at leas, what the official documentation says, but: I couldn't verify header outputs anything. By looking at the source code, I'd say header is removed.
You can use (the undocumented) variable name instead. name will output the name, you gave your Form in the backend.
  • metaRobots: An undocumented variable is metaRobots it will print the <meta name="robots" content="(index|noindex)"> tag. Without rendering this variable the Disable search indexing setting will have no effect.

Once again, a simple bootstrap powered form.html.twig form landing page:

<html>

<head>

  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{{name}}</title>
  {metaRobots}
  
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">

</head>

<body>

  <div class="col-lg-8 mx-auto p-4 py-md-5">
    <header class="d-flex align-items-center pb-3 mb-5 border-bottom">
      <span class="fs-4">My Site · {{name}}</span>
    </header>

    <main>
      <h1 class="text-body-emphasis">Get started with your new newsletter</h1>
      <p class="fs-5 col-md-8">
      Simply enter your email below and get access to the hottest cheat sheet for your niche. You'll get valuable tips on how to be even more successful in your market, every week, as an add-on.
      </p>
      
    {% if message is defined %}
    <div class="h-50 p-5 text-bg-info rounded-3 d-flex align-items-center">
        <h2>{{ message|raw }}</h2>
    </div>
    {% endif %}



      <hr class="col-3 col-md-2 mb-5">

      <div class="row g-5">
        <div class="col-md-6">
          {{content | raw}}
        </div>

        <div class="col-md-6">
          <h2 class="text-body-emphasis">We take your privacy seriously</h2>
          <p>Read more detailed instructions and documentation on using or contributing to Bootstrap.</p>
          <ul class="list-unstyled ps-0">
            <li>
              ➡️&nbsp;We will never sell your data
            </li>
            <li>
              ➡️&nbsp;You can cancel anytime
            </li>
            <li>
              ➡️&nbsp;<a class="icon-link mb-1" href="#">Privacy Policy</a>
            </li>
            <li>
              ➡️&nbsp;<a class="icon-link mb-1" href="#">Imprint</a>
            </li>
          </ul>
        </div>
      </div>
    </main>
    <footer class="pt-5 my-5 text-body-secondary border-top">
      Talk soon! · My Site © 2023
    </footer>
  </div>

</body>

</html>

The Email Template: html/email.html.twig

The email.html.twig template is probably the most interesting part of a Mautic theme. This template serves as the base when creating a new email, allowing you to design the layout and styling of your email content.

The email content is (or rather should be) written in MJML (Mailjet Markup Language). MJML is a markup language designed to reduce the pain of coding responsive emails. By using MJML, you can ensure that your emails look consistently good across different email clients and devices.

Here's a simple example. This example is just a confirmation message, hence not really suitable for a template, but it's short. You get the gist.

<mjml>
  <mj-head>
  </mj-head>
  <mj-body background-color="#f5f5f5">
    <mj-section background-color="#fff" padding="20px">
      <mj-column padding="0">
        <mj-text align="center" color="#a1483a" font-size="40px" padding="10px">
          <strong>Hej there</strong>
        </mj-text>
      </mj-column>
    </mj-section>
    <mj-section background-color="#fff" padding-bottom="20px" padding-left="20px" padding-right="20px" padding-top="0px" padding="20px">
      <mj-column padding="0">
        <mj-spacer height="10px"></mj-spacer>
        <mj-text align="center" color="#231F20" font-size="24px" line-height="1.5" padding="10px">
          You're all set up. Thanks for subscribing<br />
        </mj-text>
        <mj-spacer height="30px"></mj-spacer>
        <mj-image fluid-on-mobile="true" padding="0px" src="https://unsplash.com/photos/BYPGE0ZYID8/download?ixid=M3wxMjA3fDB8MXxzZWFyY2h8Nnx8b2theXxkZXwwfHx8fDE2ODQ5NjExODB8MA&force=true&w=640"></mj-image>
      </mj-column>
    </mj-section>
    <mj-section background-color="#fff" padding-bottom="60px" padding-left="20px" padding-right="20px" padding-top="20px" padding="20px">
      <mj-column padding="0">
        <mj-text align="center" color="#231F20" font-size="16px" line-height="1.5" padding="10px">
          We do have great content on our social media, too. Follow us for valuable niche insights and more.
        </mj-text>
        <mj-spacer height="30px"></mj-spacer>
        <mj-button background-color="#a1483a" border-radius="4px" font-size="18px" line-height="1.5" padding="0px">
          <strong>FOLLOW</strong>
        </mj-button>
        <mj-spacer height="10px"></mj-spacer>
        <mj-text align="center" color="#231F20" font-size="16px" line-height="1.5" padding="10px">
          <strong>Talk soon!</strong>
        </mj-text>
      </mj-column>
    </mj-section>
    <mj-section background-color="#f5f5f5" padding="20px">
      <mj-column padding="0">
        <mj-text align="center" font-size="14px" padding="10px">
          <a style="color:#231F20" href="#">Imprint</a> &nbsp;<a style="color:#231F20" href="#">Privacy Policy</a>
        </mj-text>
        <mj-spacer height="10px"></mj-spacer>
        <mj-text align="center" color="#231F20" font-size="12px" line-height="1.5" padding="10px">
          Classic Lorem Ipsum dolorem.
        </mj-text>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>
html/email.html.twig

Providing Thumbnails

Thumbnails serve as a visual representation of your theme with demo content. They provide a preview of your theme. Thumbnails are displayed in various places within Mautic—if you provide them.

The recommended dimensions for thumbnails are 575x600 pixels. This ensures that they are displayed correctly and clearly across different parts of Mautic.

By default, Mautic looks for a file named thumbnail.png in your theme bundle. This image serves as the general thumbnail for your theme. It is used if in the theme manager and for every feature that doesn't have its unique thumbnail.

If you want a different thumbnail for the different features, then Mautic got your back. It supports feature-specific thumbnails. You can add feature-specific thumbnails by adding a thumbnail named: thumbnail_[feature].png. So you can create:

  • thumbnail_email.png for emails.
  • thumbnail_page.png for landing pages.
  • thumbnail_form.png for forms.

Wrapping it up

Developing a theme in Mautic for the first time can seem like a daunting task. I hope, I could provide you with a solid understanding of the key components involved—from creating the theme bundle and configuration file, to crafting the actual templates. Hopefully, you can now tackle this process and create your very own theme.

Happy theming!