Shopify CROโฑ 5 min read

How to Add a Free Gift With Purchase Tier in Shopify Cart Drawer (Liquid Snippet)

Learn how to engineer a tiered Free Gift With Purchase (GWP) progress bar inside your Shopify cart drawer using pure Liquid and Shopify Cart API.

Muhammad Bilal ShakeelWritten by Muhammad Bilal Shakeel
โ€ขPublished: 2026-08-16โ€ขUpdated: 2026-09-18
Advertisement

Offering an automated Free Gift with Purchase (GWP) is a proven direct-to-consumer (DTC) merchandising strategy that lifts Average Order Value (AOV) while introducing shoppers to new product lines. Instead of relying on expensive third-party cart apps that inject heavy JavaScript libraries and charge monthly subscription fees, you can engineer an automated free gift tier directly into your native Shopify cart drawer using Liquid and the Shopify Ajax Cart API. Below is a complete implementation guide for Shopify Dawn and OS 2.0 themes.

๐ŸŽ The Mechanics of an Automated Cart Drawer Gift Tier

A native Gift with Purchase workflow requires three coordinated mechanics: (1) Liquid qualification check that evaluates if cart.total_price meets the spend threshold (e.g. $100.00 / 10000 cents); (2) Automated Ajax injection that adds the promotional gift variant ID to the cart with a special property (_is_free_gift: true); and (3) Automated removal logic that removes the gift if the shopper decreases cart value below the qualification threshold, preventing promotional abuse.

1. Production Liquid Snippet: snippets/cart-drawer-free-gift.liquid

Create a new snippet in your theme named cart-drawer-free-gift.liquid:

{% comment %}
  snippets/cart-drawer-free-gift.liquid
  Free Gift with Purchase Progress Bar and Status Banner
{% endcomment %}
{% assign gift_threshold = 10000 %}{% comment %} Threshold in cents: $100.00 {% endcomment %}
{% assign gift_variant_id = 42987654321098 %}{% comment %} Target promotional product variant ID {% endcomment %}
{% assign cart_total = cart.total_price %}

{% assign has_gift = false %}
{% for item in cart.items %}
  {% if item.variant_id == gift_variant_id %}
    {% assign has_gift = true %}
    {% break %}
  {% endif %}
{% endfor %}

<div id="cart-drawer-gift-tier" class="gift-tier-container" data-threshold="{{ gift_threshold }}" data-gift-id="{{ gift_variant_id }}" data-has-gift="{{ has_gift }}">
  {% if cart_total >= gift_threshold %}
    <div class="gift-badge gift-unlocked">
      <span class="gift-icon">๐ŸŽ</span>
      <span class="gift-text"><strong>Free Gift Unlocked!</strong> Your bonus gift has been added to your cart.</span>
    </div>
  {% else %}
    {% assign deficit = gift_threshold | minus: cart_total %}
    <div class="gift-badge gift-locked">
      <span class="gift-icon">โœจ</span>
      <span class="gift-text">Add <strong>{{ deficit | money }}</strong> more to unlock your <strong>FREE Mystery Gift</strong>!</span>
    </div>
  {% endif %}
</div>

2. Client-Side Ajax Auto-Add & Removal in assets/cart-drawer.js

In your theme's assets/cart-drawer.js, hook into the cart update cycle to automatically inject or remove the promotional gift:

// Automated Gift with Purchase Handler
async function syncFreeGiftTier(cart) {
  const tierEl = document.getElementById('cart-drawer-gift-tier');
  if (!tierEl) return;

  const threshold = parseInt(tierEl.dataset.threshold, 10);
  const giftVariantId = parseInt(tierEl.dataset.giftId, 10);
  const cartTotal = cart.total_price;
  const hasGiftInCart = cart.items.some(item => item.variant_id === giftVariantId);

  // Case A: Reached threshold and gift not yet in cart -> Auto Add
  if (cartTotal >= threshold && !hasGiftInCart) {
    await fetch('/cart/add.js', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        items: [{
          id: giftVariantId,
          quantity: 1,
          properties: { '_is_free_gift': 'true' }
        }]
      })
    });
    // Trigger drawer re-render
    if (window.routes && window.routes.cart_url) window.location.reload();
  }
  // Case B: Cart dropped below threshold and gift is still in cart -> Auto Remove
  else if (cartTotal < threshold && hasGiftInCart) {
    const giftItem = cart.items.find(item => item.variant_id === giftVariantId);
    if (giftItem) {
      await fetch('/cart/change.js', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ id: giftItem.key, quantity: 0 })
      });
      if (window.routes && window.routes.cart_url) window.location.reload();
    }
  }
}

3. Shopify Platform Limitations & Pricing Protection

Understanding platform checkout constraints is critical when developing custom GWP solutions:

  • Shopify Base Price Immutability: The Shopify Ajax Cart API cannot override a product variant's price to $0.00 directly on standard plans. To ensure the customer is not billed for the gift at checkout, pair this workflow with an Automatic Discount in Shopify Admin ("Spend $100, get Variant X for 100% off") or deploy a Shopify Functions Discounts API extension on Shopify Plus.
  • Quantity Lock in Cart Drawer: Disable the quantity increment button (+) and quantity input box for items possessing the custom property _is_free_gift: true to prevent shoppers from claiming multiple free gifts.
  • Inventory Controls: If the free gift variant inventory reaches 0 units, ensure the script detects out-of-stock status and falls back to a secondary promotional variant rather than throwing an Ajax error.

4. Multi-Tier Milestone Architecture: Free Shipping + Free Gift Stacking

To maximize conversion momentum, leading e-commerce brands combine the Free Shipping threshold with one or more Free Gift tiers in a unified progress component. For example: unlocks Free Shipping, unlocks a Free Travel Bag, and unlocks an Exclusive Full-Size Serum. Implementing this in Liquid and JavaScript requires maintaining a structured configuration array:

// Multi-Tier Milestone Configuration
const MILESTONE_TIERS = [
  { threshold: 5000, label: 'Free Shipping', type: 'shipping' },
  { threshold: 10000, label: 'Free Travel Bag', type: 'gift', variantId: 42987654321098 },
  { threshold: 15000, label: 'Full-Size Serum', type: 'gift', variantId: 42987654321099 }
];

When handling multiple automated gift additions, queue Ajax requests sequentially using Promise chaining or async/await calls. Firing simultaneous uncoordinated POST requests to /cart/add.js triggers Shopify race conditions, causing inventory lock errors or omitted items.

5. Frequently Asked Questions

Can customers order multiple quantities of the free gift without paying?

In our snippet, the free gift item is marked with the custom line item property _is_free_gift: true. In your theme's cart-drawer.liquid, check for this property: if present, hide the quantity incrementer (+) and quantity selector input. This prevents shoppers from adjusting the quantity from 1 to 5 in the cart drawer.

What happens if the promotional gift goes out of stock during a flash sale?

Before executing /cart/add.js, query /products/[handle].js to verify that the gift variant has available: true. If out of stock, configure the script to fall back to an alternate variant ID or display an alternate perk (such as complimentary samples) to maintain trust and prevent checkout errors.

Looking for Custom Shopify Liquid Architecture?

Need custom cart drawers, tiered reward progress bars, or checkout extensibility engineering? Explore our Shopify Engineering services or review our App-Free Cart Drawer Tutorial.

Advertisement
โ“

Frequently Asked Questions

How does Free Gift with Purchase (GWP) increase Shopify AOV?

GWP creates a powerful psychological milestone, incentivizing shoppers who have $70 in their cart to add another $30 item to hit a $100 free gift threshold, lifting Average Order Value by 18-25%.

How do you automatically add a free gift variant to the cart via Liquid?

When `cart.total_price` exceeds your threshold, JavaScript dispatches a POST request to `/cart/add.js` with the gift variant ID and price set to $0 or discounted via automatic Shopify discount scripts.

What prevents customers from keeping the free gift if they remove cart items?

A cart change event listener validates `cart.total_price`. If the total falls below the qualifying threshold, the script automatically sends a POST to `/cart/change.js` setting the gift item quantity to 0.

Muhammad Bilal Shakeel (Goofy Developer)

Founder of Build With Goofy. Specializing in bespoke Shopify Liquid development, Core Web Vitals & mobile performance engineering, and automated GoHighLevel CRM workflows for clients across the USA, Canada, UK, and worldwide.

โšก Shopify Store Optimization & Development

Need Help Fixing This on Your Store?

Send us your Shopify store URL for a comprehensive speed, Liquid code, and conversion architecture review.

๐Ÿ’ฌ WhatsApp Bilal Directly

Related Developer Guides & Systems

View all guides โ†’