In January 2026, we noticed something ugly: 87% of users who started checkout never completed a purchase. Not "abandoned cart" — abandoned checkout. They filled in their name, email, selected dates, entered passenger counts, and then… nothing. Zero clicks on the payment button.
This is the story of how we diagnosed it, what we found, and the fixes that brought completion back to a normal range. If you run any WooCommerce site with date pickers, payment iframes, or caching plugins, some of this might save you weeks of debugging.
The Symptoms
We use Microsoft Clarity for session recordings. When we actually watched users going through checkout, the pattern was immediately clear:
- User selects a tour, picks a date, adds to cart
- User fills in personal info (name, email, phone) — no issues
- User reaches the payment section (Mercado Pago iframe)
- User clicks the "Pagar" (Pay) button
- Nothing happens
- User clicks again. And again. Rage clicks. Leaves.
Clarity's rage click heatmap looked like a crime scene — the pay button was getting hammered by frustrated users who had already committed to buying.
The Investigation: Four Hypotheses
We opened a bug ticket with four possible root causes. Here's what we checked:
Hypothesis 1: WP Rocket Delay JS breaking the payment iframe
WP Rocket's "Delay JavaScript Execution" feature defers all JS until user interaction. The idea is great for Core Web Vitals — but it means scripts don't run until a scroll, click, or keypress. The Mercado Pago SDK needs to initialize before the user clicks pay.
We tested by adding Mercado Pago's SDK to WP Rocket's exclusion list:
// wp-rocket delay JS exclusions
// Settings → WP Rocket → File Optimization → Delay JS
// Exclude Mercado Pago SDK
/sdk\.mercadopago\.com/
/v1\/checkout/
/mercadopago/
// Also exclude WooCommerce checkout scripts
/wc-checkout/
/checkout\.min\.js/
Result: Partial improvement. The payment iframe now loaded on time for most users, but some sessions still showed the dead-click behavior.
Hypothesis 2: WooTours date picker conflict
WooTours (v3.3.2 — critically outdated, current is v3.6.5) injects its own jQuery UI datepicker. When WP Rocket delays jQuery, the datepicker initializes late. This cascades: if the date selection doesn't register properly, the cart data is incomplete, and Mercado Pago's checkout form never receives the order total.
We confirmed this by checking the browser console on affected sessions:
// Console error on affected sessions:
Uncaught TypeError: $(...).datepicker is not a function
at wootours-frontend.min.js:1:4328
// jQuery UI wasn't loaded yet when WooTours tried to init
The fix: exclude jQuery UI from delay as well, and load WooTours scripts with an explicit dependency chain.
// functions.php — force correct load order
add_action('wp_enqueue_scripts', function() {
if (is_checkout() || is_product()) {
wp_enqueue_script('jquery-ui-datepicker');
wp_script_add_data('wootours-frontend', 'group', 1);
}
}, 20);
Hypothesis 3: Cloudflare Rocket Loader double-deferring
Cloudflare has its own JS deferral mechanism called Rocket Loader. If both WP Rocket's Delay JS and Cloudflare Rocket Loader are active, scripts get deferred twice — they load so late that the payment iframe misses its initialization window entirely.
We had Rocket Loader enabled. Turning it off while keeping WP Rocket's delay (with exclusions) resolved the double-deferral issue.
⚠️ Lesson learned: If you use WP Rocket + Cloudflare, disable Cloudflare Rocket Loader. They do the same thing, and having both active creates race conditions with third-party payment SDKs. WP Rocket gives you more granular control over exclusions anyway.
Hypothesis 4: Consent mode blocking the SDK
We use Complianz for GDPR/cookie consent. Complianz's "consent mode" integration can block third-party scripts until the user accepts cookies. Mercado Pago's SDK was being categorized as "statistics" instead of "functional", meaning users who hadn't accepted cookies couldn't pay.
// Complianz → Integrations → Script Center
// Mercado Pago was incorrectly categorized
// Before: Category = "statistics" (blocked until consent)
// After: Category = "functional" (always allowed)
// Payment processing is functional, not tracking
The Combined Fix
No single hypothesis was the full answer. The actual bug was a combination of all four, creating a cascade failure:
- Cloudflare Rocket Loader + WP Rocket Delay JS double-deferred all scripts
- jQuery UI loaded after WooTours tried to initialize, breaking the date picker
- Broken date picker meant incomplete cart data
- Mercado Pago SDK was also blocked by Complianz consent mode
- Even when the SDK loaded, it received incomplete order data and silently failed
- The "Pay" button looked clickable but did nothing
The fix was four changes deployed together:
|
Change |
What |
|
Disable Cloudflare Rocket Loader |
Cloudflare dashboard → Speed → Optimization → Rocket Loader OFF |
|
WP Rocket JS exclusions |
Exclude Mercado Pago SDK, jQuery UI, WooCommerce checkout, and WooTours scripts from Delay JS |
|
WooTours dependency chain |
wp_enqueue_script with explicit dependency on jquery-ui-datepicker |
|
Complianz recategorization |
Move Mercado Pago from "statistics" to "functional" in Script Center |
Results
We deployed the combined fix to our staging environment first (back.calafate.tours), tested across Chrome, Safari, Firefox, and mobile, then pushed to production.
|
Metric |
Before |
After |
|
Checkout completion rate |
~13% |
~58% |
|
Rage clicks on pay button |
340/week |
12/week |
|
LCP (Largest Contentful Paint) |
1.8s |
2.1s (+0.3s) |
|
TBT (Total Blocking Time) |
120ms |
180ms (+60ms) |
Checkout completion went from 13% to 58%. The trade-off was a small hit to Core Web Vitals (LCP +0.3s, TBT +60ms) because we're loading more scripts eagerly now. Acceptable — a slightly slower page that actually converts is infinitely better than a fast page where nobody can pay.
What We'd Do Differently
If we were starting this site from scratch, here's what we'd change:
Ditch WooTours entirely. The plugin is outdated (we're on v3.3.2, three major versions behind), the jQuery UI dependency is a liability, and the date picker is the root of too many cascading failures. We've scoped a custom replacement — roughly 2,450 lines of vanilla JS with a modern date picker component and direct WooCommerce REST API integration. No jQuery dependency.
Use a headless checkout for payments. The Mercado Pago iframe-within-WooCommerce-checkout architecture is fragile. A headless approach where the checkout is a standalone React/Next.js component calling WooCommerce's REST API would eliminate the script-loading race conditions entirely.
Separate the blog. We actually already did this — our blog runs on Next.js/Vercel at /blog/, routed via a Cloudflare Worker. This keeps the WordPress install lighter and avoids plugin bloat on the content side. If you run a content-heavy WooCommerce site, consider this architecture.
// Simplified Cloudflare Worker for blog routing
export default {
async fetch(request) {
const url = new URL(request.url);
// Route /blog/* to Next.js on Vercel
if (url.pathname.startsWith('/blog') ||
url.pathname.startsWith('/en/blog') ||
url.pathname.startsWith('/pt/blog')) {
const blogUrl = new URL(url.pathname, 'https://blog.calafate.tours');
const newRequest = new Request(blogUrl, {
headers: { ...Object.fromEntries(request.headers),
'Host': 'blog.calafate.tours' }
});
return fetch(newRequest);
}
// Everything else → WordPress origin
return fetch(request);
}
};
The Broader Lesson: Performance Tools Can Break Functionality
The irony of this whole bug is that every tool involved — WP Rocket, Cloudflare Rocket Loader, Complianz — was doing exactly what it was designed to do. Defer scripts for performance. Block tracking for privacy. Each one is a good tool used correctly.
The problem is the interaction between them. No single tool knew about the others. WP Rocket didn't know Cloudflare was also deferring. Complianz didn't know Mercado Pago was a payment processor, not a tracker. And WooTours didn't know its jQuery dependency would load 3 seconds after it needed it.
If you're running a WooCommerce site with multiple optimization and compliance layers, here's my checklist:
- Pick ONE JS deferral method — WP Rocket OR Cloudflare Rocket Loader, never both
- Exclude all payment SDKs from deferral — Stripe, PayPal, Mercado Pago, whatever. Payment scripts are mission-critical
- Audit your consent tool's script categorization — payment processing is "functional", not "statistics" or "marketing"
- Test checkout on a fresh browser with no cookies — this simulates a first-time visitor who hasn't granted consent yet
- Use session recordings (Clarity, Hotjar) on your checkout page — analytics will tell you the what, recordings tell you the why
Stack Summary
For reference, here's our full production stack:
|
Layer |
Tool |
|
CMS |
WordPress 6.x |
|
E-commerce |
WooCommerce |
|
Booking |
WooTours (v3.3.2, migration planned) |
|
Translation |
TranslatePress (ES base, /en/, /pt/) |
|
Caching |
WP Rocket |
|
CDN / SSL |
Cloudflare (Full Strict) |
|
Payment |
Mercado Pago |
|
Consent |
Complianz |
|
Analytics |
GA4 via GTM + Microsoft Clarity |
|
Blog |
Next.js on Vercel, routed via CF Worker |
|
SEO |
Yoast SEO + custom FAQPage JSON-LD |
The site is calafate.tours if you want to see the live implementation. We're a small team running a tour booking operation in Patagonia — not a dev shop — so this was very much a "learn by breaking things" process.
— — —
If you've dealt with similar WP Rocket + payment gateway conflicts, I'd love to hear how you solved it. And if you're building booking systems on WooCommerce: update your plugins, test your checkout on a clean browser, and for the love of all that is holy, watch your session recordings.
📌 TL;DR: WP Rocket Delay JS + Cloudflare Rocket Loader + Complianz consent mode were triple-blocking our Mercado Pago payment iframe. Fix: disable Rocket Loader, exclude payment + jQuery UI from WP Rocket delay, recategorize payment SDK as "functional" in Complianz. Checkout completion went from 13% to 58%.
Top comments (0)