Skip to main content

SEO toolkit for Wagtail CMS - meta tags, Open Graph, Twitter Cards, and Schema.org structured data

Project description

wagtail-herald

PyPI version CI codecov License: BSD-3-Clause Published on Django Packages

Philosophy

SEO optimization shouldn't require deep technical knowledge. While Wagtail provides excellent content management, setting up proper meta tags, Open Graph, Twitter Cards, and Schema.org structured data requires significant manual work.

wagtail-herald provides a comprehensive SEO solution with just two template tags. Site-wide settings are managed through Wagtail's admin interface, while page-specific SEO can be configured per-page with sensible defaults.

The goal is to help content editors achieve best-practice SEO without touching code, while giving developers full control when needed.

Key Features

  • Simple Integration - Just 2 template tags: {% seo_head %} and {% seo_schema %}
  • Site-wide Settings - Configure Organization, favicons, social profiles from admin
  • Page-level SEO - Uses Wagtail's built-in SEO fields + OG image override
  • 13+ Schema Types - Article, Product, FAQ, Event, LocalBusiness, and more
  • Automatic BreadcrumbList - Generated from page hierarchy
  • Locale Support - Per-page language/region targeting with {% page_lang %} tag
  • Analytics Integration - GTM, GA4, Facebook Pixel, Microsoft Clarity from admin
  • robots.txt Management - Configure robots.txt from admin interface
  • Japanese UI - Full Japanese localization for admin interface

Comparison with Existing Libraries

Feature wagtail-seo wagtail-metadata wagtail-herald
Meta tags Yes Yes Yes
Open Graph Yes Yes Yes
Twitter Card Yes Yes Yes
Organization Schema Yes No Yes
Article Schema Yes No Yes
BreadcrumbList No No Auto-generated
FAQPage Schema No No Yes
Product Schema No No Yes
Event Schema No No Yes
LocalBusiness Schema No No Yes
13+ Schema types No No Yes
Locale (og:locale) No No Yes
GTM/Analytics No No Yes
robots.txt No No Yes
Template tags 3 includes 1 tag 2 tags
Japanese UI No No Yes

Installation

pip install wagtail-herald

Add to your INSTALLED_APPS:

# settings.py
INSTALLED_APPS = [
    # ...
    'wagtail.contrib.settings',  # Required
    'wagtail_herald',
    # ...
]

Quick Start

1. Add Template Tags

{% load wagtail_herald %}
<!DOCTYPE html>
<html>
<head>
    {% seo_head %}
</head>
<body>
    <!-- Your content -->

    {% seo_schema %}
</body>
</html>

That's it! The template tags handle everything:

  • {% seo_head %} - Meta tags, OG, Twitter Card, favicon, hreflang, analytics scripts
  • {% seo_schema %} - All JSON-LD structured data

2. Configure Site Settings

Go to Settings > SEO Settings in Wagtail admin to configure:

  • Organization name, logo, type
  • Social media profiles (Twitter, Facebook, etc.)
  • Default OG image
  • Favicon and Apple Touch Icon
  • Google/Bing site verification
  • Analytics (GTM, GA4, Facebook Pixel, Clarity)

3. Add SEO Mixin to Pages (Optional)

For page-level SEO control, add the mixin to your page models:

from wagtail.models import Page
from wagtail_herald.models import SEOPageMixin

class ArticlePage(SEOPageMixin, Page):
    # Your fields...

    content_panels = Page.content_panels + [
        # Your panels...
    ]

    promote_panels = Page.promote_panels + SEOPageMixin.seo_panels

This adds an "SEO" panel in the page editor with:

  • OG image override
  • Schema type selector (Article, Product, FAQ, etc.)
  • Locale selector (ja_JP, en_US, en_GB, etc.)
  • noindex/nofollow options
  • Canonical URL override

Note: For SEO title and meta description, use Wagtail's built-in seo_title and search_description fields in the Promote tab. The template tags automatically use these fields.

Supported Schema Types

Site-wide (Automatic)

  • WebSite - Site search box support
  • Organization - Company/organization info

Page-selectable

Type Use Case
WebPage General pages (default)
Article General articles
NewsArticle News content
BlogPosting Blog posts
Product Product pages
LocalBusiness Store/business info
Service Service descriptions
FAQPage FAQ pages
HowTo How-to guides
Event Events
Person Profile pages
Recipe Recipes
Course Online courses
JobPosting Job listings

Automatic

  • BreadcrumbList - Generated from page hierarchy

Output Example

{% seo_head %} Output

<!-- Basic Meta -->
<title>Page Title | Site Name</title>
<meta name="description" content="Page description...">
<meta name="robots" content="index, follow">

<!-- Canonical -->
<link rel="canonical" href="https://example.com/page/">

<!-- hreflang (multilingual) -->
<link rel="alternate" hreflang="ja" href="https://example.com/ja/page/">
<link rel="alternate" hreflang="en" href="https://example.com/en/page/">
<link rel="alternate" hreflang="x-default" href="https://example.com/ja/page/">

<!-- Favicon -->
<link rel="icon" type="image/svg+xml" href="/media/favicon.svg">
<link rel="icon" type="image/png" sizes="48x48" href="/media/favicon.png">
<link rel="apple-touch-icon" sizes="180x180" href="/media/apple-touch-icon.png">

<!-- Open Graph -->
<meta property="og:type" content="article">
<meta property="og:title" content="Page Title">
<meta property="og:description" content="Page description...">
<meta property="og:image" content="https://example.com/media/og-image.jpg">
<meta property="og:url" content="https://example.com/page/">
<meta property="og:site_name" content="Site Name">

<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@handle">
<meta name="twitter:title" content="Page Title">
<meta name="twitter:description" content="Page description...">
<meta name="twitter:image" content="https://example.com/media/og-image.jpg">

<!-- Verification -->
<meta name="google-site-verification" content="xxxxx">

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){...})(window,document,'script','dataLayer','GTM-XXXXXX');</script>

<!-- Google Analytics 4 -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-XXXXXXXXXX');</script>

<!-- Facebook Pixel -->
<script>!function(f,b,e,v,n,t,s){...}(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');fbq('init','XXXXXXXXXXXXXXX');fbq('track','PageView');</script>

<!-- Microsoft Clarity -->
<script type="text/javascript">(function(c,l,a,r,i,t,y){...})(window,document,"clarity","script","xxxxxxxxxx");</script>

{% seo_schema %} Output

<script type="application/ld+json">
[
  {
    "@context": "https://schema.org",
    "@type": "WebSite",
    "name": "Site Name",
    "url": "https://example.com/"
  },
  {
    "@context": "https://schema.org",
    "@type": "Organization",
    "name": "Company Name",
    "url": "https://example.com/",
    "logo": "https://example.com/media/logo.png",
    "sameAs": [
      "https://twitter.com/company",
      "https://www.facebook.com/company"
    ]
  },
  {
    "@context": "https://schema.org",
    "@type": "BreadcrumbList",
    "itemListElement": [
      {"@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/"},
      {"@type": "ListItem", "position": 2, "name": "Blog", "item": "https://example.com/blog/"},
      {"@type": "ListItem", "position": 3, "name": "Article Title"}
    ]
  },
  {
    "@context": "https://schema.org",
    "@type": "Article",
    "headline": "Article Title",
    "image": "https://example.com/media/article-image.jpg",
    "author": {"@type": "Person", "name": "Author Name"},
    "datePublished": "2025-01-15T10:00:00+09:00",
    "dateModified": "2025-01-16T15:30:00+09:00"
  }
]
</script>

Configuration

All settings are optional and configured through Wagtail admin:

Site Settings (Admin UI)

Setting Description
Organization name Company/site name for Schema
Organization type Corporation, LocalBusiness, etc.
Organization logo Logo image for Schema
Twitter handle @username (without @)
Facebook URL Facebook page URL
Default OG image Fallback image for social sharing (1200x630)
Favicon (SVG) SVG favicon for modern browsers (recommended)
Favicon (PNG) PNG fallback, minimum 48x48 (Google requirement)
Apple Touch Icon iOS home screen icon (180x180)
Google verification google-site-verification code
GTM Container ID Google Tag Manager (GTM-XXXXXX)
GA4 Measurement ID Google Analytics 4 (G-XXXXXXXXXX)
Facebook Pixel ID Meta Pixel for ads tracking
Clarity Project ID Microsoft Clarity for heatmaps
robots.txt content Custom robots.txt content

Django Settings (Optional)

# settings.py
WAGTAIL_HERALD = {
    # Default robots meta (can be overridden per-page)
    'DEFAULT_ROBOTS': 'index, follow',

    # OG image rendition filter (1200x630 is optimal for social sharing)
    'OG_IMAGE_FILTER': 'fill-1200x630',

    # Favicon rendition filter (48x48 minimum recommended by Google)
    'FAVICON_FILTER': 'fill-48x48',
}

Locale Support

wagtail-herald provides per-page language and region targeting for mixed-language content.

Use Case: Mixed Language Content

Write Japanese and English articles on the same site by selecting locale per page:

{% load wagtail_herald %}
<!DOCTYPE html>
<html lang="{% page_lang %}">
<head>
    {% seo_head %}
    <!-- Outputs: <meta property="og:locale" content="ja_JP"> -->
</head>
  • {% page_lang %} - Returns language code (e.g., ja, en)
  • {% page_locale %} - Returns full locale (e.g., ja_JP, en_US)
  • {% seo_head %} - Automatically includes og:locale meta tag

Available Locales

Locale Language
ja_JP 日本語 (日本)
en_US English (US)
en_GB English (UK)
zh_CN 中文 (简体)
zh_TW 中文 (繁體)
ko_KR 한국어
fr_FR Français (France)
de_DE Deutsch (Deutschland)
es_ES Español (España)
pt_BR Português (Brasil)

Set the default locale in Settings > SEO Settings, then override per-page using the SEOPageMixin.

robots.txt Management

Configure robots.txt from Wagtail admin without editing files.

Setup

Add the robots.txt view to your urls.py:

from wagtail_herald.views import robots_txt

urlpatterns = [
    path('robots.txt', robots_txt, name='robots_txt'),
    # ... other urls
]

Configuration

Go to Settings > SEO Settings and edit the robots.txt content:

User-agent: *
Allow: /
Disallow: /admin/
Disallow: /search/

Sitemap: https://example.com/sitemap.xml

If no custom content is set, a sensible default is used.

Requirements

Python Django Wagtail
3.10+ 4.2, 5.1, 5.2 6.4, 7.0, 7.2

Documentation

Project Links

Related Projects

Contributing

We welcome contributions! Please see our Contributing Guide for details.

License

BSD 3-Clause License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wagtail_herald-0.2.0.tar.gz (99.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wagtail_herald-0.2.0-py3-none-any.whl (96.2 kB view details)

Uploaded Python 3

File details

Details for the file wagtail_herald-0.2.0.tar.gz.

File metadata

  • Download URL: wagtail_herald-0.2.0.tar.gz
  • Upload date:
  • Size: 99.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wagtail_herald-0.2.0.tar.gz
Algorithm Hash digest
SHA256 b4b0f532eb21a2ccd91a078e3589b83e0404a2d44c38f3a8ca3c07d7fb5d8195
MD5 13ea0abc692efe23222da6ba5911e991
BLAKE2b-256 fc5f4c4a9eca344b9ca03c8b2bcef2a83a55b4a302ad704a74434c1e4ceeb3f9

See more details on using hashes here.

Provenance

The following attestation bundles were made for wagtail_herald-0.2.0.tar.gz:

Publisher: publish.yml on kkm-horikawa/wagtail-herald

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wagtail_herald-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: wagtail_herald-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 96.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wagtail_herald-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 04a551cc85665f0d219b4b3cafd7678bd31f11d4022affc6ee5b60cd8142bdc1
MD5 a6e0fb621a5d873522071ce824ea69d9
BLAKE2b-256 288225456bd4b19ecb2329b2623c9e0c2f261027e5ab32a01482ef42a1e61566

See more details on using hashes here.

Provenance

The following attestation bundles were made for wagtail_herald-0.2.0-py3-none-any.whl:

Publisher: publish.yml on kkm-horikawa/wagtail-herald

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page