Notes
The price you show and the price you charge
They are meant to be one number in one currency. The ways they come apart are quieter than a broken checkout, and they sit in places a checkout test never reaches.
PJ Roch
A customer should be charged the price they were shown, in the currency they were shown it in. Every business agrees with that sentence. Agreeing with it does not check it.
When it fails, nothing looks broken. The page loads, the checkout opens, the payment goes through and the order is recorded. The only person who sees the fault is your customer, reading a bank statement some days later.
It rarely hides on your checkout page. It hides in the gap between two records that are meant to agree and that nothing compares. The examples below come from systems PJ Roch designed and built himself: a platform that sells subscriptions, credit packs and a small range of hardware; Nemolines, an iPhone app for actors learning lines; and this website.
Two price lists that are meant to agree
If you take card payments online, you probably have two price lists. One is on your website: the figure on the page and in the code behind it. The other is in your payment provider's catalogue, and it is the one the card is actually charged against.
On that platform, a check was written to compare the two, line by line. Its first run against the real accounts found three faults. Subscriptions in the United States and the EU were pointed at the pound prices, so a subscriber reading a dollar price would have been charged in pounds.
Credit packs were shown with a dollar sign and charged in pounds. And once the first fault was fixed, the UK was about to fall through to the dollar price, because nothing had ever named the UK's prices explicitly. All three were fixed the same day.
None of them was visible by reading the code, because each line was correct on its own. A reference to a price record is only a string. It goes on looking right until something outside the code is asked what it points at.
The check now runs daily. It reports a disagreement and never corrects it, because a job that rewrote the catalogue to match the code would be the same fault in the other direction. What a price should be is a commercial decision.
The credit pack fix could have been one character, a pound sign where the dollar sign was. It was a currency field stored beside the amount instead, read by both the page and the check, so the two cannot disagree.
Who decides the currency
The same platform's hardware store went from pounds only to charging each visitor in their own currency. The rule written for it is one sentence.
A page must never show a price that the checkout then charges differently.
The region is worked out on the server from the request, and any currency the browser sends is ignored. Before the payment form opens, the checkout's total is compared with the prices in the code. If the two disagree, the sale is refused.
The work turned up a price surface that is easy to forget. The page's title, the text in the browser tab and in every link preview, was found quoting a pound figure while the page itself priced in dollars. A link preview has no country, so the title now carries no figure at all, and a test fails if one comes back.
The last copy of a price is the line on the bank statement. After a real hardware purchase on PJ Roch's own card, his bank's app labelled the charge with an unrelated company's name. It had matched the one bare word on the statement to somebody else. The statement now carries the site's full domain.
The fallback typed into the code
Nemolines sells one upgrade, and its price comes from Apple's store at runtime, in the buyer's own currency. One screen already refused to show a price the store had not supplied. Four other places, when the store had not answered, fell back to a price typed into the code in dollars, and two of them were purchase buttons.
Outside the US, that fallback showed the wrong currency. Then the price was raised in the store while the live build still carried the typed one. On those two buttons it would now have understated the real charge by a factor of three.
All four places now ask one owner whether there is a price to show. A review by a second AI model found the tests would stay green if a typed price came back, because they checked the owner and not the screens that call it. A scan of the source now fails the test run on six shapes of hardcoded price.
The same review found that the script which loads the app's prices into the store still named the old base currency. Run again, it would have replaced the new schedule and recalculated every country's price from the wrong starting point. It also printed the old currency beside each result, which read as confirmation.
A cookie that outranked the location
This site quotes pounds, or dollars to visitors in the United States. There used to be a switch between the two, and when it was removed, a footer line was left naming the currency. Someone on a VPN would read "Prices in US dollars", suspect they had the wrong sheet, and find nothing to press.
The line is gone, and a test fails if it returns. Then PJ Roch read dollar prices in London himself. A cookie from once checking the other sheet outranked his location, and it lasted a year.
It now ends when the browser closes. The site's cookie page had also said a year, so the header the site sends and the sentence the reader is given are now tested against each other.
Where to look in your own business
Each place above is a hand-off: from catalogue to page, from request to currency, from store to screen, from payment to statement. Each needed one owner for the price and one check at the hand-off.
- Checkout. Compare the total with the price the page showed before payment is taken, and refuse the sale if they differ.
- Currency. Decide it on the server. Know how long a visitor's earlier choice outlives their location.
- The catalogue. Compare your site's prices with your payment provider's on a schedule, and send any difference to a named person.
- Fallbacks. Search your templates and code for a currency symbol next to a number. Every hit is a price that will not move when you change it.
- Copies. Tab titles, link previews, confirmation emails, invoices and the statement line all repeat the price.
Where a price can come apart
Unchecked
- Price typed in code
- Page shows it
- Catalogue charges its own
- Customer reads the statement
Checked
- One owner per price
- Currency set on the server
- Total compared before payment
- Catalogue compared daily
- Statement names the site
Buy one thing from your own site this week, from a phone on mobile data, then ask someone in another country to buy the same thing. Write down the price on the page, at checkout, on the receipt and on the bank statement. Put the currency, and the name on the statement, beside each one.
An Office Review is where we look at the operating system your business is already running on.