Сount the number of unique products in different line items

Topic summary

Problem: A Shopify Script for volume discounts only counted quantities per line item. Bundled products caused the same product (with different properties) to appear as separate line items, so totals per product weren’t aggregated.

Proposed approach: Iterate through all line items, extract each line_item.variant.id, and use a set/dictionary to track and sum quantities per unique variant. Apply discounts based on these aggregated counts rather than per-line counts.

Implemented solution: The poster used a Hash to accumulate quantities: counts[line_item.variant.id] += line_item.quantity. On a second pass, for items not already discounted (line_price == original_line_price), they apply percentage discounts based on aggregated variant quantity thresholds: ≥7 and <10 uses DISCOUNT_MIN7; ≥10 and <20 uses DISCOUNT_MIN10; ≥20 uses DISCOUNT_MIN20. Discount percentages are read from line item properties and applied via change_line_price with a “VOLUME_DISCOUNT” message.

Outcome: Confirmed working with provided code snippet. Issue resolved; no outstanding questions.

Summarized with AI on January 8. AI used: gpt-5.

Hi.
I have Shopify script for volume discounts (quantity >= 7 - 10%,…).
The script checks the line item quantity. All works.
But I’ve created product bundles and the same products in the cart with different properties are displayed as different line items.
One product can have a quantity 4 in line item row. And the same product can have quantity 3 in another row…
Shopify script count only line item quantity.

How can I count number unique products (ids)?
Then it will be possible to add a discount for those IDs, the total number of which satisfies the discount.

You might have to use something like this solution here:

Retrieve Line Items: When processing an order, retrieve all line items from the order.

Extract Variant IDs: For each line item, extract the variant ID. The variant ID can be found using the .variant method in the Shopify Script API, which returns the specific product variant represented by the line item.

Track Unique Products: Create a data structure (like a set or dictionary) to track unique products. As you iterate through the line items, check if the variant ID is already in your data structure. If not, add it. This way, you can count unique products.

Apply Discounts Based on Unique Counts: Once you have the count of unique products, you can apply your volume discount logic based on this count.

Thank You. Works for me!

DISCOUNT_MIN7 = 'discount_min7'
DISCOUNT_MIN10 = 'discount_min10'
DISCOUNT_MIN20 = 'discount_min20'

MIN7_VALUE = 0
MIN10_VALUE = 0
MIN20_VALUE = 0

counts = Hash.new(0)
Input.cart.line_items.each do |line_item|
    counts[line_item.variant.id] += line_item.quantity
end

Input.cart.line_items.each do |line_item|

    properties = line_item.properties
    variant = line_item.variant.id
    variant_qty = counts.fetch(variant).to_f

    # puts variant_qty
    # puts counts.fetch(variant)

    if line_item.line_price === line_item.original_line_price
        if variant_qty >= 7 && variant_qty < 10 && properties.has_key?(DISCOUNT_MIN7)
            MIN7_VALUE = properties[DISCOUNT_MIN7].to_f
            line_item.change_line_price(line_item.line_price - line_item.line_price * (MIN7_VALUE / 100), message: "#{MIN7_VALUE}% VOLUME_DISCOUNT" )
        elsif variant_qty >= 10 && variant_qty < 20 && properties.has_key?(DISCOUNT_MIN10)
            MIN10_VALUE = properties[DISCOUNT_MIN10].to_f
            line_item.change_line_price(line_item.line_price - line_item.line_price * (MIN10_VALUE / 100), message: "#{MIN10_VALUE}% VOLUME_DISCOUNT")
        elsif variant_qty >= 20 && properties.has_key?(DISCOUNT_MIN20)
            MIN20_VALUE = properties[DISCOUNT_MIN20].to_f
            line_item.change_line_price(line_item.line_price - line_item.line_price * (MIN20_VALUE / 100), message: "#{MIN20_VALUE}% VOLUME_DISCOUNT")
        end
    end
end

Output.cart = Input.cart
1 Like

Awesome, Glad I could help! Thanks for posting your code for others in this situation!