How7o
  • Home
  • Tools
  • Prank Screens
  • Contact
  • Blog
Reading: How to Include SKU in WooCommerce Search
Share
Subscribe Now
How7oHow7o
Font ResizerAa
  • Marketing
  • OS
  • Features
  • Guide
  • Complaint
  • Advertise
Search
  • Home
  • Tools
  • Prank Screens
  • Contact
  • Blog
Follow US
Copyright © 2014-2023 Ruby Theme Ltd. All Rights Reserved.
How7o > Blog > Web Development > How to Include SKU in WooCommerce Search
Web Development

How to Include SKU in WooCommerce Search

how7o
By how7o
Last updated: May 10, 2026
8 Min Read
WooCommerce SKU search — posts_search filter injecting SKU-matched product IDs
SHARE

By default, woocommerce sku search fails — a customer searching for a product code like SHOE-002-RED gets no results. WordPress’s core search only scans post_title and post_content; SKUs live in post meta (_sku) and stay invisible. The fix is a posts_search filter that runs a parallel meta query for SKU matches and OR-merges the result IDs into the main search SQL. This guide walks through the snippet, its caveats, and when to consider an external search instead.

Contents
  • TL;DR
  • Why the default search misses SKUs
  • How the filter works
  • Scoping to product queries only
  • The brittle bit
  • When to skip this and use external search
  • Frequently asked questions
  • Related guides
  • References

Last verified: 2026-04-23 on WooCommerce 9.x with WordPress 6.5. Originally published 2023-04-01, rewritten and updated 2026-04-23.

TL;DR

add_filter( 'posts_search', 'how7o_include_sku_in_search', 999, 2 );

function how7o_include_sku_in_search( $search, $query_vars ) {
    global $wpdb;

    if ( empty( $query_vars->query['s'] ) ) {
        return $search;
    }

    $term = $query_vars->query['s'];

    $posts = get_posts( array(
        'post_type'      => 'product',
        'posts_per_page' => -1,
        'fields'         => 'ids',
        'meta_query'     => array(
            array(
                'key'     => '_sku',
                'value'   => $term,
                'compare' => 'LIKE',
            ),
        ),
    ) );

    if ( empty( $posts ) ) {
        return $search;
    }

    $id_list = implode( ',', array_map( 'absint', $posts ) );
    $search  = str_replace(
        'AND (((',
        "AND ((({$wpdb->posts}.ID IN ({$id_list})) OR (",
        $search
    );

    return $search;
}

Why the default search misses SKUs

The core WordPress search assembles a query like:

SELECT * FROM wp_posts
WHERE ...
  AND (((post_title LIKE '%term%') OR (post_content LIKE '%term%')))
  AND ...

No wp_postmeta join means no chance of matching the _sku row. WooCommerce doesn’t extend this by default — SKU-as-searchable is left to developers.

How the filter works

  • posts_search is a filter WordPress applies after it’s built the AND (((title OR content))) fragment.
  • Before the fragment is stitched into the final query, we intercept it.
  • We run a parallel get_posts() against _sku meta with LIKE, collect the matching IDs.
  • We inject those IDs as an OR-clause at the start of the search block: AND ((({posts}.ID IN (...)) OR (title OR content))).
  • The final query matches anything whose ID is in our SKU-match list or whose title/content matches.
woocommerce sku search — posts_search filter injects meta-queried IDs into the title/content SQL

Scoping to product queries only

add_filter( 'posts_search', function ( $search, $query ) {
    if ( ! is_search() || $query->get( 'post_type' ) !== 'product' ) {
        return $search;
    }

    // ... (filter body as above)
    return $search;
}, 999, 2 );

The base snippet fires on every search, including post and page searches — wasteful even though the meta_query is scoped to products. Wrapping with is_search() plus the post_type check skips non-product searches entirely.

The brittle bit

$search = str_replace( 'AND (((', "AND ((({$wpdb->posts}.ID IN ({$id_list})) OR (", $search );

WordPress generates the search fragment with a distinctive AND ((( prefix, which this str_replace targets. It’s worked for many years but is technically tied to WordPress’s internal SQL generator. If a future WordPress release changes the fragment shape, this str_replace silently stops matching and SKU search stops working — no error, just empty results. Watch for it on major version upgrades (test a SKU search after updating core).

When to skip this and use external search

  • Catalogs over ~10,000 products — the get_posts with -1 scans every SKU on every search. Fine at a few hundred products, slow at tens of thousands.
  • Need typo-tolerance / ranking — “SHOE-002-RED” vs “shoe 002 red” are very different to MySQL’s LIKE; they’re the same to ElasticPress, Algolia, or Meilisearch.
  • Need multi-field fuzzy matching — search against SKU + attribute + category + description with relevance scoring. MySQL LIKE is out of its depth here.

For small catalogs where the native filter works, keep this snippet. For production shops, an external index is the appropriate tool.

Frequently asked questions

Why doesn’t the default woocommerce sku search find products by SKU?

Because WordPress’s core search only scans post_title and post_content. SKUs live in product meta (_sku row in wp_postmeta), which the default LIKE query never touches. Extending the search to match SKUs requires filtering posts_search to inject an OR-clause that also matches products whose meta _sku value contains the term.

Does the filter affect search results on every post type?

It’s scoped with 'post_type' => 'product' inside the meta query, so only products match by SKU. Other post types (posts, pages) still only match by title/content. But the filter itself fires on every search query, so if your theme runs the search form across mixed post types, the meta_query runs every time — harmless but an extra query. For scope, wrap the filter body in is_search() && $query->get('post_type') === 'product'.

Will this include products without an SKU?

The filter only adds matching products with an SKU to the result set; it doesn’t exclude SKU-less products from title/content matches. A search for ‘shoes’ will still match both a product titled ‘Running Shoes’ (no SKU needed) and a product with SKU SHOES-001 via the meta clause — the OR’ing is additive.

Is the str_replace on the SQL safe?

Yes, because AND ((( is a stable string literal in WordPress’s generated search SQL — it marks the start of the search clause group, and the replacement injects our own post-ID list before that. It’s not elegant — it’s a workaround for a filter that gives you the SQL fragment rather than structured data. If WordPress ever changes the literal, the filter silently stops matching. Keep an eye on major WP version changes.

Is there a cleaner approach using pre_get_posts?

You can set the meta_query directly in pre_get_posts, but the catch is that WordPress’s search uses the s parameter to build its own SQL, and combining that with a meta_query results in AND (match title AND sku), not the OR you want. The posts_search filter is the pragmatic path — ugly, works. For a more robust solution, an external search layer (ElasticPress, Algolia, Meilisearch) indexes SKUs as searchable fields natively.

Related guides

  • How to Prepare a %LIKE% SQL Statement in WordPress — the raw $wpdb LIKE mechanics behind WordPress’s search.
  • How to Search Users by Multiple Fields in WordPress — the same “search across multiple fields” problem on the user side.
  • How to Display a Product View Counter in WooCommerce Without a Plugin — another meta-based product enhancement.
  • How to Apply pre_get_posts on Custom Post Types in WordPress — cousin query-modification pattern.

References

WordPress developer reference for posts_search: developer.wordpress.org/reference/hooks/posts_search.

TAGGED:mysqlphpsqlWooCommercewordpress

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Copy Link Print
Previous Article WooCommerce get customer ID from order — WC_Order::get_user_id How to Get the Customer ID from an Order ID in WooCommerce
Next Article WooCommerce remove checkout fields — woocommerce_checkout_fields filter unsetting fields How to Remove Checkout Fields in WooCommerce
Leave a Comment

Leave a Reply Cancel reply

You must be logged in to post a comment.

FacebookLike
XFollow
PinterestPin
InstagramFollow

Subscribe Now

Subscribe to our newsletter to get our newest articles instantly!
Most Popular
Display PHP errors — ini_set + php.ini configuration
How to Display PHP Errors
May 10, 2026
PHP convert string to uppercase — strtoupper and mb_strtoupper
How to Convert a String to Uppercase in PHP
May 10, 2026
PHP string to float conversion with cast, regex cleanup, NumberFormatter
How to Convert a String to Float in PHP
May 10, 2026
PHP merge arrays without duplicates — union operator and array_unique
How to Combine Two Arrays Without Duplicates in PHP
May 10, 2026
PHP delete array element — unset, array_splice, array_filter, array_search
How to Delete an Element from a PHP Array
May 10, 2026

You Might Also Like

Deleting a Laravel user cascades to remove related posts, photos, and notifications
Web Development

How to Delete Related Records in Laravel Eloquent

6 Min Read
Return or throw an error in Laravel (JSON response vs exception)
Web Development

How to Manually Return or Throw an Error Exception in Laravel

6 Min Read
WordPress prepare LIKE SQL — %s placeholder + % wildcards in the value
Web Development

How to Prepare a %LIKE% SQL Statement in WordPress

7 Min Read
Laravel updateOrCreate method shown in an Eloquent code snippet with insert and update branches
Web Development

Laravel updateOrCreate: Insert or Update Records in Eloquent

8 Min Read
How7o

We provide tips, tricks, and advice for improving websites and doing better search.

Latest News

  • SEO Audit Tool
  • Client ReferralsNew
  • Execution of SEO
  • Reporting Tool

Resouce

  • Google Search Console
  • Google Keyword Planner
  • Google OptimiseHot
  • SEO Spider

Get the Top 10 in Search!

Looking for a trustworthy service to optimize the company website?
Request a Quote
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?