How to Add a Free Gift With Purchase on Shopify (Including Automatic Add-to-Cart)

Last updated
•
Expert reviewed
•
5 min read
Jacques Blom
Jacques Blom
CTO at Fudge.

Key takeaways

  • Shopify can make a gift free, but it will not put it in the cart. A Buy X Get Y discount only applies once the customer has added the gift themselves.1
  • There are three ways to close that gap: clear messaging, theme code that adds and removes the gift through the Cart AJAX API, or an app.
  • Fudge writes that theme code from a prompt. You describe the gift rule and it adds the add-and-remove logic to your cart as native theme code.
  • The discount always lives in the Shopify admin. Theme code only moves the item into the cart. Buy X Get Y is what takes it to $0.
  • Simple spend tiers work natively with one automatic discount per tier, as long as the tiers are not set to combine with each other.

A Shopify free gift with purchase takes one native discount to set up, and it has one gap that often surfaces only after launch: Shopify makes the gift free, but the customer has to add it to the cart themselves. This guide covers the native setup, three ways to get the gift into the cart, and the edge cases merchants ask about.

It is timed for Black Friday 2026 (27 to 30 November) but works for any promotion. Still choosing the offer? Black Friday sale ideas for Shopify stores compares a gift against the other mechanics on margin.

Why you can trust us

We have been in the Shopify space for over four years and have worked with hundreds of Shopify brands on their storefronts. Jacques has over 15 years of development experience. We build Fudge, an AI storefront editor with a 4.9 rating on the Shopify App Store and Built for Shopify status, and cart drawer logic like the gift code in this guide is the kind of theme work it writes.


How does a free gift with purchase work natively in Shopify?

Shopify has no discount type called “free gift”. The native route is a Buy X Get Y discount with a spend or quantity trigger and a reward set to free.1

Create it as a Shopify automatic discount and there is no code for the customer to enter. Automatic discounts apply in the cart and at checkout when the conditions are met.2

How to set up the Buy X Get Y discount

  1. In your Shopify admin, go to Discounts and click Create discount.
  2. Choose Buy X get Y, then under Method select Automatic discount and enter a title. Dawn prints the discount title next to the discounted line in the cart, so write it for customers.
  3. Under Customer buys, choose Minimum purchase amount (for example $75) or Minimum quantity of items, then select the products or collections that count toward it.
  4. Under Customer gets, set the quantity to 1, select the gift product or a gift collection, and under At a discounted value choose Free.
  5. Check Set the maximum number of uses per order and enter 1, so the promotion applies once per order.
  6. Set Combinations and the active dates, then click Save.

The minimum purchase amount counts product prices only. Shipping and taxes are excluded, and products count at full price before any other discount.1

Because you choose which products count, keep the gift itself out of that selection so its own price cannot help a cart qualify. For where to set the number, see our guide to setting a free shipping threshold - the same logic applies.

What are the limits?

Why doesn’t Shopify add the free gift to the cart automatically?

Because a discount changes prices, not cart contents. Shopify’s help page is direct about it: “The free or discounted ‘get’ item is never automatically added to the cart.”1

A shopper who spends $80 and goes straight to checkout gets no gift, no error, and no hint that one was on offer. There are three ways to close the gap.

Method 1: Tell the customer clearly (no code)

The cheapest fix is copy. Say what the gift is, what the threshold is, and that it has to be added - on the product page, in the cart and in the announcement bar - and link straight to the gift product.

The weakness is plain: some shoppers will not read it. A message that reacts to the cart is harder to miss than a static line. It works like a free shipping bar that updates with the cart: read the cart total, compare it with the threshold, show the difference.

The Fudge route. Fudge writes that message into your cart drawer and product page as native theme code. Tell Fudge:

“Add a gift progress message to the cart drawer and the product page. Under $75 it says ‘You’re $12 away from a free travel-size cleanser’ using the real remaining amount. At $75 or more it shows the cleanser with an ‘Add my free gift’ button.”

You get a draft to preview and review before publishing. The Buy X Get Y discount still does the discounting.

Method 2: Add the gift with theme code

Shopify’s Cart AJAX API lets theme JavaScript change the cart: a POST to /cart/add.js adds a variant, and a POST to /cart/change.js with a quantity of 0 removes a line.4 A short script can add the gift when spend reaches the threshold and take it out when spend falls back.

Duplicate your theme first. Then go to Online Store → Themes → ⋯ → Edit code, create snippets/free-gift.liquid, and paste this in with your own threshold and variant ID. The ID is the number after /variants/ in the admin URL when you open the variant; for a product without variants, add .json to the product’s admin URL and read the variant ID there.

<script>
    document.addEventListener('DOMContentLoaded', function () {
        var GIFT_VARIANT_ID = 41234567890123 // your gift variant ID
        var THRESHOLD = 7500 // $75.00 - the Cart API works in cents
        var root = window.Shopify.routes.root
        var busy = false

        function post(path, body) {
            return fetch(root + path, {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify(body),
            })
        }

        function syncGift() {
            if (busy) return
            busy = true
            fetch(root + 'cart.js')
                .then(function (response) {
                    return response.json()
                })
                .then(function (cart) {
                    var gift = null
                    var spend = 0
                    cart.items.forEach(function (item) {
                        if (item.variant_id === GIFT_VARIANT_ID) gift = item
                        else spend += item.original_line_price
                    })
                    var offered = sessionStorage.getItem('giftOffered') === '1'
                    if (gift) sessionStorage.setItem('giftOffered', '1')

                    if (spend >= THRESHOLD && !gift && !offered) {
                        sessionStorage.setItem('giftOffered', '1')
                        return post('cart/add.js', {
                            items: [{id: GIFT_VARIANT_ID, quantity: 1}],
                        })
                    }
                    if (spend < THRESHOLD) {
                        sessionStorage.removeItem('giftOffered')
                        if (gift) return post('cart/change.js', {id: gift.key, quantity: 0})
                    }
                })
                .then(function (response) {
                    // Dawn: ask the cart drawer or cart page to re-render
                    if (response && response.ok && window.publish) {
                        publish(PUB_SUB_EVENTS.cartUpdate, {source: 'free-gift'})
                    }
                })
                .catch(function (error) {
                    console.error(error)
                })
                .finally(function () {
                    busy = false
                })
        }

        // Dawn announces every cart change on this event
        if (window.subscribe) {
            subscribe(PUB_SUB_EVENTS.cartUpdate, function (event) {
                if (event && event.source === 'free-gift') return
                syncGift()
            })
        }
        syncGift()
    })
</script>

Then load the snippet just before the closing body tag in layout/theme.liquid:

{% render 'free-gift' %}

The script totals every line except the gift at its pre-discount price, mirroring how the discount counts the minimum. The giftOffered flag stops it adding the gift twice, re-adding one the customer removed, or retrying a sold-out gift.

The script only moves the item. The Buy X Get Y discount is still what makes it free, so the two thresholds must match. If the script’s number is lower, customers find a full-price item in the cart.

Know its edges before you ship it:

The Fudge route. Fudge does this for you: it writes the add-and-remove logic for your theme’s cart, so there is nothing to hand-code and no rewiring per theme. Tell Fudge:

“When the cart subtotal reaches $75, automatically add the free travel-size cleanser to the cart and show a ‘Free gift added’ line in the cart drawer. Remove it if the cart drops below $75, and don’t add it twice.”

Fudge writes the cart drawer logic as native Liquid, CSS and JavaScript in your theme, as a draft you review before publishing. The discount that makes the gift $0 is still the Buy X Get Y discount you create in the Shopify admin - Fudge does not create or configure discounts.

Want the gift in the cart without hand-coding it? Describe it to Fudge.
Try Fudge for Free

Method 3: Use an app or a Shopify Function

Gift apps package Method 2 behind a settings screen: you pick the gift and the threshold, and the app adds the item to the cart. Check the live App Store listing for current plans.

The trade is a monthly fee plus app code on your storefront, because something has to run in the browser to add the item. If you already use an app for cart upsells, check whether it covers gifts before adding another.

Shopify Functions fit less well than they sound. Discount Functions decide what cart lines cost, and the Cart Transform API expands, merges or updates lines already in the cart. Neither reference describes an operation that drops a separate new item into it.6

Stores on any plan can use Functions through a public App Store app; custom apps that contain Functions require Shopify Plus.6

Which free gift with purchase method should you use?

MethodCostAdds the gift?Removes it below the threshold?Effort
Buy X Get Y + clear messagingIncluded in ShopifyNo, the customer adds itNo - it stays at full priceLow
Buy X Get Y + hand-written theme codeDeveloper timeYesYes, if you code itHigh, theme-specific
Buy X Get Y + FudgeFudge planYesYes, when the prompt asks for itLow - a prompt and a review
Gift appMonthly fee, see the listingYesConfirm on the listingLow to medium

Do the messaging whichever row you pick. The Shopify store editor page shows how the Fudge route works.


What edge cases should you plan for?

What happens when the gift is out of stock?

Turn on Inventory tracked for the gift variant and leave Continue selling when out of stock unchecked. At zero stock customers cannot buy it, the add request from Method 2 is rejected with a 422 error, and orders go through without a gift.4

Your messaging does not update itself, so pull the banner when the gift runs out, or point Customer gets at a gift collection so a second item can stand in.

What if the cart drops below the threshold?

The discount stops applying. The gift does not leave the cart on its own - it stays there at full price. The Method 2 script removes it; with Method 1, the cart message should say the gift is no longer free.

What if the customer removes the gift?

Let them. The script above adds the gift once, and not again until the cart has dropped below the threshold and come back.

Can customers choose their gift?

Yes. Customer gets accepts a collection, so any item in it can be the free one. Auto-add cannot guess a shade or a size, so a choice needs a picker. If the gift is really part of a set, compare native Shopify bundles vs bundle apps.

The Fudge route. Tell Fudge:

“When the cart reaches $75, show a ‘Choose your free gift’ block in the cart drawer with the three products from my Free Gifts collection. Let the customer pick one, add it to the cart, and let them swap it for another.”

The result is a native theme block in draft. Set the discount’s Customer gets to the same collection.

How do you stop the gift being bought on its own for free?

Give the gift product a real price. The discount only takes it to $0 when the minimum is met, so on its own it sells at full price. A product priced at $0 can be added by anyone.

What happens when the qualifying item is returned?

The discount pages we checked describe no automatic recovery of the gift, so treat it as a policy decision. State in your returns policy whether the gift must come back or its value is deducted.

How does the gift show on the order?

As a regular line item with its own SKU, discounted to $0. A real product with tracked inventory reaches picking and packing like any other line.

Spend more, save more: what about tiered discounts?

Shopify tiered discounts have no dedicated discount type. Shopify’s help page sends merchants who need advanced tiered discounts to the App Store, or to Checkout Blocks on Shopify Plus.7

Simple spend tiers can still be assembled from native parts. Create one automatic amount off order discount per tier, each with its own minimum purchase amount:

Under Combinations, leave order discounts unchecked on both. A cart that qualifies for two discounts that cannot combine gets the one that is best for the customer.3

Worked example. A $230 cart qualifies for both tiers. They cannot combine, so the 20% tier applies: $46 off, $184 to pay. A $150 cart reaches only the first tier: $15 off, $135 to pay.

The trap is the combination box. If the tiers are allowed to combine, both percentages are calculated on the original subtotal, so that $230 cart gets 30% off and pays $161.3

Each tier uses one of your 25 automatic discount slots.

What still needs an app or a discount Function: tiers managed as a single discount, and one discount that mixes rewards such as a percentage off plus free shipping.7 To run tiers alongside the free gift, check product discounts on each tier and order discounts on the Buy X Get Y discount, then test a cart at every tier boundary.

Our BFCM playbook covers where to show the tiers on the storefront.

FAQ

Does Shopify automatically add a free gift to the cart?

No. A Buy X Get Y discount makes the gift free, but the customer has to add the gift to the cart before the discount applies. To add it automatically you need theme code that uses the Cart AJAX API, which Fudge can write from a prompt, or an app that does the same job.

How do I create a free gift with purchase on Shopify without an app?

In your Shopify admin go to Discounts, create a Buy X get Y discount, choose Automatic discount, set a minimum purchase amount under Customer buys, select the gift under Customer gets, and choose Free. Then tell customers to add the gift, or add theme code that puts it in the cart when the threshold is reached.

Why is my Buy X Get Y free gift not applying?

The usual causes are that the gift is not in the cart, the qualifying products are below the minimum, or the items are not in the collections the discount names. Another discount can also win: when discounts cannot combine, Shopify applies the one that is best for the customer's cart.

Can customers choose which free gift they get?

Yes. Point the Customer gets part of the discount at a collection of gifts and any item in that collection can be the free one. Because automatic add-to-cart cannot guess a shade or a size, a gift choice needs a picker in the cart or on the product page.

What happens to the free gift if the cart drops below the threshold?

The discount stops applying and the gift stays in the cart at full price. Shopify does not remove it. Theme code or an app has to remove the gift line, or your cart message has to tell the customer it is no longer free.

Can I run tiered discounts on Shopify without an app?

Simple spend tiers, yes. Create one automatic amount off order discount per tier with its own minimum purchase amount, and do not let them combine with each other, so the best one applies to each cart. Tiers managed inside a single discount need an app or a discount Function.

How many automatic discounts can be active at once on Shopify?

Up to 25 active automatic discounts per store, including Buy X Get Y, amount off, free shipping and app-based automatic discounts. A free gift uses one of them, and each native spend tier uses one more.

Jacques's signature
Describe the gift logic. Get theme code, not an app.

Footnotes

  1. Shopify Help Center, “Buy X get Y discounts” - customers must add all items to the cart manually and the “get” item is never added automatically; the minimum purchase amount counts product prices only, excludes shipping and taxes, and counts products at full price before other discounts; the reward can be a percentage, an amount off each, or free, with an optional maximum number of uses per order. https://help.shopify.com/en/manual/discounts/discount-types/buy-x-get-y ↩ ↩2 ↩3 ↩4

  2. Shopify Help Center, “Automatic discounts” - automatic discounts apply in the cart and at checkout when eligibility conditions are met, can be amount off, free shipping, Buy X Get Y or app-based, and a store can have a maximum of 25 active at once. https://help.shopify.com/en/manual/discounts/discount-methods/automatic-discounts ↩ ↩2

  3. Shopify Help Center, “Combining discounts” - discounts combine only when their combination settings allow it; products in a Buy X Get Y discount are ineligible for further product discounts outside Shopify Plus; when discounts cannot combine, the best discount for the customer’s cart applies; two percentage order discounts that do combine are both calculated on the original subtotal. https://help.shopify.com/en/manual/discounts/discount-combinations ↩ ↩2 ↩3 ↩4 ↩5

  4. Shopify developer documentation, “Cart API reference” - /cart/add.js adds variants from an items array and returns a 422 error when the product is sold out; /cart/change.js accepts a line item key or variant ID and removes the line when quantity is 0; /cart.js returns prices in cents; requests should be built from window.Shopify.routes.root. https://shopify.dev/docs/api/ajax/reference/cart ↩ ↩2

  5. Shopify, Dawn theme source, assets/cart.js - the cart items and cart drawer items elements subscribe to the theme’s cart update event and re-fetch their section when it fires from another source; the drawer handler replaces the drawer items and footer. https://github.com/Shopify/dawn/blob/main/assets/cart.js ↩

  6. Shopify developer documentation, “Shopify Functions” - stores on any plan can use public App Store apps that contain Functions, and only Shopify Plus stores can use custom apps that contain them (https://shopify.dev/docs/apps/build/functions). The Cart Transform Function API reference lists three operations, which expand, merge and update cart lines (https://shopify.dev/docs/api/functions/latest/cart-transform). ↩ ↩2

  7. Shopify Help Center, “Discount types” - for more advanced needs such as tiered discounts the page points to discount apps on the Shopify App Store, or Checkout Blocks on Shopify Plus, and notes that apps can provide a single discount that applies more than one saving to an order. https://help.shopify.com/en/manual/discounts/discount-types ↩ ↩2

You might also be interested in

Sticky Add to Cart on Shopify PDPs (2026)
Sticky add to cart on Shopify keeps price, variant, and buy button visible as shoppers scroll. How to build it natively with no app.
Shopify Image Sizes: Product Photos, Banners, and Mobile Cropping Explained
Shopify image sizes in one table: product photos, banners, logos and favicons. Plus why banners crop on mobile and how to fix blurry images.
Server-Side Tagging for BFCM: Meta CAPI on Shopify
What Shopify's Meta channel sends server-side, when you need server-side GTM or Stape, event_id deduplication, and how to check Event Match Quality.