Used Newie, our AI search tool in the docs? Take a 2-minute survey to rate your experience!

Adding customized products to a cart

Prev Next

Associate App allows users to customize products before adding them to the cart. This guide outlines the process of implementing this functionality on our platform and covers handling product configurations. You can customize a product using add-ons or by extending the product attributes.

Add-ons are product extensions, such as embroidery (physically attached) or accessories like power adapters. A parent-child relationship exists between an add-on and the product it is attached to. For example, associates could add a laptop to a cart and customize it by selecting add-ons like extended warranties or additional storage.

After implementing this functionality, users will experience a flow like explained in the example below that will allow them to customize and add the product to cart:

  1. Open the laptop product details page in the Associate App.

  2. Tap the customization button.

  3. View the webview displaying the UI you provided for product customization.

  4. In the UI, add the warranty to the laptop.

  5. Add the laptop with the warranty to the cart, automatically returning to the Associate App and showing the changed cart.

Product detail page with custom button “Product configurator”.

To create this flow, you need to:

Setting up a custom button

To add a custom "Call to Action" button on the Product Details screen you must create a custom button:

  1. In Omnichannel Manager, go to Settings > Associate App > Customizations and click Add.

  2. Enter a name for the customization. For example, Custom product configurator.

  3. Select Product Details as the Location.

  4. Choose Webview as the Type.

  5. Click Create to proceed.

  6. Creating the button will take you to the custom product configurator screen. Enter the button Title and Caption. Leave all other fields empty, and save the changes. You can set the URL after publishing the app, and remember to enable the customization after that.

Setting up a new web app

After adding the button to the Product Details, you must build and publish a web application that allows users to customize products. This application will be displayed within the Associate App through a webview.

  1. When your application is rendered from the Product Details, it receives cart, store, associate identifiers, and the product data from the webview through the window.NEWSTORE object.

const { cartId, storeId, associateId, ...product } = window.NEWSTORE.contextProps.formData
  1. Navigating to the application does not change the cart by default. You need to add the product to the cart using the Cart API, which allows you to include any extended attributes or custom price books.

const parentProductResponse = await fetch(`${baseUrl}/checkout/carts/${cartId}/items`, {
    headers: {
       authorization: Bearer ${auth.accessToken},
       "content-type": "application/json",
   },
   body: JSON.stringify({
      product_id: product.id,
      fulfillment: "IN_STORE_HANDOVER",
      price: { source: "INTERNAL", source_id: "default" }
   }),
   method: "POST",
   mode: "cors",
})
  1. After adding the product, use Cart API to customize it with one or more add-ons. There are no restrictions on the product identifiers that you can attach as an add-on. It is up to the application to decide which ones are valid: it can be a hard-coded list, obtained an integration, or passed from the Associate App through the extended attributes of the parent product.

    
    const parentLocation = parentProductResponse.headers.get('Location')
    await fetch(`${parentLocation}/add-ons`, {
       headers: {
          authorization: `Bearer ${auth.accessToken}`,
          "content-type": "application/json",
       },
       body: JSON.stringify({
          product_id: addon.id,
          fulfillment: "IN_STORE_HANDOVER",
          price: { source: "INTERNAL", source_id: pricebook },
       }),
       method: "POST",
       mode: "cors",
    })

  2. Reload the cart from within your application using a deeplink:

    window.open(`com.newstore.associate-one://cart/load?cartId=${cartId}`)

  3. After the cart is refreshed, close the webview and return to the Associate App.

    window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'close' }))

  4. After publishing the app, return to your custom product configurator settings in Omnichannel Manager and set the URL. This will ensure that the custom button correctly redirects users to your custom app.

Fulfilling or canceling add-ons

Set the same fulfillment method on an add-on (such as warranties) that is applied to its parent item. For example, if the parent item uses SHIPPING, set fulfillment to SHIPPING on the add-on too. NewStore then routes both items to the same fulfillment request, and your fulfillment integration can ship or cancel them together.

NewStore does not validate that a parent item and its add-on have the same fulfillment status. Your fulfillment integration must apply the same action, such as shipping or canceling, to both items. If the statuses differ, NewStore might route the add-on separately, or a cancellation might fail and leave the order in an inconsistent state.

When you fulfill or cancel add-ons, consider the following:

  • ATP: A non-physical add-on, such as a warranty, still needs Available to Promise (ATP) inventory when its fulfillment method is SHIPPING. Set a sufficiently high ATP value for the add-on SKU at every location where NewStore can route the parent item.

  • Fulfillment method: Do not set IN_STORE_HANDOVER on an add-on whose parent uses SHIPPING. NewStore fulfills the add-on at checkout, so you cannot cancel it together with the parent. The customer must return the add-on separately and receive a refund instead.

  • Cancellation: The Cancel order method of the Order API cancels the whole order. The Cancel line items method applies to pre-order items only. To cancel specific items in an order routed to a distribution center, use the Cancel items method of the Fulfillment Provider API and include both the parent item and the add-on in the request.

  • Injected orders: When you inject an order with the Order Injection API, the add-on and its parent must be in the same shipment. NewStore rejects an add-on whose parent is in a different shipment.

For more information, see Integrating a fulfillment provider.

Adjusting sales receipt template

To adjust the sales receipt template to display add-ons, update the template configuration to nest add-ons under their respective parent products. In the template, ensure that add-ons are visually linked to their parent product by using indentation or grouping. This adjustment helps maintain clarity for both customers and sales associates by clearly distinguishing primary products from their associated extensions.

{% for addon in item.addons %}
  <tr>
    <td class="desc" style="padding-left:2rem">
      <strong>{{ addon.product_name }}</strong>
    </td>
    <td class="amount">
      <span>{{ currency_code }} {{ format_currency(addon.price_net) }}</span>
    </td>
  </tr>
{% endfor %}