How to Add a Free Gift with Purchase on Shopify (Step-by-Step Guide) - eCommerce Thesis

How to Add a Free Gift with Purchase on Shopify (Step-by-Step Guide)

In the competitive world of eCommerce, increasing average order value and reducing cart abandonment are constant challenges. One proven strategy that addresses both issues is implementing a free gift widget that rewards customers when they reach a specific spending threshold. In this comprehensive guide, we’ll explore how to create a premium free gift cart widget that not only boosts conversions but enhances the overall shopping experience.

Table of Contents

  1. The Power of Free Gifts in eCommerce
  2. Key Features of a Premium Gift Widget
  3. Design Elements That Convert
  4. Technical Implementation Guide
  5. Psychological Triggers and UX Considerations
  6. Measuring Success and Optimization
  7. Future Trends in Cart Incentivization

The Power of Free Gifts in eCommerce

Free gifts have long been a powerful marketing tool, but their impact on eCommerce is particularly significant. According to recent studies:

  • 72% of consumers are more likely to purchase from brands that offer free gifts with purchase
  • Average order value increases by 28-35% when free gift thresholds are implemented
  • Cart abandonment decreases by up to 18% when shoppers are close to qualifying for a gift

The psychology behind this is simple yet powerful: free gifts trigger dopamine release in the brain, creating positive associations with your brand while simultaneously increasing perceived value.

Key Features of a Premium Gift Widget

1. Visual Appeal with Purpose

Our premium widget incorporates:

  • Elegant card design with subtle gradients and shadows
  • Strategic color psychology using blues (trust) and ambers (excitement)
  • Animated elements that guide attention without being distracting
  • Responsive design that works flawlessly across all devices

2. Advanced Animation Suite

Engage customers with subtle animations:

  • 360-degree rotating gift icon that suggests celebration
  • Gentle product image shake that creates a “unboxing” anticipation
  • Pulsing “FREE” badge that draws attention to the value proposition
  • Progress bar with shimmer effect that visually represents achievement

3. Smart Cart Integration

  • Real-time threshold tracking that updates without page refresh
  • Session-based dismissal that respects user preferences
  • Seamless gift addition without disrupting the shopping experience
  • Inventory-aware functionality that only shows available gifts

4. Psychological Triggers

  • Progress visualization that leverages the goal-gradient effect
  • Social proof through “You’ve qualified” messaging
  • Scarcity and urgency through limited-time gift offers
  • Value contrast between original price and “FREE” designation

Design Elements That Convert

Color Psychology Implementation

Our widget uses a carefully researched color scheme:

  • Primary Blue (#3B82F6): Creates trust and professionalism
  • Amber Accent (#F59E0B): Draws attention and suggests value
  • White Background: Provides clarity and highlights the gift
  • Gradient Effects: Adds depth and premium feel

Typography Hierarchy

  • Bold headings (1.375rem) for primary messaging
  • Clear body text (0.9375rem) for explanations
  • Prominent CTAs with sufficient size and contrast
  • Consistent font families that match your store’s branding

Interactive Elements

  • Hover effects on buttons that provide tactile feedback
  • Smooth transitions between states (add to cart → loading → success)
  • Non-obtrusive close option for users who aren’t interested
  • Mobile-optimized touch targets for thumb-friendly interaction

Technical Implementation Guide

Step 1: Schema Configuration

The widget uses Shopify’s section schema for easy customization:

json

{
  "type": "number",
  "id": "cart_threshold",
  "label": "Cart minimum amount (in cents)",
  "info": "Widget appears when cart total reaches this amount.",
  "default": 10000
}

Step 2: Smart Cart Detection

JavaScript functions monitor cart changes in real-time:

javascript

function updateWidgetVisibility(cartTotal) {
  const shouldShow = cart.item_count > 0 && cartTotal >= threshold;
  // Logic to show/hide widget based on threshold
}

Step 3: Animation Implementation

CSS keyframes create engaging animations:

css

@keyframes faIconRoll {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

Step 4: Performance Optimization

  • Lazy loading of gift images
  • Efficient DOM queries for better performance
  • Debounced cart updates to prevent excessive API calls
  • Session storage for user preferences

Psychological Triggers and UX Considerations

The Goal-Gradient Effect

Humans are motivated by proximity to goals. Our progress bar visually represents how close customers are to receiving their gift, encouraging them to add just one more item to qualify.

Perceived Value Enhancement

By showing the original price crossed out next to “FREE,” we create a powerful contrast that makes the gift feel more valuable than its actual cost.

Decision Simplicity

The widget reduces cognitive load by:

  • Clearly stating the requirement
  • Showing the exact reward
  • Providing a one-click addition process
  • Confirming success with visual feedback

Reducing Abandonment Anxiety

Customers near the threshold are less likely to abandon their cart when they know they’re close to receiving a reward, reducing last-minute abandonment.

Measuring Success and Optimization

Key Performance Indicators

  1. Threshold Achievement Rate: Percentage of carts that reach the gift threshold
  2. Gift Redemption Rate: Percentage of qualified carts that claim the gift
  3. Average Order Value Impact: Change in AOV after implementation
  4. Conversion Rate Change: Overall impact on completed purchases

A/B Testing Opportunities

  • Threshold values ($50 vs. $75 vs. $100)
  • Gift types (product samples vs. accessories vs. full products)
  • Messaging variations (“Free Gift” vs. “Bonus” vs. “Special Reward”)
  • Design treatments (color schemes, animation intensity)

Analytics Implementation

Track widget performance with custom events:

javascript

// Example tracking event
document.addEventListener('fa:gift-added', function(event) {
  // Send to analytics platform
  analytics.track('Gift Added to Cart', {
    productId: event.detail.productId,
    variantId: event.detail.variantId
  });
});

Future Trends in Cart Incentivization

Personalization

Future implementations will include:

  • Customer-specific thresholds based on purchase history
  • Personalized gift options tailored to individual preferences
  • Dynamic messaging that references past purchases

AI-Powered Optimization

Machine learning will enable:

  • Predictive threshold setting based on real-time conversion data
  • Automated gift selection that maximizes perceived value
  • Sentiment analysis to determine optimal messaging

Augmented Reality Integration

  • Virtual gift previews that show products in customers’ environments
  • Interactive unboxing experiences before purchase
  • Social sharing features that leverage gift excitement

Conclusion

Implementing a premium free gift cart widget is one of the most effective strategies for increasing average order value and reducing cart abandonment. By combining psychological principles with elegant design and smooth functionality, you can create a powerful tool that delights customers while boosting your bottom line.

The key to success lies in:

  1. Strategic threshold setting that balances achievability and profitability
  2. High-perceived-value gifts that genuinely excite customers
  3. Seamless user experience that doesn’t disrupt the shopping journey
  4. Continuous optimization based on performance data

Ready to implement your own premium gift widget? The code provided in this article offers a complete, production-ready solution that you can customize for your eCommerce store. Start with the recommended color scheme and threshold values, then iterate based on your specific customer behavior and business goals.


This guide was created by Foysal Ahmed as part of an eCommerce thesis project. The implementation represents industry best practices for cart incentivization and conversion rate optimization.


{% comment %}
<!-- Premium Cart Free Gift Widget -->
<!-- Designed and developed by Foysal Ahmed for eCommerce Thesis -->
{% endcomment %}

{% if section.settings.enable_widget and section.settings.gift_product %}
  {% assign gift_product = all_products[section.settings.gift_product] %}
  {% if gift_product and gift_product.available %}
    {% assign gift_variant = gift_product.selected_or_first_available_variant %}
    <div class="fa-gift-widget" id="fa-gift-widget-{{ section.id }}" style="display: {% if cart.empty? or cart.total_price < section.settings.cart_threshold %}none{% else %}block{% endif %};">
      <div class="fa-gift-container">
        <div class="fa-gift-card">
          <div class="fa-gift-header">
            <div class="fa-gift-icon">
              <svg width="52" height="52" viewBox="0 0 52 52" fill="none">
                <circle cx="26" cy="26" r="26" fill="var(--fa-icon-bg-{{ section.id }})"/>
                <path d="M26 10L29.755 20.845L41 19.32L33.445 28L41 36.68L29.755 35.155L26 46L22.245 35.155L11 36.68L18.555 28L11 19.32L22.245 20.845L26 10Z" fill="var(--fa-icon-inner-{{ section.id }})"/>
              </svg>
            </div>
            <div class="fa-gift-header-content">
              <h3 class="fa-gift-title">{{ section.settings.main_title }}</h3>
              <p class="fa-gift-subtitle">{{ section.settings.subtitle }}</p>
            </div>
            <button class="fa-gift-close" aria-label="Close gift widget">
              <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
                <path d="M13.854 2.146a.5.5 0 0 1 0 .708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708 0z"/>
              </svg>
            </button>
          </div>
          
          <div class="fa-gift-body">
            <div class="fa-gift-product">
              <div class="fa-product-image">
                {% if gift_product.featured_image %}
                  <img src="{{ gift_product.featured_image | image_url: width: 140 }}" 
                       alt="{{ gift_product.title | escape }}" 
                       loading="lazy"
                       width="140"
                       height="140">
                {% else %}
                  <div class="fa-product-placeholder">
                    <svg width="48" height="48" viewBox="0 0 48 48" fill="currentColor">
                      <rect x="8" y="12" width="32" height="24" rx="2" stroke="currentColor" stroke-width="2" fill="none"/>
                      <circle cx="18" cy="22" r="3"/>
                      <path d="M32 28l-5-5-7 7-3-3-5 5"/>
                    </svg>
                  </div>
                {% endif %}
              </div>
              <div class="fa-product-details">
                <h4 class="fa-product-title">{{ gift_product.title }}</h4>
                <p class="fa-product-description">{{ gift_product.description | strip_html | truncatewords: 12 }}</p>
                <div class="fa-product-price">
                  {% if section.settings.display_price and section.settings.display_price != blank %}
                    <span class="fa-original-price">{{ section.settings.display_price | times: 100 | money }}</span>
                  {% endif %}
                  <span class="fa-free-label">FREE</span>
                </div>
                <div class="fa-product-actions">
                  <button class="fa-add-gift-btn" 
                          id="fa-add-gift-{{ section.id }}"
                          data-variant-id="{{ gift_variant.id }}"
                          data-product-id="{{ gift_product.id }}"
                          data-threshold="{{ section.settings.cart_threshold }}"
                          data-quantity="{{ section.settings.gift_quantity }}">
                    <span class="fa-btn-text">{{ section.settings.button_text }}</span>
                    <span class="fa-btn-loading" style="display: none;">
                      <svg width="20" height="20" viewBox="0 0 24 24" fill="none">
                        <circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-dasharray="28.27" stroke-dashoffset="28.27">
                          <animate attributeName="stroke-dasharray" dur="1.5s" values="0 28.27;14.135 14.135;0 28.27" repeatCount="indefinite"/>
                          <animate attributeName="stroke-dashoffset" dur="1.5s" values="0;-14.135;-28.27" repeatCount="indefinite"/>
                        </circle>
                      </svg>
                    </span>
                    <span class="fa-btn-success" style="display: none;">
                      <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
                        <path d="M16.136 6.136a.5.5 0 0 1 0 .708l-8 8a.5.5 0 0 1-.708 0l-4-4a.5.5 0 1 1 .708-.708L7.5 13.793l7.636-7.637a.5.5 0 0 1 .708 0z"/>
                      </svg>
                    </span>
                  </button>
                  <p class="fa-already-added" style="display: none;">
                    <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
                      <path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm-1-5.5a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v5zM8 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
                    </svg>
                    {{ section.settings.already_added_text }}
                  </p>
                </div>
              </div>
            </div>
          </div>
          
          <div class="fa-gift-footer">
            <div class="fa-progress-container">
              <div class="fa-progress-label">
                <span class="fa-progress-text">You're {{ cart.total_price | times: 1.0 | divided_by: section.settings.cart_threshold | times: 100 | round }}% to your free gift</span>
                <span class="fa-progress-amount">{{ cart.total_price | money }} / {{ section.settings.cart_threshold | money }}</span>
              </div>
              <div class="fa-progress-bar">
                <div class="fa-progress-fill" style="width: {% if cart.total_price >= section.settings.cart_threshold %}100%{% else %}{{ cart.total_price | times: 1.0 | divided_by: section.settings.cart_threshold | times: 100 }}%{% endif %}"></div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  {% endif %}
{% endif %}

<style>
  :root {
    --fa-card-bg-{{ section.id }}: {{ section.settings.card_background_color }};
    --fa-card-border-{{ section.id }}: {{ section.settings.card_border_color }};
    --fa-icon-bg-{{ section.id }}: {{ section.settings.icon_background_color }};
    --fa-icon-inner-{{ section.id }}: {{ section.settings.icon_inner_color }};
    --fa-title-color-{{ section.id }}: {{ section.settings.title_color }};
    --fa-subtitle-color-{{ section.id }}: {{ section.settings.subtitle_color }};
    --fa-product-title-color-{{ section.id }}: {{ section.settings.product_title_color }};
    --fa-product-description-color-{{ section.id }}: {{ section.settings.product_description_color }};
    --fa-price-color-{{ section.id }}: {{ section.settings.price_color }};
    --fa-free-bg-{{ section.id }}: {{ section.settings.free_label_background }};
    --fa-free-text-{{ section.id }}: {{ section.settings.free_label_text }};
    --fa-btn-bg-{{ section.id }}: {{ section.settings.button_background }};
    --fa-btn-text-{{ section.id }}: {{ section.settings.button_text_color }};
    --fa-btn-hover-{{ section.id }}: {{ section.settings.button_hover_color }};
    --fa-progress-bg-{{ section.id }}: {{ section.settings.progress_background }};
    --fa-progress-fill-{{ section.id }}: {{ section.settings.progress_fill }};
    --fa-progress-text-{{ section.id }}: {{ section.settings.progress_text_color }};
  }

  #fa-gift-widget-{{ section.id }} {
    margin: 28px 0;
    width: 100%;
    position: relative;
    z-index: 5;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-container {
    position: relative;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-card {
    background: linear-gradient(135deg, var(--fa-card-bg-{{ section.id }}), color-mix(in srgb, var(--fa-card-bg-{{ section.id }}) 90%, black));
    border: 1px solid var(--fa-card-border-{{ section.id }});
    border-radius: 16px;
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 20px;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.15), 0 10px 10px -5px rgba(0, 0, 0, 0.08);
    position: relative;
    overflow: hidden;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: linear-gradient(90deg, var(--fa-icon-bg-{{ section.id }}), var(--fa-free-bg-{{ section.id }}));
    animation: faProgressPulse 3s infinite;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-header {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    position: relative;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-close {
    position: absolute;
    top: 0;
    right: 0;
    background: transparent;
    border: none;
    color: var(--fa-subtitle-color-{{ section.id }});
    opacity: 0.7;
    cursor: pointer;
    padding: 4px;
    border-radius: 4px;
    transition: all 0.2s ease;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-close:hover {
    opacity: 1;
    background: rgba(0, 0, 0, 0.05);
    transform: rotate(90deg);
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-icon {
    background: linear-gradient(135deg, var(--fa-icon-bg-{{ section.id }}), color-mix(in srgb, var(--fa-icon-bg-{{ section.id }}) 80%, black));
    border-radius: 50%;
    width: 52px;
    height: 52px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: var(--fa-icon-inner-{{ section.id }});
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
    animation: faIconRoll 8s infinite linear;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-header-content {
    flex: 1;
    min-width: 0;
    padding-right: 24px;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-title {
    font-family: var(--font-heading-family);
    font-size: 1.375rem;
    font-weight: 800;
    color: var(--fa-title-color-{{ section.id }});
    margin: 0 0 6px 0;
    line-height: 1.3;
    letter-spacing: -0.02em;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-subtitle {
    font-family: var(--font-body-family);
    font-size: 0.9375rem;
    color: var(--fa-subtitle-color-{{ section.id }});
    margin: 0;
    line-height: 1.5;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-body {
    border-top: 1px solid rgba(255, 255, 255, 0.2);
    border-bottom: 1px solid rgba(255, 255, 255, 0.2);
    padding: 20px 0;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-product {
    display: flex;
    align-items: center;
    gap: 16px;
  }

  #fa-gift-widget-{{ section.id }} .fa-product-image {
    width: 100px;
    height: 100px;
    border-radius: 12px;
    overflow: hidden;
    flex-shrink: 0;
    background: linear-gradient(45deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.2));
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
    position: relative;
    animation: faImageShake 6s infinite ease-in-out, faImageZoom 8s infinite alternate ease-in-out;
  }

  #fa-gift-widget-{{ section.id }} .fa-product-image::after {
    content: 'GIFT';
    position: absolute;
    top: 6px;
    right: 6px;
    background: var(--fa-free-bg-{{ section.id }});
    color: var(--fa-free-text-{{ section.id }});
    font-size: 10px;
    font-weight: 800;
    padding: 2px 6px;
    border-radius: 4px;
    letter-spacing: 0.5px;
    animation: faPulse 2s infinite;
  }

  #fa-gift-widget-{{ section.id }} .fa-product-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.5s ease;
  }

  #fa-gift-widget-{{ section.id }} .fa-product-image:hover img {
    transform: scale(1.1);
  }

  #fa-gift-widget-{{ section.id }} .fa-product-placeholder {
    color: var(--fa-subtitle-color-{{ section.id }});
    opacity: 0.6;
  }

  #fa-gift-widget-{{ section.id }} .fa-product-details {
    flex: 1;
    min-width: 0;
  }

  #fa-gift-widget-{{ section.id }} .fa-product-title {
    font-family: var(--font-heading-family);
    font-size: 1.125rem;
    font-weight: 700;
    color: var(--fa-product-title-color-{{ section.id }});
    margin: 0 0 6px 0;
    line-height: 1.3;
  }

  #fa-gift-widget-{{ section.id }} .fa-product-description {
    font-family: var(--font-body-family);
    font-size: 0.875rem;
    color: var(--fa-product-description-color-{{ section.id }});
    margin: 0 0 12px 0;
    line-height: 1.5;
    opacity: 0.9;
  }

  #fa-gift-widget-{{ section.id }} .fa-product-price {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
  }

  #fa-gift-widget-{{ section.id }} .fa-original-price {
    font-family: var(--font-body-family);
    font-size: 0.9375rem;
    color: var(--fa-price-color-{{ section.id }});
    text-decoration: line-through;
    opacity: 0.8;
    font-weight: 500;
  }

  #fa-gift-widget-{{ section.id }} .fa-free-label {
    font-family: var(--font-heading-family);
    background: linear-gradient(to right, var(--fa-free-bg-{{ section.id }}), color-mix(in srgb, var(--fa-free-bg-{{ section.id }}) 80%, black));
    color: var(--fa-free-text-{{ section.id }});
    padding: 4px 10px;
    border-radius: 6px;
    font-size: 0.875rem;
    font-weight: 800;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    animation: faBounce 2s infinite;
  }

  #fa-gift-widget-{{ section.id }} .fa-product-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  #fa-gift-widget-{{ section.id }} .fa-add-gift-btn {
    font-family: var(--font-heading-family);
    background: linear-gradient(to right, var(--fa-btn-bg-{{ section.id }}), color-mix(in srgb, var(--fa-btn-bg-{{ section.id }}) 90%, black));
    color: var(--fa-btn-text-{{ section.id }});
    border: none;
    border-radius: 8px;
    padding: 12px 20px;
    font-size: 0.9375rem;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.3s ease;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    position: relative;
    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
    overflow: hidden;
  }

  #fa-gift-widget-{{ section.id }} .fa-add-gift-btn::before {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
    transition: 0.5s;
  }

  #fa-gift-widget-{{ section.id }} .fa-add-gift-btn:hover:not(:disabled) {
    background: linear-gradient(to right, var(--fa-btn-hover-{{ section.id }}), color-mix(in srgb, var(--fa-btn-hover-{{ section.id }}) 90%, black));
    transform: translateY(-2px);
    box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2), 0 4px 6px -2px rgba(0, 0, 0, 0.1);
  }

  #fa-gift-widget-{{ section.id }} .fa-add-gift-btn:hover::before {
    left: 100%;
  }

  #fa-gift-widget-{{ section.id }} .fa-add-gift-btn:active {
    transform: translateY(0);
    box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.1);
  }

  #fa-gift-widget-{{ section.id }} .fa-add-gift-btn:disabled {
    opacity: 0.7;
    cursor: not-allowed;
    transform: none;
  }

  #fa-gift-widget-{{ section.id }} .fa-add-gift-btn:focus {
    outline: 2px solid var(--fa-icon-inner-{{ section.id }});
    outline-offset: 2px;
  }

  #fa-gift-widget-{{ section.id }} .fa-already-added {
    font-family: var(--font-body-family);
    font-size: 0.9375rem;
    color: var(--fa-free-bg-{{ section.id }});
    font-weight: 600;
    margin: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 0;
  }

  #fa-gift-widget-{{ section.id }} .fa-gift-footer {
    padding-top: 8px;
  }

  #fa-gift-widget-{{ section.id }} .fa-progress-container {
    width: 100%;
  }

  #fa-gift-widget-{{ section.id }} .fa-progress-label {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
  }

  #fa-gift-widget-{{ section.id }} .fa-progress-text {
    font-family: var(--font-body-family);
    font-size: 0.875rem;
    color: var(--fa-progress-text-{{ section.id }});
    font-weight: 500;
  }

  #fa-gift-widget-{{ section.id }} .fa-progress-amount {
    font-family: var(--font-heading-family);
    font-size: 0.875rem;
    color: var(--fa-progress-text-{{ section.id }});
    font-weight: 700;
  }

  #fa-gift-widget-{{ section.id }} .fa-progress-bar {
    height: 8px;
    background-color: var(--fa-progress-bg-{{ section.id }});
    border-radius: 4px;
    overflow: hidden;
  }

  #fa-gift-widget-{{ section.id }} .fa-progress-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--fa-progress-fill-{{ section.id }}), color-mix(in srgb, var(--fa-progress-fill-{{ section.id }}) 80%, white));
    border-radius: 4px;
    transition: width 0.8s cubic-bezier(0.22, 0.61, 0.36, 1);
    position: relative;
    overflow: hidden;
  }

  #fa-gift-widget-{{ section.id }} .fa-progress-fill::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 20px;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
    animation: faProgressShine 2s infinite;
  }

  /* Animation for widget entrance */
  @keyframes faSlideIn {
    from {
      opacity: 0;
      transform: translateY(10px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  /* Icon rolling animation */
  @keyframes faIconRoll {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }

  /* Image shake animation */
  @keyframes faImageShake {
    0%, 100% {
      transform: translateX(0) translateY(0);
    }
    25% {
      transform: translateX(-2px) translateY(2px);
    }
    50% {
      transform: translateX(2px) translateY(-2px);
    }
    75% {
      transform: translateX(-1px) translateY(1px);
    }
  }

  /* Image zoom animation */
  @keyframes faImageZoom {
    0%, 100% {
      transform: scale(1);
    }
    50% {
      transform: scale(1.03);
    }
  }

  /* Pulse animation for gift badge */
  @keyframes faPulse {
    0%, 100% {
      transform: scale(1);
      opacity: 1;
    }
    50% {
      transform: scale(1.1);
      opacity: 0.8;
    }
  }

  /* Bounce animation for free label */
  @keyframes faBounce {
    0%, 20%, 50%, 80%, 100% {
      transform: translateY(0);
    }
    40% {
      transform: translateY(-5px);
    }
    60% {
      transform: translateY(-3px);
    }
  }

  /* Progress bar pulse animation */
  @keyframes faProgressPulse {
    0%, 100% {
      opacity: 1;
    }
    50% {
      opacity: 0.7;
    }
  }

  /* Progress bar shine animation */
  @keyframes faProgressShine {
    0% {
      left: -20px;
    }
    100% {
      left: calc(100% + 20px);
    }
  }

  #fa-gift-widget-{{ section.id }}[style*="block"] .fa-gift-card {
    animation: faSlideIn 0.5s ease forwards;
  }

  @media (max-width: 768px) {
    #fa-gift-widget-{{ section.id }} {
      margin: 20px 0;
    }
    
    #fa-gift-widget-{{ section.id }} .fa-gift-card {
      padding: 20px;
      gap: 16px;
    }
    
    #fa-gift-widget-{{ section.id }} .fa-gift-header {
      gap: 12px;
    }
    
    #fa-gift-widget-{{ section.id }} .fa-gift-icon {
      width: 44px;
      height: 44px;
    }
    
    #fa-gift-widget-{{ section.id }} .fa-gift-title {
      font-size: 1.25rem;
    }
    
    #fa-gift-widget-{{ section.id }} .fa-gift-body {
      padding: 16px 0;
    }
    
    #fa-gift-widget-{{ section.id }} .fa-gift-product {
      flex-direction: column;
      align-items: flex-start;
      gap: 16px;
    }

    #fa-gift-widget-{{ section.id }} .fa-product-image {
      width: 80px;
      height: 80px;
    }

    #fa-gift-widget-{{ section.id }} .fa-product-details {
      width: 100%;
    }

    #fa-gift-widget-{{ section.id }} .fa-add-gift-btn {
      width: 100%;
      justify-content: center;
    }
    
    #fa-gift-widget-{{ section.id }} .fa-progress-label {
      flex-direction: column;
      align-items: flex-start;
      gap: 4px;
    }
  }
</style>

<script>
  document.addEventListener('DOMContentLoaded', function() {
    const widget = document.getElementById('fa-gift-widget-{{ section.id }}');
    if (!widget) return;
    
    const threshold = {{ section.settings.cart_threshold }};
    const addButton = document.getElementById('fa-add-gift-{{ section.id }}');
    const closeButton = widget.querySelector('.fa-gift-close');
    const alreadyAddedText = widget.querySelector('.fa-already-added');
    const progressFill = widget.querySelector('.fa-progress-fill');
    const progressText = widget.querySelector('.fa-progress-text');
    const progressAmount = widget.querySelector('.fa-progress-amount');
    
    // Close widget functionality
    if (closeButton) {
      closeButton.addEventListener('click', function() {
        widget.style.display = 'none';
        // Store dismissal in session storage
        sessionStorage.setItem('faGiftWidgetDismissed', 'true');
      });
    }
    
    function addGiftToCart(variantId, productId, quantity, giftThreshold) {
      const button = addButton;
      const btnText = button.querySelector('.fa-btn-text');
      const btnLoading = button.querySelector('.fa-btn-loading');
      const btnSuccess = button.querySelector('.fa-btn-success');
      
      button.disabled = true;
      btnText.style.display = 'none';
      btnLoading.style.display = 'block';
      
      const formData = new FormData();
      formData.append('id', variantId);
      formData.append('quantity', quantity);
      formData.append('properties[_gift]', 'true');
      formData.append('properties[_gift_threshold]', giftThreshold);
      formData.append('properties[_gift_product_id]', productId);
      
      fetch('/cart/add.js', {
        method: 'POST',
        body: formData
      })
      .then(response => response.json())
      .then(data => {
        btnLoading.style.display = 'none';
        btnSuccess.style.display = 'block';
        
        // Dispatch custom event for other components
        document.dispatchEvent(new CustomEvent('fa:gift-added', {
          detail: { productId, variantId }
        }));
        
        setTimeout(() => {
          button.style.display = 'none';
          alreadyAddedText.style.display = 'flex';
          updateCartAndRefresh();
        }, 1500);
      })
      .catch(error => {
        console.error('Error adding gift to cart:', error);
        button.disabled = false;
        btnLoading.style.display = 'none';
        btnText.style.display = 'block';
        btnText.textContent = 'Try Again';
      });
    }
    
    function updateCartAndRefresh() {
      // Update cart count without full page reload if possible
      if (typeof Shopify === 'object' && Shopify.updateCartInfo) {
        Shopify.updateCartInfo(function(cart) {
          document.dispatchEvent(new CustomEvent('cart:updated', {
            detail: { cart }
          }));
        });
      } else {
        // Fallback to full reload after a short delay
        setTimeout(() => {
          window.location.reload();
        }, 2000);
      }
    }
    
    function checkGiftInCart(productId) {
      return fetch('/cart.js')
        .then(response => response.json())
        .then(cart => {
          const hasGift = cart.items.some(item => 
            item.properties && 
            item.properties._gift === 'true' && 
            item.properties._gift_product_id === productId.toString()
          );
          return hasGift;
        })
        .catch(() => false);
    }
    
    function updateProgressBar(cartTotal) {
      if (!progressFill || !progressText || !progressAmount) return;
      
      const progressPercent = Math.min(100, (cartTotal / threshold) * 100);
      progressFill.style.width = `${progressPercent}%`;
      
      progressText.textContent = progressPercent >= 100 ? 
        'You qualified for a free gift!' : 
        `You're ${Math.round(progressPercent)}% to your free gift`;
        
      progressAmount.textContent = `${Shopify.formatMoney(cartTotal)} / ${Shopify.formatMoney(threshold)}`;
    }
    
    function updateWidgetVisibility(cartTotal) {
      if (!widget) return;
      
      // Check if user dismissed the widget
      const isDismissed = sessionStorage.getItem('faGiftWidgetDismissed');
      if (isDismissed === 'true') {
        widget.style.display = 'none';
        return;
      }
      
      fetch('/cart.js')
        .then(response => response.json())
        .then(cart => {
          const shouldShow = cart.item_count > 0 && cartTotal >= threshold;
          
          if (shouldShow) {
            const productId = addButton?.getAttribute('data-product-id');
            if (productId) {
              checkGiftInCart(productId).then(hasGift => {
                if (hasGift) {
                  addButton.style.display = 'none';
                  alreadyAddedText.style.display = 'flex';
                } else {
                  addButton.style.display = 'flex';
                  alreadyAddedText.style.display = 'none';
                }
                widget.style.display = 'block';
                updateProgressBar(cartTotal);
              });
            } else {
              widget.style.display = 'block';
              updateProgressBar(cartTotal);
            }
          } else {
            widget.style.display = 'none';
          }
        })
        .catch(() => {
          const shouldShow = cartTotal >= threshold;
          widget.style.display = shouldShow ? 'block' : 'none';
          if (shouldShow) updateProgressBar(cartTotal);
        });
    }
    
    if (addButton) {
      addButton.addEventListener('click', function() {
        const variantId = this.getAttribute('data-variant-id');
        const productId = this.getAttribute('data-product-id');
        const quantity = this.getAttribute('data-quantity');
        const giftThreshold = this.getAttribute('data-threshold');
        
        addGiftToCart(variantId, productId, quantity, giftThreshold);
      });
    }
    
    // Listen for cart updates
    document.addEventListener('cart:updated', function(event) {
      if (event.detail && event.detail.cart && event.detail.cart.total_price !== undefined) {
        updateWidgetVisibility(event.detail.cart.total_price);
      }
    });
    
    const cartUpdateEvents = ['cart:refresh', 'cart:change', 'cart:build', 'fa:gift-added'];
    cartUpdateEvents.forEach(eventName => {
      document.addEventListener(eventName, function(event) {
        if (event.detail && event.detail.cart && event.detail.cart.total_price !== undefined) {
          updateWidgetVisibility(event.detail.cart.total_price);
        }
      });
    });
    
    // Initialize widget
    let pollCount = 0;
    const maxPolls = 5;
    const pollInterval = setInterval(() => {
      fetch('/cart.js')
        .then(response => response.json())
        .then(cart => {
          updateWidgetVisibility(cart.total_price);
          pollCount++;
          if (pollCount >= maxPolls) {
            clearInterval(pollInterval);
          }
        })
        .catch(() => {
          pollCount++;
          if (pollCount >= maxPolls) {
            clearInterval(pollInterval);
          }
        });
    }, 500);
  });
</script>

{% schema %}
{
  "name": "Premium Free Gift Widget",
  "tag": "section",
  "class": "section",
  "settings": [
    {
      "type": "header",
      "content": "Author Information"
    },
    {
      "type": "paragraph",
      "content": "Designed and developed by Foysal Ahmed for eCommerce Thesis"
    },
    {
      "type": "header",
      "content": "Widget Settings"
    },
    {
      "type": "checkbox",
      "id": "enable_widget",
      "label": "Enable free gift widget",
      "default": true
    },
    {
      "type": "number",
      "id": "cart_threshold",
      "label": "Cart minimum amount (in cents)",
      "info": "Widget appears when cart total reaches this amount. Example: 10000 = $100",
      "default": 10000
    },
    {
      "type": "header",
      "content": "Gift Product Settings"
    },
    {
      "type": "product",
      "id": "gift_product",
      "label": "Select gift product"
    },
    {
      "type": "number",
      "id": "gift_quantity",
      "label": "Gift quantity",
      "default": 1,
      "info": "Number of gift items to add to cart"
    },
    {
      "type": "number",
      "id": "display_price",
      "label": "Display price (in cents)",
      "info": "Price to show crossed out next to FREE (e.g., 2999 for $29.99)",
      "default": 2999
    },
    {
      "type": "header",
      "content": "Content Settings"
    },
    {
      "type": "text",
      "id": "main_title",
      "label": "Main title",
      "default": "Free Gift with Your Order!"
    },
    {
      "type": "text",
      "id": "subtitle",
      "label": "Subtitle",
      "default": "You've qualified for a complimentary gift"
    },
    {
      "type": "text",
      "id": "button_text",
      "label": "Add gift button text",
      "default": "Add Free Gift"
    },
    {
      "type": "text",
      "id": "already_added_text",
      "label": "Already added message",
      "default": "Gift already added to cart"
    },
    {
      "type": "header",
      "content": "Color Settings"
    },
    {
      "type": "color",
      "id": "card_background_color",
      "label": "Card background",
      "default": "#3B82F6"
    },
    {
      "type": "color",
      "id": "card_border_color",
      "label": "Card border",
      "default": "#2563EB"
    },
    {
      "type": "color",
      "id": "icon_background_color",
      "label": "Icon background",
      "default": "#F59E0B"
    },
    {
      "type": "color",
      "id": "icon_inner_color",
      "label": "Icon star color",
      "default": "#FFFFFF"
    },
    {
      "type": "color",
      "id": "title_color",
      "label": "Title color",
      "default": "#FFFFFF"
    },
    {
      "type": "color",
      "id": "subtitle_color",
      "label": "Subtitle color",
      "default": "#E0F2FE"
    },
    {
      "type": "color",
      "id": "product_title_color",
      "label": "Product title color",
      "default": "#FFFFFF"
    },
    {
      "type": "color",
      "id": "product_description_color",
      "label": "Product description color",
      "default": "#E0F2FE"
    },
    {
      "type": "color",
      "id": "price_color",
      "label": "Original price color",
      "default": "#E0F2FE"
    },
    {
      "type": "color",
      "id": "free_label_background",
      "label": "FREE label background",
      "default": "#F59E0B"
    },
    {
      "type": "color",
      "id": "free_label_text",
      "label": "FREE label text",
      "default": "#1E40AF"
    },
    {
      "type": "color",
      "id": "button_background",
      "label": "Button background",
      "default": "#FFFFFF"
    },
    {
      "type": "color",
      "id": "button_text_color",
      "label": "Button text color",
      "default": "#3B82F6"
    },
    {
      "type": "color",
      "id": "button_hover_color",
      "label": "Button hover background",
      "default": "#F3F4F6"
    },
    {
      "type": "color",
      "id": "progress_background",
      "label": "Progress bar background",
      "default": "rgba(255, 255, 255, 0.2)"
    },
    {
      "type": "color",
      "id": "progress_fill",
      "label": "Progress bar fill",
      "default": "#F59E0B"
    },
    {
      "type": "color",
      "id": "progress_text_color",
      "label": "Progress text color",
      "default": "#FFFFFF"
    }
  ],
  "presets": [
    {
      "name": "Premium Free Gift Widget",
      "category": "Cart"
    }
  ]
}
{% endschema %}