Action and filter hooks — Veldform — vanrossum.dev                    

       vanrossum.dev 

Action and filter hooks — Veldform
==================================

  [home](https://vanrossum.dev)/[veldform](https://vanrossum.dev/products/veldform)/docs 

Veldform / Docs

Action and filter hooks
=======================

Veldform is built around registries — field types, actions, payment gateways and captcha providers all share the same registration pattern, and your additions are treated exactly like the built-in ones. All hooks are prefixed `veldform/`.

- [Registering your own](#registering-your-own)
- [Submission](#submission)
- [Rendering](#rendering)
- [Email](#email)
- [Merge tags](#merge-tags)
- [Payments](#payments)
- [Outgoing HTTP](#outgoing-http)
- [Other](#other)

Registering your own
--------------------

Registries are built on `init` (priority 5), so hook at the default priority or later.

### Field type

```php
add_action( 'veldform/register_fields', function ( $fields ) {
    $fields->register( new MyField() ); // implements Veldform\Fields\FieldType
} );

```

A field type declares its label, schema (the options shown in the builder), sanitization, validation and rendering. Once registered, it shows up in the builder palette automatically — and becomes available to the AI form builder too.

### Action

```php
add_action( 'veldform/register_actions', function ( $actions ) {
    $actions->register( new MyAction() ); // implements Veldform\Actions\Action
} );

```

An action declares its config schema and a `run( $context, $config )` method. Whatever `run()` returns is merged into the outputs, so later actions and the confirmation can use it as `{{ output.your_key }}`.

### Payment gateway

```php
add_action( 'veldform/register_gateways', function ( $gateways ) {
    $gateways->register( new MyGateway() ); // implements Veldform\Payments\PaymentGateway
} );

```

### Captcha provider

```php
add_filter( 'veldform/register_captcha', function ( array $providers ) {
    $provider = new MyCaptcha(); // implements Veldform\Captcha\CaptchaProvider
    $providers[ $provider->id() ] = $provider;
    return $providers;
} );

```

### Other registration hooks

HookTypeDescription`veldform/form_templates`filterAdd starter templates to the "New form" modal`veldform/connection_presets`filterAdd connection presets for your own service`veldform/liquid/filters`actionRegister custom Liquid filters, e.g. `$t->registerFilter( 'upper', fn( $v ) => strtoupper( $v ) );`Submission
----------

HookTypeDescription`veldform/submit`actionFires after a successful submission. Receives `$form_id, $clean, $schema, $entry_id` (`$entry_id` is 0 when entry storage is off)`veldform/actions/context`filterThe context array passed to every action's `run()``veldform/submit/rate_limit`filterMax submissions per device per minute (default 30, 0 disables)Rendering
---------

HookTypeDescription`veldform/render/control`filterThe bare control element of a field, receives `$html, $field, $value, $ctx``veldform/render/field`filterThe complete field block (wrapper, label, control, help, error)`veldform/form/wrapper`filterThe full `` HTML`veldform/render/styles`filterReturn `false` to not enqueue the plugin stylesheet, receives `$enabled, $form_id``veldform/fields/countries`filterThe country list used by the address fieldFor overriding field markup from your theme, see [Customization](/products/veldform/docs/customization).

Email
-----

HookTypeDescription`veldform/email/use_template`filterWhether to wrap a notification in the HTML template`veldform/email/logo`filterThe logo HTML in the template`veldform/email/footer`filterThe footer HTML in the template`veldform/email/html`filterThe final assembled email HTMLMerge tags
----------

HookTypeDescription`veldform/liquid/filters`actionRegister custom [Liquid filters](/products/veldform/docs/merge-tags)Payments
--------

HookTypeDescription`veldform/payment/{status}`actionFires once per status change, e.g. `veldform/payment/paid`, `veldform/payment/failed`, `veldform/payment/refunded`. Receives the payment record`veldform/payment/amount_minor`filterThe final charge amount in minor units (cents)`veldform/payments/webhook_url`filterThe webhook URL passed to the provider`veldform/payments/expire_hours`filterHours before an abandoned checkout is marked expired (default 24)Outgoing HTTP
-------------

These apply to all requests Veldform makes: the external API action, data providers and payment gateways.

HookTypeDescription`veldform/http/before`actionFires before a request, receives `$url, $args``veldform/http/after`actionFires after a request, receives `$url, $args, $response``veldform/http/sslverify`filterWhether SSL is verified (default true, except on local environments)`veldform/http/allow_host`filterAllow a specific host past the internal-address guard`veldform/webhook/allow_internal`filterAllow the external API action to reach internal/private hostsOther
-----

HookTypeDescription`veldform/captcha/recaptcha_min_score`filterThe reCAPTCHA v3 pass threshold (default 0.5)`veldform/create_user/roles`filterThe selectable roles for the Create user action`veldform/upload_dir`filterWhere uploaded entry files are stored`veldform/ai/rate_limit`filterAI requests per window (default 20)`veldform/log/enabled`filterReturn `false` to disable logging, receives `$enabled, $event, $level``veldform/log/retention_days`filterHow long log entries are kept (default 30 days)

   © 2026 Jeffrey van Rossum · [privacy](https://vanrossum.dev/privacy) · [terms](https://vanrossum.dev/terms) · [cookies](https://vanrossum.dev/cookies) [𝕏](https://x.com/jeffreyrossum) [YouTube](https://www.youtube.com/@jeffrey.rossum) [GitHub](https://github.com/jeffreyvr) [LinkedIn](https://www.linkedin.com/in/jeffrey-van-rossum-97b27321) [Instagram](https://www.instagram.com/jeffrey.rossum/) [Nomads](https://www.nomads.com/@jeffreyrossum/) [Unsplash](https://unsplash.com/@jeffreyrossum) 

 made with ☕
