WooCommerce Single Product Page Actions and Hooks Visual Guide

Template hooks are easiest way to customize your pages in WooCommerce by rearranging elements or adding additional features on single product page. Template hooks are convenient for customizing templates of our plugins like Simple Auctions, Lottery and Group Buy. Easily move and rearrange page elements like progress bar, buy now, texts, countdown timers etc. since all elements are hooked onto existing WooCommerce template hooks (both for single product and for product archive elements).

Here is one example of how to run a shortcode (for our WooCommerce Lottery Pick Number addon) just above buy button on single product page:

add_action( 'woocommerce_after_add_to_cart_quantity', 'wpgenie_add_shortcode_lottery_lucky_dip_buton', 40 );

function wpgenie_add_shortcode_lottery_lucky_dip_buton(){

	echo do_shortcode( '[lottery_lucky_dip_buton qty="5" label="buy 5 tickets"]' );
}

Best visual WooCommerce hook (both template and other) guide can be found here https://hooks.wpdesk.org/– by clicking on each page you will see how hooks are arranged through every WooCommerce page:

WooCommerce Single Product Page Hooks Visual Guide

This is complete list of template hooks:

<?php
/**
 * WooCommerce Template Hooks
 *
 * Action/filter hooks used for WooCommerce functions/templates.
 *
 * @author 		WooThemes
 * @category 	Core
 * @package 	WooCommerce/Templates
 * @version     2.1.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

add_filter( 'body_class', 'wc_body_class' );
add_filter( 'post_class', 'wc_product_post_class', 20, 3 );

/**
 * WP Header.
 *
 * @see  wc_generator_tag()
 */
add_action( 'get_the_generator_html', 'wc_generator_tag', 10, 2 );
add_action( 'get_the_generator_xhtml', 'wc_generator_tag', 10, 2 );

/**
 * Content Wrappers.
 *
 * @see woocommerce_output_content_wrapper()
 * @see woocommerce_output_content_wrapper_end()
 */
add_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper', 10 );
add_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end', 10 );

/**
 * Sale flashes.
 *
 * @see woocommerce_show_product_loop_sale_flash()
 * @see woocommerce_show_product_sale_flash()
 */
add_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_show_product_loop_sale_flash', 10 );
add_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_sale_flash', 10 );

/**
 * Breadcrumbs.
 *
 * @see woocommerce_breadcrumb()
 */
add_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0 );

/**
 * Sidebar.
 *
 * @see woocommerce_get_sidebar()
 */
add_action( 'woocommerce_sidebar', 'woocommerce_get_sidebar', 10 );

/**
 * Archive descriptions.
 *
 * @see woocommerce_taxonomy_archive_description()
 * @see woocommerce_product_archive_description()
 */
add_action( 'woocommerce_archive_description', 'woocommerce_taxonomy_archive_description', 10 );
add_action( 'woocommerce_archive_description', 'woocommerce_product_archive_description', 10 );

/**
 * Products Loop.
 *
 * @see woocommerce_result_count()
 * @see woocommerce_catalog_ordering()
 */
add_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
add_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );
add_action( 'woocommerce_no_products_found', 'wc_no_products_found' );

/**
 * Product Loop Items.
 *
 * @see woocommerce_template_loop_product_link_open()
 * @see woocommerce_template_loop_product_link_close()
 * @see woocommerce_template_loop_add_to_cart()
 * @see woocommerce_template_loop_product_thumbnail()
 * @see woocommerce_template_loop_product_title()
 * @see woocommerce_template_loop_category_link_open()
 * @see woocommerce_template_loop_category_title()
 * @see woocommerce_template_loop_category_link_close()
 * @see woocommerce_template_loop_price()
 * @see woocommerce_template_loop_rating()
 */
add_action( 'woocommerce_before_shop_loop_item', 'woocommerce_template_loop_product_link_open', 10 );
add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_product_link_close', 5 );
add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
add_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
add_action( 'woocommerce_shop_loop_item_title', 'woocommerce_template_loop_product_title', 10 );

add_action( 'woocommerce_before_subcategory', 'woocommerce_template_loop_category_link_open', 10 );
add_action( 'woocommerce_shop_loop_subcategory_title', 'woocommerce_template_loop_category_title', 10 );
add_action( 'woocommerce_after_subcategory', 'woocommerce_template_loop_category_link_close', 10 );

add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_rating', 5 );

/**
 * Subcategories.
 *
 * @see woocommerce_subcategory_thumbnail()
 */
add_action( 'woocommerce_before_subcategory_title', 'woocommerce_subcategory_thumbnail', 10 );

/**
 * Before Single Products Summary Div.
 *
 * @see woocommerce_show_product_images()
 * @see woocommerce_show_product_thumbnails()
 */
add_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20 );
add_action( 'woocommerce_product_thumbnails', 'woocommerce_show_product_thumbnails', 20 );

/**
 * After Single Products Summary Div.
 *
 * @see woocommerce_output_product_data_tabs()
 * @see woocommerce_upsell_display()
 * @see woocommerce_output_related_products()
 */
add_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_product_data_tabs', 10 );
add_action( 'woocommerce_after_single_product_summary', 'woocommerce_upsell_display', 15 );
add_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 );

/**
 * Product Summary Box.
 *
 * @see woocommerce_template_single_title()
 * @see woocommerce_template_single_rating()
 * @see woocommerce_template_single_price()
 * @see woocommerce_template_single_excerpt()
 * @see woocommerce_template_single_meta()
 * @see woocommerce_template_single_sharing()
 */
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_title', 5 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_rating', 10 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_excerpt', 20 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_meta', 40 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_sharing', 50 );

/**
 * Reviews
 *
 * @see woocommerce_review_display_gravatar()
 * @see woocommerce_review_display_rating()
 * @see woocommerce_review_display_meta()
 * @see woocommerce_review_display_comment_text()
 */
add_action( 'woocommerce_review_before', 'woocommerce_review_display_gravatar', 10 );
add_action( 'woocommerce_review_before_comment_meta', 'woocommerce_review_display_rating', 10 );
add_action( 'woocommerce_review_meta', 'woocommerce_review_display_meta', 10 );
add_action( 'woocommerce_review_comment_text', 'woocommerce_review_display_comment_text', 10 );

/**
 * Product Add to cart.
 *
 * @see woocommerce_template_single_add_to_cart()
 * @see woocommerce_simple_add_to_cart()
 * @see woocommerce_grouped_add_to_cart()
 * @see woocommerce_variable_add_to_cart()
 * @see woocommerce_external_add_to_cart()
 * @see woocommerce_single_variation()
 * @see woocommerce_single_variation_add_to_cart_button()
 */
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
add_action( 'woocommerce_simple_add_to_cart', 'woocommerce_simple_add_to_cart', 30 );
add_action( 'woocommerce_grouped_add_to_cart', 'woocommerce_grouped_add_to_cart', 30 );
add_action( 'woocommerce_variable_add_to_cart', 'woocommerce_variable_add_to_cart', 30 );
add_action( 'woocommerce_external_add_to_cart', 'woocommerce_external_add_to_cart', 30 );
add_action( 'woocommerce_single_variation', 'woocommerce_single_variation', 10 );
add_action( 'woocommerce_single_variation', 'woocommerce_single_variation_add_to_cart_button', 20 );

/**
 * Pagination after shop loops.
 *
 * @see woocommerce_pagination()
 */
add_action( 'woocommerce_after_shop_loop', 'woocommerce_pagination', 10 );

/**
 * Product page tabs.
 */
add_filter( 'woocommerce_product_tabs', 'woocommerce_default_product_tabs' );
add_filter( 'woocommerce_product_tabs', 'woocommerce_sort_product_tabs', 99 );

/**
 * Additional Information tab.
 *
 * @see wc_display_product_attributes()
 */
add_action( 'woocommerce_product_additional_information', 'wc_display_product_attributes', 10 );

/**
 * Checkout.
 *
 * @see woocommerce_checkout_login_form()
 * @see woocommerce_checkout_coupon_form()
 * @see woocommerce_order_review()
 * @see woocommerce_checkout_payment()
 */
add_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_login_form', 10 );
add_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 );
add_action( 'woocommerce_checkout_order_review', 'woocommerce_order_review', 10 );
add_action( 'woocommerce_checkout_order_review', 'woocommerce_checkout_payment', 20 );

/**
 * Cart widget
 */
add_action( 'woocommerce_widget_shopping_cart_buttons', 'woocommerce_widget_shopping_cart_button_view_cart', 10 );
add_action( 'woocommerce_widget_shopping_cart_buttons', 'woocommerce_widget_shopping_cart_proceed_to_checkout', 20 );

/**
 * Cart.
 *
 * @see woocommerce_cross_sell_display()
 * @see woocommerce_cart_totals()
 * @see woocommerce_button_proceed_to_checkout()
 */
add_action( 'woocommerce_cart_collaterals', 'woocommerce_cross_sell_display' );
add_action( 'woocommerce_cart_collaterals', 'woocommerce_cart_totals', 10 );
add_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );

/**
 * Footer.
 *
 * @see  wc_print_js()
 * @see woocommerce_demo_store()
 */
add_action( 'wp_footer', 'wc_print_js', 25 );
add_action( 'wp_footer', 'woocommerce_demo_store' );

/**
 * Order details.
 *
 * @see woocommerce_order_details_table()
 * @see woocommerce_order_again_button()
 */
add_action( 'woocommerce_view_order', 'woocommerce_order_details_table', 10 );
add_action( 'woocommerce_thankyou', 'woocommerce_order_details_table', 10 );
add_action( 'woocommerce_order_details_after_order_table', 'woocommerce_order_again_button' );

/**
 * Auth.
 *
 * @see woocommerce_output_auth_header()
 * @see woocommerce_output_auth_footer()
 */
add_action( 'woocommerce_auth_page_header', 'woocommerce_output_auth_header', 10 );
add_action( 'woocommerce_auth_page_footer', 'woocommerce_output_auth_footer', 10 );

/**
 * Comments.
 *
 * Disable Jetpack comments.
 */
add_filter( 'jetpack_comment_form_enabled_for_product', '__return_false' );

/**
 * My Account.
 */
add_action( 'woocommerce_account_navigation', 'woocommerce_account_navigation' );
add_action( 'woocommerce_account_content', 'woocommerce_account_content' );
add_action( 'woocommerce_account_orders_endpoint', 'woocommerce_account_orders' );
add_action( 'woocommerce_account_view-order_endpoint', 'woocommerce_account_view_order' );
add_action( 'woocommerce_account_downloads_endpoint', 'woocommerce_account_downloads' );
add_action( 'woocommerce_account_edit-address_endpoint', 'woocommerce_account_edit_address' );
add_action( 'woocommerce_account_payment-methods_endpoint', 'woocommerce_account_payment_methods' );

More details are here.

WooCommerce Lottery – Give ticket for free when client purchase another item

We had couple of inquries if it is possible to give ticket for free and allow clients to participate in prize draw when they purchase regular items sold on websites. This is possible and relatively easy to setup using our plugin. If you want to give users ticket number you will need Pick Number Mod addon for WooCommerce Lottery.

Easiest and fastest solution, would be that you create new lottery product and treat it as regular simple product so when someone purchase it you will ship actual item, (or give user access for download, etc) but also state that user will participate in lottery and could win a prize after purchase.

It is possible to change text from “Participate now for” via translations to anything you like and thing might be more suitable.

That lottery product was setup like this (here we use only WooCommerce Lottery without Pick Number Mod addon in this example):

If you want more complex solution then you will need 3rd party plugin which implements Buy One, Get One Free option / feature for WooCommerce.

In this tutorial I used PW WooCommerce BOGO Free plugin which is really trivial to setup and use. After installation you need to publish promotion and for each purchase of regular product you can add lottery ticket for free if price is lower or equal to product you purchased. There are plenty of similar plugins which you can use for this purpose – all should work just fine.

Here are couple of screenshots to see how this looks like on website during checkout:

Please note that you need to manually add lottery ticket to cart, plugin does not add it automatically. This implementation is handy if you want to use question / answers.

On last screenshot you can see how sample lottery / prize draw was setup. Please note WooCommerce Lottery and Pick Number Mod addon are enabled in this test setup.

Important thing to setup is minimum number of tickets for draw to be done, max number of tickets can be increased or decreased whole time during lottery active phase but make sure you don’t set max tickets below number of sold tickets since that can result with unexpected behaviour.

Keep on your mind that with this solution users would be able to participate by buying lottery ticket directly since we have not implemented anything that would prevent purchasing ticket directly by going to lottery product single page. If you need lottery to be restricted only for those who purchase something else you might need to get different plugin for “Buy One, Get One Free” or get pro version for this plugin.

Now here you can see screenshots of implementation without Pick Number Mod addon. Key difference is that there is no ticket number and that draw will be automatically done once lottery ends (no manual pick winner option – plugin will do that automatically using mt_rand function from all participants – there will always be 1 winner if there is at least 1 participant).

WooCommerce Simple Auctions now with Elementor support

elementor

WooCommerce Simple Auctions supports Elementor fully from version v2.0. You can create single auction page and auction base page with Elementor using Elementor widgets that are specific for auctions. To edit auction templates with Elementor you need Elementor (free) plus Elementor Pro (paid) or PRO Elements (free).

Screenshots below show Elementor widgets you can use for designing your templates:

Easiest way to create your single auction page with Elementor is to create new template for single product. There you can now add, rearrange and style Simple Auction elements like countdown, auction history, auction dates, auction max bid (for proxy), auction reserve price, sealed bid auction elements and auction bid form.

Auction product type will be recognized automatically and there is no need to add conditional for template. To create auction base page you will need to create new template type “Auctions Archive”:

To create auction base page you will need to create new template type “Auctions Archive”

Once template is designed you need to add condition as per screenshot below:

Add condition for “Auctions Archive” template

In Elementor Settings -> Experiments make sure that beta option “Landing Pages” is set to “inactive” otherwise you will have issues with lottery base page. See screenshot below:

Adding lottery countdown timer and progress bar to product archive / loop

We got quite a few inquries to display countdown timer and progress bar not only on single lottery page but in product archive / loop. This is covered in our documentation, FAQ item no 12 but we also made handy little plugin which enables those two code snippets with just few clicks and no need to edit functions.php file. You can download it here.

End result is shown on screenshot below. Plugin can be your base for further customizations.

WooCommerce Lottery resource and ticket limits – can user purchase 30 000 tickets at once?

Our plugin is basically limited with hosting solution that your WordPress installation runs on. There is no limit how many tickets can be sold at once or how many numbers can you list for lottery but usually on lower spec hosting (especially on cheaper shared hosting) you will hit limit around couple thousands ticket purchases – orders (around 3 000 to 5 000 orders). This would be same as if you would run regular WooCommerce web shop and problem is easily resolved by upgrading your hosting (you can contact us for suggestion).

There are couple of limits you can hit (for this example we will consider WordPress has only WooCommerce and our plugin installed and nothing else) – how many different users (orders) have purchased tickets in your store, more orders mean you need more resources for order data and its custom fields. Another is having a lot of tickets for a lottery say 1 million – this is not problem unless you want pick number table displayed which becomes cumbersome and we strongly suggest agains that (just use randomly assign ticket number instead). Sometimes lot of tickets cause JS issue in backend for auction history export table – for that we have option in Lottery Settings to disable this feature.

Cronjob that we suggest you install is lightweight and is used to finish lottery on time in case WordPress does not have enough traffic to run its internal cronjob. For busier websites this can be skipped, everything will work fine and in most cases lotteries will be ended on time.

When planning big lottery site with many orders you need to keep on your mind that except orders we log data to two log tables used by our plugins called wc_lottery_log and wc_lottery_pn_log which should not be big problem since only integer values are logged to those tables.

In general cheapest dedicated server (quad core cpu and 8GB – 16GB memory, normal disk drive no need for SSD) should enable site owner to run big lottery website with hundreds daily orders without performance issues. If you go for cloud solution you will need to get some mid priced solution since from our experience cheap cloud / vps proved to be problematic (probably due to heavy resource throttling done by their service providers). Further scaling can be done by separating app and db and have them on separate servers / vps or cloud instances.

We strongly suggest that before going to production you test all of these cases, for example try to purchase 1 million tickets or do some stress testing and see what is happening in your particular setup. You do not want to end up migrating website to new setup during marketing campaign and fixing things while orders are coming in.

Other than that we can suggest keeping number of active plugins to minimum, do some WordPress / WooCommerce optimization and use 3rd party / external SMTP server for mail notifications (offload main app server and better inboxing rates).

Icons missing in product list for auctions, lotteries and group buy / deals

We had a lot of inquries about missing icons in product type column WooCommerce product list. Users were asking why icons vanished in WooCommerce product list and how can they get it back. From WooCommerce 3.4.0 update, WooCommerce developers removed that column in product list (as a result of users’ feedback).

There is way to restore it back using this plugin https://wordpress.org/plugins/woocommerce-product-type-column/ so in case you are too missing this feature, download and activate this plugin and icons will be back in product list.

Using code snippets and template customizations in child theme

Every now and then you need to modify plugin or theme’s templates, add some code snippet or change couple things using CSS. Best way to include your changes and make them update proof is to do it via child theme. Child theme is special theme that loads parent theme files from parent theme folder and your customized files from child theme folder like templates and styles.

You need to have base (parent) theme like StoreFront (or Avada, Divi, any WooCommerce compatible theme will do just fine) and then you create new folder wp-content\themes\mycustomtheme\ with its own style.css and functions.php

Here is how to create child theme in 4 easy steps:

Step 1: create child theme folder for example /wp-content/themes/my-first-child-theme

Step 2: in that folder create style.css and functions.php filse, in style.css add code below:

/*
Theme Name: My Sample WordPress Child Theme
Theme URI: https://wpgenie.org
Description: StoreFront theme based child theme
Author: wpgenie
Author URI: https://wpgenie.org
Template: storefront
Version: 1.0
*/

Step 3: go to Appearance -> Themes and activate your newly created child theme.

Step 4: you can now add your modified templates to child theme folder, code snippets to your functions.php and custom CSS to your child theme’s style.css

Once you have customizations in your child theme you can now update plugin or theme without worries that your modifications will be lost during an update (theme or plugin update). ZIP with child theme described in this tutorial can be downloaded here (it will work only if you have installed StoreFront theme).

Detailed tutorial is here How to Create a Child Theme an article by WordPress about child themes.

For example you want to edit Simple Auction template from folder \woocommerce-simple-auctions\templates\single-product\bid.php – copy it to wp-content\themes\yourchildtheme\woocommerce\single-product\bid.php and make changes there. You will need some kind of file manager best is to use FTP client (for example FileZilla or file managed included in your hosting control panel).

Illustration from https://zenwp.co/child-theme/
How child theme templating works from https://zenwp.co/child-theme/

We have extensive archive of code snippets and modified plugin templates on our Pastebin archive.

WooCommerce Lottery and Pick Number addon Now with full Elementor support

elementor lottery

Today we have released version 2.0.0 for WooCommerce Lottery and Pick Number Mod addon which include full Elementor support. In today’s update there were few minor changes and fixes too and version has been bumped to v2.0.0 for both plugin and addon. To edit lottery template with Elementor you need Elementor (free) plus Elementor Pro (paid) or PRO Elements (free).

Couple of screenshots how it looks like Elementor support:

WooCommerce Lottery and Pick Number addon natively supported in Elementor

Easiest way to create your single lottery page with Elementor is to create new template for single product. Click on wp-admin menu entry Templates -> Add New and you will get modal popup like on image below:

There you can now create your new single lottery product page – add, rearrange and style Woo Lottery elements like countdown, progress bar, lottery winner, lottery info and Pick Number Mod elements like ticket numbers, lucky dip and question / answers.

In order not to have template applied to all single products, you need to tag or categorize lotteries and then apply template only to tag or category your lotteries are tagged / categorized with.

Make sure that in Elementor Settings -> Experiments beta option “Landing Pages” is set to “inactive” otherwise you will have issues with lottery base page. See screenshot below:

elementor landing pages experiment should be set to inactive

How to open support ticket – Support access problem – 401 API forbidden

We had couple of cases when, during access to ticket system, users might get 401 API forbidden error message. Here is quick explanation of what is really happening here and what is causing this error. Since our support system is integrated via CodeCanyon / Envato API to check and verify your purchase / licence you need to approve API access for your account. This is normally done during registration process (when you open our support page on this URL https://wpgenie.org/support without being logged in). When this process is skipped, support system cannot access data via API for your account and system displays that error.

To resolve that problem log out from Envato / CodeCanyon and then go to https://wpgenie.org/support click login and allow API access. Once this is done and you have valid purchase you will be able to open ticket.

In case you have purchased some addon from our website you can access ticket support system by going to My Account -> Orders and then in order row you will have option to download addon or get support. Please consult screenshot below.

In case you still have problem please contact us.