Skip To Content

Improve Content Authoring in Kentico Xperience Using Allowed Types and Global System Events

On a recent Kentico Xperience project, we provided a headless CMS (Content Management System) architecture for a customer who was already heavily invested in their existing ecommerce platforms and microservices architecture. The architecture enabled them to adapt Xperience as a headless CMS and a headless online marketing platform. This involved creating Web APIs using Xperience’s robust extensibility, but more importantly, it involved creating a solid content model that enabled content reuse. 

Our customer was excited about the value of a headless CMS, especially content reuse, so as we worked on the content model and solution architecture, we aimed to make every piece of content reusable. In a sense, we were borrowing the Do Not Repeat Yourself (DRY) principle from software development. The goal was to prevent authors from having to recreate content. This led to designing a content tree structure in Xperience that provided a central library of folders for reusable content. Makes sense, right?

Epiphany

 

While trying to create the ultimate solution for content reusability, I discovered that I had put myself on a quest for the Holy Grail. Was it realistic for all content to be reusable? Could it ever be? By aiming for such an ideal goal, I was creating an architecture that was becoming overly complicated for authors, the same people I was trying to help. The realization struck me when I authored the content for a complex page to prepare for a demo. 

To create this page, I had to navigate all over the content tree, selecting small bits of reusable content, and linking them to the main page to compose the whole. The image below illustrates the concept. I was immediately struck by how cumbersome this process was. On top of that, I looked at the page and realized most of the content would never be reused. Much of it was clearly unique for this page. If I continued this direction, authors would have extra work without a big payoff. My big lesson was to always try out the entire process that is being created for end users, not just isolated widgets, or pieces. Try out the entire content production process. It could be eye opening for you, too.

traditional CMS structure - back end to front end

Solution

Fortunately, we were at an early stage of the project and had plenty of time to change course. This allowed us to implement several improvements. The foundation was to recognize that only some content would realistically be reusable, major building blocks like locations, people, and promotions. Page-specific content could be organized with the page instead of in central library folders. In Xperience, the simplest author usability comes by using a page’s form tab for all content. However, we often need to support pages that can have many optional types of content. A great way to handle this is to allow multiple pieces of child content to be organized with the page in the content tree, instead of in shared folders that are many clicks away from the page. To solve this, I went back to a solution that I had been using for years, originally inspired by Joel Dahlin’s blog article on using structured content. If you are new to Xperience development, give it a read. 

The solution is to enable authors to have a special “page asset” folder for each page that may require child content. These folders are typically type-specific, so that developers have fine control of the author experience. This means that when an author creates a page like a new landing page, they would have a page assets folder immediately below the page that only allows adding content for the landing page. Additionally, the solution allows excluding types of content that should be reusable. For example, if the customer decides that promotions, locations, and testimonials should be reusable, we can configure Xperience to prevent adding those types of content to the page-specific assets folder. This helps authors remember to add reusable content in the shared section of the content tree, while allowing them to manage page-specific content in the most convenient location.

Allowed Types

The first step of this solution is to create container page types for each type of page that needs an asset folder. For example, if you create a “Landing Page” type, also create a “Landing Page Asset Folder” container type, and if you create an “Inspiration Page” type, an “Inspiration Page Asset Folder” container type. This will allow you to provide fine-grained configurations for each type of page, so that you can keep the author experience simple. 

In this case, the most interesting page type configurations are the allowed type settings. These configurations allow you to control what child types are allowed under each page or folder. So, you can ensure that a landing page asset folder is only allowed under a landing page. Likewise, you can configure the landing page asset folder to only allow content that can be used on the parent page. This small touch provides a significant improvement to usability. Authors will have a nicely trimmed list of options when they add content to a folder, so they do not have overwhelming choices, and more importantly the solution does not allow creating unsupported content. This reduces confusion and support costs. 

Additionally, you can use these configurations to promote reusable content when it makes sense. For example, if the content is valuable reusable content like a testimonial, location, or a person, you can permit these types in a central folder but not in a page-specific folder. As a result, when authors attempt to create new content in the landing page asset folder, they can create a new teaser, or media block, but the solution would guide them to put promotion, testimonial, and location content in shared folders. 

The figure below illustrates this solution, which allows page-specific content to be organized close to the page, so it is easy to find and manage, while still encouraging the use of shared re-usable content when appropriate. It is the best of both worlds.

flowchart with multiple CMS structures

Global Events

These out-of-the-box configurations enable authors to create page-specific folders and organize their content. However, would it be better if the folders were automatically created? Xperience provides a solution, global events, which enables developers to add code that fires whenever a page is added, updated, or published. To automatically provide page asset folders for authors, developers can create a custom module that registers the event DocumentEvents.Insert.After and automatically creates the asset folder . Developers may also want to handle the DocumentEvents.Update.After event, so that the solution will automatically recreate missing folders when a page is updated. Here is a rudimentary example that demonstrates creating a module that uses Xperience’s global system events.

using Acme.Kentico.Modules;

using CMS;

using CMS.DataEngine;

using CMS.DocumentEngine;

using CMS.EventLog;

using System;

 

[assembly: RegisterModule(typeof(PageTypeManagerModule))]

namespace Acme.Kentico.Modules

{

    public class PageTypeManagerModule: Module

    {

        public PageTypeManagerModule() : base(nameof(Acme) + "." + nameof(PageTypeManagerModule)) { }

 

        protected override void OnInit()

        {

            DocumentEvents.Insert.After += Document_Insert_After;

        }

 

        private void Document_Insert_After(object sender, DocumentEventArgs e)

        {

            TreeNode page = e.Node;

            if (page.ClassName == "Acme.LandingPage")

            {

                try

                {

                    var provider = page.TreeProvider;

                    var culture = page.DocumentCulture;

                    var contentFolder = TreeNode.New("Acme.LandingPageAssetFolder", provider);

                    contentFolder.DocumentName = "Asset folder";

                    contentFolder.DocumentCulture = culture;

                    contentFolder.Insert(page);

                }

                catch (Exception ex)

                {

                    EventLogProvider.LogException(nameof(PageTypeManagerModule),

                                                  nameof(Document_Insert_After), ex);

                }

            }

        }

    }

}

With this solution, whenever the author creates a page, the module will ensure the asset folder is created.

Page Asset Folders Module in the Marketplace

This article provides a rudimentary sample, but in the real world you will want a module that:

  1. Allows the list of page types and their related asset folder types to be configured.
  2. Ensures the asset folder is published if workflow is applied.
  3. Moves the asset folder to the top of the child list and keeps it there.
  4. Prevents event recursion so that multiple asset folders are not accidentally created in race conditions.

To make your life easier, we created the “Kentico Xperience Page Asset Folder Module” which you can get from the in the Xperience DevNet Marketplace or on GitHub. It is compatible with projects built in Xperience version 12 or 13.  I hope this module inspires you to provide easy-to-use solutions for your Xperience authors. 

Have questions on how to get the most out of your Kentico Xperience implementation? Drop me a line on Twitter (@HeyMikeWills), or view my other articles here.