If you are a developer or store owner building a highly customized e-commerce experience, you’ve probably run into the new WooCommerce Blocks Checkout. Out of the box, it’s beautiful. It’s React-based, it features real-time validation, and it feels like a modern, frictionless Shopify checkout.

But what happens when you need to break the mold?

Recently, while engineering a deeply customized checkout flow, we hit a massive wall with the Blocks architecture. Here is the story of our descent into React workarounds, accidentally triggering our own server firewalls, and why we ultimately went back to the trusty old [woocommerce_checkout] shortcode.

The Goal: A Gated, Multi-Step Checkout

We wanted to build a guided “Wizard” experience. Instead of dumping the user into a massive form, we wanted to ask for their Location first, calculate the exact Shipping Methods (like local “Entrega Personal” vs. “Delivery Motorizado”), and conditionally lock, hide, or pre-fill address fields based on their choices. We also needed to inject custom fields, like asking for a MercadoLibre or Instagram username.

In the old days, this was a breeze with a few PHP filters like woocommerce_checkout_fields. With Blocks? Not so much.

The Problem: React State vs. PHP Hooks

The WooCommerce Blocks Checkout is a compiled React application. The HTML structure isn’t built PHP line-by-line anymore.

When we tried to physically move the Shipping Options above the Contact fields using CSS flexbox (order: -1), we ended up fighting the React reconciliation process. Elements would disappear, animations would break, and the UI would glitch. The backend PHP hooks we all know and love are effectively useless for structural DOM manipulation in Blocks.

The “Puppeteer” Workaround

Not wanting to give up the smooth, API-driven UX of the Blocks checkout, we got creative. We built what we called a “Proxy Component.”

The strategy was pure mad science:

  1. Hide the native UI: We used CSS to make the entire native shipping and address blocks invisible.
  2. Build a custom UI: We injected our own HTML form at the very top of the page.
  3. Drive the engine remotely: We used jQuery to listen to our custom form, and then used wp.data.dispatch('wc/store/cart') to silently push data into the hidden WooCommerce React store.

It was essentially a puppeteer manipulating the checkout engine from behind the curtain.

The Breaking Point: Race Conditions and Firewalls

The proxy approach worked, but it introduced a terrifying amount of complexity.

Because the React store updates asynchronously, tying a custom loading spinner to the native calculation process became a nightmare of MutationObservers and race conditions. At one point, syncing our custom address fields with the React store created an infinite loop: the store updated, which triggered our render function, which updated the store again. It flooded the server with API calls so fast that our web application firewall panicked and threw a site-wide 403 error to save the server from itself.

We patched it using strict debouncing (syncing only 500ms after the user stopped typing), which stabilized the system. But then we hit the final nail in the coffin.

The Custom Field Reality Check

We needed to add a custom text field for an Instagram/MercadoLibre identifier.

In the classic checkout, this is a 10-line PHP snippet. In Blocks, adding a true custom field requires writing custom React components, registering them with the WooCommerce Blocks registry via JavaScript, and then exposing that data to the WooCommerce Store API so the server can save it.

It was at this moment we stepped back and asked: Why are we doing this?

The Verdict: Classic is Still King for Customization

The main selling point of the Blocks checkout is “no page reloads.” But as we’ve seen on heavily optimized stores like electronica.club, the classic checkout handles UX just fine using standard AJAX. When you change a delivery method, the classic checkout updates the totals seamlessly without reloading the page.

We reverted to the Classic Checkout.

The takeaway: If you are running a standard store and want a beautiful, modern checkout with zero code, use WooCommerce Blocks. But if you are building a custom flow, gating your checkout, manipulating fields conditionally, or adding custom data parameters, the Classic Checkout isn’t just a fallback—it is the right tool for the job.

Sometimes, the old PHP hooks are exactly what you need to keep your sanity (and keep your firewall from blocking you).

Leave a Reply

Your email address will not be published. Required fields are marked *