There are plenty of apps out there that allow you to add promotions to the cart. But your store may not need the overhead, complexity or cost of more apps. If that's the case for you, here's how to implement your own Do-It-Yourself cart promotions.
Implementing these requires you to edit your theme code. The code added uses Liquid, HTML and CSS. But it requires no JavaScript. And this code requires that your theme use a page for the cart. So it doesn't work for mini-carts or pop-up carts.
Here are some examples of promotions that I have added to clients' carts. The code for all of these are provided.
Discount Code Based on Cart Size
In this promotion, you get to set a cart size threshold. Before the threshold is hit, the promotion shows what the customer gets when they hit the threshold, like a 10% off discount code. When they pass the threshold, the message changes to a congratulations message and they can click the button to immediately add the discount code to their order.
Gift Wrapping
This promotion allows the customer to add a gift-wrapping product to their order by clicking a button. This promotion goes away once the Rush Order Processing product is in the cart.
Rush Order Processing
This is a great promotion for companies that take time to process their orders, for example, if they are selling personalized products. This promotion allows the customer to add a rush processing product to their order by clicking a button. This promotion goes away once the Rush Order Processing product is in the cart.
Product Cross-Sell
This promotion allows you to queue up to three product promotions to customers in your cart. When one product is added to the cart by the customer than the promotion shows the second product in the queue. When the second product is added to the cart by the customer than the promotion shows the third product in the queue. When the second product is added to the cart by the customer than the promotion shows the third product in the queue. When the third product is added to the cart by the customer than the promotion doesn't show.
Out of Office Notification
This notification allows you to provide a general message to your customers in the cart. I've seen my clients use this to make customers aware when the office is shut down, like during the holidays, and may affect shipping times. They've also used this to let customers know in Canada when Canada shipping was slowed down due to a strike.
Code Changes
The code edits required for this aren't too complex. If you are comfortable with editing the Liquid code in your theme, then you should be able to this. This code will give you ideas on how to implement DIY Cart Promotions in your theme.
Theme Disclaimer: All of the code provided works well inside the Turbo theme by Out of the Sandbox. If you are using a different theme, you may need to make some edits to get things working as desired.
Here are the files that need to be added/edited:
Cart-Messages.liquid
This is a snippet that I add to the theme. The code here is what drives the promotions to display in the cart. Then I add the following include statement - {% include 'cart-messages' %} - wherever I want the promotions to show on the cart page. You'll add that either in the template 'cart.liquid' or section 'cart-template.liquid'.
<!-- Start Cart Size Discount Section --> | |
{% if settings.cart_size_enable %} | |
{% assign cartamount = cart.total_price %} | |
{% assign threshold = settings.sleepwear_threshold | times:100 %} | |
{% assign cart-remaining = threshold %} | |
{% assign cart-remaining = cart-remaining | minus:cartamount %} | |
{% if cartamount < threshold %} | |
<div class="cart-upsell"> | |
<div class="cart-upsell-row"> | |
<div class="cart-upsell-image"> | |
<img src="https://cdn.shopify.com/s/files/1/0032/9262/7053/{{ settings.under_threshold_image }}"> | |
</div> | |
<div class="cart-upsell-text"> | |
{{ settings.under_threshold_top_text }} | |
<p>You just need to add <strong>{{ cart-remaining | money }} of products</strong> to your cart to receive your discount.</p> | |
<p> | |
<a href="/collections"> | |
<div class="button"><span class="make-rush-order">{{ settings.under_threshold_button }}</span></div> | |
</a> | |
</p> | |
</div> | |
</div> | |
</div> | |
{% else %} | |
<div class="cart-upsell"> | |
<div class="cart-upsell-row"> | |
<div class="cart-upsell-image"> | |
<img src="https://cdn.shopify.com/s/files/1/0032/9262/7053/{{ settings.over_threshold_image }}"> | |
</div> | |
<div class="cart-upsell-text"> | |
{{ settings.over_threshold_top_text }} | |
<p> | |
<a href="https://www.cool-jams.com/discount/{{ settings.threshold_discount_code }}?redirect=/cart"> | |
<div class="button"><span class="make-rush-order">{{ settings.over_threshold_button }}</span></div> | |
</a> | |
</p> | |
{{ settings.over_threshold_bottom_text }} | |
</div> | |
</div> | |
</div> | |
{% endif %} | |
{% endif %} | |
<!-- End Cart Size Discount Section --> | |
<!-- Start Gift Wrap Section --> | |
{% if settings.gift_wrap_enable %} | |
{% unless settings.cart_cross_sell_product_1 == blank %} | |
{% assign upsellg = 0 %} | |
{% assign productg = settings.gift_wrap_product %} | |
{% assign productg-title = all_products[productg].title %} | |
{% assign productg-variant-id = all_products[productg].variants.first.id %} | |
{% for item in cart.items %} | |
{% if item.product.title contains productg-title %} | |
{% assign upsellg = upsellg | plus:1 %} | |
{% endif %} | |
{% endfor %} | |
{% if upsellg == 0 %} | |
<div class="cart-upsell"> | |
<div class="cart-upsell-row"> | |
<div class="cart-upsell-image"> | |
<img src="{{ all_products[productg] | img_url: '300x' }}"> | |
</div> | |
<div class="cart-upsell-text"> | |
{{ settings.gift_wrap_top_text }} | |
<p> | |
<a href="/cart/add?id={{ productg-variant-id }}"> | |
<div class="button"><span class="make-rush-order">{{ settings.gift_wrap_button }}</span></div> | |
</a> | |
</p> | |
</div> | |
</div> | |
<div class="make-rush-details">{{ settings.gift_wrap_bottom_text }}</div> | |
</div> | |
{% endif %} | |
{% endunless %} | |
{% endif %} | |
<!-- End Gift Wrap Section --> | |
<!-- Start Holiday/Vacation Section --> | |
{% if settings.cart_holiday_message_enable %} | |
<div class="cart-upsell"> | |
<div class="cart-upsell-row"> | |
<div class="cart-upsell-image"> | |
<img src="{{ settings.cart_holiday_image | img_url: '300x' }}"> | |
</div> | |
<div> | |
{{ settings.cart_holiday_text }} | |
</div> | |
</div> | |
</div> | |
{% endif %} | |
<!-- End Holiday/Vacation Section --> | |
<!-- Start Cross Sell Section --> | |
{% if settings.cart_cross_sell_enable %} | |
{% unless settings.cart_cross_sell_product_1 == blank %} | |
{% assign upsell1 = 0 %} | |
{% assign product1 = settings.cart_cross_sell_product_1 %} | |
{% assign product1-title = all_products[product1].title %} | |
{% assign product1-variant-id = all_products[product1].variants.first.id %} | |
{% for item in cart.items %} | |
{% if item.product.title contains product1-title %} | |
{% assign upsell1 = upsell1 | plus:1 %} | |
{% endif %} | |
{% endfor %} | |
{% if upsell1 == 0 %} | |
<div class="cart-upsell"> | |
<div class="cart-upsell-row"> | |
<div class="cart-upsell-image"> | |
<img src="{{ all_products[product1] | img_url: '300x' }}"> | |
</div> | |
<div class="cart-upsell-text"> | |
{{ settings.cart_cross_sell_top_text }} | |
<p> | |
<a href="/cart/add?id={{ product1-variant-id }}"> | |
<div class="button"><span class="make-rush-order">{{ settings.cart_cross_sell_button }}</span></div> | |
</a> | |
</p> | |
</div> | |
</div> | |
<div class="make-rush-details">{{ settings.cart_cross_sell_bottom_text }}</div> | |
</div> | |
{% else %} | |
{% unless settings.cart_cross_sell_product_2 == blank %} | |
{% assign upsell2 = 0 %} | |
{% assign product2 = settings.cart_cross_sell_product_2 %} | |
{% assign product2-title = all_products[product2].title %} | |
{% assign product2-variant-id = all_products[product2].variants.first.id %} | |
{% for item in cart.items %} | |
{% if item.product.title contains product2-title %} | |
{% assign upsell2 = upsell2 | plus:1 %} | |
{% endif %} | |
{% endfor %} | |
{% if upsell2 == 0 %} | |
<div class="cart-upsell"> | |
<div class="cart-upsell-row"> | |
<div class="cart-upsell-image"> | |
<img src="{{ all_products[product2] | img_url: '300x' }}"> | |
</div> | |
<div class="cart-upsell-text"> | |
{{ settings.cart_cross_sell_top_text2 }} | |
<p> | |
<a href="/cart/add?id={{ product2-variant-id }}"> | |
<div class="button"><span class="make-rush-order">{{ settings.cart_cross_sell_button2 }}</span></div> | |
</a> | |
</p> | |
</div> | |
</div> | |
<div class="make-rush-details">{{ settings.cart_cross_sell_bottom_text2 }}</div> | |
</div> | |
{% else %} | |
{% unless settings.cart_cross_sell_product_3 == blank %} | |
{% assign upsell3 = 0 %} | |
{% assign product3 = settings.cart_cross_sell_product_3 %} | |
{% assign product3-title = all_products[product3].title %} | |
{% assign product3-variant-id = all_products[product3].variants.first.id %} | |
{% for item in cart.items %} | |
{% if item.product.title contains product3-title %} | |
{% assign upsell3 = upsell3 | plus:1 %} | |
{% endif %} | |
{% endfor %} | |
{% if upsell3 == 0 %} | |
<div class="cart-upsell"> | |
<div class="cart-upsell-row"> | |
<div class="cart-upsell-image"> | |
<img src="{{ all_products[product3] | img_url: '300x' }}"> | |
</div> | |
<div class="cart-upsell-text"> | |
{{ settings.cart_cross_sell_top_text3 }} | |
<p> | |
<a href="/cart/add?id={{ product3-variant-id }}"> | |
<div class="button"><span class="make-rush-order">{{ settings.cart_cross_sell_button3 }}</span></div> | |
</a> | |
</p> | |
</div> | |
</div> | |
<div class="make-rush-details">{{ settings.cart_cross_sell_bottom_text3 }}</div> | |
</div> | |
{% endif %} | |
{% endunless %} | |
{% endif %} | |
{% endunless %} | |
{% endif %} | |
{% endunless %} | |
{% endif %} | |
<!-- End Cross Sell Section --> | |
<!-- Start RUSH Order Section --> | |
{% if settings.cart_rush_enable %} | |
{% assign upsellr = 0 %} | |
{% assign productr = settings.rush_product %} | |
{% assign productr-title = all_products[productr].title %} | |
{% assign productr-variant-id = all_products[productr].variants.first.id %} | |
{% for item in cart.items %} | |
{% if item.product.title contains productr-title %} | |
{% assign upsellr = upsellr | plus:1 %} | |
{% endif %} | |
{% endfor %} | |
{% if upsellr == 0 %} | |
<div class="cart-upsell"> | |
<div class="cart-upsell-row"> | |
<div class="cart-upsell-image"> | |
<img src="{{ all_products[productr] | img_url: '300x' }}"> | |
</div> | |
<div class="cart-upsell-text"> | |
{{ settings.rush_top_text }} | |
<p> | |
<a href="/cart/add?id={{ productr-variant-id }}"> | |
<div class="button"><span class="make-rush-order">{{ settings.rush_button }}</span></div> | |
</a> | |
</p> | |
</div> | |
</div> | |
<div class="make-rush-details">{{ settings.rush_bottom_text }}</div> | |
</div> | |
{% endif %} | |
{% endif %} | |
<!-- End RUSH Order Section --> |
Additional.css.liquid
This is the CSS code that is used to render the display of the promotions in the cart. So this CSS code is used on the classes used in the cart-messages.liquid code. You can add this code to your theme's CSS file. Though I prefer to keep a seperate CSS file in the theme for all of the CSS code that I add. If that's the case for you, you'll need to load the CSS file in theme.liquid.
/*--- Cart Messages ---*/ | |
#cart-message { | |
background-color: {{ settings.cart_promo_background }}; | |
padding: 15px; | |
} | |
.cart-upsell { | |
padding: 20px; | |
text-align: center; | |
margin: 20px auto; | |
max-width: 800px; | |
border: 1px solid #dddddd; | |
border-radius: 5px; | |
} | |
.cart-upsell-row { | |
display: -webkit-flex; | |
display: flex; | |
-webkit-flex-direction: row /* works with row or column */ | |
flex-direction: row; | |
-webkit-align-items: center; | |
align-items: center; | |
-webkit-justify-content: center; | |
justify-content: center; | |
max-width: 600px; | |
margin: 0 auto; | |
} | |
.make-rush-order { | |
max-width: 200px; | |
margin-top: 3px; | |
color: white !important; | |
} | |
.make-rush-details { | |
font-size: 13px; | |
line-height: 1.6em; | |
max-width: 700px; | |
margin: auto; | |
} | |
.cart-upsell-image { | |
max-width: 30%; | |
margin: 3px; | |
} | |
.cart-upsell-image img { | |
max-width:100%; | |
max-height: 170px; | |
} | |
.cart-upsell-text { | |
padding-left: 10px; | |
} | |
@media (max-width: 768px) { | |
.cart-upsell-image { | |
display: none; | |
} | |
} | |
/*--- End Cart Messages ---*/ |
Settings_schema.json
This code needs to be added to the existing setttings_schema.json file in your theme. This code adds controls to Theme Customization elements to your theme that will allow to easily setup and edit the content of the promotions.
{ | |
"name": "Cart Promotions", | |
"settings": [ | |
{ | |
"type": "header", | |
"content": "Rush Processing" | |
}, | |
{ | |
"type": "checkbox", | |
"id": "cart_rush_enable", | |
"label": "Show RUSH promotion in cart" | |
}, | |
{ | |
"type": "product", | |
"id": "rush_product", | |
"label": "Rush Product" | |
}, | |
{ | |
"type": "richtext", | |
"id": "rush_top_text", | |
"label": "Rush text", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "text", | |
"id": "rush_button", | |
"label": "Button text" | |
}, | |
{ | |
"type": "richtext", | |
"id": "rush_bottom_text", | |
"label": "Rush bottom text", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "header", | |
"content": "Cart Size Promotion" | |
}, | |
{ | |
"type": "checkbox", | |
"id": "cart_size_enable", | |
"label": "Show cart size promotion in cart" | |
}, | |
{ | |
"type": "range", | |
"id": "sleepwear_threshold", | |
"min": 50, | |
"max": 250, | |
"step": 5, | |
"unit": "$", | |
"label": "Sleepwear Threshold", | |
"default": 175 | |
}, | |
{ | |
"type": "text", | |
"id": "threshold_discount_code", | |
"label": "Discount code" | |
}, | |
{ | |
"type": "image_picker", | |
"id": "under_threshold_image", | |
"label": "Under threshold image" | |
}, | |
{ | |
"type": "richtext", | |
"id": "under_threshold_top_text", | |
"label": "Under Threshold text", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "text", | |
"id": "under_threshold_button", | |
"label": "Button text" | |
}, | |
{ | |
"type": "richtext", | |
"id": "under_threshold_bottom_text", | |
"label": "Under threshold bottom text", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "image_picker", | |
"id": "over_threshold_image", | |
"label": "Over threshold image" | |
}, | |
{ | |
"type": "richtext", | |
"id": "over_threshold_top_text", | |
"label": "Under Threshold text", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "text", | |
"id": "over_threshold_button", | |
"label": "Button text" | |
}, | |
{ | |
"type": "richtext", | |
"id": "over_threshold_bottom_text", | |
"label": "Under threshold bottom text", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "header", | |
"content": "Gift Wrap Promotion" | |
}, | |
{ | |
"type": "checkbox", | |
"id": "gift_wrap_enable", | |
"label": "Show gift wrap promotion in cart" | |
}, | |
{ | |
"type": "product", | |
"id": "gift_wrap_product", | |
"label": "Product" | |
}, | |
{ | |
"type": "richtext", | |
"id": "gift_wrap_top_text", | |
"label": "Gift wrap text", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "text", | |
"id": "gift_wrap_button", | |
"label": "Button text" | |
}, | |
{ | |
"type": "richtext", | |
"id": "gift_wrap_bottom_text", | |
"label": "Gift wrap bottom text", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "header", | |
"content": "Cross-sell Promotion" | |
}, | |
{ | |
"type": "checkbox", | |
"id": "cart_cross_sell_enable", | |
"label": "Show cross-sell promotion in cart" | |
}, | |
{ | |
"type": "product", | |
"id": "cart_cross_sell_product_1", | |
"label": "Product 1" | |
}, | |
{ | |
"type": "richtext", | |
"id": "cart_cross_sell_top_text", | |
"label": "Cross-sell text", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "text", | |
"id": "cart_cross_sell_button", | |
"label": "Button text" | |
}, | |
{ | |
"type": "richtext", | |
"id": "cart_cross_sell_bottom_text", | |
"label": "Cross-sell bottom text", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "product", | |
"id": "cart_cross_sell_product_2", | |
"label": "Product 2" | |
}, | |
{ | |
"type": "richtext", | |
"id": "cart_cross_sell_top_text2", | |
"label": "Cross-sell text 2", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "text", | |
"id": "cart_cross_sell_button2", | |
"label": "Button text 2" | |
}, | |
{ | |
"type": "richtext", | |
"id": "cart_cross_sell_bottom_text2", | |
"label": "Cross-sell bottom text 2", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "product", | |
"id": "cart_cross_sell_product_3", | |
"label": "Product 3" | |
}, | |
{ | |
"type": "richtext", | |
"id": "cart_cross_sell_top_text3", | |
"label": "Cross-sell text 3", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "text", | |
"id": "cart_cross_sell_button3", | |
"label": "Button text 3" | |
}, | |
{ | |
"type": "richtext", | |
"id": "cart_cross_sell_bottom_text3", | |
"label": "Cross-sell bottom text 3", | |
"default": "<p><\/p>" | |
}, | |
{ | |
"type": "header", | |
"content": "Holiday Message" | |
}, | |
{ | |
"type": "checkbox", | |
"id": "cart_holiday_message_enable", | |
"label": "Show closed for the holidays message in cart" | |
}, | |
{ | |
"type": "image_picker", | |
"id": "cart_holiday_image", | |
"label": "Holiday Image", | |
"info": "Recommended size - 300x220" | |
}, | |
{ | |
"type": "richtext", | |
"id": "cart_holiday_text", | |
"label": "Holiday Shipping Message", | |
"default": "<p><\/p>" | |
} | |
] | |
}, |
This code should give you the building blocks that you need. You'll need to edit the code to have only the promotions that you want, to have the promotions show up the way you want and get it to work in your theme.