Storyblok
Sync products and assets with Storyblok
Table of Contents
- Features
- Installation
- Configuration
- Storyblok Setup
- Admin UI
- How It Works
- Image Management
- Troubleshooting
- Contributing
- License
- Support
Features
- ✅ Automatic Product Sync: Products created in Medusa are automatically synced to Storyblok
- ✅ Image Management: Product and variant images are automatically uploaded to Storyblok with smart deduplication
- ✅ Bi-directional Sync: Content updates in Storyblok sync back to Medusa via webhooks
- ✅ Variant Support: Full support for product variants with individual image galleries
- ✅ Asset Organization: Creates dedicated folders for each product's assets
- ✅ Bulk Sync: Sync multiple products or your entire catalog at once
- ✅ Cleanup: Automatically removes assets and folders when products are deleted
- ✅ Image Optimization: Built-in image optimization with configurable quality and dimensions
Installation
yarn add @alphabite/medusa-storyblok
Configuration
1. Add Plugin to Medusa Config
In your Copy to clipboardmedusa-config.js or Copy to clipboardmedusa-config.ts, add the plugin to the Copy to clipboardpluginsarray:
import { AlphabiteStoryblokPluginOptions } from "@alphabite/medusa-storyblok";
plugins: {
[
// ... other plugins
{
resolve: "@alphabite/medusa-storyblok",
options: {
accessToken: process.env.STORYBLOK_ACCESS_TOKEN,
region: process.env.STORYBLOK_REGION, // "eu" or "us"
personalAccessToken: process.env.STORYBLOK_PAT,
spaceId: process.env.STORYBLOK_SPACE_ID,
productsParentFolderId: process.env.STORYBLOK_PRODUCTS_PARENT_FOLDER_ID,
productsParentFolderName: "products",
deleteProductOnSbProductStoryDelete: false,
webhookSecret: process.env.STORYBLOK_WEBHOOK_SECRET,
imageOptimization: {
quality: 80,
width: 800,
},
} satisfies AlphabiteStoryblokPluginOptions,
},
];
}
2. Environment Variables
Add the following environment variables to your Copy to clipboard.env file:
# Storyblok Access Token (Content Delivery API - read-only)
STORYBLOK_ACCESS_TOKEN=your_access_token
# Storyblok Personal Access Token (Management API - write access)
STORYBLOK_PAT=your_personal_access_token
# Storyblok Space ID
STORYBLOK_SPACE_ID=your_space_id
# Storyblok Region (eu or us)
STORYBLOK_REGION=eu
# Parent Folder ID where product stories will be created
STORYBLOK_PRODUCTS_PARENT_FOLDER_ID=your_folder_id
# Optional: Webhook secret for validating Storyblok webhooks
STORYBLOK_WEBHOOK_SECRET=your_webhook_secret
Configuration Options
Option
Type
Required
Default
Description
Copy to clipboardaccessToken
Copy to clipboardstring
✅
-
Storyblok Access Token for Content Delivery API (read-only)
Copy to clipboardpersonalAccessToken
Copy to clipboardstring
✅
-
Personal Access Token for Management API (write access)
Copy to clipboardspaceId
Copy to clipboardstring
✅
-
Your Storyblok Space ID
Copy to clipboardregion
Copy to clipboard"eu" | "us"
✅
-
Storyblok region of your space
Copy to clipboardproductsParentFolderId
Copy to clipboardstring
✅
-
Folder ID where product stories will be created
Copy to clipboardproductsParentFolderName
Copy to clipboardstring
✅
-
Folder name (usually "products")
Copy to clipboardversion
Copy to clipboard"draft" | "published"
❌
Copy to clipboard"draft"
Version of stories to fetch
Copy to clipboardwebhookSecret
Copy to clipboardstring
❌
-
Secret for validating Storyblok webhooks
Copy to clipboarddeleteProductOnSbProductStoryDelete
Copy to clipboardboolean
❌
Copy to clipboardfalse
Delete Medusa product when Storyblok story is deleted
Copy to clipboardimageOptimization
Copy to clipboardobject
❌
-
Image optimization settings
Copy to clipboardimageOptimization.width
Copy to clipboardnumber
❌
Copy to clipboard800
Target image width in pixels
Copy to clipboardimageOptimization.quality
Copy to clipboardnumber
❌
Copy to clipboard80
Image quality (1-100)
Copy to clipboardimageOptimization.mapImageUrl
Copy to clipboardfunction
❌
-
Custom function to transform image URLs
Why Two Access Tokens?
Access Token (Copy to clipboardaccessToken):
- Used for reading content from Storyblok (Content Delivery API)
- Read-only access
- Found in: Storyblok → Settings → Access Tokens
Personal Access Token (Copy to clipboardpersonalAccessToken):
- Used for creating, updating, and deleting stories (Management API)
- Required to grant write access for syncing products
- How to get it:
- Go to your Storyblok account (top-right corner)
- Click on "My Account"
- Go to "Account Settings"
- Navigate to "Personal Access Tokens"
- Create a new token with appropriate permissions
Important: Make sure you are working with the correct Copy to clipboardspaceId, since the PAT grants write access to all of your Storyblok spaces.Storyblok Setup
1. Create a Products Folder
- In Storyblok, go to the Content tab and create a folder where all product stories will be stored (e.g., "products")
- Open the folder and note the Folder ID from the URL:
https://app.storyblok.com/#/me/spaces/{space_id}/stories/0/0/{folder_id}
↑ This is your folder ID
- Use this ID for Copy to clipboard
productsParentFolderIdin your configuration - Use the name of the folder for Copy to clipboard
productsParentFolderName
2. Create Required Bloks
Gallery Image Blok
Create a blok named Copy to clipboardgalleryImage with the following fields:
Field Name
Type
Required
Description
Copy to clipboardimage
Asset (Image)
✅
The image asset
Copy to clipboardisThumbnail
Boolean
✅
Whether this image is the thumbnail
Product Variant Blok
Create a blok named Copy to clipboardproductVariant with the following fields:
Field Name
Type
Required
Description
Copy to clipboardtitle
Text
✅
Variant title/name
Copy to clipboardmedusaProductVariantId
Text
✅
Medusa variant ID (for syncing)
Copy to clipboardgallery
Blocks
❌
Gallery of images (accepts Copy to clipboardgalleryImage blok)
Product Content Type
Create a content type named Copy to clipboardproduct with the following fields:
Field Name
Type
Required
Description
Copy to clipboardmedusaProductId
Text
✅
Medusa product ID (for syncing)
Copy to clipboardtitle
Text
✅
Product title/name
Copy to clipboardgallery
Blocks
❌
Product image gallery (accepts Copy to clipboardgalleryImage blok)
Copy to clipboardvariants
Blocks
❌
Product variants (accepts Copy to clipboardproductVariant blok)
Note: You can add any additional fields you need for your content management (description, SEO fields, custom attributes, etc.)
3. Configure Webhooks (Optional but Recommended)
To enable bi-directional sync (Storyblok → Medusa), set up webhooks:
- Go to Storyblok → Settings → Webhooks
- Create webhooks with the following URLs (replace with your backend URL):
https://your-medusa-backend.com/storyblok/webhook/story/update?token=YOUR_WEBHOOK_SECRET
https://your-medusa-backend.com/storyblok/webhook/story/delete?token=YOUR_WEBHOOK_SECRET
- Select the appropriate events:
- Story published (for update webhook)
- Story deleted (for delete webhook)
Note: The webhook secret is passed as a query parameter Copy to clipboard?token=YOUR_SECRETin the URLAdmin UI
The plugin provides a comprehensive admin UI for managing product synchronization with Storyblok.
Product Page Widget
On each product detail page in Medusa Admin, you'll see a Storyblok widget with:
When Product is Synced:
- 🟢 Green "Synced" status badge
- "Open in Storyblok" button - Opens the product story in Storyblok (new tab)
When Product is Not Synced:
- 🔴 Red "Not Synced" status badge
- "Sync to Storyblok" button - Creates the story in Storyblok with all variants and images
Storyblok Management Page
Access via Medusa Admin sidebar → "Storyblok"
This dedicated page shows all your Medusa products with their sync status:
Features:
- Product List - View all products with sync status
- Individual Sync - Each row has a "Sync" or "Open in Storyblok" button
- Bulk Selection - Checkboxes to select multiple products
- Sync Selected - Sync only checked products
- Sync All - Bulk sync all products at once
Status Indicators:
- 🟢 Synced - Product exists in Storyblok, shows "Open in Storyblok" button
- 🔴 Not Synced - Product doesn't exist in Storyblok, shows "Sync" button
How It Works
Medusa → Storyblok Sync
1. Product Creation
When a product is created in Medusa:
- ✅ A new story is created in Storyblok with the product data
- ✅ A dedicated asset folder is created (named after product slug)
- ✅ Product thumbnail is uploaded to the folder
- ✅ All product images are uploaded to the folder
- ✅ Images are added to the product's gallery with proper thumbnail marking
- ✅ Product variants are NOT created automatically (see below)
2. Product Update
When a product is updated in Medusa:
- ✅ Only the product handle (slug) is synced to Storyblok
- ❌ Other fields (title, images, etc.) are NOT synced from Medusa to Storyblok
Important: Once a product is synced to Storyblok, content management should happen in Storyblok. Updates will sync back to Medusa via webhooks.
3. Product Deletion
When a product is deleted in Medusa:
- ✅ The Storyblok story is deleted
- ✅ The product's asset folder is deleted
- ✅ All images in the folder are deleted
- ✅ Complete cleanup - no orphaned assets
4. Variant Creation
When a variant is created in Medusa:
- ✅ Variant is added to the product story in Storyblok
- ✅ Variant thumbnail is uploaded (if exists)
- ✅ Variant images are uploaded to the product's folder
- ✅ Images are added to the variant's gallery
Important: When a new product is created, the plugin will automatically also create its default variant (or the multiple variants you have added during creation), and it will upload the images added to the product or variants during creation
5. Variant Deletion
When a variant is deleted in Medusa:
- ✅ The variant is removed from the product story in Storyblok
- ⚠️ Associated images remain in the folder (may be used by product or other variants)
Storyblok → Medusa Sync
When a product story is published in Storyblok:
- ✅ Product handle is synced back to Medusa
- ✅ Product thumbnail URL is synced to Medusa
- ✅ Product images are synced to Medusa
- ✅ Variant thumbnails are synced to Medusa
- ✅ Image URLs point to optimized Storyblok CDN URLs
This enables your storefront to use Storyblok's CDN for images without additional fetches.
Image Management
Smart Deduplication
The plugin intelligently handles image uploads:
- ✅ Checks if an image already exists in the folder before uploading
- ✅ Reuses existing assets when the same image is used across variants
- ✅ Prevents duplicate uploads when variants share product images
- ✅ Case-insensitive filename matching
Folder Organization
Each product gets its own asset folder:
products/
└── my-product-slug/
├── thumbnail.webp
├── image1.png
├── image2.png
└── variant-image.jpg
Image Optimization
Images served from Storyblok are automatically optimized:
- Configurable width and quality
- Automatic WebP conversion
- CDN delivery
- Custom transformation functions supported
Troubleshooting
Products not syncing
- Check that all required environment variables are set
- Verify your Personal Access Token has write permissions
- Check Medusa logs for error messages
- Ensure the products parent folder exists in Storyblok
Images not uploading
- Verify product images have valid URLs
- Check that the asset folder exists (created automatically)
- Review Storyblok asset limits for your plan
- Check Medusa logs for upload errors
Webhooks not working
- Verify webhook URL is publicly accessible
- Check webhook secret matches in both Storyblok and Medusa config
- Review webhook logs in Storyblok dashboard
- Ensure webhook events are configured correctly
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
License
MIT
Support
For issues and questions:
- Discord Community: Join our Discord - Get help, share feedback, and connect with other users
- GitHub Issues: Report bugs or request features
- Medusa Discord: Official Medusa Discord
Credits
Developed with ❤️ by Alphabite


