How to add Bootstrap columns to WooCommerce Shop Page

If you prefer the Bootstrap Grid System over the default woocommerce column setup then it requires a few lines of code to get going.

This is one of many ways to accomplish our goals.

  • Create our grid-based container
  • Add our column classes to the products in the container
  • Close the container

Open our bootstrap container

First open up a new div with .row to house our products by hooking into woocommerce_product_loop_start.

function gerrg_woocommerce_product_loop_start(){
     * opens up any category and shop pages as a boostrap row.
    return '<div id="gerrg-archive" class="row">';
add_filter('woocommerce_product_loop_start', 'gerrg_woocommerce_product_loop_start', 999);

Add bootstrap .col-* to products

Now we need to add bootstrap colomn classes to woocommerce products by hooking into the woocommerce_post_class filter.

  • .col-6 – 1/2 the row on mobile
  • .col-sm-3 = 1/4 the row on small displays
  • .col-xl-2 = 1/6 the row on large displays
function gerrg_add_bootstrap_cols_to_product( $class ){
     * adds bootstrap grid classes to all category and shop pages.
    $class[] = 'col-6 col-sm-3 col-xl-2';
    return $class;

add_filter('woocommerce_post_class', 'gerrg_add_bootstrap_cols_to_product', 30, 3);

Wrapping things up

Finally we close up our shop row and have a functional bootstrap grid system on all woocommerce shop, category & taxonomy pages.

Just like be began, we adding some html to close our div by hooking into the woocommerce_product_loop_end filter.

function msp_woocommerce_product_loop_end(){
     * closes up any category and shop pages
    return '</div>';
add_filter('woocommerce_product_loop_end', 'msp_woocommerce_product_loop_end', 999);

You did it!

Good job, if you have any questions or concerns or have a better way to succeed than above


How to add Free Gifts on Woocommerce Programmatically

A client wanted a free pack of blades to be automatically added to when a customer added 20 knives to their cart.

This seemed like good information to share for aspiring “woocommerce store owners / developers”.

If you have any questions, please feel free to reach out.


So here is what we have to do to get this to work.

  1. Write down the ID’s of the items you wish to target and the reward.
  2. Create a check for the condition (20 of the target in the cart)
  3. Add the reward if not already in the cart
  4. Make the reward free and check bugs.

Find the product ID’s

So first we need to learn which item’s we want to target. An easy way to find the ID is to login to the backend and go to the products tab.

Simple Products

Hover a product in the products tab to display the ID. Use that to target.

For simple products we need only to over the product to see it’s ID.


Variations as you know are individual products that make up a variable product.

To find the ID of a variation, edit a variable product, go to the variations tab and they will be listed on the left hand side.

Edit a variable product and go to the variations tab to find variation ID’s

So for our example, we are going to keep it simple and just use Pants, Shirts & a Hat.

  • Pants – ID: 553, Type: Variable
  • Hat – ID: 562, Type: Simple

I suggest you write your target & reward ID’s before proceeding, it will make customizing your code to work with your setup much easier, IMO.

Target the product ID’s

Now we will jump into the code.

First add this helper function we will use later to check if a product is in the cart.

function gerrg_get_product_cart_key( $product_id ){
	$product = wc_get_product( $product_id );

	if( ! $product ) return;

	return ( $product->is_type( 'variation' ) ) ? WC()->cart->generate_cart_id( $product->get_parent_id(), $product->get_id() ) : 
												  WC()->cart->generate_cart_id( $product->get_id() );

We are hooking into wp because we want this to run on every page load.

add_action( 'wp', 'gerrg_programically_add_to_cart' );

Open up your function and include a check to prevent this from running on the admin side (it causes an error).

function gerrg_programically_add_to_cart(){
	 * Looks for hard coded ID's in $targets array, check if ID meets product quantity and adds reward if so
	if( is_admin() ) return;

Next create a targets array, include the ID of all items you wish to target.

For variable products you must use the variation ID’s. I am targeting all sizes of a specific shirt.

These are the variations I am targetting. All sizes of a shirt.
// setup needles
$targets = array( 558, 559, 560, 561 );

Next set the reward, for me I am targeting a hat.

// free gift ID
$reward = 562;

This next bit is just a fancy woocommerce method of checking if something is in the cart.

We will use the helper method you added earlier to generate a cart key to pass to woocommerce to check for the item we are rewarding (otherwise they’d get so many!).

// key for quick searching in cart
$reward_item_key = WC()->cart->find_product_in_cart( gerrg_get_product_cart_key( $reward ) );

Now we will loop through the cart and look at EACH item in the cart.

foreach( WC()->cart->get_cart() as $cart_item ){

We make sure to use the ID given, sometimes working between different product types can cause problems.

// get real ID
$id = ( $cart_item['variation_id'] === 0 ) ? $cart_item['product_id'] : $cart_item['variation_id'];

Now we will loop through each ID in our $targets array.

// loop needles
foreach( $targets as $target ){

Now we are going to add the condition. In this specific circumstance, I need 3 things to be true.

  • The target ID is in the cart
  • That item has a quantity of 3 or more.
  • and finally, the reward is not ALREADY in the cart.
// if needle in haystack, quantity over 20 && reward not in cart
if( $target === $id && $cart_item['quantity'] >= 20 && ! $reward_item_key ){

Add the reward to the cart.

// Add reward
WC()->cart->add_to_cart( $reward );

Close everything up.

Discount the free gift

Now we are going to need to make that free gift free.

We have to hook into woocommerce_cart_calculate_fees to discount the free gift.

// this is where fees are calculated
		add_action('woocommerce_cart_calculate_fees', 'gerrg_discount_free_gift' ) );

Then add the following function

function discount_free_gift( $cart ){
		 * Look for free gift in cart, discount item if in cart.
		 * @param WC_Cart
		$product = wc_get_product( $this->reward );
		if( ! $product ) return;
		$reward_item_key = WC()->cart->find_product_in_cart( $this->get_product_cart_key( $this->reward ) );
		foreach( WC()->cart->get_cart() as $cart_item ){

			$id = ( $cart_item['variation_id'] === 0 ) ? $cart_item['product_id'] : $cart_item['variation_id'];

			foreach( $this->targets as $target ){

				if( $target === $id && $cart_item['quantity'] >= 20 && $reward_item_key ){

					// Meets all condititions? Add discount (fee).
					$cart->add_fee( 'Free Gift', ( $product->get_price() * -1), true  );

Very similar to the last function we loop the cart and check if the targets are in the cart, the quantity is met AND the reward is in the cart as well.


If you want to skip to the chase, download the plugin.


How to setup SSH Keys (TL DR;)

SSH Keys are wonderful and easy to set up. You can SSH keys to quickly log into a remote server (like your website) from the command line WITHOUT a password prompt.

How does it work?

Essentially SSH works by generating two keys (strings) on your machine: a public and a private one. You place the public key on a external server and when you log in the server makes the connection and access is granted.

How do I do it?

Setting up SSH can be done in as little as two steps:

  1. Generate SSH key Pair
  2. Copy public key to remote server (where you want to login)

Generate SSH Key Pair

First generate the SSH key pair with ssh-keygen.

ssh-keygen -t rsa

You will be asked where you want to store the file and whether or not you want a password, I just click ENTER twice.

Copy the public SSH key

Use ssh-copy-id to quickly move the public SSH key to the remote server.


You must know the username of server you are trying to access.


How to Setup WP-CLI on WordPress Server

Setting up WP-CLI is super easy and can be done in just a few steps.


First download WP-CLI using curl or wget.

curl -O

Next check if it worked.

php wp-cli.phar --info 

To make things easier, make the wp-cli.phar file an executable.

chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp

sudo: command not found

If you don’t have sudo powers there are a number of things you can do:

Easy Way

You can use the relative path to the wp-cli.phar file.


Best Way

A better solution would be to create an alias to run the same command as above with less keystrokes.

Open up your .bashrc file and add this line to the bottom

# User specific aliases and functions
alias wp="~/wp-cli.phar"

Re-source your .bash_profile and run wp --info.

source .bash_profile
wp --info

You did it!

Ruby on Rails

How to add Bootstrap 4 to your Ruby on Rails Application

Luckily adding Twitter Bootstrap 4 to your ruby on rails application is not too complex.

Here’s the quick and dirty steps to adding bootstrap to your rails application.

Launch your app

Move into your existing application directory or run rails new myapp to create a new application.

Add the bootstrap and jquery gems to your Gemfile.

gem 'bootstrap', '~> 4.4.1'
gem 'jquery-rails'

Run bundle install --verbose (it may take a while).

Restart your server if you have it running. This is an important step for ensuring bootstrap is available in the applications pipeline.

Import styles in application.scss

Rename the default app/assets/stylesheets/application.css to a .scss file.

mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss

Remove all the *= and *= require_tree statements to have access to Bootstrap mixins and variables.

Importing bootstrap at app/assests/stylesheets/application.scss

Add jQuery

Bootstrap 4 relies on jQuery for all the JavaScript heavy lifting.

Earlier we added the ‘jquery-rails gem’ and ran bundle install.

Now all we have to do is add bootstrap dependencies to our app/assests/javascripts/application.js

//= require jquery3
//= require popper
//= require bootstrap
Add bootstrap dependencies to your application.js file.

Check the source code

To test that bootstrap was added to our applications assets pipeline, launch the server and check the source code.

Checking the applications source code for links to bootstrap.

You did it!

What did we do?

  • Added the Bootstrap and Jquery gems to our Gemfile and ran bundle install --verbose.
  • Renamed our application.css to a .scss file and added @import "bootstrap";
  • Added jQuery dependancies to application.js
  • Confirmed what we did by launching the app and checking the source code.
Ruby on Rails

How to setup Rails App for Heroku

If you want to host your Ruby on Rails application with Heroku- your database must be PostgreSQL.

Unfortantely, it can be difficult to get setup if you’ve never done anything like use the Heroku CLI or manually create databases in psql.

Here are the quick and dirty steps for setting up your rails application for hostign on heroku.

Install Heroku

If you haven’t installed heroku-cli, that is step number one.

Visit the download instructions to figure out how to install heroku.

For me (xubuntu) I used snap.

sudo snap install --classic heroku

Next, you’ll be prompted to setup/login with Heroku.

Create the application

If you are starting from scratch, run the rails new command and specify you want a postgreSQL database (since thats what heroku requires).

rails new myapp –database=postgresql

Move into your new application and run bundle install.

cd myapp
bundle install
Bundle complete! 18 Gemfile dependencies, 78 gems now installed.

Test the databases

For my setup, I have to manually create the databases in PostgreSQL.

Run the following commands, using your application’s name instead of myapp.

CREATE DATABASE myapp_development;

If psql didn’t work or needs to be setup, I wrote a short post about getting setup with PostgreSQL.

Go back into your application and run rails db:migrate to test your databases were added correctly.

No error message? Good!

Create a welcome page

Rails 5.x no longer includes a default page in a production environment.

So we will have to make one! First create a controller.

rails g controller pages home

Now create a home.html.erb file in the app/views/pages/ directory.

Add some simple HTML to the homepage.

<a href=""> Learn to build a Rails Application and Host with Heroku</a>

Finally add the route to the newly create homepage. Open up config/routes.rb and add the following line.

root 'pages#home'

Open up your terminal and launch your server with rails server.

Add it to Github

Now that you’ve got your self a fancy new rails application complete with default page in production environments…

Its time to add it to GitHub before we host the application on Heroku.

Setup repository on GitHub: add, commit and push application.

git add -A
git commit -n 'init commit'
git push

Your push will not work if you haven’t setup your remote origin. In fact, you’ll get an error message about it.

Host on Heroku

Okay so far we have:

  • created our rails application
  • setup our postgreSQL databases
  • built a default page for our production environment
  • and created a repository on github.

Finally, we are going to host our rails application with Heroku and have our site out there on the world wide web.

Run Heroku create to create a repository with Heroku, then push your application from git to Heroku.

heroku create
git push heroku master
This push will take a while and you will see lots of scary messages… just let it finish.

If the command completes, the push was complete and you should be able to visit your application with heroku open.

you did it!

Ruby on Rails

How to fix “A server is already running.” error in Ruby on Rails

Luckily this is an easy fix. You error message will more accurately say something along the lines of:

A server is already running. Check /home/greg/odin/spitter/tmp/pids/

If you run cat on the file referenced in the message, it will return a 5 digit number like 30351.

cat /home/greg/odin/spitter/tmp/pids/ returns the ID of the process.

30351 is the ID of the process running the current rails server. Run kill -9 30351 to end the process and free up room for a new server.

You are now free to run rails s to boot up the server.


How to Match & Index with Excel & LibreOffice Calc

Match and index is a super useful tool that has personally saved me hours of manual copy and pasting of information.

Instead there is a better way. All you need is two sets of data, and a point where they match.

In my experience, I’ve used this to match two price lists based on SKU and easily copy over UPC codes, weight, our cost and other useful information you may want to upload to your wordpress database or whatever.

Here is a brief example of how to do this- it works on Microsoft Excel and LibreOffice Calc.

Essentially, we are going to use the MATCH and INDEX functions common on most spreadsheet programs to copy over some data (like price) based on a match in the same row (like SKU).

INDEX(the column you want to copy, MATCH(the cell you want to match, the column of data you are matching against))

Keep in mind

Match sure all data is formatted the same way; strings will not match numbers.

Make sure you make the row absolute (A$5).

Ruby on Rails

How to create PostgreSQL database for Ruby On Rails

This is a note to myself and those who are interested.


I use Heroku for hosting my Ruby on Rails applications. Problem is, Heroku doesn’t support SQlite databases.

If you’ve ever tried to run rails db:migrate to create a postgesSQL database WITHOUT first setting up the databases manually, you will recognize this error:

rails aborted!
ActiveRecord::NoDatabaseError: FATAL:  database "spitter_development" does not exist

Setup a PostgreSQL database

Run the following command.


If you get this error, your package manager did not setup your user account up properly.

createdb: database creation failed: ERROR:  source database "template1" is being accessed by other users

Run the createdb command.

$ createdb
$ psql
psql (10.10 (Ubuntu 10.10-0ubuntu0.18.04.1))
Type "help" for help.

Create the databases

Once you are in psql, run \list to see all the databases on your server (service)

before we add the databases

Now run the CREATE DATABASE command followed by the name of your rails applications and finally suffixed with _development and _test respectively.

Dont forget the semi-colons! ( ; )

CREATE DATABASE yourapp_development;
CREATE DATABASE yourapp_test;

Run the \list command again to confirm your databases were added correctly.

with new databases added

How to create a WordPress plugin

Creating the plugin

WordPress plugins make it easy for anyone to modify a WordPress website.

First, create the folder ‘gerrg-wordpress-plugin‘.

Next create the main PHP file ‘gerrg-wordpress-plugin.php‘.

cd ~
mkdir gerrg-wordpress-plugin
touch gerrg-wordpress-plugin/gerrg-wordpress-plugin.php

Next open up the .php file you just created with your favorite code editor ( I like VS Code ).

code gerrg-wordpress-plugin/gerrg-wordpress-plugin.php

File Headers

The file header contains all the plugin information like: name, description, author and licensing.

Copy the following into your gerrg-wordpress-plugin.php file:

 * Plugin Name:       Gerrg WordPress Plugin
 * Plugin URI:
 * Description:       Allows the admin to implement BOGO marketing rules
 * Version:           0.5
 * Author:            Gerrg
 * Author URI:
 * License:           GPL v2 or later
 * License URI:
 * Text Domain:       gerrg
 * Domain Path:       /languages

defined( 'ABSPATH' ) or die( 'No script kiddies please!' );

Testing the plugin

Before we get started, lets actually make sure that our plugin is setup properly.

First we are going to add some code to the plugin which simply outputs ‘Hello’. Next we will move the folder to the wp-content/plugins directory. Finally, we will activate our plugin and check for the ‘Hello’ on our webpage.

echo ‘hello’

First add the following code to the bottom of your .php file.

add_action( 'wp_head', 'gerrg_say_hello' );

function gerrg_say_hello(){
    echo 'hello';

If you are not familiar with the WordPress Plugin API, in the code above we are simply adding an action to a hook. A action is simply a function, a hook is a SPOT in the code where that function will run.

Above we are adding our gerrg_say_hello function to the wp_head hook. The wp_head hook is triggered between the <head></head> section of the website.

Simply put, we expect to see ‘hello’ at the top of our webpage.

Activating your plugin

It’s very likely you already know how to activate a plugin. First we need to move our folder into the wp-content/plugins directory of our web server.

There is more than one way to do this and I leave it to you get accomplish this task.

mv gerrg-wordpress-plugin ~/www/wp-content/plugins/

The above code is a simple linux command for moving my plugin folder into the wp-content/plugins directory of my web server.

After moving the plugin, log into your admin section of your WordPress website. Navigate to the plugin section you should see the Gerrg Woocommerce BOGO plugin.

Plugin section featuring the plugin we just created…

Click activate and navigate the the homepage. In the top left corner of the screen you should see a simple ‘hello’.

If you see the ‘hello’ message than your plugin is ready to actually do something useful.

Congrats! You’ve created your very own plugin.