Menu

Sitecore Content Hub for Developers

It’s trivia to say that time flies.

Me with a nervous smile before my presentation.
Me with a nervous smile before my presentation.

I remember preparing my submission for Sugcon CFP in December, then the shock when my talk was accepted and freaking out for three months about presenting in front of entire Sitecore community and now here we are, two weeks after this splendid event. The conference was great as previous two events I have attended and it was good to see that the community is still strong.

If you haven’t attended, or perhaps if you would like to recall some of the details of my talk, you can find below a short summary.

The event was opened by Sitecore CEO Steve Tzikakis himself and it was really encouraging to hear directly from him how much Sitecore cares about the community. Steve talked about the direction Sitecore is heading which might seem revolutionary from my, as a .NET developer, point of view.

Sitecore CEO Steve Tzikakis during keynote.
Sitecore CEO Steve Tzikakis during keynote.

The word composable was nearly overused during the keynote and the Sitecore strategy overview given shortly after by Dave O’Flanagan. It describes a new suite of Sitecore products. Independent, API and cloud based applications, which can be used to compose any architecture you or your clients should require.

Sitecore content hub is one of those products. And you might ask why invest into another content related application when there is already one we all know and love - good, old Sitecore XP. It all becomes clear, when you look at the role of each of those systems. While Sitecore XP’s main role is to deliver the content to the customers, Content Hub’s responsibility is to deliver the content to the internal systems and employees. Long time ago Sitecore XP should have started being considered as just one of the channels for content delivery. And since content is distributed acorss different channels in various forms, you can think of all those web editors who are copy-pasting it from Word documents into Sitecore. With Content Hub they can focus on arranging the content on the page using Sitecore XP because the content is already there. It is fed automatically from Content Hub where it was produced. In this way Content Hub complements Sitecore XP.

What is Content Hub

Content Hub consists of 5 modules, all off them accessible through the navigation. There are three core content repositories for different types of content: assets, products and text. Content Hub’s main goal is to provide easy access to thousands of elements so it puts heavy focus on search and share functionality. On top of that there are two additional modules: for organizing work into tasks and projects and for exporting content elements into digital assets using flexible templates.

Content Hub is a repository for content
Content Hub is a repository for content

This is how the users see Content Hub.

Internally, a very important concept is schema. Schema defines all the available entities - products, assets and content elements as well as taxonomies used to describe them. Each entity definition determines what properties are available and what relations to other entities are possible to set up. Just like in Sitecore XP everything is an item, in Content Hub nearly everything is an entity.

Role of a developer

For most of the time working with Content Hub is about configuration of what users can or cannot do. This includes mostly changes to the schema or the user interface. But sometimes it’s also about making users life a little bit easier. Or ours. And this can be done by automating all off the boring and repetitive stuff that has to be done, using scripts. The scripts are written in a web based editor inside Content Hub. Thankfully the scripts are also based on the Web SDK, a C# based API to interact with the Content Hub. And this has two implications - they can be developed using Visual Studio. And they are quite powerful.

My idea for working with the scripts was pretty simple. I have set up a base class which consits of a Execute and SetUp methods. In a SetUp method I am creating a script context which is just an object based on this documentation page. The Execute method contains actual script.

// IScript interface defines only Execute method
public abstract class BaseScript : IScript
{
    // This field is available withing the script to interact with the API
    protected IWebMClient MClient { get; private set; }

    // This object contains the context of the script
    protected ScriptContext Context { get; private set; }

    public BaseScript()
    {
        Uri endpoint = new Uri("https://contenthub.url/");

        OAuthPasswordGrant oauth = new OAuthPasswordGrant
        {
            // These two values can be found in OAuth clients page in Manage section within Content Hub
            ClientId = "ID of the client",
            ClientSecret = "Client secret,
            // Username and password
            UserName = "john.doe",
            Password = "super_secret"
        };

        MClient = MClientFactory.CreateMClient(endpoint, oauth);
        Context = new ScriptContext();

        SetUp().Wait();
    }

    public abstract void Execute();

    public abstract Task SetUp();
}

And below is an example implementation

/*
 * This example script always sets a relation between product
 * for which it is run and the "Sweets" tag, represented by an id
 * 33857
 */
public class EnsureSweetsTags : BaseScript
{
    public async override void Execute()
    {
        // Only contents of this method is used within Content Hub
        var tagsRelationName = "S.Demo.ProductToTags";
        var sweetsEntityId = 33875;

        // During development Context is set in the SetUp method below. In the script it is set by Content Hub
        var entity = Context.Target as IEntity;

        await entity.LoadRelationsAsync(new RelationLoadOption(tagsRelationName));
        var tagsRelation = entity.GetRelation<IChildToManyParentsRelation>(tagsRelationName);

        tagsRelation.Add(sweetsEntityId);

        await MClient.Entities.SaveAsync(entity);
    }

    public async override Task SetUp()
    {
        this.Context.Target = await MClient.Entities.GetAsync(33873);
    }
}

In this way I can develop my script inside Visual Studio, taking advantage of all of its cool features and once the script is ready I can simply copy it to Content Hub. This is maybe a little naive solution but it’s a good start for something more comprehensive, like this example Content Hub solution.

Let’s talk about automation

Software development is not only programming, is also deployment and automation. In case of Content Hub, Sitecore is responsible for the deployment and maintenance of the application but the developers are responsible for deployment of the configuration.

Depending on the license agreement Content Hub is offered with up to three environments. One environment is meant for development, second for testing new configuration changes and finally the last one for the end users. The changes in configuration can be moved between the environments using export/import feature. This is quite simple process of clicking a button on one environment and then clicking a button on another one. However, I really like to take a backup of the environment where I’m deploying changes. I also tend to rename the packages to include the name of the environment and copy them over to a shared location.

And in this is only the beginning.

Sometimes it might be required to exclude taxonomies from the deployment (because of their size, which might be impactin deployment time and small frequency of changes) so it means the packages must be split to be able to install them in correct order. This doubles the clicking and renaming. Another package split might be needed in order to update connection strings in actions which are connecting to Azure or other services. That’s even more clicking and renaming.

If only it was possible to script the entire process.

Well it turns out it is. Content hub provides command line interface which allows for some handy operations: synchronizing scripts, checking statuses of jobs and of course exporting and importing packages. If that’s not enough is possible to develop custom plugins. It is possible to select which system components to include in the package, where to save it and how it should be named. Just perfect.

First it is necessary to register and endpoint. ClientId and ClientSecret can be found in OAuth Clients page in Manage section inside the Content Hub. Redirect URI should match the URI set in the OAuth client.

ch-cli endpoint add --name "Sandbox" --url "https://contenthub.url/" --client-id "ClientId" --client-secret "ClientSecret" --redirect-uri=http://localhost:9000

Once the endpoint is created it is possible to run the actual script.

$date = Get-Date -Format "yyyyMMddhhmm"

if (-not (Test-Path $date)) {
    New-Item -Type Directory $date
}

ch-cli system  export -t EntityDefinitions -t OptionLists -o "$date/01-DEV-release-$date.zip"
ch-cli system  export -t Triggers -t Scripts -t StateFlows -o "$date/02-DEV-release-$date.zip"
ch-cli system  export -t ExportProfiles -t MediaProcessing -t RenditionLinks -t Settings -o "$date/03-DEV-release-$date.zip"
ch-cli system  export -t PortalPages -o "$date/04-DEV-release-$date.zip"
ch-cli system  export -t Policies -o "$date/05-DEV-release-$date.zip"

Sitecore XP and Content Hub

It is of course possible to connect Content Hub with Sitecore XP. Sitecore offers a package which has to be installed and of course a little configuration is necessary to make the two systems talk to each other. Two modules which are supported for such a connection are DAM and CMP.

DAM support is really simple since the assets are linked on demand by Sitecore XP users whenever they need to include an image. Inside Content Hub there is a dedicated asset search page which should be configured in Sitecore, and a small adjustment in allowed content header does the trick.

CMP support is more sophisticated since the communication is reversed. It’s Content Hub which pushes content to Sitecore every time new piece is accepted. This communication is done using Azure Service Bus and Content Hub Action to post messages to a Service Bus topic which is then monitored by Sitecore to get the content from Content Hub automatically.

I think that configuration details really deserves a dedicated article, which I would like to publish soon.

Does a cloud based application require a developer

This was the question I started my talk with. After couple of months with Content Hub I am sure there is a space for someone with developer background to use their skills working with this system. And I am pretty sure there is even more to discover!

At the end I would like to say big köszönöm (thank you in Hungarian) to everyone who helped me prepare and deliver this talk. Everyone involed in organization of this great event - without you my talk would have never existed. Łukasz Skowronski who was a great support as a room master. Sebastian Winter who helped me shape the presentation. All my friends and collegues from Poland and Apollo Division who showed their support.

Mandatory run to catch-up with the sightseeing.
Mandatory run to catch-up with the sightseeing, after spending first day on rehersing.