Sync a custom field value to an external system on save
When a custom field value is saved in Benecaster, this hook fires immediately with the field ID, object ID, object type slug, and new value — including when a value is cleared. It fires once per field per save, not once per batch, so each change produces its own event. Use the object type slug to filter to the specific post type you care about (episode, guest, or other), then push the updated value to a CRM, CDP, or external content system in real time — no polling or scheduled sync required.
When to Use This
Use benecaster_field_value_saved when:
-
You need to react to a specific field changing — not all fields, just one
-
You want to sync data to an external system that has its own record per field (a CRM contact property, a product attribute, a content platform field)
-
Your integration cares about individual field-level events rather than episode-level events
Use benecaster_episode_field_values_updated instead when:
-
You want one callback after all field changes in a save batch are committed
-
You need to know the full set of changed fields before acting (e.g. to batch a single API call covering all changes)
How It Works
The action passes the field ID, the object ID, the CPT slug, and the saved value. Guard on the CPT slug first, then on the specific field IDs you track, and return early for everything else — this hook fires for every field save on every registered CPT. The recipe covers two shapes:
-
Syncing guest fields to a CRM. Map your Benecaster field IDs to the CRM’s property keys, look up the linked contact ID from post meta, and PATCH the change. Send the request non-blocking so a slow or failing API doesn’t hold up the save response, and translate a cleared field into whatever your API expects for “empty” rather than passing a null literal.
-
Invalidating a page cache. A much lighter use — check for one CPT and one field ID, delete the relevant transient, done.
Notes
The value is null when a field is cleared. When a podcaster removes a value from a field and saves, the stored row is deleted and the action fires with $value = null. Always check for null before sending to external systems — most APIs expect an empty string or a delete operation rather than a null literal.
This hook fires for all CPTs. Check the CPT slug for benecaster_episode or benecaster_guest as appropriate. A missing CPT guard means your callback fires for every field save across every registered CPT.
Send external HTTP requests non-blocking. The hook fires synchronously during the save request, so a slow or failing external API blocks the save response. Fire and forget unless you genuinely need to inspect the response.
For batch processing, prefer benecaster_episode_field_values_updated. If you need to know all the fields that changed in a single save before acting, that action fires once per request after all field writes complete and provides the full list of changed field IDs. benecaster_field_value_saved fires once per field, so a save that changes five fields fires your callback five times.
Related
- Custom Fields — overview of the Field Groups system for podcasters
Code
<?php
add_action( 'benecaster_field_value_saved', function (
int $field_id,
int $object_id,
string $cpt_slug,
mixed $value
): void {
if ( 'benecaster_guest' !== $cpt_slug ) {
return;
}
$crm_field_map = [
42 => 'crm_booking_url',
43 => 'crm_preferred_name',
];
if ( ! isset( $crm_field_map[ $field_id ] ) ) {
return;
}
$guest_id = get_post_meta( $object_id, '_my_crm_contact_id', true );
if ( ! $guest_id ) {
return;
}
wp_remote_post( 'https://api.my-crm.example.com/contacts/' . $guest_id, [
'method' => 'PATCH',
'headers' => [ 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . MY_CRM_API_KEY ],
'body' => wp_json_encode( [ $crm_field_map[ $field_id ] => $value ] ),
'timeout' => 5,
'blocking' => false,
] );
}, 10, 4 );
Hooks Used
Need this built rather than just documented? See our services →