Create forms programmatically
Use a programmatic form when a plugin or child theme owns the workflow and must version its fields/configuration in code. Use a saved form under Forms when editors need to change layout, notifications, webhook or Create Post behavior.
Public renderer
pom_render_programmatic_form(
array $layout,
array $config = array(),
array $args = array()
): string
Check the function before calling it when POM Theme is optional.
if ( ! function_exists( 'pom_render_programmatic_form' ) ) {
return '';
}
$config = pom_forms_get_default_config();
$html = pom_render_programmatic_form(
$layout,
$config,
array(
'title' => 'Product information request',
'custom_css_class' => 'my-product-request',
)
);
echo $html; // Trusted output from the POM form renderer.
Layout contract
steps
└── rows
└── columns
└── field_ids
fields
└── field definition keyed by ID
Every referenced field ID must exist in the top-level fields map. Use stable field names because merge tags, conditions and notification routes depend on them.
Configuration contract
Start with pom_forms_get_default_config() and override only the integration-owned behavior. The public convenience arguments are:
| Argument | Purpose |
|---|---|
title |
Human-readable form name |
custom_css_class |
Additional wrapper class |
admin_routes |
Replace administrator notification routes |
client_routes |
Replace submitter routes |
messages |
Merge message overrides |
subject |
Apply one subject to administrator routes |
rebuild |
Signed descriptor for reconstructing a code-owned form after cache/transient loss |
Programmatic payloads receive the current schema/revision and a deterministic signed token. POM stores a short-lived server-side payload for submission. Webhook and Create Post are forcibly disabled for programmatic forms; use a saved form for those actions.
Full-page cache support
For cached pages, register a rebuilder:
pom_forms_register_programmatic_rebuilder(
'my_product_request',
static function ( array $args ): array {
return my_plugin_build_product_request_form( $args );
}
);
Then pass:
'rebuild' => array(
'key' => 'my_product_request',
'args' => array( 'product_id' => $product_id ),
),
POM signs this small descriptor so a visitor cannot alter it. The rebuilder must still validate its arguments and return layout, config and optional args.
The references below cover field definitions, validation, actions, and the rendering/submission lifecycle.