Simple Poll Shortcode
Adds a [wpide_poll] shortcode that shows a question with answer buttons and, after voting, the results as accessible bars. One vote per visitor, stored without personal data.
Opens WPIDE on
Code
add_action( 'template_redirect', function () {
if ( empty( $_POST['wpide_poll_nonce'] ) || empty( $_POST['wpide_poll_id'] ) ) {
return;
}
$poll = sanitize_key( wp_unslash( $_POST['wpide_poll_id'] ) );
$choice = isset( $_POST['wpide_poll_choice'] ) ? absint( $_POST['wpide_poll_choice'] ) : -1;
$back = wp_get_referer() ? wp_get_referer() : home_url( '/' );
if ( wp_verify_nonce( sanitize_key( wp_unslash( $_POST['wpide_poll_nonce'] ) ), 'wpide_poll_' . $poll ) && $choice >= 0 && $choice < 20 && empty( $_COOKIE[ 'wpide_poll_' . $poll ] ) ) {
$ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
$key = 'wpide_poll_ip_' . md5( wp_salt() . $poll . $ip );
if ( ! get_transient( $key ) ) {
$votes = (array) get_option( 'wpide_poll_' . $poll, array() );
$votes[ $choice ] = ( isset( $votes[ $choice ] ) ? (int) $votes[ $choice ] : 0 ) + 1;
update_option( 'wpide_poll_' . $poll, $votes, false );
set_transient( $key, 1, DAY_IN_SECONDS );
}
if ( ! headers_sent() ) {
setcookie( 'wpide_poll_' . $poll, '1', time() + YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
}
}
wp_safe_redirect( add_query_arg( 'wpide_voted', $poll, $back ) . '#wpide-poll-' . $poll );
exit;
} );
add_shortcode( 'wpide_poll', function ( $atts ) {
$atts = shortcode_atts( array( 'id' => 'poll', 'question' => 'What do you think?', 'options' => 'Yes|No' ), $atts, 'wpide_poll' );
$poll = sanitize_key( $atts['id'] );
$options = array_slice( array_map( 'trim', explode( '|', $atts['options'] ) ), 0, 20 );
$voted = ! empty( $_COOKIE[ 'wpide_poll_' . $poll ] ) || ( isset( $_GET['wpide_voted'] ) && sanitize_key( $_GET['wpide_voted'] ) === $poll );
$html = '<div id="wpide-poll-' . esc_attr( $poll ) . '" class="wpide-poll"><p class="wpide-poll-question"><strong>' . esc_html( $atts['question'] ) . '</strong></p>';
if ( $voted ) {
$votes = (array) get_option( 'wpide_poll_' . $poll, array() );
$total = max( 1, array_sum( $votes ) );
$html .= '<ul class="wpide-poll-results" style="list-style:none;padding:0;">';
foreach ( $options as $i => $label ) {
$count = isset( $votes[ $i ] ) ? (int) $votes[ $i ] : 0;
$pct = round( $count / $total * 100 );
$html .= sprintf( '<li style="margin:.4em 0;"><span>%1$s – %2$d%%</span><div role="img" aria-label="%1$s: %2$d percent" style="background:rgba(127,127,127,.2);border-radius:4px;height:.6em;"><div style="width:%2$d%%;height:100%%;background:currentColor;border-radius:4px;"></div></div></li>', esc_html( $label ), (int) $pct );
}
return $html . '</ul><p><small>' . esc_html( sprintf( '%d vote(s)', array_sum( $votes ) ) ) . '</small></p></div>';
}
$html .= '<form method="post" action="">';
foreach ( $options as $i => $label ) {
$html .= sprintf( '<button type="submit" name="wpide_poll_choice" value="%d" style="margin:0 .5em .5em 0;">%s</button>', (int) $i, esc_html( $label ) );
}
$html .= '<input type="hidden" name="wpide_poll_id" value="' . esc_attr( $poll ) . '">' . wp_nonce_field( 'wpide_poll_' . $poll, 'wpide_poll_nonce', false, false ) . '</form></div>';
return $html;
} );
Notes
Use [wpide_poll id="coffee" question="Tea or coffee?" options="Tea|Coffee|Neither"] with a unique id per poll; votes are counted in an option per poll.
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.