How to Create a Customizable Promotional Popup for Shopify

Jan 9, 2025

This guide will walk you through implementing a customizable promotional popup that appears when customers add specific products to their cart. Perfect for offering free gifts, upsells, or special promotions! I've broken the code into sections, you could however download all the code and throw it straight in there without a care in the world. However, having a basic understanding of what each part of the code means is going to help massively.

How It Works

  1. The script monitors the cart for changes

  2. When the trigger product is added, it checks if:
    - The free gift isn't already in the cart
    - The user hasn't previously declined the offer

  3. If conditions are met, the popup appears

  4. Users can either:
    - Add the free gift (redirects to cart)
    - Decline the offer (popup won't appear again in this session)

Features

✨ Fully customizable appearance
🎯 Targeted product promotion
🔄 Single-session decline memory
📱 Responsive design
🎁 Automatic free gift addition

How to automatically add a free product to cart with a single purchase?

Shopify just loves to have you reliant on apps! The problem with apps is they cost money and will most likely slow your site down as well. Not good. Shopify's Buy X Get Y is a great discount, but it requires the customer to go and add their free gift, resulting in more clicks and increasing potential drop-off.

One solution is to utilize a pop-up that appears once the trigger product has been added. So today's your lucky day boys and gals, cos we're gonna do just that!

  1. Create an automatic Buy X get Y discount code in Shopify. This way the discount will automatically apply when the item is added to the cart.

  2. Add this code and customize.

  3. Enjoy!

Step 1: Grab Your Code

Download your FREE Logo Ticker code…you're welcome!

Step 2: Initial Setup

First, locate your theme's theme.liquid file in your Shopify theme editor. Add the following configurable settings at the bottom of the page right before </body>

<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Configurable settings
    const promoSettings = {
      // Main product that triggers the popup
      triggerProduct: {
        title: "TRIGGER PRODUCT",  // Change this to your main product title
      },
      // Free gift product details
      freeGift: {
        title: "FREE GIFT",         // Change this to your free gift title
        handle: "FREE-GIFT",         // Change this to your free gift product handle
      },
      // Popup content
      popup: {
        heading

Step 3: Create the Popup HTML

The pop-up structure uses dynamic styling based on your settings:

    // Add flag to track if user has declined the offer
    let hasDeclinedOffer = false;

    // Create popup HTML using settings
    const popupHTML = `
      <div id="promoPopup" style="display:none; position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); background:${promoSettings.popup.backgroundColor}; padding:20px; border-radius:8px; box-shadow:0 0 10px rgba(0,0,0,0.2); z-index:1000;">
        <h3 style="color:${promoSettings.popup.textColor}">${promoSettings.popup.heading}</h3>
        <p style="color:${promoSettings.popup.textColor}">${promoSettings.popup.description}</p>
        <button id="addFreeGift" style="background:${promoSettings.popup.addButtonColor}; color:${promoSettings.popup.addButtonTextColor}; padding:10px 20px; border:none; border-radius:4px; cursor:pointer; margin-right:10px;">${promoSettings.popup.addButtonText}</button>
        <button id="skipPromo" style="background:${promoSettings.popup.backgroundColor}; color:${promoSettings.popup.textColor}; padding:10px 20px; border:1px solid ${promoSettings.popup.skipButtonBorderColor}; border-radius:4px; cursor:pointer;">${promoSettings.popup.skipButtonText}</button>
      </div>
      <div id="popupOverlay" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:999;"></div>
    `;
    document.body.insertAdjacentHTML('beforeend', popupHTML);

Step 4: Add Cart Monitoring

This code watches for changes in the cart and shows the popup when appropriate:

 // Function to close popup
    function closePopup() {
      hasDeclinedOffer = true;
      document.getElementById('promoPopup').style.display = 'none';
      document.getElementById('popupOverlay').style.display = 'none';
    }

    // Show popup when trigger product is added
    const cartObserver = new MutationObserver(() => {
      fetch('/cart.js')
        .then(res => res.json())
        .then(cart => {
          let hasTriggerProduct = cart.items.some(item => 
            item.product_title === promoSettings.triggerProduct.title
          );
          let hasFreeGift = cart.items.some(item => 
            item.product_title === promoSettings.freeGift.title
          );
          
          if (hasTriggerProduct && !hasFreeGift && !hasDeclinedOffer) {
            document.getElementById('promoPopup').style.display = 'block';
            document.getElementById('popupOverlay').style.display = 'block';
          }
        });
    });

Step 5: Handle the Free Gift Addition

Add this code to handle adding the free gift to cart:

 // Add free gift when button clicked and redirect to cart
    document.getElementById('addFreeGift').addEventListener('click', function() {
      fetch(`/products/${promoSettings.freeGift.handle}.js`)
        .then(res => res.json())
        .then(product => {
          let variantId = product.variants[0].id;
          return fetch('/cart/add.js', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
              items: [{
                id: variantId,
                quantity: 1
              }]
            })
          });
        })
        .then(() => {
          window.location.href = '/cart';
        });
    });

    // Add close functionality
    document.getElementById('skipPromo').addEventListener('click', closePopup);
    document.getElementById('popupOverlay').addEventListener('click', closePopup);

    cartObserver.observe(document.body, {
      subtree: true,
      childList: true
    });
  });
<

Step 6: Customize for Your Store

To adapt this code for your store:

  1. Change the triggerProduct.title to match your main product's exact title

  2. Update the freeGift settings with your gift product's details:

    • title: Exact product title

    • handle: Product handle from URL: shopifystore.com/products/FREE-GIFT

  3. Customize the popup appearance in the popup settings:

    • Modify text content

    • Adjust colors to match your brand

    • Update button text