This year I had the very good fortune to attend and present at SUGCON ANZ in Melbourne – the first ANZ SUGCON since 2019 in Sydney. It was fantastic to hang out with some long lost Sitecore friends that I hadn’t seen since before COVID times, and to meet new Sitecore community folks as well as the crew from Sitecore – some of whom had travelled a long way to get there.
This year my presentation was “Making the journey to headless without losing your head” which looks at some of the challenges and choices that you might want to consider when taking your first steps towards a Sitecore headless implementation, based on my experiences over the last couple of years doing headless development with Sitecore XP and JSS.
Anyway, for what it’s worth here are my slides. There is some supporting content in the speaker notes, if you get that far… Thanks to all who attended, especially the Perth Sitecore crew, and thanks again to the organisers of SUGCON for the opportunity and good times.
Consuming data from a “headless” CMS is a pretty popular approach these days, as the trend towards the delivery of API-driven front end rendering solutions continues to grow. Sitecore has been increasing its footprint in this space for several years now, and has developed some offerings that leverage the legacy of Sitecore’s content management, personalisation, and analytics features whilst also enabling the delivery of content to headless rendering apps. In this post I outline the options available for delivering and shaping Sitecore content via APIs using the features that Sitecore Headless Services adds on to the base platform, and also mention a couple of methods that are already available without the need for a JSS license.
[N.B. The following methods require Headless Services to be installed on your Sitecore instance]
The Layout Service exposes a REST endpoint (or endpoints, you can have multiple) through which content items can be retrieved using an API key and the results are returned in a specific JSON structure. I won’t go into the specifics of it here, but you can read more details in one of my earlier blog posts.
The API is quite flexible and extensible, and you can use a few different approaches to tailor the data to your needs:
Requesting an item (a route in JSS parlance) from the API returns a fully assembled description of the route content, as well as the renderings assigned to the placeholders on that route. One of the key differentiators of the layout service is that it leverages the Sitecore rendering engine to include rendering information along with content, and this means that you can use Sitecore personalisation and content management techniques to customise the data returned to your headless solution. Thus your digital producers and content authors can take advantage of the tools with which they are already familiar, such as Experience Editor, to add renderings to placeholders, apply rules based personalisation, and create and deploy tests, all of which are fully supported in headless mode when using the API.
One lesser known option available in the layout service API is that you can use it to retrieve only the contents of a specific placeholder. This might not sound like much but it is really quite a powerful and useful feature. In a headless delivery model, once the layout data has been retrieved from the API for a given route, the user can continue to interact with the site UI without the need for additional calls to the Sitecore delivery server (unless they request a new route of course.) Using the placeholder API call, you can dynamically retrieve and update the contents of specific placeholders in your headless application based on interactions that your user has had with your site.
For example you could append a querystring to the placeholder API call and personalise the rendering data in the placeholder on the server side, then dynamically update the UI with the freshly customised rendering information. Or you could send data to a custom endpoint, update a goal or a facet, and then pull the personalised rendering data based on the new information about your user. Or perhaps you could lazy load content into your UI to improve performance.
In addition, the JSON returned from the placeholder API call is very lean compared to the route API data, so requests are lightweight and fast.
Rendering contents resolvers
Headless Services introduced the concept of Rendering Contents Resolvers. These are a set of 6 “resolvers” that can be used to tailor the data returned for a specific rendering. The tailored rendering contents are then passed back to the Layout Service. The out-of-the-box resolvers are quite flexible and provide a quick and simple way to tailor rendering contents without the need for custom code. They can be easily extended and you can read more details about how to do that here.
GraphQL was added to Headless Services and announced at Sitecore Symposium back in 2018, along with the “official” release of JSS. The Sitecore docs describe it as “a generic GraphQL service platform on top of Sitecore. It hosts your data and presents it through GraphQL queries. The API supports real-time data using GraphQL subscriptions.”
What this means in practical terms is that you can query Sitecore items and perform Content Search queries via GraphQL. Integrated GraphQL is the use of GraphQL queries to shape your rendering contents. This is done by simply pasting the query code into a multi-line text field in your rendering (what could go wrong?). This will override any other rendering behaviours and return the query results instead of a datasource, or the output of a rendering contents resolver. GraphQL always wins.
One key difference that should be borne in mind, however, is that the JSON contract returned by an integrated GraphQL query will be quite different to the rendering contracts returned when using out-of-the-box options like rendering contents resolvers. This can result in a bit of a mixed bag of data structures being returned to your headless data consumers, some using the “standard” approach and some using a variety of GraphQL shaped rendering contents.
This is Sitecore: everything is extensible! So it is not difficult to extend the code that powers the API and customise the data contract. You can read about extending the context here.
That pretty much sums up the options for using the Layout Service but it’s not the end of the story. More techniques are available for powering headless solutions.
Other options using Headless Services
This approach uses the same schema as Integrated GraphQL, but exposes API endpoints to which you can send your queries. Using this feature your apps can query Sitecore content and send variables with those queries, perhaps based on client interactions. One example might be to provide a headless search feature, passing user-supplied search terms back to the API endpoint which would in turn use the Content Search API to query Sitecore. Or perhaps use it to retrieve configuration settings or other values on-the-fly without the need to use the Layout Service. Customised GraphQL approaches such as that described in Aaron Bickle’s post mentioned earlier can also be leveraged to customise the default functionality available via Connected GraphQL.
Options that don’t requires Headless Services
Don’t have JSS and Headless Services? Not to worry! There are other options available to feed data to your headless solutions.
Using SXA? Great! SXA is awesome! This also means that you can use SXA data modelling and JSON renderings and variants to return data to your headless app without a JSS license. This approach is pretty flexible because you have the power of SXA rendering variants and Scriban at your disposal.
Sitecore Services Client
The Sitecore Services Client has been around for quite a while and in a headless scenario it would most likely be used to provide read-only access to items via the ItemService. It’s a flexible API and if you want to simply pull content items out of Sitecore and consume that data in a headless app, then this is a great alternative to Headless Services. One downside is that you don’t get the rendering information that you would have been able to retrieve via the Layout Service, but if you only need items then this is your simplest, best, and cheapest option.
Finally, you can always create your own API endpoints using .NET. In ASP.NET MVC this will probably be a Controller API or Web API endpoint with custom routing. This approach is very flexible, is something that any .NET developer will be comfortable with creating, and it doesn’t require any additional licenses to serve content.
No doubt there are other ways to pull content out of Sitecore for consumption in your headless solutions (e.g. the Item WebAPI – does that still exist?) but these are the mainstream approaches. If you want to take full advantage of the headless rendering SDKs and leverage analytics, personalisation, content testing, and the power of Sitecore’s content management feature set (placeholders, renderings, templates, datasources, etc) then Headless Services is probably the best option, but if you don’t need those features, or if your client/employer doesn’t want to foot the bill for headless, then there are still some solid options available for pulling data out of Sitecore to power your headless solutions.