26 KiB
WordPress Integration & Publishing Flow - Complete Technical Documentation
Last Updated: January 10, 2026
Version: 1.7.0
Status: Production Active
Table of Contents
- System Overview
- Integration Setup Flow
- Manual Publishing Flow
- Automation Publishing Flow
- Webhook Sync Flow (WordPress → IGNY8)
- Metadata Sync Flow
- Data Models & Storage
- Plugin Distribution System
- Current Implementation
- Flow Diagrams
1. System Overview
Architecture Summary
IGNY8 integrates with WordPress sites through a custom WordPress plugin (igny8-wp-bridge) that:
- Receives content from IGNY8 via a custom REST endpoint (
/wp-json/igny8/v1/publish) - Sends status updates back to IGNY8 via webhooks
- Authenticates using API keys stored in both systems
- Auto-updates via IGNY8 plugin distribution system (v1.7.0+)
- Supports advanced template rendering with image layouts
Communication Pattern
IGNY8 App ←→ WordPress Site
│ │
│ HTTP POST │
├─────────────→│ Publish content via /wp-json/igny8/v1/publish
│ │
│ HTTP POST │
│←─────────────┤ Webhook status updates via /api/v1/integration/webhooks/wordpress/status/
│ │
│ HTTP GET │
├─────────────→│ Check plugin updates via /wp-json/igny8/v1/check-update
│ │
Key Components
| Component | Location | Purpose |
|---|---|---|
| SiteIntegration Model | business/integration/models.py |
Stores WordPress credentials & config |
| SyncEvent Model | business/integration/models.py |
Logs all sync operations |
| Plugin Models | plugins/models.py |
Plugin versioning and distribution |
| Celery Task | tasks/wordpress_publishing.py |
Background publishing worker |
| Webhook Handler | modules/integration/webhooks.py |
Receives WordPress status updates |
| Frontend Form | components/sites/WordPressIntegrationForm.tsx |
User setup UI |
Recent Updates (v1.7.0)
Plugin Distribution System:
- ✅ Automated plugin distribution and updates
- ✅ WordPress plugin v1.3.3 with template improvements
- ✅ Image layout fixes (square/landscape positioning)
- ✅ Auto-update mechanism via WordPress hooks
- ✅ Health check and monitoring endpoints
2. Integration Setup Flow
2.1 Pre-requisites (WordPress Side)
- WordPress 5.6+ with REST API enabled
- Pretty permalinks enabled (Settings → Permalinks)
- IGNY8 WordPress Bridge plugin v1.3.0+ installed and activated
- No security plugins blocking REST API
2.2 Plugin Installation (Updated v1.7.0)
Option 1: Manual Download & Install
- User downloads latest plugin from IGNY8 app
- Frontend: Site Settings → WordPress Integration → Download Plugin
- Download endpoint:
https://api.igny8.com/api/plugins/igny8-wp-bridge/download/ - Installs in WordPress: Plugins → Add New → Upload ZIP
Option 2: Direct URL Install
- WordPress admin → Plugins → Add New → Upload Plugin
- Paste ZIP URL with signed download token
- Plugin installs and auto-registers with IGNY8
Plugin Auto-Update:
- WordPress checks for updates every 12 hours
- Plugin hooks into
pre_set_site_transient_update_plugins - Compares current version with latest from IGNY8 API
- Notifies admin if update available
- Can be updated via WordPress admin (one-click)
2.3 Setup Steps (User Flow)
Step 1: User navigates to Site Settings
- Frontend:
/sites/{id}/settings→ WordPress Integration section - Component:
WordPressIntegrationForm.tsx
Step 2: User clicks "Generate API Key"
- Frontend calls:
POST /v1/integration/integrations/generate-api-key/ - Body:
{ "site_id": 123 } - Backend creates/updates
SiteIntegrationrecord with new API key
Step 3: User configures WordPress plugin
- Configures plugin with:
- IGNY8 API URL:
https://api.igny8.com - Site API Key: (copied from IGNY8)
- Site ID: (shown in IGNY8)
- IGNY8 API URL:
Step 4: Test Connection
- User clicks "Test Connection" in either app
- IGNY8 calls:
GET {wordpress_url}/wp-json/wp/v2/users/me - Uses API key in
X-IGNY8-API-KEYheader - Success: Connection verified,
is_activeset to true, plugin registers installation - Failure: Error message displayed
2.4 Data Created During Setup
SiteIntegration Record:
{
"id": 1,
"site_id": 123,
"account_id": 456,
"platform": "wordpress",
"platform_type": "cms",
"config_json": {
"site_url": "https://example.com"
},
"credentials_json": {
"api_key": "igny8_xxxxxxxxxxxxxxxxxxxx"
},
"is_active": true,
"sync_enabled": true,
"sync_status": "pending"
}
3. Manual Publishing Flow
3.1 Trigger Points
- Content Review Page - "Publish to WordPress" button
- Content Approved Page - Publish action in context menu
- Bulk Actions - Select multiple, publish all
3.2 Detailed Flow
Step 1: User clicks "Publish to WordPress"
- Frontend:
ContentViewSet.publishaction called - Endpoint:
POST /api/v1/writer/content/{id}/publish/ - Optional body:
{ "site_integration_id": 123 }
Step 2: Backend validates content
- Checks content exists and belongs to user's site
- Checks content not already published (
external_idmust be null) - Finds active WordPress integration for the site
- Error if no integration found
Step 3: Optimistic status update
- Content status changed to
publishedimmediately - User sees success message
- Actual WordPress publishing happens async
Step 4: Celery task queued
- Task:
publish_content_to_wordpress.delay(content_id, site_integration_id) - Task name:
igny8_core.tasks.wordpress_publishing
Step 5: Celery task execution (Background)
The task performs these steps:
- Load data - Get Content and SiteIntegration from database
- Check if already published - Skip if
external_idexists - Generate excerpt - Strip HTML, take first 150 chars
- Load taxonomy terms - Categories from
taxonomy_termsM2M field, fallback to cluster name - Load tags - From
taxonomy_terms+ primary/secondary keywords - Load images - Featured image and gallery images, convert paths to URLs
- Build payload:
{ "content_id": 123, "title": "Post Title", "content_html": "<p>Full HTML content...</p>", "excerpt": "Short excerpt...", "status": "publish", "seo_title": "SEO Title", "seo_description": "Meta description", "primary_keyword": "main keyword", "secondary_keywords": ["kw1", "kw2"], "featured_image_url": "https://app.igny8.com/images/...", "gallery_images": [{ "url": "...", "alt": "", "caption": "" }], "categories": ["Category Name"], "tags": ["tag1", "tag2"] } - Send to WordPress:
- URL:
{site_url}/wp-json/igny8/v1/publish - Headers:
X-IGNY8-API-Key: {api_key} - Method: POST
- Timeout: 30 seconds
- URL:
Step 6: Process WordPress response
| HTTP Code | Meaning | Action |
|---|---|---|
| 201 | Created | Update content with external_id, external_url, log success |
| 409 | Already exists | Update content with existing WordPress post data |
| 4xx/5xx | Error | Log failure, retry up to 3 times with exponential backoff |
Step 7: Update IGNY8 content record
content.external_id = str(wp_post_id)
content.external_url = wp_post_url
content.status = 'published'
content.metadata['wordpress_status'] = 'publish'
content.save()
Step 8: Create SyncEvent record
SyncEvent.objects.create(
integration=site_integration,
site=content.site,
account=content.account,
event_type='publish',
action='content_publish',
description=f"Published content '{title}' to WordPress",
success=True,
content_id=content.id,
external_id=external_id,
details={...}
)
3.3 Error Handling
- Timeout: Retry after 60 seconds (first attempt), then exponentially
- Connection Error: Same retry logic
- Max Retries: 3 attempts total
- Final Failure: SyncEvent created with
success=False, error logged
4. Automation Publishing Flow
4.1 Automation Stage 7: Review → Published
Automation Stage 7 handles auto-approval and publishing:
Current Implementation:
- Content in
reviewstatus is changed topublishedstatus - Status change only - NO automatic WordPress push currently implemented
- Lock released, automation run marked complete
What DOES NOT happen automatically:
- No
publish_content_to_wordpresstask is triggered - Content sits in
publishedstatus waiting for manual publish or scheduled task
4.2 Scheduled Publishing Task (NOT CURRENTLY SCHEDULED)
There exists a task process_pending_wordpress_publications() that:
- Finds content with
status='published'andexternal_id=NULL - Queues each item to
publish_content_to_wordpresstask - Processes max 50 items per run
CURRENT STATUS: This task is NOT in Celery Beat schedule!
Looking at celery.py, the beat schedule includes:
check-scheduled-automations(hourly)replenish-monthly-credits(monthly)- Various maintenance tasks
Missing:
process_pending_wordpress_publicationsis NOT scheduled
4.3 To Enable Auto-Publishing After Automation
Two options:
Option A: Add to Celery Beat Schedule
'process-pending-wordpress-publications': {
'task': 'igny8_core.tasks.wordpress_publishing.process_pending_wordpress_publications',
'schedule': crontab(minute='*/5'), # Every 5 minutes
},
Option B: Call directly from Stage 7
Modify run_stage_7() to queue publish tasks for each approved content item.
5. Webhook Sync Flow (WordPress → IGNY8)
5.1 Purpose
Keeps IGNY8 in sync when content is modified directly in WordPress:
- Post status changed (published → draft, etc.)
- Post deleted/trashed
- Post metadata updated
5.2 Webhook Endpoints
| Endpoint | Purpose |
|---|---|
POST /api/v1/integration/webhooks/wordpress/status/ |
Status changes |
POST /api/v1/integration/webhooks/wordpress/metadata/ |
Metadata updates |
5.3 Status Webhook Flow
Step 1: WordPress plugin detects status change
- Hooks into
transition_post_statusaction - Collects: post_id, content_id, new_status, post_url
Step 2: Plugin sends webhook to IGNY8
POST https://app.igny8.com/api/v1/integration/webhooks/wordpress/status/
Headers:
X-IGNY8-API-KEY: {api_key}
Body:
{
"post_id": 123,
"content_id": 456,
"post_status": "publish",
"post_url": "https://example.com/my-post/",
"post_title": "My Post Title",
"site_url": "https://example.com"
}
Step 3: IGNY8 validates and processes
- Extract API key from header
- Find Content by
content_id - Find SiteIntegration by site_url + platform
- Verify API key matches stored key
- Map WordPress status to IGNY8 status:
WordPress IGNY8 publish published draft draft pending review private published trash draft future review - Update Content record:
content.external_id = str(post_id) content.external_url = post_url content.status = mapped_status content.metadata['wordpress_status'] = post_status content.metadata['last_wp_sync'] = now content.save() - Create SyncEvent log
5.4 Metadata Webhook Flow
Similar to status webhook but updates content.metadata['wp_metadata'] with:
- Categories
- Tags
- Author info
- Modified date
6. Metadata Sync Flow
6.1 Manual Sync (User-Initiated)
Trigger: User clicks "Sync Now" in Site Settings
Endpoint: POST /api/v1/integration/integrations/{id}/sync/
What it does:
- Calls
SyncMetadataService.sync_wordpress_structure() - Fetches from WordPress:
- Post types and counts
- Categories list
- Tags list
- Site metadata
- Updates integration's
last_sync_at - Does NOT push/pull content
6.2 Structure Update
Endpoint: POST /api/v1/integration/integrations/{id}/update_structure/
Refreshes understanding of WordPress site:
- Available post types
- Taxonomy structures
- Capabilities
7. Data Models & Storage
7.1 SiteIntegration
| Field | Type | Purpose |
|---|---|---|
| id | AutoField | Primary key |
| account | FK(Account) | Owner account |
| site | FK(Site) | IGNY8 site |
| platform | CharField | 'wordpress' |
| platform_type | CharField | 'cms' |
| config_json | JSONField | { "site_url": "https://..." } |
| credentials_json | JSONField | { "api_key": "igny8_xxx" } |
| is_active | Boolean | Connection enabled |
| sync_enabled | Boolean | Two-way sync enabled |
| last_sync_at | DateTime | Last successful sync |
| sync_status | CharField | pending/success/failed/syncing |
| sync_error | TextField | Last error message |
7.2 SyncEvent
| Field | Type | Purpose |
|---|---|---|
| id | AutoField | Primary key |
| integration | FK(SiteIntegration) | Parent integration |
| site | FK(Site) | Related site |
| account | FK(Account) | Owner account |
| event_type | CharField | publish/sync/error/webhook/metadata_sync |
| action | CharField | content_publish/status_update/etc |
| description | TextField | Human-readable event description |
| success | Boolean | Event outcome |
| content_id | Integer | IGNY8 content ID |
| external_id | CharField | WordPress post ID |
| error_message | TextField | Error details if failed |
| details | JSONField | Additional event data |
| duration_ms | Integer | Operation duration |
| created_at | DateTime | Event timestamp |
7.3 Content Fields (Publishing Related)
| Field | Purpose |
|---|---|
| external_id | WordPress post ID (string) |
| external_url | WordPress post URL |
| status | IGNY8 status (draft/review/published) |
| metadata['wordpress_status'] | WordPress status (publish/draft/etc) |
| metadata['last_wp_sync'] | Last webhook sync timestamp |
8. Current Implementation Gaps
8.1 Missing: Scheduled Auto-Publishing
Problem: Content approved by Automation Stage 7 is not automatically pushed to WordPress.
Current State:
process_pending_wordpress_publications()task exists- Task is NOT in Celery Beat schedule
- Content remains in
publishedstatus withexternal_id=NULL
Impact: Users must manually publish each content item even after automation completes.
8.2 Missing: Pull Sync (WordPress → IGNY8 Content)
Problem: No way to import existing WordPress posts into IGNY8.
Current State:
- Webhooks only handle status updates for content that originated from IGNY8
- No "Import from WordPress" feature
- No scheduled pull sync
8.3 Missing: Content Update Sync
Problem: Editing content in IGNY8 after publishing doesn't update WordPress.
Current State:
- Only initial publish is supported
- No "republish" or "update" functionality
external_idcheck prevents re-publishing
8.4 Missing: Image Upload to WordPress
Problem: Featured images are passed as URLs, not uploaded to WordPress media library.
Current State:
- Image URL is sent in payload
- WordPress plugin must download and create attachment
- If plugin doesn't handle this, no featured image
8. Plugin Distribution System
8.1 Architecture (v1.7.0)
Plugin Distribution Components:
Pluginmodel - Multi-platform plugin registryPluginVersionmodel - Version tracking with files and checksumsPluginInstallationmodel - Installation tracking per sitePluginDownloadmodel - Download analytics
Distribution Endpoints:
GET /api/plugins/igny8-wp-bridge/download/ - Download latest ZIP
POST /api/plugins/igny8-wp-bridge/check-update/ - Check for updates
GET /api/plugins/igny8-wp-bridge/info/ - Plugin metadata
POST /api/plugins/igny8-wp-bridge/register/ - Register installation
POST /api/plugins/igny8-wp-bridge/health-check/ - Health monitoring
8.2 Auto-Update Mechanism
WordPress Side:
- Plugin hooks into
pre_set_site_transient_update_plugins - Calls
/api/plugins/igny8-wp-bridge/check-update/with current version - Receives update info if newer version available
- WordPress displays update notification
- User clicks "Update Now" (or auto-update runs)
- WordPress downloads ZIP from
/download/endpoint - Installs and activates new version
IGNY8 Side:
- Developer updates plugin source code
- Creates new
PluginVersionin Django admin - Changes status to "released"
- Signal automatically builds ZIP with checksums
- Files stored in
/plugins/wordpress/dist/ - WordPress sites can now download/update
8.3 Version History (Recent)
| Version | Date | Changes |
|---|---|---|
| 1.3.3 | Jan 10, 2026 | Template design: Square image grid fixes, landscape positioning, direct styling for images without captions |
| 1.3.2 | Jan 9, 2026 | Template rendering improvements, image layout enhancements |
| 1.3.1 | Jan 9, 2026 | Plugin versioning updates |
| 1.3.0 | Jan 8, 2026 | Distribution system release, auto-update mechanism |
8.4 Security Features
- Signed URLs: Download links expire after configurable time
- Checksums: MD5 and SHA256 verification
- Rate Limiting: Per IP/site download limits
- API Authentication: Required for sensitive operations
- Version Verification: WordPress validates plugin before update
8.5 Monitoring
Installation Tracking:
- Total installations per version
- Active installations by site
- Version distribution analytics
Download Analytics:
- Download counts per version
- Geographic distribution
- Failed download attempts
Health Checks:
- Plugin health status per installation
- Error reporting from WordPress sites
- Version compatibility tracking
9. Current Implementation
9.1 Production Status (v1.7.0)
✅ Fully Operational:
- WordPress plugin distribution system
- Auto-update mechanism
- Template rendering with advanced layouts
- Image positioning (square/landscape)
- Content publishing (manual + automation)
- Webhook status sync
- API authentication
- Health monitoring
✅ Template Features (v1.3.3):
- Square images: Side-by-side layout (left/right aligned)
- Landscape images: Full-width with max 1024px
- Images appear after first paragraph in sections
- Direct border-radius/shadow on images without captions
- Responsive design for mobile/tablet
9.2 Known Limitations
Missing Features:
- Bi-directional content sync (WordPress → IGNY8 editing)
- Conflict resolution for dual edits
- Advanced metadata sync beyond basics
- Multi-site WordPress network support
- Custom post type publishing
9.3 Future Enhancements
Planned:
- Image regeneration feature (Phase 9)
- Advanced template customization
- Custom field mapping
- Bulk publishing operations
- Real-time sync notifications
10. Flow Diagrams
9.1 Integration Setup
┌──────────┐ ┌──────────────┐ ┌───────────────┐
│ User │ │ IGNY8 App │ │ WordPress │
└────┬─────┘ └──────┬───────┘ └───────┬───────┘
│ │ │
│ 1. Open Site Settings │
├─────────────────>│ │
│ │ │
│ 2. Download Plugin │
├─────────────────>│ │
│ │ │
│<─────────────────┤ │
│ 3. Plugin ZIP │ │
│ │ │
│ 4. Install Plugin──────────────────────┼──────────>
│ │ │
│ 5. Generate API Key │
├─────────────────>│ │
│<─────────────────┤ │
│ 6. Display API Key │
│ │ │
│ 7. Enter API Key in Plugin─────────────┼──────────>
│ │ │
│ 8. Test Connection │
├─────────────────>│ │
│ │ 9. GET /wp-json/... │
│ ├────────────────────>│
│ │<────────────────────┤
│<─────────────────┤ 10. Success │
│ │ │
│ │ 11. Register Install│
│ │<────────────────────┤
10.2 Manual Publishing
┌──────────┐ ┌──────────────┐ ┌──────────┐ ┌───────────────┐
│ User │ │ IGNY8 API │ │ Celery │ │ WordPress │
└────┬─────┘ └──────┬───────┘ └────┬─────┘ └───────┬───────┘
│ │ │ │
│ 1. Click Publish │ │ │
├─────────────────>│ │ │
│ │ │ │
│ │ 2. Validate │ │
│ │ 3. Update status │ │
│ │ 4. Queue task │ │
│ ├─────────────────>│ │
│<─────────────────┤ │ │
│ 5. "Publishing..." │ │
│ │ │ │
│ │ │ 6. POST /publish │
│ │ ├──────────────────>│
│ │ │ │
│ │ │<──────────────────┤
│ │ │ 7. 201 Created │
│ │ │ │
│ │ 8. Update Content│ │
│ │<─────────────────┤ │
│ │ 9. Create SyncEvent │
│ │ │ │
10.3 Plugin Auto-Update Flow
┌───────────────┐ ┌──────────────┐
│ WordPress │ │ IGNY8 API │
└───────┬───────┘ └──────┬───────┘
│ │
│ 1. Check for updates (cron)
│ POST /check-update/│
├───────────────────>│
│ (current: 1.3.2) │
│ │
│<───────────────────┤
│ 2. Update available│
│ (latest: 1.3.3) │
│ │
│ 3. User clicks │
│ "Update Now" │
│ │
│ GET /download/ │
├───────────────────>│
│ │
│<───────────────────┤
│ 4. ZIP file │
│ │
│ 5. Install & Activate
│ │
│ POST /register/ │
├───────────────────>│
│ (new version info) │
│ │
│<───────────────────┤
│ 6. Registration OK │
│ │
10.4 Webhook Status Sync
┌───────────────┐ ┌──────────────┐
│ WordPress │ │ IGNY8 API │
└───────┬───────┘ └──────┬───────┘
│ │
│ 1. User changes status in WP
│ │
│ 2. POST /webhooks/wordpress/status/
├───────────────────>│
│ │
│ │ 3. Validate API key
│ │ 4. Find Content
│ │ 5. Map status
│ │ 6. Update Content
│ │ 7. Create SyncEvent
│ │
│<───────────────────┤
│ 8. 200 OK │
│ │
Summary
| Flow | Status | Notes |
|---|---|---|
| Integration Setup | ✅ Working | API key based |
| Manual Publish | ✅ Working | Via Celery task |
| Automation Publish | ⚠️ Partial | Stage 7 sets status but doesn't trigger WordPress push |
| Webhook Status Sync | ✅ Working | WordPress → IGNY8 status updates |
| Webhook Metadata Sync | ✅ Working | WordPress → IGNY8 metadata |
| Scheduled Auto-Publish | ❌ Not Active | Task exists but not scheduled |
| Content Pull Sync | ❌ Not Implemented | No import from WordPress |
| Content Update Sync | ❌ Not Implemented | No republish capability |