DatoCMS is a headless CMS that delivers content via GraphQL API to your frontend framework. Since DatoCMS doesn't render the frontend itself, all tracking and analytics are implemented in your chosen frontend framework (Next.js, Gatsby, Nuxt, React, etc.).
Available Integrations
Analytics Platforms
- Frontend framework implementation (Next.js, Gatsby, Remix, etc.)
- Real-time content tracking with GraphQL queries
- Custom event tracking for DatoCMS content types
- Modular content block analytics
Tag Management
- Framework-specific GTM installation
- Data layer structure for DatoCMS records
- SSR/SSG compatibility with Next.js, Gatsby
- Dynamic content tracking from GraphQL queries
Marketing Pixels
- Frontend integration methods
- Conversions API for server-side tracking
- Event tracking with DatoCMS metadata
- Privacy-compliant implementation
DatoCMS-Specific Integration Considerations
Headless CMS Architecture
DatoCMS's architecture separates content management from presentation:
- DatoCMS Dashboard: Visual content editing interface
- Content Delivery API: GraphQL endpoint for content fetching
- Asset CDN: Imgix-powered image optimization
- Frontend Framework: Where all tracking is implemented
Content Delivery Methods
Real-time Preview:
- Content updates via preview endpoint
- Special handling for analytics in preview mode
- Exclude preview sessions from production analytics
CDN-Cached Content:
- Static content delivery via DatoCMS CDN
- Cache-aware analytics implementation
- Consider cache timing in event tracking
Incremental Static Regeneration (ISR):
- Next.js ISR support with DatoCMS
- Track content freshness
- Monitor revalidation patterns
Common Frontend Frameworks with DatoCMS
Next.js (Most Popular)
- App Router and Pages Router support
- Server Components and Client Components tracking
- Image optimization with next-image-loader
- API routes for server-side tracking
Gatsby
- Build-time content fetching with source plugin
- gatsby-source-datocms integration
- Static site generation tracking
- Incremental builds support
Nuxt.js
- Vue-based DatoCMS sites
- SSR and SSG support
- Nuxt modules for analytics
- Dynamic route generation
Remix
- Modern React framework support
- Loader-based data fetching
- Progressive enhancement
- Streaming SSR
GraphQL Query Integration
Leverage GraphQL queries for rich analytics data:
// Fetch content with analytics-relevant fields
const query = gql`
query BlogPost($slug: String!) {
blogPost(filter: { slug: { eq: $slug } }) {
id
title
slug
publishedAt
author {
name
}
categories {
title
}
seo {
title
description
}
}
}
`
// Track with fetched metadata
gtag('event', 'view_content', {
content_id: post.id,
content_title: post.title,
content_category: post.categories?.map(c => c.title).join(','),
author: post.author?.name
});
Modular Content Tracking
Track engagement with DatoCMS modular content blocks:
// Track specific content blocks
function trackBlockEngagement(blockType, blockId, timeSpent) {
gtag('event', 'content_block_engagement', {
block_type: blockType,
block_id: blockId,
time_spent_seconds: timeSpent,
content_id: article.id
});
}
// Example with DatoCMS structured text
post.content.blocks.forEach((block, index) => {
// Track each block type
trackBlockEngagement(block._modelApiKey, block.id, 0);
});
Preview Mode Considerations
Handle DatoCMS preview modes appropriately:
// Next.js example with DatoCMS preview mode
export default async function Page({ searchParams }) {
const isPreview = searchParams.preview === 'true';
// Skip analytics in preview mode
if (!isPreview) {
trackPageView();
}
return <Content />;
}
Image Optimization with Imgix
DatoCMS uses Imgix for powerful image optimization:
// Track optimized image performance
const responsiveImage = post.coverImage.responsiveImage;
gtag('event', 'image_load', {
content_id: post.id,
image_width: responsiveImage.width,
image_height: responsiveImage.height,
image_format: responsiveImage.webpSrcSet ? 'webp' : 'jpg',
image_srcset_sizes: responsiveImage.sizes
});
Integration Best Practices
1. Use DatoCMS Record IDs
Track content using stable DatoCMS record IDs:
// Use id for consistent tracking across URL changes
gtag('event', 'view_content', {
content_id: record.id, // Stable ID
content_slug: record.slug, // May change
content_model: record._modelApiKey // Model type
});
2. Track Content Models
Leverage DatoCMS's model structure for content classification:
gtag('event', 'content_view', {
content_type: record._modelApiKey,
content_id: record.id,
content_locale: record._locales?.[0] // Multi-language support
});
3. Monitor Real-time Content
Track live content updates using DatoCMS webhooks:
// Webhook handler for content updates
export default async function handler(req, res) {
const { entity_type, event_type, entity } = req.body;
gtag('event', 'content_updated', {
model: entity_type,
update_type: event_type,
record_id: entity.id
});
res.status(200).json({ received: true });
}
4. Handle Localized Content
For multi-language DatoCMS projects:
gtag('event', 'page_view', {
content_id: record.id,
content_locale: record._locales?.[0] || 'en',
localization_strategy: 'field-level',
available_locales: record._allLocales?.join(',')
});
5. Track Structured Text Engagement
DatoCMS uses structured text for rich content:
// Track structured text reading progress
function trackStructuredTextEngagement(content) {
const blockCount = content.blocks?.length || 0;
const wordCount = estimateWordCount(content.value);
gtag('event', 'structured_text_view', {
block_count: blockCount,
estimated_word_count: wordCount,
has_embedded_blocks: blockCount > 0
});
}
Testing Integrations
Verify tracking across different scenarios:
Draft Content:
- Exclude from production analytics
- Test preview mode handling
- Verify draft/published distinction
CDN-Cached Pages:
- Test cache hit vs miss behavior
- Verify analytics on cached content
- Monitor stale-while-revalidate
Multi-locale Content:
- Test locale-specific tracking
- Verify language switching events
- Monitor locale fallback behavior
Performance Considerations
Imgix Image Optimization
DatoCMS's Imgix integration provides powerful image optimization:
// Use responsive images from DatoCMS
const { responsiveImage } = post.coverImage;
<img
src={responsiveImage.src}
srcSet={responsiveImage.srcSet}
sizes={responsiveImage.sizes}
alt={responsiveImage.alt}
loading="eager" // For LCP images
width={responsiveImage.width}
height={responsiveImage.height}
/>
GraphQL Query Optimization
Optimize queries to reduce load time:
# Bad - fetches everything
query {
allBlogPosts {
id
_allReferencingBlogPosts
_allSlugLocales
}
}
# Good - only needed fields
query {
allBlogPosts {
id
title
slug
coverImage {
responsiveImage(imgixParams: { w: 800, fit: crop }) {
src
srcSet
width
height
}
}
}
}
Next Steps
Choose your integration to get started:
Additional Resources
DatoCMS Documentation: