Using a given parameter as a where condition in GROQ in Sanity.io
Unfortunately, you cannot inject query fragments, conditions, or operators as string parameters in GROQ. As explained in the GROQ Parameters documentation, parameters using the $ syntax are designed to inject values only - they must be JSON literals and cannot contain GROQ expressions, field paths, or operators.
This is by design for security and parsing reasons. Your approach won't work:
// ❌ This won't work
*[_type == "product" && $superComplexCondition]Your Best Options
1. Build the entire query string dynamically (most flexible)
Instead of using parameters for the condition, construct the full GROQ query as a string:
const superComplexCondition = `(status == "active" && price > 100 && (category == "electronics" || category == "gadgets"))`;
const productsQuery = `*[_type == "product" && ${superComplexCondition}]{
_id,
title
}`;
const products = await sanityFetch<ProductsQueryResponseType>({
query: productsQuery,
params: {
language: 'en',
},
cache: 'no-store',
});Security note: If you're building queries from any user input, be extremely careful about GROQ injection attacks. Sanitize and validate all values.
2. Use multiple parameters for individual values (safer)
Break down your complex condition into individual value parameters that GROQ can handle:
const queryParams = {
status: 'active',
minPrice: 100,
category1: 'electronics',
category2: 'gadgets',
};
const productsQuery = groq`
*[_type == "product" &&
status == $status &&
price > $minPrice &&
(category == $category1 || category == $category2)
]{
_id,
title
}
`;
const products = await sanityFetch({
query: productsQuery,
params: queryParams,
});This approach keeps you safe from injection issues while maintaining flexibility. As noted in this discussion about GROQ security, using parameters for values prevents syntax errors from special characters and GROQ injection attacks.
3. Server-side query builder function
If your conditions are truly complex and dynamic based on external API data, consider building a validated query builder:
function buildProductQuery(externalData: ComplexConditions) {
// Transform your external API data into safe GROQ conditions
const whereClause = constructSafeWhereClause(externalData);
return `*[_type == "product" && ${whereClause}]{
_id,
title
}`;
}The first approach (dynamic query string building) is the most common solution when you need truly dynamic conditions based on complex external data from another API endpoint, but remember to handle any untrusted input carefully to avoid injection vulnerabilities.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.