Basic Shortcode
The primary way to embed a form on any WordPress page or post:
Form not found.
| Parameter | Type | Default | Description |
|---|---|---|---|
id | int | 0 | Required. Form ID from wp_formforge_forms |
The shortcode is registered globally and calls FORMFORGE_Form_Renderer::instance()->render(). It returns an empty string if the form ID is invalid or the form status is not publish.
Gutenberg Block
Form Forge registers a formforge/form Gutenberg block that provides a visual form selector in the editor. Detection in templates:
// Check if a post uses the Gutenberg block
if ( has_block( 'formforge/form', $post ) ) {
// Form Forge block is present on this page
}The block stores its configuration as a block attribute:
{
"name": "formforge/form",
"attributes": {
"formId": 42
}
}Frontend assets (CSS/JS) are conditionally loaded only when the shortcode or block is detected on the current page:
// From class-core.php — assets load only when needed
global $post;
if ( $post && (
has_shortcode( $post->post_content, 'formforge' ) ||
has_block( 'formforge/form', $post )
) ) {
// CSS and JS are enqueued
wp_enqueue_style( 'formforge-frontend' );
wp_enqueue_script( 'formforge-frontend' );
}Rendering in Custom Locations
You can render forms anywhere PHP runs: widgets, custom blocks, AJAX responses, or REST API responses.
In a custom widget:class My_Form_Widget extends WP_Widget {
public function __construct() {
parent::__construct( 'my_form_widget', 'Form Forge Widget' );
}
public function widget( $args, $instance ) {
echo $args['before_widget'];
if ( ! empty( $instance['form_id'] ) ) {
echo FORMFORGE_Form_Renderer::instance()->render( (int) $instance['form_id'] );
}
echo $args['after_widget'];
}
public function form( $instance ) {
$form_id = $instance['form_id'] ?? '';
$forms = class_exists( 'FORMFORGE_Form_Builder' )
? FORMFORGE_Form_Builder::instance()->get_all()
: [];
?>
<p>
<label for="<?php echo $this->get_field_id( 'form_id' ); ?>">Form:</label>
<select id="<?php echo $this->get_field_id( 'form_id' ); ?>"
name="<?php echo $this->get_field_name( 'form_id' ); ?>">
<option value="">-- Select a Form --</option>
<?php foreach ( $forms as $form ) : ?>
<option value="<?php echo $form->id; ?>"
<?php selected( $form_id, $form->id ); ?>>
<?php echo esc_html( $form->title ); ?>
</option>
<?php endforeach; ?>
</select>
</p>
<?php
}
public function update( $new_instance, $old_instance ) {
return [ 'form_id' => absint( $new_instance['form_id'] ) ];
}
}
add_action( 'widgets_init', function() {
register_widget( 'My_Form_Widget' );
} );add_filter( 'woocommerce_product_tabs', function( $tabs ) {
$tabs['inquiry'] = [
'title' => 'Product Inquiry',
'priority' => 50,
'callback' => function() {
echo FORMFORGE_Form_Renderer::instance()->render( 15 );
},
];
return $tabs;
} );add_action( 'rest_api_init', function() {
register_rest_route( 'mytheme/v1', '/form-html/(?P<id>d+)', [
'methods' => 'GET',
'callback' => function( WP_REST_Request $request ) {
$html = FORMFORGE_Form_Renderer::instance()->render( $request['id'] );
return new WP_REST_Response( [ 'html' => $html ] );
},
'permission_callback' => '__return_true',
] );
} );Force-Loading Assets
If you render a form dynamically (e.g., via AJAX or in a footer hook) after WordPress has already printed scripts, you need to ensure assets are loaded:
add_action( 'wp_enqueue_scripts', function() {
// Force-load Form Forge assets on specific pages
if ( is_page( 'dynamic-form-page' ) ) {
wp_enqueue_style( 'formforge-frontend', FORMFORGE_URL . 'assets/css/frontend.css', [], FORMFORGE_VERSION );
wp_enqueue_script( 'formforge-frontend', FORMFORGE_URL . 'assets/js/frontend.js', [ 'jquery' ], FORMFORGE_VERSION, true );
wp_localize_script( 'formforge-frontend', 'formforgeFront', [
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'formforge_nonce' ),
] );
}
} );—