Skip to article body
A woman sliding a kraft paper parcel along a wooden counter in a small Cairo boutique
A woman sliding a kraft paper parcel along a wooden counter in a small Cairo boutique

Process · Field Notes

The Card Form That Charged Nobody

We built a checkout design screen by screen, then deleted most of it so Shopify could do its job.

By Shehab Waleed, Founder, Cairo Studio 3 min read

Maison Gacha sells a small range of objects from its website, in French and English. The design showed a three step checkout on the site itself: a shipping address, a choice of carrier with prices, and a card form, followed by a confirmation page. We built it as drawn, and the work is part of our Maison Gacha project.

Then we connected the shop to Shopify, and most of those screens turned out to be either repeated or pretend.

What each step was really doing

On a standard Shopify plan, the hosted checkout is one flow: contact, then shipping, then payment. You can send a customer into it. You cannot take parts out of it and run them on your own pages.

So our address form collected an address that Shopify then asked for again. The carrier picker offered Colissimo, Chronopost and pickup at prices we calculated ourselves, and none of that choice reached Shopify, which works out real rates at its own checkout. The card form, built to match the design before payments were connected, moved the customer to a confirmation page without charging anyone.

Real orders went through Shopify, so nobody was charged wrongly. But a page that looks like it takes payment and does not is a liability on any shop, however finished it looks.

What the checkout page became

The page is now a recap of the cart: items, quantities, the subtotal and a line saying shipping is calculated at payment. One button creates a Shopify cart and sends the customer to Shopify’s checkout. In simplified form:

const res = await fetch('/api/checkout', {
method: 'POST',
body: JSON.stringify({ lines })
});
const { checkoutUrl, cartId } = await res.json();

localStorage.setItem('pendingCart', cartId);
location.href = checkoutUrl;

The 50 euro free shipping teaser went too, because it belonged to the shipping prices we had invented. Carts saved before the Shopify connection were dropped on load, since their items had no Shopify variant to buy.

Emptying the cart after payment

Handing checkout to Shopify leaves one gap. The customer pays on Shopify’s pages and our site never hears about it. When they come back, their cart is still full.

The answer was in how Shopify treats carts: once a cart’s checkout completes, Shopify deletes the cart. So on the next visit, the site asks whether the cart it sent to checkout still exists. If it is gone, the order went through, and the local cart is cleared.

const pending = localStorage.getItem('pendingCart');
if (pending) {
localStorage.removeItem('pendingCart');
const res = await fetch(
`/api/checkout?cartId=${pending}`
);
const { exists } = await res.json();
if (exists === false) clearCart();
}

Two details matter. The check runs once: the saved id is removed after the first answer either way, so a checkout someone abandoned can never empty their cart weeks later. And any error keeps the cart, because an emptied cart is worse than a full one.

What we would do differently

Ask how payment works before building any checkout screen. The design was reasonable for a shop that owns its checkout. This one did not, and knowing that on day one would have saved three screens. We wrote earlier about when we build a shop at all.

Share
X LinkedIn Facebook WhatsApp Email
Two hands passing a kraft paper parcel across a wooden counter

Hand it over, and let them finish.

First build
Our form, asked again by Shopify
Now
Asked once, by Shopify
First build
Our picker and our own maths
Now
Real rates at Shopify checkout
First build
A form that charged nobody
Now
Shopify payments
First build
Our own page
Now
Shopify’s order confirmation
First build
Still full
Now
Cleared on the next visit

From the Maison Gacha shop, July 2026.

You can send customers to Shopify’s hosted checkout and style it to your brand, but the steps run as one flow on Shopify. Changing the steps themselves is largely limited to Shopify Plus.

Save the cart id before redirecting. On the next visit, query that cart. Shopify removes a cart once its checkout completes, so a missing cart means the order went through.

Only if they come from the same source as checkout. Prices worked out on your side will drift from what Shopify charges. A line saying shipping is calculated at payment is honest.

We build headless Shopify stores that look like the rest of your site and leave payments to Shopify.

See our e-commerce work

More from the Journal

view all →