Guide: Open Graph and social images

Every page that has a title, meta_description, and canonical_url already produces functional Open Graph and Twitter card tags automatically. The basics need no extra configuration.


What gets emitted automatically

When the resolver finalises metadata, it fills gaps in the og and twitter dicts from the resolved page-level fields:

Tag Automatic source
og:title title (unless og:title already set)
og:description meta_description (unless og:description already set)
og:url canonical_url (unless og:url already set)
og:image og_image (unless og:image already set)
twitter:title og:title
twitter:description og:description
twitter:image og:image
twitter:card "summary_large_image" if an image is present, else "summary"

The og:type default of "website" comes from SEO_SUITE["DEFAULTS"]["og"].


Adding a social sharing image

The simplest way is to map your image field:

class Article(SeoModelMixin, models.Model):
    cover = models.ImageField(upload_to="covers/", blank=True)

    SEO_FIELD_MAP = {"og_image": "cover"}

Or, if your field follows one of the conventional names (image, cover_image, photo, thumbnail, og_image), no mapping is needed at all.

Once og_image is set, both og:image and twitter:image are populated automatically, and twitter:card becomes "summary_large_image".


Setting og:type per model

The default og:type is "website". For articles and blog posts you typically want "article". Override it via the og dict:

class Article(SeoModelMixin, models.Model):
    ...

    def get_seo_metadata(self, context=None):
        from seo_suite.metadata import SeoMetadata
        base = super().get_seo_metadata(context)
        og_override = SeoMetadata.partial(og={"type": "article"})
        return SeoMetadata.merge(base, og_override)

Or, more concisely, at the view level:

class ArticleDetail(SeoViewMixin, DetailView):
    model = Article

    def get_seo_metadata(self, context=None):
        from seo_suite.metadata import SeoMetadata
        return SeoMetadata.partial(og={"type": "article"})

Custom og: and twitter: tags

Supply any Open Graph or Twitter tag as a key in the respective dict. Keys are the part after og: or twitter::

class ArticleDetail(SeoViewMixin, DetailView):
    model = Article

    def get_seo_metadata(self, context=None):
        from seo_suite.metadata import SeoMetadata
        return SeoMetadata.partial(
            og={
                "type": "article",
                "site_name": "My Blog",
                "locale": "en_US",
            },
            twitter={
                "site": "@myblog",
                "creator": "@author",
            },
        )

The og and twitter dicts are deep-merged across layers (see How resolution works): a higher-priority layer's keys win key-by-key; neither dict is replaced wholesale.


Site-wide og:site_name

The og:site_name tag is commonly set once for the whole site. Add it to the global defaults:

SEO_SUITE = {
    "DEFAULTS": {
        "title_suffix": " | My Blog",
        "robots": "index,follow",
        "og": {
            "type": "website",
            "site_name": "My Blog",
        },
    },
}

All pages inherit og:site_name from this default; any higher-priority layer can still override og:type per-page without affecting og:site_name.


Suppressing og or twitter tags on specific pages

Set a key to None or "" to suppress it from a specific page. Because og and twitter dicts are deep-merged, you can suppress one key without clearing the rest:

class InternalToolView(SeoViewMixin, TemplateView):
    def get_seo_metadata(self, context=None):
        from seo_suite.metadata import SeoMetadata
        return SeoMetadata.partial(og={"image": None})  # suppress og:image only

Rendered HTML output

For an article page with a cover image, the rendered output looks like:

<meta property="og:type" content="article">
<meta property="og:site_name" content="My Blog">
<meta property="og:title" content="How Django Routing Works">
<meta property="og:description" content="A deep dive into URL resolvers.">
<meta property="og:url" content="https://example.com/articles/how-django-routing-works/">
<meta property="og:image" content="https://example.com/media/covers/routing.jpg">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="How Django Routing Works">
<meta name="twitter:description" content="A deep dive into URL resolvers.">
<meta name="twitter:image" content="https://example.com/media/covers/routing.jpg">