WP Webhooks / Blog / Gravity Forms
Article · Gravity Forms

Gravity Forms Hooks: Developer Reference & Examples

A developer reference to the most useful Gravity Forms hooks: submission, validation, field, entry, and notification filters — with examples.

6 min 2026-06-18
#gravity-forms#wordpress#webhooks

TL;DR

  • Gravity Forms exposes its lifecycle through actions (do something when an event fires) and filters (modify a value before the plugin uses it).
  • The hooks you reach for most: gform_pre_submission, gform_validation, gform_after_submission, gform_after_update_entry, and the field filters gform_pre_render and gform_field_value_*.
  • To fire a webhook on submit, hook gform_after_submission — it runs once the entry is saved, so you have the entry ID and all field values.
  • The Webhook Actions plugin binds to these hooks from the admin UI, so you get async delivery, retries, and logs without writing the dispatch code yourself.

/ Overview

What are Gravity Forms hooks?

Gravity Forms hooks are the WordPress actions and filters the plugin fires as a form moves through its lifecycle — render, validation, submission, entry storage, notification, and confirmation. You attach a callback with add_action() or add_filter() and run your own logic at exactly the right moment, without editing the plugin.

There are hundreds of them. In practice a handful cover almost every integration: validate input, modify a field before it renders, react after an entry is saved, and react when an entry is later edited. Everything below is organized by where it fires in the lifecycle, with the canonical Gravity Forms documentation linked for each¹.

User submits form
       │
       ▼
  gform_field_validation / gform_validation   ← reject or accept input
       │  (valid)
       ▼
  gform_pre_submission                         ← last chance to mutate $_POST
       │
       ▼
  Entry written to database
       │
       ▼
  gform_after_submission( $entry, $form )      ← entry ID + all field values
       │
       ├─▶ gform_after_email / notifications
       └─▶ gform_confirmation                  ← what the user sees next
FIG 01 — Gravity Forms submission hook order

/ Actions vs filters

How do Gravity Forms actions and filters differ?

Actions let you do something; filters let you change something. An action callback receives data and returns nothing — gform_after_submission hands you the saved entry so you can send it somewhere. A filter callback receives a value and must return it (modified or not) — gform_pre_render hands you the form array and expects the form array back.

The practical rule: if your callback forgets to return inside a filter, you will blank out the value Gravity Forms was about to use. Actions have no such trap. When in doubt, the docs label each hook as an action or a filter at the top of its page².

HookTypeFires whenUse it for
gform_pre_renderFilterBefore the form is renderedInject choices, hide fields, set defaults
gform_field_validationFilterPer field, on submitReject a single field
gform_validationFilterOn submit, across all fieldsReject a submission with custom logic
gform_pre_submissionActionAfter validation, before saveMutate $_POST values
gform_after_submissionActionAfter the entry is savedWebhooks, CRM sync, analytics
gform_after_update_entryActionAn existing entry is editedPropagate edits downstream
gform_confirmationFilterAfter save, before displayChange the confirmation or redirect
gform_pre_send_emailFilterBefore a notification is sentRewrite or abort the email

/ Submission

Which hooks fire when a form is submitted?

Three matter most, in order. gform_pre_submission runs after validation passes but before the entry is saved — the last point you can mutate $_POST['input_5'] values. gform_after_submission runs once the entry exists in the database, giving you the complete $entry array (including $entry['id']) and the $form definition. gform_after_email fires after notifications are sent.

Use gform_after_submission for almost all outbound integrations — CRM sync, webhook dispatch, analytics — because the entry is persisted and has a stable ID to deduplicate on.

PHP — react after a submission is saved

// Fires once the entry is in the database. $entry has the ID + all fields.
add_action( 'gform_after_submission', function( $entry, $form ) {
    $email = rgar( $entry, '3' );   // field ID 3
    $entry_id = $entry['id'];
    // hand off to your integration here
}, 10, 2 );

/ Validation

How do you validate submissions with gform_validation?

Use gform_validation to reject a submission server-side based on logic Gravity Forms cannot express in the field settings — a remote API check, a duplicate-entry lookup, a business rule across multiple fields. The filter hands you a $validation_result array; set ['is_valid'] = false, mark the offending field's failed_validation, and return the array.

For single-field checks, gform_field_validation is narrower and simpler. Both run before the entry is saved, so a failed validation means no entry, no notifications, and no gform_after_submission — which is exactly why validation is the right place to stop bad data, not a post-submission webhook.

Validation hooks run before the entry is saved — so rejecting bad input there means it never reaches your downstream systems in the first place.

/ Fields

How do you change field values and choices before render?

gform_pre_render is the filter for modifying a form on the way to the screen — inject choices into a dropdown, hide a field, or change a default. It receives the $form array and must return it. For pre-populating a single field from a query string or dynamic source, the field-specific gform_field_value_{parameter_name} filter is more precise and avoids rebuilding the whole form array³.

Both are filters, so the cardinal rule applies: always return the value. A common mistake is calling gform_pre_render to read the form and forgetting to return it, which renders an empty form.

/ Entries

Which hooks fire when an entry is created or updated?

gform_after_submission covers new entries. For edits, gform_after_update_entry fires when an existing entry is changed from the wp-admin entry editor or via the GFAPI — and it hands you both the updated entry and the $original_entry, so you can diff fields and only act on real changes. This pairing is what lets you keep a downstream CRM mirrored rather than just snapshotting it at submit time.

We cover both in depth: the gform_after_submission webhook guide for new submissions, and the gform_after_update_entry guide for edits and deduplication.

/ Notifications

How do you customize confirmations and notifications?

gform_confirmation filters what the user sees after submitting — swap the confirmation message, change the redirect URL conditionally, or return a different confirmation per logic branch. gform_pre_send_email filters the notification email immediately before it is sent, letting you rewrite recipients, subject, or body, or abort the send entirely by setting $email['abort_email'] = true.

Both are filters and both fire after the entry is saved, so they are safe places to read final entry values but the wrong place to do outbound integration work — use gform_after_submission for that.

/ Webhooks

Which hook should you use to fire a webhook?

Use gform_after_submission for new submissions and gform_after_update_entry for edits. Both fire after the entry is persisted, so the payload has a stable entry ID and complete field values — everything a receiving system needs to deduplicate and process the event. Firing from a pre-save hook risks sending data for a submission that later fails validation.

The raw approach is a hook callback that builds a payload and calls wp_remote_post(). That works until the endpoint is slow (your form submit blocks on it), returns a 500 (you have no retry), or silently changes (you have no log). The Gravity Forms to n8n guide walks through the full pattern.

CapabilityRaw hook + wp_remote_postWebhook Actions
SetupCustom PHP per form and hookAdmin UI trigger picker — no code
TimingSynchronous — blocks the form submitAsync queue — submit returns immediately
RetryNone — one attempt onlyExponential backoff, default 5 attempts
LogsNone — failures are invisiblePer-attempt log with status + response body
ReplayNot possible without custom toolingOne-click replay from the Logs screen

The Webhook Actions plugin binds to gform_after_submission and gform_after_update_entry from the admin UI. Pick the form, point it at an endpoint, and delivery runs through a background queue with smart retry and exponential backoff (~30s, 60s, 120s, 240s, 480s, capped at 1 hour; default 5 attempts) and a full delivery log — no dispatch code on your side.

/Footnotes
¹ Gravity Forms hooks index — the canonical list of actions and filters.
³ Field filters: gform_pre_render and gform_field_value_{parameter_name}. Entry editing and the GFAPI: GFAPI reference.
FAQ

Common questions always ask.

Don't see yours? Open an issue on GitHub or check the full reference in the API docs.

What are Gravity Forms hooks? +
Gravity Forms hooks are the WordPress actions and filters the plugin fires throughout a form lifecycle — render, validation, submission, entry storage, notification, and confirmation. You attach a callback with add_action() or add_filter() to run custom logic at the right moment without editing the plugin.
What is the difference between Gravity Forms actions and filters? +
Actions let you do something when an event fires and return nothing — gform_after_submission hands you the saved entry. Filters let you modify a value and must return it — gform_pre_render hands you the form array and expects it back. Forgetting to return inside a filter blanks out the value Gravity Forms was about to use.
Which Gravity Forms hook fires after a form is submitted? +
gform_after_submission fires once the entry is written to the database, giving you the complete $entry array including the entry ID, plus the $form definition. It is the right hook for outbound integrations like CRM sync and webhook dispatch.
How do I send a webhook from a Gravity Forms hook? +
Hook gform_after_submission for new entries (or gform_after_update_entry for edits) and call wp_remote_post() with your payload. Both fire after the entry is saved, so the payload has a stable entry ID. The Webhook Actions plugin binds to these hooks from the admin UI and adds async delivery, retries, and logs without dispatch code.
Where is the official Gravity Forms hooks documentation? +
The canonical list lives at docs.gravityforms.com under the developers/hooks category. Each hook has its own reference page that labels it as an action or a filter and documents its parameters.
Ready

Stop losing webhooks.
Start logging them.

$ wp plugin install flowsystems-webhook-actions --activate