Skip to main content

Hooks Reference

Core Forms provides filters and actions throughout the form lifecycle for customization.

Filters

cf_validate_form

Validate form data before processing. Return an error code string to block submission.

add_filter( 'cf_validate_form', function( $error_code, $form, $data ) {
    // Pass through if another validator set an error
    if ( '' !== $error_code ) {
        return $error_code;
    }

    // Custom validation
    if ( empty( $data['agree_terms'] ) ) {
        return 'terms_required';
    }

    return ''; // Empty string = valid
}, 10, 3 );

Parameters: $error_code (string), $form (Form), $data (array)

cf_form_html

Modify the complete form HTML output (outer wrapper included).

add_filter( 'cf_form_html', function( $html, $form ) {
    return '<div class="custom-wrapper">' . $html . '</div>';
}, 10, 2 );

Parameters: $html (string), $form (Form)

cf_form_markup

Modify the inner form markup (the HTML between <form> tags).

add_filter( 'cf_form_markup', function( $markup, $form ) {
    // Append a disclaimer before the submit button
    $disclaimer = '<p class="disclaimer">By submitting, you agree to our terms.</p>';
    $markup = str_replace( '</form>', $disclaimer . '</form>', $markup );
    return $markup;
}, 10, 2 );

Parameters: $markup (string), $form (Form)

cf_schema_markup

Modify the HTML generated from the form schema before it is used as form markup.

add_filter( 'cf_schema_markup', function( $markup, $schema, $form ) {
    return $markup;
}, 10, 3 );

Parameters: $markup (string), $schema (FormSchema), $form (Form)

cf_form_default_settings

Set default values for form settings.

add_filter( 'cf_form_default_settings', function( $settings ) {
    $settings['save_submissions'] = true;
    $settings['redirect_url']     = '';
    $settings['display_mode']     = 'normal';
    return $settings;
} );

cf_form_default_messages

Set default form messages (success, error, validation).

add_filter( 'cf_form_default_messages', function( $messages ) {
    $messages['success'] = 'Thank you! We will be in touch.';
    $messages['error']   = 'Something went wrong. Please try again.';
    return $messages;
} );

cf_process_form_action_{type}

Process a custom action type. This is an action hook (despite the filter-like name) fired via do_action.

add_action( 'cf_process_form_action_my_crm', function( $settings, $submission, $form ) {
    // Send data to your CRM
    wp_remote_post( $settings['api_url'], [
        'body' => wp_json_encode( $submission->data ),
    ] );
}, 10, 3 );

cf_webhook_request_args

Modify the wp_remote_post arguments for webhook requests.

add_filter( 'cf_webhook_request_args', function( $args, $url, $submission ) {
    $args['headers']['Authorization'] = 'Bearer ' . MY_API_KEY;
    $args['timeout'] = 30;
    return $args;
}, 10, 3 );

cf_upload_max_filesize

Change the maximum upload file size (default: 8,000,000 bytes / 8 MB).

add_filter( 'cf_upload_max_filesize', function() {
    return 25 * 1024 * 1024; // 25 MB
} );

cf_create_user_allowed_roles

Restrict which roles the Create User action can assign.

add_filter( 'cf_create_user_allowed_roles', function( $roles ) {
    return [ 'subscriber', 'contributor' ];
} );

cf_template_tags

Add custom template tags for {{tag.field}} syntax.

add_filter( 'cf_template_tags', function( $tags ) {
    $tags['company'] = function( $field ) {
        return get_option( "company_{$field}", '' );
    };
    return $tags;
} );
// Usage: {{company.name}}, {{company.phone}}

cf_available_form_actions

Register custom action types in the Actions dropdown.

add_filter( 'cf_available_form_actions', function( $actions ) {
    $actions['my_action'] = 'My Custom Action';
    return $actions;
} );

Actions

cf_form_success

Fires after a successful, non-spam form submission. This is the primary hook for post-submission processing.

add_action( 'cf_form_success', function( $submission, $form ) {
    // Log, notify, integrate, etc.
    error_log( "Form {$form->ID} submitted by {$submission->data['email']}" );
}, 10, 2 );

Parameters: $submission (Submission), $form (Form)

cf_submission_inserted

Fires immediately after a submission is inserted into the database, before actions run.

add_action( 'cf_submission_inserted', function( $submission, $form ) {
    // $submission->id is now available
}, 10, 2 );

cf_form_response

Fires when the form response is being prepared, including for spam.

add_action( 'cf_form_response', function( $form, $submission, $error_code ) {
    if ( $error_code === 'spam' ) {
        // Track spam attempt
    }
}, 10, 3 );

cf_process_form

Fires during form processing, before validation.

add_action( 'cf_process_form', function( $form, $submission ) {
    // Modify submission data before processing
}, 10, 2 );

cf_fullscreen_head

Output content in the <head> of fullscreen form pages.

cf_fullscreen_footer

Output content before </body> of fullscreen form pages.

4.1 additions

cf_can_view_form_analytics

Gate per-form analytics REST endpoints on something stricter than the edit_forms capability — for example, post-author ownership.

add_filter( 'cf_can_view_form_analytics', function ( $allowed, $form_id ) {
    $post = get_post( $form_id );
    return $post && (int) $post->post_author === get_current_user_id();
}, 10, 2 );

Parameters: $allowed (bool), $form_id (int), $form (Form|null)

cf_submit_rate_limit

Override the per-IP-per-minute submission cap for a form. Returning 0 disables the limit; the default is 0 (unlimited) unless the form's submit_rate_limit setting is non-zero.

add_filter( 'cf_submit_rate_limit', function ( $limit, $form ) {
    return $form->slug === 'contact' ? 5 : $limit;
}, 10, 2 );

cf_draft_ttl_days

Days before an unfinished draft is purged by the daily cf_cleanup_drafts cron. Default 30. Return 0 to disable cleanup.

cf_analytics_retention_days

Days to keep tracker rows before the daily cf_cleanup_analytics cron deletes them. Default 365. Return 0 to disable retention.

cf_action_queue_stale_minutes

Minutes a row may sit in the workflow queue's processing status before it's considered stuck and requeued by ActionQueue::recover_stale(). Default 10.

cf_payments_orchestrator

Returns the singleton Payments orchestrator so you can reach the registered gateways from elsewhere in the codebase. Returns null if called before init.

$payments = apply_filters( 'cf_payments_orchestrator', null );
$stripe   = $payments?->get_gateway( 'stripe' );

cf_payment_completed

Fires once a webhook confirms a payment for a submission. Use it for behaviour that must only happen on paid submissions (free submissions fire cf_form_success directly, without going through this hook).

add_action( 'cf_payment_completed', function ( $submission, $form ) {
    // ... your code here ...
}, 10, 2 );

Related