Sitecore XM Cloud GraphQL: A Practical Guide to Building Efficient Content Queries

Sitecore XM Cloud GraphQL: A Practical Guide to Building Efficient Content Queries

Sitecore

Introduction

Sitecore XM Cloud is a headless CMS. This implies that while the content is hosted on Sitecore, the presentation can be hosted anywhere, often a modern frontend such as Next.js. However, there is one question that is always raised when using headless architecture: how will the frontend obtain the required content?

In that regard, GraphQL provides the answer. Unlike traditional APIs that return a certain payload from an endpoint, GraphQL allows the frontend to ask for exactly the fields it requires.

But writing such a query is quite straightforward. Real projects grow: content structures deepen, templates multiply, items get translated, and references start pointing at other references. Queries grow with them.

Queries that grow carelessly pull back fields nobody uses, become difficult to change, and eventually break against endpoint limits on query depth.

This article covers the techniques that keep queries lean as a project scales. Rather than surveying every GraphQL feature, it focuses on what developers reach for most often when building headless Sitecore applications:

  • GraphQL search queries
  • _path and _templates filtering
  • Language filtering
  • GraphQL variables
  • Multilist and reference fields
  • Query optimization
  • Common GraphQL errors

The examples use a tournament-based content structure, but the same principles apply to news, teams, FAQs, products, events, and any other structured Sitecore content.

Why Use GraphQL with Sitecore XM Cloud?

In a traditional API approach, an endpoint generally determines what information is returned. This can sometimes result in an application receiving more data than it actually needs.

GraphQL takes a different approach. The client defines the fields it wants in the query.

For example, a tournament listing component may only require:

  • Tournament ID
  • Tournament name
  • Tournament logo
  • Tournament status

There is little benefit in retrieving every field stored on the Tournament item if the component does not use them.

This makes GraphQL particularly useful for headless Sitecore implementations because developers can design queries around the requirements of individual frontend components.

A simplified architecture looks like this:

Sitecore XM Cloud

        |

        | GraphQL

        v

    Next.js App

        |

        v

   React Components

Sitecore remains responsible for content management, while the frontend consumes the required content through GraphQL.

Understanding Sitecore GraphQL Search

One of the most useful capabilities when working with Sitecore content is searching for multiple items based on specific conditions.

Instead of requesting individual items one at a time, a search query can locate content based on its location, template, language, or other indexed properties.

This is particularly useful for components such as:

  • Tournament lists
  • Team lists
  • Search results

For example, imagine a Sitecore content structure like:

Data

β”œβ”€β”€ Tournaments

β”‚   β”œβ”€β”€ Tournament A

β”‚   β”œβ”€β”€ Tournament B

β”‚   β””── Tournament C

β”‚

└── Teams

    β”œβ”€β”€ Team A

    β”œβ”€β”€ Team B

    β””── Team C

If a component needs all Tournament items, it would be better to search within the Tournament folder rather than querying every tournament individually.

This is where _path becomes useful.

Example 1: Searching Content Using _path and _templates

A practical Sitecore GraphQL search query can combine _path, _templates, and a language variable.

query TournamentList($language: String!) {

  search(

    where: {

      AND: [

        {

          name: "_path"

          value: "{TOURNAMENT-FOLDER-ID}"

          operator: CONTAINS

        }

        {

          name: "_templates"

          value: "{TOURNAMENT-TEMPLATE-ID}"

          operator: CONTAINS

        }

      ]

    }

    language: $language

  ) {

    results {

      items {

        id

        name

      }

    }

  }

}

The corresponding variables are:

{

  "language": "en"

}

Understanding the Query

There are several important concepts in this example.

_path

The _path condition defines the area of the Sitecore content tree that should be searched.

{

  name: "_path"

  value: "{TOURNAMENT-FOLDER-ID}"

  operator: CONTAINS

}

Instead of searching the entire content tree, the query limits the search to items located beneath the specified folder.

This is useful for dynamic content because new tournament items can be created by content authors without requiring a developer to update the query.

For example:

Data

└── Tournaments

   β”œβ”€β”€ Tournament A

   β”œβ”€β”€ Tournament B

   β””── Tournament C

When another tournament is added below the same folder, it can be discovered by the same query.

_templates

The _templates condition identifies the type of content that should be returned.

{

  name: "_templates"

  value: "{TOURNAMENT-TEMPLATE-ID}"

  operator: CONTAINS

}

This is particularly useful when a folder contains different types of Sitecore items.

Using _path together with _templates gives the query two levels of control:

Where should Sitecore search?

_path

and:

What type of item should Sitecore return?

_templates

Combining these conditions helps prevent unrelated content from being returned to the frontend.

Language Filtering with GraphQL Variables

Multilingual content is common in Sitecore XM Cloud implementations.

A tournament may have different language versions:

Tournament

β”œβ”€β”€ English

└── Arabic

Instead of creating separate queries for every language, a variable can be used.

The query defines:

query TournamentList($language: String!) {

and the language is supplied separately:

{

  "language": "en"

}

For Arabic content, the same query can be reused:

{

  "language": "ar"

}

This approach provides a clean separation between the query itself and the values supplied to it.

It also makes the query easier to reuse from a Next.js application where the current language may be determined dynamically from the application's routing or localization configuration.

Why GraphQL Variables Matter

Variables are useful whenever a value changes between requests.

Without variables, developers may be tempted to create multiple versions of the same query with different values.

For example:

TournamentListEnglish

TournamentListArabic

TournamentListJapanese

This creates unnecessary duplication.

Instead, one query can accept a language variable:

query TournamentList($language: String!) {

    ...

}

The application can then provide:

{

  "language": "en"

}

or:

{

  "language": "ar"

}

The same principle can be applied to other dynamic values such as item IDs, search terms, paths, or pagination parameters.

Working with Multilist and Reference Fields

Sitecore content models frequently contain relationships between items.

For example, a Tournament template may contain a multilist field called Teams, allowing content authors to select multiple Team items.

The relationship can conceptually look like this:

Tournament

  |

  +-- Team A

  +-- Team B

  +-- Team C

In this situation, the frontend may need the actual referenced Team items rather than only the IDs stored in the multilist field.

GraphQL can expose the referenced items through the field's target items.

Example 2: Retrieving Referenced Items

The following example demonstrates a Tournament item with a teams reference field:

query Tournament($language: String!) {

  item(

    path: "/sitecore/content/FanID Platform/FanID/Data/Tournaments/Example"

    language: $language

  ) {

    ... on Tournament {

      name

      teams {

        targetItems {

          id

          name

        }

      }

    }

  }

}

The variables are:

{

  "language": "en"

}

The important part of the query is:

teams {

  targetItems {

    id

    name

  }

}

Instead of working with a raw collection of referenced item IDs, the query requests the properties required from the referenced Team items.

This can simplify frontend development because the application receives structured content that can be directly mapped to a component.

For example, a tournament component could use the returned Team information to render a list of participating teams.

The same approach can be applied to other Sitecore relationships, such as:

  • Related articles
  • Categories
  • Countries
  • Stadiums
  • Authors
  • Related tournaments

The exact fields available depend on the Sitecore template and GraphQL schema used by the implementation.

Avoiding Unnecessary Reference Expansion

References are useful, but developers should be careful when expanding them.

Imagine a content relationship such as:

Tournament

  β†“

Teams

  β†“

Country

  β†“

Stadium

  β†“

Location

It can be tempting to retrieve everything through one large GraphQL query.

However, if the frontend only needs the team name and logo, retrieving the country, stadium, and location adds unnecessary complexity.

A better approach is to request only what the component needs.

For example, a tournament card may require:

  • Tournament Name
  • Team Name
  • Team Logo

There is no reason to retrieve unrelated content simply because it is available through a reference.

This leads to one of the most important GraphQL development principles:

Request the content required by the component, not everything available in the content model.

GraphQL Query Optimization

A GraphQL query can be technically correct and still be inefficient.

When developing Sitecore XM Cloud applications, optimization should be considered from the beginning rather than after performance problems appear.

1. Limit the Search Scope

Use _path to restrict the search to the relevant section of the Sitecore content tree.

For example, if tournaments are stored under a specific folder, search within that folder instead of searching the entire content tree.

This makes the intent of the query clearer and helps avoid unrelated results.

2. Filter by Template

Use _templates when the search location can contain multiple types of content.

This allows the query to return only the content type required by the component.

The combination of:

_path + _templates

is a useful pattern for structured Sitecore content searches.

3. Request Only Required Fields

Avoid returning fields that the frontend does not use.

If a component only needs:

  • id
  • name
  • image

there is little reason to request dozens of additional fields.

Smaller responses are easier to process and maintain.

4. Avoid Excessive Query Depth

GraphQL makes it easy to navigate through related content, but deeply nested queries can become expensive.

For example:

Tournament

 β†’ Teams

   β†’ Country

     β†’ Stadium

       β†’ Location

If the frontend does not need all of this information, do not retrieve it.

Deep nesting can also cause the query to exceed the maximum depth supported by the GraphQL endpoint.

5. Reuse Queries with Variables

Variables make a query reusable.

Instead of creating separate queries for each language or dynamic value, create one query and pass the required value as a variable.

This reduces duplication and makes frontend integration cleaner.

Common Sitecore GraphQL Errors

Even a well-designed query can fail if it does not match the GraphQL schema or exceeds endpoint limitations.

Here are some common issues developers may encounter.

Query Is Too Nested

One possible error is:

Query is too nested to execute.

Depth is 17 levels, maximum allowed on this endpoint is 15.

This means the query has exceeded the maximum nesting depth configured for the endpoint.

This is usually caused by expanding too many nested relationships.

If the application genuinely needs information from multiple levels, consider whether the data can be retrieved through separate, smaller requests.

Cannot Query a Field

Another common error is similar to:

Cannot query field "tournaments" on type "Item".

GraphQL is strongly typed. A field may be available only on a specific type and not on the generic Item type.

When this occurs, inspect the GraphQL schema and verify the type associated with the field.

In some cases, an inline fragment may be required:

... on Tournament {

  ...

}

The exact type and available fields depend on the schema generated by the Sitecore implementation.

Empty Search Results

A query may execute successfully but return:

{

  "items": []

}

This does not necessarily indicate a GraphQL problem.

When this happens, check:

Content Path

Verify that the _path value points to the expected Sitecore item.

Template ID

Verify that the content item is based on the template specified in _templates.

Language

Check whether the requested language version exists.

Content Availability

Verify that the content is available in the environment and context where the query is being executed.

Search Index

If the query depends on Sitecore search, verify that the expected content is available to the relevant index.

Building GraphQL Queries Based on Components

One of the best approaches to keep GraphQL queries easy to handle is to think of them in terms of frontend components.

For example, suppose a Tournament List component needs:

  • Tournament Name
  • Tournament Logo
  • Start Date
  • Status

The GraphQL query should be designed around those requirements.

A common mistake is to think:

"What data does this Sitecore item contain?"

A better question is:

"What data does this component actually need?"

This small change in thinking can prevent unnecessarily large queries.

Conclusion

GraphQL simplifies content delivery in Sitecore XM Cloud by allowing developers to retrieve only the data required by their applications. Filters like _path and _templates, language variables, and structured references make it possible to construct focused, reusable queries.

By avoiding unnecessary fields and deep nesting, developers can build GraphQL queries that are efficient, maintainable, and scalable for headless Sitecore applications.

Written by
Meet Shah Author

Meet Shah

Sitecore Expert

I’m Meet Shah, a Sitecore Certified Software Developer at Arroact Technologies. I work with Sitecore XP, Sitecore Order Cloud, and .NET to build digital experiences that connect content, commerce, and data in a way that actually makes sense for users and teams. 

I’m especially interested in how Sitecore AI can be used to create smarter, more personalized experiences. I like exploring how small improvements in logic or structure can make a big difference in how a system performs and feels. 

Most of my work revolves around taking complex ideas and turning them into solutions that are clear, reliable, and easy to work with. I enjoy building things that don’t just work but continue to work well as they grow. 

Related Blogs blue-line-vector-3

Developing Code Assistants and AI Prompts in Sitecore Stream
21 August 26 β€’ 10 min read
Sitecore
Developing Code Assistants and AI Prompts in Sitecore Stream
Most personalization bugs don’t come from the architecture. They come from the tiny bits: …
Read More
Integrating Sitecore Search APIs: Custom Schema Mapping and GraphQL Integration
20 August 26 β€’ 16 min read
Sitecore
Integrating Sitecore Search APIs: Custom Schema Mapping and GraphQL Integration
Search is among those functionalities which appear simple in demonstrations but start be…
Read More
Taming Environment Sprawl: A Practical Governance Framework for Sitecore Cloud Portal
14 August 26 β€’ 12 min read
Sitecore
Taming Environment Sprawl: A Practical Governance Framework for Sitecore Cloud Portal
If you have worked with  Sitecore Cloud Portal for more than a few months, you alrea…
Read More
Make Smarter Decisions with an Accurate Sitecore Project Estimate. Get Your Free Sitecore Project Estimate
Get Project Estimate