8 min readwoocommerce searchWooCommercetypossite search

"figrua" returns nothing: WooCommerce search and typos

18 products for "figura", zero for "figrua". Measured today on a real 1,473-product store where, over 47 days, 131 words were typed wrong across 254 searches. Here is how to find yours and what you can fix today.

Open your store and do this. It takes fifteen seconds.

Search for a word of yours, one that appears in several products. Now search for it again with two letters swapped, the way you type when you're going fast on a phone.

This is what a real WooCommerce collectibles store with 1,473 products returned today, 25 August 2026:

Search Products
figura 18
figrua 0
vegeta 18
vegueta 0
attack 17
atack 0

One letter. That's the whole difference between a shop window and a page that says "no products were found".

What WooCommerce actually does

It isn't a bug, and it's worth understanding before going looking for someone to blame: WooCommerce does exactly what it says on the tin.

When somebody searches, WordPress splits the phrase into words and requires every one of them to appear, letter for letter, inside a product's title, excerpt or description. In SQL it's roughly this:

WHERE (post_title LIKE '%figrua%' OR post_content LIKE '%figrua%')
  AND (post_title LIKE '%one%'    OR post_content LIKE '%one%')

figrua appears nowhere in your catalogue, because you never misspelled it. So the condition is never satisfied and the result is zero. It doesn't matter that you stock fifty figures: this is string comparison, not search.

That has one useful consequence almost nobody notices: half-typed words do work. If someone types narut mid-keystroke, LIKE '%narut%' finds "Naruto" just fine, because it's a substring. Native search copes well with you typing too little. What it can't cope with is you typing it wrong.

And one letter too many, one too few, or two swapped isn't "too little". It's a different word.

How often this really happens

This is usually where the argument starts: sure, but that happens once a month. So I measured it.

This is 34,399 real searches on that same store, with 1,473 active products, between 10 July and 25 August 2026 — 47 days.

I took the 500 most-searched queries, which account for 15,121 searches (44% of the total), and simulated WordPress's literal matching against the catalogue. The result: 60 of those 500 queries would return zero, and that's 1,385 searches, 9.2%.

That 9.2% is several things mixed together — brands the store doesn't carry, acronyms, phrases — and not all of it is a typo. So I went after pure typos, the ones that are unambiguously a word of yours, spelled wrong:

131 distinct misspelled words, across 254 searches.

That's a floor, not a ceiling: it only counts words that appear in no product at all, not even as part of another one, and that closely resemble one that does. Even so, a handful of examples:

Typed Should be Times
atack attack 35
ichibanso ichibansho 16
chuuya chuya 10
krilin krillin 9
lufy luffy 8
bleacj bleach 8

The part I didn't expect

The two most repeated typos in the whole store aren't in that table. And why they aren't is the most interesting thing here.

They're these:

Typed Should be Times Native search
figrua one piece figura one piece 73 0 results
vegueta vegeta 49 0 results

Seventy-three people typed figrua. It isn't a difficult Japanese name: it's the Spanish word "figura", with the r and the u swapped. The most human keyboard slip there is.

They're missing from the table above because the method almost everyone uses to detect typos — comparing trigrams, groups of three consecutive letters — is terrible at exactly this. "figura" breaks into fig, igu, gur, ura. "figrua" breaks into fig, igr, gru, rua. They share one. To a trigram matcher these are two different words.

So the most frequent real-world typo is also the one that standard fuzzy matching handles worst. If your search plugin claims to "tolerate typos", it's worth testing this specific case before trusting it.

How to find yours

The awkward part of all this is that WooCommerce doesn't store searches. Not the term, not how many results it returned. That information passes through your server and is thrown away.

Twenty lines fix it. Save this as wp-content/mu-plugins/search-log.php — you can create the mu-plugins folder if it doesn't exist, and anything inside it activates on its own:

<?php
/**
 * Plugin Name: Search log
 * Description: Records every store search and how many results it returned.
 */

add_action('wp', function () {
    if (is_admin() || !is_search() || !is_main_query()) {
        return;
    }

    $term = trim(get_search_query());
    if ($term === '') {
        return;
    }

    global $wp_query, $wpdb;
    $table = $wpdb->prefix . 'searches';

    // The table is created once, not on every search.
    if (get_option('search_log_table') !== '1') {
        $wpdb->query("CREATE TABLE IF NOT EXISTS {$table} (
            id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
            term VARCHAR(191) NOT NULL,
            results INT NOT NULL,
            created DATETIME NOT NULL,
            INDEX idx_term (term),
            INDEX idx_created (created)
        ) {$wpdb->get_charset_collate()}");
        update_option('search_log_table', '1');
    }

    $wpdb->insert($table, [
        'term'    => mb_substr($term, 0, 191),
        'results' => (int) $wp_query->found_posts,
        'created' => current_time('mysql'),
    ]);
});

Leave it running for a week. Then, the query that matters:

SELECT term, COUNT(*) AS times
FROM wp_searches
WHERE results = 0
GROUP BY term
ORDER BY times DESC
LIMIT 50;

(Swap wp_ for your own table prefix if yours is different.)

With WP-CLI it's a single line from the server:

wp db query "SELECT term, COUNT(*) times FROM wp_searches WHERE results=0 GROUP BY term ORDER BY times DESC LIMIT 50" --skip-column-names

That list is by some distance the most profitable document in your store. Every line is someone who told you what they wanted to buy and left empty-handed. And there are only three explanations, all three actionable: you don't stock it (now you know what to buy), you stock it under another name (a synonym fixes it), or they typed it wrong (this).

What you can fix today, for free

Once you have your twenty or thirty most frequent typos, correct them by hand. Another file in mu-plugins:

<?php
/**
 * Plugin Name: Search corrections
 * Description: Replaces frequent typos before searching.
 */

add_action('pre_get_posts', function ($query) {
    if (is_admin() || !$query->is_search() || !$query->is_main_query()) {
        return;
    }

    // Your list, taken from the query above: misspelled => correct.
    $corrections = [
        'figrua'  => 'figura',
        'vegueta' => 'vegeta',
        'atack'   => 'attack',
        'lufy'    => 'luffy',
        'krilin'  => 'krillin',
    ];

    $words = preg_split('/\s+/', mb_strtolower($query->get('s')), -1, PREG_SPLIT_NO_EMPTY);
    if (!$words) {
        return;
    }

    $changed = false;
    foreach ($words as $i => $word) {
        if (isset($corrections[$word])) {
            $words[$i] = $corrections[$word];
            $changed = true;
        }
    }

    if ($changed) {
        $query->set('s', implode(' ', $words));
    }
});

Five minutes, zero euros, and you recover the searches that repeat most. If your store is small and your product names are ordinary words, this will probably do.

Where it stops working

It has a limit, and it's fair to say so: 131 distinct words in 47 days, on a single store. A hand-written map isn't going to keep that pace, and every new product brings new names people will misspell in ways you don't know yet.

Past that point the correction has to be automatic, and this is where it gets genuinely technical, because no single method is enough:

  • Trigram fuzzy matching (pg_trgm in Postgres, for instance) handles wrong, extra and missing letters. It's what most search plugins call "typo tolerance".
  • But it fails on transpositions, which as we just saw are the most frequent kind. That needs a different comparison: edit distance, or understanding the word rather than comparing it.
  • And it doesn't fix the other problem, the vocabulary one: someone types "hoodie" and you wrote "sweatshirt". That isn't a typo, it's another language. It takes synonyms, or semantic search.

What works is running all three at once — literal, fuzzy and semantic — and fusing the results, rather than picking one and hoping. Which is what a dedicated search engine does, and what LIKE '%figrua%' will never do.


In order, what I'd do this week:

  1. The fifteen-second test. One word of yours, spelled right and spelled wrong. If it's 18 against 0, you know the problem exists on your store.
  2. Paste in the search log. It's what turns this from a hunch into a number of your own.
  3. After seven days, read the zero-result list. It will sting, and it will be useful.
  4. Correct the top ten by hand. It's the best effort-to-money ratio in ecommerce.
  5. If the list grows faster than you maintain it, that's the signal it's time for a search engine that does it on its own.

If you're at that last point, we have the full guide on how to choose an ecommerce search engine, with each option's prices verified and a section on when each competitor is better than us. And if what you want is to put a euro figure on the hole, there's how much your ecommerce search is costing you, with the order data from this same store.

Is your store losing sales to searches that find nothing?

WildRock adds a search to your WooCommerce that understands what shoppers mean, and tells you in euros how much it generates. Free plugin, no code.