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

# Banner Types

> Define the fields merchandising banners carry to your storefront. Reuse typed schemas across rules to render richer promos than image and link.

A **banner type** is a reusable field schema attached to a merchandising banner. It gives a banner named, typed fields — headline, subheadline, product reference, expiration timestamp — that flow through as a structured `data` object on the [browse response](/api-reference/browse). Your storefront reads those fields to render richer promos than a plain image plus link.

Every store starts with a built-in **Link** type. Custom types are additive: existing banners keep working, and each rule can mix banners of different types up to the five-banner-per-rule limit.

## The link system type

Every store has a system banner type with slug `link` and a single field:

* `link` (URL, optional) — the click-through URL for `inject` banners.

`link` cannot be edited or deleted. Banners created before custom types shipped are treated as `link` banners and keep their previous behavior — the storefront still reads `banner.link` at the top level for those.

## Custom banner types

Create a custom banner type when you want banners with more than an image and a click-through URL — for example, a countdown promo that carries an `end_at` timestamp, or a spotlight banner that references a specific product and pulls its live handle.

A custom banner type has:

* **Name** — human-readable, shown when merchandisers pick a type on a banner (e.g. "Countdown Promo").
* **Slug** — a lowercase snake\_case identifier derived from the name at creation and locked afterward. The slug appears as `banner.type` on the [browse response](/api-reference/browse) and is the discriminator your storefront switches on.
* **Allowed Modes** — one or both of `inject` and `overtake`. A banner using this type can only be saved in a mode you allow here. This lets you forbid link-only variants on hero placements, for example.
* **Field Schema** — the ordered list of fields merchandisers fill in when they attach a banner of this type. Each field has a `key`, `label`, `type`, `required` flag, and per-field `validations`.

### Field types

Field types match Shopify's [metafield type taxonomy](https://shopify.dev/docs/apps/build/custom-data/metafields/list-of-data-types) so the shape of the data you get is predictable and portable.

| Group       | Type                     | Value shape                                        | Validations                                          |
| :---------- | :----------------------- | :------------------------------------------------- | :--------------------------------------------------- |
| General     | `single_line_text_field` | string                                             | **Pattern**, **Allowed values**                      |
| General     | `multi_line_text_field`  | string                                             | —                                                    |
| General     | `rich_text_field`        | Shopify rich-text JSON AST object                  | —                                                    |
| General     | `number_integer`         | integer                                            | **Minimum**, **Maximum**                             |
| General     | `number_decimal`         | decimal string                                     | **Minimum**, **Maximum**, **Maximum decimal places** |
| General     | `boolean`                | boolean                                            | —                                                    |
| General     | `date`                   | `YYYY-MM-DD` string                                | **Minimum**, **Maximum**                             |
| General     | `date_time`              | ISO-8601 string                                    | **Minimum**, **Maximum**                             |
| General     | `url`                    | string, `http`/`https` only                        | —                                                    |
| General     | `color`                  | `#RRGGBB` or `#RRGGBBAA` hex string                | —                                                    |
| General     | `money`                  | `{ "amount": "12.50", "currency_code": "USD" }`    | —                                                    |
| General     | `rating`                 | `{ "value": 4.5, "scale_min": 1, "scale_max": 5 }` | **Minimum**, **Maximum** (both required)             |
| General     | `json`                   | arbitrary JSON value                               | —                                                    |
| General     | `link`                   | `{ "url": "https://…", "text": "Shop now" }`       | —                                                    |
| General     | `id`                     | string                                             | —                                                    |
| General     | `language`               | ISO 639-1 code string                              | —                                                    |
| Measurement | `dimension`              | `{ "value": <number>, "unit": <unit> }`            | **Minimum**, **Maximum**                             |
| Measurement | `weight`                 | `{ "value": <number>, "unit": <unit> }`            | **Minimum**, **Maximum**                             |
| Measurement | `volume`                 | `{ "value": <number>, "unit": <unit> }`            | **Minimum**, **Maximum**                             |
| Reference   | `product_reference`      | local product id string                            | —                                                    |
| Reference   | `collection_reference`   | local collection id string                         | —                                                    |
| Reference   | `variant_reference`      | local variant id string                            | —                                                    |
| Reference   | `file_reference`         | `{ "id": …, "url": …, "alt": … }`                  | **Accepted files** (images, videos, or both)         |

Measurement units:

* `dimension`: `mm`, `cm`, `m`, `in`, `ft`, `yd`
* `weight`: `g`, `kg`, `oz`, `lb`
* `volume`: `ml`, `cl`, `l`, `m3`, `us_fl_oz`, `us_pt`, `us_qt`, `us_gal`, `imp_fl_oz`, `imp_pt`, `imp_qt`, `imp_gal`

Any general/measurement/reference type except the JSON, rich text, multi-line text, boolean, money, ID, and language types can be turned into a **list** with a minimum and maximum number of list items.

### Reference resolution

When a field is `product_reference`, `collection_reference`, or `variant_reference` (or a list of those), merchandisers pick a resource in the dashboard and Layers stores its local ID. On the browse response, Layers resolves each ID to a stable payload before shipping it:

```json theme={null}
{
  "id": "8123456789012",
  "handle": "canvas-tote-bag"
}
```

Unpublished references (product/variant not published on the surface serving the request) are dropped — the field is either omitted (single reference) or filtered out of the list (list of references). This means the storefront never has to guard against dead handles or 404s.

## Payload shape

Every banner in the [browse response](/api-reference/browse) carries the same envelope regardless of type:

```json theme={null}
{
  "id": "01KWD5S5R50690NXFW32PXM0V2",
  "name": "Fall promo",
  "mode": "inject",
  "link": "https://shop.example.com/collections/fall",
  "type": "countdown_promo",
  "data": {
    "headline": "Fall drop is live",
    "cta_label": "Shop the drop",
    "end_at": "2026-10-31T23:59:59Z",
    "spotlight_product": { "id": "8123456789012", "handle": "canvas-tote-bag" }
  },
  "sort_index": 0,
  "web_media": { /* ... */ },
  "mobile_media": { /* ... */ },
  "web_layout":    { "placement": "inline", "width": 1, "height": 1, "position": 1 },
  "mobile_layout": { "placement": "inline", "width": 1, "height": 1, "position": 1 }
}
```

The two type-driven fields are:

| Field  | Type   | Description                                                                                                                                                                        |
| :----- | :----- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | string | Banner type slug — either `link` (system) or the slug of one of your custom types. Storefronts switch renderers on this.                                                           |
| `data` | object | The saved values for that type's field schema. Keys match the schema's `key` values. Only keys defined in the current schema are returned — retyped or removed fields are dropped. |

`link` banners still carry a top-level `link` on the envelope so existing storefront code keeps working. Custom types can define their own `link` field inside `data` if they want a click-through URL that lives in structured data.

## Editing a banner type

Renaming a type or reordering its fields is safe. Two changes are **destructive** because they invalidate stored banner values:

* **Removing a field** — the value stored on every banner of this type is dropped.
* **Retyping a field** (`single_line_text_field` → `url`, or removing/adding the `list.` prefix) — the value stored on every banner of this type is dropped, since Layers cannot safely coerce between shapes.

The dashboard surfaces a warning listing the affected banners before you save. There is no automatic migration — write the new schema to accept the old values first (for example, keep both the old and new field on the type until you have rewritten each banner), then remove the old field in a follow-up save.

## Deleting a banner type

Banner types can only be deleted when no banner references them. If any rule still has a banner of that type, the dashboard rejects the delete and lists the specific banners so you can retype or remove them first. The system `link` type cannot be deleted.

## Limits and behavior

* **One system type per store** (`link`). Custom types are unlimited.
* **Slug is locked at creation.** The slug is the storefront's payload discriminator, so Layers derives it from the name once and never re-derives it. Rename the type freely; the slug does not change.
* **Cache invalidation runs on any banner-type change.** Editing a type flushes every rule that uses it so the new schema takes effect on the next browse response.
* **[Config history](/help/configuration/config-history)** captures banner-type create/update/delete alongside rule and banner changes.

## See also

* [Banner Injection](/platform/merchandising/banners) — how banners plug into merchandising rules.
* [Create a banner type](/help/configuration/create-banner-type) — dashboard walkthrough.
* [Add a banner to a merchandising rule](/help/merchandising/add-banner-to-rule) — how merchandisers pick a type and fill in its fields.
* [Rendering banners in Liquid](/developers/rendering-banners-in-liquid) — theme-side switch on `banner.type`.
* [Rendering banners with the SDK](/developers/rendering-banners-with-the-sdk) — SDK equivalent.
