Django Open Graph Meta Tags: Add OG Tags to Templates and Views
Learn how to add og:title, og:image, og:description, and Twitter card tags to Django templates — with per-view dynamic data and a reusable base template pattern.
Why Django is great for OG tags
Django renders HTML on the server, so social crawlers automatically receive a fully populated page — including any <meta> tags in your templates. There is no JavaScript execution step; what Django renders is what crawlers read. This makes adding OG tags straightforward: it's just HTML in a template.
Base template with OG tag blocks
The cleanest pattern is to define default OG tags in a base.html template and override them in child templates using Django's {% block %} tag:
{# templates/base.html #}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}My Django Site{% endblock %}</title>
{# Open Graph #}
<meta property="og:title" content="{% block og_title %}My Django Site{% endblock %}">
<meta property="og:description" content="{% block og_description %}Default site description.{% endblock %}">
<meta property="og:image" content="{% block og_image %}https://example.com/og-default.jpg{% endblock %}">
<meta property="og:url" content="{% block og_url %}https://example.com{% endblock %}">
<meta property="og:type" content="{% block og_type %}website{% endblock %}">
{# Twitter Card #}
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{% block twitter_title %}My Django Site{% endblock %}">
<meta name="twitter:description" content="{% block twitter_description %}Default site description.{% endblock %}">
<meta name="twitter:image" content="{% block twitter_image %}https://example.com/og-default.jpg{% endblock %}">
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>Override in child templates
In any page template that extends base.html, override only the blocks you need:
{# templates/blog/post_detail.html #}
{% extends "base.html" %}
{% block title %}{{ post.title }} | My Blog{% endblock %}
{% block og_title %}{{ post.title }}{% endblock %}
{% block og_description %}{{ post.excerpt }}{% endblock %}
{% block og_image %}{{ post.cover_image_url }}{% endblock %}
{% block og_url %}https://example.com/blog/{{ post.slug }}/{% endblock %}
{% block og_type %}article{% endblock %}
{% block twitter_title %}{{ post.title }}{% endblock %}
{% block twitter_description %}{{ post.excerpt }}{% endblock %}
{% block twitter_image %}{{ post.cover_image_url }}{% endblock %}
{% block content %}
<h1>{{ post.title }}</h1>
{{ post.body }}
{% endblock %}Passing OG data from views
Pass context variables from your view and render them directly in the template:
# views.py
from django.shortcuts import render, get_object_or_404
from .models import Post
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug)
og_image = post.cover_image.url if post.cover_image else request.build_absolute_uri('/static/og-default.jpg')
return render(request, 'blog/post_detail.html', {
'post': post,
'og_image': og_image,
'og_url': request.build_absolute_uri(),
})Use request.build_absolute_uri() to generate absolute URLs for og:url and image paths.
django-meta package
For complex sites, the django-meta package provides a structured approach with model mixins, view mixins, and template tags:
pip install django-meta
# settings.py
INSTALLED_APPS = [..., 'meta']
META_SITE_PROTOCOL = 'https'
META_USE_OG_PROPERTIES = True
META_USE_TWITTER_PROPERTIES = True
# models.py
from meta.views import Meta
class Post(models.Model):
# ...
def as_meta(self, request):
return Meta(
title=self.title,
description=self.excerpt,
image=request.build_absolute_uri(self.cover_image.url),
url=request.build_absolute_uri(self.get_absolute_url()),
object_type='article',
)Common Django OG tag mistakes
- Relative image paths: og:image must be an absolute URL. Use
request.build_absolute_uri()in views. - HTML-encoding issues: special characters in titles or descriptions must be HTML-escaped. Django's auto-escaping handles this in templates, but verify with
{{ value|escape }}. - Missing fallbacks: always define default OG values in your base template for pages without specific overrides.
Preview your OG tags free at OGFixer.com → Paste your Django URL to see exactly how your link card renders on Twitter, LinkedIn, Discord, and Slack.