Content modeling with Shopstory

In this chapter we discuss the best ways to add Shopstory to your content model. So far in the "Getting started" guide we only scratched the surface:

  1. We added a new content type (or document type) Shopstory Block to the content model. It's a very simple type that has only 2 fields: title and shopstory field. The function of the title is organisational. It makes it easy to find the block we're looking for. shopstory represents Shopstory content.

  2. We created a page /shopstory-block/[entryId].tsx which purpose is to render the content from Shopstory Block which id equals entryId value from the URL.

This example is good to get started fast but it's not very practical. In reality you don't need a /shopstory-block page, but you probably want to add Shopstory capabilities in your own content types representing pages (landing page, product page, etc).

Traditional page content management

For most projects the CMS data model for managing page content is very similar. Each reusable page block (like hero banner, featured products, etc) is represented by its own content type. These block content types are then referenced by content types representing pages like Landing Page, Product Page, etc. The end result usually looks like this:

This pattern is used in literally every headless CMS. The problem with it is that marketing teams and designers can only use the very narrow set of sections and each time they have a new idea they fall into long development cycles. Also, the library of content blocks must be constantly maintained and the bigger it gets the harder it becomes (and imagine the moment when a big redesign comes up). At Shopstory we believe that developers should focus on other things like integrations, stability, performance or custom features and pass the ownership for building the 100th variant of the hero section directly to the designers or marketers.

Adding Shopstory to the content model

The most important information about Shopstory is that it's really just a CMS field. You can think of Shopstory as something very similar to rich text, just way more advanced. As like you can add rich text field anywhere within your content model, so you can add a Shopstory field.

You can learn here how to do it in your CMS.

The place where Shopstory is most valuable are content types representing page content (landing pages, product pages, etc). There are two recommended ways of adding Shopstory to these content types:

  1. Blocks mode.

  2. Full page mode.

Blocks mode

Blocks mode is the least intrusive way of adding Shopstory to your project. It simply means that entries of Shopstory Block type can be added to your existing page builder fields. Shopstory Block is treated just as another reusable content block:

When using rendering Shopstory content in blocks mode please remember to use only one instance of ShopstoryClient and simply run client.add() for each block. Internally it allows Shopstory to fetch all the resources of the same type in one call instead of one call per block which is a huge performance gain.

Full-page mode

Full page mode means that Shopstory field is added directly to your page content type and it replaces traditional page builder field. It allows editors to build entire page visually with Shopstory in one go. The advantages of this approach:

  1. No need of turning Shopstory on and off all the time. It matters especially when most of the blocks are built with Shopstory.

  2. Full WYSIWYG experience, users always see exactly what's gonna be rendered in the browser. This is particularly important for CMSes without live preview like Contentful or Strapi.

Can I use my custom reusable blocks inside of Shopstory?

Absolutely yes. The general recipe is like this:

  1. Add a new custom component, let's call it Custom Section (the name is arbitrary).

  2. The component schema should have one field of the type linking to other CMS entry. For Contentful it will be contenful.entry, for Sanity sanity.document. You can find full code examples in CMS Guides. The field should narrow down the content types that can be linked (only the content types representing your custom sections should be allowed). For Sanity the schema could look like this:

    schema: [ 
        prop: "section",
        type: "resource",
        label: "Sanity Section",
        resourceType: "sanity.document",
        params: {
          // only the allowed custom content types
          documentType: ["block_banner", "block_twoColumns"], 
  3. (Optional) Customize how data is fetched from the CMS. Please read the Resources to learn more.

As you can see thanks to this approach you can easily embed custom-coded sections inside of Shopstory even in a full page mode.

Last updated