Integration Guides

Craft CMS

Add Rybbit analytics to your Craft CMS site

Craft CMS renders pages from Twig templates in the templates/ folder, so the snippet goes into the base template that your section templates extend. A fresh craftcms/craft project ships a single templates/index.twig containing the full HTML document; most projects move that boilerplate into a base template and {% extends %} it.

Get your tracking snippet

In your Rybbit dashboard, open Site Settings → Tracking Script and copy your snippet. It looks like this:

<script src="https://app.rybbit.io/api/script.js?siteId=YOUR_SITE_ID" defer></script>

YOUR_SITE_ID is the numeric ID of your site. If you self-host Rybbit, app.rybbit.io is the domain of your own instance.

Add the snippet to Craft CMS

  1. Open the template that owns your <head>. In a fresh install that is templates/index.twig; in a project with a base template it is the underscore-prefixed file every page extends, such as templates/_layout.twig.
  2. Add the tag before </head>:
templates/_layout.twig
<!DOCTYPE html>
<html lang="{{ currentSite.language }}">
<head>
    <meta charset="utf-8">
    <title>{{ siteName }}</title>
    <script src="https://app.rybbit.io/api/script.js?siteId=YOUR_SITE_ID" defer></script>
</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>
  1. Every section template that extends the base template now loads the script:
templates/blog/_entry.twig
{% extends "_layout" %}

{% block content %}
    <h1>{{ entry.title }}</h1>
    {{ entry.body }}
{% endblock %}
{% endraw %}

To keep the site ID out of templates and vary it per environment, read it from .env with {{ getenv('RYBBIT_SITE_ID') }}, or store it in a Global Set and use {{ settings.rybbitSiteId }}.

Verify installation

Open your live site in a new tab and click through a few pages. Within a few seconds the pageviews appear in the Rybbit dashboard.

If nothing shows up:

  • View the page source and search for script.js?siteId= to confirm the snippet is on the page.
  • Open the browser Network tab and check that script.js returns 200 and that POST requests go to /api/track.
  • Disable ad blockers, or set up a proxy so the script loads from your own domain.
  • See the script troubleshooting guide for other common causes.

Troubleshooting

  • Template caching: if you wrap the head in {% cache %} tags, the change appears only after the cache expires or you run php craft clear-caches/all.
  • Live Preview counts as visits: the control panel's Live Preview renders your template in an iframe with x-craft-live-preview in the query string. Wrap the tag in {% if not craft.app.request.isPreview %} to leave editors' previews out of your data.
  • Control panel is not tracked: /admin uses Craft's own templates, so the snippet never runs there.
  • Multiple base templates: if some sections extend a different base (for example _layout-landing.twig), add the tag to each one, or move it into a partial and {% include %} it from every base.

Next steps

On this page