Dynamic data controls what goes into the rendered email (merge tags) and what is shown or hidden (context / visibility rules).

Structure

type DynamicData = {
  merge_tags?: {
    text?: Record<string, string>  // paragraph, heading, button text
    url?:  Record<string, string>  // href, src, image URLs
    attr?: Record<string, string>  // alt, aria-label, etc.
  }
  context?: Record<string, string | number | boolean>
}

All fields are optional — include only what your template uses.

Merge tags

text — inline content

await client.renderHtml("template-id", {
  merge_tags: {
    text: {
      name:       "Noruwa",
      company:    "Maildeno",
      reset_name: "Password",
    },
  },
})

Values are HTML-escaped before insertion.

await client.renderHtml("template-id", {
  merge_tags: {
    url: {
      reset_url:    "https://app.example.com/reset/abc123",
      banner_image: "https://cdn.example.com/banner.jpg",
    },
  },
})

Values are URL percent-encoded before insertion.

attr — HTML attributes

await client.renderHtml("template-id", {
  merge_tags: {
    attr: {
      alt_text:   "Monthly promotion banner",
      aria_label: "Open the dashboard",
    },
  },
})

Values are HTML attribute-safe encoded before insertion.

Context

Context drives visibility rules — it controls which rows are shown or hidden. Values are never injected into content.

await client.renderHtml("template-id", {
  context: {
    plan:         "pro",          // string
    country:      "usa",          // string
    age:          25,             // number
    is_verified:  true,           // boolean
    country_rank: "2",            // number-as-string is also fine
  },
})

All options together

await client.render({
  templateId: "550e8400-e29b-41d4-a716-446655440000",
  target: "mjml",
  dynamicData: {
    merge_tags: {
      text: {
        name:       "Noruwa",
        company:    "Maildeno",
        reset_name: "Password",
      },
      url: {
        reset_url: "https://app.example.com/reset/abc123",
      },
      attr: {
        alt_text: "Cave image",
      },
    },
    context: {
      country:      "usa",
      country_rank: "2",
      expiry:       "2028",
    },
  },
})

Missing and extra values

  • A merge tag in the template with no supplied value renders as an empty string.

  • A supplied value for a tag not present in the template is silently ignored.

  • Context keys not matched by any visibility rule are silently ignored.

See Merge Tags and Visibility Rules for the builder-side documentation.