Personalized checkout and custom promotions with Shopify Scripts
Hi everyone!
I have a script running on a client to identify product bundles using tags and apply discounts. Recently, I've been getting A LOT of MemoryQuotaExceeded errors. Despite those errors, the script is working normally. Given that I'm not a Ruby expert (to say the least), could I improve the memory usage of this script? Any help is appreciated.
The code is the following:
products_in_cart = Input.cart.line_items
products_with_tag = {}
variants_with_discount = []
# Step 1: Group products by their tags
products_in_cart.each do |line_item|
variant = line_item.variant
product = variant.product
product.tags.each do |tag|
if tag.start_with?('bundle')
key = tag # Use the tag as the key for grouping
products_with_tag[key] ||= []
products_with_tag[key] << {
id: product.id,
variant: variant.id,
quantity: line_item.quantity,
tag: tag
}
break # If one tag matches, move to the next product
end
end
end
unless products_with_tag.empty?
# Step 2: Identify bundles
products_with_tag.each do |_tag, products_in_bundle|
# Create a hash where the keys are the tags and the values are arrays of product IDs
products_by_id = products_in_bundle.group_by { |item| item[:id] }
# Flatten the array of products
flattened_products = products_by_id.values.flatten(1)
# Pair them up
paired_products = []
flattened_products.each_slice(2) { |pair| paired_products << pair }
# If there's an odd number of products, remove the last one
paired_products.pop if paired_products.last.size % 2 != 0
# Now we have all possible pairs of products with the same tag
paired_products.each do |pair|
# Check if both elements of each pair have the same quantity
if pair[0][:quantity] != pair[1][:quantity]
# Identify the product with the largest and smallest quantity
max_product = pair.max_by { |product| product[:quantity] }
min_product = pair.min_by { |product| product[:quantity] }
# Calculate the difference as the result of the largest quantity divided by the smallest quantity
difference = max_product[:quantity] / min_product[:quantity]
# Add a property with that difference to the object with the largest quantity
max_product[:difference] = difference
end
# Create a new object with the variant, quantity, and difference (if any) from each pair
new_object = pair.map { |product| { variant: product[:variant], quantity: product[:quantity], difference: product[:difference] } }
# Add the new object to the array of all new objects
variants_with_discount << new_object
end
end
# Step 3: Add discounts
products_in_cart.each do |line_item|
variant = line_item.variant
# Find the corresponding new object for this variant
var = variants_with_discount.flatten.find { |obj| obj[:variant] == variant.id }
# If a new object was found and it has a difference, adjust the discount
if var && var[:difference]
calc = 0.25 / var[:difference]
discount = 1 - calc
message = 'Bundle'
line_item.change_line_price(line_item.line_price * discount, message: message)
elsif var
discount = 0.75
message = 'Bundle'
line_item.change_line_price(line_item.line_price * discount, message: message)
end
end
end
Output.cart = Input.cart
Discover how to increase customer engagement on your store with articles from Shopify A...
By Jacqui Apr 23, 2025Hey Community 👋 Did you know that March 15th is National Everything You Think Is W...
By JasonH Apr 1, 2025Discover how to increase the efficiency of commerce operations with Shopify Academy's l...
By Jacqui Mar 26, 2025