22 KiB
IGNY8 Phase 3: WordPress Plugin — Connected Mode (03B)
IGNY8 SaaS ↔ WordPress Bidirectional Integration
Document Version: 1.0
Date: 2026-03-23
Phase: IGNY8 Phase 3 — WordPress Ecosystem
Status: Build Ready
Source of Truth: Codebase at /data/app/igny8/
Audience: Claude Code, WordPress Developers, Architects
1. CURRENT STATE
Existing WordPress Bridge
The IGNY8 WordPress Bridge Plugin v1.5.2 at /data/app/igny8/plugins/wordpress/source/igny8-wp-bridge/ provides basic content sync:
- Content push from IGNY8 → WordPress via
POST /wp-json/igny8/v1/sync/push - SAG blueprint sync via
POST /wp-json/igny8/v1/sag/sync-blueprint - Taxonomy creation via
POST /wp-json/igny8/v1/sag/create-taxonomies - API key authentication using
X-IGNY8-API-KEYheader
What v2 Connected Mode Replaces
Phase 3 connected mode is part of the new v2 plugin (03A). It replaces and extends all v1.5.2 capabilities with:
- Full content queue + review workflow (not just raw push)
- Image downloading and attachment creation
- SAG blueprint → taxonomy + term → cluster hub page mapping
- Bidirectional sync events and confirmation callbacks
- Schema bulk push from IGNY8 backend (02G)
- GSC status sync from IGNY8 backend (02C)
- Auto-linking from IGNY8 backend (02D)
- Social auto-post from IGNY8 backend (02H)
Prerequisites
- Standalone plugin (03A) must be installed and active
- IGNY8 SaaS subscription with valid API key
- Connection established via Setup Wizard Step 5 or Settings → Connect
IGNY8 Backend Models That WordPress Interacts With
Content(writer app, db_table=igny8_content) — content_type: post/page/product/taxonomy; content_structure choicesTasks(writer app, db_table=igny8_tasks) — writing tasks, status: queued/completedImages(writer app) — generated images for contentClusters(planner app, db_table=igny8_clusters) — keyword clustersSAGBlueprint,SAGAttribute,SAGCluster(sag app) — Phase 1 SAG modelsSiteIntegration(integration app) — WordPress connection detailsSyncEvent(integration app) — sync operation logsPublishingSettings,PublishingRecord(publishing app)- All IDs are integers (BigAutoField) — never UUIDs
2. WHAT TO BUILD
Overview
Two connected-mode modules that extend the standalone plugin (03A) when an IGNY8 SaaS subscription is active. These modules are only loaded when igny8_api_connected option is true.
Module 11: Content Sync
Purpose: Receive content from IGNY8 SaaS, queue it, download images, map types, create/update WordPress posts, and confirm back.
Classes:
| Class | File | Purpose |
|---|---|---|
IGNY8_Sync_Module |
modules/content-sync/class-sync-module.php |
Module entry, webhook receiver |
IGNY8_Content_Puller |
modules/content-sync/class-content-puller.php |
Fetch content from IGNY8 SaaS API |
IGNY8_Content_Mapper |
modules/content-sync/class-content-mapper.php |
Map IGNY8 content_type → WP post_type |
IGNY8_Image_Downloader |
modules/content-sync/class-image-downloader.php |
Download images → wp_upload_dir(), wp_insert_attachment() |
IGNY8_Sync_Queue |
modules/content-sync/class-sync-queue.php |
Sync queue DB table management |
IGNY8_Publish_Scheduler |
modules/content-sync/class-publish-scheduler.php |
Review queue, scheduled publishing |
Content Type Mapping:
| IGNY8 content_type | WP post_type | Notes |
|---|---|---|
post |
post |
Default blog post |
page |
page |
Standard page |
product |
product |
Requires WooCommerce active |
service |
service |
Requires companion theme CPT (03C) |
company_page |
page |
Uses page-company template |
taxonomy_landing |
— | Written to term description (not a post) |
cluster_hub |
page |
Landing page preset applied |
comparison |
post |
Standard post with comparison structure |
brand_page |
page |
Standard page |
Content Sync Flow:
1. IGNY8 SaaS publishes content
2. → POST /wp-json/igny8/v1/sync/push (validated via X-IGNY8-API-KEY)
Payload: {igny8_content_id, content_type, title, content_html, excerpt,
featured_image, meta: {focus_keyword, secondary_keywords,
cluster_id, taxonomies: {service_category: [...], cluster: [...]}}}
3. → Plugin creates {prefix}igny8_sync_queue entry (status: pending)
4. → WP Cron job (igny8_process_sync_queue) processes queue:
a. Download images → wp_upload_dir(), wp_insert_attachment()
b. Map content_type → WP post_type via IGNY8_Content_Mapper
c. wp_insert_post() or wp_update_post()
d. Set post meta (_igny8_content_id, _igny8_cluster_id, _igny8_sync_status)
e. wp_set_object_terms() for taxonomy assignment
f. Status: 'review' (manual mode) or 'synced' (auto-publish mode)
5. → Plugin POSTs confirmation to IGNY8: POST /api/v1/integration/sync-events/
Methods:
push_content_to_queue($data)— validate payload, insert into sync queueprocess_sync_queue()— WP Cron handler, batch process pending itemsmap_content_type($igny8_type)— return WP post_type + templatecreate_post_from_content($data)—wp_insert_post()+ meta + termsdownload_images($content)— download towp_upload_dir(), create attachmentsschedule_publish($post_id, $date)— set future publish dateget_review_queue()— list items with statusreview
Post Meta (Connected Mode):
_igny8_content_id -- int: links WP post to IGNY8 Content record
_igny8_cluster_id -- int: links WP post to IGNY8 SAGCluster
_igny8_sync_status -- string: pending/synced/failed/modified
_igny8_last_sync -- string: ISO timestamp
_igny8_related_links -- JSON: [{post_id, anchor_text, priority}]
_igny8_link_suggestions -- JSON: AI-generated link suggestions from 02D
Hooks:
- Actions:
wp_scheduled_event(igny8_process_sync_queue),rest_api_init - Filters:
igny8_content_before_sync,igny8_post_mapped,igny8_sync_status_updated
Module 12: SAG Structure (Blueprint Sync)
Purpose: Receive SAG blueprint from IGNY8, create WordPress taxonomies and terms matching SAG dimensions and attributes, map clusters to hub pages, and provide structure visualization.
Classes:
| Class | File | Purpose |
|---|---|---|
IGNY8_SAG_Module |
modules/sag/class-sag-module.php |
Module entry |
IGNY8_Blueprint_Sync |
modules/sag/class-blueprint-sync.php |
Receive + cache blueprint |
IGNY8_Taxonomy_Builder |
modules/sag/class-taxonomy-builder.php |
register_taxonomy() from SAG attributes |
IGNY8_Term_Builder |
modules/sag/class-term-builder.php |
wp_insert_term() with hierarchy |
IGNY8_Cluster_Manager |
modules/sag/class-cluster-manager.php |
Map clusters → hub pages/terms |
IGNY8_Structure_Visualizer |
modules/sag/class-structure-visualizer.php |
Visual site structure admin page |
SAG Blueprint Sync Flow:
1. IGNY8 confirms blueprint (01D setup wizard)
2. → POST /wp-json/igny8/v1/sag/sync-blueprint (validated via X-IGNY8-API-KEY)
Payload: {blueprint: {dimensions: [{id, name, slug, attributes: [{id, name, slug}]}],
clusters: [{id, name, dimension_ids, hub_page_id, recommended_content_count}]}}
3. → Plugin stores in option igny8_sag_blueprint
4. → Admin sees "Blueprint Review" notice
5. → User clicks "Approve Blueprint":
a. Loop dimensions → register_taxonomy() if not exists
b. Loop attribute values → wp_insert_term() with parent hierarchy
c. Set term meta (_igny8_term_sag_attribute, _igny8_term_sag_level)
d. Loop clusters → create/link hub pages
6. → POST confirmation back: {term_ids_map, hub_page_ids_map}
Methods:
sync_blueprint($json)— validate, store in option, trigger admin noticecreate_taxonomies_from_blueprint($bp)—register_taxonomy()per dimensioncreate_terms_from_blueprint($bp)—wp_insert_term()per attribute valuemap_cluster_to_page($cluster_id, $page_id)— link SAGCluster to WP hub pageget_blueprint()— return cached blueprint from optionget_structure_overview()— summary for structure visualizer admin page
Term Meta (Connected Mode):
_igny8_term_content -- string: rich HTML for term landing page
_igny8_term_faq -- JSON: [{question, answer}]
_igny8_term_related_terms -- JSON: [term_id, term_id, ...]
_igny8_term_sag_attribute -- string: attribute name from SAG
_igny8_term_sag_level -- string: primary/secondary/tertiary
_igny8_term_cluster_id -- int: linked SAGCluster ID
_igny8_term_igny8_id -- int: ID in IGNY8 platform
_igny8_term_seo_title -- string: SEO title for term archive
_igny8_term_meta_description -- string: meta description for term archive
_igny8_term_robots_index -- string: index/noindex
_igny8_term_og_image -- int: OG image attachment ID
3. DATA MODELS & APIS
Database Table
The sync queue table is created by 03A's class-installer.php (table 6), used here:
{prefix}igny8_sync_queue
CREATE TABLE {prefix}igny8_sync_queue (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
igny8_content_id VARCHAR(100) NOT NULL,
content_type VARCHAR(50) NOT NULL,
sync_status VARCHAR(20) NOT NULL DEFAULT 'pending',
wp_post_id BIGINT NULL,
wp_term_id BIGINT NULL,
data LONGTEXT NULL,
created_at DATETIME NOT NULL,
synced_at DATETIME NULL,
error_message TEXT NULL,
INDEX idx_status (sync_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Options (Connected Mode)
| Option Key | Purpose |
|---|---|
igny8_api_key |
API key for IGNY8 SaaS (encrypted via wp_encrypt() or openssl) |
igny8_api_connected |
Boolean — is connected mode active |
igny8_api_url |
Base URL (default: https://api.igny8.com/api/v1/) |
igny8_site_id |
IGNY8 Site record ID (integer) |
igny8_last_sync |
ISO timestamp of last successful sync |
igny8_sag_blueprint |
JSON: full blueprint data from IGNY8 |
API Client (class-api-client.php)
Outbound requests from WordPress to IGNY8 SaaS API:
| Property | Value |
|---|---|
| Base URL | From igny8_api_url option (default: https://api.igny8.com/api/v1/) |
| Auth Header | Authorization: Bearer {igny8_api_key} |
| Methods | get($endpoint, $params), post($endpoint, $data), put($endpoint, $data), delete($endpoint) |
| Error Handling | WP_Error wrapping, log failures via error_log() |
| Rate Limiting | Respect 429 responses with exponential backoff (1s → 2s → 4s → 8s) |
| Connection Test | GET /api/v1/system/status/ |
IGNY8 Backend Endpoints Consumed by Plugin:
GET /api/v1/writer/content/?site_id=X&status=approved -- content ready for sync
GET /api/v1/writer/content/{id}/ -- single content with HTML, images, taxonomy data
GET /api/v1/planner/clusters/?site_id=X -- cluster data
GET /api/v1/sag/blueprints/?site_id=X -- SAG blueprint (Phase 1)
POST /api/v1/integration/sync-events/ -- log sync results
POST /api/v1/publishing/records/ -- log publishing
REST Endpoints (Inbound from IGNY8)
All endpoints validate X-IGNY8-API-KEY header. Under /wp-json/igny8/v1/:
| Method | Endpoint | Purpose | Payload |
|---|---|---|---|
| POST | /sync/push |
Content push from IGNY8 | {igny8_content_id, content_type, title, content, excerpt, featured_image, meta: {...}} |
| POST | /sag/sync-blueprint |
Blueprint sync | {blueprint: {dimensions: [...], clusters: [...]}} |
| POST | /sag/create-taxonomies |
Taxonomy creation | {taxonomies: [{name, slug, hierarchical, post_types}]} |
| POST | /terms/{id}/content |
Term content push | {term_id, content, faq, related_terms, meta: {...}} |
| POST | /schema/bulk-update |
Schema JSON-LD bulk push | {schemas: [{post_id, schema_type, schema_data}]} |
| POST | /gsc/status-sync |
GSC index statuses | {statuses: [{url, index_status, coverage_state, last_checked}]} |
| POST | /event |
Webhook events | {event_type, data: {...}} |
Endpoint Payload Examples
POST /sync/push:
{
"igny8_content_id": 12345,
"content_type": "post",
"title": "Content Title",
"content": "<p>HTML content...</p>",
"excerpt": "Short excerpt",
"featured_image": "https://cdn.igny8.com/image.jpg",
"meta": {
"focus_keyword": "main keyword",
"secondary_keywords": ["kw2", "kw3"],
"cluster_id": 123,
"taxonomies": {
"service_category": ["emergency-plumbing"],
"cluster": ["drain-services"]
}
}
}
POST /sag/sync-blueprint:
{
"blueprint": {
"dimensions": [
{
"id": 1,
"name": "Service Type",
"slug": "service_type",
"attributes": [
{"id": 1, "name": "Emergency Plumbing", "slug": "emergency-plumbing"}
]
}
],
"clusters": [
{
"id": 1,
"name": "Emergency Drain Cleaning",
"dimension_ids": [1, 2],
"hub_page_id": null,
"recommended_content_count": 12
}
]
}
}
POST /terms/{id}/content:
{
"term_id": 1001,
"content": "<p>HTML content for term landing page</p>",
"faq": [{"question": "Q1?", "answer": "A1"}],
"related_terms": [1002, 1003],
"meta": {
"seo_title": "Custom title",
"meta_description": "Custom description"
}
}
POST /schema/bulk-update:
{
"schemas": [
{
"post_id": 123,
"schema_type": "Article",
"schema_data": {"@context": "https://schema.org", "@type": "Article"}
}
]
}
POST /gsc/status-sync:
{
"statuses": [
{
"url": "https://example.com/post",
"index_status": "Indexed",
"coverage_state": "Submitted and indexed",
"last_checked": "2026-03-22T12:00:00Z"
}
]
}
4. IMPLEMENTATION STEPS
Admin UI Additions (Connected Mode)
When connected, two new submenus appear:
IGNY8 (top-level)
├── ... (all standalone modules from 03A)
├── Content Sync — Sync queue, review queue, settings, sync log
└── SAG Structure — Blueprint review, cluster manager, structure visualizer
Build Sequence
Phase 8: Content Sync Module (Days 21-24)
- Build
IGNY8_Sync_Module— module entry, register REST endpoints - Build
IGNY8_Content_Mapper— content_type → post_type mapping table - Build
IGNY8_Image_Downloader— download remote images, create WP attachments - Build
IGNY8_Sync_Queue— queue management, status transitions - Build
IGNY8_Content_Puller— fetch content from IGNY8 API - Build
IGNY8_Publish_Scheduler— review queue UI, scheduled publishing - Register WP Cron event:
igny8_process_sync_queue(every 5 minutes)
Phase 9: SAG Structure Module (Days 25-27)
- Build
IGNY8_SAG_Module— module entry, register REST endpoints - Build
IGNY8_Blueprint_Sync— receive, validate, store blueprint - Build
IGNY8_Taxonomy_Builder—register_taxonomy()from blueprint dimensions - Build
IGNY8_Term_Builder—wp_insert_term()from attribute values - Build
IGNY8_Cluster_Manager— map clusters → hub pages - Build
IGNY8_Structure_Visualizer— admin page with visual site structure - Build
class-api-client.php— outbound IGNY8 API client with rate limiting
Security Considerations
- API Key Validation: Every inbound REST endpoint validates
X-IGNY8-API-KEYheader against storedigny8_api_keyoption usinghash_equals()for timing-safe comparison - Payload Sanitization: All incoming content HTML sanitized via
wp_kses_post(). All text fields viasanitize_text_field(). All URLs viasanitize_url(). All integers viaabsint() - API Key Storage: Encrypted at rest. Never exposed in admin UI after initial entry. Use
wp_optionswith obfuscated display (****...last4) - Rate Limiting: API client respects 429 responses. Exponential backoff: 1s → 2s → 4s → 8s max
- Nonce Bypass for REST: Inbound webhooks use API key auth, not nonce. WordPress REST permission callbacks enforce
X-IGNY8-API-KEYvalidation
5. ACCEPTANCE CRITERIA
Content Sync (Module 11)
POST /wp-json/igny8/v1/sync/pushreceives content and creates sync queue entry- WP Cron processes sync queue — creates/updates WordPress posts
- Content type mapping works for all 9 IGNY8 → WP type combinations
- Images downloaded from IGNY8 CDN, created as WP attachments, set as featured
- Post meta set:
_igny8_content_id,_igny8_cluster_id,_igny8_sync_status - Taxonomy terms assigned via
wp_set_object_terms() - Review mode: items land in review queue (status
review) for manual approval - Auto-publish mode: items publish directly (status
synced) - Confirmation callback POSTs to
POST /api/v1/integration/sync-events/ - Sync queue admin page shows all items with status, errors, retry button
SAG Structure (Module 12)
POST /wp-json/igny8/v1/sag/sync-blueprintreceives and stores blueprint- Admin sees "Blueprint Review" notice after blueprint sync
- "Approve Blueprint" creates taxonomies from SAG dimensions
- Terms created from attribute values with correct hierarchy
- Term meta set:
_igny8_term_sag_attribute,_igny8_term_sag_level,_igny8_term_cluster_id - Clusters mapped to hub pages
POST /wp-json/igny8/v1/terms/{id}/contentpushes rich content to term metaPOST /wp-json/igny8/v1/schema/bulk-updateupdates schema meta on postsPOST /wp-json/igny8/v1/gsc/status-syncupdates GSC status display- Structure visualizer admin page renders site taxonomy/cluster hierarchy
API Client
- Connection test via
GET /api/v1/system/status/returns success - All outbound requests include
Authorization: Bearer {api_key}header - 429 responses trigger exponential backoff (1s → 2s → 4s → 8s)
- Failed requests wrapped in
WP_Errorand logged
Security
- All inbound REST endpoints validate
X-IGNY8-API-KEYviahash_equals() - Incoming HTML sanitized via
wp_kses_post() - API key stored encrypted, displayed as
****...last4in admin - No API key exposed in client-side JavaScript or HTML source
6. CLAUDE CODE INSTRUCTIONS
Context Requirements
Before starting implementation:
- Read 03A (standalone plugin) — understand module manager, admin menu, DB tables
- Read existing WP Bridge v1.5.2 at
/data/app/igny8/plugins/wordpress/source/igny8-wp-bridge/ - Read 01A (SAG Data Foundation) for SAGBlueprint, SAGAttribute, SAGCluster models
- Read 01D (Setup Wizard) for blueprint generation flow that triggers sync
- Read 02B (Taxonomy Term Content) for term content that pushes via
/terms/{id}/content - Read 01G (SAG Health Monitoring) for health scoring context
Execution Order
Content Sync module (6 files) → SAG Structure module (6 files) → API Client → Admin UI views
Critical Rules
- All IGNY8 IDs are integers —
igny8_content_id,cluster_id,term_idare all integer (BigAutoField), never UUIDs - IGNY8 model names are PLURAL — Clusters, Keywords, Tasks, ContentIdeas, Images, Content (stays singular)
- Connected modules only load when
igny8_api_connectedistrue - REST security — every inbound endpoint validates
X-IGNY8-API-KEYwithhash_equals() - No blocking — all API calls and sync processing via WP Cron, never on page load
- Image downloads — use
wp_remote_get()for fetching,wp_handle_sideload()for attachment creation - Taxonomy registration — use
register_taxonomy()with propershow_in_rest => truefor block editor support - Term creation — use
wp_insert_term(), not direct DB insert
File Creation Order
1. includes/modules/content-sync/class-sync-module.php
2. includes/modules/content-sync/class-content-mapper.php
3. includes/modules/content-sync/class-image-downloader.php
4. includes/modules/content-sync/class-sync-queue.php
5. includes/modules/content-sync/class-content-puller.php
6. includes/modules/content-sync/class-publish-scheduler.php
7. includes/modules/sag/class-sag-module.php
8. includes/modules/sag/class-blueprint-sync.php
9. includes/modules/sag/class-taxonomy-builder.php
10. includes/modules/sag/class-term-builder.php
11. includes/modules/sag/class-cluster-manager.php
12. includes/modules/sag/class-structure-visualizer.php
13. includes/class-api-client.php
14. includes/admin/views/sync-queue.php
15. includes/admin/views/blueprint-review.php
16. includes/admin/views/structure-visualizer.php
Cross-References
| Doc | Relationship |
|---|---|
| 03A WP Plugin Standalone | Base plugin — module manager, DB tables, admin menu, igny8() singleton |
| 01A SAG Data Foundation | SAGBlueprint, SAGAttribute, SAGCluster models — data source for Module 12 |
| 01B SAG Blueprint Engine | Blueprint generation that produces data synced to WordPress |
| 01D Setup Wizard | Blueprint generation triggers POST /sag/sync-blueprint to WordPress |
| 01G SAG Health Monitoring | Health scoring data available in connected mode intelligence module |
| 02B Taxonomy Term Content | Generates term content pushed via POST /terms/{id}/content |
| 02C GSC Integration | GSC metrics pushed via POST /gsc/status-sync |
| 02D Linker Internal | SAGLink data feeds connected mode auto-linker in Module 6 |
| 02G Rich Schema SERP | Schema data pushed via POST /schema/bulk-update |
| 02H Socializer | SocialAccount OAuth feeds connected mode auto-poster in Module 8 |
| 03C Companion Theme | Theme consumes blueprint data, term meta, cluster navigation |