> ## Documentation Index
> Fetch the complete documentation index at: https://docs.instantcampaign.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Personalization and template data

> Personalize emails with merge tags and Liquid, preview them as a real contact with sample data, and mark variables a send must provide.

Templates can include each recipient's name, their custom field values, and data sent with the email, such as an order from your store or your API. This page covers how to insert those values and how to check them before you send.

## Merge tags

Merge tags are placeholders in double curly braces, such as `{{first_name}}`. They're replaced for each recipient when the email is sent.

**To insert one:** select a Heading, Text or Rich Text block and click the **Merge Tag** pill above it. Search or pick a tag and it's added at the end of the block's text. You can also type tags directly, or insert them from the **HTML** tab of an HTML or Rich Text block.

These tags work in every campaign, journey and transactional email:

| Tag                                                | Inserts                                                                          |
| -------------------------------------------------- | -------------------------------------------------------------------------------- |
| `{{first_name}}`, `{{last_name}}`, `{{full_name}}` | The contact's name                                                               |
| `{{email}}`                                        | The contact's email address                                                      |
| `{{company}}`                                      | The contact's company                                                            |
| `{{customField:KEY}}`                              | A [custom field](/guides/audience-and-campaigns/custom-fields) value, by its key |
| `{{company_name}}`, `{{company_address}}`          | Your workspace's name and postal address                                         |
| `{{current_year}}`                                 | The current year                                                                 |
| `{{unsubscribe_url}}`, `{{preferences_url}}`       | Links to unsubscribe or to the preference centre                                 |
| `{{unsubscribe_link}}`, `{{preferences_link}}`     | Ready-made "Unsubscribe" and "Manage preferences" links                          |
| `{{view_in_browser_url}}`                          | A link to this recipient's own copy of the email, opened in the browser          |

### Fallback values

Add a fallback after a pipe to cover contacts with no value: `Hi {{first_name|there}},` prints "Hi there," when the first name is empty.

The picker's **Custom** group lists your workspace's custom fields and inserts each as `{{customField:KEY}}`. They work in every send and are converted to the other platform's syntax by **Push to ESP**.

### View in browser

`{{view_in_browser_url}}` (and the **View Online** block, which uses it) links each recipient to a web page showing their copy of the email: campaigns, journey emails and transactional messages all fill it in. The page is on your [custom endpoint](/guides/sending-and-workspace/workspace-settings#custom-endpoint-url) when you have one, and opening it doesn't count as an open or a click.

For campaigns and journeys, the page is built again when it is opened, from the same template and the contact's **current** details, so an email sent before a contact changed their name shows the new name. Transactional emails show the copy that was sent. Anything that has since been deleted (the campaign send, the journey, the contact) makes the link show "no longer available". A test send's link opens a page that says it is a test. **Push to ESP** converts the tag to the other platform's own web-view link.

## Liquid

For anything beyond a simple value, templates support [Liquid](https://shopify.github.io/liquid/): conditions, loops and filters. Liquid works in the email body and the subject line.

```liquid theme={null}
Hi {{ contact.first_name | default: "there" }},

{% if data.order.total > 100 %}
  Your order qualifies for free shipping.
{% endif %}
```

What you can read depends on how the email is sent:

| Variable                                                                        | Contains                                                                                                        | Available in                      |
| ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| `contact.first_name`, `contact.last_name`, `contact.full_name`, `contact.email` | The recipient                                                                                                   | Everywhere                        |
| `contact.company`                                                               | The recipient's company                                                                                         | Everywhere                        |
| `customField.KEY` or `contact.KEY`                                              | A custom field value, by its key                                                                                | Everywhere                        |
| `data.*`                                                                        | The payload sent with the email: your API's `data`, an event's properties, a form submission or a Shopify order | Transactional emails and journeys |
| `event.*`                                                                       | The event that started the journey (`event.name`, `event.properties`, …)                                        | Journeys started by an event      |
| `unsubscribe_url`, `preferences_url`                                            | Recipient links                                                                                                 | Everywhere                        |

Values are HTML-escaped automatically, so data from your API can't inject markup. To output trusted HTML as-is, add `| raw`, for example `{{ data.promo_html | raw }}`.

<Tip>
  To show a list of items (order lines, products, articles), use the [Repeater or Item List block](/guides/email-and-templates/dynamic-lists) instead of writing a loop by hand.
</Tip>

## Preview as a contact

The **Preview** tab shows merge tags as written. To see real values, use **Preview as…** in the toolbar.

<Steps>
  <Step title="Open Preview as…">
    Click **Preview as…** (the person icon) in the toolbar.
  </Step>

  <Step title="Choose who to preview as">
    Pick **Me**, **A contact** (search by email), **A list** or **A segment**. For a list or segment, use the arrows to step through its members one at a time.
  </Step>

  <Step title="Check the result">
    The **Preview** tab now renders the email exactly as that person would receive it, including the subject line.
  </Step>
</Steps>

## Sample data

**Template data** in the same panel is the JSON payload the email is previewed with: what your API sends as `data`, or what an event carries. Paste the contents of `data`, without a `"data"` wrapper. If you paste it wrapped, the panel warns you and offers **Remove the wrapper**.

* **Update preview** re-renders with the JSON you typed.
* **Save** stores it on the template as its sample data, so everyone on your team previews with it.
* **Load from a recent send…** fills in the payload from a recent transactional send of this template.

The test email uses the same contact and data when you click **Send test with this preview context**.

## Variables and required variables

The **Variables** list shows every value the template reads. Any the current contact and sample data don't provide are marked **missing**.

Tick **required** next to a variable to make it mandatory. When a transactional API send doesn't provide a required variable, the send is refused instead of going out with a blank. This is useful for things like a password-reset link. See [Transactional email](/guides/developers/transactional-email).

<Note>
  Required variables are enforced for transactional API sends. Campaigns and journeys don't check them.
</Note>

## What happens when Liquid fails

If a template contains Liquid that can't be rendered:

* **Campaigns** skip that recipient. The message log shows `Template error:` with the reason.
* **Journeys** fail the email step with the reason.
* **Transactional API** requests are rejected with an error.

Use **Preview as…** before sending. It catches syntax errors and missing values.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The email shows {{first_name}} literally">
    Check the spelling and that there are exactly two braces on each side. Tags the system doesn't recognize are left as they are.
  </Accordion>

  <Accordion title="A value comes out blank">
    Open **Preview as…** and look at the **Variables** list. A variable marked **missing** isn't in the contact's record or the sample data. Remember that `data.*` is empty in campaigns.
  </Accordion>

  <Accordion title="Everything under data.* is blank even though I pasted sample data">
    Your JSON is probably wrapped in a `"data"` key, so the template would need `data.data.*`. Click **Remove the wrapper**.
  </Accordion>
</AccordionGroup>
