Quote Request Form Shortcode
Adds a [wpide_quote_form] shortcode where visitors pick a service, budget and timeline and describe their project; requests are emailed to you with spam protection and rate limiting built in.
Opens WPIDE on
Code
$wpide_quote = array(
'to' => '', // Recipient; empty = admin email.
'services' => array( 'Website design', 'Online store', 'SEO', 'Maintenance', 'Something else' ),
'budgets' => array( 'Under $1,000', '$1,000 – $5,000', '$5,000 – $15,000', 'Over $15,000' ),
);
add_action( 'template_redirect', function () use ( $wpide_quote ) {
if ( empty( $_POST['wpide_quote_nonce'] ) ) {
return;
}
$back = remove_query_arg( 'wpide_quote', wp_get_referer() ? wp_get_referer() : home_url( '/' ) );
$done = function ( $status ) use ( $back ) {
wp_safe_redirect( add_query_arg( 'wpide_quote', $status, $back ) . '#wpide-quote' );
exit;
};
if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['wpide_quote_nonce'] ) ), 'wpide_quote' ) ) {
$done( 'expired' );
}
if ( ! empty( $_POST['wpide_quote_hp'] ) ) {
$done( 'sent' );
}
$ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
$key = 'wpide_quote_' . md5( wp_salt() . $ip );
if ( (int) get_transient( $key ) >= 3 ) {
$done( 'limit' );
}
$get = function ( $name, $textarea = false ) {
$value = isset( $_POST[ $name ] ) ? wp_unslash( $_POST[ $name ] ) : '';
return $textarea ? sanitize_textarea_field( $value ) : sanitize_text_field( $value );
};
$name = str_replace( array( '<', '>', '"' ), '', $get( 'wpide_q_name' ) );
$email = sanitize_email( $get( 'wpide_q_email' ) );
$service = in_array( $get( 'wpide_q_service' ), $wpide_quote['services'], true ) ? $get( 'wpide_q_service' ) : '';
$budget = in_array( $get( 'wpide_q_budget' ), $wpide_quote['budgets'], true ) ? $get( 'wpide_q_budget' ) : 'Not given';
$deadline = $get( 'wpide_q_deadline' );
$details = $get( 'wpide_q_details', true );
if ( '' === $name || ! is_email( $email ) || '' === $service || strlen( $details ) < 20 ) {
$done( 'invalid' );
}
$body = "Name: $name\nEmail: $email\nCompany: " . $get( 'wpide_q_company' ) . "\nPhone: " . $get( 'wpide_q_phone' ) . "\nService: $service\nBudget: $budget\nTimeline: $deadline\n\n$details";
$to = is_email( $wpide_quote['to'] ) ? $wpide_quote['to'] : get_option( 'admin_email' );
$sent = wp_mail( $to, sprintf( 'Quote request: %s from %s', $service, $name ), $body, array( 'Reply-To: ' . $name . ' <' . $email . '>' ) );
set_transient( $key, (int) get_transient( $key ) + 1, HOUR_IN_SECONDS );
$done( $sent ? 'sent' : 'error' );
} );
add_shortcode( 'wpide_quote_form', function () use ( $wpide_quote ) {
$messages = array(
'sent' => 'Thanks! We will get back to you with a quote within two working days.',
'invalid' => 'Please fill in the required fields and describe your project in a little more detail.',
'limit' => 'You have sent several requests recently. Please try again later.',
'expired' => 'The form expired. Please try again.',
'error' => 'Sorry, your request could not be sent. Please email us directly.',
);
$status = isset( $_GET['wpide_quote'] ) ? sanitize_key( $_GET['wpide_quote'] ) : '';
$options = function ( $list ) {
$html = '';
foreach ( $list as $item ) {
$html .= '<option value="' . esc_attr( $item ) . '">' . esc_html( $item ) . '</option>';
}
return $html;
};
ob_start();
?>
<div id="wpide-quote" class="wpide-form wpide-quote-form">
<?php if ( isset( $messages[ $status ] ) ) : ?>
<p class="wpide-form-notice" role="status"><?php echo esc_html( $messages[ $status ] ); ?></p>
<?php endif; ?>
<form method="post" action="">
<p><label for="wpide-q-name">Your name *</label><br><input id="wpide-q-name" name="wpide_q_name" required autocomplete="name"></p>
<p><label for="wpide-q-email">Email *</label><br><input type="email" id="wpide-q-email" name="wpide_q_email" required autocomplete="email"></p>
<p><label for="wpide-q-company">Company</label><br><input id="wpide-q-company" name="wpide_q_company" autocomplete="organization"></p>
<p><label for="wpide-q-phone">Phone</label><br><input type="tel" id="wpide-q-phone" name="wpide_q_phone" autocomplete="tel"></p>
<p><label for="wpide-q-service">Service *</label><br><select id="wpide-q-service" name="wpide_q_service" required><option value="">Choose…</option><?php echo $options( $wpide_quote['services'] ); // phpcs:ignore ?></select></p>
<p><label for="wpide-q-budget">Budget</label><br><select id="wpide-q-budget" name="wpide_q_budget"><option value="">Choose…</option><?php echo $options( $wpide_quote['budgets'] ); // phpcs:ignore ?></select></p>
<p><label for="wpide-q-deadline">Ideal timeline</label><br><input id="wpide-q-deadline" name="wpide_q_deadline" placeholder="e.g. within 2 months"></p>
<p><label for="wpide-q-details">Project details *</label><br><textarea id="wpide-q-details" name="wpide_q_details" rows="6" required minlength="20"></textarea></p>
<p style="position:absolute;left:-9999px;" aria-hidden="true"><input name="wpide_quote_hp" tabindex="-1" autocomplete="off"></p>
<?php wp_nonce_field( 'wpide_quote', 'wpide_quote_nonce', false ); ?>
<p><button type="submit">Request a quote</button></p>
</form>
</div>
<?php
return ob_get_clean();
} );
Notes
Edit the services, budgets and recipient at the top; replies go straight to the visitor thanks to the Reply-To header.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.