
Foreward
This may be incompatible with stores that are using earlier versions of jQuery. This may occur if you have apps installed which had fairly lazy designers or you are using an outdated theme.
I won’t claim that this is the prettiest or most elegant code ever, but it certainly got the results my clients wanted. If you want something impressive, hire a developer. If you want efficient results, try it yourself!
Motivation
This article will teach you how to install a snippet into your Shopify store that will allow you to run a “buy X get Y” deal. I had a client who wanted to give a free yoga mat to any customer who purchased 5 items from their yoga apparel collection. I have taken this code and generalized it for your use!
I at first looked to see if some combination of apps could accomplish what I was trying to do. I found that I could hack the behavior they wanted together from a franken-install of no less than FOUR apps. That isn’t exactly an elegant execution. On top of that, it still allowed their customers to cheat the system!
First, let me showcase an example of what this little snippet can do!
Example
ART OF LIV’N was kind enough to let me showcase their implementation here in our blog. They wanted to have a free dog mat added to the customer’s order when the customer purchased any 3 items from their Art of Riding collection. You can see this in action below!

Now, let’s say a customer tries to break your rules: they want to get the free dog mat while only buying TWO products from Art of Riding. You can see the result below.

Neat.
Implementation
If you’re still reading, I’m assuming that you’d like to look at the implementation for your own store! First, copy the following code and paste it into a new snippet in your theme’s editor.
{% comment %}
Make sure we're loading jquery, we'll need it.
{% endcomment %}
{{ 'api.jquery.js' | shopify_asset_url | script_tag }}
{% comment %}
This code block determines the number of products in the customers cart which are
eligible for the free item.
#check_var is used to count the number of free-item eligible products.
#check_var2 is used to determine whether or not the free item is already in the cart.
{% endcomment %}
{% comment%}
Shopify's 'increment' operator (for some reason) writes the current value of the variable
onto the document whenver you call it. To stop strange numbers from appearing during your
customer's shopping experience, we wrap the incrementations in a hidden HTML object (the header
below).
{% endcomment %}
<h1 style="visibility:hidden;">
{% comment %}
Initialize #check_var2 to 0, a value which indicates that the free item is *not* in the cart yet
{% endcomment %}
{% assign check_var2 = 0 %}
{% comment %}
Look through the cart contents and perform some actions (the conditionals) for each line_item
{% endcomment %}
{% for line_item in cart.items %}
{% comment %}
Liquid variables created with 'increment'/'decrement' are actually distinct from those created
with 'assign'. Here, we initialize check_var.
{% endcomment %}
{% increment check_var %}
{% comment %}
We check to see if the free item is already in the cart.
{% endcomment %}
{% if line_item.product_id == FREEITEM_ID %}
{% assign check_var2 = 1 %}
{% endif %}
{% comment %}
We check to see if items eligible to trigger the free product are in the cart
Add more 'or line_item.product_id == ELIGIBLE_ITEM_ID' as needed. You can actually
run this check against any sub-property of 'line_item', such as vendor or 'discount'.
{% endcomment %}
{% if line_item.product_id == ELIGIBLE_ITEM_1_ID
or line_item.product_id == ELIGIBLE_ITEM_2_ID
%}
{% comment %}
If any of the above conditions are met, then the following loop is triggered.
This loop simply adds the quantity of the eligible product to the incremental variable
'check_var'.
{% endcomment %}
{% for i in (2..line_item.quantity) %}
{% increment check_var %}
{% endfor %}
{% comment %}
If we have no eligible items, we must decrement check_var. This is another unfortunate property
of incremental variables/operators in Shopify : they don't play well with loops.
{% endcomment %}
{% else %}
{% decrement check_var %}
{% endif %}
{% endfor %}
</h1>
{% comment %}
Now we are checking our variable states and injecting jQuery cart modifications
as needed.
{% endcomment %}
{% comment %}
Check_var > NUM_ELIGIBLE_ITEMS_REQUIRED AND check_var2 != 1
In this situation, the customer has enough of the eligible items, but does not have
the free item in their cart yet.
The script adds 1x of FREEITEM_ID to their cart.
{% endcomment %}
{% if check_var > NUM_ELIGIBLE_ITEMS_REQUIRED and check_var2 != 1 %}
<script type="text/javascript">
jQuery.post('/cart/add.js', {quantity: 1,id: FREEITEM_ID});
</script>
{% comment %}
However, if the customer tries to lower the amount of eligible items below the
required level, we add some jQuery that takes away their free item.
{% endcomment %}
{% elsif check_var < NUM_ELIGIBLE_ITEMS_REQUIRED and check_var2 == 1 %}
<script type="text/javascript">
jQuery.post('/cart/change.js', {quantity: 0,id: FREEITEM_ID});
</script>
{% else %}
{% endif %}
You can copy my actions from the GIF below to get the snippet in the right place!

The code is commented fairly well. It is very important that you ensure the following steps are complete before proceeding:
1. Create a new product. This will be the free product that is added to the customer’s order. Unfortunately, we cannot add an existing product with a 100% discount.
2. The following variables are set.
- FREEITEM_ID : This is the product_id of the free item (the product you created in step 1) you’d like to have added to your customer’s cart once the requirements are met.
- ELIGIBLE_ITEM_#_ID : This is the product_id of items which may qualify the customer for the free item.
- NUM_ELIGIBLE_ITEMS_REQUIRED : The number of qualifying items the customer must purchase in order to get the deal.
Once you have these variables set, head over to cart.liquid and include the snippet on that page. The new text you need in cart.liquid is:
{% include 'your_snippet_name' %}
You can see a demonstration below:

Now, we have to prevent your customers from attempting to get extra free items. In order to do this, we have to add a “catch” to the quantity modifier on your cart page. The code we need to add is as follows:
{% if item.product_id == FREEITEM_ID %} value="1" style="visibility:hidden;" {% endif %}
This needs to be inserted in the input element that contains:
value="{{ item.quantity }}"
Be sure you set FREEITEM_ID to the value of your free item. See the example below:

With that in place, everything should be fully functional! Be sure to email me or leave comments with any questions you might have!