Mandrill
Mandrill merge vars render blank when merge_language mismatches tag syntax, global_merge_vars is nested wrong, or entries are malformed. How to fix each.
Updated Jul 1, 2026
The short answer
"Mandrill merge vars not working" means your template renders with blank or unreplaced merge tags even though the email sends. It is not an API error code. The usual causes are a merge_language mismatch (Handlebars {{tag}} vs Mailchimp *|TAG|*), placing global_merge_vars at the wrong nesting level, or malformed name/content entries. Fix it by matching merge_language to your tag syntax and nesting global_merge_vars correctly inside the message object.
"Mandrill merge vars not working" is not an SMTP reply or API error code — the message sends successfully (HTTP 200, status sent/queued), but the template arrives with merge tags blank or printed literally (e.g. recipients see an empty space or a raw *|FNAME|*). It happens with Mailchimp Transactional (formerly Mandrill) messages/send-template and messages/send when the merge data and the template don't line up.
There are four common, distinct causes:
*|FNAME|*) and Handlebars ({{fname}}). If your template uses one syntax but the request (or your account's Sending Defaults) is set to the other, the tags never resolve and render blank. The default is set under Settings → Sending Defaults → Merge Language, and is overridden per call with the merge_language parameter or the X-MC-MergeLanguage SMTP header.merge controls whether merge tags are evaluated. Per Mailchimp's docs it is set to true automatically when you provide merge_vars or global_merge_vars — but only if those arrays are at the correct level of the message object. If they're attached to the wrong object (a frequent mistake with wrapper libraries), Mandrill never sees them.name/content entries. Each entry in global_merge_vars and merge_vars must be an object with a name and a content key. Names are case-insensitive and may contain alphanumeric characters and underscores; they cannot contain colons and cannot begin with an underscore. A typo, a missing content, or a name that doesn't match the tag in the template yields a blank.global_merge_vars vs merge_vars confusion. global_merge_vars applies to all recipients; merge_vars is per-recipient and is keyed by rcpt (the recipient email). A per-recipient value only fills in if its rcpt exactly matches an address in to.Step 1 — Match merge_language to your tag syntax. If your template uses {{fname}}, send merge_language: "handlebars". If it uses *|FNAME|*, use "mailchimp". This is the single most common cause of blank tags.
Step 2 — Send well-formed merge data. A correct messages/send-template body:
{"template_name": "welcome","template_content": [],"message": {"to": [{ "email": "sample@example.com" }],"merge": true,"merge_language": "handlebars","global_merge_vars": [{ "name": "fname", "content": "Sample" },{ "name": "email", "content": "sample@example.com" }],"merge_vars": [{"rcpt": "sample@example.com","vars": [{ "name": "fname", "content": "Sample" }]}]}}
Note that merge, merge_language, global_merge_vars, and merge_vars live inside message — not at the top level of the request. template_name and template_content, by contrast, are top-level parameters alongside message.
Step 3 — Confirm the template variable names match exactly. A {{fname}} tag is filled by a merge var named fname. Mismatched or misspelled names render empty.
If you use the (now-archived) nodemailer-mandrill-transport, mandrillOptions is deep-merged onto the Mandrill API call. So merge, merge_language, and global_merge_vars must be nested under a message key inside mandrillOptions, not placed directly on mandrillOptions:
var message = {to: "sample@example.com",mandrillOptions: {template_name: "template1",template_content: [],message: {merge: true,merge_language: "handlebars",global_merge_vars: [{ name: "fname", content: "Sample" },{ name: "email", content: "sample@example.com" }]}}};
How the transport picks an endpoint: the transport inspects the merged payload and calls Mandrill's sendTemplate (messages/send-template) when a template_name is present, and messages/send otherwise (its code is effectively var method = payload.template_name ? 'sendTemplate' : 'send';). So a stored template is used — provided template_name is set at the top level of mandrillOptions (as above) and your merge data is nested in message. The most common reason tags stay blank here is the nesting mistake (merge data placed directly on mandrillOptions instead of under message), not the endpoint. Because the library is archived, for new work prefer calling the Mailchimp Transactional messages/send-template endpoint directly or using the official @mailchimp/mailchimp_transactional SDK. Through Courier's Mandrill integration, configure template and merge data under message.providers.mandrill.override.body.message — e.g. message.providers.mandrill.override.body.message.global_merge_vars — matching Courier's documented override examples.
Use the Mailchimp Transactional API Console or messages/info for the returned message _id, or the Outbound Activity → message detail in the dashboard, to inspect the rendered content and confirm whether the merge data was received and which tags resolved.
References
FAQ
Most often the merge_language doesn't match your tag syntax: Handlebars templates use {{tag}} and require merge_language "handlebars", while the Mailchimp merge language uses *|TAG|*. A mismatch, a merge var name that doesn't match the template tag, or merge data placed at the wrong nesting level all cause tags to render empty.
One API, every provider
Courier connects to your email, SMS, and push providers, handles retries and failover, and surfaces delivery errors in plain language.
Last reviewed Jul 1, 2026. Courier is not affiliated with third-party providers; error behavior may vary by implementation.
© 2026 Courier. All rights reserved.