Adaptyle
Adaptyle gives each customer a reason to act within a shared email. You mark the content that should adapt and describe the writing job. It uses the selected customer context and brand guidance to generate those passages when the email is rendered.
The same mechanism works in templates, broadcasts and workflow email steps. maxinja can build the template and its instructions from your brief, or you can add them in the composer.
Keep the facts. Adapt the message.
| Content | Use | Example |
|---|---|---|
| A supplied value | Liquid | Customer name, order number, price or product URL. |
| A reason to act | Adaptyle | Explain why the supplied coffee may interest a customer with recorded single-origin purchases. |
| Required campaign content | Authored copy or Liquid outside AI regions | Offer terms, deadline, approved wording and destination link. |
In the Halden demo, Sarah's introduction draws on single-origin orders and a pour-over preference. Marcus's draws on espresso purchases. The product and offer stay the same. See the personalization guide for generated samples and the source context behind them.
Write your first instruction
Put an instruction between <<< and >>> anywhere in your subject or body:
<p><<<Introduce the supplied coffee using this customer's recorded purchases.
If history is absent, introduce it without assuming a preference.>>></p>
The instruction is evaluated with each recipient's context. Generated wording can vary; distinct wording for every recipient is not guaranteed.
Rewriting something you already wrote
If you already have copy you like and want it tailored, put your instruction first, then :::, then your copy:
<p><<<Make this warmer and mention their last order:::Thanks for shopping with us.>>></p>
Everyone gets a version of your sentence rather than something written from scratch. Use this when you want to keep control of the message and only personalize the edges.
What maxinja already knows
The rendering context includes the configured recipient data and selected published brand kit. Stored customer fields and tags provide facts for the instruction. A campaign cannot use information that has not been supplied or selected.
Evaluated fields and related records must be selected explicitly. Open the Data tab, expand the contact row and select the fields your instruction needs. Check a sample value before relying on it in the message.
Describe what to write from that context and what to do when a field is absent:
<!-- Use only the purchase history selected in the Data tab. -->
<<<Write a short reason to explore the supplied product, based on the customer's recorded purchases. If purchase history is absent, introduce the product without claiming a previous purchase.>>>
Hiding things maxinja does not need to read
If a chunk of your email is styling or markup rather than words, wrap it in <## and ##> with a name, a :::, then the content. maxinja sees only the name, and your content is put back exactly as you wrote it:
<div <##card-style:::style="font-family: sans-serif; padding: 16px;"##>>
<<<Write a one-line product teaser for this customer.>>>
</div>
Hidden blocks remove those bytes from the model’s view and restore them afterwards. This can reduce tokens for large static sections; a short placeholder can cost more than the text it replaces. Give each block a different name. Hidden content still becomes part of the final email and must pass its HTML checks.
Telling maxinja what the email is for
In the MJML and HTML code editors you can add a short brief at the very top of the template, between <<# and #>>. It never appears in the email. Its only job is to give maxinja context.
Use description for the writing brief. maxclicks combines the subject and body descriptions into one email context. Declare locale when the email needs an explicit language:
<<#
locale: en-GB
description: |
Our weekly product roundup.
Audience: tech-savvy early adopters. Tone: enthusiastic but professional.
#>>
The email renderer replaces your manifest title with its email title. Use
description for instructions and locale for a valid language tag such as
en-GB or de-DE. Subject and body locales must agree. A qualified AI
broadcast requires an explicit locale matching its approved campaign settings.
A manifest tools entry does not make an external tool available during email
rendering.
What happens during a render
- maxclicks resolves the email’s declared data, selected expansions and branding.
- Liquid resolves values, loops and conditions once. This establishes the reference content for that recipient. Values supplied by a contact cannot introduce new Adaptyle instructions.
- Subject and body are processed together as one document. The model resolves the authored prompt regions with the whole email in view. Nested instructions are not a promise of one separate model call per prompt.
- maxclicks checks that the output preserved protected content and hidden placeholders, resolved the instructions, and produced a valid subject and body.
- The footer is added, MJML is compiled when needed, and the final HTML is validated before it becomes sendable content.
The model receives the supplied data object and branding, not just the fields you mention in a sentence. Keep the declared data and expansions relevant to the email. It does not fetch an unspecified order history or generate a new image merely because an email prompt asks for one.
Protect the parts that must stay fixed
Text outside prompt regions is checked against the Liquid-resolved reference, with document-edge whitespace normalized. Hidden placeholders are checked for their position and occurrence count. The final email checks protect links, attributes, stylesheets and structural context from the AI rewrite.
Keep buttons, image URLs, offer terms and required wording outside AI regions. Give prompts a writing task inside an existing layout. Asking a runtime prompt to add new styled sections, change link destinations or redesign the HTML can fail validation. Make those structural changes while authoring the draft instead.
These checks establish content and structural boundaries. They do not prove that every generated statement is true, that an instruction achieved the desired tone, or that every email client displays the result identically. Compare representative recipient samples and send inbox tests.
Resolve a failed personalization
| Symptom | What it means | Next step |
|---|---|---|
| Model or thinking setting missing | The template’s runtime AI configuration is incomplete. | Set both in Personalize, then generate again. |
| Adaptyle syntax error | A delimiter, nesting structure or manifest cannot be parsed. | Fix the marked source; retrying unchanged syntax will not help. |
| Protected text, placeholder or link changed | The generated result exceeded its allowed edit scope. | Narrow the prompt and keep layout and essential facts outside it. |
| Locale mismatch | Subject/body languages disagree, or the campaign’s approved locale no longer matches. | Align the manifest language and campaign settings. |
| Empty subject/body or invalid final artifact | The result is not a sendable email. | Inspect the Base sample first, then the generated passage and markup. |
| Credits or provider capacity unavailable | Rendering could not proceed with its current resources. | Check billing and the campaign/run status before restarting work. |
Correction attempts may use additional model usage. Qualified broadcasts use the correction budget in their campaign policy; a failed render is not permission to send unvalidated output. See broadcast preparation for how this affects an audience send.
Why a later refresh may not change an active send
A standalone sample can read the latest published computed values. A broadcast revision or root workflow run instead captures the published calculation generations on its first read; child runs inherit that snapshot. Publishing a newer calculation does not replace the values already selected for that execution.
A calculation that was unavailable when that snapshot was captured remains unavailable there. If the captured generation is erased or no longer usable, execution reports an error rather than silently switching to a newer value. Compare the sample and the execution’s data context when investigating different results. See attribute expansion.
What it costs
AI usage is metered for personalized rendering, including previews and regenerations. At campaign scale, each recipient whose content is personalized adds model usage. Content outside AI regions is preserved through the rewrite; Liquid still resolves its supplied values.
Select the passages where context changes the message, such as the opening or product explanation. If no instructions remain after Liquid resolves for a recipient, that render skips the model call. Other recipients can still need AI. Sending allowances, application work, possible correction calls and campaign reviews are separate; see the editor estimate and billing.
An email with instructions requires its own model and thinking settings under Personalize → Runs with. Those settings are used during rendering; the workspace default is not a fallback.
Getting good results
- Describe the outcome, not the words. "Write a one-line reason to come back, based on what they bought" beats "Say we miss them".
- Keep it to a handful. More than 10 instructions in one email is a sign the email is doing too much, and maxclicks warns you.
- You can nest one inside another, and maxinja works from the inside out. More than two levels deep gets hard to predict, and maxclicks warns you there too.
- Inspect representative samples. Compare the source fields with the generated message for an engaged customer, an infrequent customer and someone with missing context. A later render can produce different wording.
- Keep essential facts fixed. Put amounts, deadlines, required wording and links outside AI regions. Inspect generated claims as well: preserving fixed blocks does not establish that every generated statement is accurate.
Writing the symbols literally
If you need <<< or ::: to appear in the email as text rather than as an instruction, write the escape code instead and maxclicks prints the symbol:
| To print | Write |
|---|---|
<<< | <##ESCPO##> |
>>> | <##ESCPC##> |
::: | <##ESCS##> |
<## | <##ESCHO##> |
##> | <##ESCHC##> |
<<# | <##ESCMO##> |
#>> | <##ESCMC##> |