Applying discount codes in the cart (prior to checkout)

mfs-mindsize
Excursionist
20 0 7

We've been asked to add an (Apply) Discount Code text input to the client's side cart. I've done some discovery and found a couple apps what say they support this. On the other hand, we naturally want to be thorough and see if we can do it ourselves.  

I created a discount and used apply via link. 

https://help.shopify.com/en/manual/discounts/managing-discount-codes#promote-a-discount-using-a-shar...

When I get to the actual checkout page, the discount shows up (as it should). 

Then I added a get cart (via AJAX) to the side cart (prior to checkout):

https://shopify.dev/docs/themes/ajax-api/reference/cart#get-cart-js

And dump that via console.log() and the cart object returned doesn't show anything about a discount. No code. Nuttin'. 

Yet, if I continue on to checkout, the discount shows up again / still. 

Based on some additional research, evidently there's no way to apply a coupon code via AJAX. The last discussion I found was about a year old. Is there still no relatively easy way to apply a discount via Ajax? 

All that being said, if there are no other options, we'll go the app route. Does anyone have any suggestions for such apps?

 

 

 

 

 

Replies 26 (26)

mfs-mindsize
Excursionist
20 0 7

Bump. Anyone? Anything?

yasmim
Visitor
2 0 2

Dear friend, I'm struggled in the same situation. Could you find a solution for such problem? I need to apply discount in ajax cart so it's showed on cart like automatic discounts are.

SantoshKori
Shopify Partner
3 0 1

Create a new code snippet with cart-apply-discount

{% comment %}
  Replace the text below with the handle of your add-on product.
{% endcomment %}

{% assign product = all_products['put-your-product-handle-here'] %}

{% unless cart.item_count == 0 or product.empty? or product.variants.first.available == false %}

  {% assign variant_id = product.variants.first.id %}

  <script>
  (function($) {

    var cartItems = {{ cart.items | json }},
        qtyInTheCart = 0,
        cartUpdates = {};

    for (var i=0; i<cartItems.length; i++) {
      if ( cartItems[i].id === {{ variant_id }} ) {
        qtyInTheCart = cartItems[i].quantity;
        break;
      }
    }

    if ( ( cartItems.length === 1 ) && ( qtyInTheCart > 0 ) ) {
      cartUpdates = { {{ variant_id }}: 0 }
    }
    else if ( ( cartItems.length >= 1 ) && ( qtyInTheCart !== 1 ) ) {
      cartUpdates = { {{ variant_id }}: 1 }
    }
    else {
      return;
    }

    var params = {
      type: 'POST',
      url: '/cart/update.js',
      data: { updates: cartUpdates },
      dataType: 'json',
      success: function(stuff) { 
        window.location.href = '/cart';
      }
    };

    $.ajax(params);

  })(jQuery);
  </script>

{% endunless %}

Include the new snippet in your cart.liquid template

{% include 'cart-discount' %}

 

yasmim
Visitor
2 0 2

Thanks for replying @SantoshKori . 

I can't see excatly in your code where are you applying a discount code. Can you explain it to me?

As I can see, you're only updating quantity of an item.

Thnaks again.

AdrianExpert
Shopify Partner
28 1 1

Shopify doesn't allow to process discounts in checkout directly. There is no API to apply a discount code. There is workaround with making ajax call to checkout page but it's quite complicated. 

I was searching for liquid code to achieve that and stumbled upon an app. It works perfectly with cart drawer and cart page. Here is how my drawer now looks like:

 

Screen Shot 2020-09-21 at 19.22.03.png

 

https://apps.shopify.com/discount-in-cart 

For you to achieve your goals, visitors must first achieve theirs
0x15f
Visitor
1 0 0

Late to the thread but I'm implementing this as well. Does the `checkoutdiscountcodeapplyv2` mutation of the StoreFront API not work for this? I believe the StoreFront API can be used on the frontend of a normal Shopify website without a Plus subscription.

https://shopify.dev/docs/storefront-api/reference/mutation/checkoutdiscountcodeapplyv2

AdrianExpert
Shopify Partner
28 1 1

As far as I understand the app should be a sales channel. You you are making a private app it's okay. But if you made a public app you may face with the limitation of the appstore. As the sales channel should not only create checkouts/add discounts there but also publish products at the different platforms.

 

For you to achieve your goals, visitors must first achieve theirs
benshrimpton
Shopify Partner
12 0 26

This works, but the Storefront API does not with the the `cart.js` endpoint, so it's useless.

benshrimpton
Shopify Partner
12 0 26

This wont work with the /cart.js endpoint, only the GraphQL endpoints, which aren't a cart, they're a checkout.

ShopDoctors
Shopify Partner
39 2 5

If you're only looking for a way to display a discount input, then you can add a regular input field with the name 'discount' to the cart's <form> element. This works on the cart page as well as a cart popup, as long as the form action posts into the checkout.

E.g. <input name="discount" type="text>

The tricky part is if you want to check that the coupon is applicable to the cart and display the discounted amount. There is no easy way to do that yourself at this time, which is why apps exist to handle this functionality. There are many apps that apply a discount on the cart page. They differ in appearance as well as supporting functionality and price. The app we've developed for this purpose is https://apps.shopify.com/discount-on-cart-pro. It has a 14-day free trial so you can give it a shot risk-free.

juceisk
Shopify Partner
19 0 2

Hi, there is a simple way to add discount codes before checking out, this is what I do in my store:
In the cart-drawer.liquid file I add an input with the name of the previously created discount and at the time of checking out it should already appear applied.

<input type = "hidden" name = "discount" value = "DISCOUNT_NAME" />

this is what you need?

Zanath
Shopify Partner
1 0 6

This JavaScript snippet should allow you to apply the discount to the current session.

 

// Setup the Apply Discount Code URL
let shopDomain = "somesite.myshopify.com";
let discountCode = "MYDISCOUNTCODE123";
let discountApplyUrl = "https://" + shopDomain + "/discount/" + discountCode;
	
// Applies discount using hidden iframe to the checkout session
let i = document.createElement('iframe');
i.style.display = 'none';
i.onload = function() { i.parentNode.removeChild(i); };
i.src=discountApplyUrl;
document.body.appendChild(i);
Joaqib
Shopify Partner
2 0 2

Hi Zanath,

 

We just found your solution, the main issue is that we are encountering a problem with the implementation:

 

Refused to frame 'https://some-site.myshopify.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'none'".

 

Have you encountered the same issue?? We keep reading the documentation and could not find a solution.

 

Thanks in advance!

Dixor
Shopify Partner
30 3 9

It doesnt work any more.

iamkeir
Shopify Partner
205 0 41

One thing you could consider is to add the discount code to Shopify's discount cookie via JavaScript. This will then be auto-applied when you checkout (if your cart is eligible).

document.cookie = 'discount_code=YOURDISCOUNTCODE';

 

http://iamkeir.com
owlvark
Shopify Partner
2 0 1

When 

/cart?discount=ABC123

stopped working this method was a good replacement, thanks

seymur_crsp
Shopify Partner
65 4 9

Thanks @Zanath . But is there a way to apply multiple discounts with this link ?

iamkeir
Shopify Partner
205 0 41

The checkout permalink works with multiple discount codes separated by commas, e.g. `?discount=DISCOUNT1,DISCOUNT2`. If you append this to your cart form action (e.g. /cart?discount=DIS1,DIS2`), when submitting cart to proceed to checkout, it will apply the discounts.

 

For the `/discount/` solution, I tried `/discount/DISCOUNT1+DISCOUNT2` and `/discount/DISCOUNT1,DISCOUNT2` and `/discount/DISCOUNT1&DISCOUNT2` but none worked, so I suspect this solution is only for singular discounts.

 

Same goes for the `discount_code` cookie, singular only in my testing.

 

The above is unconfirmed from Shopify, just via experimenting.

http://iamkeir.com
MaxDesign
Shopify Expert
186 13 73

I'm also curious about that. This seems undocumented so use with caution, but it seems this way we can apply a manual discount code to the cart page with a simple client-side fetch request:

fetch('/discount/discount-1').then(async () => {
  // refresh cart here
});

 
But I too can't figure out a way to make this call with combined discounts (tried a few things as well). It seems only possible to combine in checkout page. 

Reach out to me at admin@maxdesign.expert

owlvark
Shopify Partner
2 0 1

I used a modified version of this ajax solution:
https://gist.github.com/elghorfi/ce7e5b1080aae37d0a415643f33bc79e
It is complex but I can confirm that it works.

MaxDesign
Shopify Expert
186 13 73

It's an interesting find! But I don't get why his solution is so... convoluted I'd say. I actually shared my own solution on the gist feed (I believe much simpler and more efficient), could be interesting to compare the pros & cons.

Reach out to me at admin@maxdesign.expert
scottshop
Shopify Partner
7 1 1

A few things I wanted to add:

fetch(`/checkout?discount=${code}`);

This alone seems to work, as does this:

fetch(`/discount/${code}`);

I'm wondering if anyone has seen a case when only doing one or other fails in some cases. 

Also, with some of the built-in themes (Refresh, Craft) I've seen many cases where the cart views (both the cart drawer and the dedicated cart page) end up getting cached so they only ever show whatever discount was applied the first time you viewed that particular page. This has nothing to do with applying a code via either fetch call either, as the results held true even when applying the discount code manually in the checkout as a user would normally.

Anyway, in my tests, either fetch call above works to get the discount in the checkout but I'm betting not all themes would see the same result.

MaxDesign
Shopify Expert
186 13 73
Also, with some of the built-in themes (Refresh, Craft) I've seen many cases where the cart views (both the cart drawer and the dedicated cart page) end up getting cached so they only ever show whatever discount was applied the first time you viewed that particular page. This has nothing to do with applying a code via either fetch call either, as the results held true even when applying the discount code manually in the checkout as a user would normally.

You might be talking about automatic discouts? Automatic discounts will apply in cart page "automatically" as their name imply (as long as the cart liquid template is using the discount_allocation and discount_application objects). 

What seems to be new (in my experience) since the release of these objects, is that now the manual discounts that are applied also render within these objects, which is quite convenient and opens up some possibilities.

Reach out to me at admin@maxdesign.expert
scottshop
Shopify Partner
7 1 1

This isn't with automatic discounts, but it seems like some newer versions of these Shopify-provided themes will show you any cart-level discounts that you may have applied during checkout *in the cart view*.  For example, in this view YUM10 isn't an automatic discount, but one I added during checkout and then clicked back to the store to continue shopping. In my experience, if I then go back to checkout, remove YUM10, then click from the checkout back to "Cart", the old discount is still there, even if reloading the page manually.   I thought this was a bug with our plugin but it turns out this behavior exists even with no plugins installed. 

Anyway, would love to hear if you've noticed any difference between the `/checkout?discount=CODE` and the `/discount/CODE` fetch techniques. Both seem to work equally well in my case.



cart-discount.png

MaxDesign
Shopify Expert
186 13 73

Okay I see, so this is what I mentioned  in the second part of my message. The caching issue, this might be a miss on Shopify side, or maybe due do the page caching by the browser, which happens when returning to a page with the back button (typical use case for navigation from checkout to cart).

I suppose this could be detected with javascript pageshow event, and then fetching a fresh version of the cart.

I've only used the '/discount/CODE'  technique, which I guess is originally the API intended for shareable discount urls. I have not had any issue with it yet but I've only played around with it for a month, and since it's undocumented...

I suppose this method '/checkout?discount=CODE' might allow to apply multiple manual discounts at once (comma separated) whereas it's not possible with the first method. I have not checked for myself though.

Reach out to me at admin@maxdesign.expert
iamkeir
Shopify Partner
205 0 41

Oh wow, I am really interested to see how this is achieved - do you have a link to the store? I wonder if it is checking the cookie, and showing it accordingly BUT the discount amount isn't stored in the cookie I don't think, so I'd be curious how it is doing that. Maybe the theme is using a discount API or something? My understanding was you couldn't show manual discounts in the cart because they rely on checkout data to check if eligible.

http://iamkeir.com