Migrating GraphQL Queries from Sitecore XP to XM Cloud: Key Differences and Best Practices

As Sitecore transitions from the traditional XP platform to the modern XM Cloud architecture, developers will notice significant differences in how GraphQL queries are structured and executed.

When migrating component queries from XP to XM Cloud, it’s essential to adjust your approach to ensure compatibility. This is primarily because XM Cloud relies on Sitecore Search-based GraphQL, unlike XP, which used an item-based querying model.

🧩 Component GraphQL Query Example — Sitecore XP

query GetPageContent($datasource: String!) {
  datasource(value: $datasource) {
    id(format: "B")
    ...participatingList
  }
}

fragment participatingList on CampaignParticipatingRestaurants{
  title{value}
  tagline{value}
  cards:restaurants{
    restaurants:targetItems{...Restaurant}
  }
}

fragment Restaurant on Restaurant{
  cuisine{targetItems{...cuisineType}} ctaLink:url
  restaurantDetails:children{
    restaurantName:children(includeTemplateIDs:"{4D154240-9085-441B-A8B0-59DD4B75E39E}"){...RestDetails}}
  primaryHotel{targetItem{...Hotel}}
}

fragment cuisineType on RestaurantTags{title{value}}

fragment RestDetails on RestaurantDetails{title{value} backgroundImage{src}}

fragment Hotel on Hotel{hotelName:menuTitle{value}}


🧩 Component GraphQL Query Example — Sitecore XM Cloud

query GetPageContent($datasource:String!, $language:String!) {
 search(
    where: {
      AND: [
	{
          name: "_templates"
          value: "{A5C21E2A-6575-4548-9444-70079F4BE6B4}"
          operator: EQ
        }
        {
          name: "_path"
          value: $datasource
          operator: EQ
        },{ name: "_language",  value: $language }
      ]
    }
  ) 
  {
    results
    {
      id
    ...participatingList
    }
  }
}

fragment participatingList on CampaignParticipatingRestaurants{
  title{value}
  tagline{value}
  cards:restaurants{
    restaurants:targetItems{...Restaurant}
  }
}

fragment Restaurant on Restaurant{
  cuisine{targetItems{...cuisineType}} 
  ctaLink:field(name:"Reserve Now CTA Link")
  {
    jsonValue
  }
  restaurantDetails:children{
    results{
      restaurantName:children(includeTemplateIDs:"{4D154240-9085-441B-A8B0-59DD4B75E39E}")
    	{
        results{
         ...RestDetails 
        }
      }
    }
    	
  }
  primaryHotel{targetItem{...Hotel}}
}

fragment cuisineType on RestaurantTags{title{value}}

fragment RestDetails on RestaurantDetails{title{value} backgroundImage{jsonValue}}

fragment Hotel on Hotel{hotelName:menuTitle{value}}
  

🔍 Key Differences and Migration Learnings


1️⃣ Datasource Query Is Not Supported — Use search or item Instead

In XM Cloud, the traditional datasource(value: $datasource) query used in XP is no longer supported.
Instead, we must use the search or item query and filter using fields like _path, _templates, and _language.

✅ Migration Tip: When moving your query from XP → XM Cloud:

  • Replace datasource(value: $datasource) with a search or item query.
  • Include filtering parameters in the where clause to target your specific item.

2️⃣ The jss Field Type Is Deprecated

In Sitecore XP, developers often used { jss } to return field data in JSON format for use with Sitecore JSS components:

Example from XP:

cTALink { jss }

XM Cloud no longer supports jss, as it doesn’t rely on the JSS rendering engine. Instead, use jsonValue, which returns structured JSON suitable for headless frameworks like Next.js.

Example in XM Cloud:

cTALink { jsonValue } 

✅ Migration Tip:
Replace all instances of jss with jsonValue to ensure compatibility with XM Cloud’s headless output format.

3️⃣ Avoid Using src for Multilingual CTALinks

In XP, it was common to use ctaLink { src } to fetch URLs directly.
However, in XM Cloud, src does not append language prefixes, which can cause issues in multilingual environments.

✅ Migration Tip:

  • Avoid using src for CTALinks.
  • Use jsonValue instead — it provides a structured JSON output where href includes the language prefix.

Example:

"ctaLink": {
                "jsonValue": {
                  "value": {
                    "class": "",
                    "id": "{B5FCF49A-10F5-4983-8E21-62179D751E96}",
                    "querystring": "",
                    "anchor": "",
                    "title": "",
                    "linktype": "internal",
                    "text": "",
                    "url": "<Headless Tenant>/<Headless Site>/home/<item path>",
                    "href": "/en/<item path>"
                  }
                }
              }

4️⃣ Children and Related Items Must Be Wrapped Under results

In XP, child or related items were often accessed directly.
In XM Cloud, all returned data — including children — must be wrapped under the results node from the search API.

✅ Migration Tip:

  • Ensure that all item-level and child collections are accessed via results.
  • XM Cloud queries always return arrays, even when retrieving a single datasource.

🚀 Final Thoughts

Migrating GraphQL queries from Sitecore XP to XM Cloud isn’t just a syntax change — it’s a shift in architecture.
XM Cloud’s search-driven GraphQL model offers faster, more scalable, and cloud-native data access.

When adapting your queries, keep these in mind:

  • 🔁 Replace datasource with search or item
  • 🧱 Use jsonValue instead of jss
  • 🌐 Avoid src for multilingual CTALinks
  • 📦 Wrap all data and children under results

By following these best practices, your components will remain compatible, performant, and aligned with the modern headless architecture of XM Cloud.

Leave a comment