Skip to content

Configuration

GoatSEO has no global configuration object and never parses configuration per request. Defaults are ordinary Metadata instances, validated once when your settings module loads.

from goatseo import Metadata, Robots

SITE_DEFAULTS = Metadata(
    site_name="Example",
    title_template="{title} | Example",
    locale="en_US",
    language="en",
    theme_color="#0f172a",
    robots=Robots(max_snippet=-1, max_image_preview="large"),
)

Where defaults go

Framework Setting
Plain Python SEO(defaults=SITE_DEFAULTS) or seo.defaults(SITE_DEFAULTS)
Django GOATSEO_DEFAULTS = SITE_DEFAULTS in settings.py
FastAPI GoatSEO(defaults=SITE_DEFAULTS) dependency
Flask SEOExtension(app, defaults=SITE_DEFAULTS)

Layering more defaults

Use seo.defaults(metadata, precedence) to add the application, model or view layers:

from goatseo import Precedence

seo.defaults(Metadata(author="Blog team"), Precedence.APPLICATION)
seo.defaults(Metadata(description="All our articles."), Precedence.VIEW)

Calling defaults twice with the same precedence merges into that layer.

Title template

title_template must contain {title}. It is applied with a plain substitution, not str.format, so titles containing braces are safe:

Metadata(title="Sets {a, b}", title_template="{title} | Example").full_title
# 'Sets {a, b} | Example'

Robots

Robots fields are tri-state: True, False or None (not specified).

Field Directive
index, follow index / noindex, follow / nofollow
archive, snippet, image_index, translate noarchive, nosnippet, noimageindex, notranslate when False
max_snippet, max_video_preview max-snippet:N, max-video-preview:N (-1 means no limit)
max_image_preview max-image-preview: followed by none, standard or large
unavailable_after unavailable_after:<ISO 8601>

The Django middleware and the Flask robots_header=True option copy the same directives to the X-Robots-Tag response header.