Serious trouble converting our site features

Solved

Serious trouble converting our site features

FutureAndAHope
Shopify Partner
32 1 16

We are a Shopify Plus merchant. We have a use case that is critical to our success in using Shopify. We have always used scripts to satisfy our requirements, but now with scripts being deprecated and replaced with functions we are finding we can not use the functionality to fulfill our requirements. We need some serious help to get this working. We were supposed to have this done before Christmas.

 

We have both product bundles and tiered pricing on our current Shopify website. Bundles are just a   group of existing products bundled together. Having looked into functions I can see that the bundling feature should work for this use case. However, our tiered pricing is becoming a problem within the new system. We offer tiered pricing for a subset of our products. As an example Widget 1, could be 10% off for 2, 15% off for 3 Widgets, and 20% for 4 Widgets. We have other products that use similar tiered pricing.

 

The problem we are having is we don’t have a way to implement this using functions. Let's say we have a bundle, it may contain 2 Widgets, that we don’t want to count towards the discount. There may be in the same order 4 additional widgets for which we wish to discount by 20%, due to tiered pricing.

 

Items can be added or removed from the cart. This makes using bundles for tiered pricing problematic. Let’s say we added 2 items, this could be bundled under a parent variant, but then what happens if 2 more items are added to the order? We only have a single operation to change the cart. We can not delete the old bundle (One operation), and replace it (second non-occurring operation), or I have no idea how to do this. It is also super messy for our store, who wants a whole heap of dummy parent variants?

 

We can not use discounts for they are applied to a single variant ID, there are two problems here, there is no way to segregate the Widgets in the bundle from those in the cart, and more importantly, if we have Widgets in a bundle, and Assembly Manuals in another, we cannot do both discounts together, there could potentially be many types of products in an order all with their individual tiered pricing.

 

We have contacted Shopify Plus support with our problem many times and had no adequate reply. We need some real knowledge and assistance here.

Accepted Solution (1)
Nick_Wesselman
Shopify Staff
167 42 65

This is an accepted solution.

Hi @FutureAndAHope -- Sounds like you need the ability to target specific line items with a discount, not just a variant. This is a highly requested feature that's currently on the roadmap for Q1. You might keep an eye on the roadmap here as well as this feature request.

Nick Wesselman | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

View solution in original post

Replies 2 (2)

FutureAndAHope
Shopify Partner
32 1 16

I have put our testing code here so you can see what we are attempting to do. I know we really should be using product metadata in this use case rather than product attributes, but for now, ignore that as it has no effect on the functionality.

 

query RunInput {
  cart {
    lines {
      id
      quantity
      quantity_price_breaks:  attribute(key: "quantity_price_breaks"){
        key
        value
      }
      bundle_id:  attribute(key: "bundle_id"){
        key
        value
      }
      bundle_products:  attribute(key: "bundle_products"){
        key
        value
      }
      bundle_product_discount:  attribute(key: "bundle_product_discount"){
        key
        value
      }
      merchandise{
        ... on ProductVariant {
          id
          product {
            id
          }
        }
      }
    }
  }
}

 

 

 

// -check
import { DiscountApplicationStrategy } from "../generated/api";

/**
 * @typedef {import("../generated/api").RunInput} RunInput
 * @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult
 */

/**
 * @type {FunctionRunResult}
 */
const EMPTY_DISCOUNT = {
  discountApplicationStrategy: DiscountApplicationStrategy.First,
  discounts: [],
};

/**
 *  {RunInput} input
 * @returns {FunctionRunResult}
 */
export function run(input) {
  const lines_length = input.cart.lines.length;

  let count_of_products = {};
  let variants_of_product = {};
  let qty_price_breaks = {};

  for(let i = 0; i < lines_length; i++){
      if(input.cart.lines[i].bundle_products !== null && input.cart.lines[i].bundle_products.value.length > 0){
          //is a bundle so ignore
      } else {

           if(typeof variants_of_product[input.cart.lines[i].merchandise.product.id] === 'undefined'){
             variants_of_product[input.cart.lines[i].merchandise.product.id] = {};
           }
          variants_of_product[input.cart.lines[i].merchandise.product.id][input.cart.lines[i].merchandise.id] = true;

          if(typeof count_of_products[input.cart.lines[i].merchandise.product.id] === 'undefined'){
            count_of_products[input.cart.lines[i].merchandise.product.id] = 0;
          }
          count_of_products[input.cart.lines[i].merchandise.product.id] += input.cart.lines[i].quantity;

        if(typeof qty_price_breaks[input.cart.lines[i].merchandise.product.id] === 'undefined' && input.cart.lines[i].quantity_price_breaks !== null && input.cart.lines[i].quantity_price_breaks.value.length > 0){
          qty_price_breaks[input.cart.lines[i].merchandise.product.id] = input.cart.lines[i].quantity_price_breaks.value;
        }
      }
  }

  let discounts = [];

  for(let i in count_of_products){
    if(count_of_products.hasOwnProperty(i)){
      if(typeof qty_price_breaks[i] !== 'undefined'){
           const qty_bits = qty_price_breaks[i].split(";");
           let discount = 0;
           for(let j = 0; j < qty_bits.length; j++){
               if(count_of_products[i] >= qty_bits[j].split(":")[0]){
                 discount = qty_bits[j].split(":")[1];
               }
           }

           if(discount >  0){
               let variants = [];
               for(let k in variants_of_product[i]){
                   if(variants_of_product[i].hasOwnProperty(k)){
                    
                       variants.push({
                           // Use the variant ID to create a discount target
                           productVariant: {
                               id: k
                           }
                       })

                   }
               }
               discounts.push({
                   // Apply the discount to the collected targets
                   targets: variants,
                   // Define a percentage-based discount
                   value: {
                       percentage: {
                           value: discount
                       }
                   }
               })
           }
      }

    }
  }




if(discounts.length === 0){
  return EMPTY_DISCOUNT;
} else {


  return {
    discounts: discounts,
    discountApplicationStrategy: DiscountApplicationStrategy.First
  };
}


};

 

 

For the following cart, it only applies the discount to one item, not all the ones we need.

 

testing.jpg

 

So the main problem that we are having is enabling the discount to be applied to any line item, with any discount amount. Not to the first discount that matches.

Nick_Wesselman
Shopify Staff
167 42 65

This is an accepted solution.

Hi @FutureAndAHope -- Sounds like you need the ability to target specific line items with a discount, not just a variant. This is a highly requested feature that's currently on the roadmap for Q1. You might keep an eye on the roadmap here as well as this feature request.

Nick Wesselman | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog