If you need to do something after a Fluent Forms submission – send data to an external API, update a custom database table, or trigger an automation – the fluentform/submission_inserted hook is what you are looking for.
What Is the fluentform/submission_inserted Hook?
This is an action hook that runs after a form submission is saved to the database. It gives you access to:
- $submissionId – The ID of the submitted entry
- $formData – All submitted field data
- $form – The form object (contains form ID, settings, etc.)
It is the most commonly used hook for extending Fluent Forms
Basic Usage
Here is the standard way to use the hook:
add_action('fluentform/submission_inserted', 'your_custom_function', 20, 3);
function your_custom_function($submissionId, $formData, $form) {
// Your code here
}
The priority 20 ensures your function runs after the submission is fully saved
Important: Do not use echo or print_r inside this function. It will break the AJAX response and cause the form to keep loading forever

Example 1: Target a Specific Form
Most of the time, you only want to run code for a specific form:
add_action('fluentform/submission_inserted', 'process_specific_form', 20, 3);
function process_specific_form($submissionId, $formData, $form) {
// Only run for form ID 5
if ($form->id != 5) {
return;
}
// Do something with the submission
error_log('Form 5 submitted. Entry ID: ' . $submissionId);
}
Check the form ID first and exit early if it is not the one you need
Example 2: Send Data to an External API
If you need to send submission data to a third-party service:
add_action('fluentform/submission_inserted', 'send_to_external_api', 20, 3);
function send_to_external_api($submissionId, $formData, $form) {
if ($form->id != 5) {
return;
}
// Get specific field values
$name = isset($formData['name']) ? $formData['name'] : '';
$email = isset($formData['email']) ? $formData['email'] : '';
// Prepare the data
$api_data = array(
'name' => $name,
'email' => $email,
'source' => 'Fluent Forms'
);
// Send to external API
$response = wp_remote_post('https://your-api-endpoint.com/leads', array(
'headers' => array(
'Content-Type' => 'application/json'
),
'body' => json_encode($api_data),
'timeout' => 30
));
if (is_wp_error($response)) {
error_log('API call failed: ' . $response->get_error_message());
}
}
Example 3: Insert Data into a Custom Database Table
This example shows how to insert form data into your own custom database table
add_action('fluentform/submission_inserted', 'insert_into_custom_table', 20, 3);
function insert_into_custom_table($submissionId, $formData, $form) {
if ($form->id != 3) {
return;
}
global $wpdb;
// Extract field values
$name = isset($formData['name']) ? sanitize_text_field($formData['name']) : '';
$email = isset($formData['email']) ? sanitize_email($formData['email']) : '';
$phone = isset($formData['phone']) ? sanitize_text_field($formData['phone']) : '';
// Insert into custom table
$wpdb->insert(
'your_custom_table_name',
array(
'name' => $name,
'email' => $email,
'phone' => $phone,
'date' => current_time('mysql')
),
array('%s', '%s', '%s', '%s')
);
// Log the submission ID for debugging
error_log('Inserted into custom table. Entry ID: ' . $submissionId);
}
When inserting into custom tables, always sanitize the data and use %s or %d placeholders for security
Example 4: Trigger Custom Events and Automations
If you need to trigger other plugins or custom events, use do_action inside the hook
add_action('fluentform/submission_inserted', 'trigger_custom_automation', 20, 3);
function trigger_custom_automation($submissionId, $formData, $form) {
// List of form IDs that should trigger the automation
$target_forms = array('3', '4', '9', '10');
if (!in_array($form->id, $target_forms)) {
return;
}
// Trigger a custom action for other plugins to catch
do_action('my_custom_form_submission', $submissionId, $formData, $form);
// Or trigger specific events based on form type
if ($form->id == 3) {
do_action('my_free_subscription_event', $submissionId, $formData);
} elseif ($form->id == 4) {
do_action('my_premium_subscription_event', $submissionId, $formData);
}
}
This approach is useful for integrating with plugins like GamiPress or custom notification systems
Example 5: Modify Webhook Data Before It Is Sent
For webhook integrations, you can filter the data being sent to the external endpoint. The filter fluentform/webhook_request_data is used for this
add_filter('fluentform/webhook_request_data', 'modify_webhook_data', 10, 5);
function modify_webhook_data($selectedData, $settings, $data, $form, $entry) {
if ($form->id != 5) {
return $selectedData;
}
// Combine multiple fields into one
$dropdown1 = isset($data['service_required']) ? $data['service_required'] : '';
$dropdown2 = isset($data['branch']) ? $data['branch'] : '';
$name = isset($data['name']) ? $data['name'] : '';
$combined = $name . ' - ' . $dropdown1 . ', ' . $dropdown2;
// Add the combined field to the webhook data
$selectedData['combined_info'] = $combined;
// Remove individual fields if needed
unset($selectedData['service_required']);
unset($selectedData['branch']);
return $selectedData;
}
Note: Fluent Forms does not support nested JSON data by default. This filter allows you to restructure the data before it is sent to the webhook endpoint
Example 6: Update User Meta or Custom Fields
add_action('fluentform/submission_inserted', 'update_user_meta_on_submission', 20, 3);
function update_user_meta_on_submission($submissionId, $formData, $form) {
if ($form->id != 5) {
return;
}
// Get current logged-in user
$user_id = get_current_user_id();
if (!$user_id) {
return;
}
// Update user meta with form data
if (isset($formData['phone'])) {
update_user_meta($user_id, 'user_phone', sanitize_text_field($formData['phone']));
}
if (isset($formData['address'])) {
update_user_meta($user_id, 'user_address', sanitize_textarea_field($formData['address']));
}
error_log('User meta updated for user: ' . $user_id);
}
The Action Hook Field (Pro Feature)
Fluent Forms Pro includes an Action Hook field that lets you inject custom code at specific positions within your form
To use it:
- Add the Action Hook field from the Advanced Fields section
- Enter a unique hook name
- Add your custom function with
add_action('HOOK_NAME', ...)
This is useful when you need to display dynamic content inside the form itself
Common Mistakes and How to Avoid Them
| Mistake | Why It Happens | How to Fix |
|---|---|---|
| Form keeps loading forever | Using echo or print_r inside the hook |
Remove all output. Use error_log() for debugging |
| $submissionId is null | Hook priority too low or wrong hook used | Use priority 20 and confirm you are using fluentform/submission_inserted |
| Data is not being saved | Missing table name or incorrect column names | Check your table structure and column names |
| Hook runs for all forms | Not checking $form->id |
Add if ($form->id != YOUR_ID) { return; } |
Quick Reference
| Hook | When It Runs | Use Case |
|---|---|---|
| fluentform/submission_inserted | After submission is saved | Send data to API, insert into custom table, trigger automations |
| fluentform/before_insert_submission | Before submission is saved | Validate or modify data before database insert |
| fluentform/webhook_request_data | Before webhook data is sent | Restructure or combine fields for webhook endpoints |
Final Tips
- Always test your code on a staging site first
- Use
error_log()for debugging – neverecho - Sanitize all user input (
sanitize_text_field,sanitize_email, etc.) - Check
$form->idbefore running expensive operations - Keep your functions focused – do one thing well
Need Help with Your Fluent Forms Customization?
If you are stuck with custom hooks, webhook integrations, or complex automations, I can help.
Get a free estimate within 24 hours for your specific issue.
Send me:
- What you are trying to achieve
- What code you have tried
- URL of your site
I will look at your setup and tell you exactly what needs to be fixed and how much it will cost.
If I am fully booked, one of our WordPress developers will step in to help you.
No obligations. Just an honest assessment.
24-hour response time. Serious inquiries only.