Welcome to WordPress. This is your first post. Edit or delete it, then start writing!

This is one of the cases we get called in on most often: a store that looks like it’s working. Orders are coming in, support is quiet, conversion rate looks normal. But revenue is down and no one can explain why.

The symptom

In this case, a fashion label on WooCommerce noticed their revenue was about 14% below forecast for six weeks running. Not a crash — a slow bleed. Their checkout completion rate in GA4 looked normal. Their payment gateway dashboard showed normal approval rates. Nobody flagged it.

The diagnosis

When we got access, the first thing we did was check the order status distribution in WooCommerce. We saw an unusually high ratio of “pending payment” orders that were never transitioning to “processing.” These weren’t abandoned carts — the customer had reached the payment step, submitted, and the order was created, but the gateway callback was timing out before it could update the order status.

The root cause: a hosting provider had silently changed their outbound request timeout from 30s to 8s as part of a “performance optimization.” The payment gateway’s webhook was taking 9-12 seconds on average. Every single one was timing out.

The fix

We patched it in three steps: increased the timeout threshold, added a retry queue for failed webhooks, and implemented a reconciliation job that catches any orders stuck in pending for more than 15 minutes and re-queries the gateway directly.

We also rebuilt their order status monitoring so this class of issue surfaces as an alert within 30 minutes rather than six weeks.

The numbers

$180k recovered in the 30-day window after the fix. That’s money that was sitting in a pending queue — some of it we were able to manually process, the rest was refunded and recaptured.

“They found the leak in 20 minutes. The old agency spent two months on it.” — Client, fashion label

Cart abandonment is the most consistent revenue leak we see on intake. The industry average sits around 70%, and most stores are catching maybe 2-3% of those with a single email three hours later. Here’s the full system we build for every client on Rapid Response and above.

The four-channel stack

We run four channels in parallel, sequenced so they don’t overlap and don’t annoy people who already converted.

Email — 3 touches over 48 hours

Touch 1 lands 45 minutes after abandonment. No discount. Just a reminder with the cart items, product images, and a direct link back. This alone recovers 40% of email-recoverable carts.

Touch 2 lands 24 hours later. Social proof: reviews for the specific items in cart, “X people bought this today” if true. Still no discount.

Touch 3 lands 48 hours later. This is where a time-limited offer goes — but only if the cart value justifies it. We use a margin-aware discount ladder: carts over $150 get 10%, carts over $300 get 15%, below $150 get free shipping only.

SMS — 1 touch, 90 minutes after abandonment

Short, direct, one link. Consent-compliant. Quiet-hours aware (we don’t send between 9pm and 9am local). SMS typically adds another 8-12% recovery on top of email.

Browser push — on-site exit intent

Exit-intent overlay fires when the user moves toward the browser chrome. Not aggressive — a single modal, one chance, can be dismissed with one click. Saves a further 3-5% in sessions where the user is still on the page.

Retargeting — live cart audiences

We feed Meta and Google with real-time cart event data via server-side CAPI. Abandoners go into a dedicated audience, excluded from prospecting, and shown dynamic product ads for exactly what they left behind. Budget is proportional to cart value — we spend more to win back a $400 cart than a $30 one.

What this system typically recovers

Across our current retainer clients, this four-channel stack recovers 18-28% of abandoned carts. On a store doing $50k/month with 70% abandonment, that’s a meaningful lift without touching traffic or conversion on the store itself.

AI shopping agents are not a future thing. They’re here. ChatGPT, Perplexity, Google AI Overviews, and Amazon Rufus are already answering “where should I buy X” for millions of queries every day. Most stores are invisible to all of them.

Why stores are invisible to AI agents

AI agents parse structured data. They look for Schema.org markup to understand what a product is, what it costs, whether it’s in stock, what people think of it. They look for clean, machine-readable product feeds. They follow patterns established by large retailers.

Most stores, even well-built ones, have incomplete or incorrect schema, no structured product feed beyond a Google Shopping XML, and checkout flows that an agent can’t navigate programmatically.

The five-part AI-agent readiness build

1. Full Schema.org implementation

Product, Offer, AggregateRating, Review, Brand, Organization, FAQ, BreadcrumbList. Every page type gets the right schema. We validate against Google’s Rich Results Test and monitor for regressions weekly.

2. Machine-readable product feed

Beyond Google Shopping. A structured JSON feed that AI crawlers can consume directly — updated in real time as inventory changes, with full attributes (material, dimensions, compatibility, variants).

3. MCP endpoints

Model Context Protocol is the emerging standard for letting AI agents interact with external services. We build basic MCP endpoints that let agents query stock levels, pricing, and availability without scraping your store.

4. Conversational commerce on PDP

An on-site AI widget that answers product questions, compares variants, suggests size guidance, and handles “what’s the difference between X and Y.” Reduces support load and increases conversion on higher-consideration products.

5. Discovery monitoring

We track how often your brand and products appear in ChatGPT, Perplexity, and Google AI Overview responses for relevant queries. We report on it monthly and iterate the schema and content to improve it.

Early results

Clients who completed the full build are seeing 4-8% of new traffic attributed to AI-referred sessions within 90 days. That number is growing fast as AI shopping adoption accelerates.

The most common misconception we encounter on intake: “we need more blog posts.” In almost every case, the blog is not what’s holding back organic revenue. The category architecture is.

Why category pages matter more

A well-built category page targets high-volume, high-intent keywords at the category level. “Women’s leather bags,” “waterproof hiking boots under $200,” “B2B office furniture bulk.” These are the queries that convert. They’re also the queries where ecommerce stores consistently underperform.

A blog post about “how to choose leather bags” might rank for informational queries. A category page for “women’s leather bags” ranks for commercial queries and directly hosts the products. The revenue impact is not comparable.

The five structural problems we fix first

1. Faceted URL canonicalization

Filter URLs — size=large&color=black — are almost always generating thousands of duplicate pages. We implement canonical tags and crawl directives that consolidate authority to the base category URL without breaking the filters.

2. Thin category content

Category pages with only a grid of products and a page title are thin pages in Google’s eyes. We add above-the-fold category introductions (150-250 words), structured buying guides, and FAQ blocks — all of which feed schema and add topical depth without hurting UX.

3. Internal linking from products to categories

Product pages almost never link back to their categories with anchor text. Fixing this distributes PageRank correctly and helps Google understand category hierarchy.

4. Breadcrumb schema

BreadcrumbList schema on every page, correctly nested. This gets breadcrumbs in SERPs and helps search engines map your site structure.

5. Category page Core Web Vitals

PLPs are usually the worst-performing page type in a store. Lazy image loading, virtual scrolling, and deferred JS on filters typically move LCP by 1-2 seconds.

What happens after

We track category-level ranking share of voice monthly. Most clients see measurable movement in the first 60-90 days on priority categories.

The client called us on day two of the outage. They’d attempted a Magento 2.4.5 → 2.4.7 upgrade in-place on production, without a proper staging run, on the Friday before a major sale.

What we found

The upgrade had partially completed. The database schema was in a hybrid state — some tables updated for 2.4.7, some still on 2.4.5 structure. The cache was corrupted. Several third-party extensions were incompatible with the new version and throwing fatal errors on checkout.

The store was completely non-functional. 404 on every product page, 500 on checkout, admin panel partially accessible.

The recovery

Day one: we rolled back to the last full backup (18 hours old — they’d been running on autopilot backups, not pre-upgrade snapshots) and got the store back online on 2.4.5. Revenue loss was severe but stopped.

Day two: we audited every third-party extension for 2.4.7 compatibility. Three were blocking: a custom shipping calculator, a B2B quote module, and a legacy loyalty integration. Two had compatible versions from the vendor; one needed a custom patch.

Days three through seven: built a proper staging environment mirroring production, ran the upgrade in staging, identified and resolved every conflict, ran UAT with the client’s team.

Day eight: zero-downtime cutover using read-replica strategy — synced data to staging environment, pointed DNS, migrated remaining delta in a 12-minute window at 2am local time.

The aftermath

The upgrade was successful. We also set them up with automated pre-upgrade snapshot backups, a proper staging pipeline, and a policy that no production changes happen without a staging run first.

Total downtime including the original botched attempt: 4 days. Estimated revenue loss: ~$85k. Not recoverable, but the store is now running on a modern, maintained version of Magento with a sane deployment process.

Meta Ads Manager will tell you your ROAS is 4.2x. Your bank account will not reflect that. Here’s why the number lies, and what to use instead.

Why Meta ROAS overstates performance

Meta’s default attribution window is 7-day click, 1-day view. This means if a customer sees your ad Monday, does nothing, buys on Friday after a Google search, Meta takes full credit. So does Google. You’ve attributed the same purchase twice — or three times if they also clicked an email.

The degree of overstatement varies by business model, but for most DTC stores we see Meta’s reported ROAS running 1.5-2.5x higher than what you’d calculate from actual incremental revenue.

Three tools that give you a clearer picture

1. Post-purchase surveys

A single question on the thank-you page: “How did you first hear about us?” Unscientific, but gives you a directional read on actual influence. Stores are almost always surprised how much word of mouth and organic are under-attributed in their dashboard.

2. Geo holdout tests

Turn off Meta spend in one market (a state, a country) for 2-4 weeks. Measure the revenue difference versus a matched control market. This is incrementality testing — it tells you what Meta spend is actually adding, not what it’s claiming credit for.

3. Marketing mix modelling

At scale (typically $500k+ annual spend), MMM gives you a statistically-grounded view of contribution by channel. At smaller scale, a simplified version using weekly spend and revenue data in a regression model is surprisingly useful and not hard to build.

What we tell clients

Stop optimizing toward the ROAS number in Meta Ads Manager. Optimize toward blended ROAS — total ad spend divided by total revenue — and use the tools above to understand which channels are actually pulling weight.

This usually means reducing Meta spend somewhat and reallocating toward channels that are under-attributed (often email and SEO). In almost every case, blended ROAS goes up when you stop chasing the platform number.

We run an access audit on every new client before we touch anything. Across the last 80-odd audits, we’ve seen the same five conflicts appear again and again — independently, on stores of every size. Here they are, ranked by frequency.

1. Multiple caching plugins active simultaneously

W3 Total Cache + WP Super Cache + the hosting provider’s built-in cache is a common combination. Each one has different rules for when to invalidate cache, and they conflict constantly. Symptoms: cart contents persisting between sessions, prices not updating, logged-in / logged-out state bleeding over.

Fix: pick one caching layer, configure it properly, disable the rest.

2. Payment gateway SSL certificate mismatch

The store’s SSL certificate is issued to www.example.com but the gateway callback URL is configured to example.com (without www), or vice versa. The gateway POSTs to the wrong URL, gets a redirect, drops the POST body, and the order stays in pending. Checkout “works” but orders don’t complete.

Fix: ensure the callback URL in the payment gateway portal exactly matches the store URL in WordPress settings.

3. WooCommerce session handler conflicts with object caching

WooCommerce stores sessions in the database by default. When object caching (Redis, Memcached) is added, some configurations start caching session data without proper invalidation. Result: cart totals are stale, coupons don’t clear properly, checkout state is inconsistent.

Fix: configure WooCommerce to use its own session handler explicitly and exclude session keys from the object cache.

4. Page builder CSS interfering with checkout

Elementor, Divi, and Beaver Builder all inject global CSS. Their reset styles and grid systems frequently break WooCommerce checkout step layouts — particularly the order review column, payment method selection, and the place order button on mobile.

Fix: audit checkout pages for page builder CSS interference; usually solvable with targeted overrides scoped to woocommerce-checkout class.

5. Duplicate order bump / upsell plugins

Two different upsell plugins both hooking into woocommerce_add_to_cart and woocommerce_checkout_order_processed. Symptoms: duplicate line items, incorrect totals, failed webhook signatures because the order data is different from what was authorized.

Fix: one upsell plugin, configured properly, not two.

We redesigned a homewares brand’s product detail pages over a 6-week engagement. Conversion rate went from 2.3% to 4.2% — an 81% lift. Here are the twelve changes we made, ranked by measured impact.

High impact (test these first)

1. Move the primary CTA above the fold on mobile. Add to cart was below two carousels and a product description block. Moving it to immediately below the price increased mobile CVR by itself more than any other single change.

2. Real stock urgency, not fake urgency. “Only 3 left” when you actually have 3 left. Real stock counts pulled from the database, shown when stock drops below 10. Converts significantly better than countdown timers or fabricated scarcity.

3. Video before images. For this category (ceramic homewares), a 15-second product video showing the item in a real setting outperformed all static imagery. First image slot = video auto-playing on loop, muted.

4. Reviews near the CTA. Average rating + review count pulled up from the bottom of the page to directly below the price. Not the full review block — just the star rating and count as a link.

Medium impact

5. Size/variant selection redesign. Text buttons replaced with visual swatches where relevant. Selected state clearly indicated. Out-of-stock variants shown with strikethrough, not hidden.

6. Trust signals in the buy box. Free shipping threshold, return window, and secure payment icons placed inside the buy box, not in a separate section below.

7. Sticky add to cart on scroll. A minimal sticky bar with product title, price, and add-to-cart button that appears when the user scrolls past the main CTA. Particularly impactful on long pages.

8. Above-fold image count indicator. “1 / 8” counter on the image carousel. Users who know there are more images view more, and higher image engagement correlates with higher purchase rate.

Lower impact but worth doing

9. FAQ block with schema. Three to five common questions answered below the description. Feeds FAQ schema, reduces support contacts, and adds content for SEO.

10. Shipping estimate. “Order today, receive by [date]” calculated dynamically from warehouse location. Reduces checkout abandonment from delivery uncertainty.

11. Complementary product suggestions. “Frequently bought with” section based on actual order data, not an algorithm guess. Small lift, but the data to build it is already in the database.

12. Image alt text and filename optimization. SEO benefit rather than CRO — but image search sends a non-trivial amount of high-intent traffic to PDP pages in the homewares category.

We’ve deployed AI-assisted support triage for eleven clients in the past eighteen months. The ones that went badly all made the same mistake: they let the AI resolve too much, and CSAT dropped before anyone noticed.

The right division of labour

AI is genuinely good at: reading incoming tickets, classifying them by type and urgency, pulling relevant order data, drafting a first response, and routing to the right human. It is not good at: handling complaints from upset customers, resolving disputes, processing refunds without policy checks, or anything that requires judgement about edge cases.

The line we draw for every client: AI classifies and drafts, human reviews and sends — except for the lowest-stakes ticket types (order status enquiries with clear answers, shipping tracking requests, password resets) where we allow fully automated responses.

The build

Intake classification

Every incoming ticket gets classified into one of eight categories: order status, shipping, returns, product question, complaint, technical issue, billing, and other. Classification accuracy runs above 94% on the stores we’ve built this for.

Data enrichment

For order-related tickets, the system pulls order data, tracking status, and previous support history automatically and attaches it to the ticket before a human sees it. This alone cuts average handle time by 40%.

Draft generation

For classified ticket types with clear resolution paths, the AI drafts a response using the order data and a set of approved response templates. The human reviews, edits if needed, and sends. Not auto-sends — reviews and sends.

Escalation rules

Tickets containing specific signals — refund, lawyer, fraud, wrong, terrible, disgusting, not received — skip AI drafting and go straight to a senior support agent queue. Do not pass go.

What to measure

CSAT (obviously), first response time, average handle time, and escalation rate. If escalation rate goes up after launch, the classification is putting things in the wrong bucket. Fix the classifier, not the escalation rules.

Results across our clients

Average handle time down 38%. First response time down 61%. CSAT unchanged or slightly up (faster responses help). Support headcount flat despite growing ticket volume. Roughly the outcome you’d want.