Skip to main content

Register an add-on CPT with the custom field system

Premium Intermediate

Benecaster registers benecaster_episode with the field system automatically. Add-ons that introduce their own CPTs (e.g. Guest Manager’s benecaster_guest) must call benecaster_register_field_cpt() inside a benecaster_boot callback so the CPT appears in the Field Group editor’s “Attached CPT” dropdown. Also shows using useFieldValues and useSaveFieldValues hooks in a React editor panel for the new CPT.

When to Use This

  • Your add-on introduces a custom post type with its own editor screen

  • You want podcasters to be able to create Field Groups and attach them to that CPT via Benecaster → Fields

  • You want to render those field groups in your editor using the same tabbed field UI the episode editor uses

  • You want field values to be stored and retrieved through the standard benecaster_get_field() / benecaster_get_fields() API

Benecaster auto-registers benecaster_episode. Everything else must be registered explicitly at add-on boot.

How It Works

There are two halves — a one-line PHP registration and a React panel in your editor.

PHP — register the CPT at add-on boot. Call benecaster_register_field_cpt() inside a benecaster_boot callback, passing your CPT slug and a human-readable label. The label is what podcasters see in the “Attached CPT” dropdown of the Field Group editor.

React — fetch and save values in your editor. useFieldValues( cpt, objectId ) and useSaveFieldValues(), both exported from @benecaster/hooks/useFieldValues, accept any registered CPT slug. Pass yours and the record ID and you get back the same FieldGroupWithValues[] shape the episode editor uses, which the same field UI renders for you — no additional components required. Hold edited values in local state, and on save map them into an array of { field_id, value } pairs for the mutation.

useSaveFieldValues() POSTs to /benecaster/v1/field-values/{cpt}/{id}. That endpoint is already registered for every CPT once boot-time registration has happened, so there is nothing further to wire up on the server side.

Notes

Registration happens at boot, not on every request. benecaster_register_field_cpt() writes to an in-memory registry inside FieldRegistry. It fires once per request. Calling it outside a benecaster_boot callback risks running before the container is ready — always use the hook.

The benecaster_field_groups filter works for your CPT automatically. After registration, the filter fires with your CPT slug whenever the field editor loads. Add-ons can inject synthetic groups for your CPT using the same pattern as for episodes — see Inject a Dynamically Generated Field Group.

benecaster_get_field() and benecaster_get_fields() work for your CPT without any extra configuration. The REST endpoint and public functions respect CPT context because every stored field value carries the CPT slug it belongs to — field values are scoped per CPT automatically.

The useEpisodeFieldValues hook is a thin wrapper. It calls useFieldValues( 'benecaster_episode', episodeId ) internally. Your add-on calls useFieldValues directly with its own slug — no hook duplication needed.

Related

Code

<?php
// PHP — register the CPT at add-on boot
add_action( 'benecaster_boot', function ( \Benecaster\Container $container ) {
    benecaster_register_field_cpt( 'benecaster_guest', __( 'Guest', 'benecaster-guest-manager' ) );
} );

// React — fetch and save field values in a guest editor panel
// (see recipe page for full TSX example using useFieldValues / useSaveFieldValues)

View on GitHub →

Hooks Used

Need this built rather than just documented? See our services →