Goal
Register a custom Gravity Forms field type that the mobile app can render and that round-trips submissions correctly.
Background
Gravity Forms ships with standard field types (text, email, phone, address, choice, file upload, etc.). Some customer flows need a field type that doesn’t exist out of the box — a signature pad, a barcode scanner, a “select from my chat threads” picker, a multi-photo capture, etc.
Registering a custom field type for the mobile app requires two hooks. Forgetting one breaks the round trip silently:
| Hook | Direction | Purpose |
|---|---|---|
mam_form_manager_process_field_type_{type} |
App → server (submit-time) | Process the submitted value for a custom field type. Fires in mam_form_manager_form_processor::map_values_to_fields() with signature ( $field_value, $form_field_value, $field ) (3 args) |
Build-time transform (mam_populate_gravity_form, or a mam_form_manager_content_class_{type} field filter) |
Build → app | Translate the field’s GF schema into the mobile-renderable shape so the app knows how to render it |
Note:
mam_form_manager_process_field_type_{type}is a submit-time value processor, not the build-time schema transform — verify againstincludes/forms-manager/form-data-manager.php. The build-time shaping is done inmam_populate_gravity_form/ the content-class field filters (see Hook reference).
Steps
1. Decide on the field-type slug
Pick a string slug — signature_pad, barcode_scan, chat_picker. Use snake_case. This becomes the {type} in the dynamic filter name.
2. Register the submit-time value processor
add_filter( 'mam_form_manager_process_field_type_signature_pad',
function ( $field_value, $form_field_value, $field ) {
// $form_field_value is the raw submitted value; return the processed
// value to store against the field slug.
return sanitize_text_field( $form_field_value );
},
10, 3
);
The returned value becomes $field['value'] in the submission pipeline. This hook fires at submit-time, per field, only for the custom {type} in the dynamic filter name.
The build-time schema→mobile-shape transform is a separate concern (mam_populate_gravity_form). The mobile client team needs to know about the new type value — coordinate with them; adding a string without client support is a no-op.
3. Register the per-form result handler
The simplest approach: register a per-form submission filter that handles the custom field for that form’s specific instance. The framework calls it as apply_filters( 'mam_for_gravity_forms_form_submitted_42', $form_id, $post_id, $values ), so the handler receives ( $form_id, $post_id, $values ):
add_filter( 'mam_for_gravity_forms_form_submitted_42', function ( $form_id, $post_id, $values ) {
// $values is keyed by field slug: [ slug => [ 'value' => x, ... ], ... ].
foreach ( $values as $slug => $field ) {
if ( 'signature' !== $slug ) {
continue;
}
$value = $field['value'] ?? '';
// Validate. For signature_pad, value is base64 PNG.
if ( ! preg_match( '#^data:image/png;base64,#', $value ) ) {
// Build an error result envelope for the app.
return array( 'status' => 'error', 'message' => 'Signature is required.' );
}
// Optionally persist $post_id media attachment, etc.
}
return array( 'status' => 'success', 'process_normal' => false, 'type' => 'go_home', 'message' => 'Saved.' );
}, 10, 3 );
For a globally-registered field type (used across many forms), register the submit-time processor via mam_form_manager_process_field_type_{type} (Step 2), which the standard handler (mam_gf_standard_form_handler → mam_form_manager_form_processor) dispatches to automatically.
4. Add the field to the form
In Gravity Forms, the easiest path is to use a hidden text field (or a custom HTML field) and tag it with customFieldType=signature_pad via per-field special-handling. Configure this in Mobile App Manager → Forms → [your form] → Special handling.
5. Invalidate the form cache
The transformed form payload is cached as form_cache post meta on the associated post. Invalidate it by deleting that meta:
delete_post_meta( $post_id, 'form_cache' );
(There is no mam_form_manager_cache_manager::invalidate() method — mam_form_manager_cache_manager only exposes is_form_in_array() / add_or_update_form_in_array() over the in-memory $local_app_form_array.) Cache invalidation is the most common cause of “I made the change but the app still shows the old field.”
6. Coordinate with the mobile client
The mobile app needs to know how to render signature_pad. Without client support, the field shows as an unknown type or falls back to a text input. New field types require a coordinated mobile release.
Verification
- The form’s mobile JSON includes a field with
type: signature_padand the build-time settings - Submitting the form with a valid signature succeeds (entry inserted, confirmation returned)
- Submitting with an invalid signature returns a structured error
- The cache invalidates when the per-field special handling is changed
Gotchas
- Two hooks, one will silently break. A build-time transform with no submit-time handler accepts any value. A submit-time handler with no build-time transform shows the GF native field, which the app may not know how to render.
typestrings must match exactly between server and client. Snake_case both sides.- The form cache is
form_cachepost meta, not an option. Invalidate withdelete_post_meta( $post_id, 'form_cache' )(the framework itself does this insubmit-app-form.phpafter a submission). - Mobile client coordination is required. Server-side registration alone doesn’t make the field render.
Related articles
- Forms manager overview
- Form submission lifecycle
- Form cache and invalidation
- Hook: mam_form_manager_process_fieldtype{type}
- Hook: mam_for_gravity_forms_formsubmitted{id}
- Recipe: Register a custom field type (companion admin recipe)
Metadata
| Field | Value |
|---|---|
| Article type | Recipe (Developer) |
| Plugin slug | mam-main |
| Applies to plugin version | 2.1.11+ |
| Category | Extending MAM Suite |
| Audience | PHP developer |
| Estimated time | 30–60 minutes |
| Last verified | 2026-05-02 |
