Mini-Cart Test

This example demonstrates how to test showing or hiding a specific element (like a free shipping message) in your mini cart. Visitors only enter the test when they interact with the cart.

What We're Testing

  • Control: Standard mini cart without promotional message

  • Variant: Mini cart with free shipping progress bar

Step 1: Create Your Test in Shoplift

  1. Navigate to Tests → Create New Test

  2. Select "JavaScript API" as the test type

  3. Choose Manual trigger (only assigns users who open cart)

  4. Create your hypothesis and copy the ID

Step 2: Add HTML Structure

Add the test element to your mini cart, hidden by default:

<!-- In your mini cart template -->
<div class="mini-cart">
  <div class="cart-header">
    <h3>Your Cart</h3>
    <button class="close-cart">×</button>
  </div>
  
  <!-- Free shipping element - hidden by default -->
  <div class="free-shipping-progress" style="display: none; opacity: 0;">
    <div class="shipping-message">
      <span class="shipping-icon">🚚</span>
      <span class="shipping-text">You're $<span class="amount-remaining">50</span> away from free shipping!</span>
    </div>
    <div class="progress-bar">
      <div class="progress-fill" style="width: 0%"></div>
    </div>
  </div>
  
  <div class="cart-items">
    <!-- Cart items here -->
  </div>
  
  <div class="cart-footer">
    <!-- Checkout button etc -->
  </div>
</div>

Step 3: Add CSS for Smooth Transitions

/* Prevent flicker with transitions */
.free-shipping-progress {
  transition: opacity 0.3s ease;
  padding: 15px;
  background: #f0f8ff;
  border-radius: 8px;
  margin: 10px;
}

.free-shipping-progress.show {
  display: block !important;
  opacity: 1 !important;
}

.shipping-message {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  font-size: 14px;
}

.progress-bar {
  width: 100%;
  height: 8px;
  background: #e0e0e0;
  border-radius: 4px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #4CAF50, #45a049);
  transition: width 0.3s ease;
}

Step 4: Implement the Test Logic

// Mini Cart Free Shipping Test
(function() {
  // Configuration
  const HYPOTHESIS_ID = 'your-hypothesis-id-here'; // Replace with your ID
  const FREE_SHIPPING_THRESHOLD = 75; // Free shipping at $75
  
  // Cache the test result
  let variantAssignment = null;
  let cartTotal = 0;
  
  // Initialize test when cart is opened
  async function initCartTest() {
    // Only check once per session
    if (variantAssignment !== null) {
      applyTestResult();
      return;
    }
    
    // Check if Shoplift is available
    if (!window.shoplift) {
      console.warn('Shoplift not available, hiding promotional element');
      variantAssignment = false;
      return;
    }
    
    try {
      // This triggers test assignment on first cart open
      variantAssignment = await window.shoplift.isHypothesisActive(HYPOTHESIS_ID);
      console.log('Mini cart test assigned:', variantAssignment ? 'variant' : 'control');
      
      // Apply the test result
      applyTestResult();
      
    } catch (error) {
      console.error('Mini cart test failed:', error);
      variantAssignment = false; // Default to control (hide element)
    }
  }
  
  // Apply test result to UI
  function applyTestResult() {
    const shippingElement = document.querySelector('.free-shipping-progress');
    if (!shippingElement) return;
    
    if (variantAssignment) {
      // Show free shipping progress (variant)
      updateShippingProgress();
      
      // Add show class with slight delay to ensure smooth transition
      setTimeout(() => {
        shippingElement.classList.add('show');
      }, 10);
      
      // Track interaction if analytics exists
      if (window.analytics) {
        window.analytics.track('Free Shipping Bar Viewed', {
          test_id: 'mini-cart-shipping',
          variant: 'shown'
        });
      }
    } else {
      // Hide free shipping progress (control)
      shippingElement.classList.remove('show');
      
      // After transition, hide completely
      setTimeout(() => {
        if (!variantAssignment) {
          shippingElement.style.display = 'none';
        }
      }, 300);
    }
  }
  
  // Update shipping progress bar
  function updateShippingProgress() {
    const shippingElement = document.querySelector('.free-shipping-progress');
    if (!shippingElement || !variantAssignment) return;
    
    // Get current cart total (you'd get this from your cart data)
    fetchCartTotal().then(total => {
      cartTotal = total;
      
      const remaining = Math.max(0, FREE_SHIPPING_THRESHOLD - cartTotal);
      const progress = Math.min(100, (cartTotal / FREE_SHIPPING_THRESHOLD) * 100);
      
      // Update text
      const textElement = shippingElement.querySelector('.shipping-text');
      if (remaining > 0) {
        textElement.innerHTML = `You're $${remaining.toFixed(2)} away from free shipping!`;
      } else {
        textElement.innerHTML = `🎉 You've qualified for free shipping!`;
      }
      
      // Update progress bar
      const progressFill = shippingElement.querySelector('.progress-fill');
      if (progressFill) {
        progressFill.style.width = `${progress}%`;
      }
      
      // Make sure element is visible
      shippingElement.style.display = 'block';
    });
  }
  
  // Fetch cart total from Shopify
  async function fetchCartTotal() {
    try {
      const response = await fetch('/cart.js');
      const cart = await response.json();
      return cart.total_price / 100; // Convert from cents
    } catch (error) {
      console.error('Failed to fetch cart:', error);
      return 0;
    }
  }
  
  // Set up event listeners
  function setupEventListeners() {
    // Cart open triggers
    const cartTriggers = document.querySelectorAll('.cart-icon, [data-cart-open], a[href="/cart"]');
    
    cartTriggers.forEach(trigger => {
      trigger.addEventListener('click', async (e) => {
        // Prevent default if it's a link
        if (trigger.tagName === 'A') {
          e.preventDefault();
        }
        
        // Initialize test on first interaction
        await initCartTest();
        
        // Open your cart (implement your cart open logic here)
        openCart();
      });
    });
    
    // Listen for cart updates
    document.addEventListener('cart:updated', () => {
      if (variantAssignment) {
        updateShippingProgress();
      }
    });
    
    // Also check if cart is already open on page load
    if (document.querySelector('.mini-cart.active')) {
      initCartTest();
    }
  }
  
  // Your existing cart open function
  function openCart() {
    // Your cart opening logic here
    const cart = document.querySelector('.mini-cart');
    if (cart) {
      cart.classList.add('active');
    }
  }
  
  // Initialize when DOM is ready
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', setupEventListeners);
  } else {
    setupEventListeners();
  }
})(); 

Step 5: Test Your Implementation

1. Force the Variant

https://yourstore.com/?slVariant=your-hypothesis-id

Open the cart - you should see the free shipping message.

2. Test Control

Open in incognito without URL parameters - the message should be hidden.

3. Debug in Console

// Check if test is working
console.log(window.shoplift);

// Manually check assignment
await window.shoplift.isHypothesisActive('your-hypothesis-id');

// Check visitor data
window.shoplift.getVisitorData();

Last updated

Was this helpful?