Skip to content

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 readme

The 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

MethodReturnPurpose
isActive()boolReturn true if your field plugin is active
getName()stringHuman-readable plugin name
getVersion()stringPlugin version string
getCustomPostTypes()arrayCPTs registered by the plugin
getCustomTaxonomies()arrayTaxonomies registered by the plugin
getFieldGroups()arrayAll field group configurations
getFieldGroupsForPostType(string $postType)arrayField groups for a specific CPT
getFields($fieldGroupId)arrayFields within a field group
getFieldsForPostType(string $postType)arrayAll fields for a CPT across all groups
saveFieldValue(int $postId, string $fieldName, $value)boolSave a generated field value to a post
getFieldConfig(string $fieldNameOrKey)?arrayGet field configuration by name or key
mapFieldTypeToFaker(array $field)stringMap a plugin field type to a Faker method
getSupportedFieldTypes()arrayList of field type slugs the adapter handles
setCptContext(string $slug, ?string $label)selfSet 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

MethodReturnPurpose
getProviderKey()stringUnique provider key (e.g. 'my_ai')
getProviderName()stringDisplay name shown in Settings UI
isAvailable()boolWhether provider has an API key and is enabled
isEnabled()boolWhether provider is enabled (regardless of API key)
getMaskedApiKey()stringAPI key masked for safe display
detectFieldType(...)?arrayDetect the type of a single field
detectFieldsBatch(...)?arrayDetect field types for all fields of a CPT in one call
detectFieldsBatchWithConfig(...)?arrayBatch detection with complete Faker configurations
generateTitleTemplates(...)?arrayGenerate title templates for a CPT
generateCptContext(...)?arrayGenerate context data for a CPT
testConnection()arrayTest 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.

Released under the GPL2 License. wpfaker.com