Checkout UX and conversion¶
checkout-ux-and-conversion
Design checkout so the full cost is visible before payment, guest purchase works, and field or payment errors can be corrected without losing the cart. Use when changing the checkout flow, address form, payment choice, or order confirmation page.
Version 0.3.2 · MIT · Source · Rule
Install this skill
Copy the skill and its rule into your project:
The skill goes to .agents/skills/ and the rule to .agents/rules/. See Command line for other directories.
Use this skill when changing the checkout a shopper sees. Payment capture rules live in the payment skill. Persian and RTL layout lives in the localization skill. Field-level review questions are in the checkout review.
This skill does not claim a conversion rate. It states conditions the checkout has to meet so a shopper can finish an order they already decided to place.
Procedure¶
- Show merchandise, discounts, shipping, tax, and the amount that will be charged before the pay control.
- Allow a guest purchase. Offer account creation after the order, or as an optional choice that does not block payment.
- Validate fields inline, next to the field, in the shopper's language. Move focus to the first error.
- Keep the cart and the entered address when payment is declined.
- Disable the pay control after the first accepted submit, and make the order request idempotent so a double submit creates one order.
- Confirm with an order number and a plain statement of what was charged. Do not offer a second pay control on that page.
Cost¶
- Shipping method and shipping cost are chosen before payment. If the address changes the cost, update the total before the shopper pays.
- A fee or payment surcharge is a line in the total, not a surprise on the provider's page.
- The currency is visible. If you display a second currency, the charged currency is the one in the pay button label.
- Coupon entry does not clear the address or the selected shipping method.
Address and contact¶
- Ask for the fields the order needs. Drop a field rather than marking it optional and ignoring it.
- Use autocomplete attributes from the HTML specification:
given-name,family-name,address-line1,address-line2,address-level1,address-level2,postal-code,country,email,tel. - Set input types:
email,tel, and an appropriate keyboard for the postal code. Do not force a North American phone mask on other countries. - When the country changes which fields are required, update the form before submit. WooCommerce does this through country locale settings. Do not keep a second hard-coded field list that disagrees with
woocommerce_get_country_locale. - The country control comes before fields whose labels and requirements depend on it.
Payment choice¶
- List only methods the shop can capture and refund.
- Each method shows its name and, when it adds a cost, that cost.
- Card entry uses the provider's hosted fields or a redirect. The merchant page does not collect PAN or CVV.
- The primary control states the action and the amount, for example "Pay 19.00 USD". A generic "Submit" is not enough when more than one control is on the page.
- Express wallets, when you offer them, create the same server-side order and idempotency path as the regular form.
Errors¶
- Field errors name the field and how to fix it. Do not rely on color alone.
- A payment decline says that the payment was not taken and that the shopper can try another method. Do not say the order was placed.
- A network timeout says the outcome is unknown and points to the order status or a retrieve. Do not immediately start a second charge. Reuse the same idempotency key.
- Keep the shopper's typed values. Re-render the form with those values and the error.
Confirmation¶
- Show the order number, the charged total, and the shipping destination.
- Send the receipt email once, from the paid transition, not from the browser page load.
- A reload of the confirmation page does not place another order.
Mobile and accessibility¶
- One column when the viewport is narrow. The total stays visible near the pay control.
- Tap targets are large enough to hit without zooming. Error text is not only a tooltip.
- Every control has a label. Errors use
aria-invalidand are referenced from the field. - Focus order follows the visual order, including in RTL layouts.
Gotchas¶
- Hiding shipping cost until after the pay button is the usual reason a shopper abandons at the last step. Show it earlier.
- Creating the account, and requiring the shopper to leave checkout to verify email, loses the order in progress. Save the order first.
- A pay button that stays enabled can create two pending orders. Disable it and dedupe on the server.
- Validation that only runs in the browser will be skipped. Repeat every rule on the server.
- Third-party badge images do not replace a real returns or shipping policy link.
Verification¶
- A guest can pay without creating a password.
- Changing the address updates shipping and the pay-button amount before payment.
- A declined payment preserves the cart and the address.
- Submitting twice creates one order and charges once.
- Keyboard-only use reaches every field, the error, and the pay control. In a narrow viewport the total is still visible with the pay control.
Evaluation¶
Worked examples and the checks they must satisfy are in evals/tasks.json.
References¶
Checkout review¶
Walk a real order in the browser. Record pass or fail. Do not treat a screenshot of the empty form as a review.
Before payment¶
- Guest checkout is available, or the shop has a written reason it is not.
- Line items, discounts, shipping, tax, and total match what the pay control will charge.
- The shipping method can be changed without retyping the address.
- A coupon or gift card failure leaves the rest of the form intact.
- The pay button names the amount and currency.
Address¶
- Required fields match the selected country.
- Autocomplete attributes are set on contact and address fields.
- Phone and postal code inputs do not apply a mask from a different country.
- Error text is next to the field and is announced to assistive technology.
Payment¶
- Only live, refundable methods are listed.
- Card data is entered in hosted fields or on the provider page.
- The first submit disables the pay control.
- A second submit does not create a second order.
- A decline keeps the cart.
After payment¶
- The confirmation page shows the order number and the charged total.
- Reloading confirmation does not charge again.
- The receipt email is sent once.
- The order is unpaid until the payment skill's server-side confirmation runs. The confirmation page does not itself mark the order paid.
RTL¶
- Totals align to the correct side for the document direction.
- The pay control is in the focus order a shopper expects for that direction.
- Payment marks and card logos are not mirrored.
Use the Persian and RTL skill for the layout rules behind these checks.
Evaluation¶
Fixtures from evals/tasks.json. See evaluation fixtures for how the checks work.
guest-total¶
Let a guest see shipping and the charged total before paying, without creating a password first.
Must include: guest, shipping
Must not include: password is required
Worked example
Show the full cost and allow a guest purchase.
The shipping method and tax are visible before the pay control. A guest can pay. Account creation is offered after the order, not as a gate.
single-submit¶
Stop a double click on the pay control from creating two orders for one cart.
Must include: idempotency, disable
Must not include: Math.random()
Worked example
After the first accepted submit, disable the pay control and send a stable idempotency key for that attempt.
The server returns the original order when the same key is retried. The cart remains if the provider declines.