Attributes
Every attribute the upsell enhancers read, grouped by where it goes.
Accept Upsell Button
Activated by data-next-action="accept-upsell" on a button element.
| Attribute | Required | Description |
|---|---|---|
data-next-action="accept-upsell" | yes | Activates the enhancer |
data-next-package-id | conditional | Numeric package ref_id. Required unless a data-next-selector-id or data-next-upsell-action-for is set |
data-next-quantity | no | Number of units to submit. Defaults to 1 |
data-next-selector-id | conditional | Links the button to a PackageSelectorEnhancer running in upsell context. Value must match the selector container's data-next-selector-id |
data-next-upsell-action-for | conditional | Links the button to a BundleSelectorEnhancer running in upsell context. Value must match the bundle selector container's data-next-selector-id. This is a different attribute from data-next-selector-id |
data-next-url | no | URL to navigate to after a successful submit. Falls back to <meta name="next-upsell-accept-url"> |
If both data-next-package-id and data-next-selector-id are set, the selector wins when a selection has been made.
Offer Container
Activated by data-next-upsell="offer" on any container element.
| Attribute | Required | Description |
|---|---|---|
data-next-upsell="offer" | yes | Activates the enhancer in single-package mode |
data-next-package-id | conditional | Numeric package ref_id. Required in single-package mode |
data-next-quantity | no | Default quantity. Defaults to 1 |
data-next-selector-id | no | Unique ID for this container, used by cross-container option/quantity sync and external display elements |
data-next-package-selector-id | no | Link to an external PackageSelectorEnhancer instead of using inline options. Auto-detected when a [data-next-package-selector] child is present |
data-next-bundle-selector-id | no | Link to an external BundleSelectorEnhancer. Auto-detected when a [data-next-bundle-selector] child is present |
Selector Container (built-in options)
Activated by data-next-upsell-selector on any container element. Used when the offer card holds a list of option cards.
| Attribute | Required | Description |
|---|---|---|
data-next-upsell-selector | yes | Marks the container as an upsell selector |
data-next-selector-id | yes | Unique ID for this selector. Used by data-next-upsell-select, cross-container sync, and external display elements |
Option Cards
| Attribute | Required | Description |
|---|---|---|
data-next-upsell-option | yes | Marks an element as a selectable option card |
data-next-package-id | yes | Numeric package ref_id for this option |
data-next-selected="true" | no | Pre-selects this option on init |
Dropdown
| Attribute | Required | Description |
|---|---|---|
data-next-upsell-select="<selectorId>" | yes | Marks a <select> element. Value must match the parent data-next-selector-id (or be set on a standalone <select>) |
Each <option value="N"> inside is a package ID. An empty value clears the selection.
Action Buttons (inside an offer container)
Place inside a data-next-upsell="offer" or data-next-upsell-selector container.
| Attribute | Values | Description |
|---|---|---|
data-next-upsell-action | add, accept, skip, decline | Action to perform on click. add and accept are aliases. skip and decline are aliases |
data-next-url | URL | Per-button override for the redirect target. Falls back to the <meta name="next-upsell-accept-url"> or next-upsell-decline-url meta tag |
data-os-next-url and data-next-next-url are accepted as legacy aliases for data-next-url.
Quantity Controls (inside an offer container)
| Attribute | Description |
|---|---|
data-next-upsell-quantity="increase" | Increment button. Clamps at 10 |
data-next-upsell-quantity="decrease" | Decrement button. Clamps at 1 |
data-next-upsell-quantity="display" | Element whose text content is updated to the current quantity |
data-next-upsell-quantity-toggle="N" | Card that sets quantity to N on click. Gets next-selected when N matches the current quantity |
data-next-quantity-selector-id | Optional. On increase/decrease buttons or display elements, scopes the quantity to a specific selector ID rather than the container default |
Linked External Selectors
When the offer container or accept button is paired with an external selector, the selector itself needs upsell context to disable cart writes.
| Attribute | On | Description |
|---|---|---|
data-next-upsell-context | [data-next-package-selector] or [data-next-bundle-selector] | Forces the selector into select mode and disables all cart writes. Required on any selector linked to an upsell |
Meta Tags
Set in the page <head>. Read by both upsell enhancers.
| Meta tag | Description |
|---|---|
<meta name="next-page-type" content="upsell"> | Marks the page as an upsell page. Triggers page-view tracking and the duplicate-dialog logic |
<meta name="next-upsell-accept-url" content="/path"> | Default URL to navigate to after a successful accept. Overridden by data-next-url on individual buttons |
<meta name="next-upsell-decline-url" content="/path"> | Default URL to navigate to after a skip or a duplicate-decline |
<meta name="next-prevent-back-navigation" content="true"> | Push a history guard so the customer cannot use the browser Back button to return to checkout. Use only on the first upsell page |
Display Bindings
Use data-next-display inside an offer container to bind any element to the package's data. The display updates when the option or quantity changes.
| Binding | Format | Description |
|---|---|---|
data-next-display="package.name" | text | Package name |
data-next-display="package.image" | text | Image URL |
data-next-display="package.price" | currency | Unit price after discount |
data-next-display="package.originalPrice" | currency | Unit price before discount |
data-next-display="package.savingsAmount" | currency | Discount per unit |
data-next-display="package.savingsPercentage" | percentage | Discount as a percentage |
data-next-display="package.hasSavings" | boolean | true when discount is non-zero. Use with data-next-show |
External display elements (outside the container) can bind to a specific selector via data-next-display="selection.<selectorId>.<property>".