Common issues you may encounter with Strapi-powered sites and how to diagnose and fix them. Since Strapi is a headless CMS, most issues occur in your frontend framework, not in Strapi itself.
Performance Issues
Strapi-powered sites can face unique performance challenges due to their headless architecture, API calls, and frontend framework rendering strategies.
Largest Contentful Paint (LCP)
LCP measures loading performance. Strapi-specific LCP issues include:
- API response times affecting Time to First Byte (TTFB)
- Unoptimized images from Strapi media library
- Framework SSR/SSG rendering delays
- Multiple API calls blocking initial render
- Heavy JavaScript bundles in frontend frameworks
Target: LCP under 2.5 seconds
Cumulative Layout Shift (CLS)
CLS measures visual stability. Strapi-specific CLS issues include:
- Images loaded from Strapi without dimensions
- Dynamic content causing layout shifts
- Font loading in Next.js/Gatsby/Nuxt
- Component hydration shifts
- Lazy-loaded content from API
Target: CLS under 0.1
General Performance Best Practices
API Optimization:
- Use Strapi's REST API filtering and field selection
- Implement GraphQL for precise data fetching
- Enable Strapi response caching
- Use CDN for Strapi media files
- Minimize API calls with proper data fetching strategies
Frontend Framework Optimization:
- Choose appropriate rendering strategy (SSR/SSG/ISR/CSR)
- Implement proper caching (SWR, React Query, etc.)
- Code-split and lazy-load components
- Optimize bundle size
- Use modern image formats (WebP, AVIF)
Strapi Configuration:
- Enable Strapi's response cache plugin
- Configure media library provider (S3, Cloudinary, etc.)
- Use Strapi's image optimization features
- Set up proper database indexes
- Monitor Strapi server performance
For general performance concepts, see the global performance hub.
Tracking & Analytics Issues
Events Not Firing
Common causes of tracking failures on Strapi-powered sites:
- SSR/SSG timing issues (scripts running on server)
- Client-side hydration delays
- API data not loaded when tracking fires
- Framework route changes not tracked
- Missing window/browser checks in tracking code
Common scenarios:
- GA4 events fire before content data loads
- Meta Pixel not initialized due to SSR
- GTM container loads but events don't fire
- Tracking works on hard refresh but not on client navigation
- Events fire multiple times due to React re-renders
Framework-Specific Tracking Issues
Next.js:
- App Router vs Pages Router differences
- Server Components can't run client-side tracking
- Route changes not tracked in App Router
- Middleware affecting tracking scripts
Gatsby:
- Build-time vs runtime data distinction
- Page transitions not triggering events
- Plugin conflicts with tracking
Nuxt.js:
- SSR hydration affecting pixel initialization
- Nuxt modules conflicting with tracking
- Client-side only code running on server
React SPA:
- Route library integration (React Router, etc.)
- State management affecting tracking timing
- Component lifecycle timing
Tracking Best Practices
Framework-Agnostic Principles:
- Always check for
windowobject before tracking - Use
useEffect(React) oronMounted(Vue) hooks - Implement route change listeners
- Handle SSR/SSG appropriately
- Test across rendering methods
Data Availability:
- Ensure Strapi API data loaded before tracking
- Use loading states to delay tracking
- Implement proper error handling
- Verify API response structure
Testing:
- Test in development and production builds
- Test SSR, SSG, and CSR pages separately
- Use browser extensions (GA Debugger, Pixel Helper, GTM Assistant)
- Check browser console for errors
- Verify in analytics platforms (GA4, Meta Events Manager)
For general tracking concepts, see the global troubleshooting hub.
Common Strapi-Specific Issues
API Response Time
Problem: Slow API responses affecting site performance.
Diagnosis:
- Check Strapi server response times in Network tab
- Monitor Strapi server metrics
- Identify slow database queries
Solutions:
- Enable Strapi's REST cache plugin
- Optimize database queries and add indexes
- Use GraphQL to fetch only needed data
- Implement CDN for API responses
- Scale Strapi server (vertical or horizontal)
- Use Strapi's populate parameter strategically
Image Optimization
Problem: Large images from Strapi media library.
Diagnosis:
- Check image sizes in Network tab
- Audit Strapi media library
- Review frontend image implementation
Solutions:
Strapi-side:
// Use Strapi's image service formats
const imageUrl = `${STRAPI_URL}${image.url}?format=webp&width=800&quality=80`;
Frontend-side (Next.js):
// Next.js Image component with Strapi
<Image
src={`${process.env.NEXT_PUBLIC_STRAPI_URL}${image.url}`}
width={image.width}
height={image.height}
alt={image.alternativeText || ''}
loader={strapiLoader}
/>
const strapiLoader = ({ src, width, quality }) => {
return `${src}?format=webp&width=${width}&quality=${quality || 75}`;
};
CORS Errors
Problem: Frontend can't access Strapi API due to CORS.
Diagnosis:
Access to fetch at 'http://localhost:1337/api/articles' from origin 'http://localhost:3000'
has been blocked by CORS policy
Solution:
Update Strapi configuration:
// config/middlewares.js
module.exports = [
// ...
{
name: 'strapi::cors',
config: {
enabled: true,
origin: ['http://localhost:3000', 'https://yourdomain.com'],
credentials: true,
},
},
];
Populate/Relations Issues
Problem: Related data not returned from Strapi API.
Diagnosis:
// Returns: { data: { id: 1, attributes: { title: 'Article', category: {} } } }
// Expected: Full category data
Solution:
// Use populate parameter
fetch(`${STRAPI_URL}/api/articles/${id}?populate=*`)
// Or populate specific fields
fetch(`${STRAPI_URL}/api/articles/${id}?populate[category]=*&populate[author][populate][avatar]=*`)
// GraphQL (more elegant)
query {
article(id: "1") {
data {
attributes {
title
category {
data {
attributes {
name
}
}
}
}
}
}
}
Preview Mode Issues
Problem: Draft content preview not working.
Solution (Next.js example):
// pages/api/preview.js
export default async function handler(req, res) {
const { slug, secret } = req.query;
// Check secret
if (secret !== process.env.PREVIEW_SECRET) {
return res.status(401).json({ message: 'Invalid token' });
}
// Fetch draft content from Strapi
const article = await fetch(
`${process.env.STRAPI_URL}/api/articles?filters[slug][$eq]=${slug}&publicationState=preview`,
{
headers: {
Authorization: `Bearer ${process.env.STRAPI_API_TOKEN}`,
},
}
).then(r => r.json());
if (!article.data[0]) {
return res.status(404).json({ message: 'Article not found' });
}
// Enable Preview Mode
res.setPreviewData({});
res.redirect(`/articles/${slug}`);
}
Authentication State
Problem: User authentication state not synced between Strapi and frontend.
Solution:
// lib/auth.js
export const checkAuth = async () => {
const jwt = localStorage.getItem('jwt');
if (!jwt) return null;
try {
const response = await fetch(`${STRAPI_URL}/api/users/me`, {
headers: {
Authorization: `Bearer ${jwt}`,
},
});
if (!response.ok) {
localStorage.removeItem('jwt');
return null;
}
return await response.json();
} catch (error) {
console.error('Auth check failed:', error);
return null;
}
};
Debugging Tools
Browser Developer Tools
Chrome DevTools (F12):
- Console: Check for JavaScript errors
- Network: Monitor API requests to Strapi
- Application: Check localStorage, cookies, session data
- Performance: Record page load to identify bottlenecks
Strapi-Specific Debugging
Enable Strapi Debug Mode:
# .env
NODE_ENV=development
STRAPI_LOG_LEVEL=debug
Monitor Strapi Logs:
# Watch Strapi console output
npm run develop
Strapi API Testing:
- Use Postman or Insomnia
- Test API endpoints directly
- Verify populate parameters
- Check authentication headers
Analytics Debugging Tools
Browser Extensions:
Platform Tools:
- GA4 DebugView
- Meta Events Manager Test Events
- GTM Preview Mode
Performance Testing Tools
Framework-Specific Debugging
Next.js
// Enable React DevTools profiler
// next.config.js
module.exports = {
reactStrictMode: true,
compiler: {
removeConsole: process.env.NODE_ENV === 'production',
},
};
// Debug API routes
// pages/api/strapi/[...slug].js
export default async function handler(req, res) {
console.log('Strapi API Request:', req.query);
// Proxy to Strapi
}
Gatsby
# Gatsby build with verbose output
gatsby build --verbose
# Clear cache if issues
gatsby clean && gatsby develop
Nuxt
// nuxt.config.js
export default {
build: {
analyze: true, // Analyze bundle size
},
debug: process.env.NODE_ENV === 'development',
};
Common Error Messages
"Cannot read property 'attributes' of undefined"
Cause: Strapi API response structure not handled properly.
Solution:
// Bad
const title = article.attributes.title;
// Good - with optional chaining
const title = article?.attributes?.title || 'Default Title';
// Better - with type checking
if (article?.data?.attributes) {
const title = article.data.attributes.title;
}
"window is not defined"
Cause: Client-side code running on server.
Solution:
// Check for window
if (typeof window !== 'undefined') {
// Client-side code
window.gtag('event', 'page_view');
}
// Or use framework hooks
useEffect(() => {
// Runs only on client
}, []);
"Hydration failed"
Cause: SSR HTML doesn't match client-side render.
Solution:
// Use dynamic import for client-only components
const ClientOnlyComponent = dynamic(() => import('./ClientOnly'), {
ssr: false,
});
// Or use suppressHydrationWarning
<div suppressHydrationWarning>
{typeof window !== 'undefined' && <ClientComponent />}
</div>
Getting Help
Strapi Support Channels
Strapi Documentation:
Strapi Discord:
- Strapi Discord Server
- Active community support
- Direct help from Strapi team
GitHub Issues:
- Strapi GitHub
- Report bugs
- Request features
Frontend Framework Support
Next.js:
Gatsby:
Nuxt:
When to Hire a Developer
Consider hiring a developer when:
- Complex custom functionality needed
- Multiple persistent errors you can't resolve
- Performance issues despite optimizations
- Large-scale migration to Strapi
- Custom Strapi plugin development needed
- Advanced SSR/SSG implementations required
Find Developers:
- Strapi Partners
- Upwork - Search for Strapi + your framework
- Toptal
Next Steps
Performance Issues:
Tracking Issues:
Prevention:
- Document your setup
- Use TypeScript for type safety
- Implement error boundaries
- Set up monitoring (Sentry, LogRocket, etc.)
- Test across different rendering methods
- Keep Strapi and frameworks updated