# django-meta: a pluggable Django app for OpenGraph, Twitter and Schema.org tags

> django-meta is a Django app that attaches description, keywords, robots, author, Google Analytics, Open Graph, Twitter Card and Schema.org tags to your HTML responses through either template tags or a view and model method interface. It supports Django 4.2 to 6.0 on Python 3.9 to 3.14, it can be reconfigured for JSON and XML responses, and it carries a custom licence rather than a standard one.

**nephila/django-meta** — Pluggable app to allow Django developers to quickly add meta tags and OpenGraph, Twitter, and Google Plus properties to their HTML responses.

- Repository: https://github.com/nephila/django-meta
- Website: https://django-meta.readthedocs.io
- Stars: 549 · Forks: 67
- Language: Python
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/nephila-django-meta

## What django-meta puts into your HTML head

django-meta is a pluggable Django app that lets developers add meta tags and OpenGraph, Twitter and Schema.org properties to their HTML responses. The stated purpose is to improve how pages are displayed in search engine results and on social media platforms.

The supported tag set covers the usual ground. Description, Keywords, Robots and Author are the classic search engine tags. Google Analytics is included, which is the one entry that dates the project slightly, since most teams now reach for a template tag of their own or a third party script manager. Then there are Open Graph tags, Twitter Cards, and Schema.org properties.

The Schema.org support is described as basic, and that word carries weight. The project states plainly in a warning that as of version 2.0 django-meta no longer supports Google+ and that basic Schema.org support has been introduced. So the app was rewritten around the two protocols that still matter for sharing, and the vocabulary it emits is not the full Schema.org vocabulary.

There are two ways to use it. You can use the provided template tags, which is the direct route and needs no changes to your views. Or you can use the view-method and model-method interface, which is described as the basic concept of the package. The second route is the more interesting one, because it moves the metadata definition away from the template and into the objects and views that already know the truth about a page.

The project was started by Branko Vukelic and is currently maintained by Iacopo Spalletti, with the full contributor list in the AUTHORS file. The last push was on 2026-10-19, and the default branch is develop.

## The view and model method interface, and why it is the core idea

Most projects solve this problem by writing meta tags into each template, which is fine for a dozen pages and unmanageable for a few hundred. django-meta's answer is to let the metadata travel with the view or the model.

In practice that means a view can declare its title, description, image and card type, and a model can carry the same information as fields. Templates then render whatever the current view decided. The advantage is not only less duplication. When the same object is rendered in a list, a detail page and a share popup, the metadata can be derived once from the object rather than restated three times in three templates, and a change to the object's summary field updates all three.

The library is packaged in two top level directories, `meta/` and `meta_mixin/`. The `meta/` package holds the app itself and the meta classes that describe each tag family, and the presence of a separate `meta_mixin` package is what makes the model-method route work, since a mixin is how a model gains the interface without inheriting from a base model you do not control.

The documentation site is django-meta.readthedocs.io, and the project page in the repository points at the installation page there rather than duplicating the steps, which is a good sign about where the canonical instructions live. The project also keeps a HISTORY.rst changelog, a `changes/` directory and a `.tx/` translation setup, and it lists third party apps and extensions built on it in the documentation, so the ecosystem is visible from one place.

## Registering your own meta classes for JSON and XML responses

By default the app is designed to work with HTML responses, and the documentation is explicit about the alternative. It can also be configured to work with non-HTML responses such as JSON or XML, and the way to do that is to define your own meta classes and register them with the django-meta app.

That is a real architectural decision rather than a settings toggle. A JSON API response is a different document from an HTML page, and the metadata for it lives in the body rather than in a head. Supporting both means the same registry has to serve two output shapes, which is why the extension point is a class you define rather than a flag you set.

For an API-first project this is the part that determines whether django-meta is usable at all. If your site returns JSON for a mobile client and HTML for a crawler, you need both registrations, and the custom classes are how you keep the two in step.

The customisation story elsewhere in the project follows the same pattern of a small declarative surface. The pyproject.toml is worth reading for the tooling choices rather than the packaging, because it shows how the project is maintained. Formatting is black with a line length of 119 and a target version of py310, import sorting is isort with the black profile, and linting is ruff with a mccabe max-complexity of 10. Changelog entries go through towncrier, with the `changes/` directory as the fragment source and HISTORY.rst as the destination, titled by version and project date. Version bumps are handled by bumpversion, whose current_version is 2.5.2.dev1.

A max-complexity of 10 is the interesting number there. It is a deliberately low ceiling for a library, and it is a signal that the code prefers many small classes over large conditional branches, which is consistent with the registry design the rest of the package uses.

## Supported versions, and the gap between the release and the branch

The compatibility matrix is stated precisely, which is what you want from a dependency that ends up in the base template of every page.

Django 4.2 to 6.0 is supported, with the honest caveat that newer versions might work but are not tested yet. Python 3.9 to 3.14 is supported. That Python range reaching 3.14 tells you the project keeps up with new interpreter releases rather than pinning to a conservative floor, and the Django range covering three consecutive LTS-plus versions means an upgrade of your framework does not immediately strand you.

The version history is slower than the compatibility matrix suggests. The recent releases are 2.4.2 from 2024-02-05, 2.5.0 from 2025-04-18 and 2.5.1 from 2026-02-17, and the working version in the repository is 2.5.2.dev1. The gap between 2.5.1 and the current development version is about eight months, which is the normal shape for a library whose changes are small and infrequent.

That pace is a feature for a dependency like this. django-meta sits in the request path of every rendered page, and a library that changes its output format rarely is a library you can leave in place for years. The cost of that stability is that a new social platform protocol, when one appears, will not be supported until someone needs it.

The repository also carries the usual infrastructure for a package that ships to PyPI: a setup.py that delegates to setuptools, a setup.cfg, a MANIFEST.in, requirements-test.txt, tox.ini, a pre-commit config, a .pyup.yml for dependency updates, a .readthedocs.yml, and a requirements.txt that contains only the editable install of the package itself.

## Where django-meta is the wrong choice

The first limit is that it solves the wrong end of the problem if your site is already server rendered with a good metadata layer. django-meta is about emitting tags, not about deciding them. It does not generate descriptions from your content, it does not pick an image, and it does not tell you which card type a link should use. If the hard part of your work is choosing the right description for a page, this package does not touch that.

The second limit is the basic Schema.org support. If your visibility depends on structured data for rich results, a video object, a product offer or a recipe, a package that describes its own support as basic is not going to carry that.

The third is the Google Analytics entry. A tag generator that includes a tracking id in its supported list is telling you the feature set was assembled at a time when that was the normal way to do analytics, and it is one more thing to strip out of your head if you have moved on.

The fourth is the framework scope. It is a Django app, it is not framework agnostic, and it is not usable outside Django without a rewrite. There is no Flask, FastAPI or Pyramid equivalent in the package.

The fifth is the licensing position, which is a real factor for a dependency in every page. The platform could not classify the licence and points to the LICENSE file instead of a standard identifier, which usually means a custom or non-commercial-friendly term, and the project also publishes on PyPI. For a commercial product, that file has to be read and accepted by someone qualified before you install the package, not after.

Compare that with hand-rolling a small template tag in your own project. The difference in approach is that a custom tag in your codebase takes an afternoon and gives you total control over exactly what is emitted, with no version upgrades and no licence question, while django-meta gives you a maintained, tested implementation of the whole tag family plus the view and model interface, at the price of a dependency whose output you do not fully control.

## Conclusion

django-meta fits a Django project that publishes shareable pages and wants one place to define title, description, image and card type instead of repeating template markup per view, and it fits a team that already uses the view-method pattern. It does not fit a project still on Google+ assumptions, since version 2.0 dropped that support, and it does not fit a team that wants a permissively licensed dependency without reading the LICENSE file, because the terms are custom and the platform cannot classify them. Before you adopt it, read the installation page at django-meta.readthedocs.io, decide whether you want the template tag route or the view and model interface, and check that the meta classes you register for JSON or XML responses match the shape your API actually returns.

## FAQ

### What is django-meta and what does it add to Django pages?

django-meta is a pluggable Django app that adds meta tags and OpenGraph, Twitter and Schema.org properties to HTML responses. The supported set includes Description, Keywords, Robots, Author, Google Analytics, Open Graph tags, Twitter Cards and Schema.org properties.

### How do I use django-meta in a Django project?

There are two routes. You can use the provided template tags to emit the tags directly, or you can use the view-method and model-method interface, which is the basic concept of the package, so metadata is declared on the view or the model and rendered by the template. The installation instructions are on the documentation site at django-meta.readthedocs.io.

### Which Django and Python versions does django-meta support?

Django 4.2 to 6.0 is supported, with the note that newer versions might work but are not tested yet, and Python 3.9 to 3.14 is supported. The recent releases are 2.4.2 from 2024-02-05, 2.5.0 from 2025-04-18 and 2.5.1 from 2026-02-17.

### Can django-meta handle JSON and XML responses?

Yes. By default the app is designed to work with HTML responses, but it can be configured for non-HTML responses such as JSON or XML by defining your own meta classes and registering them with the django-meta app.

### What licence does django-meta use?

The licence is a custom one that the platform could not classify, so the terms are in the LICENSE file at the repository root rather than a standard identifier. The project publishes on PyPI, and the default branch is develop with the last push on 2026-10-19.

## Sources

- [Issues](https://github.com/nephila/django-meta/issues)
- [nephila/django-meta on GitHub](https://github.com/nephila/django-meta)
- [Project website](https://django-meta.readthedocs.io)
- [README](https://github.com/nephila/django-meta/blob/develop/README.md)
- [Releases](https://github.com/nephila/django-meta/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nephila-django-meta
