# 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:

```html
<!-- 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

```css
/* 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

```javascript
// 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

```javascript
// 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();
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.shoplift.ai/test/javascript-api/code-examples/mini-cart-test.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
