Skip to main content

Hierarchies

On this page we'll explain how to create content type schemas so that you can add content items to hierarchies, how to sort hierarchy nodes and what information you can retrieve using the filter API.

We've also included several examples: a simple hierarchy, a hierarchy that contains multiple content types and a hierarchy that is used to tag content. The examples are all included in the schema example templates in the Dynamic Content app, so it's easy to add them to your hub. See the example schemas section for more details.

For more information about the hierarchy user interface see the working with hierarchies page.

About hierarchies
Link copied!

Hierarchies allow you to model tree structures of content. A hierarchy is a natural way of using a tree structure to represent the relationship between objects. It might be a page structure for a website, a list of worldwide store locations organised by country and city, a structured list of product content, app settings or a list of ingredients and meal types for a recipe site. Hierarchies lend themselves to many use cases.

In Dynamic Content, a hierarchy provides a new way to link content items together. The content items in a hierarchy are normal content items that have relationships to each other. Because they are normal content items, you can work with these content items independently and manage and publish items in the normal way. The main difference is that a content item that is part of a hierarchy will have a relationship with its parent.

The example below shows one possible use case, a website menu that's built from a hierarchy. On the left you can see the hierarchy as modelled in Dynamic Content. Users can see at a glance how the website is structured and where content should be displayed. On the right is how the hierarchy is consumed in the app, providing the structure for the site navigation.

An example use case: a site menu

Hierarchies let users see the whole context. It might be a page or website layout, a buyer's guide or a list of tags to apply to blog posts. The user interface makes it easy to see all of the tree, and decide where to add and remove nodes if they need to.

Creating a schema for a hierarchy node
Link copied!

A hierarchy is a tree of nodes, each of which is a content item. Each node can have descendants, or child nodes. You can model a hierarchy in which all nodes are the same content type, or choose to define your hierarchy so it can contain items of multiple content types.

In each content type schema that defines a content item that can be added as a node to a hierarchy, you will need to specify the content types of the items that can be added as child nodes. To do this you will make use of Amplience specific extensions to the JSON Schema standard.

Including the hierarchy definitions
Link copied!

In your schema core definitions you will need to include the hierarchy definitions as follows:

"$ref": "http://bigcontent.io/cms/schema/v2/hierarchy#/definitions/hierarchy-node"

Your schema will now look something like:

{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/site-menu-item",

"title": "Site menu",
"description": "A node in the site menu hierarchy",

"allOf": [
{
"$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/content"
},
{
"$ref": "http://bigcontent.io/cms/schema/v2/hierarchy#/definitions/hierarchy-node"
}
],

...

}

The hierarchy trait
Link copied!

The trait keyword is an Amplience specific keyword that is used to include additional information about a schema. By including trait:hierarchy you can specify that a content item created from this schema can be added to a hierarchy. You also provide a childContentTypes array that defines the type of content items that can be added as child nodes. You can leave this array blank if you want a node created from the schema to be a leaf node with no children.

In the example shown below, we are modelling a hierarchy for a site menu. Each node in the hierarchy will be the same content type, so we just include the schema itself in the array. Only content items created from the schema registered with the URL https://example.com/site-menu-item can be added as children.

"trait:hierarchy": {
"childContentTypes": [
"https://example.com/site-menu-item"

]
},

The schema editor includes shortcuts to make it easier to add traits to your schemas.

note

If you change a schema to include the hierarchy-trait object, any content items created with the schema prior to the change will need to be converted to reflect the update to being hierarchical content. Your users will be notified if a content item needs converting. See Converting items for use with hierarchies.

Examples
Link copied!

Example 1: The site menu
Link copied!

The simple example shown below is a simple hierarchy representing the menu for a website, including sections for mens, womens, electricals and a blog.

The site menu hierarchy.

Each node in the hierarchy will be a site-menu-item content item, so the childContentTypes array in our schema will include a single entry for the https://example.com/site-menu-item content type schema.

Because hierarchies are just content items, you can link all or part of a hierarchy to another content item with a content-link or content-reference. For example, we could assign a category such as electricals to a banner so that appropriate content is shown when the user browses to each section of the site.

The schema also includes a title and a description for each section. The complete schema is shown below.

{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/site-menu-item",
"title": "Title",
"description": "Description",
"allOf": [
{
"$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/content"
},
{
"$ref": "http://bigcontent.io/cms/schema/v2/hierarchy#/definitions/hierarchy-node"
}
],
"trait:hierarchy": {
"childContentTypes": ["https://example.com/site-menu-item"]
},
"type": "object",
"properties": {
"title": {
"title": "Title",
"description": "Title used for the menu item",
"type": "string",
"minLength": 0,
"maxLength": 100
},
"description": {
"title": "Description",
"description": "description",
"type": "string",
"minLength": 0,
"maxLength": 100
}
},
"propertyOrder": [],
"required": ["title"]
}

The filter API can be used to traverse the tree and find the children of each node.

Example 2: multiple content types: the page hierarchy
Link copied!

This more advanced example makes use of two content types to implement an ideas and advice section on a website.

The page hierarchy example.

The page-hierarchy content type (1 in the image above) represents a category such as "Lighting and electrical" or "Heating and plumbing". It contains a title, description, image and a ranking. The page-hierarchy-node content type (2 in the image above) is the help page itself, including content such as text and images.

The start of the page-hierarchy schema is shown below. The childContentTypes array in the trait:hierarchy object contains two items: the page-hierarchy and the page-hierarchy-node. This is because we want to be able to add one category as a child of another and to add the help pages as children of a category.

The page-hierarchy schema
Link copied!

{
"$schema":"http://json-schema.org/draft-07/schema#",
"$id":"https://schema-examples.com/page-hierarchy",
"title":"Page Category",
"description":"Category that can contain pages or subcategories",
"allOf":[
{
"$ref":"http://bigcontent.io/cms/schema/v1/core#/definitions/content"
},
{
"$ref":"http://bigcontent.io/cms/schema/v2/hierarchy#/definitions/hierarchy-node"
}
],
"trait:hierarchy":{
"childContentTypes":[
"https://schema-examples.com/page-hierarchy",
"https://schema-examples.com/page-hierarchy-node"
]
},

The page-hierarchy-node schema
Link copied!

Note that for the page-hierarchy-node schema the childContentTypes array is empty because we don't want to add any children to page hierarchy nodes.

{
"$schema":"http://bigcontent.io/cms/schema/v2/schema#",
"$id":"https://schema-examples.com/page-hierarchy-node",
"title":"Page",
"description":"Page as a hierarchy node",
"allOf":[
{
"$ref":"http://bigcontent.io/cms/schema/v1/core#/definitions/content"
},
{
"$ref":"http://bigcontent.io/cms/schema/v2/hierarchy#/definitions/hierarchy-node"
}
],
"trait:hierarchy":{
"childContentTypes":[

]
},

Example 3: using a hierarchy to tag content: the ingredients hierarchy
Link copied!

In this example an ingredients hierarchy is used to tag recipes. There are 2 content type schemas: the ingredients hierarchy and the recipe schema which uses an array of content types to allow the user to choose one or more items from the hierarchy. This puts the user in control by allowing recipes to be tagged dynamically rather than having to choose from a preset list of values.

The ingredients hierarchy.

The recipe content item tagged with multiple items from the hierarchy is shown below. Note that this schema makes use of the hierarchy extension to make it easy to browse and add items from a hierarchy rather than a flat view of content items.

A recipe item tagged with multiple items from the ingredients hierarchy.

The ingredients property in the recipe schema is an array of content links of the ingredients-list type. Users can choose one or more ingredients to tag the recipe. A search index could then be used to allow the user to find recipes which have been tagged with their chosen ingredients.

   "ingredients":{
"title":"ingredients",
"type":"array",
"minItems":0,
"maxItems":10,
"items":{
"allOf":[
{
"$ref":"http://bigcontent.io/cms/schema/v1/core#/definitions/content-link"
},
{
"properties":{
"contentType":{
"enum":[
"https://schema-examples.com/ingredients-list"
]
}
}
}
]
}
}

Sorting nodes
Link copied!

By default, nodes will be shown in the order in which they are added, but you can define a sort order to specify a property that will be used for sorting.

To define a sort order, include trait:sortable in your schema and specify one or more properties to use for sorting in the paths array. The sort order is specified in JSON pointer format.

In this example we will sort the hierarchy tree using the title of each content item. The children of a node will be sorted in ascending order by the title property.

"trait:sortable": {
"sortBy": [
{
"key": "default",
"paths": ["/title"]
}
]
}

In the page-hierarchy schema we've included a ranking property that allows the user to control the order in which nodes are sorted. The ranking is included in the sort, so nodes will be sorted in ascending order of ranking and, if the ranking is equal, the title will be used.

"trait:sortable":{
"sortBy":[
{
"key":"default",
"paths":[
"/ranking",
"/title"
]
}
]
}

Using hierarchies with the Content Delivery API
Link copied!

When you publish a hierarchy node you can choose whether to publish it on its own or together with its dependents. The Content Delivery API includes some additional information about a node under the hierarchy element. Here's an example of the content returned for the root of the hierarchy- that is the node that has no parent item. You can see that root is set to true.

{
"content": {
"_meta": {
"name": "Website menu",
"schema": "https://example.com/site-menu-item",
"hierarchy": {
"root": true
},
"deliveryId": "b158fe6b-fe4b-46e3-92c5-33f8a4e5675c"
},
"title": "Website menu",
"description": "Menu for our website"
}
}

Here's the content returned for an item named "Clearance", you will notice that this includes a parentId element. This is the node's immediate parent, in this case the root node shown above. You can use the parentId to traverse back up the tree or with the filter API to find the immediate children of the parent.

Use the Hierarchy API to find all descendants of the specified node, which can be the entire hierarchy or just a part of it.

{
"content": {
"_meta": {
"name": "Clearance",
"schema": "https://example.com/site-menu-item",
"hierarchy": {
"parentId": "b158fe6b-fe4b-46e3-92c5-33f8a4e5675c",
"root": false
},
"deliveryId": "da2cc1b1-d7f5-4743-b7c0-a3c893363c3e"
},
"title": "Clearance",
"description": "Items that must go"
}
}

Retrieving all descendants of a hierarchy node
Link copied!

The Hierarchy API allows you to retrieve all descendants of a specified node in a hierarchy. The following example shows how to retrieve all descendants of the node with the content item id 4c67ca5a-6050-490a-9859-be20e81ac89d to a depth of 3 levels.

https://docsportal.cdn.content.amplience.net/content/hierarchies/descendants/id/4c67ca5a-6050-490a-9859-be20e81ac89d?hierarchyDepth=3

You can see the response to this request by expanding the section below.

Example response from the Hierarchy API
{
"responses": [
{
"content": {
"_meta": {
"name": "Heating and plumbing",
"schema": "https://schema-examples.com/page-hierarchy-node",
"deliveryKey": "ideas-and-advice/heating-and-plumbing",
"hierarchy": {
"parentId": "4c67ca5a-6050-490a-9859-be20e81ac89d",
"root": false
},
"deliveryId": "2e924e92-5c68-485f-aaa4-54d3c630227e"
},
"title": "Heating and plumbing",
"description": "All your plumbing questions answered",
"ranking": 1
}
},
{
"content": {
"_meta": {
"name": "Lighting and electrical",
"schema": "https://schema-examples.com/page-hierarchy-node",
"deliveryKey": "ideas-and-advice/lighting-and-electrical",
"hierarchy": {
"parentId": "4c67ca5a-6050-490a-9859-be20e81ac89d",
"root": false
},
"deliveryId": "2dd210c1-0418-442d-8b50-bb089de773f9"
},
"title": "Lighting and electrical",
"description": "Your questions answered on all things lights and electrics",
"ranking": 2
}
},
{
"content": {
"_meta": {
"name": "How to change a socket",
"schema": "https://schema-examples.com/page-hierarchy-node",
"deliveryKey": "lighting-and-electrical/how-to-change-a-socket",
"hierarchy": {
"parentId": "2dd210c1-0418-442d-8b50-bb089de773f9",
"root": false
},
"deliveryId": "bff3769a-b8f0-4eb0-b399-b7df6cf92417"
},
"title": "How to change a socket",
"description": "How to safely change an electrical socket",
"ranking": 1
}
},
{
"content": {
"_meta": {
"name": "How to run a new cable",
"schema": "https://schema-examples.com/page-hierarchy-node",
"deliveryKey": "lighting-and-electrical/how-to-run-a-new-cable",
"hierarchy": {
"parentId": "2dd210c1-0418-442d-8b50-bb089de773f9",
"root": false
},
"deliveryId": "09d8ac5b-c24c-4d2e-936e-ae4751543b2e"
},
"title": "How to run a new cable",
"description": "Adding a new cable, the easy and safe way",
"ranking": 2
}
},
{
"content": {
"_meta": {
"name": "Outdoor and garden",
"schema": "https://schema-examples.com/page-hierarchy-node",
"deliveryKey": "ideas-and-advice/outdoor-and-garden",
"hierarchy": {
"parentId": "4c67ca5a-6050-490a-9859-be20e81ac89d",
"root": false
},
"deliveryId": "d09cea6f-265d-4e9d-98d9-4c5e95f7afa9"
},
"title": "Outdoor and garden",
"description": "Hints and tips for keeping your garden looking great",
"ranking": 3
}
},
{
"content": {
"_meta": {
"name": "Gardening questions answered",
"schema": "https://schema-examples.com/page-hierarchy-node",
"deliveryKey": "outdoor-and-garden/gardening-questions-answered",
"hierarchy": {
"parentId": "d09cea6f-265d-4e9d-98d9-4c5e95f7afa9",
"root": false
},
"deliveryId": "ce110f22-d85d-4bf1-9f20-5a6b5795ecd6"
},
"title": "Gardening questions answered",
"description": "Everything you need to know about planting and care of your garden",
"ranking": 1
}
},
{
"content": {
"_meta": {
"name": "How to sow new grass seeds",
"schema": "https://schema-examples.com/page-hierarchy-node",
"deliveryKey": "outdoor-and-garden/gardening-questions-answered/how-to-sow-new-grass-seeds",
"hierarchy": {
"parentId": "ce110f22-d85d-4bf1-9f20-5a6b5795ecd6",
"root": false
},
"deliveryId": "5992d135-cd7b-4c57-ba2c-bf1103150c58"
},
"title": "How to sow new grass seeds",
"description": "A new lawn made easy",
"ranking": 1
}
},
{
"content": {
"_meta": {
"name": "Painting and decorating",
"schema": "https://schema-examples.com/page-hierarchy-node",
"deliveryKey": "ideas-and-advice/painting-and-decorating",
"hierarchy": {
"parentId": "4c67ca5a-6050-490a-9859-be20e81ac89d",
"root": false
},
"deliveryId": "31c0b684-7a28-47ad-a871-f1882ec408fa"
},
"title": "Painting and decorating",
"description": "How to keep your home looking good as new",
"ranking": 4
}
}
],
"page": {
"responseCount": 8
}
}

Listing immediate children of a hierarchy node
Link copied!

Using the filter API you can list all the children of a specified parent node by setting the filter path to /_meta/hierarchy/parentId,as shown in the content returned from the Delivery API, and setting the parent id to the deliveryId of the item whose children you want to return. You can use the Hierarchy API to return all children in all levels of a hierarchy.

In the example filter API request shown below we are requesting all the children of the hierarchy node with the id "b158fe6b-fe4b-46e3-92c5-33f8a4e5675c". Note that just the immediate children will be returned.

{
"filterBy": [
{
"path": "/_meta/hierarchy/parentId",
"value": "b158fe6b-fe4b-46e3-92c5-33f8a4e5675c"
}
]
}

Try it out
Link copied!

To try out the filter request use the following cURL.

curl -d '{
"filterBy":[
{
"path":"/_meta/hierarchy/parentId",
"value":"b158fe6b-fe4b-46e3-92c5-33f8a4e5675c"
} ]
}' -H "Content-Type: application/json" -X POST 'https://ampproduct-doc.cdn.content.amplience.net/content/filter'

An example response is shown below. These are the items that have the node with the id "b158fe6b-fe4b-46e3-92c5-33f8a4e5675c" as their parent.

{
"responses": [
{
"content": {
"_meta": {
"name": "Homewares",
"schema": "https://example.com/site-menu-item",
"hierarchy": {
"parentId": "b158fe6b-fe4b-46e3-92c5-33f8a4e5675c",
"root": false
},
"deliveryId": "44ca42f3-8953-4ff5-99a8-ac48980e63d2"
},
"title": "Homewares",
"description": "For the home"
}
},
{
"content": {
"_meta": {
"name": "Clearance",
"schema": "https://example.com/site-menu-item",
"hierarchy": {
"parentId": "b158fe6b-fe4b-46e3-92c5-33f8a4e5675c",
"root": false
},
"deliveryId": "da2cc1b1-d7f5-4743-b7c0-a3c893363c3e"
},
"title": "Clearance",
"description": "Items that must go"
}
}
],
"page": {
"responseCount": 2
}
}

Removing a node from a hierarchy
Link copied!

When you remove a node from a hierarchy, the link between the node and its parent is still there in the published version of your content. In order to ensure that the node is not included when you list all children of its parent you need to either:

  • Remove the node from the hierarchy and re-publish it. This is the approach to use if you still want to retrieve the published version of the content item.

or

  • If you no longer need the content item: unpublish the node and then remove it from the hierarchy.

Removing and republishing the node
Link copied!

In the example below we're removing the "Bathroom" node from its hierarchy.

Removing a node from a hierarchy.

The bathroom node is no longer part of the hierarchy, but as you can see from the JSON returned by the Content Delivery 2 API, the parentId still contains the value of its previous parent node.

The removed node still contains a link to its parent.

When the item is re-published, the parentId will not longer be included in the JSON response and the item will no longer be returned as part of the hierarchy.

When the node is re-published, the link to its parent is removed.

Unpublishing and removing the node
Link copied!

If you no longer need to retrieve the node using its production Content Delivery URL, you can use the unpublish feature.

In the example below, we no longer want the Dishwashers node to be part of the hierarchy. To unpublished the node, select it in the hierarchy so the content item the node represents is shown on the content form. Choose "Unpublish" from the "Save" menu to unpublish the item.

If you're no longer using the item, you may want to archive it.

Unpublishing the content item.

After it is unpublished, the item will no longer be returned if we query all published children of its parent (in this case the Electricals node). However, it will still be returned when you query its parent using the virtual staging URL.

To remove the item from the hierarchy and the link to its parent, click the node in the hierarchy browser and choose "Remove node" from its menu.

Removing the node. There is no longer any link to its parent node.

Implementing an isActive flag
Link copied!

Another approach you can use, if you're implementing something like a page hierarchy, is to include an "isActive" flag in the Content Type schema that you can use with the filter API to return only those nodes that are marked as active. This allows the user to choose which nodes will be returned.

The hierarchy chooser extension
Link copied!

The hierarchy content field extension allows users to browse and add content items from a hierarchy rather than having to find these items in the Content Library. In the example of the recipe hierarchy, by using the hierarchy extension, it's easy to to browse and add multiple ingredients.

Tagging a recipe with items from the ingredients hierarchy using the hierarchies extension.

To use the hierarchy extension you need to include the content item id of the hierarchy node from which the hierarchy can be browsed in the extension parms. You can find the content item id from the properties pane in the content form, as shown in the image below.

Finding the content item id of the node from which the hierarchy can be browsed.

The ingredients property shown below uses the extension registered as "hierarchy-extension" and passes the id of the root node of the ingredients hierarchy- the content item named "Ingredients".

   "ingredients":{
"title":"ingredients",
"type":"array",
"minItems":0,
"maxItems":10,
"ui:extension":{
"name":"hierarchy-extension",
"params":{
"nodeId":"ea3e494b-f001-491a-9508-6387fecca1e0"
}
},
"items":{
"allOf":[
{
"$ref":"http://bigcontent.io/cms/schema/v1/core#/definitions/content-link"
},
{
"properties":{
"contentType":{
"enum":[
"https://schema-examples.com/ingredients-list"
]
}
}
}
]
}
}

Registering the hierarchy chooser extension
Link copied!

To register the hierarchy extension, go the development home page and click the extensions icon, or choose "Extensions" from the Development menu. Click the "Register extension" button.

  • In the registration window, choose "Content field" as the category.

  • Add a label and name. The name will be used as the value of the "name" field in the ui:extension section of a property that uses the extension. In the ingredients property shown above the extension is named "hierarchy-extension".

  • Enter https://hierarchy-chooser.extensions.content.amplience.net/ as the URL.

  • Click the "Permissions" tab to set the extension permissions. Set the "Read access" and "Allow same origin" permissions.

Registering the hierarchy extension.

You can specify additional parameters from the "Installation parameters" tab or add them directly in your schema. The available parameters are as follows:

ParameterDescriptionRequired / Optional
nodeIdThe content item id of the item to use as the root of the hierarchyRequired
typeThe display size of each node: large, small or chipOptional. The default is "large"

When you've finished setting up the extension, click "Save" and the extension will be registered and available to include in your schemas.

Example schemas
Link copied!

The schemas used in this page are all included in the schema example templates in the Dynamic Content app. Go to the using the schema examples page for more details.

You can also find the schemas on the following pages:

Adding traits in the schema editor
Link copied!

The schema editor includes shortcuts for adding a trait:hierarchy object to your schema. Just type control + space and and choose "trait:hierarchy" from the popup menu.

Using a shortcut to add a hierarchy trait in the schema editor.

The trait will be added to your schema. Click inside the trait object, type control + space again and choose "childContentTypes" from the menu. Then add any content types you want to allow to be added as children of nodes of the type defined in the schema.

Adding the childContentTypes array.

Working with hierarchies

List, filter and sort content

Hierarchy API

Registering extensions