Custom field types

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 against includes/forms-manager/form-data-manager.php. The build-time shaping is done in mam_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_handlermam_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_pad and 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.
  • type strings must match exactly between server and client. Snake_case both sides.
  • The form cache is form_cache post meta, not an option. Invalidate with delete_post_meta( $post_id, 'form_cache' ) (the framework itself does this in submit-app-form.php after a submission).
  • Mobile client coordination is required. Server-side registration alone doesn’t make the field render.

  • 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
Was this article helpful?
Contents

    Need Support?

    Can't find the answer you're looking for? Don't worry we're here to help!