Django
Add Rybbit analytics to your Django app
Django pages extend a base template, so the snippet goes into the <head> of that base template. Put the site ID in settings.py, read from an environment variable, and pass it to templates with a small context processor so no template hard-codes the ID.
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 Django
Configure the site ID
Add the Rybbit values to settings.py, reading from the environment:
import os
RYBBIT_INSTANCE_URL = os.environ.get("RYBBIT_INSTANCE_URL", "https://app.rybbit.io")
RYBBIT_SITE_ID = os.environ.get("RYBBIT_SITE_ID", "")Set RYBBIT_SITE_ID=YOUR_SITE_ID in your production environment (or your .env file if you load one with django-environ or python-dotenv).
Expose the values to templates
Create a context processor that adds both settings to every template context:
from django.conf import settings
def rybbit(request):
return {
"RYBBIT_INSTANCE_URL": settings.RYBBIT_INSTANCE_URL,
"RYBBIT_SITE_ID": settings.RYBBIT_SITE_ID,
}Register it under TEMPLATES in settings.py:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"myproject.context_processors.rybbit",
],
},
},
]Add the tag to your base template
Open the template that every page extends, usually templates/base.html, and add the tag inside <head>:
<head>
<meta charset="utf-8">
<title>{% block title %}My Site{% endblock %}</title>
{% if RYBBIT_SITE_ID %}
<script src="{{ RYBBIT_INSTANCE_URL }}/api/script.js?siteId={{ RYBBIT_SITE_ID }}" defer></script>
{% endif %}
</head>The {% if %} guard skips the tag when RYBBIT_SITE_ID is empty, so local development is not tracked unless you set the variable.
Pages that do not {% extends "base.html" %} (for example a separate admin or landing template) need the same tag in their own <head>.
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.jsreturns200and thatPOSTrequests 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
- Tag missing: settings are read at startup, so restart the server (or your WSGI/ASGI workers) after changing
RYBBIT_SITE_ID. Confirm the context processor path matches your project package name. - Template rendered without a request: context processors only run for templates rendered with a
RequestContext, whichrender()and class-based views provide.Template.render()without a request has noRYBBIT_SITE_IDand the guard hides the tag. - Content Security Policy: if you use django-csp, add your Rybbit host to
script-srcandconnect-src, or proxy the script through your own domain. - Self-hosted instance: set
RYBBIT_INSTANCE_URLto your own domain without a trailing slash; the template appends the script path to it.
Next steps
- Track custom events such as signups, purchases and button clicks.
- Identify users to connect sessions to accounts.
- Proxy the script through your own domain to bypass ad blockers.
- Script attributes let you skip or mask URLs and tag events.