shopifyshopify-appshopify-api

How to create Shopify function to give free shipping to customers with speicific tag(s)


I am trying to add a shopify function to our store and its functionality should be to give free shipping to customers that have at least one of these two tags: "swell_vip_learned lounger", "swell_vip_pj professional".

I have created a custom app and added an extension of type "shipping-discount". The app is installed successfully and discount is also showing applied. but when I open the checkout as a customer that has those tags, it donot apply free shipping. I am providing code for my run.graphql and run.js both as only these are two main files in extension. Kindly help me what could be wrong here ?

run.grpahql

query RunInput {

 cart {
  deliveryGroups{
    id
  }
  buyerIdentity {
    customer {
      hasTags(tags: ["swell_vip_learned lounger", "swell_vip_pj professional"]) {
        hasTag
        tag
      }
    }
  }
   cost {
      subtotalAmount {
        amount
      }

    }
 }
}

run.js

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

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

/**
 * @param {RunInput} input
 * @returns {FunctionRunResult}
 */
export function run(input) {
  console.log("Free Shipping Validation Function");
  // fetch("https://haroon-ins-dev.free.beeceptor.com/", {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(input) } )

  const headers = new Headers();
headers.append('Authorization', 'Bearer SOME-VALUE');

fetch('https://haroon-ins-dev.free.beeceptor.com', {
    method: 'POST',
    headers: headers,
    body: JSON.stringify(input)
  })
  .then(response => response.text())
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error(error);
  });

  const SWELL_TIER_2 = "swell_vip_learned lounger";
  const SWELL_TIER_3 = "swell_vip_pj professional";

  let customer = input.cart.buyerIdentity.customer;
  const deliveryGroupId = input.cart.deliveryGroups.id;

  if (
    // customer has tags
    customer && (
      customer?.hasTags.find((t) => t.tag === SWELL_TIER_2)?.hasTag === true ||
      customer?.hasTags.find((t) => t.tag === SWELL_TIER_3)?.hasTag === true
    )
  ) {
    // return free shipping
    const ShippingDiscount = {
      discounts: [
        {
          message: "Free VIP Shipping",
          targets: {
            deliveryGroup: {
              id: deliveryGroupId,
            },
          },
          value: {
            percentage: 100,
          },
        },
      ],
    };
    return ShippingDiscount;
  } else {
    // otherwise return empty discount (no free shipping)
    return EMPTY_DISCOUNT;
  }
}

I tried adding a console.log to show what form of data I am getting inside input but it donot show in the console of frontend. Tried doing a post request to Beeceptor but request is not reaching there as well.


Solution

  • I fixed the issue with the help provided by Simarjeet Singh and some additional fixes. Here are the fixes I applied that might help anyone seeking answer to same question.

    1. there was problem how I was returning the discount percentage. percentage should be object instead of number and there should be value inside it.
    2. There was problem in the if condition. here is the correct code that's working for me.

    /**
     * @typedef {import("../generated/api").RunInput} RunInput
     * @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult
     */
    
    /**
     * @type {FunctionRunResult}
     */
    const EMPTY_DISCOUNT = {
      discounts: [],
    };
    
    /**
     * @param {RunInput} input
     * @returns {FunctionRunResult}
     */
    export function run(input) {
      console.log("Free Shipping Validation Function: Input", input); // Log input data for debugging
    
      const SWELL_TIER_2_LOWER = "swell_vip_learned lounger".toLowerCase();
      const SWELL_TIER_3_LOWER = "swell_vip_pj professional".toLowerCase();
    
      let customer = input.cart.buyerIdentity.customer;
      const deliveryGroupId = input.cart.deliveryGroups[0].id;
    
      if (
        customer &&
        customer.hasTags.some(
          (t) =>
            (t.tag.toLowerCase() === SWELL_TIER_2_LOWER && t.hasTag === true) ||
            (t.tag.toLowerCase() === SWELL_TIER_3_LOWER && t.hasTag === true)
        )
      ) {
        // return free shipping
        const ShippingDiscount = {
          discounts: [
            {
              message: "Free VIP Shipping",
              targets: {
                deliveryGroup: {
                  id: deliveryGroupId,
                },
              },
              value: {
                percentage: {
                  value: 100,
                },
              },
            },
          ],
        };
        return ShippingDiscount;
      } else {
        // otherwise return empty discount (no free shipping)
        return EMPTY_DISCOUNT;
      }
    }