Adobe Experience Manager (AEM) has evolved into a powerful headless CMS by decoupling content creation from the presentation layer. At the heart of this architecture are Content Fragments, which allow you to design, create, and manage structured, channel-neutral content. To retrieve this data efficiently for modern front-end frameworks like React, Angular, or mobile apps, AEM leverages GraphQL. Unlike traditional REST APIs, the AEM GraphQL API enables developers to query specific data structures, reducing payload size and providing a flexible, “self-documenting” way to consume content. By utilizing Content Fragments with GraphQL, organizations can ensure a “create once, publish everywhere” strategy while maintaining high performance and developer agility.
There are certain pre-requisites before we proceed towards the POC for writing and testing the GraphQL, first is to define the Content Fragment Model. Follow these steps:
Creating a project configuration
Tools > General > Configuration Browser- Check Content Fragment Models & GraphQL Persistent Queries
Creating a Content Fragment Model.
Tools > Assets > Content Fragment Models.- Publish Project Configuration & Content Fragment Models
For this POC, I created 4 content fragment models at /conf/PoC_GraphQL
Person
=> Name: Textfield
=> Email: Textfield
=> Role: Checkbox
=> Profile Picture: Path Finder
=> Biography: RTE
Team
=> Title: Textfield
=> Code: Textfield
=> Description: RTE
=> Team Members: Fragment reference : Person (Multifield)
Article
=> Title: Textfield
=> Abstract: Textfield
=> Description: RTE
=> Publish Date: Date Picker
=> Tags: Tag Picker
=> Author: Fragment reference : Person
=> Departments: Fragment reference : Department (Multifield)
Department
=> Title: Textfield
=> Code: Textfield
=> Description: RTE
Next step is to populate the content fragment data using the model created above.
- Create an Asset Folder –
/content/dam/poc_graphql - Go to properties of folder and set Cloud configuration under cloud services tab
- In policies tab, make your content fragment model allowed
- Create a Content Fragment, using your selected content fragment model
- Publish Content Fragments
Configuring the endpoint for accessing the GraphQL.
Tools > Assets > GraphQL- Create GraphQL endpoint for project
Once the endpoint is created, open GraphQLQuery editor and create query:
Tools > General > GraphQL Query Editor- Write your query, test it with qauery variables if there’s any
- Save the query to make it Persist Query
- Publish GraphQL Endpoint & Persisted Queries
After query has been persisted, it can be requested using a GET request and cached at the Dispatcher and CDN layers. The performance of the persisted queries is much better. In addition to performance benefits, persisted queries ensure that extra data is not accidentally exposed to client applications.
Some of the sample queries:
allDepartment: To get the list of all departments, can be called via http://localhost:4502/graphql/execute.json/PoC_GraphQL/allDepartment
query {
departmentList {
items {
title
code
description {
html
markdown
plaintext
}
}
}
}
allTeams: To get the list of all teams, can be called via http://localhost:4502/graphql/execute.json/PoC_GraphQL/allTeams
query {
teamList {
items {
title
code
description {
html
markdown
plaintext
}
}
}
}
teamByCode: Get detail of team, by passing team code as variable. Cabe called via http://localhost:4502/graphql/execute.json/PoC_GraphQL/teamByCode;code=developers
query teamByCode($code:String!){
teamList(
filter:{
code:{
_expressions:[{
value:$code
_operator:EQUALS
}]
}
}
){
items{
title
code
description {
html
markdown
plaintext
}
teamMembers {
name
biography {
html
markdown
plaintext
}
role
profilePicture {
... on ImageRef {
_path
}
}
}
}
}
}
Query Variables:
{
"code":"developers"
}
articlesByDepartment: To get articles by department, passed as variable. Can be accessed via http://localhost:4502/graphql/execute.json/PoC_GraphQL/articlesByDepartment;department=technology
query articlesByDepartment($department:String!){
articleList(
filter:{
departments:{
_match: {
code: {
_expressions: {
value: $department
_operator: EQUALS
}
}
}
}
}
){
items {
title
abstract{
plaintext
}
publishDate
tags
description{
html
plaintext
}
author{
name
email
profilePicture {
... on ImageRef {
_path
}
}
}
departments{
code
title
}
}
}
}
Query Variables:
{
"department":"technology"
}