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

# Dynamic lists (Repeater and Item List)

> Show one row or card per item in your data, such as the products in an order or cart, with the Repeater and Item List blocks.

Order confirmations, abandoned-cart reminders and digests all show a list whose length changes from one email to the next. Two blocks handle this for you:

| Block         | Use it when                                                                                 |
| ------------- | ------------------------------------------------------------------------------------------- |
| **Item List** | You want a ready-made product table: image, name, variant, quantity, price and a total row. |
| **Repeater**  | You want to design each row yourself with any blocks: text, images, buttons, columns.       |

Both are in the **Advanced blocks** group of the block palette. Both read an array at a dotted path in the email's data, usually under `data.*`, so they're filled in for **transactional emails** and **journeys**. See [Personalization](/guides/email-and-templates/personalization) for where that data comes from.

<Note>
  Campaign emails have no `data`, so a Repeater or Item List whose path starts with `data.` shows its "empty" text in a campaign. Campaigns can use [data feeds](/integrations/data-feeds) instead: point the path at an array in `global_feed` or `recipient_feed` and the block fills in.
</Note>

## Item List

<Steps>
  <Step title="Add the block">
    Open **Advanced blocks** in the palette and add **Item List**.
  </Step>

  <Step title="Point it at your data">
    Under **Data Source**, set **Items path** to the array to list. It defaults to `data.cart.items`. For a Shopify order in a journey, use `data.order.line_items`.
  </Step>

  <Step title="Set the total and button">
    Under **Total Row**, set **Total path** (default `data.cart.total`). Under **CTA Button**, set the link. It can be a merge tag or Liquid, for example `{{ data.cart.url }}`.
  </Step>

  <Step title="Style it">
    Choose which columns to show (**Show Image**, **Show Variant**, **Show Quantity**), whether to show the header row, and fonts and colors for items and prices. Set the **Currency symbol** and the **Text when there are no items**.
  </Step>
</Steps>

Each item in the array can have these fields: `title`, `variant_title`, `quantity`, `price` and `image_url`.

```json theme={null}
{
  "cart": {
    "items": [
      { "title": "Classic Sneakers", "variant_title": "Size 10 / White", "quantity": 1, "price": "89.00", "image_url": "https://…" }
    ],
    "total": "89.00",
    "url": "https://shop.example.com/cart"
  }
}
```

On the canvas, the block uses its own **Sample Items (Preview)**. Click **+ Add Sample Item** to add more. **View Sample JSON Payload** shows the shape your API should send.

## Repeater

A Repeater is a container: whatever you put inside it is repeated once per item.

<Steps>
  <Step title="Add a Repeater">
    Open **Advanced blocks** and add **Repeater**.
  </Step>

  <Step title="Choose the array">
    Set **Repeats over** to the path of the array, for example `data.order.line_items` (the default) or `data.articles`.
  </Step>

  <Step title="Add blocks inside it">
    Drop blocks into the Repeater's area on the canvas (**Drop the blocks to repeat here**).
  </Step>

  <Step title="Insert item fields">
    Select a text block inside the Repeater and open **Merge Tag**. A **Current item** group lists every field of your sample data's first item as `{{ item.<field> }}`.
  </Step>
</Steps>

Other settings:

* **Item variable**: the name used inside the loop. It's `item` by default, so fields are written `{{ item.title }}`.
* **Layout**: **Rows** or **Cards**.
* **Max items (0 = all)**: limit how many items are shown.
* **Text when empty**: shown once if the array is missing or empty.
* **Gap between items**, background, border and padding.

You can also use `{{ forloop.index }}` inside a Repeater to print the item's position (1, 2, 3…).

## Sample data for the canvas

Both blocks need sample data to show something useful while you design:

* The Repeater badge shows **×N with sample data** when it finds an array at its path, and **No sample data at this path** when it doesn't.
* Set sample data in **Preview as…** under **Template data**. See [Personalization](/guides/email-and-templates/personalization#sample-data).
* If the template has no sample data of its own, the **Preview data** section of the block offers **Copy sample order to this template**, which saves a ready-made example order you can edit.

<Tip>
  Paste a real payload from one of your recent sends with **Load from a recent send…** in the Preview as… panel. The field names in the **Current item** group then match your real data exactly.
</Tip>

## Limits

* The path must be a plain dotted path such as `data.order.line_items`. Liquid filters or expressions aren't accepted there.
* In the AMP version of an email, a Repeater's contents are shown once, not per item.
* The data sent with one email can be up to 256 KB and 32 levels deep.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The list is empty in my test email">
    A plain test send uses the sample data saved on the template. Open **Preview as…**, add sample data and click **Save**, or click **Send test with this preview context** to use it without saving.
  </Accordion>

  <Accordion title="The Current item group doesn't appear in the merge-tag picker">
    The picker shows it only for blocks inside a Repeater. Inside one, the group always appears with at least `{{ forloop.index }}`. The item's own fields appear only when the sample data (yours, or the built-in sample order when the template has none) has an array at the Repeater's path.
  </Accordion>

  <Accordion title="Prices show the wrong currency">
    The Item List prints the **Currency symbol** you set on the block before each price. It doesn't read a currency from your data.
  </Accordion>
</AccordionGroup>
