d
Topic
Posts:
34
Last edited May 29, 2015
g
5

Autofill Discount via URL - A Step by Step Walkthrough (eg. Auto Apply discount code using a Link!)

The Problem

I wanted customers to be able to click a link that would automatically apply a discount code once the customer reaches our checkout. In practice this could be used for Marketing Emails (eg. Click this button for 15% off!), on Google Adwords ads, Facebook posts, etc. This makes things easier for the customer because they don’t have to manually enter discount codes and it also makes things easier for us because we can track every single customer that clicks that link and places and order.

================================================================

Intro

Although this should work well in a large variety of themes, this code has only been tested on our store (which uses the Minimal Theme), so just keep in mind the code in your theme may look slightly different. It’ fairly basic code though and only requires copying and pasting 3 small code snippets into 2 of your theme files.

I wanted write this tutorial as just a small way of paying it forward for all the great information on this forum I’ve learned from. This discussion was started here and huge props to Patrick, who helped tremendously in getting me started.

Disclaimers: My Javascript skills are complete rubbish so this code is provided without any sort of guarantee. Yes, I realize not all browsers support the HTML5 Storage Spec, but I couldn’t be troubled with supporting unspeakable browsers like IE 6 or 7. Others will almost certainly find ways of simplifying this and any suggestions for improvement are welcome. This is an advanced'ish type of customization we are doing so I wouldn’t expect Shopify, me, or anyone else here to fix anything if you try this and it kills your pet koala and/or your computer explodes. I’m sure myself and others here will try and help when/if we can but it should definitely not be expected. Now that we have that out of the way let’s get going!

================================================================

Overview

Here is a basic outline of what we are doing:

  1. Customer visits a link that contains our Discount Code on the end of it — eg. 

    www.YourStore.com/?discount=15percentoff

     

  2. We grab that discount code from the Query String and do 2 things with it. Note: The query string is the ?discount=15percentoff part of the URL

    1. We save it as a HTML5 sessionStorage Variable.
    2. We add it to the contents of a hidden input box. Why do we do this? because if the discount in the query string and the discount stored in our hidden input box are different, then we need to clear the sessionStorage variable before we can set it again.

    Notes: Once a sessionStorage variable is set it will persist until the customer closes the browser window/tab. When the browser window/tab is closed all sessionStorage variables are cleared, so in order to apply the discount again the customer would need to click the same link again. We could have used a HTML5 localStorage Variable but then the customer would have basically been given the same discount code on every subsequent visit until the end of time—and that’s probably not what we want.

  3. When the customer visits the cart page of our Shopify store we grab the contents of that sessionStorage variable and add that to the cart form’s action parameter. So when the customer clicks the checkout button we send them to a link that looks like

    https://checkout.shopify.com/99999/checkouts/99999999?discount=15percentoff

    This is the step that makes the magic happen.

================================================================

Step-by-Step

  1. Copy and paste the following code into your theme.liquid file right before the closing

    </head>

     This code is commented to the best of my [very limited] ability.

    <script>
    /* Begin Discount Autofill Code */
    /* Read the Query String value from the URL */    
    /* Link: http://stackoverflow.com/a/2880929 - Notes: No clue how this regex stuff works. Probably fairy magic.  */
        var urlParams;
        (window.onpopstate = function () {
            var match,
                pl     = /\+/g,  // Regex for replacing addition symbol with a space
                search = /([^&=]+)=?([^&]*)/g,
                decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
                query  = window.location.search.substring(1);
    
        urlParams = {};
        while (match = search.exec(query))
        urlParams[decode(match[1])] = decode(match[2]);
        })();
    
    /* If the value of the hidden discount input field is blank, undefined or null then set the contents of localstorage discount to be the result of our Query String function above */    
        if ($("#discount_input").val() == ('' || undefined || null || 'undefined')) {
        /* Set sessionStorage variable "discount" to the result of our Query string function above */
           sessionStorage.setItem("discount", urlParams["discount"]);
        }
    
    /* If the value in our hidden input field doesn’t match the result of our Query String function above then clear the current sessionStorage value for "discount" and replace it with the new one */
    /* Link: http://stackoverflow.com/q/19844750 */
        else if ($("#discount_input").val() != urlParams["discount"]) {
           sessionStorage.removeItem("discount");
           sessionStorage.setItem("discount", urlParams["discount"]);
        }    
    /* End Discount Autofill Code */
    </script>
    
  2. Copy and paste the following code into your theme.liquid file right after the opening <body> tag.

    <!-- Our hidden input that stores the discount code value -->
    <input id="discount_input" type="hidden" name="discount" value="">
    <!-- Set the value of our hidden input field #discount-input to the value of our sessionStorage "discount" Variable -->
    <script>document.getElementById("discount_input").value = sessionStorage.getItem("discount");</script>
  3. Copy and past the following code into your cart.liquid file right after the <form action="/cart" method="post" id="cartform"> tag.

    <script>
    /* If the length of sessionStorage "discount" is NOT 0 then add our sessionStorage value to the end of our Checkout link */
    /* Link: http://stackoverflow.com/a/4704786 */
    if (sessionStorage.getItem("discount").length != 0) {
      document.getElementById('cartform').action = "/cart?discount=" + sessionStorage.getItem("discount");
    };
    </script>

================================================================

Done!

Go to www.YourStoreHere.com/?discount=YourDiscountCodeHere Add something to your cart, go to your cart page, and then click the checkout button. If everything went well you should see your discount code automatically applied to your order.

Did this work on your store or do you have suggestions for improving it? Leave a comment below! Thanks!

i
Replies
Posts:
196
Last edited June 01, 2015
g
3
upvotes

Great post! One thing I'd add is to put your custom JS code in a Immediately-Invoked Function Expression (IIFE). This will prevent objects and variables you create from polluting the global namespace and potentially conflicting with other javascript code. 

To do this you simply wrap your JS code like this:

<script>

  (function() {
     // Your Code Here
  }());

</script>

Here is a more detailed explaination on the matter: http://benalman.com/news/2010/11/immediately-invoked-function-expression/

Stop Stressing About Shopify You’ve Got Better Things To Do =&gt; https://320ny.com/shopify/
Cam Shopify Expert elkfox.com
Posts:
155
Last edited June 02, 2015
g
2
upvotes

Nice one! The only thing that I think would make it better is to use localStorage instead of sessionStorage and add an expire function to the localStorage. That way if someone accidentally closed the tab or their browser crashed, and they expected to continue from there, they could without having to follow the original discount link again. It would just make the experience that little bit more user firendly :)

That said, the sessionStorage option is the most straightforward, and should work for most situations. That's what I originally played with before later deciding an expiry you could control may be better.

Thanks for sharing!

Head fox at Elkfox | App and web, design and development | Digital commerce experts | https://elkfox.com
Posts:
30
June 02, 2015
g
1
upvotes

Thanks for sharing :)

 

I chuckled at your comment "Notes: No clue how this regex stuff works. Probably fairy magic."

Posts:
34
June 03, 2015

@Ryan — Thanks for the suggestion about using a function wrapper. Read through that article and I definitely see the reasoning there. For sure I wouldn’t want to screw up the values of other potential variables that may be out there.

@Cam — I didn’t actually realize we can set expiry dates for localStorage, but for sure that would be a better option. What code did you end up using to set the expiry? A quick Google search pulls up all kinds of different ways of doing it—not sure if some are better than others.    ¯\_(ツ)_/¯

@Bathroomware — Glad you liked the tutorial!  :)

- - Mark  

Cam Shopify Expert elkfox.com
Posts:
155
June 04, 2015
g
1
upvotes

I haven't decided what I think is the best method. But from what I have read, adding a timestamp to the key value using stringify and JSON seems to be the general consensus. Then you can create some JS that checks the timestamp value against whatever expiry you set, and removes the localStorage content when appropriate. I'm no JS expert though!

Head fox at Elkfox | App and web, design and development | Digital commerce experts | https://elkfox.com
Posts:
8
June 04, 2015
g
2
upvotes

For those who are interested to test this in their store I built a simple little app that does something similar to automatically fill in the code during checkout. https://apps.shopify.com/autofill-discount-from-url

Jason Shopify Expert freakdesign.com.au
Posts:
7986
June 04, 2015

@rx - There's probably a few js things I'd tweak in the above to give older IE a fighting chance. If you throw this in a gist I can adjust that.

★ Winning Partner of the Build a Business competition. ★ http://freakdesign.com.au
Posts:
34
June 04, 2015

@Jason - Here it is. Sorry if I am doing Github wrong. I literally just signed up 2 minutes ago so I have no clue how it all works. Thanks for trying to improve it though! I admire your work a great deal.

Posts:
30
June 05, 2015

I should note that I've implemented this code and have not had success.

 

We use the Supply theme.

Posts:
196
Last edited June 05, 2015

@Bathroomware can you elaborate on what issues you are having? Perhaps we can help you out. 

Stop Stressing About Shopify You’ve Got Better Things To Do =&gt; https://320ny.com/shopify/
Posts:
30
June 05, 2015

When doing "Go to www.YourStoreHere.com/?discount=YourDiscountCodeHere Add something to your cart, go to your cart page, and then click the checkout button. If everything went well you should see your discount code automatically applied to your order." the discount does not apply.

Posts:
196
June 05, 2015

A few questions for you @Bathroomware.

1. Do you have the discount code setup in your shopify admin?

2. Can you look in your session storage to see if a discount code has been saved?

To do this open up the console of your browser and type: sessionStorage

Hit enter and you should see whatever data is in session storage

3. Do you know any Javascript? If so can you see if the form action on the cart page has been altered?

 

Stop Stressing About Shopify You’ve Got Better Things To Do =&gt; https://320ny.com/shopify/
Posts:
3
August 26, 2015

I too have been fighting with this. I'm using the Retina theme. I tried the app from ivory consulting, but it did not work.  I then tried to manually copy/paste the code for the original post into my theme files, it did not work. Can anyone help?

Alex

Posts:
196
Last edited August 26, 2015
g
1
upvotes

Hi Alex,

You might need to little programming experience to accomplish this.

If you ask specific questions on the forum we might be able to help you out.

Other than that you will need to hire someone. You can post the task on the jobs board. There are also long term support services. My company offers on that you can check out: https://320ny.com/shopify

There are a few others that offer something similar you can check out as well:

http://heycarson.com/

http://shopenhancer.com/

http://www.shopifyninjas.com/shopify-support-program/

http://www.jimmyweb.net/services/shopify-development/

http://boldcommerce.com/ecommerce-webmaster-services

Cheers,

Ryan

Stop Stressing About Shopify You’ve Got Better Things To Do =&gt; https://320ny.com/shopify/
Posts:
1
Last edited August 30, 2015
g
1
upvotes

This is just a quick thanks for this thread. I spent hours hunting Shopify, apps and forums for a solution to my "simple" requirement of automated, bracketed discounts (eg. 5% off £50 order, 10% off £100 order). Taking what you've discussed here and distilling it down I've managed to do that successfully although how resilient it'll be to future Shopify updates I don't know.

All I did was create 3 discount codes:
BRONZE30 gives a 3% discount at £30
SILVER50 gives a 5% discount at £50
GOLD100 gives a 10% discount at £100

I then edited templates/cart.liquid and immediately before the closing </form> tag on that page I added the following code which creates the hidden field to hold the discount code reference, the value of which is set with the simple IF statement. Remember to put them in ascending order of value so the SILVER will overwrite the BRONZE and the GOLD will overwrite the SILVER as the IF statements are executed sequentially. Note also that the figures 2999, 4999 and 9999 relate to £29.99, £49.99 and £99.99 it seems Shopify stores the value total cart value in pence.

<input id="discount_input" type="hidden" name="discount" />
  <script>   
    if ({{cart.total_price}} > 2999) {
            document.getElementById("discount_input").value = "BRONZE30";
    };  
    if ({{cart.total_price}} > 4999) {
            document.getElementById("discount_input").value = "SILVER50";
    };  
    if ({{cart.total_price}} > 9999) {
            document.getElementById("discount_input").value = "GOLD100";
    };     
  </script>

I'm sure someone who understands the code can make it look more elegant but, for now, it serves my purpose.

If anyone can see a glaring error then please advise as my shop is not active yet and I've got time to re-think it it necessary. Otherwise many thanks again for pointing me in the right direction.

NOTE: I've just noticed this doesn't work on the MODAL cart type (as set in the themes editor for the cart page). I had to select "PAGE" cart type to get it to work. Perhaps there's another liquid file to update with the above coding to get it to work on the modal cart type too.

Posts:
7
Last edited September 09, 2015

Hi, Ryan (@Ryan Bennick)! 

As a newbie to Shopify/code, may I ask two things:

  1. Are you supposed to wrap all three of RX's code snippets with the IIFE?
  2. Do I put ALL of RX's code where "// Your Code Here" is? Or does RX's opening <script> and closing </script> go outside the function? 

 

Posts:
196
September 09, 2015
g
1
upvotes

Hi Tomas,

1. Yes. THis is a JS programming technique that is used so your code does not conflict with any other JS code running on the page. 

2. The <script> tag tells the browser that it is time to start processing Javascrpt code. All of the JS code needs to be within these tags. Inside the <script> tag wel will place all of RX's code inside the IIFE like so:

<script>

(function() {

/* Begin Discount Autofill Code */
/* Read the Query String value from the URL */    
/* Link: http://stackoverflow.com/a/2880929 - Notes: No clue how this regex stuff works. Probably fairy magic.  */
    var urlParams;
    (window.onpopstate = function () {
        var match,
            pl     = /\+/g,  // Regex for replacing addition symbol with a space
            search = /([^&=]+)=?([^&]*)/g,
            decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
            query  = window.location.search.substring(1);

    urlParams = {};
    while (match = search.exec(query))
    urlParams[decode(match[1])] = decode(match[2]);
    })();

/* If the value of the hidden discount input field is blank, undefined or null then set the contents of localstorage discount to be the result of our Query String function above */    
    if ($("#discount_input").val() == ('' || undefined || null || 'undefined')) {
    /* Set sessionStorage variable "discount" to the result of our Query string function above */
       sessionStorage.setItem("discount", urlParams["discount"]);
    }

/* If the value in our hidden input field doesn’t match the result of our Query String function above then clear the current sessionStorage value for "discount" and replace it with the new one */
/* Link: http://stackoverflow.com/q/19844750 */
    else if ($("#discount_input").val() != urlParams["discount"]) {
       sessionStorage.removeItem("discount");
       sessionStorage.setItem("discount", urlParams["discount"]);
    }    
/* End Discount Autofill Code */

}());
</script>

 Cheers,

 

Ryan

Stop Stressing About Shopify You’ve Got Better Things To Do =&gt; https://320ny.com/shopify/
Posts:
7
September 11, 2015

Thanks, Ryan! To make sure, a few more questions:

a) In part 2, should the <input id="discount_input" type="hidden" name="discount" value=""> be inside or outside the IIFE? I've put it outside.

b) Will these code snippets be overwritten by Shopify updates or are they there to stay?

c) Is the below code implemented correctly?

1. Copy and paste the following code into your theme.liquid file right before the closing </head>

<!-- BEGIN: Autofill Discount via URL, with IIFE. PART 1 -->
<script>
  (function() {
/* Begin rx's Discount Autofill Code */
/* Read the Query String value from the URL */    
/* Link: http://stackoverflow.com/a/2880929 - Notes: No clue how this regex stuff works. Probably fairy magic.  */
    var urlParams;
    (window.onpopstate = function () {
        var match,
            pl     = /\+/g,  // Regex for replacing addition symbol with a space
            search = /([^&=]+)=?([^&]*)/g,
            decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
            query  = window.location.search.substring(1);

    urlParams = {};
    while (match = search.exec(query))
    urlParams[decode(match[1])] = decode(match[2]);
    })();

/* If the value of the hidden discount input field is blank, undefined or null then set the contents of localstorage discount to be the result of our Query String function above */    
    if ($("#discount_input").val() == ('' || undefined || null || 'undefined')) {
    /* Set sessionStorage variable "discount" to the result of our Query string function above */
       sessionStorage.setItem("discount", urlParams["discount"]);
    }

/* If the value in our hidden input field doesn’t match the result of our Query String function above then clear the current sessionStorage value for "discount" and replace it with the new one */
/* Link: http://stackoverflow.com/q/19844750 */
    else if ($("#discount_input").val() != urlParams["discount"]) {
       sessionStorage.removeItem("discount");
       sessionStorage.setItem("discount", urlParams["discount"]);
    }    
/* End rx's Discount Autofill Code */
  }());

</script>
<!-- END: Autofill Discount via URL, with IIFE. PART 1 -->
<!-- The closing </head> tag is right below -->

 

2. Copy and paste the following code into your theme.liquid file right after the opening <body> tag

<!-- The opening <body> tag is right above -->
<!-- BEGIN: Autofill Discount via URL, with IIFE. PART 2 -->
<!-- Our hidden input that stores the discount code value -->
<input id="discount_input" type="hidden" name="discount" value="">

<!-- Set the value of our hidden input field #discount-input to the value of our sessionStorage "discount" Variable -->
<script>

  (function() {
	document.getElementById("discount_input").value = sessionStorage.getItem("discount");
  }());

</script>
<!-- END: Autofill Discount via URL, with IIFE. PART 2 -->

3. Copy and past the following code into your cart.liquid file right after the <form action="/cart" method="post" id="cartform"> tag.

<!-- The <form action="/cart" method="post" id="cartform"> code is right above -->
<!-- BEGIN: Autofill Discount via URL, with IIFE. PART 3 -->
<script>

  (function() {
/* If the length of sessionStorage "discount" is NOT 0 then add our sessionStorage value to the end of our Checkout link */
/* Link: http://stackoverflow.com/a/4704786 */
if (sessionStorage.getItem("discount").length != 0) {
  document.getElementById('cartform').action = "/cart?discount=" + sessionStorage.getItem("discount");
};
  }());

</script>
<!-- END: Autofill Discount via URL, with IIFE. PART 3 -->

 

Posts:
7
September 11, 2015
g
1
upvotes

A side note: 

I have tried out the above code on a clean, trial version of Shopify. It works just fine as long as the discount code doesn't contain any unsafe characters. However, when I tried with discount codes like "SAVE50%" the store goes blank. I tried to URL encode the discount code. I used this link: https://flauntmydesign.myshopify.com/?discount=SAVE50%25

It work until I try to access the check-out page, which goes blank. This is what the console/SessionsStorage told me:

Failed to load resource: the server responded with a status of 400 (Bad Request)

sessionStorage
Storage {_shopify_s: "81EA3B3C-10E0-44D2-8851", discount: "SAVE50%"}

It would be nice to use the same code for both manual and automatic disount codes. Any quick fix for the problem with unsafe characters?

 

Sessionsstorage   url encoded discount thumb
Jason Shopify Expert freakdesign.com.au
Posts:
7986
September 11, 2015

You can just add it as the discount value in hidden field in the form cart form.

★ Winning Partner of the Build a Business competition. ★ http://freakdesign.com.au
Posts:
196
September 11, 2015

Tomas,

I'd keep it simple and use discount codes without special characters.

-Ryan

Stop Stressing About Shopify You’ve Got Better Things To Do =&gt; https://320ny.com/shopify/
Posts:
7
Last edited September 11, 2015

Thanks, guys! I'll keep the discount codes simple. :)

In the meantime, I have found out that Shopify themes aren't updated automatically. That cares care of question b) above. @Ryan Bennick, if you dont'mind. How about question a) and c)?

Posts:
196
September 11, 2015

Hi Tomas,

a) Outside. The input is html and should not even be in the <script> tags or else you will get en error. 

c) If it's working for you than yes. If you do come across any errors let us know.

-Ryan

Stop Stressing About Shopify You’ve Got Better Things To Do =&gt; https://320ny.com/shopify/
Posts:
7
September 13, 2015

Hi, I tried to implement the above code on a store with the "Supply" theme. A few questions:

1) The instructions for part 2 is "Copy and paste the following code into your theme.liquid file right after the opening <body> tag". In the theme, there isn't a "clean" <body> tag. Instead it looks like this:

<body id="{{ page_title | handle }}" class="{% if customer %}customer-logged-in {% endif %}template-{{ template | replace: '.', ' ' | truncatewords: 1, '' | handle }}" >

I guess part 2 of the code is to be inserted right after this code?

2) The instructions for part 3 is "Copy and paste the following code into your cart.liquid file right after the <form action="/cart" method="post" id="cartform"> tag". In the Supply theme, that tag is found in an if-statement (see below!) Where exactly should I paste the third code snippet in the below code?

{% if cart.item_count > 0 %}
  <form action="/cart" method="post" novalidate>

    <h1 class="h2">{{ 'cart.general.title' | t }}</h1>

    {% for item in cart.items %}
    <div class="cart-row" data-id="{{ item.id }}">
      <div class="grid">

        <div class="grid-item large--seven-twelfths">
          <div class="grid">

            <div class="grid-item one-third large--one-quarter">
              <a href="{{ item.url }}" class="cart-image">
                <img src="{{ item | img_url: 'medium' }}"  alt="{{ item.title | escape }}">
              </a>
            </div>

            <div class="grid-item two-thirds large--three-quarters">
              <a href="{{ item.url }}">
                {{ item.product.title }}
              </a>
              {% unless item.variant.title contains 'Default' %}
                <br>
                <small>{{ item.variant.title }}</small>
              {% endunless %}

              {% assign property_size = item.properties | size %}
              {% if property_size > 0 %}
                {% for p in item.properties %}
                  {% if forloop.first %}<br>{% endif %}
                  {% unless p.last == blank %}
                    {{ p.first }}:

                    {% if p.last contains '/uploads/' %}
                      <a href="{{ p.last }}">{{ p.last | split: '/' | last }}</a>
                    {% else %}
                      {{ p.last }}
                    {% endif %}

                    <br>
                  {% endunless %}
                {% endfor %}
              {% endif %}
            </div>

          </div>
        </div>

        <div class="grid-item large--five-twelfths medium--two-thirds push--medium--one-third">
          <div class="grid">

            <div class="grid-item one-half medium-down--one-third text-right">
              <input type="number" name="updates[]" id="updates_{{ item.id }}" value="{{ item.quantity }}" min="0" data-id="{{ item.id }}">
            </div>

            <div class="grid-item one-third medium-down--one-third medium-down--text-left text-right">
              <span class="h2">
                {% include 'price' with item.price %}
              </span>
            </div>

            <div class="grid-item one-sixth medium-down--one-third text-right">
              <a href="/cart/change?line={{ forloop.index }}&amp;quantity=0" data-id="{{ item.id }}" class="icon-fallback-text btn-secondary remove">
                <span class="icon icon-x" aria-hidden="true"></span>
                <span class="fallback-text">{{ 'cart.general.remove' | t }}</span>
              </a>
            </div>

          </div>
        </div>

      </div>
    </div>

    {% endfor %}

    <div class="cart-row">
      <div class="grid">

        {% if settings.cart_notes_enable %}
          <div class="grid-item large--one-half">
            <label for="cartSpecialInstructions">{{ 'cart.general.note' | t }}</label>
            <textarea name="note" class="input-full" id="cartSpecialInstructions">{{ cart.note }}</textarea>
          </div>
        {% endif %}

        <div class="grid-item text-right {% if settings.cart_notes_enable %}large--one-half{% endif %}">

          <div class="cart-subtotal">
            {{ 'cart.general.subtotal' | t }}
            <span class="h1 cart-subtotal--price">
              {% include 'price' with cart.total_price %}
            </span>
          </div>

          <input type="submit" name="update" class="btn-secondary update-cart" value="{{ 'cart.general.update' | t }}">

          <button type="submit" name="checkout" class="btn">
            <span class="icon icon-cart"></span>
            {{ 'cart.general.checkout' | t }}
          </button>

          {% if additional_checkout_buttons %}
            <div>{{ content_for_additional_checkout_buttons }}</div>
          {% endif %}

        </div>

      </div>
    </div>

  </form>

{% else %}

  <h2>{{ 'cart.general.empty' | t }}</h2>
  <p>{{ 'cart.general.continue_browsing_html' | t }}</p>

{% endif %}

 

Posts:
196
September 15, 2015

1. That whole thing is still the body tag. It just has some attributes and liquid code in it. Place part 2 after this. 

2. That is fine. Place the code after the form tag. All that if statement is doing is making sure you have items in your cart before showing the form. 

Stop Stressing About Shopify You’ve Got Better Things To Do =&gt; https://320ny.com/shopify/
Posts:
7
September 19, 2015

@Ryan

I installed the Supply theme & implemented the code. Problem is, the discount code isn't applied in the check-out. I've been looking into sessionsStorage. It shows the discount code on all other pages, but its then "lost" on the check-out page. 

This is the where i put the code in cart.liquid:

{% if cart.item_count > 0 %}
  <form action="/cart" method="post" class="cart-form" novalidate>

<!-- The <form action="/cart" method="post" id="cartform"> code is right above -->
<!-- BEGIN: Autofill Discount via URL, with IIFE. PART 3 -->
<script>

  (function() {
/* If the length of sessionStorage "discount" is NOT 0 then add our sessionStorage value to the end of our Checkout link */
/* Link: http://stackoverflow.com/a/4704786 */
if (sessionStorage.getItem("discount").length != 0) {
  document.getElementById('cartform').action = "/cart?discount=" + sessionStorage.getItem("discount");
};
  }());

</script>
<!-- END: Autofill Discount via URL, with IIFE. PART 3 -->
    
    <h1 class="h2">{{ 'cart.general.title' | t }}</h1>

The if statment continues further. Any ideas?

Posts:
196
September 23, 2015

Hi Tomas,

This line in the JS sets a new action on the form so the discount will be applied to the checkout. 

document.getElementById('cartform').action = "/cart?discount=" + sessionStorage.getItem("discount");

It is looking for an element in the DOM with an id of cartform. Thereform you need to change the form element to have this id.

Change this

<form action="/cart" method="post" class="cart-form" novalidate>

to this

<form id="cartform" action="/cart" method="post" class="cart-form" novalidate>

Cheers,


Ryan

Stop Stressing About Shopify You’ve Got Better Things To Do =&gt; https://320ny.com/shopify/
Posts:
23
October 20, 2015

Just a question, would these codes work with conditional coupons, like 10% when you spend more than $200 etc? Or will the codes still try to apply (and not work), if the cart is <$200.

And..is there an existing solution to show the discounted prices or "you have saved $XX" in the cart before someout checks out?

Thanks for all the work you guys shared. Was about to setup an email autoresponder and then I realised this problem. Wow, shopify sure has quite alot of limitations w.r.t coupons, stuff I expected to be basic amongst e-commerce sites. Shopify was the first recommendation I got and I didn't look elsewhere..like woocommerce or magneto. So..why shopify? Wondering if i made a wrong choice here.

Jason Shopify Expert freakdesign.com.au
Posts:
7986
October 20, 2015

This does nothing more than try and autofill the discount code in the checkout. You'll have no idea if it works - nor what the code does - until you get to the checkout. 

★ Winning Partner of the Build a Business competition. ★ http://freakdesign.com.au
Cam Shopify Expert elkfox.com
Posts:
155
October 20, 2015

Hi Esther. Woocommerce and Magento are generally quite rubbish and require a lot of maintenance. An expert will be able to set up those things you are asking about without too much difficulty. This code can be expanded upon to show discounts and create dynamic discounts if needed. But again, you would probably need to get an expert to help you with that.

Head fox at Elkfox | App and web, design and development | Digital commerce experts | https://elkfox.com
Posts:
23
October 20, 2015

Hi guys, thanks for your responses. I guess I'd have to make do with the shortfalls of shopify for now. Appreciate the code work above, really helps shed some light.

EDIT: IT works! I'm so happy, reading and working up till 4am for shopify solutions, driving me crazy~

now to figure out how to get this coupon box in the cart..or some other "shopify" workaround again.. ;(

Posts:
1
Last edited November 19, 2015

Good article.
But I propose to improve last part of your code a little bit.
Now enough just add:

<input type="hidden" name="discount" value="15percentoff"/>

Inside every:

<form action="/cart" ...

...</form>

And then you can add value to this input with JS/JQuery.

Posts:
4
November 25, 2015

This worked perfectly. Thank you!

Posts:
1
December 01, 2015

I tried to add this code to my store, but no luck.  Can't get it to work.  I am using Out of the Sandbox Responsive Theme. Anybody have issues as well?

Posts:
8
December 04, 2015

Can't get it to work either. The strange thing is that on the checkout page the session is still there i can see the value being passed, it just won't apply it to the total. Not sure why.

Posts:
34
December 09, 2015

Hi Greg, when you click the checkout button is it successfully redirecting you to https://checkout.shopify.com/NumbersHere/checkouts/ABunchOfVeryLongNumbersHere&discount=YourDiscountCode

The important part is in bold.

The session value will persist regardless but unless it is actually adding the discount code to the URL when you click the checkout button it won’t actually apply it.

Posts:
8
Last edited December 09, 2015

No, my url looks like this:

https://www.mysite.com/9116592/checkouts/d71243518d89a6458894dcc85dbd2fee?_ga=1.36051235.2030356943.1442252627

(note that I have a Shopify Plus account so the url is not checkout.shopify.com) but it shouldn't change anything.

I do have this code in my cart.liquid

<form action="/cart" method="post" id="cartform" class="cartform">
      
          <!-- BEGIN: Autofill Discount via URL, with IIFE. PART 3 -->
          <script>

              (function() {
                  /* If the length of sessionStorage "discount" is NOT 0 then add our sessionStorage value to the end of our Checkout link */
                  /* Link: http://stackoverflow.com/a/4704786 */
                  if (sessionStorage.getItem("discount").length != 0) {
                      document.getElementById('cartform').action = "/cart?discount=" + sessionStorage.getItem("discount");
                  };
                  console.log("discount = " + sessionStorage.getItem("discount"));
              }());

 </script>
          <!-- END: Autofill Discount via URL, with IIFE. PART 3 -->

         

Posts:
34
December 09, 2015

That tells us it’s not adding the discount code to the URL like it should be, so now we just need to figure out why.

Does the form that holds the contents of your cart have an CSS id of cartform? I’ve attached an example of my code. You need to check the source code of your CART page. If the CSS id of your cart is NOT cartform then you will need to change the line in the javascript code from this:

 document.getElementById('cartform').action = "/cart?discount=" + 

to this

 document.getElementById('YourCartIDGoesHere').action = "/cart?discount=" +

 

Here’s what the code looks like on my cart page:

Posts:
8
December 09, 2015

yes you can see in my code above i have

<form action="/cart" method="post" id="cartform" class="cartform">

 

Posts:
34
Last edited December 09, 2015

Sorry, it’s been a long week…I should have noticed that at the top.

The code you posted above should have had the discount value appended to the form action parameter if everything was working properly, so as far as I can tell that’s where we should start looking.

I’ll have to look at this some more tomorrow but on quick glance you have a few odd characters in your code.

<!-- BEGIN: Autofill Discount via URL, with IIFE. PART 3 -->

<script> = $0

What is the = $0 part?

Posts:
8
December 09, 2015

I don't see "$0" anywhere

Posts:
34
Last edited December 10, 2015
g
1
upvotes

Take a look at the video below. Looks like the problem has something to do with the fact that you have 2 separate Checkout buttons on your cart page. The first checkout button in your code (the one that shows whenever you hover over the cart text at the top of the page) actually works as expected.

Link to video: https://vid.me/WhVg

Posts:
8
December 10, 2015
g
1
upvotes

Oh wow thanks so much man, never thought about that, great debugging skills! I'm wondering why the cart button on the cart page won't pass the variable, that's where I put the code in. Let me investigate and I'll get back to you ;)

Thanks again, this issue was driving nuts.

Posts:
8
December 10, 2015

Ok I got it work! I had two cartform ids on my page because of the 2 checkout buttons so i did this:

if (sessionStorage.getItem("discount").length != 0) {
   document.getElementById('cartform').action = "/cart?discount=" + sessionStorage.getItem("discount");
   document.getElementById('cartform-mast').action = "/cart?discount=" + sessionStorage.getItem("discount");
};

and now it's working!

Thankyou

Posts:
34
December 10, 2015

Awesome! Way to go, Greg. Glad you got everything working correctly.  - Mark

Posts:
12
Last edited January 05, 2016

Thanks a lot, this is what I had been looking for. I've made 2 adjustments though to make it work (using the Kickstand template):

  1. I've removed the hidden input on step 1 and 2. Reasoning: the code that's added in `theme.liquid` gets executed both on the homepage and on /cart. When accessing the homepage with the discount code as parameter, all works fine, but (at least with the Kickstand template) when clicking on the link to the Cart, the discount parameter is not set anymore in the URL. And because `$("#discount_input").val() != urlParams["discount"]` the value in the sessionStorage gets reset to an empty value.
    So I've gotten rid of the hidden input, now whenever a discount value is given it gets set and remembered for the length of the session in the sessionStorage. If the page gets called with a different discount code, that new discount code is what gets remembered. Because the JavaScript code to handle the hidden input is gone, step 2 in the original post is not needed anymore.
  2. The default Kickstand template's cart page comes with a form that has no `id` set, only `name`:
    <form action="/cart" method="post" name="cartform" class="clearfix">
    So I've had to change the third step to be
    document.getElementsByName("cartform")[0].action
    instead of
    document.getElementById('cartform').action

 

I'm coming from the angle of supporting discount codes not only as actual discount codes, but also as affiliate codes, and thus want to display a message of the type "Welcome to the listeners of the Mixergy podcast." on the homepage, and on the cart page a "Your 20% discount is not shown here, but will be applied on the next step" messages. I'll most likely create a new forum thread (linking to this one) when I've got that code as user-friendly as I want.

Anyway, thanks, thanks a lot Mark-RX for sharing this step-by-step!

Posts:
9
February 09, 2016

This is really good work I'm trying to figre out the best way to get this to work with cart.js for the Parallax theme making this work in the ajax cart without the need for a page reload.

Does anyone know what javascript would need to be in the code below to append the discount code onto <form> url="checkout/" </form> when the cart is updated?

 

$(document).on('cart.requestComplete', function(event, cart) {
    // Event handling here.
});

I believe the code above listens for cart updates thefor I would need some code that looked to see if the cart total is grater then 1999 if so append the discount code to to <form> url. 

rvtech Member
Posts:
2
April 22, 2016

Hi, I am working with same app , evertything is working fine even form action is also showing 

<form action="/cart?discount=twopercent" method="post" id="cartform">

discount querystring but after that when its redirecting to checkout page, discount is not automatically applying on price and its not working. Please help to resolve this issue.

Alicia W Shopify Employee
Posts:
346
April 22, 2016
g
1
upvotes

If anyone is uncomfortable implementing this and can't afford to hire an expert at the moment, I just wanted to pop-in and let you know there is an app that can help facilitate: https://apps.shopify.com/autofill-discount-from-url

But amazing guide! I'm going to be bookmarking it for myself. ;)

Alicia | Support Lead for Shopify
Posts:
196
April 22, 2016

@rvtech Is twopercent an active discount in your store? Also, what is your store url? That will help us investigate your issue. 

Stop Stressing About Shopify You’ve Got Better Things To Do =&gt; https://320ny.com/shopify/
Posts:
2
May 09, 2016

Ok this all looks pretty straight forward. My quesion is how do I create the discount codes/urls themselves?

 

Posts:
995
May 09, 2016
Modification &amp; Repair of Themes&amp;settings, CSS,javascript,(coming soon apps) http://www.krop.com/paulnewton/ paull.newton+shopifyforum@gmail.com
Posts:
2
Last edited May 09, 2016

ok thanks Paul

I thought this should pull from our discount codes that we created in the admin panel.

 

I have gotten the discount to work if I set this line  <input id="discount_input" type="hidden" name="discount" value=" "> to a specific discount code in ("name="10percentoff" for example). How do I get this to automatically apply the discount code from the url? 

Maybe I missed this in the thread... but i'm not sure I saw anything about it.

Posts:
34
Last edited May 09, 2016

Hi Valeriy, I would start completely over and make sure you are reading through every part of this tutorial correctly and that you understand what the code is actually doing. If any of these steps are confusing I would very strongly recommend hiring a Shopify Expert [I’m not one!] to help out. The whole point of this tutorial is to have the customer click a link, which then stores your discount code [which you should have already created on your Shopify backend] and applies it to the Shopify checkout URL once the customer reaches checkout. Manually hard-coding your discount into your website code [if that’s what you’re doing] defeats the whole purpose of the tutorial.   ;)

Posts:
995
May 09, 2016

Valeriy Volkov, hopefully all is right and you just have to read over this tutorial, but if you want to delegate and finish  then this is one of the customizations I provide, reach out to me by the email in my signature.

But if you do everything to the letter and still get problems remember to provide a storefront password so forum volunteers can take a look.

Modification &amp; Repair of Themes&amp;settings, CSS,javascript,(coming soon apps) http://www.krop.com/paulnewton/ paull.newton+shopifyforum@gmail.com
Posts:
14
June 07, 2016

Thanks for this share -- 

Unfortunately, on the Retina theme, no love.

I made the edit to the cart script, to match the form id

document.getElementById('cart_form').action = "/cart?discount=" + sessionStorage.getItem("discount");

But still no love.

I also tried the two apps that claim to accomplish this, neither worked.

Anyone get this working with Retina (or other Out of the Sandbox theme) ?
Thx

 

Posts:
57
Last edited August 04, 2016
g
2
upvotes

Hey guys, I read all this thread and felt so much the pain that my team and I've decided to build it. Stop struggling with code or coupon code, try this free app instead: https://apps.shopify.com/automatic-discount-rules. The difference between our app and the one mentioned by the Shopify employee above is that it works :) You can apply a discount automatically from a link (Discount URL), but also based on the cart content (amount spent, total number of items or similar items, weight of the order and more to come based on your feedback). That means you can create discounts for customers buying more than $X or buy 2 items and get the 3rd one for free or if your order is really heavy, you get X% off. The app is in beta and we already received great feedbacks for future features. Check this out: https://apps.shopify.com/automatic-discount-rules

Shopify appstore featured thumb
Posts:
14
August 04, 2016

Hey Derek,

Thanks for building this.
If anyone can't clck the link to the apps.shopify link, there is probably a trailing space in the link.

I did not have positive results with this with the Retina theme. Derek, you've got mail.
thanks.

Posts:
57
Last edited August 04, 2016
g
1
upvotes

@Jeremy thanks for noticing the bad link to get the Automatic Discount app :D We are currently testing on the Retina theme and on testing via the console on your site. We found the bug and fix it. By the way, here's the good link to the free app: https://apps.shopify.com/automatic-discount-rules 

Feel free guys to test all the features, including the automatic discounts based on what's in the shopping cart, and give us more feedback, it really helps :D

Posts:
7
Last edited August 24, 2016

We just updated our coupon app to allow you to add the coupon directly in your 

Shopify store URL. For example yourshopifystore?coupon=CouponName 

Here is a link to our app:

https://apps.shopify.com/exit-intent-coupon-popup

We have other features to show off your coupons with popups too and background images.  We have a free version too that you can try and a one week free trial of the premium version.  Would be great to get some feedback!

Posts:
2
Last edited September 22, 2016

Good solution, people. Thanks for posting!

Question: is the Github project the most up to date per @Jason & @Ryan's suggestions?

https://github.com/dilloninstruments/shopify-autofill-discount-from-url

Posts:
1
Last edited October 06, 2016
g
2
upvotes

I appreciate everyone's work on this. Unfortunately SessionStorage (like LocalStorage) doesn't behave in either Chrome's Incognito or Safari's Private Browsing modes. Plus, the code is a bit more complex than it needs to be. So I made this: https://gist.github.com/ccashwell/38cc80a977adaf1777fc6668bd438f28

In short, it uses a cookie instead of browser storage to stash the discount code and does away with the hidden field business.

<script>
  /* Put this in theme.liquid, preferably right before "</body>" */
  (function() {
    var discountParam = document.location.search.match(/discount=(\w+)/);
    if (discountParam && discountParam.length > 1) {
      document.cookie = discountParam[0];
    }
  })();
</script>
<script>
  /* Put this in cart.liquid, preferably at the bottom of the file.
   * Also, make sure your cart's "<form>" has an ID of "cartform".
   */
  (function() {
    var discountCookie = document.cookie.match(/discount=(\w+)/);
    if (discountCookie && discountCookie.length > 1) {
      document.getElementById('cartform').action = '/cart?' + discountCookie[0];
    }
  })();
</script>

Note: This won't work as expected with discount codes containing non-alphanumeric characters. Codes should be something like "FALL10" or "OMGSecretCodesAreAwesome", not "SAVE10%" or "FREE$HIPPING".

Posts:
3
11 months ago

Some great instruction, thanks for putting all these work together, very helpful.

ready, steady, go ...
Posts:
4
11 months ago

@Chris Cashwell

Your code snippet worked like a charm! Thank you much.

@Jeremy Roberts

I use Retina theme too, I applied Chris's solution and a bit more customization and it works. Let me tell you how,

 

1- Apply whatever Chris says

2- Change the second part of his code(as he menditoned for ID) a bit because retina theme's cart form id is "cart_form". So the code you should put in your cart.liquid would be this;

<script>
  /* Put this in cart.liquid, preferably at the bottom of the file.
   * Also, make sure your cart's "<form>" has an ID of "cartform".
   */
  (function() {
    var discountCookie = document.cookie.match(/discount=(\w+)/);
    if (discountCookie && discountCookie.length > 1) {
      document.getElementById('cart_form').action = '/cart?' + discountCookie[0];
    }
  })();
</script>

3 - In retina there are 2 checkout forms. So when you add a product, a form(pop up) would appear on the right side of the screen and if you click checkout on that, it wont apply the discount code. This code will only apply the discount code when you go through Add product -> Edit Cart -> Checkout. In order to solve that you should copy paste the following code in your theme.liquid at the very end.

<script>
  (function() {
    var discountCookie = document.cookie.match(/discount=(\w+)/);
    if (discountCookie && discountCookie.length > 1) {
      document.getElementById('cart').action = '/checkout?' + discountCookie[0];
    }
  })();
</script>

On that form, the action is "/checkout" and the ID is "cart".

Hope this helps, at least its working for me. YAY!

Posts:
1
11 months ago

This was extremely helpful and will be a great addition to our tripwire page after our customers opt-in to any of our free content.

bolle Member
Posts:
18
9 months ago

Anyone able to get this figured out with the Ajax Form? 
I try changing the form action URL like the above examples, but the action won't change. 

This is the right drawer in the Fashionopolis theme I'm talking about.

ChandanKuila Member
Posts:
1
9 months ago

Thanks for the refrence.

It works 100%

KR Member topmunch.com
Posts:
2
7 months ago

This thread has grown too large to take a conclusive code out. Can anyone volunteer to please put together a final version of a generic script on a gist? It will be highly appreciated. Thanks a bunch!

Posts:
1
5 months ago

Any volunteers?  

 

Also woudl there be any differences on the parallax theme?

Posts:
2
Last edited 3 months ago

Hey@KR, @Kevin Seele,

Chris Cashwell already provided a final resolution only a couple posts up from you, and you can see the updated code here: https://gist.github.com/ccashwell/38cc80a977adaf1777fc6668bd438f28

@Chris Cashwell, + others who might be able to answer

Please note that I'm an extreme novice when it comes to web development. The only code(if you can even call it that) I write is in SQL, or VBA.

  • Is there a way to avoid the messaging stating that the discount code is not valid or has already been used if the value of the discount code = "MYDISCOUNT_CODE10"?

Thanks for everyone's time!

 

Posts:
1
about 2 months ago

In the current era, it is important for a business to have a presence on the World Wide Web. Due to such a shift in trend, every small business is coming up with a website which would help them in promotional activities. Then why there is a need in designing and development of your website? 

In order to design and develop the websites, apart from using HTML and CSS codes, we also use different CMS (Content Management System) website development platforms like 
•    WordPress Development
•    Joomla! Development
•    osCommerce Development
•    Magento Development
•    Zen-Cart Development etc.
At www.webdesigncity.com.au before starting a project, a complete analysis is done and strategies are prepared so as to make out teamwork accordingly to deliver a flawless project. We make your website run flawlessly without any glitch as we provide a complete solution to website maintenance and support. We also guarantee success when it comes to ranking in the search engines by analyzing the keywords with respect to the project. Thus, steer your business towards fame, recognition, profitability and our team will help you to achieve the goals.

Web Design Sydney City is a professional name in the field of design and development in Australia and we help you create a online solution that is capable of reaching out to your target audience and creating a positive impact on them. http://www.webdesigncity.com.au/
Posts:
2
about 1 month ago

I know many of you in this thread are JS wizards, but for those who are not:

There's a pretty powerful app that does this nicely (and has a free version):

https://apps.shopify.com/discount-url

If there's an app for it, why code it yourself right?