AIPromptTheory Suite · Free & Educational

Engine.

The content engine under your site's hood. AI-powered article campaigns that research, write, illustrate and publish on schedule — using your prompts and your choice of five AI providers. Plus the complete guide to how we built it.

The pitch

Everything Engine does

Autoblogging done responsibly: your prompts, your editorial gates, your provider keys — with the machinery to run it hands-free once you trust it.

🗂️ Campaigns

  • Keyword lists, custom prompts & writing personality per campaign
  • Article format & length controls, content variations
  • Daily or custom schedules; pause/resume per campaign
  • Category rules for automatic placement
  • Duplicate-title detection — no accidental reruns

🤖 AI providers

  • OpenAI, Claude, Gemini, Grok & DeepSeek
  • Per-campaign provider and model selection
  • One abstract provider class — add new APIs in ~50 lines
  • API keys encrypted at rest (AES-256-CBC)
  • Key test button so you know it works before a campaign runs

⏱️ Pipeline

  • Content queue with pending → approved → published flow
  • Draft-first mode for human review, or full auto-publish
  • Three WP-Cron workers: campaign checks, queue processing, log cleanup
  • Generate-now button when you can't wait for cron
  • Failed items logged with the exact error, retryable

🚀 Publishing extras

  • DALL·E featured images with Pexels fallback
  • SEO schema JSON attached to every generated post
  • Social-media snippets generated alongside the article
  • Editorial calendar view + full activity log
  • Dashboard with campaign health at a glance

Chapter 1

The campaign model: recipes, not buttons

The core abstraction is the campaign — a stored recipe that says what to write about (keywords), how to write it (prompt, personality, format, length, variations), who writes it (provider + model), where it lands (category rules, post status) and when (schedule). Once saved, the campaign runs itself; you manage recipes, not posts.

That one design decision shapes everything else in the plugin: campaigns are rows, runs are queue items, and every action is logged against its campaign — so "why did this post happen?" always has an answer.

Editorial honesty. Auto-publishing AI text with no review is how sites lose reader trust. Engine defaults new campaigns to draft status — full-auto is a choice you make deliberately, per campaign, after you've seen what it produces.

Chapter 2

Four tables: campaigns, queue, logs, keys

Engine's state lives in four custom tables: awp_campaigns (the recipes, with status and next-run time), awp_content_queue (every generated piece and its lifecycle), awp_activity_logs (who did what, when, with what result) and awp_api_keys (encrypted provider credentials).

The campaign row — a recipe with a clock
CREATE TABLE wp_awp_campaigns (
  id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  name varchar(255) NOT NULL,
  type varchar(50) NOT NULL,
  status varchar(20) NOT NULL DEFAULT 'active',
  settings longtext,                -- the whole recipe, JSON
  next_run datetime DEFAULT NULL,   -- the clock
  PRIMARY KEY (id),
  KEY status (status),
  KEY next_run (next_run)
);

The next_run index is the heartbeat: the cron worker asks one cheap question — "which active campaigns are due?" — and the database answers from the index. Settings are a JSON blob on purpose: campaign options evolve fast, and schema migrations for every new toggle would be madness.

Chapter 3

The provider factory: five AIs, one interface

OpenAI, Claude, Gemini, Grok and DeepSeek all speak different dialects of "give me an article". Engine hides that behind one abstract class — each provider implements generate_content(), and shared logic (prompt building, JSON parsing, error normalisation) lives in the parent.

class-aipt-engine-ai-factory.php
abstract class AIPT_Engine_AI_Provider {
    abstract public function generate_content( $prompt, $args );
    // shared: build_prompt(), parse_json_response(), error handling
}

class AIPT_Engine_AI_Factory {
    public static function create( $provider = 'google_gemini', $model = null ) {
        switch ( $provider ) {
            case 'openai':   return new AIPT_Engine_OpenAI( $model );
            case 'claude':   return new AIPT_Engine_Claude( $model );
            case 'grok':     return new AIPT_Engine_Grok( $model );
            case 'deepseek': return new AIPT_Engine_DeepSeek( $model );
            default:         return new AIPT_Engine_Gemini( $model );
        }
    }
}

Adding a sixth provider is a ~50-line subclass and one case. The campaign UI reads the provider list dynamically, so new engines appear in the dropdown automatically. This is the open/closed principle earning its keep in WordPress.

Chapter 4

API keys: encrypted at rest, tested before use

API keys are credentials with a credit card attached — storing them as plain options is negligence. Engine generates a per-site 256-bit key on activation and encrypts every provider key with AES-256-CBC and a random IV before it touches the database.

class-aipt-engine-settings.php — at-rest encryption
$iv        = openssl_random_pseudo_bytes( 16 );
$encrypted = openssl_encrypt( $key, 'aes-256-cbc',
                              AIPT_ENGINE_ENCRYPTION_KEY, 0, $iv );
// store iv + ciphertext; decrypt only in memory, only when calling the API
Scar #1 — guard the master key with your life. When we rebranded the plugin, the option holding the per-site encryption key was renamed. Without a migration, every stored provider key would have decrypted to garbage — silently. The fix: on boot, if the new key option is empty but the old one exists, copy it over before anything tries to decrypt. If you ever rename an encryption key's storage location, migrate it first, deploy second.

Chapter 5

The queue & three cron workers

Generation is slow (an AI round-trip can take 30+ seconds) so nothing generates inside a page request. Three WP-Cron workers split the labour:

  1. awp_check_campaigns (hourly) — finds campaigns whose next_run has passed, asks the provider for content, and files the result in the queue as pending. Duplicate titles are detected and skipped with a logged warning.
  2. awp_process_queue (hourly, offset) — takes approved items, creates the WordPress post (draft or publish per campaign), attaches images, schema and snippets, and marks the item completed — or failed with the exact error message for retry.
  3. awp_cleanup_logs (daily) — prunes old activity logs so the table never becomes the biggest thing in your database.

The status flow — pending → approved → completed / failed — is the editorial gate: in review mode a human clicks approve; in full-auto the processor approves its own work. Either way the audit log records it.

Chapter 6

Publishing extras: images, schema, snippets

A wall of AI text isn't a post. When a queue item publishes, Engine also:

  1. Generates a featured image via DALL·E — with an automatic Pexels stock-photo fallback when image generation fails or is disabled, so posts never ship naked.
  2. Attaches SEO schema — a JSON-LD block stored in post meta and injected on render, so generated articles arrive structured-data-ready.
  3. Writes social snippets — short share-ready blurbs stored alongside the post, one less thing to write when you promote it.
  4. Tags its work — every generated post carries a meta flag, so you can query, audit or bulk-manage AI content separately from human writing. Transparency is a feature.

Chapter 7

Mission control: dashboard, calendar, logs

Six admin screens in the suite's shared dark/light theme: a dashboard with campaign health and recent activity; campaigns for creating and managing recipes; the queue with inline approve/edit/reject; an editorial calendar showing what's scheduled to land when; logs for the full audit trail; and settings for provider keys (with a test button that verifies a key against the live API before you bet a campaign on it).

The calendar is the sleeper feature: autoblogging goes wrong when you lose track of volume. Seeing next week as a grid — three posts Tuesday, nothing Thursday — turns a firehose into an editorial plan.

Chapter 8

Shipping it — including the scars

Scar #2 — the rename trap, again. Engine's class files carry the plugin slug in their names. A find-and-replace rebrand rewrites the require_once strings but not the files on disk — instant fatal. We renamed the files and the references in one pass and verified every require resolves before zipping. If you rebrand this plugin (please do), follow the map below and check requires last.
Scar #3 — check your extensions. Engine needs OpenSSL for key encryption. Rather than fataling on a host without it, the bootstrap checks extension_loaded( 'openssl' ) and shows a polite admin notice instead. Fail loudly, fail early, fail politely.

Plus the standing checklist: prepared statements, nonce + capability checks on every AJAX action, escaped output, sanitised campaign settings, translation-ready strings, and cron events cleared on deactivation.

Make it yours

Rebrand it. Seriously, we encourage it.

The rename map for Engine — change these consistently (and read Scar #1 and #2 first):

WhatOursYours
Plugin folder & main fileaipt-engine/your-brand-engine/
Plugin Name headerAIPromptTheory EngineYourBrand Engine
Class prefix & file namesAIPT_Engine_* / class-aipt-engine-*.phprename files and requires together
Admin page slugsaipt-engine-dashboardyour-brand-engine-dashboard
Encryption key optionaipt_engine_encryption_keyrename with a copy-migration — or lose every stored API key
DB tables & cron hookswp_awp_*, awp_*keep them — neutral names, zero migration risk

Free, as in education

Get Engine + request the add-on pack

Engine is free. The add-ons are free too — we build them in the order people ask. Tell us which one you want next and we'll email you when it ships.

No spam, no upsells — you'll get the plugin zip and a ship-notification. That's it.