Craft CMS Integrations Overview | OpsBlu Docs

Craft CMS Integrations Overview

Learn how to integrate analytics and tracking tools with Craft CMS using Twig templates, plugins, and custom implementations.

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:

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)

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:

  1. Local Development: Use GTM Debug Mode or GA4 DebugView
  2. Staging: Test with separate tracking IDs
  3. 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

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>

Resources