> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ordergroove.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ordergroove.com/_mcp/server.

# One Time SKU Swap Configuration in the Subscription Manager

SKU Swap is an out-of-the-box feature that allows customers to change from one SKU to another without needing to cancel one product and resubscribe to another. This feature helps retention by getting ahead of common subscription cancel symptoms — often referred to as "flavor fatigue" — whether that's flavor, size, scent, or anything else.

***

## What Are the Benefits of a One-Time Swap?

By default, SKU Swap permanently changes the subscription to the newly chosen product. In some cases, a customer may only want to swap their next upcoming order without permanently switching. A common example is when an item is out of stock — customers may want to swap to avoid waiting, but keep their original subscription going. The instructions below add the ability for customers to choose between a permanent swap or a one-time swap.

***

## Setting Up One Time SKU Swap

There are two main steps: access the advanced editor, then modify the relevant files.

### 1. Accessing the Subscription Manager Advanced Editor

You can access the advanced editor through your Ordergroove Admin:

1. Log in to [Ordergroove](https://rc3.ordergroove.com/).
2. Go to **Subscriptions** on the top toolbar, and select **Subscription Manager**.
3. Toggle **Advanced** on the top left.

#### Support

Some aspects of this article require technical expertise with coding languages. This is self-serve and outside of the normal support policy.

### 2. Adding the Code Snippets

**File: `locales/en-US.js`**

Update the message for the existing SKU swap confirm button and add a new key for the one-time change button:

```javascript
"modal_change_product_save": "Change for all the Future Orders",
"modal_change_product_change_one_time": "One Time Change",
```

**File: `change-product.liquid`**

Update the SKU Swap experience with the following changes:

1. Add the current product to the SKU Swap modal. Normally the current product is excluded since customers are swapping away from it — but for a one-time swap, the customer may want to swap back. This snippet makes the existing product visible in the swap experience:

   ```liquid
   {% set customized_sku_options = 'add_items(alternative_ids, subscription.product)' | js %}
   ```

2. Replace the default product list (`alternative_ids`) with the customized options from step 1:

   ```liquid
   {% for alternative_id in customized_sku_options %}
   ```

3. Add a hidden input with the `order_id` for use in the one-time swap call:

   ```liquid
   <input type="hidden" value="{{ order_item.public_id }}" name="order_item" />
   ```

4. Create the new one-time change button. This button calls the custom function `change_item_product` defined in `script.js`:

   ```liquid
   <button class="og-button" name="change_product_one_time" type="button" @click={{ 'change_item_product' | js }}>
     {{ 'modal_change_product_change_one_time' | t }}
   </button>
   ```

5. Add a call to the custom function within the regular SKU swap form so that a permanent swap also updates the item for the current shipment:

   ```liquid
   @finally={{ 'change_item_product' | js }}
   ```

   The top of the form code will look something like this:

   ```liquid
   <form
     action="{{ 'change_product' | action }}"
     name="og_change_product"
     @success={{ 'close_closest_modal' | js }}
     @reset={{ 'close_closest_modal' | js }}
     @finally={{ 'change_item_product' | js }}>
   ```

**File: `script.js`**

Add this code at the end of `script.js`:

```javascript
const change_item_product = async function( ev ) {
  const { customer, environment: { lego_url } } = og.smi.store.getState();
  const form = ev.target.closest('form');
  const formComponents = form.querySelectorAll('select,input,button,div');
  const subscription_id = form.querySelector('[name="subscription"]').value;
  const disclaimer = document.querySelector('#og-one-time-change-disclaimer-'+subscription_id);
  const order_item = form.querySelector('[name="order_item"]').value;
  const product = form.querySelector('[name="product"]:checked').value;
  const one_time_change_params = {
    product: product
  }

  if ( disclaimer ) {
    disclaimer.setAttribute('style', 'display: none');
  }
  formComponents.forEach( it => {
    it.toggleAttribute('disabled', true)
    it.setAttribute('style', 'opacity:0.6')
  })

  const response = await fetch(`${lego_url}/items/${order_item}/change_product/`, {
    method: 'PATCH',
    headers:{
        'Authorization': JSON.stringify(customer),
        'Accept': 'application/json',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(one_time_change_params)
  })

  if (response.status === 200) {
      og.smi.api.request_subscriptions()
      og.smi.api.request_orders({ status: 1 })
      og.smi.api.request_orders_items({ status: 1 })
      .then(() => formComponents.forEach(it => {
        it.toggleAttribute('disabled', false)
        it.setAttribute("style", 'opacity: 1')
      }))
      .then(() => (disclaimer) ? disclaimer.setAttribute('style', 'display: block') : '')
      .then(() => displayCustomToast('Success! Your order item has been changed.'))
      .then(() => close_closest_modal(ev))
  }
}

function displayCustomToast (msg) {
  let customToast = document.createElement('li');
  let toastContainer =  smiElement.querySelector('.og-toasts');
  customToast.classList.add('og-toast', 'og-toast-success', 'og-show');
  customToast.innerHTML = msg;
  toastContainer.appendChild(customToast);
  toast_notification_animation();

  setTimeout(() => {
    toastContainer.removeChild(customToast);
  }, TOAST_NOTIFICATION_TIMEOUT);
}

const add_items = og.smi.memoize(function (a, b) {
  return [...a, b];
})
```

***

## Styling

**File: `order-item.less`**

Add this snippet inside the `.og-product` class to style the one-time change disclaimer:

```css
.og-one-time-change-disclaimer {
  font-size: .8em;
  font-style: italic;
  background-color: #FFFF0099;
  max-width: 80%;
}
```

**Class: `.og-change-product-control`**

To style the buttons, add this snippet inside the `.og-change-product-control` class:

```css
.og-dialog-footer {
  justify-content: space-between;
}
```