This guide covers common issues encountered in Craft CMS implementations, from performance optimization to tracking problems, with specific solutions for Craft's architecture.
Common Issue Categories
Performance Issues
Performance problems in Craft CMS typically fall into these categories:
Page Load Performance
- Slow database queries - Inefficient element queries
- Asset loading issues - Large images without transforms
- Template caching problems - Missing or misconfigured caching
- Plugin conflicts - Resource-heavy plugins
Core Web Vitals
- LCP (Largest Contentful Paint) - Image optimization, asset delivery
- CLS (Cumulative Layout Shift) - Layout stability, dynamic content
- FID (First Input Delay) - JavaScript execution, interactivity
Tracking and Analytics Issues
Common tracking problems:
- Events not firing - JavaScript errors, timing issues
- Duplicate events - Multiple script loads, session issues
- Missing data - Environment configuration, conditional loading
- Cross-domain tracking - Multi-site setups
Content and Template Issues
Template and content problems:
- Twig errors - Syntax errors, undefined variables
- Matrix field performance - Large content blocks
- Asset transform failures - Image processing issues
- GraphQL query errors - Headless implementation issues
Quick Diagnostic Checklist
Step 1: Check System Status
{# Add to any template for debugging #}
{% if craft.app.config.general.devMode %}
<!-- System Diagnostics -->
<!-- Craft Version: {{ craft.app.version }} -->
<!-- PHP Version: {{ craft.app.php.version }} -->
<!-- Environment: {{ craft.app.config.general.environment }} -->
<!-- Dev Mode: {{ craft.app.config.general.devMode ? 'Enabled' : 'Disabled' }} -->
<!-- Cache Method: {{ className(craft.app.cache) }} -->
<!-- Database Driver: {{ craft.app.db.driverName }} -->
{% endif %}
Step 2: Enable Debug Toolbar
Enable Craft's debug toolbar in development:
// config/general.php
return [
'dev' => [
'devMode' => true,
'enableTemplateCaching' => false,
'allowAdminChanges' => true,
],
];
Step 3: Check Error Logs
Monitor Craft's log files:
# View storage logs
tail -f storage/logs/web.log
# Check queue logs
tail -f storage/logs/queue.log
# PHP error log location (varies by setup)
tail -f /var/log/php-fpm/error.log
Performance Troubleshooting
Database Query Optimization
Identify slow queries using the debug toolbar:
{# Inefficient query - loads all entries #}
{% set entries = craft.entries()
.section('blog')
.all() %}
{# Optimized query - only load what you need #}
{% set entries = craft.entries()
.section('blog')
.limit(10)
.with(['author', 'featuredImage'])
.all() %}
Template Caching
Implement strategic caching:
{# Cache expensive operations #}
{% cache globally using key "global-navigation" %}
{% set navEntries = craft.entries()
.section('navigation')
.all() %}
<nav>
{% for item in navEntries %}
<a href="{{ item.url }}">{{ item.title }}</a>
{% endfor %}
</nav>
{% endcache %}
{# Cache with entry-specific keys #}
{% cache using key "entry-#{entry.id}" for 1 hour %}
{# Expensive template code #}
{% endcache %}
Asset Transform Optimization
Use Craft's image transforms instead of serving full-size images:
{# Inefficient - serves full-size image #}
<img src="{{ asset.url }}" alt="{{ asset.title }}">
{# Optimized - uses transform #}
{% set transform = {
width: 800,
height: 600,
mode: 'crop',
quality: 80,
format: 'webp'
} %}
<img src="{{ asset.getUrl(transform) }}" alt="{{ asset.title }}">
{# Even better - responsive images #}
<picture>
<source srcset="{{ asset.getUrl({ width: 400, format: 'webp' }) }} 400w,
{{ asset.getUrl({ width: 800, format: 'webp' }) }} 800w,
{{ asset.getUrl({ width: 1200, format: 'webp' }) }} 1200w"
type="image/webp">
<img src="{{ asset.getUrl({ width: 800 }) }}"
srcset="{{ asset.getUrl({ width: 400 }) }} 400w,
{{ asset.getUrl({ width: 800 }) }} 800w,
{{ asset.getUrl({ width: 1200 }) }} 1200w"
sizes="(max-width: 768px) 100vw, 800px"
alt="{{ asset.title }}">
</picture>
Analytics Troubleshooting
Scripts Not Loading
Common causes and solutions:
{# Check environment configuration #}
{% set analyticsId = getenv('GOOGLE_ANALYTICS_ID') %}
{% set environment = craft.app.config.general.environment %}
<!-- Debug Output -->
{% if craft.app.config.general.devMode %}
<!-- Analytics ID: {{ analyticsId ? 'Set (' ~ analyticsId ~ ')' : 'NOT SET' }} -->
<!-- Environment: {{ environment }} -->
<!-- Should Load: {{ analyticsId and environment == 'production' ? 'YES' : 'NO' }} -->
<!-- Live Preview: {{ craft.app.request.isLivePreview ? 'YES' : 'NO' }} -->
{% endif %}
Events Not Firing
Debug event tracking:
{% if craft.app.config.general.devMode %}
<script>
// Log all GTM dataLayer pushes
window.dataLayer = window.dataLayer || [];
var originalPush = window.dataLayer.push;
window.dataLayer.push = function() {
console.log('DataLayer Push:', arguments[0]);
return originalPush.apply(window.dataLayer, arguments);
};
// Log GA4 events
var originalGtag = window.gtag || function() {};
window.gtag = function() {
console.log('GA4 Event:', arguments);
return originalGtag.apply(this, arguments);
};
// Log Meta Pixel events
var originalFbq = window.fbq || function() {};
window.fbq = function() {
console.log('Meta Pixel:', arguments);
return originalFbq.apply(this, arguments);
};
</script>
{% endif %}
Content Security Policy Issues
If scripts are blocked by CSP:
// config/general.php
return [
'*' => [
'securityHeaders' => [
'Content-Security-Policy' => implode('; ', [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com https://connect.facebook.net",
"img-src 'self' data: https://www.google-analytics.com https://www.googletagmanager.com https://www.facebook.com",
"connect-src 'self' https://www.google-analytics.com https://analytics.google.com https://www.facebook.com",
"frame-src https://www.googletagmanager.com",
]),
],
],
];
Common Error Messages
"Undefined variable" Errors
{# Problem - variable might not exist #}
{{ entry.customField }}
{# Solution 1 - Check if defined #}
{% if entry.customField is defined %}
{{ entry.customField }}
{% endif %}
{# Solution 2 - Use default filter #}
{{ entry.customField ?? 'Default Value' }}
{# Solution 3 - Safe navigation #}
{{ entry.customField|default('') }}
"Call to a member function on null"
{# Problem - trying to access property on null object #}
{{ entry.author.fullName }}
{# Solution - check existence first #}
{% if entry.author %}
{{ entry.author.fullName }}
{% endif %}
{# Or use null-safe operator #}
{{ entry.author.fullName ?? 'Unknown Author' }}
Asset Transform Failures
# Check transform permissions
chmod -R 755 web/cpresources/
chown -R www-data:www-data web/cpresources/
# Clear transform cache
./craft clear-caches/asset-transform-index
# Regenerate transforms
./craft clear-caches/asset-indexing-data
Environment-Specific Issues
Live Preview Not Working
{# Ensure scripts don't break Live Preview #}
{% if not craft.app.request.isLivePreview %}
{# Analytics and tracking scripts #}
{% endif %}
Multi-Site Issues
{# Debug current site context #}
{% if craft.app.config.general.devMode %}
<!-- Current Site: {{ currentSite.handle }} -->
<!-- Current Site ID: {{ currentSite.id }} -->
<!-- Current Language: {{ currentSite.language }} -->
<!-- Base URL: {{ currentSite.baseUrl }} -->
{% endif %}
Plugin Conflicts
Identify Conflicting Plugins
# Disable all plugins
./craft plugin/disable --all
# Enable one at a time to identify the problem
./craft plugin/enable plugin-handle
# Check plugin compatibility
./craft plugin/list
Debugging Tools
Craft Debug Toolbar
The debug toolbar provides:
- Database query profiling
- Template rendering time
- Memory usage
- Cache hit/miss ratios
- Deprecation warnings
Custom Debug Panel
Create a custom debug panel:
{# templates/_debug/panel.twig #}
{% if craft.app.config.general.devMode %}
<div id="craft-debug-panel" style="position: fixed; bottom: 0; right: 0; background: #000; color: #fff; padding: 20px; z-index: 99999;">
<h3>Debug Info</h3>
<ul>
<li>Template: {{ _self }}</li>
<li>Entry ID: {{ entry.id ?? 'N/A' }}</li>
<li>Section: {{ entry.section.handle ?? 'N/A' }}</li>
<li>Type: {{ entry.type.handle ?? 'N/A' }}</li>
<li>Queries: {{ craft.app.db.queryCount }}</li>
<li>Memory: {{ (memory_get_usage() / 1024 / 1024)|round(2) }} MB</li>
</ul>
<button
</div>
{% endif %}
Performance Monitoring
Query Logging
Enable query logging in development:
// config/db.php
return [
'dev' => [
'enableLogging' => true,
'enableProfiling' => true,
],
];
Template Performance
Monitor template rendering time:
{% if craft.app.config.general.devMode %}
{% set startTime = now|date('U') %}
{# Your template code #}
{% set endTime = now|date('U') %}
<!-- Template rendered in {{ endTime - startTime }} seconds -->
{% endif %}
Getting Help
Craft CMS Resources
- Discord: Craft CMS Discord
- Stack Exchange: Craft CMS Stack Exchange
- GitHub Issues: Craft CMS GitHub
- Documentation: Craft CMS Docs
System Report
Generate a system report for support:
# Via CLI
./craft system-report
# Via Control Panel
# Navigate to: Utilities → System Report
Specific Troubleshooting Guides
Performance Issues
- LCP Optimization - Fix Largest Contentful Paint issues
- CLS Fixes - Resolve layout shift problems
Tracking Issues
- Events Not Firing - Debug analytics tracking
Prevention Best Practices
1. Use Eager Loading
{# Prevent N+1 query problems #}
{% set entries = craft.entries()
.section('blog')
.with(['author', 'featuredImage', 'categories'])
.all() %}
2. Implement Caching
// config/general.php
return [
'production' => [
'enableTemplateCaching' => true,
'cacheDuration' => 86400, // 24 hours
],
];
3. Monitor Performance
Use tools like:
- Google Lighthouse - Performance audits
- WebPageTest - Detailed performance testing
- New Relic / Blackfire - APM monitoring
- Craft Debug Toolbar - Built-in profiling
4. Regular Maintenance
# Clear caches
./craft clear-caches/all
# Update Craft
composer update craftcms/cms
# Optimize database
./craft db/optimize
# Clean up old revisions
./craft gc