Checkout field validation tips and tricks

Our previous post discussed what we did to improve our checkout page. In this post I’ll share with you some of the technical work we did in that process and mostly: the libraries and techniques we used for checkout field validation. We’ve tried several libraries in the process but settled on these as they were the easiest to implement and the most robust.

A lot of our ideas for form design were taken from Luke Wroblewski’s awesome classic on form design: Web Form Design, Filling in the Blanks.

Credit Card validation

The first thing we decided that we should fix was our inline credit card field validation. Entering credit card info is something a user can easily make a mistake in. As a result the earlier in the process you spot that mistake, the better it is. We started using Stripe for our payment processing (Stripe is awesome, absolutely freaking awesome) and while searching for a good library to validate credit card fields we stumbled upon one of Stripe’s projects: jQuery.payment.

If you know a little bit of jQuery, this plugin makes it ridiculously easy to both format and validate credit card form fields. Let’s start with formatting the form fields nicely: we want a nicely formatted number that is limited to 16 numbers. It’s as simple as doing this:


This makes sure the numbers are grouped into sets of 4. But you only see that once you start typing, and we wanted it to be immediately obvious that that’s the field you need to enter your credit card info in. So we added a placeholder attribute to the input field”

placeholder="•••• •••• •••• ••••"

We also did a bit of CSS trickery to add a credit card icon to the right of the input field, to remove the last bit of confusion:

input#card_number {
  background: url('images/placeholder.png') 175px 4px no-repeat;
  background-size: 25px 19px;

Now our credit card input field looks like this when empty:


When we start typing a number into it, it starts validating the number and recognizing which type of card we’re using:

credit card input visa

No I didn’t just give away my credit card number, this is a Stripe test card number. The recognition of the credit card is done by the script automatically, it adds a class to the input field which we use with the following simple CSS: {
  background-image: url('/images/icons/visa.png');

input#card_number.mastercard {
  background-image: url('/images/icons/mastercard.png');
} {
  background-image: url('/images/icons/discover.png');
} {
  background-image: url('/images/icons/amex.png');

Of course there’s more than just a number to a credit card: there’s a name on card field, an expiry field and a CVC code, all of which are needed and need their own validation. We validate the CVC field using the jQuery.payment module as well, I’d suggest reading its extensive documentation on how to best do that for your checkout module.

Inline validation

For validation of the other credit card fields and all non-credit card form fields we used the jQuery validation library. This simple script makes it very easy to define rules for input fields and other types of form fields. It is very well documented, but to convince you to use it, let me show you the rules we use for our checkout field:

  rules : {
    edd_email : {
      required: true,
      email : true
    edd_first : "required",
    edd_agree_to_terms: "required"
  messages: {
    edd_first : "Please enter your first name",
    edd_email : "Please enter a valid email address",
    edd_agree_to_terms: "<strong>Error</strong> - Please accept our terms: ",
    card_name : "Please enter the name on your credit card",
    card_address : "Please enter the billing address of your credit card",
    card_zip : "Please enter the zip / postal code of the billing address of your credit card",
    card_city : "Please enter the city of the billing address of your credit card",
    billing_country : "Please enter the country of the billing address of your credit card"

That’s all. It automatically validates on “keyup”, so when you are editing a field and on submit. As you can see, you can edit the error texts yourself, we show them like this:

email validation error

It’s really very simple to use, so go and play with it.


The jQuery.payment and jQuery.validate libraries have significantly (a word we don’t use lightly at Yoast these days) increased our conversion. There’s no valid reason left not to have proper validation on form fields with simple libraries like these being available. So go and implement them! If you have more tips for form validation: let us know in the comments!

13 Responses

  1. Bjorn
    By Bjorn on 12 November, 2013

    The downside of this plugin that server side validation is another piece of code which needs to be maintained. Not very DRY (Don’t Repeat Yourself).

    What might be a nice addition to your post is to specify classnames as a js hook.
    Elements which trigger js should get a classname js-form-validation, only to be used in JS of course!
    This will help to increase the maintainability of a website.

    • Joost de Valk
      By Joost de Valk on 12 November, 2013

      It’s not possible to prevent doing this both frontend and backend in my view. You need it on the frontend to improve usability and conversion, you need it on the backend for data validity and security. I would do the work to make sure you only maintain the errors in the frontend though.

      On the classname: that’s a very elegant solution indeed.

    • Shane Jennings
      By Shane Jennings on 15 November, 2013

      I’d go so far as to say this doesn’t violate DRY, since both purposes are distinct and the code is in two code bases. DRY only applies to what is repurposable Not to mention one of the advantages of using third party libraries is all you have to “maintain” is use of the api, which typically honors backwards compatibility. A few tests can give you a high level view of the state of your library apis across all your sites before deployment, so I think this is more of a concern of 5 years ago, not so much now.

      • Bjorn
        By Bjorn on 15 November, 2013

        Well, I have to maintain the two codebases.
        I noticed proper error handling is very important. And wanted to have the same error messages, frontend or backend.
        As we have 6 languages on our site, I had to make use of translation files. Which would need the same translation as the database driven once. Which means that needs to be converted to php or whatever.

        I found that doing the checks on the server saves a lot of time when adding new checks (regular expressions) or translations.

        • Shane Jennings
          By Shane Jennings on 15 November, 2013

          The point of the library is there are no exposed regexes and the validations themselves are language agnostic in my experience. The specifics are handled via an abstraction layer while the only integration points are high level. To explain my stubborness, I spend my time on js saas architecture, so I tend to see everything through the eyes of reducing server calls and leveraging javascript / cdn layers wherever possible as we get about a petabyte a day of throughput! Point being, good use of abstraction layers / language tokens can make both solutions manageable and I don’t think it’s accurate to say this violates DRY. :)

  2. Robert Abela
    By Robert Abela on 12 November, 2013

    HI Yoast,

    Good article. I would also like to point out that validation is also very important from the security point of view.

    Most of the common exploitable web application vulnerabilities (such as SQL injection and Cross-site scripting) are possible simply because the web application does not have enough or proper validation in place, thus attackers would be able “to inject” arbitrary and execute it.

    By having proper validation in place and filtering the user input you are protecting your website from such attacks. As a rule of thumb I would simply say “never trust the user input”.

    • Joost de Valk
      By Joost de Valk on 12 November, 2013

      We don’t. It’s double work indeed but frontend validation is mostly a conversion optimization / usability thing in my view and backend validation is a matter of data validity and security :)

      • Robert Abela
        By Robert Abela on 12 November, 2013

        Hi Yoast,

        Yeah. If you have backend data validation it still counts as a security measure, well done :)

      • Alan Reeves
        By Alan Reeves on 21 November, 2013

        I agree, having some sort of front end validation is so much nicer for user experience. There is nothing worse that filling out a long, complicated form that is rejected on the back end because you did not format the date or some other field correctly.

        Oh, and the form was completely cleared so you have to type it all in again. The validation library looks like a good step toward helping situation like that.

  3. Bjorn
    By Bjorn on 12 November, 2013

    Well a perfect solution for that is to do frontend validation using a ajax call to the backend. In this case you can write generic code for the backend and use it in frontend and backend. Something we use for a long time already on
    But purely seen as a conversion optimiser, this is a nice plugin indeed ;-)

    • Shane Jennings
      By Shane Jennings on 15 November, 2013

      This ignores scalability, why put load on the servers when it’s not necessary? Proper JavaScript architecture and TDD handles the maintenance of your integration points for you during upgrades. To me, creating the web service, handling the response, etc is just as much work if not more than adding a plugin and a few api calls, that are community endorsed and will grow stronger over time. The jQuery checks very purpose are cosmetic in nature and to keep load off the server from accidental submissions. AJAX validation would defeat the purpose.

      • Bjorn
        By Bjorn on 15 November, 2013

        The server load for some JSON call are minimal. If a server can’t handle that, something is wrong. Even if a lot of accidental submissions are done.
        For a simple site, I would not recommend this indeed.

  4. Bob Rockefeller
    By Bob Rockefeller on 30 November, 2013

    How would I go about turning on native HTML5 form validation for Genesis 2 post comment forms? I appears that they are set to “novalidate” by default.