sandywp / plugins / wp-polls
WP-Polls
Adds an AJAX poll system to your WordPress blog. You can also easily add a poll into your WordPress's blog post/page.
Ready in seconds.
v3.0.2 40,000+ installs WP 6.8+ PHP 8.2+

What you get inside
7 screens-
Polls -> Manage Polls, every poll with its voters, its dates and whether it is open
-
Add Poll: the question, its answers, when it closes, and how many answers a voter may pick
-
Poll Settings: the bar, the sort order, who may vote, and how a repeat vote is spotted
-
The Templates tab, holding the markup of the poll, of its results and of the archive
-
A poll in a post, waiting for a vote
-
The polls archive, every poll with what people said
-
The Poll block in the editor: the preview is the real poll, and the sidebar picks which poll and whether to show the voting form or the result
About this plugin
WP-Polls adds a poll to your site: a question, its answers, and a result bar that replaces the voting form once a visitor has voted, without a page reload. A poll can go in a post with a shortcode or a block, in a sidebar with the widget, or anywhere in your theme with a template tag.
A poll can accept one answer or several, close on a date you set, and be shown as a form or as its result. The markup of every part of it is a template you can edit, and the bars are styled with CSS custom properties your theme can override.
Donations
I spent most of my free time creating, updating, maintaining and supporting these plugins, if you really love my plugins and could spare me a couple of bucks, I will really appreciate it. If not feel free to use it without any obligations.
Usage
Showing A Poll From A Theme
<?php if ( function_exists( 'vote_poll' ) && ! in_pollarchive() ): ?>
<li>
<h2>Polls</h2>
<ul>
<li><?php get_poll();?></li>
</ul>
<?php display_polls_archive_link(); ?>
</li>
<?php endif; ?>
- To show specific poll, use
<?php get_poll(2); ?>where 2 is your poll id. - To show random poll, use
<?php get_poll(-2); ?> - To embed a specific poll in your post, use
[poll id="2"]where 2 is your poll id. - To embed a random poll in your post, use
[poll id="-2"] - To embed a specific poll’s result in your post, use
[poll id="2" type="result"]where 2 is your poll id.
Showing A Poll In A Block
Two blocks are available in the editor, under Widgets:
- Poll — one poll, as its voting form or as its result. Set Poll ID in the sidebar, or leave it at zero for the current poll, which is what an empty
[poll]does. Show chooses between the voting form and the result. - Polls Archive — every poll with its results, the same listing
[page_polls]produces.
Both render on the server, so the block preview in the editor is the real poll rather than an approximation, and changing a poll updates every post showing it without re-saving anything.
The shortcodes still work and are not going anywhere. [poll], [poll=2] and [page_polls] behave exactly as they always have, and a post already containing one needs no change. The blocks call the same code the shortcodes call, so the two render identically — use whichever suits the post.
Showing A Poll In A Widget
- Go to
WP-Admin -> Appearance -> Widgets. - Add the Polls widget to a widget area. On block themes the widget is under the Legacy Widget block, or in
Appearance -> Editorif your theme has no widget areas at all. - Set its title and which poll it shows, then save.
- Scroll down for instructions on how to create a Polls Archive.
How To Add A Polls Archive?
- Go to
WP-Admin -> Pages -> Add New. - Type any title you like in the post’s title area.
- If you ARE using nice permalinks, after typing the title, WordPress will generate the permalink to the page. You will see an ‘Edit’ link just beside the permalink.
- Click ‘Edit’ and type in
pollsarchivein the text field and click ‘Save’. - Type
[page_polls]in the post’s content area. - Click ‘Publish’.
- If you ARE NOT using nice permalinks, go to
WP-Admin -> Polls -> Settingsand fill inPoll Archive URL, under theArchiveheading, with the URL of the Polls Archive page you created above.
To Display Total Polls
<?php if ( function_exists( 'get_pollquestions' ) ): ?>
<?php get_pollquestions(); ?>
<?php endif; ?>
To Display Total Poll Answers
<?php if ( function_exists( 'get_pollanswers' ) ): ?>
<?php get_pollanswers(); ?>
<?php endif; ?>
To Display Total Poll Votes
<?php if ( function_exists( 'get_pollvotes' ) ): ?>
<?php get_pollvotes(); ?>
<?php endif; ?>
To Display Poll Votes by ID
<?php if ( function_exists( 'get_pollvotes_by_id' ) ): ?>
<?php get_pollvotes_by_id($poll_id); ?>
<?php endif; ?>
To Display Total Poll Voters
<?php if ( function_exists( 'get_pollvoters' ) ): ?>
<?php get_pollvoters(); ?>
<?php endif; ?>
To Display Poll Time by ID and date format
<?php if ( function_exists( 'get_polltime' ) ): ?>
<?php get_polltime( $poll_id, $date_format ); ?>
<?php endif; ?>
WP-CLI
wp polls list
wp polls list --status=open
wp polls get 3
wp polls open 3
wp polls close 3
wp polls delete 3 --yes
wp polls list --status=open --format=ids | xargs -n1 wp polls close closes every open poll one at a time.
REST API
GET /wp-json/polls/v1/poll/<id>
GET /wp-json/polls/v1/poll/<id>/result
POST /wp-json/polls/v1/poll/<id>/vote
Reading is public, because a poll is public. Voting takes the same poll_<id>-nonce the rendered voting form already carries, passed as a nonce parameter, and is subject to the same eligibility and repeat-vote settings as voting through the page.
Each response carries the rendered markup as well as the numbers, because your templates decide what a poll looks like and a client that rebuilt the markup itself would ignore them.
A refusal answers 403, not 400 — a closed poll, a vote already cast, a bad nonce, nothing selected. 400 is kept for a parameter this plugin never had a chance to look at, and a poll that does not exist is 404. So a 403 means the request was understood and the answer is no, and sending it again differently will not help.
These routes are an addition. The admin-ajax.php polls action is unchanged and still supported.
Translating the template
The plugin templates can be translated via template variables.
There are these filters for the custom template variables
wp_polls_template_voteheader_variables
wp_polls_template_votebody_variables
wp_polls_template_votefooter_variables
wp_polls_template_resultheader_variables
wp_polls_template_resultbody_variables
wp_polls_template_resultfooter_variables
The Result Body (Voted) and Result Footer (Voted) templates are filtered by
wp_polls_template_resultbody_variables and wp_polls_template_resultfooter_variables
too – the variables are shared, only the markup filters are separate.
Add filter to your theme and register custom variable where you will add your translation.
Good practice is to name them for example with prefix STR_ in the example STR_TOTAL_VOTERS.
/**
* Localize wp_polls_template_resultfooter_variables.
*
* @param array $variables An array of template variables.
* @return array $variables Modified template variables.
*/
function wp_polls_template_resultfooter_variables( $variables ) {
// Add strings.
$variables['%STR_TOTAL_VOTERS%'] = __( 'Total voters', 'theme-textdomain' );
return $variables;
}
// Trigger the filter
add_filter( 'wp_polls_template_resultfooter_variables', 'wp_polls_template_resultfooter_variables' , 10, 1 );
In the admin side just call the custom variable like so and the variable has been translated in the front-end.
%STR_TOTAL_VOTERS%’
Questions
- Everyone can vote as many times as they like
Check Settings -> Header That Contains The IP. If it names a header such as
HTTP_X_FORWARDED_FOR, make sure the proxy in front of WordPress always overwrites
that header. Anything a visitor can set themselves can be changed on every request,
and WP-Polls has no way to tell a real proxy from a forged header.Before 3.0.0 WP-Polls also used the entire header value as the voter’s identity.
X-Forwarded-For is a list,client, proxy1, proxy2, so a visitor could append one
more entry and count as somebody new. It now reads only the first address in the list.If you are not behind a proxy, leave the setting blank.
- Every voter is logged with the same IP, or the wrong one
WordPress is behind a proxy or a CDN and every request reaches it from the proxy’s
address. Name the header your proxy sets under Settings -> Header That Contains
The IP —HTTP_CF_CONNECTING_IPfor Cloudflare — or, to trust the usual set of
proxy headers without naming one, add this towp-config.php:define( 'WP_POLLS_TRUST_PROXY', true );Sites that need to decide per request can use the
wp_polls_trust_proxyfilter, which
defaults to that constant.- Poll logs show a hashed IP rather than an address
That is deliberate and unchanged: WP-Polls stores
wp_hash()of the address, so the
logs can tell two voters apart without keeping their IP addresses.- My poll bars lost their styling, or my customised result template came back
3.0.0 rebuilt the poll bar. It used to be one
<div class="pollbar">sized by an
inline width; it is now a track holding a fill:<div class="wp-polls-bar" aria-hidden="true"><div class="wp-polls-bar-fill" style="width: 42%;"></div></div>The Result Body and Result Body (Voted) templates are rewritten to that markup
on upgrade, including customised ones. There was no way to keep them: the class names
and the stylesheet changed with the markup, so a customised copy of the old template
would have rendered a bar with no rules left to match it. Re-apply your changes on
the Templates tab, keeping the twowp-polls-barelements.If you re-add a bar by hand, use
%POLL_ANSWER_PERCENTAGE%for the width.
%POLL_ANSWER_IMAGEWIDTH% was removed in 3.0.0 and is no longer substituted, so a
template still containing it emits the literal token into thestyleattribute and
the bar renders with no width at all.If your theme ships its own
wp-polls.css, the bar rules are not in it — they used to
be generated by PHP into an inline<style>block, and they now live in the plugin’s
stylesheet. Either copy the.wp-polls-barrules across, or delete your copy and
override these instead, which is the supported way now:.wp-polls { --wp-polls-bar-height: 8px; --wp-polls-bar-background: #d8e1eb; --wp-polls-bar-border: #c8c8c8; --wp-polls-bar-radius: 3px; }- Why doesn’t my poll’s answers add up to 100%?
- It is because of rounding issues. To make it always round up to 100%, the last poll’s answer will get the remainding percentage added to it. To enable this feature, add this to your theme’s functions.php:
add_filter( 'wp_polls_round_percentage', '__return_true' );
- It is because of rounding issues. To make it always round up to 100%, the last poll’s answer will get the remainding percentage added to it. To enable this feature, add this to your theme’s functions.php:
- How Does WP-Polls Load CSS?
- The stylesheet and the voting script load only on pages that show a poll, a polls archive or the poll widget; a page without one carries neither.
- WP-Polls will load
wp-polls.cssfrom your theme’s directory if it exists. - If it does not exist, it loads the
css/wp-polls.cssthat ships with WP-Polls. - This will allow you to upgrade WP-Polls without worrying about overwriting your polls styles that you have created.
- A theme copy made before 3.0.0 has no poll bar rules in it, because they used to be generated by PHP. See My poll bars lost their styling above.
- My own code renders a poll and the page loads no stylesheet or script
The head pass looks for the poll widget, a
[poll]or[page_polls]shortcode and
the two blocks, and anything rendering after it — a template tag, a poll in a loop
page — asks for the assets as it renders and gets them from the footer.Neither reaches poll markup fetched over
admin-ajax.phpor the REST API into a page
that itself shows no poll: the fetch has no footer to enqueue into, and the page
carried nothing for the head to find. The symptom is a poll that will not vote, under
a “Loading …” that never goes away.Say so from the page that will hold the poll:
add_filter( 'wp_polls_needs_assets', '__return_true' );Anywhere the poll can be predicted this early will do. Code that already runs later
in the page — athe_contentfilter inserting a placeholder, say — can call
WP_Polls_Display::request_assets() instead, which is the same request the render
paths make and is picked up by the footer pass.- How Do I Have Individual Colors For Each Poll’s Bar?
- Courtesy Of TreedBox.com
- Set
--wp-polls-bar-backgroundon the answer rather than styling the bar itself. The bar reads that custom property, so this works whichever poll bar style is configured, and it keeps working if the markup changes again. - Add to the end of your
wp-polls.css:
.wp-polls-ul li:nth-child(01) { --wp-polls-bar-background: #8fa0c5; } .wp-polls-ul li:nth-child(02) { --wp-polls-bar-background: #ffff88; } .wp-polls-ul li:nth-child(03) { --wp-polls-bar-background: #ff8a3b; } .wp-polls-ul li:nth-child(04) { --wp-polls-bar-background: #a61e2a; } .wp-polls-ul li:nth-child(05) { --wp-polls-bar-background: #4ebbff; } .wp-polls-ul li:nth-child(06) { --wp-polls-bar-background: #fbca54; } .wp-polls-ul li:nth-child(07) { --wp-polls-bar-background: #aad34f; } .wp-polls-ul li:nth-child(08) { --wp-polls-bar-background: #66cc9a; } .wp-polls-ul li:nth-child(09) { --wp-polls-bar-background: #98cbcb; } .wp-polls-ul li:nth-child(10) { --wp-polls-bar-background: #a67c52; } .wp-polls-ul li:hover { --wp-polls-bar-background: #ff0000; } .wp-polls .wp-polls-bar-fill { transition: background-color 0.7s ease-in-out; }Before 3.0.0 this was written against
.pollbar, the single element the bar used to
be. That class no longer exists, so the old snippet colours nothing.
sandywp / also on the shelf
Try another plugin
5.0 · 50K+ installs
zipaddr-jp is a collaborative tool that automatically inputs addresses from postal codes.
4.7 · 50K+ installs
Template powered live search for any WordPress theme. Does not require SearchWP, but will utilize it if available.
4.3 · 20K+ installs
Adds an AJAX rating system for your WordPress site's content.
Spin up a real WordPress site in seconds.
Test plugins, build a demo, hand a client a link — then squash it and start again. No local setup, no Docker.