Customizing WooTickets for the Events Calendar by Modern Tribe

Today we’ll run through how you can customize the relatively new WooTickets feature for Events Calendar by Modern Tribe.

By default the system will show something like this (within your given theme, of course):


That’s fine and all, they’re creating a basic form that will hopefully fit into any theme somewhat decently. But we want something a bit more fabulous, right? Let’s do it.

Theme Files

Similar to how other theme modifications in Event Calendar work, we’ll need to copy a file from the plugin to your theme. Specifically, copy tickets.php from /wp-content/plugins/wootickets/views/wootickets/ into a folder called wootickets inside a folder called tribe-events…so what you’re left with is this file setup:


Now we can customize that file, similar to any theme template file, to our heart’s content.

Customizing the Template File

I want to make a few modifications. Specifically:

  1. Change the title of the checkout form.
  2. Set the quantity of tickets to be purchased to 1 by default (instead of 0).
  3. Get rid of the table layout for something a little easier to work with in CSS.

Let’s dive in!

Change the Title of the Checkout Form

This is the easiest. I want to change it because I prefer a call to action rather than the label of “Tickets”.

Find this line of code:

<h2 class="tribe-events-tickets-title"><?php _e( 'Tickets', 'tribe-wootickets' );?></h2>

I shorten that right up to this:

<h2 class="tribe-events-tickets-title">Get Your Tickets!</h2>

Shazaam, now we’re coding with fury!

Setting the Quantity to Default to 1 instead of 0

Nobody wants to buy 0 tickets, why give them one more step to complete when trying to make a purchase. Luckily, this is another easy fix.

Find this PHP code:

woocommerce_quantity_input( array( 'input_name' => 'quantity_' . $ticket->ID,
'input_value' => 0,
'min_value' => 0,
'max_value' => $product->backorders_allowed() ? '' : $product->get_stock_quantity(), ) );

And change the input_value to 1 (or higher if it fits your situation). This removes the requirement that they click the up arrow or type in a 1 to begin with, and they can still change the value later if they’d like.

You end up with:

woocommerce_quantity_input( array( 'input_name' => 'quantity_' . $ticket->ID,
'input_value' => 1,
'min_value' => 0,
'max_value' => $product->backorders_allowed() ? '' : $product->get_stock_quantity(), ) );

Get the Layout out of a Table

I do understand that this can be considered tabular data, and certainly if you were purchasing multiple tickets which needed to be displayed before you click the Add to Cart button this would be useful. But that doesn’t even seem to be a possibility with the current way the plugin works. So let’s ditch tables.

You could search through all of the code manually on your own, or just grab my updated version below:

<?php global $woocommerce; ?>
<form action="<?php echo esc_url( add_query_arg( 'wootickets_process', 1, $woocommerce->cart->get_cart_url() ) ); ?>"
class="cart" method="post"
$is_there_any_product = false;
$is_there_any_product_to_sell = false;
foreach ( $tickets as $ticket ) {
global $product;
if ( class_exists( 'WC_Product_Simple' ) ) {
$product = new WC_Product_Simple( $ticket->ID );
} else {
$product = new WC_Product( $ticket->ID );
$gmt_offset = ( get_option( 'gmt_offset' ) >= '0' ) ? ' +' . get_option( 'gmt_offset' ) : " " . get_option( 'gmt_offset' );
$gmt_offset = str_replace( array( '.25', '.5', '.75' ), array( ':15', ':30', ':45' ), $gmt_offset );
$end_date = null;
if ( ! empty( $ticket->end_date ) ){
$end_date = strtotime( $ticket->end_date . $gmt_offset );
$end_date = strtotime( tribe_get_end_date( get_the_ID(), false, 'Y-m-d G:i' ) . $gmt_offset );
$start_date = null;
if ( !empty( $ticket->start_date ) )
$start_date = strtotime( $ticket->start_date . $gmt_offset );
if ( ( !$product->is_in_stock() ) || ( empty( $start_date ) || time() > $start_date ) && ( empty( $end_date ) || time() < $end_date ) ) {
$is_there_any_product = true;
echo sprintf( "<input type='hidden' name='product_id[]' value='%d'>", $ticket->ID );
echo "<div class='ticket-sales'>";
echo "<p><strong>";
echo $ticket->name;
echo ":</strong> ";
echo "<span class='tickets_price'>";
echo $this->get_price_html( $product );
echo "</span> ";
echo "<em>";
echo $ticket->description;
echo "</em>";
echo "</p>";
if ( $product->is_in_stock() ) {
woocommerce_quantity_input( array( 'input_name' => 'quantity_' . $ticket->ID,
'input_value' => 1,
'min_value' => 0,
'max_value' => $product->backorders_allowed() ? '' : $product->get_stock_quantity(), ) );
$is_there_any_product_to_sell = true;
} else {
echo "<span class='tickets_nostock'>" . esc_html__( 'Out of stock!', 'tribe-wootickets' ) . "</span>";
$contents = ob_get_clean();
if ( $is_there_any_product ) { ?>
<h2 class="tribe-events-tickets-title">Sign Up!</h2>
<?php echo $contents; ?>
<?php if ( $is_there_any_product_to_sell ) { ?>
<button type="submit" class="button alt"><?php esc_html_e( 'Buy Tickets', 'tribe-wootickets' );?></button>
} ?>

Let’s keep going though, because all we’ve really done at this point was removed the tables and ditched some built in styling. Add the following to your CSS file:

span.tickets_price {
background: green;
font-weight: bold;
font-size: 35px;
padding: 10px;
border-radius: 50px;
display: inline-block;
width: 100px;
height: 100px;
line-height: 230%;
.quantity.buttons_added {float:right;}
.ticket-sales button.button {
float: right;
background: green;
color: white;
font-weight: bold;
font-size: 20px;
clear: both;

Which, everything said and done, leaves us with:


Which I think looks a bit slicker and more obvious than what is output by default. You know, for when it’s all about the sales!

Even if you don’t love my final layout, this should give you a solid basis to make whatever changes you’d like for your own site!

Up Next: The Impact of a Lack of Page Refresh