Inject a dynamically generated field group
Prepend or append field groups generated at runtime — from external data, plugin state, or computed summaries — without storing them in the database. Synthetic groups (non-integer IDs) are display-only; persisting their values requires a separate table and REST endpoint in your add-on. Useful for read-only display panels, external data pulled at request time, or add-on-specific fields that only appear when the add-on is configured for the show.
When to Use This
Use benecaster_field_groups to inject a dynamic group when:
-
Your add-on manages its own data (post meta, a custom table, an external API) and wants to display it as editable fields alongside Benecaster’s built-in fields
-
You want a field group to appear only under certain conditions — when the add-on is configured, when the episode belongs to a specific show, or based on a capability check
-
You’re building a Sponsor Manager, Guest Manager, or similar add-on that integrates naturally with the episode editor
If you want to store values through the standard Benecaster field value system, create a real field group in the database instead. Synthetic groups are display-only — saving values for them requires a separate mechanism (see Notes below).
How It Works
The filter receives the array of groups about to be rendered, plus the CPT slug. Guard on the slug so you only inject into the editor you mean, guard again on whatever makes your add-on “active”, then append a group definition and return the array.
A group definition carries an id, a display name, the cpt_slug, a display_order (use a high number to append after stored groups), and a fields array. Each field needs an id, group_id, field_label, field_key, field_type, display_order, options, and required.
Use string IDs, not integers — that is what marks the group and its fields as synthetic. See the first note below.
Notes
Non-integer IDs are synthetic. Use a string ID (e.g. synthetic_sponsor) to flag the group as runtime-only. Integer IDs are assumed to be real database rows — using one for a synthetic group will cause unexpected behavior when the save endpoint validates field IDs.
Injected fields render on GET. When FieldGroupsController::get_field_values() encounters a group whose ID is non-numeric, it skips the database field lookup and preserves your injected fields directly. Your fields appear in the editor with any values your callback supplies — no database rows required.
Injected field IDs are rejected at save time. When the episode editor saves, POST /benecaster/v1/field-values/{cpt}/{id} validates all submitted field IDs against real, stored field definitions. Synthetic field IDs fail validation and their values are silently dropped. To persist values from synthetic groups, add a separate REST endpoint from your add-on that reads the submitted values and writes them to wherever your add-on stores its data (post meta, a custom table, an external API).
Hiding stored groups. You can also use this filter to remove groups you don’t want displayed — filter the incoming array by ID. Hidden groups remain in the database; their values are still returned by benecaster_get_field() and benecaster_get_fields().
The filter does not apply to the Field Groups list screen. benecaster_field_groups fires in FieldGroupsController::get_field_values() only — the admin screen that lists all field groups always shows stored groups from the database, unfiltered. Injecting a synthetic group does not make it appear in the Fields admin screen.
Related
- Custom Fields — overview of the Field Groups system for podcasters
Code
<?php
add_filter( 'benecaster_field_groups', function ( array $groups, string $cpt_slug ): array {
if ( 'benecaster_episode' !== $cpt_slug ) {
return $groups;
}
if ( ! function_exists( 'my_sponsor_plugin_active' ) || ! my_sponsor_plugin_active() ) {
return $groups;
}
$groups[] = [
'id' => 'synthetic_sponsor',
'name' => __( 'Sponsor Info', 'my-sponsor-plugin' ),
'cpt_slug' => $cpt_slug,
'display_order' => 999,
'field_count' => 0,
'fields' => [
[
'id' => 'synthetic_sponsor_name',
'group_id' => 'synthetic_sponsor',
'field_label' => __( 'Sponsor Name', 'my-sponsor-plugin' ),
'field_key' => 'sponsor_name',
'field_type' => 'text',
'display_order' => 0,
'options' => null,
'required' => false,
],
],
];
return $groups;
}, 10, 2 );
Hooks Used
Need this built rather than just documented? See our services →