Skip to content

Instantly share code, notes, and snippets.

@elghorfi
Last active June 4, 2025 17:10
Show Gist options
  • Save elghorfi/c916d63cac0a42bb61a557086d26fa07 to your computer and use it in GitHub Desktop.
Save elghorfi/c916d63cac0a42bb61a557086d26fa07 to your computer and use it in GitHub Desktop.
{% layout none%}
{% assign applied_discounts = cart.discount_applications | where: "type", "discount_code" %}
{% capture discounts %}
{% for discount_application in applied_discounts %}
{
"title" : "{{ discount_application.title }}",
"value" : "{{ discount_application.value }}",
"value_type": "{{ discount_application.value_type }}",
"type": "{{ discount_application.type }}",
"amount" : "{{ discount_application.total_allocated_amount | money }}",
"target_type": "{{ discount_application.target_type }}"
}
{% endfor %}
{% endcapture %}
{
"discounts": [{{ discounts }}],
"total_price": "{{ cart.total_price }}",
"total_price_with_currency": "{{ cart.total_price | money }}"
}
{%comment%}
#############################################
# Mohamed El-Ghorfi Discount Code on Cart #
# [Simplified Version] #
#############################################
# Paypal Me: https://paypal.me/elghorfimed #
# Buy Me A Coffee: #
# https://www.buymeacoffee.com/elghorfi #
# My Links: #
# https://linktr.ee/elghorfi #
#############################################
# [email protected] #
#############################################
{%endcomment%}
<style>
:root {
--primary_color: {{ section.settings.color }};
--btn_text_color: {{ section.settings.btn_text_color }};
--bg_color: {{ section.settings.bg_color }};
--input_bg_color: {{ section.settings.input_bg_color }};
--input_text_color: {{ section.settings.input_text_color }};
--margin: {{ section.settings.margin }}px;
--padding: {{ section.settings.padding }}px;
}
.cart-sidebar-discount {
display: grid;
grid-template-columns: 1fr auto;
width: fit-content;
margin: var(--margin);
padding: var(--padding);
background: var(--bg_color);
}
#applied-discount-code small {
grid-column-start: 1;
grid-column-end: 3;
}
#applied-discount-code {
grid-column-start: 1;
grid-column-end: 3;
}
.cart-sidebar-discount input {
margin-top: 15px;
background: var(--input_bg_color);
color: var(--input_text_color);
border: 1px solid var(--input_bg_color);
height: 45px;
outline: none;
font-size: 16px;
letter-spacing: .75px;
text-align: center;
}
.cart-sidebar-discount input:focus {
border: 1px solid var(--input_bg_color);
}
#apply-discount-btn {
background-color: var(--primary_color);
color: var(--btn_text_color);
margin-top: 15px;
border: 0;
height: 45px;
width: 100%;
font-size: 16px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: .75px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 15px;
}
#apply-discount-btn:hover {
opacity: .7;
}
.applied-discount-code-value > small {
background: var(--input_bg_color);
padding: 0 10px;
color: var(--primary_color);
font-weight: bold;
border-radius: 20px;
}
.loader {
border: 5px solid #f3f3f3;
border-top: 4px solid var(--primary_color);
border-radius: 50%;
width: 25px;
height: 25px;
animation: spin .5s linear infinite;
}
#discount-code-error {
background: #ff00004f;
color: #e22120;
padding: 5px;
border-radius: 4px;
font-size: 13px;
line-height: 1;
grid-column-start: 1;
grid-column-end: 3;
}
.applied-discount-code-wrapper {
display: none;
align-items: center;
margin: 4px 0;
width: fit-content;
line-height: 1;
}
#clear-discount-btn {
padding: 2px;
margin: 0 2px;
}
#clear-discount-btn:hover {
cursor: pointer;
color: var(--primary_color);
}
#discount-code-error:empty,
.applied-discount-code-value:empty + button {
display: none;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
<div class="cart-sidebar-discount">
<span id="applied-discount-code">
{{ section.settings.descriptive_text }}
<span class="applied-discount-code-wrapper"{% if content_for_header contains "Shopify.designMode" %}style="display: flex" {% endif %}>
<span class="applied-discount-code-value">{% if content_for_header contains "Shopify.designMode" %}Preview ($10){% endif %}</span>
<span id="clear-discount-btn">X</span>
</span>
</span>
<small id="discount-code-error">{% if content_for_header contains "Shopify.designMode" %}Preview: {{ section.settings.invalid_discount_error }}{% endif %}</small>
<input type="text" id="discount-code-input" placeholder="{{ section.settings.input_placeholder }}" autocomplete="on" value="">
<button id="apply-discount-btn">{{ section.settings.button_text }}</button>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
let clearBtn = document.querySelector("#clear-discount-btn");
let applyBtn = document.querySelector("#apply-discount-btn");
let discountCodeError = document.querySelector("#discount-code-error");
let discountCodeWrapper = document.querySelector("#applied-discount-code .applied-discount-code-wrapper");
let discountCodeValue = document.querySelector("#applied-discount-code .applied-discount-code-value");
let discountCodeInput = document.querySelector("#discount-code-input");
let totalCartSelector = document.querySelector(".cart__subtotal .money"); // Total Cart Selector to update the total amount.
if (localStorage.discountCode) applyDiscountCode( JSON.parse(localStorage.discountCode).code);
if(applyBtn)
applyBtn.addEventListener("click", function(e){
e.preventDefault()
if(discountCodeInput.value !== '') {
applyDiscountCode(discountCodeInput.value)
discountCodeInput.style.border = 'unset'
}else{
discountCodeInput.style.border = '1px solid red'
}
});
if(clearBtn)
clearBtn.addEventListener("click", function(e){
e.preventDefault()
clearDiscount();
});
function clearDiscount() {
discountCodeValue.innerHTML = "";
discountCodeError.innerHTML = "";
clearLocalStorage();
fetch("/checkout?discount=%20");
}
function clearLocalStorage() {
if(discountCodeWrapper) discountCodeWrapper.style.display = "none";
if(totalCartSelector) totalCartSelector.innerHTML = JSON.parse(localStorage.discountCode).totalCart;
localStorage.removeItem("discountCode");
}
function applyDiscountCode(code) {
applyBtn.innerHTML = "{{ section.settings.progress_button_text }} <div class='loader'></div>";
applyBtn.style.pointerEvents = "none";
console.clear()
console.log('code', code)
fetch(`/discount/${code}`).then(()=> {
fetch('/cart?view=discount', {}).then(function(res){return res.text();})
.then(function(data) {
let dataObject = JSON.parse(JSON.stringify(data))
dataObject = JSON.parse(dataObject)
const appliedCodes = data.discounts.map(i => i.title.trim().toLowerCase());
if (appliedCodes.includes(code.trim().toLowerCase())) {
if(discountCodeWrapper) discountCodeWrapper.style.display = "inline-flex";
if(discountCodeError) discountCodeError.innerHTML = "";
if(discountCodeValue) discountCodeValue.innerHTML = dataObject.discounts[0].title + " (" + dataObject.discounts[0].amount + ")";
let localStorageValue = {
'code': code.trim(),
'totalCart': dataObject.total_price_with_currency
};
localStorage.setItem("discountCode", JSON.stringify(localStorageValue));
if(totalCartSelector) totalCartSelector.innerHTML = dataObject.total_price;
}else {
if(discountCodeValue) discountCodeValue.innerHTML = "";
clearLocalStorage();
if(discountCodeError) discountCodeError.innerHTML = "{{ section.settings.invalid_discount_error }}"
}
})
.finally(function() {
if(applyBtn){
applyBtn.innerHTML = "{{ section.settings.button_text }}";
applyBtn.style.pointerEvents = "all";
}
});
})
}
});
</script>
{% schema %}
{
"name": "Discount Field By Mohamed",
"settings": [
{
"type": "range",
"id": "padding",
"min": 0,
"max": 50,
"step": 1,
"unit": "px",
"label": "Padding:",
"default": 10
},
{
"type": "range",
"id": "margin",
"min": 0,
"max": 50,
"step": 1,
"unit": "px",
"label": "Margins:",
"default": 20
},
{
"type": "select",
"id": "items_align",
"label": "Align Items",
"default": "default",
"options": [
{
"label": "Center",
"value": "center"
},
{
"label": "Left",
"value": "left"
},
{
"label": "Right",
"value": "right"
},
{
"label": "Default",
"value": "default"
}
]
},
{
"type": "header",
"content": "Content"
},
{
"type": "text",
"id": "descriptive_text",
"label": "Descriptive Text",
"default": "Apply A Discount Code!"
},
{
"type": "text",
"id": "input_placeholder",
"label": "Input Placeholder"
},
{
"type": "text",
"id": "button_text",
"label": "Button Text",
"default": "APPLY"
},
{
"type": "text",
"id": "progress_button_text",
"label": "Progress Button Text",
"default": "APPLYING",
"info": "Text showing on applying the discount"
},
{
"type": "text",
"id": "invalid_discount_error",
"label": "Invalid Discount Error",
"default": "Please Enter Valid Coupon Code."
},
{
"type": "header",
"content": "Colors"
},
{
"type": "color",
"id": "bg_color",
"label": "background Color",
"default": "#ddd"
},
{
"type": "color",
"id": "color",
"label": "Button Color",
"default": "#f38a01"
},
{
"type": "color",
"id": "btn_text_color",
"label": "Button Text Color",
"default": "#fff"
},
{
"type": "color",
"id": "input_bg_color",
"label": "Input Background Color",
"default": "#eee"
},
{
"type": "color",
"id": "input_text_color",
"label": "Input Text Color",
"default": "#000"
}
],
"presets": [
{
"name": "Discount Field By Mohamed"
}
]
}
{% endschema %}
@Coru89
Copy link

Coru89 commented May 6, 2025

I tried to implement this in the cart drawer and not the cart page--but pherhaps this is not possible. When I made the call to /cart?view=discount , the data returned seems to be the entire html document:

image

Then I get this error on json parse:

image

Any ideas?

@elghorfi
Copy link
Author

elghorfi commented May 6, 2025

I tried to implement this in the cart drawer and not the cart page--but pherhaps this is not possible. When I made the call to /cart?view=discount , the data returned seems to be the entire html document:

image

Then I get this error on json parse:

image

Any ideas?

Thank you @Coru89 For sharing, can you share with me a preview link for the theme you set it on so I can check?

@Coru89
Copy link

Coru89 commented May 6, 2025

of course! thanks so much for looking! @elghorfi

https://trsp28beo0t1gssm-82564219224.shopifypreview.com/

the code input doesnt show in the cart drawer until an item gets added to the cart

@Coru89
Copy link

Coru89 commented May 6, 2025

@elghorfi forgot to mention, you can use the test codes:

test_cmd
test_prod

These do get applied, after you force a refresh, but the code is erroring out still. =)

@lasmann
Copy link

lasmann commented May 8, 2025

@elghorfi this is an amazing solution — thanks so much! The only issue I found is that the discount code check is case-sensitive.

To fix it, you can replace the following lines:

const appliedCodes = data.discounts.map(i => i.title);
if (appliedCodes.includes(code)) {

with

const appliedCodes = data.discounts.map(i => i.title.trim().toLowerCase());
if (appliedCodes.includes(code.trim().toLowerCase())) {

@Coru89
Copy link

Coru89 commented May 9, 2025

Just wanted to follow up and say thank you. I got this working! I didn't understand the intention behind the cart.discount.liquid file. I never seen this approach of creating your own end-point to call like this. Very clever.

@elghorfi
Copy link
Author

elghorfi commented May 9, 2025

@elghorfi this is an amazing solution — thanks so much! The only issue I found is that the discount code check is case-sensitive.

To fix it, you can replace the following lines:

const appliedCodes = data.discounts.map(i => i.title);
if (appliedCodes.includes(code)) {

with

const appliedCodes = data.discounts.map(i => i.title.trim().toLowerCase());
if (appliedCodes.includes(code.trim().toLowerCase())) {

Thank you for the suggestion, I will update it.

@elghorfi
Copy link
Author

elghorfi commented May 9, 2025

Just wanted to follow up and say thank you. I got this working! I didn't understand the intention behind the cart.discount.liquid file. I never seen this approach of creating your own end-point to call like this. Very clever.

Hey @Coru89,

Thank you for the update, glad it worked for you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment