Shopify GraphQL Metafield Filtering: The Hidden Setting You're Missing!

Hey there, fellow store owners and developers!

I've been sifting through some recent discussions in the Shopify community, and a common head-scratcher popped up that I just had to share. It's about something many of us run into when trying to get specific with our data: filtering products by metafields using GraphQL. This particular thread, started by Constantine_Kulak, perfectly illustrates a subtle but absolutely critical setting that can make or break your GraphQL queries.

Constantine was trying to pull a list of products that had a specific image metafield (metafields.custom.my_image) attached to them. Sounds straightforward, right? His initial query looked something like this:

query Q {
  products(
    first: 250
    query: "metafields.custom.my_image:*"
  ) {
    nodes {
      id
      metafield(namespace: "custom", key: "my_image") {
        reference {
          ... on MediaImage {
            image {
              url
            }
          }
        }
      }
    }
  }
}

The problem? No matter what he tried, this query kept returning all products, not just the ones with the image metafield. It's a frustrating experience when you're sure your syntax is right, but the results just aren't what you expect.

The Hidden Key: Enabling Metafield Filtering

This is where the collective wisdom of the community really shines! Our sharp-eyed community member, @tim_1, pointed out the often-overlooked culprit: a setting within the metafield definition itself. He rightly directed everyone to the Shopify documentation, highlighting this crucial tidbit:

And boy, was that the answer! As @tim_1 demonstrated with his own test store, before enabling this setting, his queries would return all products. After checking that little box, suddenly, everything worked as expected. He even shared a helpful screenshot:

How to Enable Filtering for Your Metafields

This is super easy to do in your Shopify admin. Here’s a quick rundown:

  1. Go to your Shopify admin.
  2. Navigate to Settings.
  3. Click on Custom data.
  4. Select the resource type your metafield is attached to (e.g., Products if you're filtering products).
  5. Find the specific metafield definition you want to filter by (in Constantine's case, it was custom.my_image) and click on it.
  6. Under the Options section, you’ll see a checkbox labeled "Use for filtering in admin" (or something similar, depending on updates). Make sure this box is checked!
  7. Save your changes.

Once you’ve done this, your GraphQL queries that use that metafield for filtering should start working as intended!

Constantine's Success & Further Insights

Constantine quickly confirmed that @tim_1's advice was spot on. Enabling admin filtering made his original query, metafields.custom.my_image:*, work perfectly! He even experimented with a few other syntaxes, like metafields.custom.my_image:'*', metafields.custom.my_image:"*", and metafields.custom.my_image:"gid://shopify/MediaImage/*", but found that only the simpler metafields.custom.my_image:* worked for him once filtering was enabled.

This is an important distinction, because another community member, @lumine, provided some excellent context on why filtering by reference types (like a MediaImage) can be tricky. As @lumine explained, the metafields..:* syntax doesn't always behave as expected for "has any value" because the wildcard only matches against fields the indexer has tokenized. Metafield references aren't tokenized as simple strings, which can lead to the predicate evaluating true for every product if filtering isn't properly enabled.

@lumine also offered some advanced strategies for situations where direct filtering might still be challenging or if you're dealing with very large catalogs:

  • For simple metafield types (like single_line_text, integer, boolean), metafields.custom.my_image:'gid://shopify/MediaImage/*' might occasionally work, but it's not always reliable for references.
  • A more robust approach for complex scenarios is to query all products that *could* have the metafield, select the metafield field, and then filter client-side on metafield !== null. With cursor pagination and fetching first: 250 items, this can be quite efficient for many catalogs.
  • For a long-term, highly reliable solution, @lumine suggested using a webhook (specifically products/update) to write a boolean "shadow" metafield, like has_image: true. This gives you a simple boolean value that you can reliably filter on with metafields.custom.has_image:true. This is a clever workaround for advanced use cases where direct filtering isn't cutting it.

However, for Constantine's original problem and for most common scenarios, the primary fix was simply enabling that "Use for filtering in admin" setting. It's a great reminder that sometimes the simplest solution is hiding in plain sight, often tucked away in a setting you might not immediately connect to your API queries.

So, if you're ever scratching your head wondering why your GraphQL product filters aren't working for metafields, don't forget to double-check that "Admin Filterable" setting on your metafield definition. It's a common oversight, and as this community thread shows, it's usually the magic bullet!

Share:

Start with the tools

Explore migration tools

See options, compare methods, and pick the path that fits your store.

Explore migration tools