UX Case study
Improving price display through clarity
The number a traveller saw when they picked a hotel and the number they were asked for at the checkout page were not the same. This is the work that took the price apart on the page instead of at the end, and the experiment that measured whether saying more about a price sells more stock.
The key panel in the design. Every line under the room rate is money somebody used to meet for the first time at checkout.
Problem
A price that grew on the way to the till
Findhotel is a smaller player in accommodation. It works the localised markets the largest platforms tend to leave alone, and much of its portfolio is distress inventory: rooms a hotel expects not to sell and cannot list itself without being pushed down the rankings by the bigger sites.
Selling that inventory means winning on price, and the funnel was undermining its own strongest argument. The price shown when somebody chose a room was not the price they were asked for two screens later in the funnel. Data showed a large drop-off of users concentrated in the checkout page.
The gap was widest for travellers outside the United States, because that is where the extra lines live: a city tax collected by the municipality, a resort fee collected by the hotel, other local charges that vary street by street. None of it was hidden on purpose. It simply appeared late, unnamed, and all at once.
Two arguments pointed the same way for once. The business wanted a higher conversion rate. I wanted our users to be able to answer the question what am I paying for and why without opening a second tab.
Deal details, the one screen in the funnel whose entire job is to answer that question.
Goals
What the work had to do
Price display sits on the revenue path of every booking the company takes, so a change to it is a change nobody can be relaxed about. Being able to point at a staged rollout was what made the conversation possible at all.
Team & audience
Who did what
The product owner brought the business case and set the priorities. The data scientist supplied the numbers the decisions rested on and designed the A/B tests that measured them. A copywriter owned the wording of every label. A third-party agency translated that wording into the languages the site runs in.
Everything between the problem and the handover was mine: the benchmark, the ideation and scoping sessions, the wireframes and the prototype, the guerrilla tests, the development plan, the high-fidelity screens, the manual testing before release, the watching afterwards, and the write-up that let anybody else in the company follow what had changed.
Audience
Who we aimed at, and in what order
The first release went to American travellers arriving from Google hotel ads onto the room selection page. That was the largest and most valuable group on the site, which made it the audience worth improving and the audience worth being careful with.
Once a hypothesis had survived, the change went out to the rest of the English-speaking markets, and only then to the twenty-six other languages the site supported at the time. Each step was a smaller bet than the one it followed was worth, which is how a team is allowed to touch the revenue path more than once.
The group we aimed at first is not the group the result came from.
Scope and constraints
What we could reach, and what we could not
The company was organised so that the room selection page and everything after it belonged to us, meaning that the search and landing pages did not. That is a hard boundary drawn through the middle of the problem: a traveller forms their expectation of the price on a screen we were not allowed to change, and then meets ours.
There was also no budget for moderated testing. A handful of customers were called, but the purpose of those calls was to collect what they already disliked about the current experience, not to put a prototype in front of them. So the qualitative half of this project is a benchmark and a set of session recordings rather than a study.
The first card is the one worth dwelling on, because it is the difference between a change to a screen and a change to a product. A price breakdown that is only fully visible at the moment of payment is not honest; it is a disclosure. So the same rows had to survive past the point where the money moves, into the screen that confirms the booking and the email that follows it.
This wireframe is where that was settled. It is the confirmation screen, carrying the identical breakdown the checkout carries, with two additional lines that checkout did not have: what has already been paid, and what the property is still going to collect. Everything later in this page is downstream of that decision.
Confirmation, wireframed. The breakdown does not stop at the payment, and the currency placeholders in the small print are there because it had to be true in every market too.
Process
Nine steps, repeated every iteration
This was never one project with an end. It is a loop that has run several times, and each pass leaned on whichever of these steps the product needed most at that moment. The benchmark is the exception: it was done thoroughly once and consulted afterwards.
Mapping where a price appears
A rough diagram of the interactions a traveller can have with a price and what follows from each. It is not a complete account of every state the funnel can be in, and it was never going to be. What it buys is the edge cases you can see in advance rather than the ones a developer finds in a sprint, and a shared object to point at when somebody asks whether we thought about a very specific edge case.
Benchmarking eight platforms in seven countries
It started as one question with a complex answer: what do other platforms include in the nightly price?
Answering it honestly meant deciding who to compare against, where, and under what booking. So: Findhotel against Expedia, Booking, Agoda, Skyscanner, TripAdvisor, Airbnb and Kayak, because those are the ones the company already measured itself against. In the Netherlands, Germany, the United Kingdom, Australia, Belarus, Indonesia and Israel, because those are the markets where our own price display rules already differed.
Comparable results need a control, so every search was the same search: Park Plaza Victoria in Amsterdam, one adult, one room, for the night of 13 October 2020, a hotel chosen precisely because it carries both a city tax and a tourism fee. The searches themselves were run in September, a month out, which is roughly when somebody books a city break. A second pass asked for two nights, 13 to 15 October, in the five markets where the first pass had raised a question. Where a platform did not carry that hotel, the nearest equivalent was used and the substitution written down.
Vendor includes general tax in nightly rate?
Yes, from the search results onwards
No, only at checkout
Names the base rate and the total together
Vendor includes local tax in nightly rate?
Yes, from the search results onwards
No, only at checkout
Names the base rate and the total together
Two questions, asked at every platform
Does the nightly rate include the general tax – the sales tax the platform itself collects?
Does the nightly rate include the local tax – the city or tourist tax the destination collects?
- Included from the start
- Revealed in checkout
- Inconsistent
- Stated separately
Two searches, one hotel
Search 1 · 1 night
Park Plaza Victoria Amsterdam, 13–14 Oct 2020 · 1 adult, 1 room
Airbnb used a different hotel here; TripAdvisor didn’t carry this one at all.
Search 2 · 2 nights
Same hotel, 13–15 Oct 2020 · 1 adult, 1 room
Airbnb, Skyscanner and TripAdvisor didn’t carry it either; another hotel stood in for all three.
| Local | General | |||||||
|---|---|---|---|---|---|---|---|---|
| Market | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately |
| GermanyDE: Germany | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| NetherlandsNL: Netherlands | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| United KingdomUK: United Kingdom | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| AustraliaAU: Australia | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| BelarusBY: Belarus | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| IndonesiaID: Indonesia | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| IsraelIL: Israel | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| Local | General | |||||||
|---|---|---|---|---|---|---|---|---|
| Market | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately |
| GermanyDE: Germany | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| NetherlandsNL: Netherlands | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| United KingdomUK: United Kingdom | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| AustraliaAU: Australia | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| BelarusBY: Belarus | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| IndonesiaID: Indonesia | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| IsraelIL: Israel | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| Local | General | |||||||
|---|---|---|---|---|---|---|---|---|
| Market | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately |
| GermanyDE: Germany | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| NetherlandsNL: Netherlands | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| United KingdomUK: United Kingdom | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| AustraliaAU: Australia | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| BelarusBY: Belarus | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
| IndonesiaID: Indonesia | Not recorded | Not: Included from the start | Revealed in checkout | Not: Inconsistent | Not: Stated separately | |||
| IsraelIL: Israel | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Stated separately |
More platforms
| Local | General | |||||||
|---|---|---|---|---|---|---|---|---|
| Market | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately |
| GermanyDE: Germany | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| NetherlandsNL: Netherlands | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| United KingdomUK: United Kingdom | *Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | *Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| AustraliaAU: Australia | *Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | *Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| BelarusBY: Belarus | Not: Included from the start | *Revealed in checkout | Not: Inconsistent | Not: Stated separately | Not: Included from the start | *Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| IndonesiaID: Indonesia | Not: Included from the start | *Revealed in checkout | Not: Inconsistent | Not: Stated separately | Not: Included from the start | *Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| IsraelIL: Israel | Not: Included from the start | *Revealed in checkout | Not: Inconsistent | Not: Stated separately | Not: Included from the start | *Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| Local | General | |||||||
|---|---|---|---|---|---|---|---|---|
| Market | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately |
| GermanyDE: Germany | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| NetherlandsNL: Netherlands | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| United KingdomUK: United Kingdom | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| AustraliaAU: Australia | Not: Included from the start | Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| BelarusBY: Belarus | Not: Included from the start | Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| IndonesiaID: Indonesia | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| IsraelIL: Israel | Not: Included from the start | Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| Local | General | |||||||
|---|---|---|---|---|---|---|---|---|
| Market | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately |
| GermanyDE: Germany | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| NetherlandsNL: Netherlands | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| United KingdomUK: United Kingdom | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| AustraliaAU: Australia | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately |
| BelarusBY: Belarus | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately |
| IndonesiaID: Indonesia | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately |
| IsraelIL: Israel | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| Local | General | |||||||
|---|---|---|---|---|---|---|---|---|
| Market | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately |
| GermanyDE: Germany | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| NetherlandsNL: Netherlands | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| United KingdomUK: United Kingdom | *Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | *Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| AustraliaAU: Australia | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately |
| BelarusBY: Belarus | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately |
| IndonesiaID: Indonesia | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately |
| IsraelIL: Israel | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately | Not: Included from the start | Not: Revealed in checkout | Inconsistent | Not: Stated separately |
| Local | General | |||||||
|---|---|---|---|---|---|---|---|---|
| Market | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately | Incl.: Included from the start | Held: Revealed in checkout | Mix: Inconsistent | Split: Stated separately |
| GermanyDE: Germany | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| NetherlandsNL: Netherlands | Not: Included from the start | Revealed in checkout | Not: Inconsistent | Not: Stated separately | Not: Included from the start | Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| United KingdomUK: United Kingdom | *Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately | *Included from the start | Not: Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| AustraliaAU: Australia | Not: Included from the start | Revealed in checkout | Not: Inconsistent | Not: Stated separately | Not: Included from the start | Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| BelarusBY: Belarus | Did not appear to sell into Belarus that month. | |||||||
| IndonesiaID: Indonesia | Not: Included from the start | Revealed in checkout | Not: Inconsistent | Not: Stated separately | Not: Included from the start | Revealed in checkout | Not: Inconsistent | Not: Stated separately |
| IsraelIL: Israel | Not: Included from the start | *Revealed in checkout | Not: Inconsistent | Not: Stated separately | Not: Included from the start | *Revealed in checkout | Not: Inconsistent | Not: Stated separately |
* Added the nights together only at checkout – search and room selection still quoted them one at a time.
The finding is in the two starred rows. Airbnb and Expedia were the only platforms that answered both questions the same way in every market, and the answer they gave was neither yes nor no: they name the base rate and the total at the same time. Everyone else, Findhotel included, picked one number and hoped it was the right one for that country.
The board also records what did not work. Skyscanner's figures did not add up, and TripAdvisor did not appear to sell in Belarus at all.
The table below displayed their prices in November 2020 for a single and multiple rooms.
Use a coupon, credit, or promotion code
Rates are quoted in US dollars. Taxes and/or property imposed fees of $15.70 will be collected by the property in the local currency (€13.34). Taxes and/or fees due at the property are based on current exchange rates, which may vary at time of travel.
Use a coupon, credit, or promotion code
Rates are quoted in US dollars. Taxes and/or property imposed fees of $60.56 will be collected by the property in the local currency (€51.47). Taxes and/or fees due at the property are based on current exchange rates, which may vary at time of travel.
Thu 22 Oct 2020Check-out
Fri 23 Oct 2020
FREE cancellation before 23:59 on 20 October 2020
No payment needed now. You’ll pay at the property.
Included in price: Hotel tax and service fees € 4.95
Not included in price (collected by the property): City Tax € 3.85
YOU SAVED € 353.76 ON THIS BOOKING!
14% OFF TODAY
Included in price: VAT 9%
Not included in price (collected by the property): City Tax € 12.50
YOU SAVED € 15.96 ON THIS BOOKING!
🚗 Free cancellation
Book now. Pay later when you stay.
Free Cancellation until Oct 18, 2020 ⓘ
Non Refundable ⓘ
1 room, 2 guests, 2 nights
Fri 09-11-2020 - Sun 09-13-2020
Charges
€288.70
2 rooms, 4 guests, 2 nights
Fri 09-11-2020 - Sun 09-13-2020
Charges
€407.12
USD 88.00
(US$44.00/night x 2 nights)
Learn moreRefundable until Oct 02, 2020
Price
USD 79.29
(US$79.29/night x 1 night)
Learn moreNon Refundable
Additional Fees (Pay at Hotel)
Taxes and fees may vary upon arrival
Check-out: Wed, Oct 141 night
Taxes due at hotel: ≈ €53.72
Prepay Online
An online prepayment of €138.04 is required to book this room.
Included in the price: Breakfast not included
other tax and fee
(Local currency: US$225.58)
Taxes and fees may vary upon arrival
130 Trip Coins = €1.11
Best stay with free cancellation
for 1 room, 2 guests, 1 night
including taxes and fees
Superior Twin Room 👤👤
Free cancellation
Executive Double Room 👤👤👤
Free cancellation
for 2 rooms, 5 guests, 1 night
including taxes and fees
(30,34€)
*Prices are quoted in CAD based on the current exchange rate. The amount due at the property is payable in EUR.
Those seven images represent the raw material the matrix was read off. Each is one country's whole landscape captured in a single pass, which is also why the study has a date on it: this is what these sites looked like in September 2020.
Ideation, then scoping it down
I ran the ideation sessions, and the benchmark is what made them worth running. Walking a team through what eight competitors do to the same booking is a faster way to establish what is possible than any opinion. It moves the conversation from opinions about price to observations about prices.
Scoping followed each session, with the product owner and the data scientist. Two questions, always in this order: "What would the right answer look like if nothing were in the way of development?", and "What is the smallest piece we could develop to put in real traffic?". The gap between those two answers made the roadmap.
A prototype cheap enough to argue with
The wireframes became a clickable prototype, kept deliberately rough. The audience was stakeholders and anybody in the company with a stake in the outcome, and a finished-looking screen invites a conversation about how finished it looks. A grey one invites a conversation about the price.
Then guerrilla testing, which here means grabbing whoever was available and watching them try. It does not replace a study and it was never offered as one. It catches the obvious, and it generates the questions that go back to the team as real research: what happens when the currency of the traveller is not the currency of the provider, what happens across several rooms, what happens when the fee is larger than the room.
The whole flow on a phone, banded by stage, in the form it was first argued about. It runs past checkout into the emails, booking management and cancellation.
Turning it into tickets
A diagram of the happy path and the edge cases that matter, each branch carrying the screen it produces. That drawing is what a product owner writes tickets from. It is also the artefact I go back to in step seven, when the question is whether the build does what was agreed.
Handing it to the front end
High fidelity screens, designed with the company's style guide and component library so that a developer is assembling known parts rather than interpreting a picture. The key screens went into Zeplin in both desktop and mobile, which is where the padding, the colour and the icon come from.
Checking the build against the scenarios
Once developers had something unreleased, I worked back through the scenarios agreed for that sprint by hand. This is where the map from step one and the diagram from step five pay for themselves, because otherwise the answer to whether everything was covered is somebody's memory of a conversation.
Two recordings from production
Once it was live the question changes from whether it works to what people do with it. FullStory records real sessions and lets you segment by behaviour or by where somebody is, and anything I found worth keeping, a bug or an idea or a habit nobody had predicted, went into a document.
Two of those sessions are here because each shows something a conversion rate cannot. One is an American traveller on the B side going from room selection through to checkout. The other is a traveller in Japan opening the price breakdown on a room, which is the exact gesture this project existed to make worth making.
United States, room selection through to checkout, on the B side of the test
Japan, opening the price breakdown from the room selection page
Making the change legible to colleagues
The last step is the one that decides whether any of the others travel. The product owner and the data scientist wrote the readable account; my part was to draw the two sides against each other so that somebody who had never been in a single meeting about this could scroll once and see what moved.
Both boards below run the same journey twice, room selection on the left and checkout on the right, with the decision points presented in questions and the resulting panel under each branch. Put them side by side and the whole change is three things: the fee gets its name back, what you pay now is separated from what you pay there, and a sentence says who collects it.
More than one night, or more than one room?
Resort Tower Two Queen …
Deal detailsCompared with 2 other sites No changes
Resort Tower Two Queen …
Non-refundable rate
Resort Tower Two Queen …
Non-refundable rate
Nightly price including taxes and fees
CLP 59,803
CLP 51,381 Nightly price including taxes and fees
Price details 14% off
- 1 night x 1 room
- CLP 17,540.28
- Taxes and fees
- CLP 2,699.71
- Due at property
- CLP 31,140.86
- Resort fee
- CLP 31,109.12
Resort Tower Two Queen …
Deal detailsCompared with 2 other sites No changes
Resort Tower Two Queen …
CLP 74,507
Non-refundable rate
Resort Tower Two Queen …
CLP 74,531
Non-refundable rate
Nightly price per room including taxes and fees
CLP 74,531
CLP 62,031 Nightly price per room including taxes and fees
Price details 17% off
- 2 nights x 2 rooms
CLP 26,773.45 average per night per room - CLP 107,093.81
- Taxes and fees
CLP 4,116.28 average per night per room - CLP 16,465.10
- Due at property
- CLP 124,563.46
- Resort fee
CLP 31,109.12 average per night per room - CLP 124,436.48
Is the guest’s currency different from the property’s?
Is anything due at the property?
More than one night, or more than one room?
1 King Bed, Nonsmoking
Non-refundable rate
Price details 5% off
- 1 night x 1 room
- CLP 41,437.44
- Taxes and fees
- CLP 12,690.22
with taxes & fees
($68.97)
The price is converted to show you the approximate cost in CLP. You’ll pay in USD.
The price is converted to show you the approximate cost in CLP. You’ll pay now in USD ($68.97).
1 King Bed, Nonsmoking
Non-refundable rate
Price details 5% off
- 2 nights x 2 rooms
CLP 41,437.44 per night per room - CLP 165,749.76
- Taxes and fees
CLP 12,643.13 per night per room - CLP 50,572.51
with taxes & fees
($275.64)
The price is converted to show you the approximate cost in CLP. You’ll pay in USD.
The price is converted to show you the approximate cost in CLP. You’ll pay now in USD ($275.64).
More than one night, or more than one room?
Resort Tower Two Queen Room
Partially refundable rate
Price details 14% off
- 1 night x 1 room
- CLP 17,540.28
- Taxes and fees
- CLP 2,699.71
- Due now
- CLP 20,239.99
- Due at property
- CLP 31,109.12
- Resort fee
- CLP 31,109.12
with taxes & fees
($65.47)
The price is converted to show you the approximate cost in CLP. You’ll pay in USD.
The price is converted to show you the approximate cost in CLP. You’ll pay now in USD ($25.79). Pay at property amount will be collected by the property in the local currency.
Resort Tower Two Queen Room
Partially refundable rate
Price details 17% off
- 2 nights x 2 rooms
CLP 26,773.45 per night per room - CLP 107,093.81
- Taxes and fees
CLP 4,112.08 per night per room - CLP 16,465.10
- Due now
- CLP 123,558.91
- Due at property
- CLP 124,436.48
- Resort fee
CLP 31,109.12 per night per room - CLP 124,436.48
with taxes & fees
($316.16)
The price is converted to show you the approximate cost in CLP. You’ll pay in USD.
The price is converted to show you the approximate cost in CLP. You’ll pay now in USD ($157.44). Pay at property amount will be collected by the property in the local currency.
Prototype
The prototype itself
One flow, three locales: the same shared figure that runs the X-ray planner’s prototype, pointed at this file instead. Pick a locale to see how the total price is put together for it.
Prototype
The Figma prototype the concept was tested on, one flow shown for three locales. Click anywhere off a control to see what can be clicked.
Conclusion
What five weeks of traffic said
Conversion, for travellers outside the United States, over a five-week test.
The effect was sharpest where people already expect a displayed price to contain the tax. What we had folded in was not tax at all: it was the accommodation fees sitting beside it.
Desktop traffic converted better. Mobile traffic converted slightly worse, on the same change, in the same weeks.
Bookings made about a week in advance improved. Last-minute bookings were slightly worse off, which is the pattern you would expect if reading takes time somebody does not have.
We aimed this at American travellers arriving from Google hotel ads, on the argument that they were the largest and most valuable group on the site. The gain came from everywhere else.
That is not a failure, but it is a result about the target rather than about the change, and it deserves to be read as one. A market where the displayed price already contains the tax has trained its travellers to expect the number on the tile to be the number they pay. Break that expectation and the correction is worth a lot. A market where tax is added at the end has trained the opposite expectation, and there was less to correct.
Every charge given its own line is another line, and a phone is where a line costs the most. Nobody measured which of the two effects was doing the work, so what the result really says is that clarity is not free everywhere and this project never found out where it stops paying.
What came next
By December 2020 the work had become a document rather than a screen: one map of how a price should be stated at each stage of the funnel, from the search results through room selection and deal details to checkout. Four boards, one per stage, each of them the rule rather than an example of it.
This is also where the two Findhotel projects on this site meet. The bottom of that checkout board is a choice between paying now and paying at the property, and giving somebody that choice properly is its own case study. Naming what the property collects is what made it possible to offer.
Free cancellation
Nightly price including taxes
Free cancellation
Nightly price including taxes
Free cancellation
Nightly price
Free cancellation
Nightly price per room including taxes
Free cancellation
Nightly price per room including taxes
Free cancellation
Nightly price per room
Free cancellation
Nightly price including taxes
Free cancellation
Nightly price including taxes
Free cancellation
Nightly price
Free cancellation
Nightly price per room including taxes
Free cancellation
Nightly price per room including taxes
Free cancellation
Nightly price per room
Free cancellation
before 14 Sep 2020
Nightly price including taxes and fees
Free cancellation
before 14 Sep 2020
Nightly price including taxes
Free cancellation
before Sep 14, 2020
Nightly price
Free cancellation
before 14 Sep 2020
Nightly price per room including taxes and fees
Free cancellation
before 14 Sep 2020
Nightly price per room including taxes
Free cancellation
before Sep 14, 2020
Nightly price per room
Free cancellation
before 14 Sep 2020
Nightly price including taxes and fees
Free cancellation
before 14 Sep 2020
Nightly price including taxes
Free cancellation
before Sep 14, 2020
Nightly price
Free cancellation
before 14 Sep 2020
Nightly price per room including taxes and fees
Free cancellation
before 14 Sep 2020
Nightly price per room including taxes
Free cancellation
before Sep 14, 2020
Nightly price per room
- 1 night × 1 room
- €90
- Taxes and fees
- €9
- Local tax
- €1
- Total
- €100
- 1 night × 1 room
- €90
- Taxes and fees
- €9
- Subtotal
- €99
- Local tax fee
- €1
- Total
- €100
Additional charges
- 1 night × 1 room
- $90
- Taxes and fees
- $9
- Local tax
- $1
- Total
- $100
- 1 night × 2 rooms
- €180
- Taxes and fees
- €18
- Local tax
- €2
- Total
Average nightly price per room €100 - €200
- 1 night × 2 rooms
- €180
- Taxes and fees
- €18
- Subtotal
Average nightly price per room €99 - €198
- Local tax fee
- €2
- Total
- €200
Additional charges
- 1 night × 2 rooms
- $180
- Taxes and fees
- $18
- Local tax
- $2
- Total
Average nightly price per room $90 - $200
- 3 nights × 1 room
- €270
- Taxes and fees
- €27
- Local tax
- €3
- Total
Average nightly price €100 - €300
- 3 nights × 1 room
- €270
- Taxes and fees
- €27
- Subtotal
Average nightly price €99 - €297
- Local tax fee
- €3
- Total
- €300
Additional charges
- 3 nights × 1 room
- $270
- Taxes and fees
- $27
- Local tax
- $3
- Total
Average nightly price $90 - $300
- 2 nights × 2 rooms
- €360
- Taxes and fees
- €36
- Local tax
- €4
- Total
Average nightly price per room €100 - €400
- 2 nights × 2 rooms
- €360
- Taxes and fees
- €36
- Subtotal
Average nightly price per room €99 - €396
- Local tax fee
- €4
- Total
- €400
Additional charges
- 2 nights × 2 rooms
- $360
- Taxes and fees
- $36
- Local tax
- $4
- Total
Average nightly price per room $90 - $400
Free cancellation before 14 Sep 2020
- 1 night × 1 room
- €90
- Taxes and fees
- €9
- Local tax
- €1
- Total
- €100
- Pay now
- €99
- Pay at property
- €1
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before 14 Sep 2020
- 1 night × 1 room
- €90
- Taxes and fees
- €9
- Subtotal
- €99
- Local tax
- €1
- Total
- €100
Additional charges
- Pay now
- €99
- Pay at property
- €1
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before Sep 14, 2020
- 1 night × 1 room
- $90
- Taxes and fees
- $9
- Local tax
- $1
- Total
- $100
- Pay now
- $99
- Pay at property
- $1
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before 14 Sep 2020
- 1 night × 2 rooms
- €180
- Taxes and fees
- €18
- Local tax
- €2
- Total
Average nightly price per room €100 - €200
- Pay now
- €198
- Pay at property
- €2
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before 14 Sep 2020
- 1 night × 2 rooms
- €180
- Taxes and fees
- €18
- Subtotal
Average nightly price per room €99 - €198
- Local tax
- €2
- Total
- €200
Additional charges
- Pay now
- €198
- Pay at property
- €2
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before Sep 14, 2020
- 1 night × 2 rooms
- $180
- Taxes and fees
- $18
- Local tax
- $2
- Total
Average nightly price per room $90 - $200
- Pay now
- $198
- Pay at property
- $2
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before 14 Sep 2020
- 3 nights × 1 room
- €270
- Taxes and fees
- €27
- Local tax
- €3
- Total
Average nightly price €100 - €300
- Pay now
- €297
- Pay at property
- €3
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before 14 Sep 2020
- 3 nights × 1 room
- €270
- Taxes and fees
- €27
- Subtotal
Average nightly price €99 - €297
- Local tax
- €3
- Total
- €300
Additional charges
- Pay now
- €297
- Pay at property
- €3
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before Sep 14, 2020
- 3 nights × 1 room
- $270
- Taxes and fees
- $27
- Local tax
- $3
- Total
Average nightly price $90 - $300
- Pay now
- $297
- Pay at property
- $3
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before 14 Sep 2020
- 2 nights × 2 rooms
- €360
- Taxes and fees
- €36
- Local tax
- €4
- Total
Average nightly price per room €100 - €400
- Pay now
- €396
- Pay at property
- €4
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before 14 Sep 2020
- 2 nights × 2 rooms
- €360
- Taxes and fees
- €36
- Subtotal
Average nightly price per room €99 - €396
- Local tax
- €4
- Total
- €400
Additional charges
- Pay now
- €396
- Pay at property
- €4
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Free cancellation before Sep 14, 2020
- 2 nights × 2 rooms
- $360
- Taxes and fees
- $36
- Local tax
- $4
- Total
Average nightly price per room $90 - $400
- Pay now
- $396
- Pay at property
- $4
The price is converted to show you the approximate cost in {userCurrencyCode}. You’ll pay now in {chargeableCurrencyCode} {CurrencySymbol}{Amount}. Local taxes or resort fees will be collected by the property in the local currency.
Those boards are the rules. What the original page offered next was the thing itself: a clickable prototype of the three price display logics the site was running at once, so that a reader could try them instead of reading about them.