I am building a discount application, but it seems like I can't call GraphQL!

I want to develop a product discount app for my store. The page has already been implemented, and users can select a collection to include products for the discount when configuring the promotion.

In the product-discount extension, within run.js, I can access the cart data. However, the issue is how should I associate the products with the collection configured in the backend?

I need to check whether the products in the cart are part of this collection. I believe this requires sending a GraphQL query, but how can I do this in run.js?

Can someone please guide me?

Hi Ekk0,

This should be possible - it would look something like this in run.js:

async function fetchProductsInCollection(collectionId, accessToken) {
  const query = `
    query getProductsInCollection($collectionId: ID!) {
      collection(id: $collectionId) {
        products(first: 100) {
          edges {
            node {
              id
            }
          }
        }
      }
    }
  `;

  const response = await fetch(`https://your-shop-name.myshopify.com/admin/api/2024-07/graphql.json`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Shopify-Access-Token': accessToken,
    },
    body: JSON.stringify({
      query: query,
      variables: { collectionId: collectionId },
    }),
  });

  const data = await response.json();
  return data.data.collection.products.edges.map(edge => edge.node.id);
}

async function checkCartProducts(cart, collectionId, accessToken) {
  const collectionProductIds = await fetchProductsInCollection(collectionId, accessToken);

  const cartProductIds = cart.map(product => product.id);

  const eligibleForDiscount = cartProductIds.some(productId =>
    collectionProductIds.includes(productId)
  );

  return eligibleForDiscount;
}

// Example usage in run.js
(async function run() {
  const cart = [
    { id: 'gid://shopify/Product/1234567890' },
    { id: 'gid://shopify/Product/0987654321' }
  ];

  const collectionId = 'gid://shopify/Collection/123456789';
  const accessToken = 'your-shopify-access-token';

  const isEligible = await checkCartProducts(cart, collectionId, accessToken);

  if (isEligible) {
    console.log("Discount can be applied!");
    // Apply discount logic here
  } else {
    console.log("No eligible products for discount in cart.");
  }
})();

I’m currently implementing a way to retrieve configuration information from others in run.js, but since run.js is executed on the server side, I cannot fetch the collection data using fetch or axios. The backend logs show an error: “The Wasm module exceeded the instruction count limit.”

Another issue has also arisen: run.js executed on the server side seems unable to obtain the current time using new Date. If I don’t pass in a specific date, the returned time is invalid. For example, using new Date(“2024-08-06”) works correctly, but directly using new Date() doesn’t work.

Hi @Ekk0
you can use the Function API’s input query, to query the product info by looking at the cart.lines.merchandise (see https://shopify.dev/docs/api/functions/reference/product-discounts/graphql/common-objects/cartline). The product field has fields for querying membership in collections, and they would use variables from their configuration metafield to drive that.

1 Like