Skip to main content

Protocol-based SEO auditing framework for Django models with automatic rule discovery

Project description

Django SEO Audit

A production-ready Django package for comprehensive SEO auditing of models using Python protocols and automatic rule discovery.

Features

  • Protocol-Based Architecture: Uses Python 3.12+ protocols for clean, loosely-coupled design
  • Automatic Rule Discovery: Rules auto-register when defined - no manual registration needed
  • Auto-Discovery Management Command: Automatically finds and audits any model using SEOAuditableMixin
  • Comprehensive Rule Set: 18 built-in rules across 4 categories:
    • Core SEO: Title length, meta descriptions, keywords, H1 tags
    • Social Media: OpenGraph and Twitter Card optimization
    • Content Quality: Content depth, introduction, resources
    • Technical SEO: Canonical URLs, robots directives, structured data
  • Django Model Mixin: Drop-in mixin with intelligent fallbacks for common field names
  • Extensible: Easy to add custom rules for your specific SEO requirements
  • Beautiful CLI Output: Color-coded results with emoji indicators and actionable suggestions

Installation

From PyPI (when published)

pip install django-seo-audit

From Source (Development)

# In your workspace directory
git clone https://github.com/directory-platform/django-seo-audit.git
cd django-seo-audit
pip install -e .

UV Workspace (Recommended for development)

Add to your workspace pyproject.toml:

[tool.uv.workspace]
members = [
    "your-project",
    "django-seo-audit",
]

Then run:

uv sync

Quick Start

1. Add to Django Settings

# settings.py
INSTALLED_APPS = [
    # ...
    "django_seo_audit",
]

2. Add Mixin to Your Models

# models.py
from django.db import models
from django_seo_audit import SEOAuditableMixin

class Article(SEOAuditableMixin, models.Model):
    name = models.CharField(max_length=200)
    seo_title = models.CharField(max_length=60, blank=True)
    meta_description = models.TextField(max_length=160, blank=True)
    focus_keyphrase = models.CharField(max_length=100, blank=True)

    # ... other fields

The mixin provides intelligent fallbacks:

  • get_seo_title()seo_title or name
  • get_meta_description()meta_description or short_description
  • get_h1_tag()h1_tag or seo_title or name

3. Run SEO Audit

# List all auditable models
python manage.py seo_audit --list-models

# Audit a specific object
python manage.py seo_audit --model blog.Article --slug my-article

# Audit with verbose output and specific categories
python manage.py seo_audit --model blog.Article --slug my-article --verbose --category core_seo

4. Programmatic Usage

from django_seo_audit import SEOAuditor

# Audit any object
article = Article.objects.get(slug="my-article")
auditor = SEOAuditor()
result = auditor.audit_object(article)

# Check results
print(f"SEO Score: {result.overall_score}/10")
print(f"Grade: {result.get_health_grade()}")
print(f"Passing: {result.is_passing()}")

# Get issues by severity
critical_issues = result.get_critical_issues()
warnings = result.get_warnings()
successes = result.get_successes()

Protocols

Django SEO Audit uses Python protocols to define contracts for auditable objects. Your models don't need to inherit from anything - just implement the methods you need.

BasicSEOAuditable

Core SEO methods every model should implement:

from django_seo_audit import BasicSEOAuditable

def get_seo_title(self) -> str: ...
def get_meta_description(self) -> str: ...
def get_canonical_url(self) -> str: ...
def get_focus_keyphrase(self) -> str: ...
def get_secondary_keywords(self) -> str: ...
def get_h1_tag(self) -> str: ...

SocialMediaAuditable

For social sharing optimization:

from django_seo_audit import SocialMediaAuditable

def get_og_title(self) -> str: ...
def get_og_description(self) -> str: ...
def get_og_image_url(self) -> str | None: ...
def get_twitter_title(self) -> str: ...
def get_twitter_description(self) -> str: ...
def get_twitter_image_url(self) -> str | None: ...

ContentAuditable

For content quality assessment:

from django_seo_audit import ContentAuditable

def has_detailed_content(self) -> bool: ...
def get_content_word_count(self) -> int: ...
def get_content_sections_count(self) -> int: ...
def has_introduction_content(self) -> bool: ...
def get_resource_count(self) -> int: ...

TechnicalSEOAuditable

For technical SEO features:

from django_seo_audit import TechnicalSEOAuditable

def get_robots_directive(self) -> str: ...
def get_schema_type(self) -> str: ...
def get_schema_data(self) -> dict | None: ...
def get_breadcrumb_title(self) -> str: ...
def has_custom_canonical_url(self) -> bool: ...

Creating Custom Rules

Creating custom SEO rules is straightforward:

# rules/custom_rules.py
from django_seo_audit import SEORule, SEOResult, SEOStatus
from django_seo_audit.protocols import BasicSEOAuditable

class CustomKeywordDensityRule(SEORule):
    """Check keyword density in content."""

    name = "Keyword Density"
    description = "Ensures focus keyword appears with optimal density"
    category = "custom"
    weight = 3  # 1-5 importance scale

    def check(self, obj: BasicSEOAuditable) -> SEOResult:
        keyword = obj.get_focus_keyphrase()
        # Your logic here

        return SEOResult(
            status=SEOStatus.GOOD,
            message="Keyword density optimal",
            score=10,
        )

Rules are automatically discovered and registered when imported!

Management Command Reference

List Auditable Models

python manage.py seo_audit --list-models

Shows all models using SEOAuditableMixin with object counts.

Audit by Slug

python manage.py seo_audit --model app_label.ModelName --slug object-slug

Audit by Primary Key

python manage.py seo_audit --model app_label.ModelName --pk 42

Filter by Category

python manage.py seo_audit --model blog.Article --slug test \
    --category core_seo \
    --category social_media

Available categories: core_seo, social_media, content, technical_seo

Verbose Output

python manage.py seo_audit --model blog.Article --slug test --verbose

Shows detailed explanations and actionable suggestions for improvements.

Built-in Rules

Core SEO (5 rules)

  • SEO Title Length: Optimal 50-60 characters
  • Meta Description Length: Optimal 150-160 characters
  • Focus Keyphrase: Presence in title and description
  • H1 Tag Optimization: Proper H1 configuration
  • Secondary Keywords: 3-7 keyword variety

Social Media (5 rules)

  • OpenGraph Image: 1200x630px image configuration
  • OpenGraph Title: Up to 95 characters
  • OpenGraph Description: Up to 200 characters
  • Twitter Card Image: Twitter-optimized imagery
  • Twitter Card Title: Up to 70 characters

Content (4 rules)

  • Detailed Content: Comprehensive content sections
  • Introduction Content: Engaging introduction
  • Supporting Resources: Videos, articles, tools
  • Content Depth: 500+ words across sections

Technical SEO (4 rules)

  • Canonical URL: Duplicate content prevention
  • Robots Directive: Proper indexing configuration
  • Structured Data: Schema.org markup
  • Breadcrumb Optimization: Navigation clarity

Architecture

  • Protocol-Based: Uses Python 3.12+ Protocol for structural subtyping
  • Auto-Registration: Rules register via __init_subclass__ metaclass magic
  • Immutable Results: SEOResult uses frozen dataclass for thread-safety
  • Graceful Degradation: Failed rules don't break the entire audit
  • Zero Config: Works out of the box with sensible defaults

Requirements

  • Python 3.12+
  • Django 4.2+

Development

Setup

# Clone repository
git clone https://github.com/heysamtexas/django-seo-audit.git
cd django-seo-audit

# Install with dev dependencies
pip install -e ".[dev]"
# or with uv
uv sync --extra dev

Running Tests

The package includes a comprehensive test suite with 207 tests:

# Run all tests
make test
# or
PYTHONPATH=. uv run python tests/manage.py test

# Run with verbose output
make test-verbose

# Run specific test module
PYTHONPATH=. uv run python tests/manage.py test tests.test_rules

Code Quality

# Run linting
make lint
# or
ruff check src/ tests/

# Auto-format code
make format
# or
ruff format src/ tests/

# Type checking
make typecheck
# or
mypy src/

# Run all checks
make check

Example Models

See tests/example_app/models.py for living documentation:

  • BlogPost: Full SEO implementation
  • Product: Minimal implementation with fallbacks
  • Page: Custom protocol without mixin

Releases and Publishing

This package uses GitHub Actions to automatically publish to PyPI when a new release is created.

Creating a Release

  1. Update version in pyproject.toml:

    [project]
    version = "0.1.1"  # Bump version
    
  2. Commit version bump:

    git add pyproject.toml
    git commit -m "Bump version to 0.1.1"
    git push origin master
    
  3. Create GitHub release:

    # Using GitHub CLI
    gh release create v0.1.1 --title "Release v0.1.1" --notes "Release notes here"
    
    # Or use GitHub web interface
    # Navigate to: https://github.com/heysamtexas/django-seo-audit/releases/new
    
  4. GitHub Actions will automatically:

    • Verify version matches tag
    • Run tests
    • Build package
    • Publish to PyPI

PyPI Trusted Publisher Setup (First Release Only)

Before creating your first release, configure PyPI Trusted Publisher:

  1. Go to PyPI: https://pypi.org/manage/account/publishing/

  2. Add a new pending publisher:

    • PyPI Project Name: django-seo-audit
    • Owner: heysamtexas
    • Repository name: django-seo-audit
    • Workflow name: publish.yml
    • Environment name: (leave blank)
  3. Create first release - PyPI will create the project automatically

No API tokens needed! Trusted Publishers are more secure and maintenance-free.

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-rule)
  3. Commit your changes (git commit -m 'Add amazing SEO rule')
  4. Push to the branch (git push origin feature/amazing-rule)
  5. Open a Pull Request

License

MIT License - see LICENSE file for details.

Credits

Built by the Directory Platform team as part of the directory ecosystem.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_seo_audit-0.2.0.tar.gz (51.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_seo_audit-0.2.0-py3-none-any.whl (27.1 kB view details)

Uploaded Python 3

File details

Details for the file django_seo_audit-0.2.0.tar.gz.

File metadata

  • Download URL: django_seo_audit-0.2.0.tar.gz
  • Upload date:
  • Size: 51.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for django_seo_audit-0.2.0.tar.gz
Algorithm Hash digest
SHA256 79f7bd377b7d7775eab51069e07cc9c72def8cb361e10465604d75d5d9ce3655
MD5 298cae7bbcc179966dd8a6663ea6619b
BLAKE2b-256 2963a9cb396fd5e2ecdc6f84a2bbeb36cbb04d327d2ab9e8d05bd7316d79fe31

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_seo_audit-0.2.0.tar.gz:

Publisher: publish.yml on heysamtexas/django-seo-audit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file django_seo_audit-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_seo_audit-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5d74fe1670ac678c2638cc4cc1cf31499d3d20962509bd6179ca56e8a5541b6e
MD5 dbf89fe51e213f7bd10f28b0e39aeacd
BLAKE2b-256 fea94710c183413bee225ffeba77aa5014b0fd57f5b92c6e49d20d96cb8a2855

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_seo_audit-0.2.0-py3-none-any.whl:

Publisher: publish.yml on heysamtexas/django-seo-audit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page