Custom Blocks
Write a block of your own in MJML once, mark what may change, and let anyone place it in the email builder without breaking the design.
The email builder comes with sixteen block types. A custom block is one of your own: a hero on your brand colour, a product card laid out the way your site lays it out, a footer with the legal line nobody may reword. Whoever looks after the brand writes it once, in MJML, and marks the parts that may change. From then on it sits in the builder under Your blocks, and whoever writes the email fills in those parts and nothing else.
What a custom block is
A custom block has two halves. The design is MJML — a small markup language for email that compiles to HTML known to render the same in Outlook, Gmail and Apple Mail — and it is locked: the builder never shows it and a marketer cannot edit it. The slots are the words, links and images the design declares as changeable; they are the only fields the builder offers for the block.
The MJML is compiled once, when the block is saved. The builder places the compiled result, so sending an email with custom blocks in it is no different from sending any other.
Writing a block
- Go to Templates → Custom blocks and click New block.
- Write the block on the left. The right-hand pane compiles it as you type and shows what MJML made of it, with any attribute it did not understand listed above the preview.
- Give it a name (this is what the builder shows) and, if it helps, a line of description.
- Under Slots, give each slot a label the marketer will understand and a default it shows until they type something.
- Click Save block.
A block is a whole MJML document: start with <mjml>, put styles and fonts in
<mj-head>, and the block itself — one or more <mj-section>s — in
<mj-body>. The builder's own document is 600 pixels wide and white; a section's background colour
fills the block's width. The MJML documentation covers
the tags. Anything active — script, forms, embedded frames — is removed when the block is compiled.
Slots
A slot is a double-bracketed name anywhere in the MJML:
| Written as | The marketer gets | Notes |
|---|---|---|
[[headline]] | A text field | What they type is escaped; line breaks are kept. No markup can come in through a slot. |
[[cta:url]] | A link field | Use it as an href. Only http(s), mailto and tel addresses, and merge tags such as {{web_version_url}}, are kept; anything else becomes #. |
[[hero:image]] | An image address field | Use it as an src. Same rules as a link. |
A name is letters, digits and underscores. The same name used twice is one slot filled in both places, which is how
a button's link and a heading's link stay the same. Up to twenty slots per block. Merge tags such as
{{first_name|there}} work inside a block exactly as they do anywhere else in the email.
Using a block in an email
In the email builder — in a campaign, a template or an automation's email — the block palette on the left ends with Your blocks. Click one, or drag it onto the email, and it appears with its defaults. Select it and the side panel lists its slots by their labels; type into them and the block updates. There is nothing else to change on it: no colours, no padding, no text outside the slots.
Changing a block later
Editing a block in the library changes what the builder offers from then on. An email that already placed the block keeps the copy it took when it was placed — a sent campaign never changes — and a draft picks up the new design the next time it is opened in the builder, with the values already typed into its slots kept. Deleting a block removes it from the palette; emails that used it are untouched.
From the API
POST /api/v1/custom-blocks with name and mjml compiles and stores a block; the
response carries the compiled html and head_html, the slots the markup declared and any
warnings. POST /api/v1/custom-blocks/preview compiles without saving. A campaign or template created
through the API places a block as { "type": "custom", "props": { "blockId", "fragment", "head", "slots", "values" } }
in its blocks, and html_content is rendered from it as for any other block. The
API reference has the full shapes.
Stuck, or found a gap? Ask in the community — questions, tips and every release note, with this page as the source of truth.