{"id":355004,"date":"2026-09-05T12:38:48","date_gmt":"2026-09-05T12:38:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/wphostee-competitions-for-woocommerce\/"},"modified":"2026-09-05T12:38:37","modified_gmt":"2026-09-05T12:38:37","slug":"wphostee-competitions-for-woocommerce","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/wphostee-competitions-for-woocommerce\/","author":13649891,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.9.17","stable_tag":"1.9.17","tested":"7.1","requires":"6.4","requires_php":"7.4","requires_plugins":null,"header_name":"WPHostee Competitions for WooCommerce","header_author":"Catalin Baicu @ <a href=\"https:\/\/wphostee.com\">WPHostee<\/a>","header_description":"Adds prize-competition ticket sales, draws and winner management on top of WooCommerce.","assets_banners_color":"","last_updated":"2026-09-05 12:38:37","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":27,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.9.17":{"tag":"1.9.17","author":"baicu4design","date":"2026-09-05 12:38:37","revision":3682443}},"upgrade_notice":{"1.9.0":"<p>Removes the one-competition-at-a-time limit for everyone. If you also run WPHostee Competitions Pro, update it to 1.4.0+ at the same time - older Pro versions expect the old behavior, temporarily bringing back the limit until both are updated.<\/p>","1.7.0":"<p>Internal database rename (safe, automatic, no data loss). If you also run WPHostee Competitions Pro, update both plugins together in the same maintenance window - Pro reads the same renamed tables directly, so updating only one at a time can cause brief errors until both are current.<\/p>","1.6.0":"<p>Fixes entries staying stuck as &quot;pending&quot; for Bank Transfer\/BACS or Cheque orders even after you mark them paid. After updating, visit Competitions -&gt; Settings and click &quot;Resync entries with paid orders&quot; once to fix any orders already affected.<\/p>","1.3.0":"<p>Fixes a checkout bug: a mandatory competition question now correctly requires the right answer, not just any answer. If you rely on the competition question for legal compliance, check your competitions still enforce it as expected after updating.<\/p>","1.0.3":"<p>Fixes the admin menu icon showing oversized in the sidebar. No action needed.<\/p>","1.0.1":"<p>Minor update to the Pro upgrade link. No action needed.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3682481,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3682481,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3682481,"resolution":false,"location":"assets","locale":false}},"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.9.17"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"Competitions Dashboard, with at-a-glance status across every competition","2":"The Competition tab on a WooCommerce product","3":"The Winners screen, with claim tracking and Void &amp; Redraw","4":"A competition's customer-facing entry page"}},"plugin_section":[],"plugin_tags":[175716,20072,46205,52252,286],"plugin_category":[45],"plugin_contributors":[279289],"plugin_business_model":[],"class_list":["post-355004","plugin","type-plugin","status-publish","hentry","plugin_tags-competitions","plugin_tags-giveaways","plugin_tags-prize-draw","plugin_tags-raffle","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-baicu4design","plugin_committers-baicu4design"],"banners":[],"icons":{"svg":"https:\/\/ps.w.org\/wphostee-competitions-for-woocommerce\/assets\/icon.svg?rev=3682481","icon":"https:\/\/ps.w.org\/wphostee-competitions-for-woocommerce\/assets\/icon.svg?rev=3682481","icon_2x":false,"generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>WPHostee Competitions turns any WooCommerce store into a prize competition platform. Customers buy tickets like a normal product; you run a fair, provably random draw whenever a competition closes.<\/p>\n\n<p>Built with three things in mind: <strong>no overselling<\/strong>, <strong>no unfair draws<\/strong>, and <strong>a full audit trail<\/strong> of everything that happens.<\/p>\n\n<h4>Core features (free)<\/h4>\n\n<ul>\n<li>A dedicated Competition product type - sells and checks out exactly like any other WooCommerce product<\/li>\n<li>Race-condition-safe ticket allocation - two customers can never be issued the same ticket number, even buying the last few tickets at the exact same moment<\/li>\n<li>Sequential ticket numbering, formatted with configurable leading zeros<\/li>\n<li>A cryptographically random draw (never a predictable <code>rand()<\/code>), with the exact eligible-entry list hashed and logged for later verification<\/li>\n<li>Built-in support for the skill-question requirement UK prize competitions need to stay legally distinct from a lottery<\/li>\n<li>Full admin toolkit: Dashboard, All Competitions, Entries, Ticket Reservations, Draws, and Winners (claim status, tracking number, notes, and a fully-audited Void &amp; Redraw)<\/li>\n<li>Customer-facing \"My Competitions\" tab in My Account, plus countdown, progress-bar, and competition-facts shortcodes<\/li>\n<li>Run as many competitions at once as you like, all sequential-numbered - the free tier is genuinely usable on its own, not a crippled trial<\/li>\n<li>Compatible with WooCommerce High-Performance Order Storage (HPOS)<\/li>\n<\/ul>\n\n<h4>WPHostee Competitions Pro<\/h4>\n\n<p>A separate, paid companion plugin unlocks: Random (Lucky Dip) ticket assignment and manual ticket selection, a Free Postal Entry route, per-customer\/order\/day entry limits, Reports with CSV export, a full Audit Log viewer, a REST API, Elementor widgets, and a winner publicity\/consent workflow with automatic emails. Free works completely on its own without it - Pro is entirely optional.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin files to <code>\/wp-content\/plugins\/wphostee-competitions<\/code>, or install directly through the WordPress Plugins screen.<\/li>\n<li>Make sure WooCommerce is installed and active - this plugin requires it.<\/li>\n<li>Activate the plugin through the \"Plugins\" screen in WordPress.<\/li>\n<li>Go to Competitions \u2192 Settings to set your ticket reservation timeout and default numbering options.<\/li>\n<li>Create a competition: add a new WooCommerce product, set its Product type to \"Competition,\" and fill in the Competition tab.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20woocommerce%20for%20this%20to%20work%3F\"><h3>Do I need WooCommerce for this to work?<\/h3><\/dt>\n<dd><p>Yes. Competitions are a WooCommerce product type, so they use your existing cart, checkout, payment gateways, and order emails.<\/p><\/dd>\n<dt id=\"can%20two%20customers%20ever%20be%20sold%20the%20same%20ticket%20number%3F\"><h3>Can two customers ever be sold the same ticket number?<\/h3><\/dt>\n<dd><p>No. Ticket allocation is protected by a database row lock plus a unique constraint at the database level, so even the very last ticket in a competition can't be double-sold under simultaneous purchases.<\/p><\/dd>\n<dt id=\"how%20is%20the%20draw%20kept%20fair%3F\"><h3>How is the draw kept fair?<\/h3><\/dt>\n<dd><p>The draw uses PHP's cryptographically secure random number generator, never a predictable function. The exact list of eligible tickets is hashed and recorded in the Audit Log at the moment of the draw, so the result can be independently checked afterwards.<\/p><\/dd>\n<dt id=\"can%20i%20run%20more%20than%20one%20competition%20at%20a%20time%3F\"><h3>Can I run more than one competition at a time?<\/h3><\/dt>\n<dd><p>Yes, the free version has no limit on how many competitions can be active at once.<\/p><\/dd>\n<dt id=\"does%20this%20delete%20customer%20data%20if%20i%20uninstall%20the%20plugin%3F\"><h3>Does this delete customer data if I uninstall the plugin?<\/h3><\/dt>\n<dd><p>No, not by default. Competition, entry, and winner data is kept even if you remove the plugin, unless you explicitly opt in to full deletion under Competitions \u2192 Settings \u2192 Privacy.<\/p><\/dd>\n<dt id=\"is%20this%20compatible%20with%20high-performance%20order%20storage%20%28hpos%29%3F\"><h3>Is this compatible with High-Performance Order Storage (HPOS)?<\/h3><\/dt>\n<dd><p>Yes, the plugin declares and works correctly with HPOS.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.9.17<\/h4>\n\n<ul>\n<li>Addressed WordPress.org plugin review feedback: every place this plugin echoes HTML built by its own helper functions, or reached through a public filter (e.g. wphc_winner_photo_html, wphc_free_entry_tab_html), is now run through wp_kses() right at the point it's echoed, rather than only trusting that the function\/filter producing it was already safe. Also removed a small admin tooltip's inline onmouseover\/onfocus JavaScript attributes (replaced with plain CSS hover\/focus) since escaping can't legitimately allow those through.<\/li>\n<li>Removed the \"pob_\" shortcode aliases ([pob_competitions] etc., kept since 1.7.0 for backward compatibility with this plugin's original naming) - WordPress.org review does not allow a generic, non-unique prefix anywhere, including a legacy alias. No page on wphostee.co.uk currently uses them; if you have an old page that does, replace [pob_competitions] with [wphc_competitions] (and similarly for any other pob_ shortcode) - the current tag names are unaffected.<\/li>\n<\/ul>\n\n<h4>1.9.16<\/h4>\n\n<ul>\n<li>Added a couple of small extensibility hooks around competition closing, used by the Pro add-on's new \"Minimum tickets\" feature (automatically extending a competition past its closing date until enough tickets have sold, rather than closing early with too few entries). No behaviour change without Pro - \"Minimum tickets\" remains purely informational on its own.<\/li>\n<\/ul>\n\n<h4>1.9.15<\/h4>\n\n<ul>\n<li>Fixed: on the [wphc_competitions] grid, the countdown\/entries-sold\/Enter Competition block inside each card could render off to one side instead of matching the card's normal centred layout. Root cause was our own content rendering while the theme's title\/image link was technically still open (invalid nested markup, since our block also includes its own link) - moved it to render after that link properly closes, and gave it the same \"stretch to the card's full width\" treatment WooCommerce's own price\/title elements already get, rather than inventing any alignment of our own.<\/li>\n<\/ul>\n\n<h4>1.9.14<\/h4>\n\n<ul>\n<li>Fixed: on a block theme, the [wphc_competitions] product grid could render noticeably narrower than the Shop page - it now stretches to the same wide content width Shop itself uses. If you already have the shortcode on a page from an earlier version, re-selecting that page in Settings &gt; \"Competitions page\" and saving won't reapply this (the shortcode's already there) - wrap it yourself in a Group block set to \"Wide width\" in the page editor, or remove it and let Settings add it again.<\/li>\n<\/ul>\n\n<h4>1.9.13<\/h4>\n\n<ul>\n<li>Choosing a page in Settings &gt; \"Competitions page\" now automatically adds the [wphc_competitions] shortcode to that page if it isn't already there, every time Settings is saved - no need to add it yourself. It's only ever added, never removed automatically (removing it is a manual step in the page editor, same as switching back to \"None\" only stops excluding competitions from the Shop page and doesn't touch the page's content).<\/li>\n<\/ul>\n\n<h4>1.9.12<\/h4>\n\n<ul>\n<li>Fixed: clicking \"Save Changes\" on the Settings screen could silently do nothing at all. The \"Payment Sync\" section's own small form was nested inside the main settings form - invalid HTML that browsers handle by closing the outer form early, leaving everything below it (including the real Save Changes button) outside any form and unable to submit. Moved that section to its own space outside the main form.<\/li>\n<\/ul>\n\n<h4>1.9.11<\/h4>\n\n<ul>\n<li>The [wphc_competitions] shortcode now renders a full product grid matching the Shop page - the same card styling, a working sorting dropdown (Default\/popularity\/rating\/latest\/price), results count, and pagination, all built in. No extra setup needed: just place the shortcode on any page.<\/li>\n<li>Settings has a \"Competitions page\" option again - pick the page carrying your [wphc_competitions] shortcode to keep competitions off the main Shop page (for stores that also sell ordinary products there).<\/li>\n<\/ul>\n\n<h4>1.9.10<\/h4>\n\n<ul>\n<li>(Superseded by 1.9.11 - the \"Competitions\" category approach below was replaced with the simpler shortcode-based one above.)<\/li>\n<\/ul>\n\n<h4>1.9.8<\/h4>\n\n<ul>\n<li>Fixed: the product photo on the Basket page (a ticket entry sitting alongside an ordinary product) could look blurred, since it was being shown much larger than the underlying image file - it's now shown at a fixed, sharp 100x100px.<\/li>\n<li>Fixed: a basket containing both a competition ticket and an ordinary product incorrectly labelled every row's photo as a ticket and relabelled the whole \"Product\" column - both now only apply to the competition ticket row(s).<\/li>\n<\/ul>\n\n<h4>1.9.5<\/h4>\n\n<ul>\n<li>Fixed: when choosing specific ticket numbers (Pro), picking a second or third ticket did nothing unless the quantity box had already been increased to match first. The quantity (and running total) now updates automatically to match however many tickets are picked, up to the competition's own per-order limit.<\/li>\n<\/ul>\n\n<h4>1.9.4<\/h4>\n\n<ul>\n<li>The competition's short description (set on the product's \"short description\" field, same as any other WooCommerce product) now shows directly under the title, instead of further down the page below the price and ticket details.<\/li>\n<li>The upgrade link shown in the free plugin now points straight to this plugin's own Pro store page.<\/li>\n<\/ul>\n\n<h4>1.9.3<\/h4>\n\n<ul>\n<li>The price shown on a competition now makes clear it's the price per ticket, and the running total while choosing quantity now makes clear it's the total for the tickets selected.<\/li>\n<li>Added explanatory tooltips to the \"minimum tickets\", \"maximum tickets\" and \"one winner\" facts shown on a competition page.<\/li>\n<li>Removed the standalone \"This is the price for 1 ticket\" note, now covered by the price label above.<\/li>\n<li>Fixed: WooCommerce's own default \"Add to basket\"-style button could appear a second time underneath this plugin's own \"Enter Competition\" button on the Shop page grid, depending on the active theme. Suppressed at the WooCommerce level so it can't reappear regardless of theme.<\/li>\n<li>Fixed: on themes that build the Shop page out of separate WooCommerce blocks (e.g. Twenty Twenty-Five), the price could be shown out of place below the \"Enter Competition\" button instead of above it like every other product.<\/li>\n<\/ul>\n\n<h4>1.9.1<\/h4>\n\n<ul>\n<li>WordPress.org Plugin Check compliance pass: fixed every flagged error and warning, including proper escaping in a handful of admin\/shortcode outputs, a missing translators comment, corrected escaping in the plain-text email templates, normalised corrupted line endings in several files, and removed a now-unnecessary load_plugin_textdomain() call (WordPress.org loads translations for hosted plugins automatically). No functional changes.<\/li>\n<\/ul>\n\n<h4>1.9.0<\/h4>\n\n<ul>\n<li>Removed the \"one active competition at a time\" limit - run as many simultaneous competitions as you like, free of charge.<\/li>\n<li>Random (Lucky Dip) ticket assignment is now implemented entirely by the separate Pro companion plugin rather than being built into this plugin and merely gated - this plugin only ever assigns tickets sequentially on its own.<\/li>\n<\/ul>\n\n<h4>1.8.0<\/h4>\n\n<ul>\n<li>WordPress.org review housekeeping: bumped Tested up to, renamed the text domain to match the assigned plugin slug, replaced a disabled admin checkbox with a plain-text note, escaped a shortcode's filter-provided output, made the Winners claim-status labels genuinely translatable, added a missing nonce check on the ticket-reservation add-to-cart flow, sanitized data passed into two extensibility filters, and moved two remaining inline admin scripts\/styles to proper wp_enqueue_* calls.<\/li>\n<\/ul>\n\n<h4>1.7.1<\/h4>\n\n<ul>\n<li>The author credit shown on the Plugins screen now reads \"Catalin Baicu @ WPHostee\", with only \"WPHostee\" linked.<\/li>\n<\/ul>\n\n<h4>1.7.0<\/h4>\n\n<ul>\n<li>Renamed the plugin's internal database tables and settings keys from the too-short \"pob_\" prefix (a leftover from this plugin's earlier life as a single-client build) to \"wphc_\", per WordPress.org plugin review requirements. Existing data migrates automatically and safely on update - no action needed. Old shortcode names ([pob_competitions] etc.) keep working indefinitely as aliases, so no existing page content needs to change. (The \"pob_\" shortcode aliases mentioned here were themselves removed in a later version below - they were still a generic, non-unique prefix, which WordPress.org review does not allow even as a backwards-compatible alias.)<\/li>\n<\/ul>\n\n<h4>1.6.1<\/h4>\n\n<ul>\n<li>Fixed: the maximum-tickets-per-order limit was only enforced on the product page - the Basket page's own quantity control had no idea it existed, letting a customer increase quantity past it after adding to basket. Now enforced by WooCommerce itself everywhere a quantity can be changed.<\/li>\n<\/ul>\n\n<h4>1.6.0<\/h4>\n\n<ul>\n<li>Fixed: entries could stay stuck showing \"pending\" forever for manual payment methods (Bank Transfer\/BACS, Cheque), even after the order was correctly marked Processing\/Completed - WooCommerce doesn't fire the hook we relied on for a manual admin status change, only for gateways that confirm payment automatically.<\/li>\n<li>Added a \"Payment Sync\" tool on Settings that safely re-checks and fixes any entries left behind by the above, for existing orders.<\/li>\n<\/ul>\n\n<h4>1.5.1<\/h4>\n\n<ul>\n<li>Fixed: the \"Live\"\/\"Closed\" countdown badge could show both at once on themes that don't reset the HTML <code>hidden<\/code> attribute, since our own CSS wasn't respecting it.<\/li>\n<\/ul>\n\n<h4>1.5.0<\/h4>\n\n<ul>\n<li>Each winner card on the admin Winners screen now shows a 115x115 round profile photo, always visible regardless of collapsed\/expanded state - the customer's account avatar by default (WPHostee Competitions Pro can substitute a photo uploaded specifically for the public winners list).<\/li>\n<\/ul>\n\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>The admin Winners screen now shows collapsible cards (each starts collapsed, click to expand\/collapse, plus \"Expand all\"\/\"Collapse all\"), filters by competition, month, year, and city, and paginates at 10 winners per page - built for stores with large numbers of winners.<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Fixed: a mandatory competition question now actually requires the <em>correct<\/em> answer to proceed to checkout - previously any selected answer was accepted, only a blank answer was blocked.<\/li>\n<li>Added help tooltips explaining \"Maximum tickets,\" \"Minimum tickets,\" and every field in the Competition Question section.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Added help tooltips explaining \"When sold out,\" \"Starting ticket number,\" \"Ticket assignment,\" and \"Manual ticket selection\" on the Competition tab.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>New \"Competition Rules\" tab on the product page - per-competition, supports plain text, HTML, or shortcodes, only shown when rules text is entered.<\/li>\n<li>The \"Enter Competition\" button, quantity selector, and total price now sit inline on the same row.<\/li>\n<li>Relabelled \"Related products\" to \"Other Related Competitions\" on competition product pages.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Fixed the admin menu icon rendering oversized in the sidebar.<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>New custom admin menu icon.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Updated the \"Upgrade to Pro\" link destination.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial public release.<\/li>\n<\/ul>","raw_excerpt":"Sell prize competition tickets through WooCommerce, with race-condition-safe ticket allocation and an auditable random draw.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/355004","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=355004"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/baicu4design"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=355004"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=355004"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=355004"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=355004"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=355004"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=355004"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}