Storyblok is a visual headless CMS with a unique Visual Editor that provides real-time preview. Since Storyblok is headless, all tracking and analytics are implemented in your frontend framework (Next.js, Nuxt, SvelteKit, Astro, etc.).
Available Integrations
Analytics Platforms
- Frontend framework implementation
- Component-level tracking with Storyblok blocks
- Visual Editor compatibility
- Real-time preview analytics handling
Tag Management
- Framework-specific GTM installation
- Data layer structure for Storyblok components
- Nested blocks tracking
- Bridge mode compatibility
Marketing Pixels
- Frontend integration methods
- Conversions API for server-side tracking
- E-commerce tracking with Storyblok Commerce
- Privacy and consent management
Storyblok-Specific Integration Considerations
Visual Editor Architecture
Storyblok's Visual Editor provides unique tracking considerations:
- Bridge Mode: Real-time editing requires special handling
- Preview URLs: Distinguish preview from production
- Component-Based: Track individual block interactions
- Nested Blocks: Handle hierarchical content structure
Component-Based Tracking
Track interactions with Storyblok blocks:
// Track block visibility and interactions
function trackBlockView(block) {
gtag('event', 'block_view', {
block_id: block._uid,
block_component: block.component,
block_position: getBlockPosition(block),
story_id: story.uuid
});
}
Common Frontend Frameworks with Storyblok
Next.js
- Official Storyblok React SDK
- App Router and Pages Router support
- Server Components with draft mode
- Automatic static optimization
Nuxt.js
- Official Storyblok Nuxt module
- SSR and SSG support
- Auto-imports for components
- Bridge integration
Astro
- Storyblok Astro integration
- Island architecture compatibility
- Partial hydration support
- Static-first approach
SvelteKit
- Storyblok Svelte SDK
- SSR/SSG flexibility
- Reactive stores integration
- Adapter support
Bridge Mode Handling
Handle Storyblok's Visual Editor bridge:
// Check if in Storyblok editor
import { useStoryblokState } from '@storyblok/react';
function Page({ story: initialStory }) {
const story = useStoryblokState(initialStory);
useEffect(() => {
// Only track in production (not in bridge mode)
if (!window.StoryblokBridge) {
trackPageView(story);
}
}, [story]);
return <StoryblokComponent blok={story.content} />;
}
Content Structure Impact
Storyblok's content structure for analytics:
Stories:
// Track story-level metrics
gtag('event', 'story_view', {
story_uuid: story.uuid,
story_name: story.name,
story_slug: story.full_slug,
story_published: story.published_at,
content_type: story.content?.component
});
Blocks (Components):
// Track component interactions
gtag('event', 'block_interaction', {
block_uid: block._uid,
block_component: block.component,
interaction_type: 'click',
parent_story: story.uuid
});
Relations and Links:
// Track cross-story navigation
gtag('event', 'internal_link_click', {
source_story: currentStory.uuid,
target_story: linkedStory.uuid,
link_field: 'related_articles'
});
Integration Best Practices
1. Use Story UUIDs for Tracking
Stories have stable UUIDs that persist across slug changes:
// Prefer UUID over slug for consistent tracking
gtag('event', 'content_view', {
content_id: story.uuid, // Stable
content_slug: story.full_slug, // May change
content_version: story.published_at
});
2. Track Block-Level Engagement
Measure engagement with specific components:
// Track time spent on each block
const blockObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
startBlockTimer(entry.target.dataset.blokUid);
} else {
endBlockTimer(entry.target.dataset.blokUid);
}
});
});
3. Handle Draft vs Published
Distinguish draft and published content:
// Check content version
const isDraft = story.first_published_at === null ||
new Date(story.published_at) > new Date(story.first_published_at);
gtag('event', 'content_view', {
content_id: story.uuid,
content_status: isDraft ? 'draft' : 'published',
is_latest: true
});
4. Track Localized Content
For multi-language Storyblok spaces:
gtag('event', 'page_view', {
story_uuid: story.uuid,
story_locale: story.lang || 'default',
translated_slugs: story.translated_slugs?.length || 0
});
5. Monitor Visual Editor Sessions
Exclude editor sessions from analytics:
// Detect Visual Editor context
function isInVisualEditor() {
if (typeof window === 'undefined') return false;
return window.location.search.includes('_storyblok') ||
window.StoryblokBridge !== undefined;
}
if (!isInVisualEditor()) {
initializeAnalytics();
}
E-commerce Tracking with Storyblok
If using Storyblok for e-commerce content:
// Track product views from Storyblok product blocks
gtag('event', 'view_item', {
currency: 'USD',
value: productBlock.price,
items: [{
item_id: productBlock.sku,
item_name: productBlock.name,
item_category: productBlock.category,
price: productBlock.price,
content_source: 'storyblok',
storyblok_uid: productBlock._uid
}]
});
Testing Integrations
Visual Editor Testing:
- Verify tracking disabled in editor
- Test bridge mode behavior
- Check preview URL handling
Production Testing:
- Verify page view tracking
- Test component interaction events
- Monitor cross-story navigation
Localization Testing:
- Test language switching events
- Verify locale in tracking data
- Check translated content tracking
Next Steps
Choose your integration to get started:
Additional Resources
Storyblok Documentation: