Incoming links, tagging and content discovery



Tagging, navigation, sitemaps, content trees. Content needs to be organized somehow, and Contentful's flexible approach offers many options. Today we'll be expanding on the concept of content types as tags.We'll go over the main limitation of that pattern — retrieving entries of a single content type per query — and learn how to overcome it using incoming links, making tags more powerful than ever.Finally, we'll take a look at how reusable content that surfaces across many channels can be discovered easily using a neat trick.

A word on content geography

The historical way of managing content for the Web had created an expectation that all content belongs somewhere on the site map. So, legacy Content Management Systems (CMSes) evolved to provide neat tree structures as the default geography.Trees apply well to page-centric approaches, but not when it comes to content organized in structured, granular content fragments. Because fragments are reusable, they can surface in more than one place, across multiple channels (such as websites, native apps, etc). As such, fragments can cross-link to one another to form a complex graph, which rarely looks like a simple tree.This fundamental difference can be tricky to reconcile, especially in projects migrating from legacy to modern CMS.Splitting the content model into Topics and Assemblies helps. A graph of topics can take any shape at all, arising naturally from the very structure of the information managed by your business. Assembly trees, shaped like the delivery channel(s) they're designed for, can then reference your topics and thus indirectly organize them in trees.Assemblies, by matching the geography of your delivery channel(s), follow a structure which is familiar to your content creators. They're therefore easy to reason about and easy to navigate, acting as containers and gateways to your topics.Tiny, specialized content types can be employed to further organize those topics and assemblies. We'll call them "tags" in this article, but you could easily think of them as "sections" or "categories."

Modeling content

In Contentful, content modeling really is the answer to life, the universe and everything. You can find a detailed explanation of how to model tags in our help centre, but the basic recipe is as follows:

  • Create a "tag" content type

    • Name (short text)

    • Slug (short text)

    • Children (multiple reference to other Tag entries)

  • Add a single reference to a tag entry to your topic or assembly content types

  • Optionally use permissions to only allow certain roles to manage tags

Tags can then be easily attached to entries as references.To easily retrieve "news" entries tagged with a tag that has the slug "sports", one would run the following search by reference query:

GET /entries?content_type=news&fields.tag.fields.slug=sports

We've seen this pattern applied successfully by many users. For most use cases, it works quite nicely. But it comes with a few compromises. Let's take a look at what they are and how it's now possible to overcome them.

Limitations of the old model

Despite its ease of use, the old model presented drawbacks in some scenarios, which required careful architecting and modeling to solve.

Single content type per query

The CDA allows querying for a single content type at a time. This fits the principle of curated content very well, which assumes a high degree of knowledge about what you're querying for, but it presents issues when you don't. This is especially true when using multiple, closely related content types such as product variants. There are ways around that, of course, but they require either multiple queries or proxy content types.

Single tag per entry

Searching by reference only works on single reference fields. Meaning, entries which reference multiple tags cannot be retrieved with a single query. Again, this would traditionally be solved by running multiple queries or applying some sort of client-side caching.

Listing all entries that have a tag is difficult

Because references are unidirectional, it's impossible to start from any given tag and discover all entries that have it. Entries know about their relationship with the tag but the tag has no idea which entries link to it.Until now.

Thanks to recent developments under the hood, we are now able to expose the other side of entry references on our API. We call them incoming links.Let's say you want to list all entries marked with a known tag, regardless of content type. Previously, you needed to iterate all content types that allow referencing tags, and run a query against each one. Despite our CDA being very fast, latency adds up.With incoming links, it's possible to query for a known entry (the tag) and ask our API to respond with a list of all entries that reference it, like so:

GET /entries?links_to_entry=tag_id

And that's actually all there is to incoming links. We made it easy on purpose. Like a LEGO block, it's simple in itself but allows infinite possibilities.Coming back to tagging and content geography, incoming links is the missing piece of the puzzle. Facets are so much more powerful when they're not limited to a single content type. You can have a meta-layer of tags to construct not only a tree structure for your delivery-oriented assemblies, you can also employ facets that describe workflow states, vendor associations, marketing campaigns and anything else you can think of.While we work on native UI support for incoming links, there's an official UI extension out which makes a lot of that goodness available right now.


No matter which content geography is implemented, chances are navigating the CMS is going to be a different experience to navigating your client application. And when content is delivered across multiple channels, chances are each one navigates differently to the other. So how can content creators browse and discover content easily?One answer is to simply employ the Search and Saved Views features of our web app. Indeed, that should get you started quickly and easily. As your content base grows, it's very natural for it to be surfaced and remixed in a variety of ways. While Search and Saved Views continue to be useful throughout the entire lifetime of this content, it's often easier for content creators to navigate it using a more familiar method: the frontend itself.This is an area where using a programmable content infrastructure like Contentful really pays off. Our APIs let you neatly separate content management from presentation, while maintaining useful links between the two.Indeed, your pre-production frontends (staging websites, development mode apps) can display deeplinks back to the Web App, or just content IDs. That way, a content creator can navigate the familiar interface of the website or mobile app they're producing content for, find what they're interested in editing, and quickly switch to the Contentful web app and get to work. Our nodejs example app offers an example of this approach. By going into "Settings" and enabling editorial features, you can see links back to Contentful appearing next to each entry:



Whether for the purpose of delivering content across multiple channels, organizing it for efficient management or making it discoverable by your own editorial team, it pays to think a little bit about which content geography is best for you.Contentful traditionally employed a loose graph geography, linking entries through references. "Tag" content types can be leveraged to create different geographies, including trees and facets. Incoming links make tags more powerful than ever, unleashing their usefulness across the entire range of content types.Topics and Assemblies further help organize your model, creating a clean separation between pure topical content and delivery-oriented assemblies.Finally, our APIs allow you to wire your frontends with a degree of editorial awareness, making it easy for your content creators to browse and discover content using the interface they - hopefully! - know and love: your own apps.

Was this helpful?
add-circle arrow-right remove style-two-pin-marker subtract-circle remove