25 KiB
Strategic Analysis & Implementation Plan
Current State Assessment
What Works Well
- Unidirectional flow: IGNY8 → WordPress (correct approach)
- Comprehensive data mapping: All fields documented
- Multiple trigger points: Manual + scheduled
- API authentication: Solid security model
- Retry mechanism: Celery handles failures
What's Actually Broken/Missing
Critical Gaps (Real Functional Issues)
GAP 1: Incomplete Data Transfer
Problem: The audit shows fields are mapped, but doesn't confirm ALL data actually transfers in one atomic operation.
Current Risk:
- Featured image might fail → rest of content publishes anyway
- Gallery images fail → content published without visuals
- SEO meta fails → content has no SEO optimization
- Categories fail to create → content published orphaned
- Sectors/clusters fail → no IGNY8 relationship tracking
What's Missing:
- Pre-flight validation before starting publish
- Atomic transaction pattern (all-or-nothing)
- Dependency chain verification (e.g., author must exist before publishing)
- Rollback on partial failure
GAP 2: No Publish Count Tracking Back to IGNY8
Problem: You stated requirement #4 isn't implemented anywhere in the audit.
What's Missing:
- After successful WordPress publish, WordPress must call IGNY8 API to increment:
post_publish_countfor postspage_publish_countfor pagesproduct_publish_countfor productstaxonomy_sync_countfor categories/tags/sectors/clusters
Current State:
- WordPress reports back
assigned_post_idandpost_url - WordPress does NOT report back publish counts or content type statistics
Impact: IGNY8 dashboard shows incomplete/wrong statistics
GAP 3: Taxonomy Sync Doesn't Track Changes
Problem: You need to track if categories/tags/clusters change in WordPress, but current system doesn't.
Current Flow:
- IGNY8 sends:
categories: ["SEO", "Marketing"] - WordPress creates/assigns these
- If user later adds "Content Strategy" in WordPress → IGNY8 never knows
- If user removes "Marketing" → IGNY8 never knows
What's Missing:
- WordPress hook to detect taxonomy changes on IGNY8-managed posts
- API call to IGNY8 to update taxonomy associations
- Endpoint in IGNY8 to receive taxonomy change notifications
GAP 4: Cluster/Sector/Keyword Changes Not Synced
Problem: Similar to taxonomy gap but for IGNY8-specific relationships.
Scenario:
- Content published with
cluster_id: 12 - User changes in WordPress to
cluster_id: 15via custom field - IGNY8 still thinks content belongs to cluster 12
- Cluster 12 shows wrong content count
- Cluster 15 missing content in its list
What's Missing:
- Detection mechanism for meta field changes on
_igny8_cluster_id,_igny8_sector_id,_igny8_keyword_ids - Sync back to IGNY8 to update relationships
- IGNY8 API endpoints to handle relationship updates
GAP 5: Manual vs Auto-Publish Flow Not Distinguished
Problem: Both flows use same code path, but they need different handling.
Manual Publish (Button Click):
- Should publish immediately
- User expects instant feedback
- Should override any scheduling
- Should force re-publish if already published
Auto-Publish/Schedule:
- Should respect
published_attimestamp - Should not override manual edits in WordPress
- Should skip if already published (idempotent)
- Should handle timezone conversions
What's Missing:
publish_modeflag in API payload (manualvsscheduled)- Different retry strategies for each mode
- Different status reporting for each mode
- Override logic for manual re-publish
GAP 6: No Verification After Publish
Problem: WordPress reports "success" but doesn't verify the content is actually viewable/accessible.
Failure Scenarios Not Caught:
- Post published but permalink returns 404 (rewrite rules not flushed)
- Featured image attached but file doesn't exist (upload failed silently)
- Categories created but not assigned (database transaction partial commit)
- SEO meta saved but plugin not active (meta stored but not used)
What's Missing:
- Post-publish verification step
- Check permalink returns 200
- Verify featured image URL accessible
- Verify taxonomies actually assigned (count > 0)
- Report verification results to IGNY8
GAP 7: Schedule Publishing Timezone Issues
Problem: IGNY8 sends UTC timestamp, WordPress stores in site timezone, confusion inevitable.
Scenario:
- IGNY8 schedules for "2025-12-01 10:00:00 UTC"
- WordPress site timezone is "America/New_York" (UTC-5)
- WordPress interprets as 10:00 AM New York time
- Content publishes 5 hours later than intended
What's Missing:
- Explicit timezone handling in payload
- Timezone conversion logic in WordPress
- Verification that scheduled time matches intent
GAP 8: All-or-Nothing Guarantees Missing
Problem: Content can be half-published (post exists but missing images/meta).
Current Flow:
1. wp_insert_post() → Success (post ID 1842)
2. Download featured image → FAILS
3. Assign categories → Success
4. Store SEO meta → Success
5. Report success to IGNY8 ✓
Result: Post published without featured image
IGNY8 thinks everything succeeded
What's Missing:
- Transaction wrapper around entire publish operation
- Failure detection for each sub-operation
- Rollback mechanism if any step fails
- Detailed error reporting (which step failed)
GAP 9: No Re-Publish Protection
Problem: If publish button clicked twice or Celery task runs twice, content duplicates.
Scenario:
- User clicks "Publish" in IGNY8
- Celery task queued
- User clicks "Publish" again (impatient)
- Second Celery task queued
- Both tasks run → 2 WordPress posts created for same content
What's Missing:
- Task deduplication based on
content_id+site_integration_id - Lock mechanism during publish
- WordPress duplicate detection by
_igny8_content_idbefore creating new post - Return existing post if already published (idempotent operation)
GAP 10: Publish Count Statistics Incomplete
Problem: You need counts by content type, but current system doesn't track this granularly.
What IGNY8 Needs:
class SiteIntegration(models.Model):
# Current (missing):
posts_published_count = models.IntegerField(default=0)
pages_published_count = models.IntegerField(default=0)
products_published_count = models.IntegerField(default=0)
# Also need:
categories_synced_count = models.IntegerField(default=0)
tags_synced_count = models.IntegerField(default=0)
sectors_synced_count = models.IntegerField(default=0)
clusters_synced_count = models.IntegerField(default=0)
last_publish_at = models.DateTimeField(null=True)
total_sync_operations = models.IntegerField(default=0)
What's Missing:
- WordPress needs to detect content type (post/page/product) and report it
- WordPress needs to count new vs updated taxonomies and report
- IGNY8 needs endpoints to receive these counts
- Dashboard needs to display these statistics
GAP 11: Auto-Publish Scheduling Mechanism Unclear
Problem: Audit shows Celery runs every 5 minutes, but doesn't explain how scheduled publishing works.
Questions Unanswered:
- If
published_atis in future, does Celery skip it? - How does Celery know when to publish scheduled content?
- Is there a separate queue for scheduled vs immediate?
- What if scheduled time is missed (server down)?
What's Likely Missing:
- Scheduled content query filter in Celery task
- Time-based condition:
published_at <= now() - Missed schedule handler (publish immediately if past due)
- Different retry logic for scheduled vs immediate
GAP 12: Taxonomy Creation vs Assignment Not Clear
Problem: If category "Digital Marketing" doesn't exist in WordPress, what happens?
Scenario 1: Auto-Create (probably current):
- WordPress creates category "Digital Marketing"
- Assigns to post
- Problem: Might create duplicates if slug differs ("digital-marketing" vs "digitalmarketing")
Scenario 2: Map to Existing:
- WordPress looks up by name
- If not found, uses fallback category
- Problem: User needs to pre-create all categories
What's Missing:
- Clear taxonomy reconciliation strategy
- Slug normalization rules
- Duplicate prevention logic
- Fallback category configuration
GAP 13: Keywords Not Actually Published
Problem: Audit shows focus_keywords stored in meta, but WordPress doesn't use this field natively.
Current State:
- IGNY8 sends:
focus_keywords: ["SEO 2025", "ranking factors"] - WordPress stores:
_igny8_focus_keywordsmeta - Nobody reads this field (unless custom code added)
What's Missing:
- Integration with actual keyword tracking plugins (Yoast, RankMath, AIOSEO)
- Mapping to plugin-specific meta fields
- Fallback if no SEO plugin installed
GAP 14: Gallery Images Limit Arbitrary
Problem: Audit mentions "5 images max" for gallery but doesn't explain why or what happens to 6th image.
Questions:
- Is this IGNY8 limit or WordPress plugin limit?
- What happens if IGNY8 sends 10 images?
- Are they silently dropped? Error thrown?
- How does user know some images were skipped?
What's Missing:
- Configurable gallery size limit
- Clear error message if limit exceeded
- Option to create separate gallery post/page for overflow
Implementation Plan (No Code)
Phase 1: Fix Critical Data Integrity Issues (Week 1-2)
1.1 Implement Atomic Transaction Pattern
- Wrap entire publish operation in WordPress transaction
- If ANY step fails → rollback everything
- Delete post if created but subsequent operations failed
- Report detailed failure info to IGNY8 (which step failed)
1.2 Add Pre-Flight Validation
Before attempting publish:
- Verify author exists (by email)
- Verify all image URLs accessible (HTTP HEAD request)
- Verify required fields present (title, content)
- Verify post type enabled in WordPress plugin settings
- Return validation errors BEFORE creating anything
1.3 Implement Duplicate Prevention
- Check if post with
_igny8_content_idalready exists - If exists → update instead of create (unless manual re-publish)
- Add unique constraint in IGNY8:
(content_id, site_integration_id)→ only one publish task active at a time - Celery task deduplication by task signature
1.4 Add Post-Publish Verification
After WordPress reports "success":
- Wait 5 seconds (let WordPress flush rewrites)
- HTTP GET the permalink → expect 200
- HTTP HEAD the featured image URL → expect 200
- Query taxonomies assigned → expect count > 0
- If verification fails → mark as "published_with_issues" status
- Report verification results to IGNY8
Phase 2: Implement Publish Count Tracking (Week 2-3)
2.1 Extend IGNY8 Models
Add to SiteIntegration:
posts_published_countpages_published_countproducts_published_countcategories_synced_counttags_synced_countsectors_synced_countclusters_synced_countlast_publish_attotal_sync_operations
2.2 Create IGNY8 Stats Endpoint
PUT /integrations/{site_id}/stats/increment/
Payload: {
"content_type": "post", // or "page", "product"
"taxonomies_created": {
"categories": 2,
"tags": 5,
"sectors": 1,
"clusters": 1
},
"taxonomies_updated": {
"categories": 0,
"tags": 1,
"sectors": 0,
"clusters": 0
},
"published_at": "2025-11-29T10:15:30Z"
}
2.3 Update WordPress Plugin Response
After successful publish, WordPress must:
- Detect post type (post/page/product)
- Count new categories created vs existing assigned
- Count new tags created vs existing assigned
- Count new sectors created vs existing assigned
- Count new clusters created vs existing assigned
- Call IGNY8 stats endpoint with all counts
- IGNY8 increments counters atomically
Phase 3: Implement Taxonomy Change Tracking (Week 3-4)
3.1 Add WordPress Hooks
Hook into:
set_object_terms(when taxonomies assigned/changed)update_post_meta(when cluster/sector/keyword meta changed)- Filter by: post has
_igny8_task_idmeta (only track IGNY8-managed posts)
3.2 Create IGNY8 Taxonomy Update Endpoint
PUT /writer/tasks/{task_id}/taxonomies/
Payload: {
"categories": [1, 2, 3], // WordPress term IDs
"tags": [5, 8, 12],
"sectors": [2],
"clusters": [7, 9],
"updated_by": "wordpress_user_123",
"updated_at": "2025-11-29T11:00:00Z"
}
3.3 Create IGNY8 Relationships Update Endpoint
PUT /writer/tasks/{task_id}/relationships/
Payload: {
"cluster_id": 15, // changed from 12
"sector_id": 5, // unchanged
"keyword_ids": [1, 2, 3, 8], // added keyword 8
"updated_by": "wordpress_user_123",
"updated_at": "2025-11-29T11:00:00Z"
}
3.4 Implement Debouncing
- Don't sync every single taxonomy change immediately
- Batch changes over 30-second window
- Send one API call with all changes
- Reduce API call volume by 95%
Phase 4: Separate Manual vs Auto-Publish Flows (Week 4-5)
4.1 Add publish_mode to API Payload
IGNY8 must send:
{
"content_id": 42,
"publish_mode": "manual", // or "scheduled"
"published_at": "2025-12-01T10:00:00Z",
...
}
4.2 Implement Different Logic
Manual Mode:
- Ignore
published_attimestamp (publish NOW) - If post already exists → force update (don't skip)
- Return immediate feedback (synchronous within 5 seconds)
- Retry aggressively (3 retries, 10 seconds apart)
- Show user real-time progress
Scheduled Mode:
- Respect
published_attimestamp - If post already exists → skip (idempotent)
- Queue for future execution
- Retry conservatively (3 retries, 1 hour apart)
- Don't notify user of each retry
4.3 Update Celery Task Query
# Current: publishes everything with status='completed'
pending_content = ContentPost.objects.filter(
wordpress_sync_status='pending',
published_at__isnull=False
)
# New: separate scheduled from immediate
immediate_content = ContentPost.objects.filter(
wordpress_sync_status='pending',
publish_mode='manual',
published_at__isnull=False
)
scheduled_content = ContentPost.objects.filter(
wordpress_sync_status='pending',
publish_mode='scheduled',
published_at__lte=now(), # only if scheduled time reached
published_at__isnull=False
)
Phase 5: Timezone Handling (Week 5)
5.1 Standardize on UTC Everywhere
- IGNY8 always sends timestamps in UTC with explicit timezone:
"2025-12-01T10:00:00Z" - WordPress plugin converts to site timezone for
post_date - WordPress converts back to UTC when reporting to IGNY8
- Never rely on implied timezones
5.2 Add Timezone to WordPress Response
{
"success": true,
"data": {
"post_id": 1842,
"post_date_utc": "2025-11-29T10:15:30Z",
"post_date_site": "2025-11-29T05:15:30-05:00",
"site_timezone": "America/New_York"
}
}
5.3 Scheduled Publish Verification
- IGNY8 stores: "Scheduled for 2025-12-01 10:00 UTC"
- WordPress publishes at: "2025-12-01 05:00 EST" (correct)
- WordPress reports back: "Published at 2025-12-01T10:00:00Z" (UTC)
- IGNY8 verifies timestamp matches expected
Phase 6: Enhanced Error Reporting (Week 6)
6.1 Add Detailed Error Structure
{
"success": false,
"error": {
"code": "FEATURED_IMAGE_DOWNLOAD_FAILED",
"message": "Failed to download featured image",
"step": "media_processing",
"step_number": 3,
"total_steps": 7,
"details": {
"image_url": "https://example.com/image.jpg",
"http_status": 404,
"error": "Not Found"
},
"recoverable": true,
"retry_recommended": true
}
}
6.2 Add Progress Reporting for Manual Publish
For manual publish, send progress updates:
POST /integrations/{site_id}/publish-progress/
{
"task_id": 15,
"step": "creating_post",
"progress": 30,
"message": "Creating WordPress post..."
}
Frontend shows real-time progress bar.
Phase 7: Taxonomy Reconciliation Strategy (Week 6-7)
7.1 Add Taxonomy Mapping Configuration
WordPress plugin settings:
- Auto-create missing taxonomies: ON/OFF
- Slug normalization: lowercase + hyphens
- Duplicate detection: by slug (not name)
- Fallback category: "Uncategorized" (if auto-create OFF and category not found)
7.2 Taxonomy Reconciliation Algorithm
For each category in IGNY8 payload:
1. Normalize slug: "Digital Marketing" → "digital-marketing"
2. Query WordPress by slug (not name)
3. If found → use existing term ID
4. If not found:
a. If auto-create ON → create new term
b. If auto-create OFF → use fallback category
5. Assign term to post
7.3 Report Taxonomy Changes to IGNY8
{
"taxonomies_processed": {
"categories": {
"requested": ["Digital Marketing", "SEO"],
"created": ["SEO"],
"existing": ["Digital Marketing"],
"assigned": [1, 5]
},
"tags": {
"requested": ["seo", "ranking"],
"created": [],
"existing": ["seo", "ranking"],
"assigned": [8, 12]
}
}
}
Phase 8: SEO Plugin Integration (Week 7-8)
8.1 Detect Active SEO Plugin
WordPress plugin detects:
- Yoast SEO
- Rank Math
- All in One SEO
- SEOPress
- (or none)
8.2 Map Focus Keywords to Plugin Fields
Yoast SEO:
_yoast_wpseo_focuskw= first keyword_yoast_wpseo_keywordsynonyms= remaining keywords (comma-separated)
Rank Math:
rank_math_focus_keyword= first keyword- Additional keywords stored in JSON meta
All in One SEO:
_aioseo_keywords= comma-separated list
No Plugin:
- Store in
_igny8_focus_keywords(current behavior) - Optional: Generate simple meta keywords tag
8.3 Report SEO Plugin Status to IGNY8
{
"seo_plugin": {
"active": "yoast",
"version": "22.0",
"keywords_supported": true,
"focus_keyword_set": true
}
}
Phase 9: Gallery Image Handling (Week 8)
9.1 Make Gallery Limit Configurable
WordPress plugin settings:
- Max gallery images: 5 (default)
- Overflow behavior:
- "Skip extra images" (current)
- "Create separate gallery post"
- "Add to post content as image grid"
9.2 Handle Overflow Images
If IGNY8 sends 10 images but limit is 5:
Option A: Skip:
- Use first 5
- Report to IGNY8:
"gallery_images_skipped": 5
Option B: Create Separate Post:
- Create new post: "{Original Title} - Gallery"
- Attach images 6-10
- Link from original post
- Report to IGNY8:
"gallery_overflow_post_id": 1843
Option C: Inline Grid:
- Append HTML grid to post content
- All 10 images in post body
- Report to IGNY8:
"gallery_images_inline": 10
Phase 10: Monitoring & Dashboard (Week 9)
10.1 IGNY8 Dashboard Enhancements
Display per site:
- Total Published: Posts (X) | Pages (Y) | Products (Z)
- Taxonomies Synced: Categories (A) | Tags (B) | Sectors (C) | Clusters (D)
- Last Published: 2 hours ago
- Publish Success Rate: 98.5% (last 30 days)
- Average Publish Time: 3.2 seconds
- Pending: 5 scheduled for today
10.2 WordPress Plugin Dashboard
Display:
- IGNY8 Posts: 142 published | 5 pending
- Last Sync: 10 minutes ago
- Connection Status: Connected ✓
- Recent Activity:
- 10:15 AM - Published "SEO Guide 2025" (post)
- 10:05 AM - Published "About Us" (page)
- 09:50 AM - Synced 3 categories
10.3 Add Health Check Endpoint
GET /wp-json/igny8/v1/health
Response:
{
"status": "healthy",
"checks": {
"api_connection": "ok",
"database": "ok",
"media_uploads": "ok",
"taxonomy_creation": "ok"
},
"stats": {
"posts_managed": 142,
"last_publish": "2025-11-29T10:15:30Z",
"disk_space": "15GB free"
}
}
Call from IGNY8 every 5 minutes to detect issues early.
Summary: What Actually Needs to Change
Backend (IGNY8 Django) Changes:
-
Add Models Fields:
publish_modeto ContentPost ('manual' or 'scheduled')- Publish count fields to SiteIntegration
- Taxonomy sync count fields
-
Add API Endpoints:
PUT /integrations/{id}/stats/increment/(receive counts from WP)PUT /writer/tasks/{id}/taxonomies/(receive taxonomy changes from WP)PUT /writer/tasks/{id}/relationships/(receive cluster/sector changes from WP)
-
Update Celery Task:
- Add pre-flight validation
- Separate scheduled vs manual queries
- Add duplicate prevention
- Add timezone handling
- Improve error reporting
-
Update API Call to WordPress:
- Send
publish_modeflag - Send explicit UTC timezone
- Handle detailed error responses
- Process verification results
- Send
Frontend (IGNY8 Vue/React) Changes:
-
Manual Publish Button:
- Show real-time progress (if WordPress sends updates)
- Show detailed success message with link to WP post
- Show detailed error message if fails (which step failed)
-
Dashboard Stats:
- Display publish counts by content type
- Display taxonomy sync counts
- Display last publish timestamp
- Display success rate graph
-
Scheduled Publish UI:
- Datetime picker with timezone display
- "Schedule for: Dec 1, 2025 10:00 AM UTC (5:00 AM your time)"
- List of scheduled publications
- Ability to cancel scheduled publish
WordPress Plugin Changes:
-
Core Publish Function:
- Wrap in transaction (all-or-nothing)
- Add pre-flight validation
- Add duplicate detection
- Add post-publish verification
- Handle
publish_modeflag differently
-
Add Taxonomy Hooks:
- Detect changes to categories/tags/sectors/clusters
- Batch changes over 30 seconds
- Call IGNY8 API to sync changes
-
Add Stats Tracking:
- Count content types published
- Count taxonomies created vs assigned
- Call IGNY8 stats endpoint after each publish
-
Settings Page:
- Taxonomy auto-create ON/OFF
- Taxonomy fallback category selector
- Gallery image limit (slider: 1-20)
- Gallery overflow behavior (dropdown)
- SEO plugin integration status
-
Response Format:
- Add verification results
- Add taxonomy processing details
- Add publish counts
- Add timezone info
Testing Strategy
1. Atomic Transaction Tests
- Publish with invalid image URL → entire operation should fail, no post created
- Publish with invalid author → entire operation should fail
- Publish with SEO plugin disabled → post created, SEO meta stored anyway
2. Duplicate Prevention Tests
- Click publish button twice rapidly → only 1 post created
- Celery task runs while manual publish in progress → only 1 post created
- Re-publish same content → update existing post, don't create new
3. Timezone Tests
- Schedule for "Dec 1, 2025 10:00 UTC" from timezone UTC+5 → publishes at correct time
- WordPress in timezone "America/New_York" → post_date stored correctly in local time
- IGNY8 receives post_date_utc → matches scheduled time exactly
4. Taxonomy Sync Tests
- Add category in WordPress → IGNY8 receives update within 30 seconds
- Remove tag in WordPress → IGNY8 receives update
- Change cluster via custom field → IGNY8 receives update
- Change multiple taxonomies at once → IGNY8 receives 1 batched update
5. Count Tracking Tests
- Publish 1 post → SiteIntegration.posts_published_count increments by 1
- Publish 1 page → SiteIntegration.pages_published_count increments by 1
- Create 2 new categories → SiteIntegration.categories_synced_count increments by 2
- Update post (no new taxonomies) → counts don't change
6. Manual vs Scheduled Tests
- Manual publish → immediate execution, ignores published_at
- Scheduled publish → waits until published_at time
- Manual re-publish of scheduled content → publishes immediately, overrides schedule
Implementation Priority
Critical (Do First):
- Atomic transactions (Phase 1.1)
- Duplicate prevention (Phase 1.3)
- Publish count tracking (Phase 2)
- Manual vs scheduled separation (Phase 4)
High Priority:
- Timezone handling (Phase 5)
- Taxonomy change tracking (Phase 3)
- Enhanced error reporting (Phase 6)
Medium Priority:
- Taxonomy reconciliation (Phase 7)
- SEO plugin integration (Phase 8)
- Gallery improvements (Phase 9)
Low Priority:
- Dashboard enhancements (Phase 10)
This plan focuses on real functional gaps that affect data integrity, user experience, and system reliability. No cosmetics, just critical infrastructure improvements.