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
The script monitors the cart for changes
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
If conditions are met, the popup appears
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!
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.
Add this code and customize.
Enjoy!

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() {
const promoSettings = {
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:
let hasDeclinedOffer = false;
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 closePopup() {
hasDeclinedOffer = true;
document.getElementById('promoPopup').style.display = 'none';
document.getElementById('popupOverlay').style.display = 'none';
}
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:
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';
});
});
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:
Change the triggerProduct.title
to match your main product's exact title
Update the freeGift
settings with your gift product's details:
title
: Exact product title
handle
: Product handle from URL: shopifystore.com/products/FREE-GIFT
Customize the popup appearance in the popup
settings:
Modify text content
Adjust colors to match your brand
Update button text