An HTML attribute potentially worth $4.4M to Chipotle

An HTML attribute potentially worth $4.4M to Chipotle

At 4/19/2024

I recently found myself racing to fill out Chipotle’s online order form before my mother could find her credit card. In the process, I discovered a bug that could cost Chipotle $4.4 million annually.

My parents are retired. They continue to try to pay for meals. I don’t want them to. So we often end up in a competition to see who can pay first.

In this case, I knew I had an advantage. My card details were already stored in the browser. I just needed to use autofill to fill in the form quickly and complete the order before my mother could find her card.

Unfortunately, the form returned errors upon submission:

Chipotle's order form displaying two errors along with text that says 'Change Payment Method.'

At that moment, I was still in a race against my mother’s parental instincts, so I quickly copied my card information from 1Password and completed the transaction.

Later, I wondered if this was a problem with autofill. I’ve written extensively about autofill in the past, and if there was a problem with autofill, I wanted to know about it.

Chipotle’s error messages didn’t give me much to go on. The first error said:

We encountered an error saving your card. Please check your card info and try again.

What? I didn’t ask Chipotle to save my card. I intentionally left that box unchecked.

While this was irritating, my hunch was that this error wasn’t causing the problem. I got the same error if I checked the box. I suspected the second error was what prevented me from buying lunch.

Unfortunately, the second error didn’t provide any useful information:

We ran into an error submitting your order, please try again.

Every time I autofilled the form and submitted it, I got the same two errors. If I didn’t use autofill, the form worked.

Then I noticed something. The credit card expiration date changed after it was filled in.

Video of autofill on the Chipotle order form. Autofill tries to enter 2023 for the year, but it changes to 20 instead.

There was the culprit. My credit card expires in 2023. The field only accepts two digits and instead of 23 to represent 2023, the form received 20.

Now that I could replicate the problem, I wanted to figure out why it was happening. Is it a problem with autofill or with Chipotle’s form?

I enjoy figuring out why browsers aren’t working the way we expect. It’s like a good mystery novel, but one you get to solve. In this case, the first clue I examined was the HTML for the expiration year field:

<input 
    class="form-control payment-control ng-pristine ng-isolate-scope ng-valid-mask ng-empty ng-invalid ng-invalid-required ng-touched" 
    aria-label="expiration year" 
    cmg-cc-expiration-validator="cmg-cc-expiration-validator" 
    cmg-cc-expiration-validator-func="$ctrl.isCardExpired($ctrl.card.expiration)" 
    ng-model-options="{ updateOn: 'default blur', debounce: { default: 500, blur: 0 } }" 
    id="expirationDateYear" 
    name="expdateyear" 
    ng-required="true" 
    ng-model="$ctrl.card.expiration.year" 
    placeholder="YY" 
    autocomplete="cc-exp-year" 
    ui-mask="99" 
    type="text" 
    required="required" 
    aria-invalid="true" 
    style="">
Code language: HTML, XML (xml)

Many of the classes starting with ng-. This is a telltale sign of Angular.

Next, I dug into Chipotle’s JavaScript to look for something that was referencing cmg-cc-expiration-validator which sounded like it might be a key attribute for validation on this field. I found what I was looking for in Chipotle’s app JS file. I’ve pulled the relevant section into a gist for reference in case Chipotle changes in their JavaScript in the future.

Among the 400 lines or so in the validation section, this reference stood out to me:

angular.module('ui.mask', []).value('uiMaskConfig', {Code language: Bash (bash)

An Angular module that masks UI? A quick search found the github repo for ui-mask. Chipotle’s JavaScript code I found earlier appeared to be leveraging this module.

After discovering the ui-mask module, one of the input field’s attributes that I had overlooked earlier suddenly took on increased significance:

ui-mask="99"Code language: Bash (bash)

The ui-mask documentation provides this example:

For example, we use '9' here to accept any numeric values for a phone number: ui-mask="(999) 999-9999"

So ui-mask="99" on the expiration year field is telling the ui-mask module to only accept two numeric values. When autofill tries to enter 2023, this ui-mask only lets the first two characters be entered.

I’m sure there are good reasons why Chipotle is using the ui-mask module. I don’t want to sound like I’m questioning their decisions. I suspect that the module is useful for multiple fields and serves other purposes on the site.

However, for this expiration year field, we could accomplish the same thing using two standard HTML5 attributes:

pattern="\d\d"
maxlength="2"Code language: HTML, XML (xml)

The pattern attribute uses regular expressions to validate that the user’s input matches what we expect. In this case, \d tells the browser we want a digit character. By supplying \d twice, we tell the browser that we want two digits so that 01 will be accepted, but 1 will not.Footnote 1

The maxlength attribute tells the browser how many characters are allowed and will prevent users from typing more than the allotted amount.

To test what would happen if Chipotle’s form used these standards, I opened my browser’s developer tools and edited the expiration year field:

Video of autofill on the Chipotle order form after `maxlength=”2″` has been added using developer tools. It works!

Adding the maxlength attribute to the field fixes the problem. This makes sense. We’re telling the browser, and by extension the autofill feature, how many digits it should use for the expiration year.

Autofill is smart enough to know that if we only want two digits for a year field, that the form needs the last two digits of the year. We just need to tell the browser how many digits we expect.

And we need to tell it in a standard way.

Now that the mystery was solved, I wondered how much this problem might cost Chipotle. The first time I encountered this error—long before the credit card race with my mother—I thought Chipotle’s website was broken. I gave up trying to order online.

How many other people have failed to finish an order because the form doesn’t support autofill and the error messages aren’t helpful?

We know that when people use autofill, they complete forms 30% faster, but we don’t know how many people use autofill overall.

So because we don’t know how many people use autofill, let’s use a conservative number.

Could we calculate how much revenue Chipotle might see from half a percentage point increase in transactions? We might be able to.

In their April 2019 quarterly report, Chipotle revealed that “the company’s relaunched website is attracting 1 million transactions a week on average”. In 2018, Chipotle said that their average online order was “$16 to $17.”

I’m going to use the upper end of that range ($17) for the average online order because that average is over a year old and in July of this year, Chipotle reported that “online sales nearly doubled in the second quarter” and “average check jumped by 3.5%.”

Based on the information in the most recent earnings report, using $17 for the average per online order and 1 million transactions per week is probably a low. That’s perfect for our attempt to make a conservative estimate.

Let’s do the math:

   1,000,000  Online transactions per week
*       .005  Half a percentage point
=      5,000  Equals 5k transactions per week
*        $17  Times average online order in 2018
=    $85,000  Equals $85k per week
*         52  Multiplied by the weeks in a year
= $4,420,000  for maxlength="2"
Code language: Bash (bash)

If fixing autofill caused a half of a percentage point increase in online orders, it would increase Chipotle’s revenue by $4.4 million.

But perhaps half of a percentage point is too high. Let’s use a quarter of a percentage point instead. That’s still $2.2 million.

I’m not sure how low you would need to go before adding the maxlength attribute wouldn’t be worth it.

There are three key takeaways from Chipotle’s order form that you should consider:

Select the correct input type for your field. Use other input attributes such as maxlength, minlength, and pattern to provide additional clues to the browser about what information the field expects.

Add the autocomplete attribute with the appropriate token to tell autofill the purpose of the field. This is now the standard way to support autofill.

Once your form works with autofill, make sure it continues to work by including autofill in your QA process. This will help you identify problems like the one with Chipotle’s form before they impact users.


P.S. Chipotle, if this is helpful, may I suggest you buy my parents’ lunch next time? 🙂

P.P.S. Oh, and if you make $4.4 million off this article, you should hire us to help you with progressive web apps and the payment request API.

Footnotes

  1. Originally I suggested changing the type of field from text to number to force a numeric value. However, Amier pointed out in the comments that number doesn’t accept maxlength. Instead, number expects you to use min and max to set the minimum and maximum values. I did some testing and found that using those values doesn’t solve the autofill issues. That’s fine. We want 01 not 1 for the expiration year which means we’re actually asking for two digits, not a number. Therefore, it makes more sense for the input type to be set to text and use the pattern attribute to constrain the input to digits.  Return to the text before footnote 1
Copyrights

We respect the property rights of others and are always careful not to infringe on their rights, so authors and publishing houses have the right to demand that an article or book download link be removed from the site. If you find an article or book of yours and do not agree to the posting of a download link, or you have a suggestion or complaint, write to us through the Contact Us, or by email at: support@freewsad.com.

More About us