Guide: Path-based overrides (seopath)

The seopath contrib app lets editors override SEO metadata for any URL path through the Django Admin, with no code change required after initial setup. Use it for marketing pages, landing pages, and any URL whose SEO needs to change without a deployment.


When to use seopath

Use seopath when:

  • A page is rendered by a third-party view you cannot modify.
  • A non-technical editor needs to update a page title or description without a code deployment.
  • You want to add a custom robots directive, canonical redirect, or JSON-LD block to an arbitrary URL.
  • The same URL serves different SEO per site or per language.

For models you own, prefer SeoModelMixin or SeoModelFieldsMixin. seopath is a URL-keyed override, not a replacement for model-level metadata.


Installation

INSTALLED_APPS = [
    "seo_suite",
    "seo_suite.contrib.seopath",
]
python manage.py migrate

Adding an override in Admin

Navigate to SEO Suite — Path rules → SEO path rules in the Django Admin and click Add SEO path rule.

Field Purpose
Path The URL path, e.g. /about/ or /products/
Site ID Leave blank to apply to all sites
Language Leave blank to apply to all languages
Title Overrides the page title
Description Overrides the meta description
Keywords Overrides meta keywords
Robots Overrides the robots directive
Canonical Overrides the canonical URL
OG image Overrides the social sharing image
Extra JSON-LD Additional JSON-LD objects

The path must be an exact match including the trailing slash (if your site uses one consistently). Leave any metadata field blank to defer to lower-priority sources.


Specificity rules

When multiple rows match the current path, the most specific row wins:

  1. Matching site_id and language: score 3
  2. Matching site_id only: score 2
  3. Matching language only: score 1
  4. No site_id, no language (applies to all): score 0

The highest-scoring row is used; the other rows are ignored.


Example: A/B testing a landing page title

Create two rows for the same path and toggle between them by updating the title field directly in the Admin, no deployment needed:

Path Site ID Language Title
/landing/summer/ (blank) (blank) Summer Sale — Up to 50% Off

Change the title at any time; the next request picks up the new value.

If caching is enabled (SEO_SUITE["CACHE_TTL"] > 0), note that path-based rows are not automatically invalidated on save. You may need to clear the cache manually or set a short TTL.


Using seopath with model-backed pages

seopath runs at priority 30, which is below the object layer (priority 40). This means a SeoPath row for /articles/my-article/ is overridden by the Article model's own get_seo_metadata().

To make a SeoPath row win over the model, you have two options:

  1. Set the field on the SeoModelFieldsMixin columns instead (those also run at priority 40, and the column layer merges on top of the convention layer).
  2. Set the field in the view layer (priority 50) by using SeoViewMixin with a custom get_seo_metadata.

If you specifically need path-based overrides to trump model fields on your own models, the cleanest solution is usually to add SeoModelFieldsMixin columns and let editors fill them in directly on the model's Admin page.


Multi-site and multilingual setup

For a multi-site project, create separate SeoPath rows per site:

Path Site ID Language Title
/about/ 1 About Us
/about/ 2 About Our UK Team
/about/ 1 fr À propos de nous

The resolver picks the most specific match for the current site_id and language. The site ID is determined by django.contrib.sites (if installed), settings.SITE_ID, or a custom SEO_SUITE["SITE_ID_RESOLVER"] callable.