# Web Components

[Nosto Web Components](https://github.com/Nosto/web-components) offers various custom elements for both store and campaign level templating.

## Components

This package provides the following web components:

| Component                           | Category                  |
| ----------------------------------- | ------------------------- |
| [Bundle](#bundle)                   | Templating (Shopify only) |
| [Campaign](#campaign)               | Progressive Enhancement   |
| [Control](#control)                 | Templating                |
| [DynamicCard](#dynamiccard)         | Templating (Shopify only) |
| [Image](#image)                     | Progressive Enhancement   |
| [Product](#product)                 | Progressive Enhancement   |
| [SectionCampaign](#sectioncampaign) | Templating (Shopify only) |
| [SimpleCard](#simplecard)           | Campaign level templating |
| [SkuOptions](#skuoptions)           | Progressive Enhancement   |
| [VariantSelector](#variantselector) | Campaign level templating |

### `Campaign`

The `Campaign` custom element is a general-purpose solution for injecting or templating campaign results dynamically. It supports both HTML and JSON response modes and is designed for dynamic use cases like rendering nested campaign results.

#### Component attributes

| Attribute     | Description                                                                                                                                                                                                                     |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `placement`   | **Required.** Placement ID used to fetch campaign content (e.g. `frontpage-nosto-1`). Can also use `id` attribute as an alternative.                                                                                            |
| `product-id`  | Product ID for contextual recommendations. If provided, the campaign is scoped to that product                                                                                                                                  |
| `variant-id`  | Reference to variant id. Refines the context to a specific product variant. Only used when `product-id` is provided                                                                                                             |
| `template`    | Name of the template to use. If provided, the campaign will use a JSON response and evaluate it using the given client-side template. If omitted, Nosto injects pre-rendered HTML from the backend directly into the component. |
| `init`        | For disabling automatic campaign loading on page load, set to `false`. Defaults to `true`.                                                                                                                                      |
| `lazy`        | If present, the component will only load the campaign when it comes into view using IntersectionObserver. Defaults to `false`.                                                                                                  |
| `cart-synced` | If present, the component will reload the campaign whenever a cart update event occurs. Useful for keeping cart-related campaigns in sync with cart changes. Defaults to `false`. Available since version 8.29.0.               |
| `nav-synced`  | If present, the component will reload the campaign on page navigation via the Navigation API. Requires browser support. Defaults to `false`.                                                                                    |

{% hint style="info" %}
In case if the merchant is using Nosto's velocity template for rendering recommendations, it is recommended to use the `id` attribute with `nosto-campaign` instead of the `placement` attribute for easier element targeting, using `#$divId` , in styling and template logic.
{% endhint %}

#### Usage examples

**Example #1**:

Static campaign rendering:

```html
<nosto-campaign placement="best-sellers"></nosto-campaign>
```

or alternatively

```html
<nosto-campaign id="best-sellers"></nosto-campaign>
```

for better compatibility with the scoped styling conventions of Velocity templates

**Example #2**:

Product-specific campaign:

```html
<nosto-campaign
  placement="best-sellers"
  product-id="123456"
  variant-id="sku-789">
</nosto-campaign>
```

**Example #3**:

Template-based rendering:

```html
<nosto-campaign placement="best-sellers">
  <template>
    <div class="product-card" v-for="product in products">
      <a :href="product.url">
        <img :src="product.imageUrl" />
      </a>
      <span class="product-name">{{ product.name }}</span>
      <span class="product-price">{{ product.price }}</span>
    </div>
  </template>
</nosto-campaign>
```

**Example #4**:

Campaign with lazy loading:

```html
<nosto-campaign placement="below-fold-recommendations" lazy></nosto-campaign>
```

**Example #5**:

Campaign with cart synchronization:

```html
<nosto-campaign placement="cart-recommendations" cart-synced></nosto-campaign>
```

**Example #6**:

Campaign with multiple features combined:

```html
<nosto-campaign placement="related-products" product-id="123456" cart-synced lazy></nosto-campaign>
```

A subset of Vue is used as the templating language. The template support is described in detail below.

{% hint style="info" %}
Checkout our API documentation for \`nosto-campaign\` custom element [here](https://nosto.github.io/web-components/classes/Campaign.html)
{% endhint %}

### `SectionCampaign`

The `SectionCampaign` custom element fetches Nosto placement results and renders them using Shopify's Section Rendering API. This component is specifically designed for Shopify stores and integrates with Shopify's section templates to dynamically render campaign content.

#### Component attributes

| Attribute        | Description                                                                          |
| ---------------- | ------------------------------------------------------------------------------------ |
| `placement`      | **Required.** Placement ID used to fetch campaign content (e.g. `frontpage-nosto-1`) |
| `section`        | **Required.** The section to be used for Section Rendering API based rendering       |
| `title-selector` | Optional. CSS selector for the title element to inject the campaign title            |

#### Usage examples

**Example #1**:

Basic usage with Shopify section rendering:

```html
<nosto-section-campaign placement="front-page" section="product-recommendations"></nosto-section-campaign>
```

**Example #2**:

Advanced usage for specific product page recommendations:

```html
<nosto-section-campaign placement="product-page-cross-sell" section="related-products-section"></nosto-section-campaign>
```

{% hint style="info" %}
Checkout our API documentation for \`nosto-section-campaign\` custom element [here](https://nosto.github.io/web-components/classes/SectionCampaign.html)
{% endhint %}

### `Control`

The `Control` custom element provides conditional content rendering capabilities to inject customer segment specific content to the web page. The segment specific injections are defined as template children of the custom element.

The default content can be defined as follow up children of the custom element.

#### Usage example

```html
<nosto-control>
 <template segment="5a497a000000000000000001">New visitor content</template>,
 <template segment="5b71f1500000000000000006">Returning visitor content</template>
</nosto-control>
```

The content of the element will become `New visitor content` for new visitors and `Returning visitor content` for returning visitors.

{% hint style="info" %}
Checkout our API documentation on \`nosto-control\` custom element [here](https://nosto.github.io/web-components/classes/Control.html)
{% endhint %}

### `DynamicCard`

`DynamicCard` is a custom element that delegates the product card rendering fully to Shopify with a given product handle and a reference to an alternate template to use. We recommend to skip the layout rendering in the alternative template.

This custom element is the recommended choice to use when the product card markup should be fully managed in Shopify templates instead of being spread to Shopify themes and Nosto templates.

#### Component attributes

| Attribute     | Description                                                                                                      |
| ------------- | ---------------------------------------------------------------------------------------------------------------- |
| `handle`      | **Required.** Handle of the product                                                                              |
| `section`     | Name of the product level section to use for rendering. Required unless using deprecated `template` attribute.   |
| `template`    | **\[DEPRECATED]** Use `section` instead. Name of the alternate template (supported for backwards compatibility). |
| `variant-id`  | Optional reference to variant id                                                                                 |
| `placeholder` | If `true`, the component will display placeholder content while loading. Defaults to `false`.                    |
| `lazy`        | If `true`, the component will only fetch data when it comes into view. Defaults to `false`.                      |
| `mock`        | If `true`, the component will render mock markup instead of fetching real data. Defaults to `false`.             |

#### Usage examples

The `DynamicCard` component relies on alternate product card templates to be exposed from Shopify. Here are example instructions for the Dawn theme:

* Identify the product grid section of the collection template
  * `main-collection-product-grid in Dawn`
* Identify the product card snippet in the product grid section
  * `card-product in Dawn`
* Copy the card snippet usage into a new product template (e.g. `product.card.liquid` under `templates`)

In addition to template targeting `DynamicCard` supports also the targeting of sections, in case you want to expose the product card as a section instead of a custom template.

```markup
{% layout none %}
{% render 'card-product', card_product: product %}
```

Make sure that web components are enabled in the Nosto Recommendation Settings after completion of the Shopify side changes.\
After that the component can be used in Nosto templates like this

**Example #1**:

Basic usage with template:

```markup
#foreach($product in $products)
<nosto-dynamic-card handle="$!product.handle" template="card">
  <div class="product-card-skeleton"></div>
</nosto-dynamic-card>
#end
```

**Example #2**:

Using with section and placeholder:

```markup
#foreach($product in $products)
<nosto-dynamic-card handle="$!product.handle" section="product-card-section" placeholder lazy>
  <div class="loading-placeholder">Loading...</div>
</nosto-dynamic-card>
#end
```

{% hint style="info" %}
Checkout our API documentation on \`nosto-dynamic-card\` custom element [here](https://nosto.github.io/web-components/classes/DynamicCard.html)
{% endhint %}

### `Image`

`Image` is a web component that provides response image rendering capabilities using the [unpic](https://unpic.pics/about/) library. It supports Shopify and BigCommerce thumbnails out of the box and uses the same configuration model and unpic's own web components. It can be used as a `img` element replacement with smart rendering capabilities.

#### Component attributes

| Attribute        | Description                                                                                                                                    |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `src`            | **Required.** The source URL of the image.                                                                                                     |
| `width`          | The width of the image in pixels.                                                                                                              |
| `height`         | The height of the image in pixels.                                                                                                             |
| `aspect-ratio`   | The aspect ratio of the image (width / height value).                                                                                          |
| `crop`           | Shopify only. The crop of the image. Can be "center", "left", "right", "top", or "bottom".                                                     |
| `layout`         | The layout of the image. Can be "fixed", "constrained", or "fullWidth". Defaults to "constrained".                                             |
| `alt`            | Alternative text for the image for accessibility purposes.                                                                                     |
| `sizes`          | The sizes attribute for responsive images to help the browser choose the right image size.                                                     |
| `loading`        | The loading behavior of the image. Use "lazy" for lazy loading or "eager" for immediate loading. Defaults to "lazy".                           |
| `fetch-priority` | Provides a hint to the browser about the priority of this image relative to other images. Can be "high", "low", or "auto". Defaults to "auto". |
| `breakpoints`    | Custom widths (as an array of numbers) for responsive image generation. Default breakpoints are generated based on common screen sizes.        |
| `unstyled`       | When present, prevents inline styles from being applied to the image element. Defaults to `false`.                                             |

#### Usage examples

**Example #1**:

Usage with Shopify image URL:

```html
<nosto-image src="https://cdn.shopify.com/static/sample-images/bath.jpeg" width="800" height="600" layout="constrained" crop="center"></nosto-image>
```

**Example #2**:

Usage with BigCommerce image URL:

```html
<nosto-image src="https://cdn11.bigcommerce.com/s-hm8pjhul3k/products/4055/images/23603/7-15297__04892.1719977920.1280.1280.jpg" width="800" height="600" layout="constrained"></nosto-image>
```

**Example #3**:

Usage with responsive sizes attribute:

```html
<nosto-image
  src="https://cdn.shopify.com/static/sample-images/bath.jpeg"
  width="800"
  aspect-ratio="1.5"
  layout="constrained"
  alt="Product showcase image"
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw">
</nosto-image>
```

{% hint style="info" %}
Checkout our API documentation on \`nosto-image\` custom element [here](https://nosto.github.io/web-components/classes/Image.html)
{% endhint %}

### `Product`

When markup (HTML) for rendering a product is wrapped with the `Product` component, the APIs for SKU selection and Add to cart functionality are automatically handled by the component. By encapsulating the necessary APIs, this component reduces any JavaScript logic that would otherwise be included in the template and helps the team to concentrate only on building the template rather than implementing the JavaScript logic.

#### Component attributes

| Attribute      | Description                                                                                                                        |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `product-id`   | **Required.** Id of the product being rendered. `$!product.productId` provides the Product Id in templates.                        |
| `reco-id`      | **Required.** The Id of the recommendation being rendered. `$!product.attributionKey` provides the Recommendation Id in templates. |
| `sku-selected` | Boolean attribute that indicates whether a SKU is currently selected. Automatically managed by the component.                      |

**Note**:\
The following examples of rendering product SKUs are applicable only for simple use-cases. For complex cases, like multi-directional SKU selections where selecting color renders the matching size and vice-versa, consider using the `SkuOptions` component.

#### Usage examples

**Example #1**:

Render Product with SKU selection dropdown and an "Add to cart" button:

```html
<nosto-product product-id="123456" reco-id="789011">
  ...
  <select n-sku-selector>
    <option value="456">SKU 1</option>
    <option value="457">SKU 2</option>
  </select>
  ...
  <div n-atc>Add to cart</div>
  ...
</nosto-product>
```

**Example #2**:

Render Product with individual SKU item acting as "Add to cart" button.

```html
<nosto-product product-id="123456" reco-id="789011">
  ...
  <div n-sku-id="456">
    <span n-atc>Blue</span>
  </div>
  <div n-sku-id="101">
    <span n-atc>Black</span>
  </div>
  ...
</nosto-product>
```

#### Markup Attributes

This component requires the following attributes to parse the markup, extract product & SKU data and attach the event handlers to the selector/button elements:

| Attribute        | Description                                                                                                                                                                 |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `n-sku-selector` | Marks the SKU select dropdown. Attaches an `onchange` event to the element. Clicking on the "Add to cart" button adds the SKU value selected from the dropdown to the cart. |
| `n-sku-id`       | Relevant when SKU options are rendered as "Add to cart" button. Supplies the ID of the SKU option value and should be supplied on the parent of "Add to cart" button.       |
| `n-sku-data`     | To be applied on an optional script element with SKU data as a JSON array of { price, listPrice, image, altImage } entries                                                  |
| `n-img`          | Image URL for SKU which will be applied to Product wrapper on click                                                                                                         |
| `n-alt-img`      | Alternate image URL for SKU which will be applied to Product wrapper on                                                                                                     |
| `n-price`        | Price for SKU which will be applied to Product wrapper on click                                                                                                             |
| `n-list-price`   | List price for SKU which will be applied to Product wrapper price on click                                                                                                  |
| `n-atc`          | Marks an element as Add to cart trigger and attaches click event to the element. Clicking on this element triggers `addSkuToCart` API and supplies the selected SKU Id.     |

```html
<div n-sku-id="456">
  <span n-atc>Blue</span>
</div>
```

{% hint style="info" %}
Checkout our API documentation on \`nosto-product\` custom element [here](https://nosto.github.io/web-components/classes/Product.html)
{% endhint %}

### `SkuOptions`

The `SkuOptions` component is recommended for cases rendering multiple SKU option groups (color, size). It manages the state and interactions of SKU options, including pre-selection, state changes, and click events.

#### Component attribute

Requires one mandatory attribute

| Attribute | Description                                                                                                                   |
| --------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `name`    | A required attribute supplied on the `nosto-sku-options` element. Supplies the option group name (color/size/material etc...) |

#### Usage examples

**Example #1**:

Dual SKU selection group

```html
<nosto-product product-id="1223456" reco-id="789011">
  <nosto-sku-options name="color">
    <span n-option n-skus="123,145">Black</span>
    <span n-option n-skus="223,234,245">White</span>
    <span n-option n-skus="334,345">Blue</span>
  </nosto-sku-options>
  <nosto-sku-options name="size">
    <span n-option n-skus="123,223">L</span>
    <span n-option n-skus="234,334">M</span>
    <span n-option n-skus="145,245,345">S</span>
  </nosto-sku-options>
  <span n-atc>Add to cart</span>
</nosto-product>
```

**Example #2**:

Trio SKU selection group

```html
<nosto-product product-id="1223456" reco-id="789011">
  <nosto-sku-options name="color">
    <span n-option n-skus="123,145">Black</span>
    <span n-option n-skus="223,234,245">White</span>
    <span n-option n-skus="334,345">Blue</span>
  </nosto-sku-options>
  <nosto-sku-options name="size">
    <span n-option n-skus="123,223">L</span>
    <span n-option n-skus="234,334">M</span>
    <span n-option n-skus="145,245,345">S</span>
  </nosto-sku-options>
  <nosto-sku-options name="material">
    <span n-option n-skus="123,234,345">Cotton</span>
    <span n-option n-skus="145,223,334">Silk</span>
    <span n-option n-skus="245">Wool</span>
  </nosto-sku-options>
  <span n-atc>Add to cart</span>
</nosto-product>
```

**Example #3**:

Usage with select elements

```html
<nosto-product product-id="1223456" reco-id="789011">
  <nosto-sku-options name="color">
    <select n-target>
      <option value="black" n-skus="123,145">Black</option>
      <option value="white" n-skus="223,234,245">White</option>
      <option value="blue" n-skus="334,345">Blue</option>
    </select>
  </nosto-sku-options>
  <nosto-sku-options name="size">
    <select n-target>
      <option value="l" n-skus="123,223">L</option>
      <option value="m" n-skus="234,334">M</option>
      <option value="s" n-skus="145,245,345">S</option>
    </select>
  </nosto-sku-options>
  <span n-atc>Add to cart</span>
</nosto-product>
```

#### Markup Attributes

| Attribute      | Description                                                                                                                                                                                      |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `n-option`     | Marks an element as SKU option element                                                                                                                                                           |
| `n-target`     | Applied to a `<select>` element to indicate it should be used for option selection instead of individual `n-option` elements                                                                     |
| `n-skus`       | Comma-separated value of linked available SKU Ids. `$!product.getSkuAggregateOptions` method in templates provides the Sku aggregates for the supplied custom field (color/size/material etc...) |
| `n-skus-oos`   | Comma-separated value of linked unavailable SKU Ids. The usage of this parameter is optional and should be considered when Out of stock SKUs should be considered.                               |
| `n-img`        | Image URL for SKU option which will be applied to Product wrapper on click                                                                                                                       |
| `n-alt-img`    | Alternate image URL for SKU option which will be applied to Product wrapper on click                                                                                                             |
| `n-price`      | Price for SKU option which will be applied to Product wrapper on click                                                                                                                           |
| `n-list-price` | List price for SKU option which will be applied to Product wrapper price on click                                                                                                                |

Disabled options that are not available due to selections in other groups are marked with the `disabled` attribute and unavailable options that are Out of stock are marked with the `unavailable` attribute. Both should be styled distinctively.

#### Pre-selected options

In addition to handling APIs, supports pre-selection of SKU options. For example in the template below, option `SKU 2` is rendered with `selected` attribute. With this template, when clicking "Add to cart" button, `SKU 2` gets added to the cart.

```html
<nosto-product product-id="123456" reco-id="789011">
  ...
  <select n-sku-selector>
    <option value="456">SKU 1</option>
    <option value="457" selected>SKU 2</option>
  </select>
  ...
  <button n-atc>Add to cart</button>
  ...
</nosto-product>
```

with `nosto-sku-options` component

```html
<nosto-product product-id="123456" reco-id="789011">
  ...
  <nosto-sku-options name="colors">
    <span black n-option n-skus="123,145" selected>Black</span>
    <span white n-option n-skus="223,234,245">White</span>
    <span blue n-option n-skus="334,345">Blue</span>
  </nosto-sku-options>
  ...
</nosto-product>
```

Note:\
The component does not handle styling for selected options and it has to be applied from the template.

#### Default disabled

This is useful when some SKU options are to be hidden or greyed out. The `disabled` attribute represents an unsupported option and is added to all unsupported SKU options on SKU selections. This is useful when SKU options that are Out-Of-Stock needs to be hidden or greyed out. By default, the `disabled` attribute is added to all unsupported SKU options. For example, when there is no `M` size in `Blue` color, on selection of `Blue` color, the component adds `disabled` attribute to option `M`.

Note:\
This functionality is applicable only when using `nosto-sku-options` component\
The component does not handle styling for disabled options and it has to be applied from the template.

```html
<nosto-product product-id="123456" reco-id="789011">
  ...
  <nosto-sku-options name="colors">
    <span black n-option n-skus="123,145">Black</span>
    <span white n-option n-skus="223,234,245" disabled>White</span>
    <span blue n-option n-skus="334,345">Blue</span>
  </nosto-sku-options>
  ...
</nosto-product>
```

{% hint style="info" %}
Checkout our API documentation on \`nosto-sku-options\` custom element [here](https://nosto.github.io/web-components/classes/SkuOptions.html)
{% endhint %}

### `SimpleCard`

The `SimpleCard` custom element displays a product card using Shopify product data. It fetches product data from `/products/<handle>.js` and renders a card with responsive product image(s), title, price, and optional brand, discount, and rating information.

The component renders inside a shadow DOM with encapsulated styles and provides built-in "Add to cart" functionality.

#### Component attributes

| Attribute     | Description                                                                                                                                                                             |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `handle`      | **Required.** The Shopify product handle to fetch data for.                                                                                                                             |
| `image-mode`  | Image display mode. Use "alternate" for hover image swap or "carousel" for image carousel with navigation. When undefined, shows only the primary image.                                |
| `brand`       | Show brand/vendor data. Defaults to `false`.                                                                                                                                            |
| `discount`    | Show discount data. Defaults to `false`.                                                                                                                                                |
| `rating`      | Show product rating. Defaults to `false`.                                                                                                                                               |
| `variant-id`  | The specific variant ID to display. By default, displays the default variant. When set, shows this variant's data instead.                                                              |
| `image-sizes` | Optional. The sizes attribute for responsive images to help the browser choose the right image size. When not provided, sizes will be calculated dynamically based on image dimensions. |
| `mock`        | If `true`, uses mock data instead of fetching from Shopify. Defaults to `false`.                                                                                                        |

#### Usage examples

**Example #1**:

Basic product card:

```html
<nosto-simple-card handle="awesome-product"></nosto-simple-card>
```

**Example #2**:

Product card with all features enabled:

```html
<nosto-simple-card handle="awesome-product" image-mode="alternate" brand discount rating></nosto-simple-card>
```

**Example #3**:

Product card with responsive images:

```html
<nosto-simple-card 
  handle="awesome-product"
  image-sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw">
</nosto-simple-card>
```

#### Events

The component listens for `variantchange` events to update the displayed product variant information.

#### Markup Attributes

| Attribute | Description                                                                                                        |
| --------- | ------------------------------------------------------------------------------------------------------------------ |
| `n-atc`   | Marks an element as "Add to cart" trigger. Clicking this element will add the current product variant to the cart. |

{% hint style="info" %}
Checkout our API documentation on \`nosto-simple-card\` custom element [here](https://nosto.github.io/web-components/classes/SimpleCard.html)
{% endhint %}

### `VariantSelector`

The `VariantSelector` custom element displays product variant options as clickable pills. It fetches product data from `/products/<handle>.js` and renders option rows with clickable value pills. Optionally preselects the first value for each option and highlights the currently selected choices.

The component emits a custom `variantchange` event when variant selections change, making it compatible with other components like `SimpleCard`.

#### Component attributes

| Attribute     | Description                                                                                                  |
| ------------- | ------------------------------------------------------------------------------------------------------------ |
| `handle`      | **Required.** The Shopify product handle to fetch data for.                                                  |
| `preselect`   | Whether to automatically preselect the options of the first available variant. Defaults to `false`.          |
| `variant-id`  | Optional. The ID of the variant to preselect on load.                                                        |
| `mode`        | Optional. Display mode: `"options"` or `"compact"`. Defaults to `"options"`.                                 |
| `max-values`  | Optional. Maximum number of option values to display per option. When exceeded, shows an ellipsis indicator. |
| `placeholder` | If `true`, the component will display placeholder content while loading. Defaults to `false`.                |

#### Usage examples

**Example #1**:

Basic variant selector:

```html
<nosto-variant-selector handle="awesome-product"></nosto-variant-selector>
```

**Example #2**:

Variant selector with auto-preselection:

```html
<nosto-variant-selector handle="awesome-product" preselect></nosto-variant-selector>
```

**Example #3**:

Variant selector combined with SimpleCard:

```html
<div class="product-display">
  <nosto-simple-card handle="awesome-product">
    <nosto-variant-selector handle="awesome-product" preselect></nosto-variant-selector>
  </nosto-simple-card>
</div>
```

#### Events

| Event           | Description                                                                                    |
| --------------- | ---------------------------------------------------------------------------------------------- |
| `variantchange` | Emitted when variant selection changes. The event detail contains `{ variant, product }` data. |

{% hint style="info" %}
Checkout our API documentation on \`nosto-variant-selector\` custom element [here](https://nosto.github.io/web-components/classes/VariantSelector.html)
{% endhint %}

### `Bundle`

The `Bundle` custom element provides product bundle selection and pricing display functionality. It allows customers to select multiple products as a bundle with dynamic pricing calculations and add-to-cart functionality. This component is specifically designed for Shopify stores.

#### Component attributes

| Attribute   | Description                                                                                                                                  |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `result-id` | Optional. The ID of the recommendation result for attribution tracking.                                                                      |
| `summary`   | Optional. Template string for summary display. Use `{amount}` for product count and `{total}` for formatted price. Default: "Total: {total}" |

**Note**: The `products` property is set programmatically as an array of product objects and is not available as an HTML attribute. See the [API documentation](https://nosto.github.io/web-components/classes/Bundle.html) for the product object structure.

#### Required markup attributes

The component requires the following attribute within a child element to function correctly:

| Attribute         | Description                                                                                                                                 |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `n-summary-price` | An element (e.g., `<span>`, `<div>`) where the total price of selected products will be displayed. Example: `<span n-summary-price></span>` |

#### Usage examples

**Example #1**:

Basic bundle with summary:

```html
<nosto-bundle>
  <div class="bundle-products">
    <!-- Products will be rendered here -->
  </div>
  <div class="bundle-summary">
    <span n-summary-price></span>
  </div>
</nosto-bundle>
```

**Example #2**:

Bundle with custom summary template:

```html
<nosto-bundle summary="Buy {amount} items for {total}">
  <div class="bundle-container">
    <!-- Product cards with variant selectors -->
  </div>
  <div class="summary">
    Total: <span n-summary-price></span>
  </div>
</nosto-bundle>
```

{% hint style="info" %}
Checkout our API documentation on \`nosto-bundle\` custom element [here](https://nosto.github.io/web-components/classes/Bundle.html)
{% endhint %}

## Vue-like templating

`Campaign` supports a subset of Vue templating as the templating language. The supported features are mustache interpolation and the directives that are listed below. Reactivity is not supported.

* [v-text](https://vuejs.org/api/built-in-directives.html#v-text)
* [v-html](https://vuejs.org/api/built-in-directives.html#v-html)
* [v-show](https://vuejs.org/api/built-in-directives.html#v-show)
* [v-if](https://vuejs.org/api/built-in-directives.html#v-if)
* [v-else](https://vuejs.org/api/built-in-directives.html#v-else)
* [v-else-if](https://vuejs.org/api/built-in-directives.html#v-else-if)
* [v-for](https://vuejs.org/api/built-in-directives.html#v-for)
* [v-bind](https://vuejs.org/api/built-in-directives.html#v-bind) (including shorthand syntax)
  * modifiers are not supported
* [v-on](https://vuejs.org/api/built-in-directives.html#v-on)
  * modifiers are not supported
* [v-pre](https://vuejs.org/api/built-in-directives.html#v-pre)
* [v-cloak](https://vuejs.org/api/built-in-directives.html#v-cloak)

For the documentation of these directives the [Vue reference docs](https://vuejs.org/api/built-in-directives.html) is a good starting point.
