Skip to content

Recipe: Blog Post

A blog post with BlogPosting schema, structured OGImage, breadcrumbs, author, and custom SchemaRegistry.

Configuration

from seoslug import SEOConfig, URLPolicy, SchemaRegistry

# Custom generator for BlogPosting
registry = SchemaRegistry()

def blog_posting_gen(entity, config, canonical, title, description, og_image):
    schema = {
        "@context": "https://schema.org",
        "@type": "BlogPosting",
        "headline": title,
        "url": canonical,
        "mainEntityOfPage": {"@id": canonical},
    }
    if description:
        schema["description"] = description
    if og_image:
        schema["image"] = og_image
    if entity.published_at:
        schema["datePublished"] = entity.published_at
    if entity.updated_at:
        schema["dateModified"] = entity.updated_at
    if entity.author_name:
        schema["author"] = {"@type": "Person", "name": entity.author_name}
    if config.publisher_name:
        publisher = {"@type": "Organization", "name": config.publisher_name}
        if config.publisher_logo:
            publisher["logo"] = config.publisher_logo
        schema["publisher"] = publisher
    return schema

registry.register("BlogPosting", blog_posting_gen)

config = SEOConfig(
    canonical_host="blog.example.com",
    public_base_url="https://blog.example.com",
    url_policy=URLPolicy(
        strip_tracking_params=True,
        lowercase_paths=True,
        trailing_slash="never",
    ),
    title_template="{title} - My Blog",
    site_name="My Blog",
    publisher_name="My Company",
    default_og_image="https://cdn.example.com/default.jpg",
    schema_type_map={"post": "BlogPosting"},
    schema_registry=registry,
)

Entity

from seoslug import SEOEntity, OGImage, Breadcrumb

entity = SEOEntity(
    entity_type="post",
    title="Hello World",
    excerpt="A brief introduction to the blog.",
    body_html="<p>Full article content here.</p>",
    status="published",
    featured_image=OGImage(
        url="https://cdn.example.com/hello.jpg",
        width=1200,
        height=630,
        alt="Hello World featured image",
    ),
    published_at="2025-01-15",
    updated_at="2025-02-01",
    author_name="Jane Doe",
    breadcrumbs=[
        Breadcrumb(name="Home", url="/"),
        Breadcrumb(name="Blog", url="/blog"),
    ],
)

Generate

from seoslug import build_seo_payload

payload = build_seo_payload(entity, "/blog/hello-world", config)

Result

{
    "title": "Hello World - My Blog",
    "description": "A brief introduction to the blog.",
    "canonical": "https://blog.example.com/blog/hello-world",
    "robots": "index,follow",
    "og": {
        "type": "article",
        "title": "Hello World - My Blog",
        "description": "A brief introduction to the blog.",
        "url": "https://blog.example.com/blog/hello-world",
        "image": "https://cdn.example.com/hello.jpg",
        "image:width": 1200,
        "image:height": 630,
        "image:alt": "Hello World featured image",
        "site_name": "My Blog",
    },
    "twitter": {
        "card": "summary_large_image",
        "title": "Hello World - My Blog",
        "description": "A brief introduction to the blog.",
        "image": "https://cdn.example.com/hello.jpg",
        "image:alt": "Hello World featured image",
    },
    "schema_jsonld": [
        {
            "@context": "https://schema.org",
            "@type": "BlogPosting",
            "headline": "Hello World - My Blog",
            "url": "https://blog.example.com/blog/hello-world",
            "mainEntityOfPage": {"@id": "https://blog.example.com/blog/hello-world"},
            "description": "A brief introduction to the blog.",
            "image": "https://cdn.example.com/hello.jpg",
            "datePublished": "2025-01-15",
            "dateModified": "2025-02-01",
            "author": {"@type": "Person", "name": "Jane Doe"},
            "publisher": {
                "@type": "Organization",
                "name": "My Company",
            },
        },
        {
            "@context": "https://schema.org",
            "@type": "BreadcrumbList",
            "itemListElement": [
                {"@type": "ListItem", "position": 1, "name": "Home", "item": "https://blog.example.com/"},
                {"@type": "ListItem", "position": 2, "name": "Blog", "item": "https://blog.example.com/blog"},
            ],
        },
    ],
}