# Testimonial Submission Form for Customers

> Adds a [wpide_testimonial_form] shortcode where customers submit a testimonial with their name and rating; each one is saved as a pending post for you to review and publish.

- Type: PHP
- Runs: Run everywhere
- Category: [Forms](https://wpide.com/library/category/forms/)
- Tags: testimonials, shortcode, reviews
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/form-testimonial-submission/

## Code

```php
add_action( 'template_redirect', function () {
    if ( empty( $_POST['wpide_testi_nonce'] ) ) {
        return;
    }

    $back = remove_query_arg( 'wpide_testi', wp_get_referer() ? wp_get_referer() : home_url( '/' ) );
    $done = function ( $status ) use ( $back ) {
        wp_safe_redirect( add_query_arg( 'wpide_testi', $status, $back ) . '#wpide-testimonial' );
        exit;
    };

    if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['wpide_testi_nonce'] ) ), 'wpide_testi' ) ) {
        $done( 'expired' );
    }
    if ( ! empty( $_POST['wpide_testi_hp'] ) ) {
        $done( 'thanks' );
    }

    $ip  = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
    $key = 'wpide_testi_' . md5( wp_salt() . $ip );
    if ( get_transient( $key ) ) {
        $done( 'limit' );
    }

    $name   = sanitize_text_field( wp_unslash( isset( $_POST['wpide_testi_name'] ) ? $_POST['wpide_testi_name'] : '' ) );
    $role   = sanitize_text_field( wp_unslash( isset( $_POST['wpide_testi_role'] ) ? $_POST['wpide_testi_role'] : '' ) );
    $text   = sanitize_textarea_field( wp_unslash( isset( $_POST['wpide_testi_text'] ) ? $_POST['wpide_testi_text'] : '' ) );
    $rating = max( 1, min( 5, absint( isset( $_POST['wpide_testi_rating'] ) ? $_POST['wpide_testi_rating'] : 5 ) ) );

    if ( '' === $name || strlen( $text ) < 20 ) {
        $done( 'invalid' );
    }

    $type = post_type_exists( 'testimonial' ) ? 'testimonial' : 'post';
    $args = array(
        'post_type'    => $type,
        'post_status'  => 'pending',
        'post_title'   => $name . ( $role ? ', ' . $role : '' ),
        'post_content' => $text,
        'meta_input'   => array( '_wpide_rating' => $rating ),
    );
    if ( 'post' === $type ) {
        $term = term_exists( 'Testimonials', 'category' );
        $term = $term ? $term : wp_insert_term( 'Testimonials', 'category' );
        if ( ! is_wp_error( $term ) ) {
            $args['post_category'] = array( (int) $term['term_id'] );
        }
    }

    $id = wp_insert_post( wp_slash( $args ) );
    if ( $id && ! is_wp_error( $id ) ) {
        set_transient( $key, 1, DAY_IN_SECONDS );
        wp_mail( get_option( 'admin_email' ), 'New testimonial to review', sprintf( "%s left a %d-star testimonial:\n\n%s\n\nReview it: %s", $name, $rating, $text, admin_url( 'post.php?post=' . $id . '&action=edit' ) ) );
    }

    $done( 'thanks' );
} );

add_shortcode( 'wpide_testimonial_form', function () {
    $messages = array(
        'thanks'  => 'Thank you for your kind words! Your testimonial will appear once we have reviewed it.',
        'invalid' => 'Please enter your name and at least a couple of sentences.',
        'limit'   => 'Thanks, we have already received your testimonial.',
        'expired' => 'The form expired. Please try again.',
    );
    $status = isset( $_GET['wpide_testi'] ) ? sanitize_key( $_GET['wpide_testi'] ) : '';

    $html  = '<div id="wpide-testimonial" class="wpide-form wpide-testimonial-form">';
    $html .= isset( $messages[ $status ] ) ? '<p class="wpide-form-notice" role="status">' . esc_html( $messages[ $status ] ) . '</p>' : '';
    $html .= '<form method="post" action="">';
    $html .= '<p><label for="wpide-testi-name">Your name</label><br><input id="wpide-testi-name" name="wpide_testi_name" required autocomplete="name"></p>';
    $html .= '<p><label for="wpide-testi-role">Company or role (optional)</label><br><input id="wpide-testi-role" name="wpide_testi_role" autocomplete="organization"></p>';
    $html .= '<fieldset><legend>Rating</legend>';
    for ( $i = 5; $i >= 1; $i-- ) {
        $html .= sprintf( '<label style="margin-right:.75em"><input type="radio" name="wpide_testi_rating" value="%1$d"%2$s> %1$d ★</label>', $i, 5 === $i ? ' checked' : '' );
    }
    $html .= '</fieldset>';
    $html .= '<p><label for="wpide-testi-text">Your testimonial</label><br><textarea id="wpide-testi-text" name="wpide_testi_text" rows="5" required minlength="20"></textarea></p>';
    $html .= '<p style="position:absolute;left:-9999px;" aria-hidden="true"><input name="wpide_testi_hp" tabindex="-1" autocomplete="off"></p>';
    $html .= wp_nonce_field( 'wpide_testi', 'wpide_testi_nonce', false, false );
    $html .= '<p><button type="submit">Send testimonial</button></p></form></div>';

    return $html;
} );
```

## Notes

Submissions become pending posts of the testimonial post type if one exists (otherwise regular posts in a "Testimonials" category), and the admin is emailed about each one.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Testimonial Submission Form for Customers" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
