This was a clothing storefront with Sanity merchandising
Next.js. Shopify catalog in Algolia. Sanity CMS documents for pins, hides, boosts. InstantSearch rendered whatever the index had after the merch pass. If the Groq filter looked at the pretty type name, Sanity returned zero documents and Algolia got a no-op.
What they would notice if it failed
A merchandiser pinned a hero SKU in Sanity. The PLP ignored it. They edited the document again. Still ignored. They blamed InstantSearch. InstantSearch was fine. The query never loaded the rule.
The puzzle: the label is not the id
Sanity schema types have an id and a title. title is what the desk shows: "Collection merchandising." id is what Groq sees: collectionMerch, or whatever you registered. I filtered *[(_type == "Collection merchandising") && locale == $locale]. Zero hits. Always. The documents sat right there in the desk.
_type is the schema id. Always. The title can change because someone wanted a nicer label. The id is the contract.
*[_type == "collectionMerch" && locale == $locale]{
_id,
collectionHandle,
pinned[]->{ sku },
hidden[]->{ sku }
}Then the server writes those pins onto the Algolia index (or a replica) with the admin client. InstantSearch on the storefront keeps using the search-only key and never talks to Sanity.
If you need to show the label in the UI, read title from the schema, not from _type. If you need to query, you want the id you put in defineType({ name: 'collectionMerch' }). That name is _type. The string in the desk heading is decoration.
I stopped matching English. I matched the schema. Pins showed up. Merchandisers stopped pinging me.
Happy coding!
Sander