Using a headless CMS has many benefits, and one of the biggest stems from the very thing that makes a headless CMS headless.
Headless means that there’s no front-end to the CMS product. That’s a little confusing, because technically the CMS does have a front-end, but it’s only for editing the content. The lack of a head (or front-end, in this case) means that there is no publicly-facing website delivered by the CMS product. This is in contrast to the more traditional (i.e. monolithic) CMS approach, used by products like WordPress and Drupal.
Being headless means the CMS doesn’t really care how you used the content. Its job is simply to provide the content to you, and then it’s up to you to determine the presentation layer. That means you are free to work with whatever tools or frameworks you prefer. That also means you can have more than one front-end application consuming content from a headless CMS.
This is great for when the same type of content is to be distributed across multiple front-ends (i.e. channels). Consider an organization that has both a website and native applications, but wants to share content to both channels. That content can be sourced from the same (headless) CMS and consumed individually by each application.
Or think about a fancy veterinarian’s office that has a website and a mobile application. The website has a blog, consisting of helpful tips for pet care, often written from the perspective of the animal. The mobile application currently only allows for making and checking appointments, but they want the blog posts to be natively available to that application as well. This is a perfect use case for a headless CMS!
While this is a valuable model, it is fairly simplistic and rigid, as it assumes all content is available to each channel. What if the vet wanted to be more discerning than that? What if, instead of sending all blog posts to all channels, they wanted to control which blog posts were published to the website and which to the blog on mobile (or both)?
This is where distribution channels come into play. A channel is simply a front-end that consumes data from your headless CMS. This enables your CMS to act as the source of truth for your distributed content. This is also referred to as the omnichannel approach.
As I’ve hinted at above, distribution channels are a powerful approach. They provide a one-stop-shop for content editing, wherein editors know exactly where to go and where that content will be distributed as they add or change it.
It gets a little trickier when we want to be more discerning and deliberate when deciding where each piece of content should be distributed. Using the vet as our example, let’s walk through a series of solutions in building out a distribution channel editing experience.
Right now, the vet has two channels: a website and an application. They want to send all articles to the website, but only a subset to the application.
When working with a headless CMS, one approach could be to add a field to the Post model (or content type) that would also publish the post to the application if selected.
(Note: All screenshots here are using Contentful.)
That’s nice and simple, but it doesn’t scale. In other words, it works great…until another channel comes into play. (And once you have two channels, there’s usually another on its way.)
The vet decides to spin up a marketing campaign site. They haven’t been getting much fish business, and want to create some attention. They’ve been authoring a few posts from the perspective of fish, which are largely all super cheesy, derivative of Dory from Finding Nemo. But still, it may sell.
So they spin up a new website, but they only want it to include the fish posts. They could add another toggle field, but that’s going to get out of hand real quick. (Because there will certainly be another channel sometime soon.) It’s time to start being a little more clever and flexible.
A better approach would be to start using tags on posts. Then they could pull the appropriate posts based on some tag association — maybe fish for the campaign site and mobile for the app, with all posts still being syndicated to the main website.
That method could certainly work. It’s flexible and built to scale.
However, the problem I’ve found with this approach is that it’s a little too flexible. Content editors tend to thrive when there’s just enough flexibility to be dangerous, but not so much that it gets in the way of being productive.
Using something open-ended like tags creates a scenario in which editors may desire to use the field for some other means of organization. And maybe eventually they want to display that content on the screen. Then you’re in a sticky situation: You could end up with distribution logic baked into a field that’s meant to be displayed on the front-end.
These are all hypotheticals, but they aim to point out that there’s simply a little too much flexibility here.
The other annoyance in this approach is that it’s inconsistent. The logic for pulling the appropriate posts differs from channel to channel. Wouldn’t it be nicer if every channel was treated equally and the logic for pulling articles was consistent across all channels?
To address the concerns of too much flexibility on the back-end and inconsistency on the front-end, let’s create a field that is focused solely on distribution channels and can only be interpreted as such.
We’ll create a new channels field. That field could be a multi-select list of channels to which the content can be distributed.
The front-ends all then have the same logic for gathering posts. They’d simply have to swap out the value of the channel.
Revisiting the tag association approach for a second, its logic looked like this:
The beauty of this channel field approach is that it is consistent across front-ends, while serving a clear and specific purpose in the CMS. The updated logic looks like this:
Now that feels like a solution I can get along with. And I like to think the animals would appreciate it, too.
One thing to note when taking the channel field approach is to also account for canonicalization. When content is duplicated across multiple pages on the web, Google only gives credence to one. And if you don’t tell Google which one is the original (the one that should show up in search results), it’ll guess. And it’s always good to be intentional when it comes to SEO.
It would be beneficial to have another field that sets the canonical host. For one project, we actually combined them all together into an interactive field using Contentful.
But that took a bit of work to get it right. You could accomplish this more easily by adding a canonical_host field with a singular-select field of your channels as choices.
Keep in mind that not all content types (or models) are designed to fit within this model. For example, we’ve found in working with our clients that pages tend to be super specific to the site on which they are published. The styling elements and the components within those pages are often drastically different from one site to another.
The reason posts work well as an example is because they are structured. Blog posts have structured fields that get mapped to specific areas on the page. Consider other types of content like locations or products, which also often have a strict structure to them.
Compare that with pages, which, if you’re designing a solid content editing experience, are often more fluid and flexible. For example, you may have to switch around sections on page, while a post is typically just a title, some meta data, imagery, and body copy.
In general, this approach works best when paired with structured content models.
That’s it — now it’s time for you to try it out!
Sign up for our email newsletter. Nothing spammy about it. Just a monthly rundown of what we’re sharing.