Appearance
Addon Development
WPfaker is designed to be extended. An addon is simply a standard WordPress plugin that hooks into WPfaker's lifecycle to add new capabilities — a custom field adapter that teaches WPfaker how to read fields from a plugin it does not natively support, an AI provider that connects an alternative language model for field type detection, or a set of generation hooks that modify how content is created. The addon system is built entirely on standard WordPress hooks (do_action and apply_filters), which means there is no proprietary API to learn, no SDK to install, and no registration portal to sign up for. If you know how to write a WordPress plugin and use add_action and add_filter, you already know how to build a WPfaker addon.
Getting Started
A WPfaker addon is a standard WordPress plugin. There is no special file format, no manifest file, and no build step. The minimum viable addon is a single PHP file with a plugin header and one add_action call. More complex addons that provide field adapters or AI providers will typically follow a directory structure like this:
wpfaker-my-addon/
├── wpfaker-my-addon.php # Plugin entry point
├── src/
│ ├── MyFieldAdapter.php # FieldPluginAdapterInterface implementation
│ └── MyAiProvider.php # AiProviderInterface implementation (optional)
└── readme.txt # Standard WordPress plugin readmeThe entry file contains the standard WordPress plugin header and the bootstrap logic that connects your addon to WPfaker. The src/ directory holds your adapter and provider classes. You can organize the internals however you prefer — WPfaker does not impose any structure beyond requiring that your code waits for the correct hooks before executing.
Entry Point
Every addon must wait for the wpfaker_loaded action before doing anything. This action fires on plugins_loaded after WPfaker has fully initialized its core classes, registered its autoloader, and set up its internal services. If you attempt to reference WPfaker classes or call WPfaker methods before this action fires, you will encounter fatal errors because the classes will not yet be available.
The standard entry point pattern nests the registration hooks inside the wpfaker_loaded callback. This ensures that your code only runs when WPfaker is active and fully loaded:
php
<?php
/**
* Plugin Name: WPfaker My Addon
* Description: Adds support for My Field Plugin to WPfaker.
* Version: 1.0.0
* Requires Plugins: wpfaker
*/
use WPFaker\Services\AdapterFactory;
// Wait for WPfaker to fully initialize
add_action('wpfaker_loaded', function (string $version) {
// Register field adapters when WPfaker asks for them
add_action('wpfaker_register_adapters', function () {
AdapterFactory::register('my_field_plugin', MyFieldAdapter::class);
});
// Register AI providers when WPfaker asks for them (optional)
add_action('wpfaker_register_ai_providers', function () {
// AiProviderFactory::register('my_provider', MyAiProvider::class, 'My AI Service');
});
});The nesting is intentional and important. The outer wpfaker_loaded callback guarantees that WPfaker's autoloader is active and its classes are available. The inner wpfaker_register_adapters callback ensures that your adapter is registered at the correct point in WPfaker's initialization sequence, after the adapter factory is ready to accept registrations but before field detection begins.
WARNING
Never call AdapterFactory::register() or AiProviderFactory::register() outside of their respective hooks. Calling them too early will fail because the factories are not yet initialized. Calling them too late will cause your adapter or provider to be silently ignored because the registration window has already closed.
Custom Field Adapters
A field adapter teaches WPfaker how to interact with a specific field plugin. When WPfaker needs to generate content for a post type, it asks each registered adapter whether it has fields for that post type. Adapters that respond affirmatively provide a list of field definitions — names, types, configurations, and validation rules — that WPfaker uses to generate appropriate fake data. After generation, WPfaker calls the adapter again to save the generated values using the field plugin's native storage mechanism.
Every adapter must implement the FieldPluginAdapterInterface from the WPFaker\Contracts namespace. The interface defines fourteen methods that cover the full lifecycle of field detection, value generation, and data persistence. Your adapter class receives a FakerService instance through its constructor, which provides access to WPfaker's configured FakerPHP generator with the correct locale and seed settings.
Interface Methods
| Method | Return | Purpose |
|---|---|---|
isActive() | bool | Return true if your field plugin is active |
getName() | string | Human-readable plugin name |
getVersion() | string | Plugin version string |
getCustomPostTypes() | array | CPTs registered by the plugin |
getCustomTaxonomies() | array | Taxonomies registered by the plugin |
getFieldGroups() | array | All field group configurations |
getFieldGroupsForPostType(string $postType) | array | Field groups for a specific CPT |
getFields($fieldGroupId) | array | Fields within a field group |
getFieldsForPostType(string $postType) | array | All fields for a CPT across all groups |
saveFieldValue(int $postId, string $fieldName, $value) | bool | Save a generated field value to a post |
getFieldConfig(string $fieldNameOrKey) | ?array | Get field configuration by name or key |
mapFieldTypeToFaker(array $field) | string | Map a plugin field type to a Faker method |
getSupportedFieldTypes() | array | List of field type slugs the adapter handles |
setCptContext(string $slug, ?string $label) | self | Set post type context for field name detection |
Registration
Register your adapter during the wpfaker_register_adapters hook by calling AdapterFactory::register() with a unique key and your adapter's fully qualified class name:
php
add_action('wpfaker_register_adapters', function () {
AdapterFactory::register('my_field_plugin', \MyAddon\MyFieldAdapter::class);
});WPfaker instantiates your adapter class automatically, passing a FakerService instance to the constructor. You do not need to create the instance yourself.
Custom AI Providers
An AI provider connects WPfaker to an alternative language model service for field type detection. WPfaker ships with built-in support for OpenAI and Anthropic, but the provider system is open — you can add support for any AI service that accepts a text prompt and returns a structured response. When a field's name does not match any of WPfaker's 700+ built-in patterns, the AI detection tier sends the field name to the configured AI provider for analysis. Your custom provider handles the API communication, prompt formatting, and response parsing for your chosen service.
Every AI provider must implement the AiProviderInterface from the WPFaker\Contracts namespace. The interface defines eleven methods that cover API configuration, request handling, response parsing, and capability reporting.
Interface Methods
| Method | Return | Purpose |
|---|---|---|
getProviderKey() | string | Unique provider key (e.g. 'my_ai') |
getProviderName() | string | Display name shown in Settings UI |
isAvailable() | bool | Whether provider has an API key and is enabled |
isEnabled() | bool | Whether provider is enabled (regardless of API key) |
getMaskedApiKey() | string | API key masked for safe display |
detectFieldType(...) | ?array | Detect the type of a single field |
detectFieldsBatch(...) | ?array | Detect field types for all fields of a CPT in one call |
detectFieldsBatchWithConfig(...) | ?array | Batch detection with complete Faker configurations |
generateTitleTemplates(...) | ?array | Generate title templates for a CPT |
generateCptContext(...) | ?array | Generate context data for a CPT |
testConnection() | array | Test the API connection |
Registration
Register your AI provider during the wpfaker_register_ai_providers hook by calling AiProviderFactory::register() with a unique key, your provider's class name, and a display name:
php
use WPFaker\Services\AiProviderFactory;
add_action('wpfaker_register_ai_providers', function () {
AiProviderFactory::register('my_ai_service', \MyAddon\MyAiProvider::class, 'My AI Service');
});Once registered, your provider automatically appears in the AI Provider dropdown on the WPfaker Settings page. No additional UI code is required on your part — WPfaker handles the settings display for all registered providers.
Hook Reference
WPfaker exposes a comprehensive set of actions and filters that let addons participate in every stage of the generation lifecycle. These hooks follow WordPress conventions — actions for side effects, filters for data modification — and are documented here with their full signatures, parameter descriptions, and practical examples.
Actions
wpfaker_loaded fires on plugins_loaded after WPfaker has fully initialized its autoloader, services, and internal state. This is the primary entry point for all addons. The action receives the current WPfaker version string as its only parameter, which you can use for version-gating features or logging compatibility information.
php
add_action('wpfaker_loaded', function (string $version) {
if (version_compare($version, '3.0.0', '<')) {
return; // Require WPfaker 3.0+
}
// Safe to use WPfaker classes here
add_action('wpfaker_register_adapters', function () {
AdapterFactory::register('my_plugin', MyAdapter::class);
});
});wpfaker_register_adapters fires during Plugin::init() after WPfaker's core adapters have been registered but before field detection begins. This is the designated moment to call AdapterFactory::register() with your custom adapter. Registering outside of this hook will either fail (too early) or be silently ignored (too late).
php
add_action('wpfaker_register_adapters', function () {
AdapterFactory::register('my_field_plugin', MyFieldAdapter::class);
});wpfaker_register_ai_providers fires immediately after wpfaker_register_adapters, during the same initialization sequence. This is when you call AiProviderFactory::register() to add your custom AI provider. The timing ensures that all adapters are registered before any AI-powered field detection could potentially begin.
php
add_action('wpfaker_register_ai_providers', function () {
AiProviderFactory::register('my_ai', MyAiProvider::class, 'My AI Service');
});wpfaker_activate fires when WPfaker itself is activated through the WordPress plugin activation process. Use this hook to perform one-time setup tasks for your addon — creating custom database tables, setting default option values, or scheduling cron events. This hook fires during WordPress plugin activation, so the full WordPress API is available.
php
add_action('wpfaker_activate', function () {
// Create addon-specific options
add_option('my_addon_version', '1.0.0');
add_option('my_addon_log_enabled', true);
});wpfaker_deactivate fires when WPfaker is deactivated. It receives a boolean parameter indicating whether the user chose to delete all WPfaker data during deactivation. When $deleteData is true, your addon should clean up its own data (drop tables, delete options, remove files). When it is false, you should leave your data intact so it persists if WPfaker is reactivated later.
php
add_action('wpfaker_deactivate', function (bool $deleteData) {
if ($deleteData) {
delete_option('my_addon_version');
delete_option('my_addon_log_enabled');
// Drop custom tables, remove files, etc.
}
});wpfaker_after_generate_item fires after each individual item is generated and saved to the database. It receives the content type (e.g., 'post', 'term', 'user'), the ID of the created item, the current index within the batch (zero-based), the total number of items being generated, and the full options array that was passed to the generation request. This hook is ideal for per-item post-processing like attaching additional metadata, triggering external API calls, or logging individual creation events.
php
add_action('wpfaker_after_generate_item', function (
string $type,
int $itemId,
int $index,
int $total,
array $options
) {
if ($type === 'post' && $options['post_type'] === 'product') {
// Add custom tracking meta to each generated product
update_post_meta($itemId, '_generated_batch_index', $index);
update_post_meta($itemId, '_generated_batch_size', $total);
}
}, 10, 5);wpfaker_after_generate fires once after an entire generation batch completes. It receives the content type, an array of all created IDs, and the full options array. This hook is suited for batch-level operations — rebuilding search indexes, sending a single summary notification, clearing caches, or logging aggregate statistics. Unlike wpfaker_after_generate_item, this hook fires only once per batch regardless of how many items were generated.
php
add_action('wpfaker_after_generate', function (
string $type,
array $ids,
array $options
) {
// Log the completed batch
error_log(sprintf(
'WPfaker generated %d %s items of type "%s"',
count($ids),
$type,
$options['post_type'] ?? 'n/a'
));
// Clear object cache after bulk generation
wp_cache_flush();
}, 10, 3);Filters
wpfaker_post_data filters the complete post data array immediately before it is passed to wp_insert_post(). This is the most powerful filter for modifying generated content because it gives you access to the entire post payload — title, content, excerpt, status, author, date, and all other fields that wp_insert_post() accepts. The filter receives five parameters: the post data array, the post type slug, the current index within the batch, the total batch size, and the full options array.
php
add_filter('wpfaker_post_data', function (
array $postData,
string $postType,
int $index,
int $total,
array $options
) {
// Force all generated events to draft status
if ($postType === 'event') {
$postData['post_status'] = 'draft';
}
// Add a sequential reference number to the title
if ($postType === 'invoice') {
$postData['post_title'] = sprintf('INV-%04d — %s', $index + 1, $postData['post_title']);
}
return $postData;
}, 10, 5);wpfaker_field_value filters each generated field value before it is saved to the database. This filter fires once per field per item, giving you fine-grained control over individual field values without needing to build a full adapter. The filter receives the generated value, the field configuration array (including name, type, and key), the post type slug, and the post ID.
php
add_filter('wpfaker_field_value', function (
mixed $value,
array $config,
string $postType,
int $postId
) {
// Override the 'event_capacity' field to always be a multiple of 10
if ($config['name'] === 'event_capacity') {
return round($value / 10) * 10;
}
// Ensure prices are never below 9.99
if ($config['name'] === 'price' && $value < 9.99) {
return 9.99;
}
return $value;
}, 10, 4);wpfaker_adapter_priority filters the priority array that determines the order in which field adapters are checked when WPfaker scans a post type for custom fields. The default priority order is ['acfe', 'acf_pro', 'acf', 'jet_engine', 'meta_box', 'acpt', 'native_meta']. The first adapter that returns true from hasFields() for a given post type wins, and its fields are used for generation. By filtering this array, you can insert your custom adapter at any position — including the front, to ensure it takes precedence over built-in adapters.
php
add_filter('wpfaker_adapter_priority', function (array $priority) {
// Insert custom adapter at the front so it is checked first
array_unshift($priority, 'my_field_plugin');
return $priority;
});wpfaker_field_name_detection_enabled filters the boolean that controls whether WPfaker's smart field name detection runs during generation. By default this is true, meaning WPfaker analyzes field names against its pattern library and optionally queries an AI provider to determine the most appropriate data type. Returning false disables all name-based detection, causing every field to fall back to generic type-based generation — a text field gets random text, a number field gets a random number, and so on. This can be useful in controlled testing scenarios where you want deterministic, predictable output without any smart inference.
php
// Disable field name detection entirely
add_filter('wpfaker_field_name_detection_enabled', '__return_false');REST API
WPfaker includes a REST endpoint that reports information about registered addons and their status. A GET request to /wpfaker/v1/addons returns a JSON array listing each registered addon, its adapter or provider type, the associated field plugin's name and version, and whether the plugin is currently active. This endpoint follows the same authentication requirements as WPfaker's other REST API endpoints and is useful for diagnostic dashboards or automated compatibility checks.
Tips
AI-Assisted Addon Development
If you are building a WPfaker addon, the Claude Code Skill can significantly accelerate your development workflow. It understands WPfaker's internal architecture, can generate adapter boilerplate from a field plugin's source code, and helps you implement interface methods correctly. Point it at your target field plugin's code and ask it to scaffold a WPfaker adapter.
Registration Timing
Always register adapters inside the wpfaker_register_adapters hook and AI providers inside the wpfaker_register_ai_providers hook. Calling AdapterFactory::register() or AiProviderFactory::register() at any other point in the WordPress lifecycle — including directly in your plugin's main file, in an init action, or in a plugins_loaded callback that fires before wpfaker_loaded — will either throw an error because the factories are not yet available, or silently fail because the registration window has already closed.
Share Your Addon
Built an addon? We want to hear about it. We are building a featured addon section on the WPfaker website to showcase community-built extensions — field adapters, AI providers, generation hooks, and anything else that extends WPfaker.
If you have a working addon you would like to share, reach out to us at hello@wpfaker.com with a short description of what it does and a link to the source code. We will review it and add it to the directory.