Dotes FAQ Generator lets you write frequently asked questions in groups and show them anywhere on your site.
[dotes_faq] shortcode.[dotes_faq id="12"] shows FAQ group 12.[dotes_faq category="support" limit="5"] lists the FAQs of a category (ID or slug).[dotes_faq toggle="list"] forces the open-list mode (accordion is the default).title="..." (or title="false" to hide the title), search="false" and featured="true" are also available for lists.The plugin exposes actions and filters for extensions, for example dotes_faq_display_modes, dotes_faq_render_output, dotes_faq_admin_tabs, dotes_faq_settings_rows, dotes_faq_editor_rows, dotes_faq_style_fields, dotes_faq_item_css, dotes_faq_schema_data, dotes_faq_schema_faq_ids, dotes_faq_output_schema, dotes_faq_metabox_post_types, dotes_faq_group_saved, dotes_faq_vote_recorded, dotes_faq_client_ip, dotes_faq_store_ip and dotes_faq_public_nonce_actions. Use dotes_faq_generator() to get the plugin instance.
Duplicate votes are detected by the visitor IP address, read from REMOTE_ADDR. Behind Cloudflare, a load balancer or another reverse proxy every visitor may arrive with the proxy address, so only the first vote would be accepted. Return the real visitor IP with the dotes_faq_client_ip filter, reading a header that only your proxy sets (for example CF-Connecting-IP on Cloudflare), or adjust the stored value with dotes_faq_store_ip (it receives the address already anonymised, or an empty string when IP collection is off).
add_filter( 'dotes_faq_client_ip', function ( $ip ) { return isset( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) : $ip; } );
The vote buttons work on cached pages: when the security token printed in a cached page has expired, the script asks the site for a fresh one (dotes_faq_nonce AJAX action) and sends the vote again, once.
When a visitor votes on a FAQ (“Was this answer helpful?”), the plugin stores the vote in your own database: FAQ ID, vote, date, user ID (logged-in users) and IP address, to block duplicate votes.
This plugin does not connect to any external service. Every request it makes goes to your own site (admin-ajax.php), and Font Awesome and DataTables are bundled with the plugin instead of loaded from a CDN.