While working to create a travel application using Storyblok Headless CMS, we came across the need to develop a bespoke field type. We wanted to give content authors the ability to assign “data tags” to content articles. At a high level, this required implementing “multi-select” fields, where the select options were populated from our library of data tags.
In this article, I’m going to run you through how we achieved this with Storyblok’s Field Type plugin editor. The idea is that this article can be used for both documentation purposes as well as serve as a tutorial for anyone looking to implement a similar solution.
Further Background
On our website, there were two types of content; blog articles and products (Holidays). We wanted a way to link related content to each other without the use of any hard-coded links which can become painful to manage when products go on/off sale regularly.
We first needed to better understand what was in these product pages and blog articles. We realized that do this we could use a library of data tags organised into categories. We had 12 categories of data tags, with things like; Countries, Towns/Cities, Landmarks, Rivers, Holiday Types, Experiences, Events, and more. We wanted content authors to be able to assign data tags to the content they were creating. \
However, for content authors to assign data tags to content, we needed a different field type to those supplied by Storyblok. We needed a multi-select for each data tag category, with the options populated from a library of data tags for that category. \
Now I am going to run you through how we achieved this, by first creating a Storyblok field type plugin in Vue.js, utilising the popular vue-multiselect
component.
I must add that before this I had never used Vue.js before, I am a React Developer by trade. However, the extensive Storyblok documentation made creating this plugin a breeze!
Prerequisites:
- A storyblok dev space
- A code editor (VSCode suggested)
- Node + npm
Step 1: Initial plugin creation/set up
In the top corner of your Storyblok UI you will see a dropdown next to the Storyblok logo. Once you click this you will see Plugins in the menu:
Click this and on the next screen you can create a “new” plugin.
Once you have created the plugin you will see the following screen:
This is the ‘“in browser” plugin editor. This editor is good for building simple field type plugins. You can also build more complex plugins with this editor, but I strongly recommend setting up a local development mode which makes development much simpler. These docs will run you through how to set up this local development mode.
Step 2: Implement a multi-select
As many of you may know, developing a multi-select from scratch is a pain, especially in Vue.js, a framework I was not yet familiar with. The first port of call, therefore, was npmjs.com where I found this vue-multiselect package.
A quick look at the docs I was able to implement in my Storyblok plugin:
This was a good start. I had a multiselect component that was allowing me to choose from multiple hard-coded options. Running npm run dev
and ticking the “Enable local dev mode” checkbox allowed me to view the current state of the plugin in the Storyblok UI:
Step 3: Make select options dynamic \
I found this really useful codepen, showing me how to use this vue-multiselect with a dynamic list of options. This was great, it showed me that I could use the mounted()
method to populate the select options from an API. It also gave me some useful props that I could add to the multiselect component to improve it’s UI and UX.
Now my plugin code looked like this:
Step 4: Creating the data tag library
We were lucky because we already had a big csv file of data tags that were being used on the existing website. Using a database tool called Filemaker, the data tags were organised into categories and all duplicates were removed.
After trying out a few different options for how to store the Data Tag Library, we decided to store them inside stories, having one story for each Data Tag Category. We did look into using Storyblok “Datasources”, however we decided that we might want to store metadata with these data tags and that just having a “key:value” as you do in datasources was too restrictive.
With the use of a node script and the Storyblok management API, we created these data tag categories in our Storyblok content:
To do this we had to create two new storyblok component types. One for the “Data Tag Category” and one for Data Tags themselves. We made Data Tag Category have a schema which accepted only data-tag
blocks:
We also set the Data Tag Category as Editmode = FormOnly so that storyblok wouldn’t try and load preview mode when you opened up this Data Tag Category content item.
This is done in the “content settings” of the parent folder where you select “Disable visual editor”:
Step 5: Populate Multi-Select options with our data tags
Previously, we saw how to pull options into our multi-select component via API. Now it’s a case of swapping out this API for a call to Storyblok itself.
Helpfully, Storyblok exposes their JS Client to use in your plugin, it’s accessed from this.api
. \
To create a multiselect field in which the user can select “Country” data tags, we changed our “mounted()” function to now look like this
You will also need to select the “Space Id” in the “input’ section of the Storyblok Plugin UI so that it knows in which space to look for these data tags. _Note: Failure to do this will result in a 401 error.
After implementing this new mounted function our Field Type preview now looked like so:
Step 6: Configuring which data tag category to look in
So we have it working for countries, but really, when I add a data tag field to my content schema, I want to be able to specify which category to populate options from.
This is where the “input options” come in. Just underneath where you selected the space id in the “input” section of Storyblok’s plugin editor UI, you can add key/value input options. These options are passed into your plugin and so we can access them in our plugin code:
We could then update your “mounted” function to retrieve the category from this.options
Step 7: Final styling touches and prod build
So now my component is fully functional in dev mode, but there are still some finishing touches needed to make the component feel more Storyblok-y.
Unfortunately there is no quick fix for this, it takes knowledge of how to play with browser dev tools and quite a bit of trial and error. But eventually my field type looked like this:
With the styling finalised I could now wrap this up in a production build and publish it.
To do this you run npm run build
from the root of your locally running Field Type plugin. This will generate a export.js
file in the dist
folder. To upload this to Storyblok, simply copy all the contents of this file and paste into the editor in the Storyblok plugin UI.
Click Save + Publish, uncheck “Enable Local Dev Mode” and you should see your plugin working exactly as it was before.
Step 8: Add Data Tag fields to my blog articles
Now the Field Type plugin is done, I can now add the data tag fields to our blog-post and product schemas. We decided to make a tab especially for data tags to keep them separate from content displayed on the page.
In order to add a data tag field, you define the name of it and then click “+Add”. In the first dropdown you select the type as “Plugin”, in the second select the plugin which we have just created
Also remember to define the category in your “options”
And there you have it, a multi-select Field Type in which you can select and assign country data tags to content.
We then added other data fields for each of our other data tag categories:
And we are done! Now content authors are able to assign data tags from multiple categories to the content so we can better understand what that content item is about.
This information lives within the story json and can be queried by using filters in the Storyblok Content Delivery API. This means we can dynamically link related content using these data tags. We can pull in every content item about Africa, for example, on our Africa landing page, or we can show related safari blog articles on our Kenya Safari product page.
The best thing about all of this is that it can all be done dynamically, no more hardcoding of links needed, no more headache when products come off sale.
I must say that I am impressed with how easy this was to do, especially being my first time using Vue.js. But also, the possibilities with this are endless, it truly gives Storyblok the flexibility to work in the way that you want it to.
Github link for finalised plugin code: https://github.com/shopkins131/data-tag-field-type-plugin-storyblok