The Storyblok Bridge V1
This documentation is for the Storyblok bridge Version 1. Please check out our documentation for Version 2: Storyblok Bridge V2.
To build a bridge between Storyblok and your website, there needs to be included a script on your page. This script will communicate via iframe with Storyblok to tell the editing interface which component needs to be opened when the user clicks on it.
This is done using a simple HTML comment before that element which is shipped in the draft JSON by adding the key _editable
to each component.
Include the script inside your tag
<script src="//app.storyblok.com/f/storyblok-latest.js?t=YOUR_TOKEN" type="text/javascript">
</script>
You can see the preview token (= YOUR_TOKEN) via the dashboard of your space. You can also conditionally exclude the script tag if the user is not in the edit mode.
Methods to check for the edit mode:
- Check for the URL parameter _storyblok
- Check for a cookie (You could set a cookie the first time the url has _storyblok in it)
Usage
For a server rendered website the following code will reload your website as soon the user saves or publishes a story.
// Optionally init if you have not provided the ?t parameter to the script tag already.
storyblok.init({
accessToken: 'your_token'
})
storyblok.on(['published', 'change'], function() {
location.reload(true)
})
storyblok.pingEditor(function() {
if (storyblok.inEditor) {
storyblok.enterEditmode()
}
})
Events
You can listen to events calling the on
handler:
storyblok.on('event_name', function(data) {
console.log(data);
})
For the published
event this would look like:
storyblok.on('published', function(data) {
console.log(data);
// invalidate cache, ...
})
For the app "Sync Button" there is a special event you can listen to:
storyblok.on('customEvent', function(data) {
if (data.event == 'start-sync') {
// Do sync
}
})
You get a 404 error after changing the slug of a Story?
If you use Storyblok with serverside rendering and want to reload whenever the content changed you need to make an additional check on the slugChanged attribute. This makes sure that the page doesn’t throw a 404 error if you change the slug:
Published and Change event
storyblok.on(['published', 'change'], function(event) {
if (!event.slugChanged) {
location.reload(true)
}
})
Input event
storyblok.on('input', function(event) {
// Access currently changed but not yet saved content via:
console.log(event.story.content)
})
Use the addComments functionality to add the _editable
properties to all blocks in your content.
Event | Will be emitted |
---|---|
input | after a user changes the value of a field |
change | after the user saves the content |
published | after the user clicks publish |
unpublished | after the user clicks unpublish |
enterEditmode | after the editor has been initialized in the editmode |
customEvent | custom event used by third party plugins |
Functions
storyblok.init(config)
config
Object
accessToken
String: The private token of the Content Delivery API to receive draft versions of content. You can find it in your space dashboard at https://app.storyblok.com.customParent
String: If you are using the Storyblok editor on your own domain a url needs to be provided. Default is: https://app.storyblok.com.
Example
storyblok.init({
accessToken: 'xf5dRMMjltLzKOcNgMaU9Att'
})
storyblok.addComments(story_object, story_id)
Enhance the event data with the _editable
properties across all components.
window.storyblok.on('input', (payload) => {
console.log(payload.story.content)
// Output: {
// "story": {
// "id": 123,
// "content": {
// "body":
// {
// "component":"hero",
// "headline": "123123"
// },
// {
// "component":"hero",
// "headline": "123123"
// }
// ]
// }
// }
//}
let updatedStoryContent = window.storyblok.addComments(payload.story.content, payload.story.id)
console.log(updatedStoryContent)
// Output: {
// "story": {
// "id": 123,
// "content": {
// "component": "page",
// "body": [
// {
// "component":"hero",
// "headline": "123123",
// "_editable": "<!- correct editable tag -->"
// },
// {
// "component":"hero",
// "headline": "123123",
// "_editable": "<!- correct editable tag -->"
// }
// ],
// "_editable": "<!- correct editable tag -->"
// }
// }
//}
// TODO: Set your state
})
Example
storyblok.isInEditor() and pingEditor()
With these functions you can check if your user has opened a page inside Storyblok.
Example
storyblok.pingEditor(() => {
if (storyblok.isInEditor()) {
// getStory('draft')
} else {
// getStory('published')
}
})
storyblok.get(query, success, error)
Get a single content entry in the frontend.
query
Objectversion
String: ‘draft’ or ‘published’. Default is ‘published’
success
Function: Success callbackerror
Function: Error callback
Example
storyblok.get({
slug: 'home',
version: 'draft'
}, (data) => {
var story = data.story
})
storyblok.getAll(query, success, error)
Get multiple content entries
query
Objectwith_tag
, Stringstarts_with
, Stringversion
, Stringsort_by
, Stringfilter_by
, Stringper_page
, Stringpage
, String
success
Function, Success callbackerror
Function, Error callback
Example
storyblok.getAll({
version: 'draft'
}, (data, xhrResponse) => {
var total = xhrResponse.getResponseHeader('Total')
var stories = data.stories
})
Troubleshooting
Why is the live preview not working?
Check if you are not redirecting to another url by clicking "Open draft" in the top right submenu. The url should contain the query parameter _storyblok.
How to validate if the user is viewing your site in the Storyblok editor?
If the user opens your page in Storyblok, we add a few parameters which you can use to securely validate their use of the edit mode.
You will need that validation to load the right version of your content to the right users. The draft
version is for the editor and the published
version is for the public.
A simple validation would be to check if there is the _storyblok parameter in url. This could be done in the frontend or in the backend. But for a secure check we recommend to implement the logic in the backend and validate the _storyblok_tk parameter.
Here are some examples of how to securely check if the user is in edit mode:
import crypto from 'crypto'
// getQueryParam = access requests URL param by name
let validationString = getQueryParam('_storyblok_tk[space_id]') + ':' + YOUR_PREVIEW_TOKEN + ':' + getQueryParam('_storyblok_tk[timestamp]')
let validationToken = crypto.createHash('sha1').update(validationString).digest('hex')
if (getQueryParam('_storyblok_tk[token]') == validationToken &&
getQueryParam('_storyblok_tk[timestamp]') > Math.floor(Date.now()/1000)-3600) {
// you're in the edit mode.
this.editMode = true
}
$sb = $app['request']->query->get('_storyblok_tk');
if (!empty($sb)) {
$pre_token = $sb['space_id'] . ':' . YOUR_PREVIEW_TOKEN . ':' . $sb['timestamp'];
$token = sha1($pre_token);
if ($token == $sb['token'] && (int)$sb['timestamp'] > strtotime('now') - 3600) {
$app['config.storyblok.edit_mode'] = true;
// you're in the edit mode.
}
}
In the demo above we expect 1 hour as the time of a token being valid. So basically that an editor will work max 1 hour on one page before switching to another entry inside the editor or refreshing the browser window. You can extend that by adjusting 3600
with the value you need.
These are the parameters Storyblok appends to your url:
Param | Description |
---|---|
_storyblok | the content entries ID |
_storyblok_tk[space_id] | the space ID |
_storyblok_tk[timestamp] | a timestamp |
_storyblok_tk[token] | a validation token. Combination of space_id, timestamp and your preview_token |
_storyblok_release | currently selected id of a release |
_storyblok_lang | currently selected language |
_storyblok_c | content type of the story |