Craft CMS provides multiple pathways for integrating analytics and tracking tools into your website. This guide covers the key approaches and best practices for implementing tracking solutions in your Craft CMS projects.
Integration Methods in Craft CMS
1. Twig Template Integration
The most common and flexible approach is implementing tracking scripts directly in your Twig templates:
{# Layout template (e.g., _layout.twig) #}
<!DOCTYPE html>
<html>
<head>
{# Head scripts - GTM, GA4, etc. #}
{{ craft.app.config.general.analyticsHeadScript|raw }}
</head>
<body>
{# GTM noscript fallback #}
{{ craft.app.config.general.analyticsBodyScript|raw }}
{# Your content #}
{{ block('content') }}
</body>
</html>
Advantages:
- Full control over script placement and execution
- Easy to implement conditional loading based on environment
- Can leverage Craft's native templating features
- No additional plugin dependencies
2. Plugin-Based Integration
Several plugins simplify analytics integration in Craft CMS:
SEOmatic Plugin
The most popular solution for managing analytics in Craft CMS:
composer require nystudio107/craft-seomatic
Features:
- Built-in support for Google Analytics, Google Tag Manager, and Facebook Pixel
- Control panel interface for managing tracking IDs
- Environment-aware tracking (disable in dev/staging)
- JSON-LD schema integration
- GraphQL API support
Configuration:
// config/seomatic.php
return [
'environment' => getenv('ENVIRONMENT') ?: 'production',
'devServerManifestPath' => getenv('VITE_DEV_SERVER_MANIFEST_PATH'),
];
Other Useful Plugins
- Analytics Widget: Dashboard widgets for viewing GA4 data
- Cookie Consent: GDPR-compliant cookie management for analytics
- Retour: Track and manage 404s and redirects with analytics integration
3. Environment Configuration
Store tracking IDs and configuration in environment variables:
# .env file
GOOGLE_ANALYTICS_ID="G-XXXXXXXXXX"
GTM_CONTAINER_ID="GTM-XXXXXXX"
META_PIXEL_ID="123456789012345"
ENVIRONMENT="production"
Access in Twig templates:
{% set analyticsId = getenv('GOOGLE_ANALYTICS_ID') %}
{% if analyticsId and craft.app.config.general.environment == 'production' %}
{# Load analytics script #}
{% endif %}
4. Custom Plugin Development
For complex requirements, create a custom Craft plugin:
// modules/analytics/Module.php
namespace modules\analytics;
use Craft;
use craft\events\TemplateEvent;
use craft\web\View;
use yii\base\Event;
class AnalyticsModule extends \yii\base\Module
{
public function init()
{
parent::init();
Event::on(
View::class,
View::EVENT_END_BODY,
function (TemplateEvent $event) {
if (Craft::$app->config->general->environment === 'production') {
$event->output .= $this->getAnalyticsScript();
}
}
);
}
private function getAnalyticsScript(): string
{
// Return your analytics script
return '';
}
}
Key Integration Areas
Google Analytics 4 (GA4)
- Setup and configuration with Craft CMS
- Event tracking for user interactions
- E-commerce tracking with Craft Commerce
- Enhanced conversions and user properties
Google Tag Manager (GTM)
- Container installation and management
- Data layer implementation with Twig
- Custom event triggering
- Dynamic variable population from Craft entries
Meta Pixel (Facebook)
- Pixel installation and verification
- Standard and custom event tracking
- Catalog integration for e-commerce
- Conversion API server-side implementation
Best Practices
Environment-Aware Loading
Only load tracking scripts in production:
{% if craft.app.config.general.environment == 'production' %}
{# Production tracking scripts #}
{% elseif craft.app.config.general.devMode %}
<!-- Analytics disabled in dev mode -->
{% endif %}
Content Security Policy (CSP)
Configure CSP headers to allow analytics scripts:
// config/general.php
return [
'*' => [
'securityHeaders' => [
'Content-Security-Policy' => [
'script-src' => "'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com",
'img-src' => "'self' data: https://www.google-analytics.com https://www.googletagmanager.com",
'connect-src' => "'self' https://www.google-analytics.com",
],
],
],
];
GDPR Compliance
Implement cookie consent before loading tracking scripts:
{% if craft.cookies.get('analytics_consent') == 'accepted' %}
{{ include('_analytics/google-analytics') }}
{{ include('_analytics/meta-pixel') }}
{% else %}
{{ include('_components/cookie-consent') }}
{% endif %}
Testing and Validation
Use Craft's environment settings to test integrations:
- Local Development: Use GTM Debug Mode or GA4 DebugView
- Staging: Test with separate tracking IDs
- Production: Monitor real-time data and tag firing
GraphQL and Headless Implementations
For headless Craft CMS setups, return tracking configuration via GraphQL:
query {
globalSet(handle: "siteSettings") {
... on siteSettings_GlobalSet {
googleAnalyticsId
gtmContainerId
metaPixelId
}
}
}
Implement tracking in your front-end application using the returned configuration.
Live Preview Considerations
Disable tracking during Live Preview sessions:
{% if not craft.app.request.isLivePreview %}
{# Analytics scripts #}
{% endif %}
Performance Optimization
Async/Defer Loading
Load analytics scripts asynchronously to avoid blocking page rendering:
<script async src="https://www.googletagmanager.com/gtag/js?id={{ analyticsId }}"></script>
Resource Hints
Add DNS prefetch and preconnect hints:
<link rel="dns-prefetch" href="//www.google-analytics.com">
<link rel="preconnect" href="https://www.google-analytics.com">
<link rel="preconnect" href="https://www.googletagmanager.com">
Next Steps
- Google Analytics Setup - Configure GA4 on Craft CMS
- Google Tag Manager Setup - Install and configure GTM
- Meta Pixel Setup - Implement Facebook Pixel tracking
Common Integration Patterns
Multi-Site Tracking
Handle different tracking IDs for multi-site installations:
{% set analyticsId = {
'site1': 'G-XXXXXXXXX1',
'site2': 'G-XXXXXXXXX2',
}[currentSite.handle] ?? null %}
{% if analyticsId %}
{# Load analytics with site-specific ID #}
{% endif %}
User Role-Based Tracking
Exclude admin users from tracking:
{% set currentUser = currentUser ?? null %}
{% if not currentUser or not currentUser.isInGroup('admins') %}
{# Analytics scripts #}
{% endif %}
Dynamic Content Tracking
Track Craft-specific content interactions:
{# Track entry views #}
<script>
gtag('event', 'view_entry', {
'entry_type': '{{ entry.type.handle }}',
'entry_id': '{{ entry.id }}',
'section': '{{ entry.section.handle }}'
});
</script>