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

# Product add-on block

> The Aftersell Cart Product add-on block: offer one specific product as a quick add inside the drawer.

> The **Product add-on** block offers a single, specific product you choose as an add-on inside the cart, promoting one known product (a warranty, a sample, a best-seller) as a quick add directly in the cart.

<Info>
  Unlike [**Upsells**](/aftersell/cart/upsells-block), which surfaces products chosen by a strategy, the Product add-on always shows the exact product you pick.
</Info>

<Frame>
  <img src="https://mintcdn.com/aftersell/1Y3gBpUfxv16VGSW/images/aftersell/cart-product-add-on-block-additional-product.png?fit=max&auto=format&n=1Y3gBpUfxv16VGSW&q=85&s=29c7598c41c78f6503af7f9cd7ec084a" alt="Product add-on block offering an additional product for the shopper to include with their cart" width="678" height="125" data-path="images/aftersell/cart-product-add-on-block-additional-product.png" />
</Frame>

## Behavior

* **If no live variant resolves** — the product is unset, archived, or out of stock — the block renders **nothing** rather than a dead button.
* The control reflects whether *this block's own* add-on line is in the cart, so switching it off removes the line it added (and won't affect the same product added elsewhere).
* A compare-at price strikes through when there's a genuine markdown; the "% off" label is hidden if the discount rounds below 1%.
* The add-on image falls back to the product's featured image when the chosen variant has none.

## Settings

| Setting          | What it controls                                                                                     | Default                               |
| ---------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------- |
| **Display type** | How the add control appears: **Toggle** or **Checkbox**.                                             | Toggle                                |
| **Product**      | The product variant to offer — one picker covers both. Image and price come from the chosen variant. | None                                  |
| **Title**        | Rich-text heading.                                                                                   | `<strong>{{product_title}}</strong>`  |
| **Price label**  | The price line.                                                                                      | `{{price}}`                           |
| **Description**  | Supporting copy.                                                                                     | `Add {{product_title}} to your order` |

**Title**, **Price label**, and **Description** all support the same four tokens: `{{product_title}}`, `{{price}}`, `{{compare_at_price}}`, and `{{savings}}`.

## Placement and limits

* **Region:** body or bottom.
* **Maximum:** 3 per cart state — the filled cart and the empty cart each get their own allowance.
* **State:** both filled and empty cart.
* Not added by default. Not locked — you can remove or hide it.

## Custom template

Supports a [custom template](/aftersell/cart/custom-templates) from its Code tab, which replaces this block's built-in markup with your JSX. These are the props it receives.

### Content

| Prop                      | Type             | What it's for                                                                                               |
| ------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------- |
| `addonTitle`              | `string`         | Plain-text title. Use it for the alt text and `aria-label`, and as the fallback when there's no rich title. |
| `addonTitleHtml`          | `string`         | Sanitized rich-text title HTML. Empty when none.                                                            |
| `descriptionHtml`         | `string`         | Sanitized rich-text description HTML. Empty when none.                                                      |
| `formattedPrice`          | `string`         | Currency-formatted price label. Empty when not shown.                                                       |
| `formattedCompareAtPrice` | `string`         | Formatted variant compare-at (MSRP). Empty when there's no real saving.                                     |
| `savings`                 | `string`         | Whole-percent saving label, for example `25%`. Empty when there's no saving.                                |
| `priceHtml`               | `string \| null` | Sanitized rich-text price HTML from the dedicated price field. `null` when empty.                           |
| `ctaText`                 | `string`         | Button label, for the `button` format.                                                                      |
| `imageUrl`                | `string`         | Product image. Empty when none.                                                                             |
| `productUrl`              | `string`         | Product page URL. Empty when none, in which case don't link the image or title.                             |

### State and actions

| Prop           | Type                                 | What it's for                                                                                        |
| -------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| `variantId`    | `number \| null`                     | Resolved variant. `null` when there's no live variant, because the product is unset or out of stock. |
| `format`       | `'button' \| 'checkbox' \| 'toggle'` | How the buyer adds the add-on. Branch your markup on this.                                           |
| `isEnabled`    | `boolean`                            | Whether the add-on is currently in the cart.                                                         |
| `isAdding`     | `boolean`                            | `true` while the add or remove is in flight. Disable your control on this.                           |
| `handleAdd`    | `() => void`                         | Adds the add-on. For the `button` format.                                                            |
| `handleToggle` | `() => void`                         | Toggles the add-on in and out of the cart. For `checkbox` and `toggle`.                              |
| `isLoading`    | `boolean`                            | `true` while the cart is still doing its first fetch.                                                |

<Warning>
  `format` decides which handler applies: `handleAdd` for `button`, `handleToggle` for `checkbox` and `toggle`. A `null` `variantId` means there's nothing to add, so gate your control on it rather than calling a handler that can't succeed.
</Warning>

## Design

Style this block with its **Design** section in the settings panel. These are per-block overrides that layer on top of your global design and fall back to it when blank.

### Text

The **Text** section in Design lets you control the typography of three elements. Use the **Text element** picker to switch between them.

**Title** — the product name. Also supports a custom font family. Bold and text color are set in the Rich Text Editor above (in the Settings tab), not here.

| Setting            | What it controls             | Default             |
| ------------------ | ---------------------------- | ------------------- |
| **Font**           | Font family for the title.   | Inherits from theme |
| **Size**           | Font size.                   | `15px`              |
| **Line height**    | Line height multiplier.      | `1.33`              |
| **Letter spacing** | Tracking between characters. | Normal              |

**Price** — the price line. Bold and text color are set in the Rich Text Editor above.

| Setting            | What it controls             | Default |
| ------------------ | ---------------------------- | ------- |
| **Size**           | Font size.                   | `15px`  |
| **Line height**    | Line height multiplier.      | `1.33`  |
| **Letter spacing** | Tracking between characters. | Normal  |

**Description** — the supporting copy. Bold and text color are set in the Rich Text Editor above.

| Setting            | What it controls             | Default |
| ------------------ | ---------------------------- | ------- |
| **Size**           | Font size.                   | `14px`  |
| **Line height**    | Line height multiplier.      | `1.29`  |
| **Letter spacing** | Tracking between characters. | Normal  |

<Tip>
  Clicking a text element directly in the cart preview highlights it and opens its controls in the panel automatically.
</Tip>

What are design settings? Learn more here: [Design settings](/aftersell/cart/design-settings).
