Pre-populating Shopify Checkout Forms and Other Undocumented Functionality

Bandaids

We’ve been using Shopify at ThankLab and chose them because they’re a hosted solution and have a simple API. However, we quickly uncovered many limitations that required us to come up with workarounds. Some of the issues we had to resolve were a result of integrating Shopify into a third-party website with existing user accounts.

As we dug into documentation on the official Shopify wiki and blog, it became clear that many of the solutions they provide are their own hacks around limitations many customers have run into. This realization was double-edged: Shopify clearly encourages hacking on their platform, but many capabilities or “features” are not really baked into their core product. In the end (frustrations aside), the challenge of making Shopify work for us became an exercise in creativity.

Seamlessly integrating third-party user accounts with Shopify checkout

Our users login to our website and checkout on Shopify. Shopify has these 3 options at checkout:

Shopify checkout options

  • Guest checkout – requires the customer to enter their email address
  • Customer login only – requires email and password to login, however each customer needs to be manually invited via email to create passwords for their account

Goal: pre-fill email address on guest checkout page (and hide email field)

Shopify limitations: Checkout page has a unique URL (is not known ahead of time), does not accept query string parameters to pre-fill form fields, and only allows you to customize CSS.

Get the Shopify checkout URL ahead of time

I kinda lied there a little bit. The checkout page CAN be determined ahead of time, but because the URL has a random looking token in it, it isn’t immediately evident. Here’s an example of my cart on the Penny Arcade store:

Shopify checkout URL


As it turns out, the ID in the URL is your shop ID (429942) and is always the same for all customers. The 32-character ID (c813f407436dc8cdda0c50d58e6d5e96) is your cart token, which is stored in a cookie called “cart”. To get the checkout URL for each customer, you’ll have to use JavaScript:

  1. Get your shop ID from your checkout page URL (simply click “checkout” in your shop)
  2. Create a JavaScript function that can read the “cart” cookie (here’s some code you can use)
  3. Create a JavaScript function that combines everything into a proper URL and do something with it

After combining these steps, you might have some JavaScript code that looks something like this:

var shop_id = "429942";
var checkout_url = "https://checkout.shopify.com/carts/" + shop_id + "/" + readCookie("cart");

We will use this URL to add some parameters to pre-fill the checkout form. Download my example script (shopify_hacks.js) from Github.

Pre-filling the Shopify checkout form

We are now able to determine the Shopify checkout URL ahead of time, but need to pre-fill the form. If you’re familiar with Ruby on Rails or web development frameworks in general, you know that you can typically take the names of form fields and add them to the URL as query string values. Those values are then pre-populated in forms that have fields matching those parameters.

In the case of the checkout form, if you view the HTML source of the page in your browser and find the “input” tags, you’ll find the field for the email address on guest checkout. The name is “order[email]“. Now, when you add that name as a query string value, the checkout URL looks like this:

Shopify checkout URL with email parameter

Unfortunately this didn’t work. The email address is still blank. However, if you submit the form with invalid information (e.g. blank email address), you’ll notice that the cart URL changes. The URL now ends in “create_order”:

Shopify checkout URL for populating form fields

 Now you can see that my email address is pre-populated in the form. You can pre-populate all form fields if you wish. In our case we are only pre-populating the email field and using CSS to hide the table row. This effectively lets our users checkout without re-entering the email address we already know.

Alternatively, use Mechanize to automate creating Shopify customer accounts with passwords

Goal: Create Shopify customer logins linked to third-party user database

Shopify limitation: Shopify customer logins can only be created by inviting a customer (manually) via email, at which point customers can create a password.

Originally wanted to create a Shopify customer account for each user in our third-party database, but Shopify doesn’t let you create customer accounts through the API. For some reason the only way to create a Shopify customer account is to manually “invite” the user via email, which sends them a link to create a password. We ended up automating this process using Mechanize:

  1. Create a Shopify customer using the API
  2. Create a Shopify administrator account that only has access to Customers
  3. Mechanize logs in to shop admin with administrator account
  4. Mechanize retrieves the invite link for a customer
  5. Mechanize visits the invite link and fills out the form to create a password

Pretty simple. However, we felt that this was less reliable than the guest checkout method. This process would also sometimes take up to 7 seconds to complete, and we decided it would add more complexity to our application to deal with this latency, as well as making sure that our users would be logged in to their Shopify accounts behind the scenes reliably (read: posting their Shopify username and password to the login form on Shopify in a hidden iframe).

Download the mechanize script (mechanize_activate_customer_login.rb) from Github. It’s a Ruby script that you can run from the command line. It accepts several arguments and outputs how long each step takes. Make sure to install the Mechanize gem before running the script.

Some other convenient undocumented Shopify functionality discovered

We actually have our own custom cart on a website separate from Shopify. So, when users click the “checkout” button, we need to “copy” the items we have in our cart to the Shopify cart. To do this, we first need to clear their existing Shopify cart and then post all items to Shopify.

Redirect after clearing Shopify cart

To clear a Shopify cart, you visit the “/cart/clear” page. After the cart is cleared, it automatically redirects you back to the empty cart page:

http://store.penny-arcade.com/cart/clear

However, if you want to send your user to a page of your choosing, all you have to do is add that page to the URL as a “return_to” parameter:

http://store.penny-arcade.com/cart/clear?return_to=http://joelvanhorn.com

This parameter is documented for adding products to the cart, but not any other pages. Presumably, you can add the “return_to” parameter to more pages that perform actions within Shopify.

 

Share

Tags: , , ,

12 comments

  1. Wow, that is some inspired hacking. Nice job!

  2. I’m glad we were able to find a solution to make things work for us!

  3. Very cool. I’ve been trying to deconstruct some of the shopify-wordpress stuff on penny-arcade.com. Did you build that?

  4. No, I didn’t. They did an amazing job though!

  5. Thanks man. I spent a long time trying to find a workaround for lack of user accounts (like in the civilized world, not the upside down Shopify world). I finally reached at the conclusion that I’d have them created on a separate website. Then I ran into the problem of populating the fields and thought MAYBE someone’s done that before and here it is!

    You just saved me some time and also in a way showed that keeping user accounts on a separate server is feasible.

    Thumbs up!

  6. I’m glad this post was of help to you!

  7. I’m not seeing a cookie with a name of carts. If I look at all the cookies I see one that definitely belongs to the shopify store, but looks kind of unfamiliar – __utmz=99684509.1344900209.6.2.utmcsr=mystore.myshopify.com|utmccn=(referral)|utmcmd=referral|utmcct=/admin/auth/message

    Any ideas?

  8. Hi Joe,

    It seems Shopify may have changed something recently where the cookie isn’t set until you add something to the cart first. You could try using Shopify’s AJAX library to 1) add an arbitrary product to the cart, then 2) access the cookie, then 3) remove the product and use the cookie value however you need to.

    Let me know if that ends up working for you or if you come up with a different solution.

    ~Joel

  9. Hi, I’m facing a similar situation. I just checked out ThankLabs. Are you still using shopify and the workaround? I want to use Shopify but would like to modify the checkout process (allow account creation before signup, capture email before credit card, etc). It looks like I’d have to maintain a separate server of user accounts. Does this get unwieldly? Thanks.

  10. Hi Kelly,

    We are not using Shopify for ThankLab currently. Shopify was too restrictive at the time as we deal with the same problems you describe. You would indeed have to maintain a separate database with users, and simply pre-fill the checkout form with their email address through a special link. We did this initially, but decided to move away from Shopify in the end.

    Shopify has made a lot of changes in the past months, so I’m not sure if they’ve made any of this easier.

    ~Joel

  11. The ‘cart’ cookie is set by website mydomain.myshopify.com, so it is not accessible for my website.
    The javascript file that creates the checkout url with prefilled data & then redirects is stored on own website.
    So how can I read that cart cookie on my website?

  12. I want to auto populate data such as email & address on shopify checkout page.
    I am not able to access cart cookie & generate checkout page url ahead of time on my website, because cart cookie is set by other domain (ie. xxx.myshopify.com).
    SO how can I genearte this checkout url ahead of time on my website?

Leave a Reply

Your email address will not be published. Required fields are marked *


− 1 = seven

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Additional comments powered by BackType