> ## 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.

# Automation steps

> What each step in an automation does — send email, wait, update contact, list and webhook actions, ad steps, If/Else conditions, A/B splits and Join.

After the [trigger](/guides/audience-and-campaigns/automation-triggers), you build the journey from steps in the **Step palette**. Click a step on the canvas to open its panel. There you can name the step, set it up, **Duplicate step** or **Delete step**.

| Palette section  | Steps                                                                                                                                                            |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Actions**      | **Send Email**, **Wait / Delay**, **Update Contact**, **Add to List**, **Remove from List**, **Send Webhook**, **Sync to Ad Audience**, **Advertising campaign** |
| **Conditions**   | **A/B Split**, **If/Else Condition**                                                                                                                             |
| **Flow Control** | **Join / Merge**                                                                                                                                                 |

Every path ends at the **Exit** node. Exit is always on the canvas and can't be removed.

## Send Email

<Steps>
  <Step title="Choose the template">
    Under **Email template**, click **Choose template** and pick one of your approved templates. Library designs only appear here after you've made them your own under **Templates**. To change the email, click **Edit template**. The builder opens, and saving brings you back to the journey. **Change template** swaps in a different one.
  </Step>

  <Step title="Write the subject line">
    Enter a **Subject line**. You can use Liquid in it. The template is the body and the subject comes from the step, so both are required.
  </Step>

  <Step title="Pick the sender and send policy (optional)">
    **Sender profile** decides who the email is from. Leave it blank to use the sender that the send policy provides. **Send policy** decides the delivery route and the default sender. If you don't pick one, the **Marketing default** is used. See [Send policies](/guides/audience-and-campaigns/send-policies).
  </Step>
</Steps>

Validation won't let you activate a journey whose **Send Email** step has no template or no subject line. If a translation of the template for the contact's language has its own subject, that subject is used instead of the step's. If a step still ends up with no subject when it runs, nothing is sent: the step fails and **Logs** shows why.

Journey emails are rendered the same way as transactional emails. You can use these tags in the subject and the body:

* Contact merge tags such as `{{ first_name }}` and `{{ email }}`
* The trigger's payload as `data`, for example `{{ data.order.total }}`. This is the `data` from an API call, the properties of an event, the answers from a form, or a normalised Shopify order.
* The event that started the journey as `event`, for example `{{ event.name }}`. This is only set when an event started the journey.

Liquid loops and conditions work, for example `{% for item in data.items %}…{% endfor %}`. If the Liquid in a template has an error, the step fails and **Logs** shows the reason.

With a **Marketing** policy, the email gets the unsubscribe footer and headers, and unsubscribed contacts are skipped. With a **Transactional** policy, there's no footer, and unsubscribed contacts still receive it. Bounced, complained and unconfirmed contacts are always skipped. If the contact has a language set and the template has a translation for it, they get the translation.

<Note>
  Journey email counts against your monthly email allowance. If the allowance runs out, the step waits instead of dropping the email. If your sending domain fails the deliverability check (or has hit its warm-up cap for the day), the email is skipped and **Logs** records why.
</Note>

## Wait / Delay

Set a **Delay amount** and a **Delay unit**: minutes, hours, days or weeks. The contact moves on to the next step once the delay has passed. A wait at the end of a path has no effect, so validation treats it as an error and the journey won't activate until you fix it.

## Update Contact

Choose a **Field**, then enter the **Value**:

* **First name**, **Last name** or **Source**.
* **Custom field**: then pick one of the fields defined under [Custom Fields](/guides/audience-and-campaigns/custom-fields). The value box follows the field's type: **Yes**/**No** for a boolean, the options for a select, a date picker for a date. The value is saved on the contact's custom field, so segments, `{{ customField.KEY }}` in emails and date-field schedules see it. If the value doesn't fit the field's type (for example text in a number field), or the field has been deleted, the step fails and **Logs** shows why.
* **Metadata key**: then enter the key, for example `plan`. This writes free-form data to the contact's `metadata`, not to a custom field.

## Add to List / Remove from List

Choose a **Contact list**.

* **Add to List** subscribes the contact to that list. This re-subscribes a contact who had unsubscribed from that one list, so use it with care. It won't send mail to someone who unsubscribed from everything, though: their contact status still blocks marketing email.
* **Remove from List** takes the contact off the list completely. It's a removal, not an unsubscribe, and it's recorded on the contact's timeline.

## Send Webhook

Posts to your own endpoint when a contact reaches the step.

| Field                        | Notes                                                                                                                                                                                                                            |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Webhook URL**              | Required. It must start with `http://` or `https://`. Private and internal addresses are blocked.                                                                                                                                |
| **HTTP method**              | POST (default), PUT or PATCH                                                                                                                                                                                                     |
| **Headers (JSON, optional)** | For example `{"X-Api-Key": "…"}`. These headers are removed before sending: `Authorization`, `Cookie`, `Proxy-Authorization`, `Host`, and any `X-Forwarded-*`, `X-Amz-*`, `X-Aws-*`, `X-Metadata-*` or `Metadata-Flavor` header. |
| **JSON body (optional)**     | Leave it blank to send a default payload with the journey and execution ids, the contact, and the trigger `data`. The default is also sent when your template doesn't render to valid JSON.                                      |

In a custom body, you can use `{{email}}`, `{{firstName}}`, `{{lastName}}` and dotted paths such as `{{ data.order.total }}` or `{{ event.name }}`. Objects and arrays are inserted as JSON, so write them without quotes.

The request times out after 10 seconds. Server errors (5xx), timeouts and network errors are tried up to 3 times in total. A 4xx response fails the step straight away.

## Ad steps

* **Sync to Ad Audience**: choose an **Ad audience** and an **Operation**, either **Add to audience** or **Remove from audience**. Only active contacts with an email address are synced.
* **Advertising campaign**: adds the contact to the audience of an ad campaign that was created for this journey. Contacts who reach the step start seeing the ad. A campaign that wasn't created from a journey has no audience for this step to use, so click **Create an ad campaign for this journey**.

For how to set up audiences and campaigns, see [Ads](/guides/ads/overview).

## If/Else Condition

Click **Configure conditions** to open the **Condition builder**. Each condition has a field, an operator and a value. You can use the same contact fields as the [segment builder](/guides/audience-and-campaigns/segments), such as status, list membership, email engagement and dates. You can also use **Payload value (data.\*)** with a dotted path such as `order.total` or `items[0].sku` to branch on the trigger's data.

To combine conditions, choose **ALL conditions** or **ANY condition**, or choose **Custom logic** and enter an expression such as `1 AND (2 OR 3)`.

The node has two outputs: **Yes** (the condition is met) and **No**. Connect at least one of them.

## A/B Split

Sends each contact down path **A** or path **B** at random. Drag the **Traffic to A** slider in steps of 5%, anywhere from **All B** through 50 / 50 to **All A**. The default is 50/50. On the canvas, the branches are labelled with their share, for example `A · 60%` and `B · 40%`.

Each contact is assigned once, when they reach the step, and the choice is saved on their journey timeline. Put a different email on each branch, then compare the per-step stats in **Analytics** to see which one did better.

<Tip>
  For A/B tests on a one-time campaign (subject, sender or content), use the campaign's A/B test instead. See [A/B testing and scheduling](/guides/audience-and-campaigns/ab-testing-and-scheduling).
</Tip>

## Join / Merge

Brings two or more paths back into one, for example after an If/Else. It has no settings. A step can have only one incoming connection, so use a Join wherever paths meet. Validation flags a Join with fewer than two incoming paths, and a Join placed right after the trigger.
