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 );