Skip to main content

Python client for the OG Pilot Open Graph image generator with Django integration

Project description

OG Pilot Python

A Python client for generating OG Pilot Open Graph images via signed JWTs, with first-class Django integration.

Installation

pip install og-pilot

For Django integration:

pip install og-pilot[django]

Quick Start

Basic Usage

import og_pilot

# Configure globally (reads from OG_PILOT_API_KEY and OG_PILOT_DOMAIN env vars by default)
og_pilot.configure(
    api_key="your-api-key",
    domain="example.com"
)

# Generate an image URL
image_url = og_pilot.create_image(
    template="blog_post",
    title="How to Build Amazing OG Images",
    description="A complete guide to social media previews",
    author_name="Jane Smith",
)

print(image_url)
# https://ogpilot.com/api/v1/images?token=eyJ...

Using Environment Variables

The SDK automatically reads from environment variables:

export OG_PILOT_API_KEY="your-api-key"
export OG_PILOT_DOMAIN="example.com"
import og_pilot

# No configuration needed - uses env vars
url = og_pilot.create_image(title="My Page", template="default")

Cache Busting with iat

By default, OG Pilot caches images indefinitely. Use iat (issued at) to refresh the cache:

import time
from datetime import datetime

# Using Unix timestamp
url = og_pilot.create_image(
    title="My Post",
    template="blog",
    iat=int(time.time())  # Changes daily
)

# Using datetime
url = og_pilot.create_image(
    title="My Post",
    template="blog",
    iat=datetime.now()
)

Get JSON Metadata

data = og_pilot.create_image(
    title="Hello OG Pilot",
    template="page",
    json_response=True
)
print(data)  # {"url": "...", "width": 1200, "height": 630, ...}

Path Handling

The path parameter enhances OG Pilot analytics by tracking which OG images perform better across different pages on your site. By capturing the request path, you get granular insights into click-through rates and engagement for each OG image.

The client automatically injects a path parameter on every request:

Option Behavior
default=False Uses the current request path when available (via request context or env vars), then falls back to /
default=True Forces the path parameter to /, regardless of the current request (unless path is provided explicitly)
path="/..." Uses the provided path verbatim (normalized to start with /), overriding auto-resolution

Automatic Framework Detection

The SDK automatically detects the current request path from popular frameworks - no middleware setup required for most cases:

Flask - Works automatically, no setup needed:

from flask import Flask
import og_pilot

app = Flask(__name__)
og_pilot.configure(api_key="...", domain="example.com")

@app.route('/blog/<slug>')
def blog_post(slug):
    # Path is automatically captured from flask.request
    url = og_pilot.create_image(title="My Post", template="blog")
    return render_template('post.html', og_image=url)

Django with django-crequest - Install django-crequest for automatic detection:

pip install django-crequest
# settings.py
MIDDLEWARE = [
    # ...
    'crequest.middleware.CrequestMiddleware',
]

Then it works automatically in your views:

import og_pilot

def blog_post(request, slug):
    # Path is automatically captured
    url = og_pilot.create_image(title="My Post", template="blog")
    return render(request, 'post.html', {'og_image': url})

Manual Setup (Optional)

If automatic detection doesn't work for your setup, you can manually set the request context:

Django Middleware (without django-crequest):

from og_pilot import set_current_request, clear_current_request

class OgPilotMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        set_current_request({'url': request.get_full_path()})
        try:
            return self.get_response(request)
        finally:
            clear_current_request()

FastAPI:

from og_pilot import set_current_request, clear_current_request

@app.middleware("http")
async def og_pilot_middleware(request: Request, call_next):
    set_current_request({'url': str(request.url.path)})
    try:
        return await call_next(request)
    finally:
        clear_current_request()

Using with_request_context:

from og_pilot import with_request_context, create_image

url = with_request_context(
    {'url': '/blog/my-post'},
    lambda: create_image(title="My Blog Post", template="blog")
)

Manual Path Override

url = og_pilot.create_image(
    template="page",
    title="Hello OG Pilot",
    path="/pricing?plan=pro"
)

Default Path

url = og_pilot.create_image(
    template="blog_post",
    title="Default OG Image",
    default=True
)
# path is set to "/"

Custom Client Instance

For multiple configurations or dependency injection:

from og_pilot import create_client

client = create_client(
    api_key="your-api-key",
    domain="example.com",
    open_timeout=10,
    read_timeout=30,
)

url = client.create_image({"template": "default", "title": "Hello"})

Django Integration

1. Add to Installed Apps

# settings.py
INSTALLED_APPS = [
    # ...
    'og_pilot.django',
]

2. Configure Settings

# settings.py

# Option 1: Using settings dict
OG_PILOT = {
    'API_KEY': 'your-api-key',  # or use OG_PILOT_API_KEY env var
    'DOMAIN': 'example.com',     # or use OG_PILOT_DOMAIN env var
    # Optional:
    # 'BASE_URL': 'https://ogpilot.com',
    # 'OPEN_TIMEOUT': 5,
    # 'READ_TIMEOUT': 10,
}

# Option 2: Using environment variables (no settings needed)
# Just set OG_PILOT_API_KEY and OG_PILOT_DOMAIN

3. Verify Configuration

python manage.py og_pilot_check
python manage.py og_pilot_check --test  # Also sends a test request

4. Use in Templates

{% load og_pilot_tags %}

<!DOCTYPE html>
<html>
<head>
    <!-- Option 1: Generate URL and use manually -->
    {% og_pilot_image title=page.title template="blog_post" as og_image_url %}
    <meta property="og:image" content="{{ og_image_url }}" />
    <meta property="og:title" content="{{ page.title }}" />

    <!-- Option 2: Simple tag (outputs URL directly) -->
    <meta property="og:image" content="{% og_pilot_url title=page.title template='default' %}" />

    <!-- Option 3: Complete meta tags (requires template) -->
    {% og_pilot_meta_tags title=page.title description=page.description template="blog" %}
</head>
<body>
    ...
</body>
</html>

5. Use in Views

from django.shortcuts import render
import og_pilot

def blog_post(request, slug):
    post = get_object_or_404(Post, slug=slug)
    
    og_image_url = og_pilot.create_image(
        template="blog_post",
        title=post.title,
        description=post.excerpt,
        author_name=post.author.name,
        publish_date=post.published_at.strftime("%Y-%m-%d"),
    )
    
    return render(request, 'blog/post.html', {
        'post': post,
        'og_image_url': og_image_url,
    })

Custom Meta Tags Template

Create templates/og_pilot/meta_tags.html in your project to customize the output of {% og_pilot_meta_tags %}:

<!-- templates/og_pilot/meta_tags.html -->
<meta property="og:title" content="{{ title }}" />
<meta property="og:description" content="{{ description }}" />
<meta property="og:image" content="{{ image_url }}" />
<meta property="og:type" content="article" />
<meta property="og:site_name" content="{{ site_name }}" />

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="{{ title }}" />
<meta name="twitter:description" content="{{ description }}" />
<meta name="twitter:image" content="{{ image_url }}" />

Configuration Options

Option Environment Variable Default Description
api_key OG_PILOT_API_KEY None Your OG Pilot API key (required)
domain OG_PILOT_DOMAIN None Your registered domain (required)
base_url - https://ogpilot.com OG Pilot API URL
open_timeout - 5 Connection timeout (seconds)
read_timeout - 10 Read timeout (seconds)

Error Handling

from og_pilot import create_image
from og_pilot.exceptions import ConfigurationError, RequestError

try:
    url = create_image(title="My Post", template="blog")
except ConfigurationError as e:
    # Missing API key or domain
    print(f"Configuration error: {e}")
except RequestError as e:
    # API request failed
    print(f"Request error: {e}")
    if e.status_code:
        print(f"Status code: {e.status_code}")
except ValueError as e:
    # Missing required parameter (e.g., title)
    print(f"Validation error: {e}")

API Reference

Module-level Functions

  • og_pilot.configure(**kwargs) - Configure the global client
  • og_pilot.reset_config() - Reset to default configuration
  • og_pilot.get_config() - Get the current configuration
  • og_pilot.client() - Get a client using global config
  • og_pilot.create_client(**kwargs) - Create a new client with custom config
  • og_pilot.create_image(params, *, json=False, iat=None, headers=None, **kwargs) - Generate image URL

Client Class

from og_pilot import Client, Configuration

config = Configuration(api_key="...", domain="...")
client = Client(config)

# Generate URL
url = client.create_image(
    params={"template": "default", "title": "Hello"},
    json_response=False,  # Set True for JSON metadata
    iat=None,             # Optional cache busting timestamp
    headers={},           # Optional additional headers
)

Development

# Clone the repository
git clone https://github.com/sunergos-ro/og-pilot-python.git
cd og-pilot-python

# Create virtual environment
python -m venv .venv
source .venv/bin/activate

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run linter
ruff check .

# Run type checker
mypy og_pilot

Publishing to PyPI

This section explains how to publish the package to PyPI so users can install it with pip install og-pilot.

Prerequisites

  1. Create PyPI Account: Register at https://pypi.org/account/register/

  2. Create API Token: Go to https://pypi.org/manage/account/token/ and create a token with "Upload packages" scope.

  3. Install Build Tools:

    pip install build twine
    

Publishing Steps

1. Update Version

Edit pyproject.toml and og_pilot/__init__.py to update the version number:

# og_pilot/__init__.py
__version__ = "0.2.0"  # New version
# pyproject.toml
[project]
version = "0.2.0"

2. Build the Package

# Clean previous builds
rm -rf dist/ build/ *.egg-info

# Build source distribution and wheel
python -m build

This creates:

  • dist/og_pilot-0.1.0.tar.gz (source distribution)
  • dist/og_pilot-0.1.0-py3-none-any.whl (wheel)

3. Test on TestPyPI (Optional but Recommended)

# Upload to TestPyPI first
twine upload --repository testpypi dist/*

# Test installation from TestPyPI
pip install --index-url https://test.pypi.org/simple/ og-pilot

4. Upload to PyPI

# Upload to production PyPI
twine upload dist/*

You'll be prompted for credentials:

  • Username: __token__
  • Password: Your PyPI API token (starts with pypi-)

5. Configure Credentials (Optional)

To avoid entering credentials each time, create ~/.pypirc:

[distutils]
index-servers =
    pypi
    testpypi

[pypi]
username = __token__
password = pypi-YOUR-TOKEN-HERE

[testpypi]
username = __token__
password = pypi-YOUR-TESTPYPI-TOKEN-HERE

Then secure it:

chmod 600 ~/.pypirc

Automated Publishing with GitHub Actions

Create .github/workflows/publish.yml:

name: Publish to PyPI

on:
  release:
    types: [published]

jobs:
  publish:
    runs-on: ubuntu-latest
    environment: release
    permissions:
      id-token: write  # Required for trusted publishing
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      
      - name: Install build dependencies
        run: pip install build
      
      - name: Build package
        run: python -m build
      
      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        # Uses trusted publishing - configure at pypi.org

Setting Up Trusted Publishing

  1. Go to your PyPI project: https://pypi.org/manage/project/og-pilot/settings/publishing/
  2. Add a new publisher:
    • Owner: sunergos-ro
    • Repository: og-pilot-python
    • Workflow: publish.yml
    • Environment: release

Version Numbering

Follow Semantic Versioning:

  • MAJOR.MINOR.PATCH (e.g., 1.2.3)
  • MAJOR: Breaking changes
  • MINOR: New features (backward compatible)
  • PATCH: Bug fixes (backward compatible)

Release Checklist

  • Update version in pyproject.toml and og_pilot/__init__.py
  • Update CHANGELOG (if you have one)
  • Run tests: pytest
  • Run linter: ruff check .
  • Run type checker: mypy og_pilot
  • Build: python -m build
  • Test locally: pip install dist/*.whl
  • Upload to TestPyPI (optional)
  • Upload to PyPI
  • Create GitHub release with tag v0.1.0

License

MIT License - see LICENSE for details.

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

og_pilot-0.2.0.tar.gz (19.5 kB view details)

Uploaded Source

Built Distribution

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

og_pilot-0.2.0-py3-none-any.whl (19.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for og_pilot-0.2.0.tar.gz
Algorithm Hash digest
SHA256 6090ff5446bb64c7096887c206af6bfd6832732a8335b8df646d105c0d281c9d
MD5 c109e3a12f901a3268b2c1b5994f043b
BLAKE2b-256 5dfe97beb97685130fcaf270d8d827fe9948697f73c412aaeb8e221f0000901e

See more details on using hashes here.

Provenance

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

Publisher: publish.yml on sunergos-ro/og-pilot-python

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

File details

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

File metadata

  • Download URL: og_pilot-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 19.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for og_pilot-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b1a7a477d1a85c458673767781a2645acde29f288958c6867f72f580719975d6
MD5 117e11541b04257097c2d9c09aa443d7
BLAKE2b-256 5e71a5be5c4090fd392b7db744f670069b2d5aaf3f9ba7a8b596c72b178340bc

See more details on using hashes here.

Provenance

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

Publisher: publish.yml on sunergos-ro/og-pilot-python

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