Reference: Template tags

Load the library with {% load seo_suite %}.


{% seo_head %}

Renders the complete <head> metadata block in one call.

{% load seo_suite %}
<head>
  {% seo_head %}
</head>

Internally includes all of the granular partials:

  1. seo_suite/_title.html: <title>
  2. seo_suite/_meta.html: description, keywords, robots
  3. seo_suite/_canonical.html: canonical link
  4. seo_suite/_hreflang.html: hreflang alternates
  5. seo_suite/_opengraph.html: og:* meta tags
  6. seo_suite/_twitter.html: twitter:* meta tags
  7. seo_suite/_jsonld.html: JSON-LD script blocks
  8. seo_suite/_extra_head.html: fragments from renderers and signals

When the seo context variable is not set (no context processor, no mixin), {% seo_head %} resolves metadata lazily from the request. If there is no request in the context either, it renders nothing.


Granular tags

Use these when you want to place individual blocks in specific locations or build a custom <head> structure.

{% seo_title %}

{% seo_title %}

Renders <title>{{ seo.full_title }}</title>. Renders nothing if full_title is empty.

full_title is the concatenation of title and title_suffix. Example with title = "My Page" and title_suffix = " | My Site":

<title>My Page | My Site</title>

{% seo_meta %}

{% seo_meta %}

Renders the meta description, keywords, and robots tags when set:

<meta name="description" content="...">
<meta name="keywords" content="...">
<meta name="robots" content="index,follow">

{% seo_canonical %}

{% seo_canonical %}

Renders the canonical link when set:

<link rel="canonical" href="https://example.com/articles/my-article/">

{% seo_hreflang %}

{% seo_hreflang %}

Renders one <link rel="alternate" hreflang> for each entry in seo.hreflang:

<link rel="alternate" hreflang="en" href="https://example.com/en/articles/my-article/">
<link rel="alternate" hreflang="fr" href="https://example.com/fr/articles/my-article/">
<link rel="alternate" hreflang="x-default" href="https://example.com/en/articles/my-article/">

Renders nothing when seo.hreflang is an empty list.


{% seo_opengraph %}

{% seo_opengraph %}

Renders one <meta property="og:key" content="value"> for each entry in seo.og that has a non-empty value:

<meta property="og:type" content="article">
<meta property="og:title" content="My Page">
<meta property="og:description" content="...">
<meta property="og:url" content="https://example.com/articles/my-article/">
<meta property="og:image" content="https://example.com/media/cover.jpg">

{% seo_twitter %}

{% seo_twitter %}

Renders one <meta name="twitter:key" content="value"> for each entry in seo.twitter that has a non-empty value:

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="My Page">
<meta name="twitter:description" content="...">
<meta name="twitter:image" content="https://example.com/media/cover.jpg">

{% seo_jsonld %}

{% seo_jsonld %}

Renders one <script type="application/ld+json"> block for each item in seo.jsonld:

<script type="application/ld+json">{"@context":"https://schema.org","@type":"Article",...}</script>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList",...}</script>

Renders nothing when seo.jsonld is an empty list.


{% seo_extra_head %}

{% seo_extra_head %}

Renders any extra HTML fragments contributed by:

  • The extra_head field of SeoMetadata (set by providers/signals).
  • Registered renderers (renderer_registry).
  • Receivers of the seo_head_rendering signal.

Template context variable

All tags read from the seo variable in the template context. This is a FinalizedSeoMetadata instance set by:

  1. SeoViewMixin.get_context_data(), the primary path for views using the mixin.
  2. The seo_suite.context.seo context processor, a lazy fallback for all other views.

You can read it directly in any template:

{{ seo.title }}
{{ seo.full_title }}
{{ seo.h1 }}
{{ seo.meta_description }}
{{ seo.canonical_url }}
{{ seo.robots }}
{{ seo.og.site_name }}
{{ seo.twitter.card }}

See SeoMetadata attributes for the complete list.