Purpose
Per-field save filter for additional user profile fields registered via mam_add_fields_to_user_profile. Use this dynamic per-field hook — not the generic save hook — for per-field validation and persistence. Hooking the generic save and switching on field key is an anti-pattern that’s hard to extend.
Signature
$value = apply_filters(
'mam_user_roles_save_addl_user_profile_field_' . $key,
$value
);
| Parameter | Type | Description |
|---|---|---|
$value |
mixed | The submitted raw value |
Returns: mixed — the (possibly normalized) value.
The filter passes only
$value— no$user_id. Resolve the user being saved yourself (e.g.MAM_Current_Request::get_user_id()) before callingupdate_user_meta().
Example: validate and persist a loyalty id
add_filter( 'mam_user_roles_save_addl_user_profile_field_my_plugin_loyalty_id',
function ( $value ) {
$user_id = MAM_Current_Request::get_user_id();
// Normalize.
$clean = preg_replace( '/[^A-Z0-9]/i', '', (string) $value );
// Validate length.
if ( $clean !== '' && ( strlen( $clean ) < 6 || strlen( $clean ) > 12 ) ) {
// Don't persist invalid value; signal an error somehow
// (note: this filter doesn't have a structured error channel —
// use mam_user_roles_modify_user_profile_values_before_save for veto).
return get_user_meta( $user_id, 'my_plugin_loyalty_id', true );
}
// Persist (yes — explicitly call update_user_meta).
update_user_meta( $user_id, 'my_plugin_loyalty_id', $clean );
return $clean;
}
);
⚠️ You must call update_user_meta yourself. This filter doesn’t auto-persist. Returning a value alone won’t write it.
When to use vs. the broader hook
| Hook | Use when |
|---|---|
mam_user_roles_save_addl_user_profile_field_{key} (this) |
Single field, per-field save logic |
mam_user_roles_modify_user_profile_values_before_save |
Cross-field validation, veto, batch transforms |
The dynamic per-field hook is the recommended pattern. The broader filter is for cases where a save depends on multiple fields together.
Related: error signaling
This filter doesn’t have a structured error channel. To reject an invalid value with a user-facing message:
- Use
mam_user_roles_modify_user_profile_values_before_save(filter on the entire payload — return modified or veto) - Or use a per-form result builder that runs validation before the save (
mam_for_gravity_forms_form_result_form_{form-id}) for forms-driven profile updates
Gotchas
- You must persist explicitly. Returning a value doesn’t auto-write. Call
update_user_meta()inside the callback. {key}in the filter name matches the field’skeyfrommam_add_fields_to_user_profile. Mismatch silently doesn’t fire.- No error channel. Validation failures need a different path.
- Empty values are still passed through. Decide whether empty means “delete the meta” or “preserve existing”.
- Fires for every save, including no-op saves where the value didn’t change. Cheap callbacks only.
Related articles
- Hook: mam_add_fields_to_user_profile
- Hook: mam_user_roles_after_create_user
- Recipe: Customize onboarding
Metadata
| Field | Value |
|---|---|
| Article type | Hook Reference |
| Plugin slug | mam-main |
| Applies to plugin version | 2.1.11+ |
| Hook type | filter (dynamic — {key} is the field’s usermeta key) |
| Audience | PHP developer |
| Last verified | 2026-05-02 |
