WooCommerce & Google Analytics Pro Setup

Often you use Google Analytics to track buyers. But a lot of beginners set up the bare basics only. You should do a WooCommerce & Google Analytics Pro Setup instead. One that allows you thorough tracking of all your customer transactions and movals on your site. One that shows you every step they take and how your goals are converting. In this blog post I will show you some great tips to do just that.

Google Analytics Goals

You want to track properly whether or not your product is being sold. That will be your end goal. The goal to sell and get paid is what you want of course. In Google Analytics you can set up goals to track your store goals. You can find them under admin:

Google Analytics Goals

Once you are there you can set up you own goal by clicking on the red “new goal button .

Revenue Goal

The type of goal we would go for here is a revenue goal. You are interested in making money after all. For that Google Analytics has a goal template ready:

Goal Template - revenue

Next step is to choose the type of revenue goal. We pick a destination.The trick is to use the WooCommerce order received page as the final step or destination. Once that page is reached it means your customer really went all the way and bought your product.

That is this slug:


In Google Analytics you indicate that under goal destination and you pick “begins with”:

Goal Destination

PayPal Caveat

If you do use PayPal you also have to make sure that the client is sent back to your store automatically and that the tracking continues. This you do by going to:

  • your profile
  • selling tools
  • website preferences

PayPal Setup

There you can choose to send users back to your store once paid automatically and add a utm slug to keep the tracking going.

PayPal Auto Return

The slug used for Imagewize is


And for you you would obviously have to change the domain to represent your shop. And that followed by the utm string: ?utm_nooverride=1 

Goal Funnel

I also recommend setting up a funnel to analyse the user’s behavior. It is very useful for example to find out where in the process the customer bailed. A few steps you could use are:

  • shop
  • product page
  • cart
  • checkout

This will depend of course on what your customer’s path will be. Some of you use the one page checkout. And in that case there may just be 2 steps. Or when you do use the shop page and then the product page you will need one step before the ones I made here:

GA Funnel

The one here starts at the product page as you can see. And I made it a required step. That is not always necessary nor desired though.

Google Analytics Ecommerce

To also track all transactions taking place you should also activate ecommerce on Google Analytics. This you can also do under admin > view. There you find the ecommerce settings option. Make sure you enable default and enhanced ecommerce to get all the goodness.

GA Ecommerce Setup

NB The abandoned cart plugin will also help of course.

Enhanced E-commerce for Woocommerce Store Plugin

Now to make the Ecommerce work well with WooCommerce and without the need to be a JavaScript ninja you need to install one plugin: Enhanced E-commerce for Woocommerce store.

Enhanced Ecommerce Google Analytics Plugin for WooCommerce

It will make it all work like a charm. Trust me it is pretty amazing. The commercial version of this plugin is even better, but this free one does most of what you need. Here is the shortlist with what it brings as told by them at WordPress:

  • Supports four New Reports in Enhanced Ecommerce
  • Shopping Behaviour Report
  • Checkout Behaviour Report
  • Product Performance Report
  • Sales Performance Report
  • Supports Guest checkout functionality
  • Supports Display Advertising Feature
  • Captures Product Impressions, Add to Cart & Product Clicks events on category page
  • Captures Product Impressions, Add to Cart & Product Clicks events on product page

As you can see it is pretty amazing, isn’t it?

Well once you have done all this tracking should have become pretty amazing. Good luck!

Bonus: Great general article on Google Analytics and Conversion Tracking

Can’t get enough? Subscribe to our mail list!

[gravityform id=”14″ title=”false” description=”false”]

[product id=”6934″]

Single Product WooCommerce Website

Sometimes you have an online store with one product or service to sell only. Sometimes that is because that is all you are selling, sometimes it is because you are just starting out. So how could you make the shop look good with a single product WooCommerce website?

Single Product Shop Layout

Oftentimes you will think that having a shop page is kind of overkill, but WooCommerce creates this page as it creates other pages like “My Account”, Cart and Checkout. So what should you do with this shop page? Well you could style it in such a way that the shop page looks a lot like the single product page. And then you could make it possible to directly put the item in the basket and go to the one page checkout. This way you will be bypassing the product page itself though that page will also exist.

Bypass Shop Page

Somehow that does not seem right to me. I would think it is better to have the product page and not have the shop page. So how could we do this? Well, we could make visitors skip the shop page, but building in a redirect to your product and by hiding the shop page by not mentioning it in the menu.

Helga the Viking mentioned a possible redirect option here:

function so_template_redirect(){
 if( function_exists( 'is_shop' ) && is_shop() ){
 $product_id = 999; // change to the ID of your 1 product
 $permalink = get_permalink( $product_id );
 wp_redirect( $permalink );
 add_action( 'template_redirect', 'so_template_redirect' );

Using the template_redirect a redirect can be done the WordPress way. I may be stating the obvious, but you need to add this code to the functions.php of your child theme or add it to a separate plugin perhaps dedicated to custom functions.

Presentation Single Product

The single product could be mentioned the navigation using the name shop or whatever you would like it to be. This way you create a single product WooCommerce website. A shop with one product that bypasses the superfluous shop overview page.

WooCommerce 2.7.0 Test Drive – Dealing with Deprecated Functions and Disallowed Direct Calls

Decided to test WooCommerce 2.7.0 beta 3 locally for my Ianua Theme. As a theme author it is always important to see if a whole new version works for you or not and if not to fix the issues. I realized a lot of code for single product page display was deprecated as functions got renamed and a lot of calls could not be made directly to the $product class anymore.

Deprecated get_gallery_attachment_ids

Ran into this PHP notice on single product pages. The function:


is now outdated and should be replaced by:


Steps to Reproduce this Error

This was the actual error message delivered by xdebug so very thorough:

 PHP Notice: WC_Product::get_gallery_attachment_ids is <strong>deprecated</strong> since version 2.7! Use WC_Product::get_gallery_image_ids instead. in /srv/www/ianua.imagewize.com/current/web/wp/wp-includes/functions.php on line 3828
 [01-Mar-2017 06:55:56 UTC] PHP Stack trace:
 [01-Mar-2017 06:55:56 UTC] PHP 1. {main}() /srv/www/ianua.imagewize.com/current/web/index.php:0
 [01-Mar-2017 06:55:56 UTC] PHP 2. require() /srv/www/ianua.imagewize.com/current/web/index.php:5
 [01-Mar-2017 06:55:56 UTC] PHP 3. require_once() /srv/www/ianua.imagewize.com/current/web/wp/wp-blog-header.php:19
 [01-Mar-2017 06:55:56 UTC] PHP 4. include() /srv/www/ianua.imagewize.com/current/web/wp/wp-includes/template-loader.php:74
 [01-Mar-2017 06:55:56 UTC] PHP 5. include() /srv/www/ianua.imagewize.com/current/web/app/themes/ianua/base.php:80
 [01-Mar-2017 06:55:56 UTC] PHP 6. wc_get_template_part() /srv/www/ianua.imagewize.com/current/web/app/themes/ianua/single-product.php:16
 [01-Mar-2017 06:55:56 UTC] PHP 7. load_template() /srv/www/ianua.imagewize.com/current/web/app/plugins/woocommerce/includes/wc-core-functions.php:173
 [01-Mar-2017 06:55:56 UTC] PHP 8. require() /srv/www/ianua.imagewize.com/current/web/wp/wp-includes/template.php:686
 [01-Mar-2017 06:55:56 UTC] PHP 9. do_action() /srv/www/ianua.imagewize.com/current/web/app/themes/ianua/woocommerce/content-single-product.php:48
 [01-Mar-2017 06:55:56 UTC] PHP 10. WP_Hook->do_action() /srv/www/ianua.imagewize.com/current/web/wp/wp-includes/plugin.php:453
 [01-Mar-2017 06:55:56 UTC] PHP 11. WP_Hook->apply_filters() /srv/www/ianua.imagewize.com/current/web/wp/wp-includes/class-wp-hook.php:323
 [01-Mar-2017 06:55:56 UTC] PHP 12. woocommerce_show_product_images() /srv/www/ianua.imagewize.com/current/web/wp/wp-includes/class-wp-hook.php:298
 [01-Mar-2017 06:55:56 UTC] PHP 13. wc_get_template() /srv/www/ianua.imagewize.com/current/web/app/plugins/woocommerce/includes/wc-template-functions.php:840
 [01-Mar-2017 06:55:56 UTC] PHP 14. include() /srv/www/ianua.imagewize.com/current/web/app/plugins/woocommerce/includes/wc-core-functions.php:203
 [01-Mar-2017 06:55:56 UTC] PHP 15. WC_Abstract_Legacy_Product->get_gallery_attachment_ids() /srv/www/ianua.imagewize.com/current/web/app/themes/ianua/woocommerce/single-product/product-image.php:25
 [01-Mar-2017 06:55:56 UTC] PHP 16. wc_deprecated_function() /srv/www/ianua.imagewize.com/current/web/app/plugins/woocommerce/includes/legacy/abstract-wc-legacy-product.php:159
 [01-Mar-2017 06:55:56 UTC] PHP 17. _deprecated_function() /srv/www/ianua.imagewize.com/current/web/app/plugins/woocommerce/includes/wc-deprecated-functions.php:48
 [01-Mar-2017 06:55:56 UTC] PHP 18. trigger_error() /srv/www/ianua.imagewize.com/current/web/wp/wp-includes/functions.php:3828

System Status Report

System status report did mention I had several files that were outdated. Those were all the WooCommerce files I heavily edited to display the store as I needed with custom queries and custom html and JavaScript voodo.

### WordPress Environment ###

Home URL: https://ianua.dev
 Site URL: https://ianua.dev/wp
 WC Version: 2.7.0
 Log Directory Writable: ✔
 WP Version: 4.7.2
 WP Multisite: –
 WP Memory Limit: 256 MB
 WP Debug Mode: ✔
 WP Cron: –
 Language: en_US

### Server Environment ###

Server Info: nginx/1.11.5
 PHP Version: 7.1.0-3+deb.sury.org~xenial+1
 PHP Post Max Size: 50 MB
 PHP Time Limit: 120
 PHP Max Input Vars: 1000
 cURL Version: 7.47.0

SUHOSIN Installed: –
 Max Upload Size: 50 MB
 Default Timezone is UTC: ✔
 fsockopen/cURL: ✔
 SoapClient: ❌ Your server does not have the SoapClient class enabled - some gateway plugins which use SOAP may not work as expected.
 DOMDocument: ✔
 GZip: ✔
 Multibyte String: ✔
 Remote Post: ✔
 Remote Get: ✔

### Database ###

WC Database Version: 2.7.0
 WC Database Prefix: wp_
 woocommerce_sessions: ✔
 woocommerce_api_keys: ✔
 woocommerce_attribute_taxonomies: ✔
 woocommerce_downloadable_product_permissions: ✔
 woocommerce_order_items: ✔
 woocommerce_order_itemmeta: ✔
 woocommerce_tax_rates: ✔
 woocommerce_tax_rate_locations: ✔
 woocommerce_shipping_zones: ✔
 woocommerce_shipping_zone_locations: ✔
 woocommerce_shipping_zone_methods: ✔
 woocommerce_payment_tokens: ✔
 woocommerce_payment_tokenmeta: ✔
 MaxMind GeoIP Database: ✔

### Security ###

Secure connection (HTTPS): ✔
 Hide errors from visitors: ❌Error messages should not be shown to visitors.

### Active Plugins (10) ###

Gravity Forms: by rocketgenius – 2.0.7
 Ianua Projects: by Imagewize – 1.2.1
 Regenerate Thumbnails: by Alex Mills (Viper007Bond) – 2.2.6
 WPML Multilingual CMS: by OnTheGoSystems – 3.6.2
 WooCommerce PayPal Express Checkout Gateway: by Automattic – 1.1.2
 WooCommerce: by Automattic – 2.7.0-beta-3
 WordPress Importer: by wordpressdotorg – 0.6.3
 WPML CMS Nav: by OnTheGoSystems – 1.4.19
 WPML String Translation: by OnTheGoSystems – 2.5.1
 WPML Translation Management: by OnTheGoSystems – 2.2.6

### Settings ###

API Enabled: ✔
 Force SSL: –
 Currency: EUR (€)
 Currency Position: left
 Thousand Separator: ,
 Decimal Separator: .
 Number of Decimals: 2
 Taxonomies: Product Types: external (external)
 grouped (grouped)
 simple (simple)
 variable (variable)
 ### WC Pages ###

Shop base: #235 - /shop/
 Cart: #236 - /cart/
 Checkout: #237 - /checkout/
 My account: #238 - /my-account/

### Theme ###

Name: Ianua
 Version: 1.0.0
 Author URL: https://ianua.com
 Child Theme: ❌ – If you're modifying WooCommerce on a parent theme you didn't build personally
 then we recommend using a child theme. See: How to create a child theme

WooCommerce Support: ✔

### Templates ###

Overrides: ianua/archive-product.php version - is out of date. The core version is 2.0.0
 ianua/woocommerce/single-product/product-image.php version 2.6.3 is out of date. The core version is 2.7.0
 ianua/woocommerce/single-product/related.php version 1.6.4 is out of date. The core version is 2.7.0
 ianua/single-product.php version - is out of date. The core version is 1.6.4

Outdated Templates: ❌Learn how to update

So I knew there were things I had to check out or fix. Just did not realize there were quite a few issues I had to deal with.

Product Image Template

So I checked product-image.php as that is where I deal with product images as I should.

Path to file:


and on line 25 I had:

$attachment_ids = $product->get_gallery_attachment_ids();

and as stated get_gallery_attachment_ids is outdated or deprecated. So I replaced it by get_gallery_image_ids . And this worked and the image gallery came back again without the error notice.

get_display_price Deprecated

And then other issues showed up. The function:


is outdated as well. So we had to deal with this too. The exact PHP notice in brief was:

Notice: WC_Product::get_display_price is <strong>deprecated</strong> since version 2.7! Use wc_get_price_to_display instead. in /srv/www/ianua.imagewize.com/current/web/wp/wp-includes/functions.php on line 3828

I found it inside:


on line 1046:

 echo '<div class="six columns tab-whole product-content right"><span class="price">$' . $product->get_display_price() . '</span>';

I have it as part of an action I added as a replacement of

add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );

Just replacing it with wc_get_price_to_display() got me another error

Fatal error: Uncaught Error: Call to undefined method WC_Product_Simple::wc_get_price_to_display() in /srv/www/ianua.imagewize.com/current/web/app/themes/ianua/lib/extras.php on line 1046

So I added:


which worked. It was inspired by the new:


And this worked like a charm. Will do some more testing later on of course. But let’s move on to the other notices shall we?

product_type called directly

Then I had a product_type called directly notice. Another direct call notice stating this should not be done basically.

[01-Mar-2017 06:55:56 UTC] PHP Notice:  product_type was called <strong>incorrectly</strong>. Product properties should not be accessed directly. Please see <a href="https://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a> for more information. (This message was added in version 2.7.) in /srv/www/ianua.imagewize.com/current/web/wp/wp-includes/functions.php on line 4136

NB Woo Poly Integrations had similar issues mentioned in a ticket at their Github repo.

This was in the same extra.php file on line 1066:

 do_action( 'woocommerce_' . $product->product_type . '_add_to_cart' );

That is what happens when you use many filters. Might need to get rid of some of these soon. Anyways, I realized it now has to be


based on /plugins/woocommerce/includes/class-wc-product-simple.php line 33. Again I may need to do some more testing.

Get_related is deprecated

Had a get_related is outdated notice:

[01-Mar-2017 08:18:11 UTC] PHP Notice:  WC_Product::get_related is <strong>deprecated</strong> since version 2.7! Use wc_get_related_products instead. in /srv/www/ianua.imagewize.com/current/web/wp/wp-includes/functions.php on line 3828

line 29 of the theme’s single-product/related.php I had

if ( ! $related = $product->get_related( $posts_per_page ) ) {

wc_get_related_products which again caused a fatal error as it could not find the method. This was I as I had it all wrong and just need to run the function and necessary arguments. So turned it into:

if ( ! $related = wc_get_related_products( $product->get_id(), $args['posts_per_page'] )) {

And now all product were displaying well.


There also seems to be a new file for working with sliders in single products (beta one blog post mentions it here. It is Photoswipe. Somehow the code was injected at the bottom of the page in the footer. So I added my own in woocommerce/single-product/photoswipe.php . One with only the header code:


 * Photoswipe markup
 * This template can be overridden by copying it to yourtheme/woocommerce/single-product/photoswipe.php.
 * HOWEVER, on occasion WooCommerce will need to update template files and you
 * (the theme developer) will need to copy the new files to your theme to
 * maintain compatibility. We try to do this as little as possible, but it does
 * happen. When this occurs the version of the template file will be bumped and
 * the readme will list any important changes.
 * @see https://docs.woocommerce.com/document/template-structure/
 * @author WooThemes
 * @package WooCommerce/Templates
 * @version 2.7.0

This as I use my own flex slider based one. That took care of that issue. I may use it for other projects though.

Backend Product Editing Issues

What I currently do have is working on the product details does not go well. It seems I cannot switch tabs to let’s say inventory or shipping. Will do some testing on this a little later on. Could be the fact that WooCommerce 2.7.0 is beta after all. But that seems to be an Advanced Custom Fields issue as I found this JavaScript error:

Uncaught Error: Option 'ajax' is not allowed for Select2 when attached to a <select> element.
 at String.<anonymous> (select2.js?ver=3.5.2:930)
 at Function.each (jquery.js?ver=1.12.4:2)
 at constructor.prepareOpts (select2.js?ver=3.5.2:928)
 at constructor.prepareOpts (select2.js?ver=3.5.2:2601)
 at constructor.init (select2.js?ver=3.5.2:690)
 at HTMLSelectElement.<anonymous> (select2.js?ver=3.5.2:3391)
 at Function.each (jquery.js?ver=1.12.4:2)
 at jQuery.fn.init.each (jquery.js?ver=1.12.4:2)
 at jQuery.fn.init.$.fn.select2 (select2.js?ver=3.5.2:3378)
 at HTMLSelectElement.<anonymous> (wc-enhanced-select.js?ver=2.7.0:115)


Custom Product Tabs for WooCommerce

Sometimes you need more tabs for your products. Sometimes the descriptions tab, reviews and attributes tab are not enough. You may need a tab with directions on how to use the product, a tab on ingredients of the product or a tab displaying all available sizes. So let’s talk about adding custom product tabs for WooCommerce. How can you add an additional tab to the product page?

WooCommerce Product Tabs Filter

To add a custom product tabs for WooCommerce you can follow WooCommerce’s guidelines and add the following to your functions.php file:

add_filter( 'woocommerce_product_tabs', 'woo_new_product_tab' );
function woo_new_product_tab( $tabs ) {
 // Adds the new tab
 $tabs['test_tab'] = array(
 'title' => __( 'New Product Tab', 'woocommerce' ),
 'priority' => 50,
 'callback' => 'woo_new_product_tab_content'

return $tabs;

function woo_new_product_tab_content() {

// The new tab content

echo '<h2>New Product Tab</h2>';
 echo '<p>Here\'s your new product tab.</p>';

You will of course have to adjust the code to your liking. So you should at least:

  • $tabs label
  • title – pick you own title
  • priority – set the priority of the tab – perhaps it should come first?
  • callback – add the name of the function loading the tab data

So something like:

$tabs['ingredients'] = array(
 'title' => __( 'Ingredients' ),
 'priority' => 10,
 'callback' => 'ianua_product_ingredients_tab'

should do the trick just fine.

Tab Contents Callback Function

Inside the code above we also added the function being the one loading the content in the tab:

function woo_new_product_tab_content() {

// The new tab content

echo '<h2>New Product Tab</h2>';
 echo '<p>Here\'s your new product tab.</p>';

So the filter is followed by the function loading the content. Later on we shall see we did not do the same and used a template tag woocommerce_get_template to load the code from another file.

Content to Load

What would you like to load in the tab and how would you like to display it? For that you need to create a function and add it to your functions.php file or include it somehow. You could load custom field data using a custom field added to product pages. And that is what we are going to do and that is also what most developers would do.

Creating Custom Fields

To create the custom field you could use Advanced Custom Fields (free or premium) or GenerateWP (Premium version for meta boxes) for example. Or you use the built in option and generate them on the product page. Does not look really pretty though. You can code them yourself too of course. For just one or two custom fields ACF would be overkill really but you could use it locally to generate the fields and then export them as PHP to add to your theme. AND you would need to include ACF in your theme.

Advanced Custom Fields Custom Field

To create a meta box or custom field in ACF you just to to advanced custom fields in the backend. Code I created in like a minute would be:

if( function_exists('acf_add_local_field_group') ):

acf_add_local_field_group(array (
 'key' => 'group_5881d7c5ba966',
 'title' => 'Product Page Meta Boxes',
 'fields' => array (
 array (
 'key' => 'field_5881d81b4ad68',
 'label' => 'Ingredients',
 'name' => 'ingredients',
 'type' => 'textarea',
 'instructions' => 'Fill in the ingredients for the product here',
 'required' => 0,
 'conditional_logic' => 0,
 'wrapper' => array (
 'width' => '',
 'class' => '',
 'id' => '',
 'default_value' => 'Text to be added here',
 'placeholder' => '',
 'maxlength' => '',
 'rows' => '6',
 'new_lines' => 'wpautop',
 'location' => array (
 array (
 array (
 'param' => 'post_type',
 'operator' => '==',
 'value' => 'product',
 'menu_order' => 0,
 'position' => 'normal',
 'style' => 'default',
 'label_placement' => 'top',
 'instruction_placement' => 'label',
 'hide_on_screen' => '',
 'active' => 1,
 'description' => '',


As stated this will not work without advanced custom fields included in your theme. So if you feel like this is overkill it would be better to add your own code.

Clean Generated Meta Box code

Coding yourself takes some time like I said and there is a site where you can generate a custom field for free. One that uses native code. It has been created by Jeremy Hixon and can be found here. I created one for WooCommerce products with a text area and the code looks like this:


 * Generated by the WordPress Meta Box generator
 * at http://jeremyhixon.com/tool/wordpress-meta-box-generator/

function ingredients_get_meta( $value ) {
 global $post;

$field = get_post_meta( $post->ID, $value, true );
 if ( ! empty( $field ) ) {
 return is_array( $field ) ? stripslashes_deep( $field ) : stripslashes( wp_kses_decode_entities( $field ) );
 } else {
 return false;

function ingredients_add_meta_box() {
 __( 'Ingredients', 'ingredients' ),
 __( 'Ingredients', 'ingredients' ),
add_action( 'add_meta_boxes', 'ingredients_add_meta_box' );

function ingredients_html( $post) {
 wp_nonce_field( '_ingredients_nonce', 'ingredients_nonce' ); ?>

<p>Product Ingredients</p>

 <label for="ingredients_product_ingredients_text"><?php _e( 'Product Ingredients Text', 'ingredients' ); ?></label><br>
 <textarea name="ingredients_product_ingredients_text" id="ingredients_product_ingredients_text" ><?php echo ingredients_get_meta( 'ingredients_product_ingredients_text' ); ?></textarea>

function ingredients_save( $post_id ) {
 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
 if ( ! isset( $_POST['ingredients_nonce'] ) || ! wp_verify_nonce( $_POST['ingredients_nonce'], '_ingredients_nonce' ) ) return;
 if ( ! current_user_can( 'edit_post', $post_id ) ) return;

if ( isset( $_POST['ingredients_product_ingredients_text'] ) )
 update_post_meta( $post_id, 'ingredients_product_ingredients_text', esc_attr( $_POST['ingredients_product_ingredients_text'] ) );
add_action( 'save_post', 'ingredients_save' );

 Usage: ingredients_get_meta( 'ingredients_product_ingredients_text' )

It does miss a couple of elements though like how many rows you would like to have and the text domain. And the meta key here is not as we have it inside the filter so that needs adjusting too. The new generator does have the text domain, but the amount of rows is not an automated option yet. Five rows are added by default. But that you could adjust that in the code yourself.

Basic Custom Field

Besides ACF or hand made meta boxes you could just use the built in version as long as aesthetics is not paramount. When you just want to add one in your product you need to make sure custom fields are active in screen options:

Custom Fields Active

and then you will see this block underneath your product text to add a new custom field:

Add a new Custom Field

Make sure the key (= name)  and value are the ones you use in your function to call them inside your theme. And that you of course save the custom field. Once that is done you can load it for all products.

Custom Callback Code

Here is the code to grab the custom field data:

global $woocommerce, $post;
if ( !empty($post->post_content) ) : ?>
 <?php $heading = apply_filters('woocommerce_product_description_heading', __('Product Description', 'woocommerce')); ?>
<h5><?php echo $heading; ?></h5>
<?php echo get_post_meta($post->ID, 'Ingredients', true); ?>
<?php endif; ?>

As you can see we use get_post_meta . That is the best way to grab a meta key or value. We added this code inside a separate ingredients.php file which we added under single-product/tabs and we load it with:

function ianua_product_ingredients_tab() {
 woocommerce_get_template( 'woocommerce/single-product/tabs/ingredients.php' );

but you could also add the code inside the filter itself as is shown above in the basic filter.


If your theme is styled for tabs properly already this should work and look well.  But if not you can always add specific classes andor wrap the code in a div to target that tab or all tabs more specifically. In my case so far it worked fine in several themes out of the box.

Final Custom Product Tab

So if all went well you were able to create a custom product tab for WooCommerce that is loaded under all products, either as a basic custom field, an ACF custom field or a custom generated custom field. And you added the necessary filter and function to load the tab as the next tab in line.


Extending WooCommerce Storefront

When you are installing the Storefront theme as discussed in our earlier post WooCommerce Storefront Theme Configuration you are given a teaser with options to extend WooCommerce Storefront. A couple of enhancements using plugins as well as possible child themes are mentioned. Let’s go through them in this post.

Storefront Enhancing Plugins

Storefront recommend a couple of plugins you can use to extend it, to make it easier to work with this theme as well enhance it with more features. Here is the list of the plugins for extending WooCommerce Storefront:

  • Powerpack ($59)
  • Mega Menus ($39)
  • Reviews ($19)
  • Pricing Tables ($19)
  • Product Hero ($19)
  • Blog Customizer ($19)
  • Parallax Hero ($19)

NB  Addons only works with Storefront

As you can see these are all commercial plugins that you need to pay for. They are not for free as WordPress is. Well, I would say WordPress is not really for free either as it will require your time and $ to make it work for your business too, but that is another debate. Do I think some of these plugins are useful?


Well the Powerpack is not cheap, but it is an interesting extension. It is an addon that basically allows you to customize way more elements of your theme in the customizer without the need for extra coding in a child theme or plugins. What does it allow you to do more besides what you can in Storefront is:

  • header customization including logo, cart and navigation
  • styling – adjust font families, font size color, margins and padding
  • checkout options – option to go for distraction free checkout or keep two step checkout
  • homepage editor – basic homepage editor to add calls to action and configure general layout
  • product page editor – edit product page layout

Powerpack Features

Mega Menus

Must say I find it a bit expensive for a menu enhancement, but it is a solid mega menu that offers multiple options to create a solid mega menu dropdown to show store items with or without images. And it allows you to drag and drop multiple types of widgets inside the menu from the customizer. And Magento has extensions for similar or more expensive prices.


Storefront Mega Menu


A lot of themes have basic reviews built in when they are catering to the e-commerce crowd and there are universal WordPress review plugins out there so you do not really need this one per se. But this is a solid review plugin with multiple display options. You can

  • display it as a slider or in blocks,
  • use three styling options and there is a
  • review scope you can configure to display certain specific reviews, reviews from certain products, load the most ones recent first

Pricing Table

A lot of themes do have pricing tables built in. Either via a page builder like Visual Composer or simply as a custom post type. So what does this addon have to offer that we may like? Well, nothing much really besides the fact that the customizing can be done in the customizer. So I am not that impressed really.

Pricing Tables

Product Hero

This is more like a slider that integrates well with Storefront and WooCommerce. But frankly as I am using Revolution Slider already that can do that and more I do not see the advantage of using this Product Hero slider.

Product Hero

Blog Customizer

The blog customizer is a useful addon. What it does it that it allows you to pick a certain blog layout. You may like the classical one after another blog article look or the magazine look with several next to each other. It also allows you to move the post meta data around. This means you can decide where the sidebar with additional information goes, if the category and tag details should go to the end of the post or just below the title and so on.

However, most multi purpose themes with or without a builder or even with the builder alone will allow you to do this all. So if you are going for a page builder like Beaver Builder or the Visual Composer you can probably go without this addon.

Parallax Hero

Parallax scroll or the display of content parallax style has been popular since 2012 or s0. Designer Depot mentioned this on it in 2013 in a blog post:

parallax scroll is when content scrolls at different speeds, creating a sense of perspective and therefore depth.

Some clients really love it for blogs, others for the homepage. Well, the parallax hero can enhance your Storefront Hero header with the parallax hero scroll effect. I do (no longer ) like this effect and I think it is a bit outdated now. But it is an easy implementation of it. So if you, or your client, likes it go ahead and purchase this addon.

Child Themes

There are a whole bunch of child themes available and all for just $39 bucks. So if the style of Storefront is not appealing to you and you do not want to code your own child theme to change its looks you should have a look at the child themes available.

Storefront Child Themes

Now, I think the WooCommerce team, nowadays a part of Automattic, does a solid job coding these themes and design wise there are some really nice ones. So do have a look. The advantage here is that these all work with Storefront and saves you the extra coding. It may still be needed that you want further tweaks. In that case it is better to convert a child theme into a new version. The only downside as always is that updates for that child theme can then no longer be applied with ease. But hey if the child theme gets you closer to your goal then go for it!

Child Themes in Detail

I won’t be discussing the child themes in detail now. What I will do is that I will create a new post in the future on adding one of these child themes and my and or my client’s experience with that particular theme. This post took quite some time already and is rather large and insightful already so hope you are happy with the content for this blog post as it is for now.

WooCommerce Related products, Up-Sells and Cross-Sells Explained

When you work with WooCommerce products there are several ways to stimulate customers to buy other products. Often we talk about related or recommended products when we talk about products we want customers to buy on top of the one they are considering buying or put into their cart. In WooCommerce speak we talk about related products, up-sells and cross-sells. Let’s go through WooCommerce Related products, Up-Sells and Cross-Sells one by one here, shall we?

Related Products

Related products are products that are loaded below an individual product when they have something in common. They are related in some way. This commonality can be based on two things:

  • tags the product is tagged with
  • categories the product is under

So, to make related products work, or at least work on product pages you have to do the following. You should give your product tags so they can share those among each other and connect or relate that way. The other option is to put the products into categories. That way they can be connected by category. If you do not do either one of these related products won’t work well.


Upselling means suggesting more expensive or better quality products for example. These products can be added manually to each product in the backend. You do this under product data (simple product) > linked products field:

Linked Products

When you click on the field it will ask you to add three characters so it can try to guess the product you want to connect it to:

Up-sells Search


Cross selling – suggesting product on the cart page before customers goes to the checkout – is something else. It does work in the same way as up-sells in the backend. You add cross-sells the same way. Where it differs is that cross-sells are offered in the cart view:

WooCommerce Cross-Sells

So if you would like to make customers buy other products before they go to the checkout cross-sells are the way to go.



Well, I think we covered WooCommerce Related products, Up-Sells and Cross-Sells pretty well here. Do make sure you use these options. They will helop you increase your sales. Displaying related products, doing cross-sells or up-sells  simply work really well. In increases your bottom line big time. That is why big stores use these techniques.

What is not covered here is trying to sell products on the checkout page nor suggested sales based on history or email campaigns suggesting products based on past sales. For that I will create another blog post or two one of these days.


WooCommerce – DIY One Page Checkout

To improve conversion on your WooCommerce website a one page checkout page is very useful. When you allow customers to skip the cart page and go directly to checkout this will make it easier for them to buy an item. This reduces the rate of potential customers dropping out during the buying process. A whopping one in ten people drop out because the checkout process is too long – Webcredible Poll. And that makes sense in this age of everything on demand, smartphones and Google doesn’t it. We do not like waiting. So let’s deal with this shall we? Let’s build a DIY One Page Checkout!

DIY One Page Checkout Prerequisites

There are paid plugins that help you with direct checkout, product button options and all on one checkout pages. There is for example WooCommerce Direct Checkout Pro. But this direct checkout plugin does not do all that is needed. You after all still need a checkout page that loads cart details, but not all cart view details.

There are also a couple of One Page Checkout plugins like WooCommerce One Page Checkout and One Page Shopping , but again they do not really offer what we need. The former offers custom one page checkouts while we want this to be for all products. The latter has a demo that currently is not working and support that is lacking.

There may be others that I have missed of course, but let’s go the DIY way and set all up ourselves shall we? Let’s build a DIY One Page Checkout setup.

To set up the whole one page checkout there are several things we have to take care of. To achieve better lead conversion and get your customers to buy using direct checkout you need the following:

  • Redirect to Checkout on clicking “add to cart”
  • Title change of “add to cart” to buy now or “process to checkout”
  • Add Cart or view cart details on checkout page
  • Checkout Cart Notice – Should not be loaded as it will be irrelevant

Direct Checkout

To get the add to cart button, not just add your product to the customer’s shopping cart, but send him directly to the cart you can add the following code to your theme’s functions.php

add_filter('add_to_cart_redirect', 'theme_prefix_add_to_cart_redirect');
function theme_prefix_add_to_cart_redirect() {
 global $woocommerce;
 $checkout_url = $woocommerce->cart->get_checkout_url();
 return $checkout_url;

This code will make the “add to cart” button redirect to the checkout page. This way the view cart is bypassed.

Product “Add to Cart” Button Change

To change the button text from “add to cart” to “proceed to checkout” or “buy not” there are two action hooks you can use. One to replace the text on the product archive page or shop page and one action to replace the text on the single product page.

To change the “add to cart” text on the single product page add the following filter:

add_filter( 'woocommerce_product_single_add_to_cart_text', 'woo_custom_cart_button_text' ); // 2.1 +
function woo_custom_cart_button_text() {
 return __( 'Proceed to Checkout', 'woocommerce' );

To change the “add to cart” text on the shop page add the following filter:

add_filter( 'woocommerce_product_add_to_cart_text', 'woo_archive_custom_cart_button_text' ); // 2.1 +
function woo_archive_custom_cart_button_text() {
 return __( 'Proceed to Checkout', 'woocommerce' );

Cart Content Display on Checkout

To load the cart view or cart contents at the top of the checkout page before the billing forms you can just add the shortcode for the cart before the checkout shortcode on the checkout page.

[woocommerce _ cart]
[woocommerce _ checkout]

NB Spacing added to avoid real display

This will then show the full cart on the checkout page. A lot easier than dealing with this using custom code. There may be a good action or filter for it, but I have not found one as of yet.

Abridged Cart View on Checkout

The issue with the cart loading as we are doing with the shortcode  is that the coupon code option will then be shown twice. To hide this in the cart display table use this CSS:

.woocommerce-checkout div.coupon {display:none;}

.woocommerce-checkout td > input.button {display:none;}

I may add an action or filter for this too at a later stage. But this CSS option does the trick and does not force you to add a checkout template to your-theme/woocommerce folder and tweak it. I prefer to avoid WooCommerce templates in child themes as you then depend on updates in WooCommerce AND the parent theme.

Hiding Cart Notice

It does not make sense to show the cart notice on the checkout page. The cart overview will be there already so no need to have this notice with a link to the cart. Especially if you have a cart icon with these options in the main navigation already. Use this CSS to hide this notice completely:

.woocommerce-checkout .woocommerce-message {display: none !important;}


And there you have it. A DIY One Page Checkout all done with all the tweaks needed:

  • direct to checkout from product or shop page
  • proceed to checkout or buy now button text
  • checkout cart notice removed
  • checkout page with cart overview

As mentioned here and there, some solutions could perhaps be replaced with better ones. Certainly the CSS tweaks would be better done as actions or filters. However until I find better and easier options these will work wonderfully well for you and me!


Disclaimer: All tested with Total Theme Child Theme

Keeping Local WooCommerce Site in Synch with Live Site

Been working locally on a WooCommerce site. Changed permalinks, changed the theme, using local theme supported FAQ instead of plugin based FAQ on live. Also dropped a Text based widget in favor of a menu widget and changed the slider. And some other stuff. So I changed a lot. In the meanwhile there have been orders as well as AWeber newsletter subscriptions. So how do I deal with keeping the local WooCommerce site in synch with live site?

Options to Keep Local and Production in Synch

Mind you, synchronization of files is not the issue here. That can be done with version control such as Git. Or in my case not an issue really as the client won’t update content or products so no new files will be added. The database synchronization is the issue.

Well there are three things you can do to keep your WooCommerce Stores in synch. You can export the products, variations,orders, refunds, coupons and webhooks  using the WordPress export tool and import them. Two, you can use the Customer/Order/Coupon CSV Import Suite . This way they do keep in synch. The other way is just to leave database synching alone and update the live site with file changes and update the database by activating and changing content live. Here the three options in detail with pros and cons.

WordPress Importer

This can be done using the slightly buggy WordPress Importer Tool. I have used it before for importing and exporting basic content from one site to another. I have also used table export and import. And it does offer the option to export:

  • Products
  • Variations
  • Orders
  • Refunds
  • Coupons
  • Webhooks – see docs

There will be issues though as it is kind of buggy – new tools in the works for ages – and not a WooCommerce only tool. So definitely not my first choice.

Customer/Order/Coupon CSV Import Suite

Then you think well, let’s use the WooCommerce Addon – the Customer/Order/Coupon CSV Import Suite – mentioned earlier. That should do the job. Well, not quite apparently according to Mike Jolly. Mike Jolley, a WooCommerce Developer stated in this WordPress support thread that:

I think it’s safer to move code than move data, imo anyway. Especially if it’s constantly changing.

That makes sense and shops of course do change constantly. But sometimes, and I my case, it would be nice to do so. It would be great to move all files and the database once all is done and in the meanwhile keep things in synch.

There is another bigger issue he mentions though with exporting and importing WooCommerce data. And that is worse:

The orders you import may have different IDs due to auto-incrementing IDs in the database. The problem is IDs may differ from your emails + records.

So you could later on have issues with order IDs not matching emails and records. And that would be a big problem. However, Mike Jolley talked about this 8 months ago. Seems like the latest Customer/Order/Coupon CSV Import Suite can do more now .

woocommerce customer coupon order import suite

Since June 2016 it can merge customer, order and coupon data that is. Isn’t that cool!  Still, you could of course have to cough up $79, but that certainly can be worth it in many situations including mine. The main issue I was having is a difference in orders. And this addon should help me with that.

Updating Live with Local Site Data

The final option is just to not keep the database locally and on production in synch. You could test all needed changes locally and do them on live when all is done. That does mean more downtime or maintenance time. This as you would have to move all changed files, added theme, and plugins to live first. Activate them there. Then configure them and adjust content when need be. So this option really depends on how confident you are you can do all this in the maximum downtime allotted by you and your client.

What to Choose?

Well, in my case I will probably go for leaving database synchronization alone for now. I have not tested that addon and I prefer not to spend extra $ on this project now. I may use it in the future though. And if you read this post and are a developer with experience using that addon do leave me a comment. And if you are an end user, well perhaps the addon is the right choice for you. It does sound like an awesome tool and Skyverge is a solid company.

PS I do hope Delicious Brains will have Mergebot up and running soon so I do no longer have to deal with these database synch issues – post on it here.

Footnote Image of the White Rabbit in Alice in Wonderland by John Tenniel is in the in public domain

WooCommerce Featured Products Page

Sometimes you would like to have a homepage with WooCommerce featuring products or a separate page to show of your current trending products. In that case you need to create a template that loads certain WooCommerce products. That and some code voodoo.

For the HumbleShop theme we have implemented this for a customer before. Let me show you what code is needed and what it does. If you prefer the full template see the final chapter of this post. Just remember that we load no. of featured items from the theme options page here.

Featured Products Custom Query

To load the featured products you need a custom query with arguments to load them. For that we use the WP_Query class. The custom arguments we added to it are:

  • post type
  • no of featured products per page
  • pagination
  • meta query loading the proper meta key and value
 $num = ot_get_option( 'hs_homefeatno' );
 $paged = ( get_query_var('page') ) ? get_query_var('page') : 1;
 $args = array( 'post_type' => 'product', 'posts_per_page' => $num, 'paged' => $paged );
 $args['meta_query'] = array(); 
 $args['meta_query'][] = array(
 'key' => '_featured',
 'value' => 'yes'
 $loop = new WP_Query( $args );
 while ( $loop->have_posts() ) : $loop->the_post(); global $product; ?>
 <?php wc_get_template_part( 'content', 'product' ); ?>
 <?php endwhile; ?>

With the arguments discussed further below you can start a new instance of WP_Query to load the the featured products. As you can see we added $product as a global variable. This to make the variable available outside the local scope. Reason for using WP Query is to customize the loop ( awesome Treehouse blog post on WordPress Loops) .

Post Type

WooCommerce creates the post type product so we add that as our custom post type to be loaded. It is a custom post type to be precise. WordPress has five post types or content types and they are:

  • page,
  • posts
  • attachments and
  • revisions
  • navigation menu items

WordPress allows you to add your own and WooCommerce takes care of that for us creation products.

Featured Items Theme Option

To add the no. of featured items to display we added an extra item to the theme options. You could hard code it as well, but this is much more convenient. HumbleShop uses the theme options Options Tree by Valet Designs. Their repository is here in case you want to learn more about it.

Here below the option we added:

 'id' => 'hs_homefeatno',
 'label' => 'Number of Featured Products',
 'desc' => 'Number of featured products you want to display on homepage',
 'std' => '9',
 'type' => 'text',
 'section' => 'general',
 'rows' => '',
 'post_type' => '',
 'taxonomy' => '',
 'min_max_step'=> '',
 'class' => '',
 'condition' => '',
 'operator' => 'and'

We load the number added with the code:

ot_get_option( 'hs_homefeatno' )

ot_get_option being an Options Tree option


The $paged variable activates pagination for the featured product page. It uses the get_query_var function. The same snippet and more details can be found in this codex article. Basically it loads pagination for the current page. Without it the pagination navigation won’t work. You can add pagination links with the code below:

<nav id="home-products-nav">
 <?php previous_posts_link( '&laquo; PREV', $loop->max_num_pages) ?></li>
 <?php next_posts_link( 'MORE PRODUCTS &raquo;', $loop->max_num_pages) ?>

It works thanks to the earlier added pagination in the custom query.

Meta Query

Meta_Query is part of the WP_Meta_Query class. It is an argument of that class and an array at that. It can contain the meta key (custom field key) and value (custom field value). And this is needed here as we need to check whether a product is featured and if so add it to the loop.

WooCommerce Product Content

Once the loop has been started up we load the products with this WooCommerce request:

wc_get_template_part( 'content', 'product' );

WooCommerce Get Template Code is documented here and the function in detail can be checked here. It looks for the WooCommerce template in your theme root or woocommerce folder inside your theme and then grabs that content. We have woocommerce/content-product.php in the child theme that can be loaded.

NB woocommerce_get_template_part is deprecated and


is the new WooCommerce template tag and recommended now. It has been deprecated since WooCommerce 2.1

After all that code has been added the while loop will be closed. All should be well and then content should be loaded. Pagination loading follows below it, but we covered that discussing the pagination argument for the WP_Query earlier.

Full Template Code

Here below is the full template code we use for displaying the featured posts on the homepage for our HumbleShop child theme. As you can see we load a slider as well. This and some other snippets and html tags we need to display all well. This piece of code and others you can leave out of course.

Just like any other page template you can this one to your theme’s root.

 Template Name: Homepage
 get_header(); ?>

<!-- ============ -->
 <!-- MAIN SECTION -->
 <!-- ============ -->
 <div class="container">
 <section class="feat">

<?php get_template_part( 'slider', 'index' ); ?>

<div class="row">

<!-- Content -->
 <div class="col-xs-12">
 <?php while ( have_posts() ) : the_post(); ?>

<div class="row">


<div class="row">
 <div class="col-xs-12">
 <?php do_action('woocommerce_before_shop_loop'); ?>

<div class="products clearfix">
 $num = ot_get_option( 'hs_homefeatno' );
 $paged = ( get_query_var('page') ) ? get_query_var('page') : 1;
 $args = array( 'post_type' => 'product', 'posts_per_page' => $num, 'paged' => $paged );
 $args['meta_query'] = array();
 $args['meta_query'][] = array(
 'key' => '_featured',
 'value' => 'yes'

$loop = new WP_Query( $args );
 while ( $loop->have_posts() ) : $loop->the_post(); global $product; ?>

<?php wc_get_template_part( 'content', 'product' ); ?>

<?php endwhile; ?>
 <nav id="home-products-nav">
 <?php previous_posts_link( '&laquo; PREV', $loop->max_num_pages) ?></li>
 <?php next_posts_link( 'MORE PRODUCTS &raquo;', $loop->max_num_pages) ?>

<?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'humbleshop' ), 'after' => '</div>' ) ); ?>
 <?php edit_post_link( __( 'Edit', 'humbleshop' ), ' <p class="text-center"><i class="fa fa-pencil"></i>', '</p>' ); ?>
 <?php endwhile; // end of the loop. ?>

 $brand = ot_get_option( 'hs_brand' );
 $brandlist = ot_get_option( 'hs_brandlist' );

if ($brandlist) { ?>
 <h5 class="subhead theme brands"><strong><?php echo $brand; ?></strong></h5>

<div class="tab-brand">
 <div id="flexcarousel-brands" class="flexslider">
 <ul class="slides">

<?php foreach($brandlist as $key => $value) {
 echo '<li>';
 if ($value['hs_brandimage']) {
 echo '<img src="'.$value['hs_brandimage'].'" alt="'.$value['title'].'" />';
 } else {
 echo '<img src="http://cambelt.co/200x100" />';
 echo '</li>';
 } ?>

 <?php } ?>


<?php get_footer(); ?>

WooCommerce Customer Loyalty Tips

Just today I read a great post by Nicole Kohler at WooCommerce It had some great tips on improving customer loyalty for WooCommerce users. Here my take on her WooCommerce Customer Loyalty Tips.

Pre Purchase Strategy Downsides

I have a lot of customers that do work with pop-ups and often then offer a discount right away. This seems to be a good way to get customers on board, but perhaps not the best one long term. If you can reward a customer for when he returns you can make more customers happy long term and get them to come back for that second order.

Post Purchase Reward

A reward after a purchase seems like an interesting strategy and perhaps better than the off the bat discount for the first purchase. This as a repeat customer tends to be way more valuable than a one of buyer. So this way you can hit multiple birds / customers with one stone. And we can all agree that is a great outlook.

Multiple Purchases Rewards

Buying a certain product multiple times should be rewarded too. This can be done giving discounts or reward badges like big players like Target do. Basically you should build something into your WooCommerce store to reward customers if they:

  • buy certain items multiple times or
  • buy from certain categories multiple times
  • belong to special groups like veterans

Dynamic Pricing Extension

WooCommerce also has an extension to dynamically adjust pricing based upon customer purchases. Totally new to me to be honest, but this sounds really awesome. This extension automatically can adjust the price based on

  • amount of products or
  • customer user role (silver members, gold members,…) or
  • product category

You can configure this all with is from the backend and adjust again when need be. Sounds like a great WooCommerce extension doesn’t it!

Members Only Programs

She also mentioned other tips such as loyalty programs for members only. So giving additional or general discounts for people who become a member. You could create bronze, silver and gold membership programs for example and give each its own discount category. Many malls globally do this and people do love these deals.

There are many member websites already out there that I know of. I do think many entrepreneurs have thought about this or tried this out. But this might be harder to get started at the beginning stages. Still something to keep in mind though.