Storyblok Analytics Integrations: Setup Guide | OpsBlu Docs

Storyblok Analytics Integrations: Setup Guide

Available integrations for Storyblok-powered sites including analytics platforms, tag managers, and marketing pixels.

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

Google Analytics 4

  • Frontend framework implementation
  • Component-level tracking with Storyblok blocks
  • Visual Editor compatibility
  • Real-time preview analytics handling

Tag Management

Google Tag Manager

  • Framework-specific GTM installation
  • Data layer structure for Storyblok components
  • Nested blocks tracking
  • Bridge mode compatibility

Marketing Pixels

Meta Pixel

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: