Use Forms hooks when you need custom validation, extra payload fields, or side effects around public submissions.
Hook reference: Hooks: Forms. User overview: Notifal Forms Overview.
Register callbacks after WordPress loads plugins. Prefer constants from FilterHooks and ActionHooks.
Example: block a specific form
<?php
/**
* Plugin Name: My Notifal Forms Guard
* Description: Example block for notifal/forms/submit/allow/{form_id}.
* Version: 1.0.0
* Requires PHP: 7.4
*/
defined( 'ABSPATH' ) || exit;
use Notifal\Infrastructure\WordPress\Hooks\FilterHooks;
/**
* Block form CPT 42 unless a honeypot-style marketing consent field is checked.
*
* @return void
*/
add_action( 'plugins_loaded', static function () {
$form_id = 42;
add_filter(
sprintf( FilterHooks::FORMS_SUBMIT_ALLOW_FORM, $form_id ),
static function ( $allowed, $schema, $fields ) {
$consent = isset( $fields['marketing_consent'] ) ? (string) $fields['marketing_consent'] : '';
if ( $consent === '1' || $consent === 'on' || $consent === 'yes' ) {
return $allowed;
}
return array(
'message' => __( 'Please accept marketing consent to continue.', 'my-notifal-forms-guard' ),
'code' => 'consent_required',
'field' => 'marketing_consent',
);
},
10,
3
);
} );
Example: custom field validation
<?php
defined( 'ABSPATH' ) || exit;
use Notifal\Infrastructure\WordPress\Hooks\FilterHooks;
add_action( 'plugins_loaded', static function () {
add_filter(
sprintf( FilterHooks::FORMS_VALIDATE_FIELD_FORM, 42, 'email' ),
static function ( $errors, $field, $value ) {
$email = is_string( $value ) ? $value : '';
if ( $email !== '' && false !== strpos( $email, '@blocked.test' ) ) {
$errors[] = 'blocked_domain';
}
return $errors;
},
10,
3
);
} );
Example: mutate fields before validation
<?php
defined( 'ABSPATH' ) || exit;
use Notifal\Infrastructure\WordPress\Hooks\FilterHooks;
add_filter(
FilterHooks::FORMS_SUBMIT_FIELDS,
static function ( $fields, $schema ) {
$form_id = isset( $schema['form_id'] ) ? absint( $schema['form_id'] ) : 0;
if ( 42 === $form_id ) {
$fields['referral'] = 'campaign-a';
}
return $fields;
},
10,
2
);
Example: react after a successful store
<?php
defined( 'ABSPATH' ) || exit;
use Notifal\Infrastructure\WordPress\Hooks\ActionHooks;
add_action(
sprintf( ActionHooks::FORMS_SUBMIT_AFTER_FORM, 42 ),
static function ( $submission_id, $schema, $fields ) {
// Side effects only: logging, CRM push, cache busting.
do_action( 'my_crm_push_lead', (int) $submission_id, $fields );
},
10,
3
);
Example: frontend JavaScript
document.addEventListener( 'notifal:form:before-submit:42', function ( event ) {
event.detail.fields.referral = 'campaign-a';
} );
document.addEventListener( 'notifal:form:validate:42', function ( event ) {
if ( ! event.detail.fields.email ) {
event.detail.valid = false;
event.preventDefault();
}
} );
document.addEventListener( 'notifal:form:success:42', function ( event ) {
// Optional analytics after AJAX success.
window.dataLayer = window.dataLayer || [];
window.dataLayer.push( {
event: 'notifal_form_success',
formId: 42,
message: event.detail.message || '',
} );
} );
Cancelable events: validate and before-submit. Call event.preventDefault() or set detail.valid = false on validate to stop the flow.
Safety checklist
- Sanitize any values you inject into
$fieldsor emails. - Do not put secrets into
notifal/forms/submit_response. - Prefer form-scoped hooks when logic applies to one Form CPT only.
- Keep frontend listeners lightweight; Forms assets load only when a form is present.