Fallback Chains¶
Every field in the SEO payload resolves through a fallback chain. The first non-empty value wins.
This means you can set site-wide defaults in config, override per-entity in SEOEntity, and fine-tune per-page with SEOOverrides.
Understanding precedence¶
The general precedence order is:
SEOOverrides: per-call overrides (highest priority)SEOEntity: content entity fieldsSEOConfig: configuration defaults- Hardcoded defaults: library fallbacks (lowest priority)
Overrides always win. Entity data is next. Config defaults come last.
Title fallback chain¶
SEOOverrides.meta_titleSEOEntity.title"Untitled"(hardcoded)
After resolution, the title template is applied unless skip_title_template=True.
config = SEOConfig(title_template="{title} - My Site")
# title "My Post" becomes "My Post - My Site"
Description fallback chain¶
SEOOverrides.meta_descriptionSEOEntity.excerpt- Auto-generated snippet from
SEOEntity.body_html(max 160 chars) ""(empty string)
The body snippet is extracted via lxml (fallback to pure-Python regex). Scripts and styles are stripped. Whitespace is normalized. Result is truncated to 160 characters with an ellipsis.
entity = SEOEntity(
entity_type="post",
body_html="<p>A long article about something interesting.</p>",
)
# description becomes "A long article about something interesting."
Canonical fallback chain¶
SEOOverrides.canonical_url- Normalized route path (passed through full URL normalization pipeline)
Robots fallback chain¶
SEOOverrides.robots(string orRobotsobject)- Entity-derived default
The entity-derived default logic:
entity_type == "search"usesconfig.search_robots(default:"noindex,follow")entity.statusis"published"uses"index,follow"- Everything else uses
config.default_robots(default:"index,follow")
og:title fallback chain¶
SEOOverrides.og_title- Resolved title (after template)
og:description fallback chain¶
SEOOverrides.og_description- Resolved description
og:image fallback chain¶
SEOOverrides.og_image(string orOGImage)SEOEntity.featured_image(string orOGImage)SEOConfig.default_og_image(string orOGImage)
The resolved image cascades to twitter:image.
twitter:card fallback chain¶
SEOOverrides.twitter_card"summary_large_image"(hardcoded default)
twitter:title fallback chain¶
SEOOverrides.twitter_title- Resolved og:title
twitter:description fallback chain¶
SEOOverrides.twitter_description- Resolved og:description
twitter:image fallback chain¶
SEOOverrides.twitter_image(string orOGImage)- Resolved og:image
Summary table¶
| Field | Chain order |
|---|---|
| title | Override > Entity > "Untitled" + template |
| description | Override > Excerpt > Body snippet > "" |
| canonical | Override > Normalized route |
| robots | Override > Entity status default |
| og:title | Override > Resolved title |
| og:description | Override > Resolved description |
| og:image | Override > Entity image > Config default |
| twitter:card | Override > "summary_large_image" |
| twitter:title | Override > og:title |
| twitter:description | Override > og:description |
| twitter:image | Override > og:image |