Decoding payment error codes - and earning user trust

Role: UX writer + content designer
What: Booking.com, Flights, all platforms

The problem space: Data tells us failed bookings due to payment rejections are seldom recovered, even though the user has made the choice to transact. An audit of the existing flow on all platforms shows many gaps in the frontend experience. Is there information on the backend that can help fill them, or do we have a tech problem? Turns out, a bit of both.

Hypothesis: If we tell the user what went wrong with their payment, and allow them to retry on the payment screen itself, they’ll be more likely to complete their booking

The before: less-than-ideal UX

  • In most cases, a payment error immediately led to ‘failed’ confirmation screen

  • Going back to try again bumped users to the beginning, with nothing saved

  • The user’s endpoint, the ‘failed’ confirmation screen, mentions a potential payment error, but doesn’t provide a way forward. We also do not confirm whether or not the user was charged.

  • Yikes

In one case on the backend (if the bank refused the transaction), we were showing an error banner (below). This is problematic because:

  • We’re placing blame on ‘something else,’ but we don’t sound very empathetic apart from ‘unfortunately’

  • We use a red warning icon indicating something went wrong, but we don’t explain what happened to the booking

  • Despite the newly appearing error, the user still has a dead-end

  • Yikes again

What I did:

  • Collaborated with engineers to investigate payment error codes, and what we were receiving

  • Groupd the error codes into common, user-friendly scenarios

  • Wrote new, contextual, and user-friendly messages for each group

  • Got legal approval on whether we can contextualize payment-related language, and by how much. This was a more productive discussion with prewritten messages they could react to, despite having to scale a few back.

  • Worked with engineering and design to define the UX requirements for ‘trying again’ - how many attempts could a user make before landing on an official ‘failed’ page? What does the experience look like? What content was missing before, during, or after a user taps the ‘Pay’ button

  • Localized into 45 languages, keeping tone and sensitivity in mind. Some languages prefer not to sound conversational or apologetic when it comes to transactional moments. And that’s okay, as long as we’re consistent.

Error code grouping with engineers

The after:

  • On-the-spot recovery - the user can make the fix on the same screen

  • Functional, yet friendly - keeping in the punchy and relatable tone-of-voice, but explaining what caused the error, in plain terms

  • Copy that leads with action - the user should read the error message and know what they can do

  • Ease of use - no back navigation required to retry, and less guesswork for the use

Two of five new messages

How I scaled beyond the MVP: Because UX is a perpetual cycle of improvement, I asked myself how else can I apply contextual errors to the end-to-end flow. I started with an audit, and worked out three must-do next steps.

  • 1. Expand the scope of what we already did - can we better signal something is loading, especially considering the user’s payment is processing in the back ground. Can we make the confirmation screen more personal and emotional? The answer to these is yes.

    • Not only did I write a new ‘payment loading’ state, I also split the logic so this use case felt seen and heard. Since they’re recovering from a payment error, I’ve said ‘We’re giving it another go.’

  • 2. Look beyond payments - using the hypothesis that users need visual and contextual cues of things ‘moving or changing’ in the background, where else can we apply this UX approach? I began to design similar improvement strategies for: form field errors, empty searches/empty states, outages, and all loading states.

    • I’m particularly proud of my loading state content strategy, titled ‘What Is Happening?’ Not only do users stick around when you tell them something is loading in the background, they also trust you enough to transact!

  • 3. After we built the payment loading state, could we still optimize further? Which messages performed better? Can we hypothesize why? Do we need to test alternative designs?

Friendly loading message

Before and after: contextual outage message with a clear, positive action