HOW TO: Display Extra Meta Data For Ticketed Events on a Woocommerce Shop Page

Home Forums Ticket Products Event Tickets Plus HOW TO: Display Extra Meta Data For Ticketed Events on a Woocommerce Shop Page

  • This topic has 5 replies, 3 voices, and was last updated 7 years ago by Adam.
Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #1260071
    Adam
    Participant

    This is just a “HOW TO” I wanted to share on what I did to customise Woocommerce to display more useful event / ticket information on the shop page under each event. I wasn’t sure where to submit it, so if this the wrong place my apologies. I just thought some people may find it helpful.


    So, before I start:

    1. This isn’t that hard to do, but you do need to be comfortable editing WordPress config files like functions.php, and using a database tool like phpmyadmin. If not, then stop and get someone who is to follow this.
    2. If you follow this and it messes up your site I take no responsibility. However, if you take the usual precautions before starting this, like making sure your site is FULLY backed up, if you do run into problems you can restore your site back to its former glory.
    3. This is specifically for the Woocommerce e-commerce plugin. The principles are “likely” to be valid for whatever e-commerce plugin you use (if it uses posts to store product information), BUT you will need to adjust accordingly.
    4. “Tickets” created by Event Tickets Plus are instantiated as Woocommerce “Products” as far as Woocommerce is concerned. So, whenever I talk about Woo products, think Event Ticket Plus tickets – and vice versa.
    5. This assumes you’re using Woo’s default templates and / or widgets. If you have customised templates this should still work, but bear in mind you may need to adjust your customised templates.

    Got all that? Okay then, let’s begin.

    <span style=”text-decoration: underline;”>Introduction</span>

    I have The Events Calandar (Free) and Event Tickets Plus, and I use Woocommerce as the e-commerce platform. All work well together and do pretty much all I need managing and selling tickets for events.

    However, one of the things I really wanted was better, fuller information on the ticket products when displayed on Woocommerce shop pages.

    I knew I could update / add to the relevant post types between Woo and Events, or create custom fields. But that meant manually having to remember to update those fields if things needed changing with the event. Also the data was already there in one form or another, and I didn’t want to duplicate stuff.

    Knowing the data was already there I thought it couldn’t be that hard getting the data I wanted displayed where I wanted it. I didn’t find much on the forum / knowledgebase specifically dealing with this so I thought I’d share what I did here as I’m sure I’m not the only one who wants to do this.

    The default product display in Woocommerce (whether it’s tickets, T-shirts or kettles) is a grid of products showing a product image (if there is one), the title of the Product, maybe a short description, the product’s price, and button or link allowing you buy it or add it to the shopping cart.

    Now, that’s all well and good. But I wanted to show more information under the product image than that. Plus, I wanted the button to say “Event Details”, and for it to take the customer to the detailed event page. If you are happy with the default button’s text and behaviour then just ignore the section below dealing with that.

    So, what did I want to be displayed under the product’s image, apart from just the event title and price? Well, I thought it needed to show the event’s date and start time, summary venue information, and ticket availability. Re the latter I don’t mean how many tickets are available. I personally don’t like to show that. What I mean is displaying one of four coloured status messages indicating purchasability.

    The attached picture illustrates the final result using mock events showing all four possibe stock status messages.

    Of course, those are my choices. You can use the methods described here to display any meta data values in use, e.g. the number of tickets sold / remaining etc.

    <span style=”text-decoration: underline;”>UNDERSTANDING THE DATA AND WHERE IT LIVES</span>

    The purpose of this section is to explain how I determined what to use and where to find it. Ultimately my investigation identified what and where the right data could be found, so that I could build a hook function for extracting it automatically. The reason for illustrating that process here is so if you want different stuff displayed you can use this to help you find what you need so you can modify the function at the end to use the specific data you want to see. Skip to the function below if you just want to implement it as I have set it up.

    NOTE: All Woo ticket products (from Event Tickets Plus) and all Events (from The Event Calendar) are stored as posts.

    Once you have figured out what you want to show, probably the hardest bit is determining what and where that data is held. Essentially it will be in one of two places. Either Event post meta data, or Woocommerce product post meta data.

    To find the Woocommerce meta data I examined the WordPress database itself. You can skip to the sample output below to save time, but bear in mind that future updates to Woo and / or Event Tickets Plus and / or The Event Calendar may add / remove / modify keys listed.

    So to do this yourself you can use whatever tool you like for that but I used phpmyadmin (the following assumes you know how to use a tool like phpmyadmin to view database tables / run queries etc – if not, skip ahead to the output).

    If you view the database you’ll see many tables listed. The one we’re interested in is has a name of: xxxxx_postmeta (where xxxxx will be whatever prefix was generated when wordpress was originally installed). If you view that table you will see all the post meta data for the whole site. We really want to see what meta_keys exist for tickets.

    To do that we need to run a simple query against a ticket post. So first we’ll need to get the post ID of a ticket (any one will do). To do that, from the WordPress Dashboard, under Woocommerce, click on Products. All the products will be listed on the right. Click on Edit on any one that is a ticket. The post ID (e.g. 315) is in the URL in the browser address bar, e.g. …/wp-admin/post.php?post=315&action=edit

    Entering simple query below will list all of the meta_keys for that ticket. Replace the two “xxxx”s with your own database prefix, and “PPP” with the post ID you found.

    SELECT meta_key , meta_value <br />FROM <span style="color: #ff0000;">xxxx</span>_postmeta<br />WHERE post_id = <span style="color: #ff0000;">PPP</span> <br />ORDER BY <span style="color: #ff0000;">xxxx</span>_postmeta.meta_key ASC

    SAMPLE WOO TICKET OUTPUT:

    <table style=”height: 1031px;” border=”1″ width=”401″ cellspacing=”1″ cellpadding=”4″>
    <tbody>
    <tr>
    <td style=”text-align: center;” width=”190″>meta_key</td>
    <td style=”text-align: center;” width=”138″>meta_value</td>
    </tr>
    <tr>
    <td width=”190″>_backorders                   </td>
    <td width=”138″>no</td>
    </tr>
    <tr>
    <td>_crosssell_ids                </td>
    <td>a:0:{}</td>
    </tr>
    <tr>
    <td>_downloadable                 </td>
    <td>no</td>
    </tr>
    <tr>
    <td>_edit_last                    </td>
    <td>2</td>
    </tr>
    <tr>
    <td>_edit_lock                    </td>
    <td>1490437846:2</td>
    </tr>
    <tr>
    <td>_featured                     </td>
    <td>no</td>
    </tr>
    <tr>
    <td>_global_stock_cap             </td>
    <td>0</td>
    </tr>
    <tr>
    <td>_global_stock_mode            </td>
    <td>own</td>
    </tr>
    <tr>
    <td>_height                       </td>
    <td> </td>
    </tr>
    <tr>
    <td>_length                       </td>
    <td> </td>
    </tr>
    <tr>
    <td>_manage_stock                 </td>
    <td>yes</td>
    </tr>
    <tr>
    <td>_price                        </td>
    <td>25</td>
    </tr>
    <tr>
    <td>_product_attributes           </td>
    <td>a:0:{}</td>
    </tr>
    <tr>
    <td>_product_image_gallery        </td>
    <td> </td>
    </tr>
    <tr>
    <td>_product_version              </td>
    <td>2.6.14</td>
    </tr>
    <tr>
    <td>_purchase_note                </td>
    <td>0</td>
    </tr>
    <tr>
    <td>_regular_price                </td>
    <td>25</td>
    </tr>
    <tr>
    <td>_sale_price                   </td>
    <td> </td>
    </tr>
    <tr>
    <td>_sale_price_dates_from        </td>
    <td> </td>
    </tr>
    <tr>
    <td>_sale_price_dates_to          </td>
    <td> </td>
    </tr>
    <tr>
    <td>_sku                          </td>
    <td>JSE5</td>
    </tr>
    <tr>
    <td>_sold_individually            </td>
    <td> </td>
    </tr>
    <tr>
    <td>_stock                        </td>
    <td>20</td>
    </tr>
    <tr>
    <td>_stock_status                 </td>
    <td>instock</td>
    </tr>
    <tr>
    <td>_tax_class                    </td>
    <td> </td>
    </tr>
    <tr>
    <td>_tax_status                   </td>
    <td>taxable</td>
    </tr>
    <tr>
    <td>_thumbnail_id                 </td>
    <td>58</td>
    </tr>
    <tr>
    <td>_ticket_end_date              </td>
    <td>15/08/2017  17:00:00</td>
    </tr>
    <tr>
    <td>_ticket_purchase_limit        </td>
    <td>0</td>
    </tr>
    <tr>
    <td>_ticket_start_date            </td>
    <td>08/02/2017  08:00:00</td>
    </tr>
    <tr>
    <td>_tribe_tickets_meta_enabled   </td>
    <td>0</td>
    </tr>
    <tr>
    <td>_tribe_wooticket_for_event    </td>
    <td>313</td>
    </tr>
    <tr>
    <td>_upsell_ids                   </td>
    <td>a:0:{}</td>
    </tr>
    <tr>
    <td>_virtual                      </td>
    <td>yes</td>
    </tr>
    <tr>
    <td>_visibility                   </td>
    <td>visible</td>
    </tr>
    <tr>
    <td>_wc_average_rating            </td>
    <td>0</td>
    </tr>
    <tr>
    <td>_wc_rating_count              </td>
    <td>a:0:{}</td>
    </tr>
    <tr>
    <td>_weight                       </td>
    <td> </td>
    </tr>
    <tr>
    <td>_width                        </td>
    <td> </td>
    </tr>
    <tr>
    <td>_total_sales                   </td>
    <td>0</td>
    </tr>
    </tbody>
    </table>

    These are all the meta_keys and their associated values for that ticket – the majority are Woo meta_keys, the others are custom fields added by Event Tickets Plus. For the purposes of what I wanted I needed _ticket_start_date, _ticket_start_date, and _stock_status.

    The first two are the dates between when this ticket can be purchased. Note, one or both of these can be empty. When you set up the ticket you have an option of adding either of these dates. If the start date is left blank it is treated as available “now”. If the end date is left blank it is treated as the date / time the event itself ends (we will cater for that later on in the function).

    The _stock_status key is pretty self explanatory.

    We’ll also need _tribe_wooticket_for_event which allows us later on to automatically determine know the correlating Event post ID.

    Those are the ones I needed for this exercise but if you wanted to display tickets remaining, for example, you can see you can use the _stock key.

    We also need the Event post meta data too (which is why we need _tribe_wooticket_for_event just mentioned – the function needs to pull data from the ticket post as well as its corresponding Event post). I used a similar approach as above to get these (see below). Note, there is a knowledebase article here that lists all the event post meta data keys. It includes PRO fields too, so bear that in mind if you don’t have Events Calendar PRO (the fields I’m using don’t require PRO).

    So, using the process from before, here’s how to get it yourself…

    View the database and find the xxxxx_postmeta file (if you’re not already in there). This time we want to see what meta_keys exist for Events.

    So first we’ll need to get the post ID of an Event ticket (any one will do). To do that, from the WordPress Dashboard, click Events. All the Events will be listed on the right. Click on Edit on any one. The post ID (e.g. 313) is in the URL in the browser address bar, e.g. …/wp-admin/post.php?post=313&action=edit

    Run exactly the same query as before, but change the post ID to be what you just determined.

    SAMPLE EVENT POST OUTPUT:

    <table style=”height: 797px;” border=”1″ width=”616″ cellspacing=”1″ cellpadding=”4″>
    <tbody>
    <tr>
    <td style=”text-align: center;” width=”268″>meta_key                                  </td>
    <td style=”text-align: center;” width=”335″>meta_value</td>
    </tr>
    <tr>
    <td>_edit_last                                </td>
    <td>2</td>
    </tr>
    <tr>
    <td>_edit_lock                                </td>
    <td>1490453623:2</td>
    </tr>
    <tr>
    <td>_EventCost                                </td>
    <td>25</td>
    </tr>
    <tr>
    <td>_EventDuration                            </td>
    <td>0</td>
    </tr>
    <tr>
    <td>_EventEndDate                             </td>
    <td>02/07/2017  20:00:00</td>
    </tr>
    <tr>
    <td>_EventEndDateUTC                          </td>
    <td>02/07/2017  19:00:00</td>
    </tr>
    <tr>
    <td>_EventOrigin                              </td>
    <td>events-calendar</td>
    </tr>
    <tr>
    <td>_EventOrigin                              </td>
    <td>events-calendar</td>
    </tr>
    <tr>
    <td>_EventOrigin                              </td>
    <td>events-calendar</td>
    </tr>
    <tr>
    <td>_EventOrigin                              </td>
    <td>events-calendar</td>
    </tr>
    <tr>
    <td>_EventShowMap                             </td>
    <td>1</td>
    </tr>
    <tr>
    <td>_EventShowMapLink                         </td>
    <td>1</td>
    </tr>
    <tr>
    <td>_EventStartDate                           </td>
    <td>02/07/2017  20:00:00</td>
    </tr>
    <tr>
    <td>_EventStartDateUTC                        </td>
    <td>02/07/2017  19:00:00</td>
    </tr>
    <tr>
    <td>_EventTimezone                            </td>
    <td>Europe/London</td>
    </tr>
    <tr>
    <td>_EventTimezoneAbbr                        </td>
    <td>BST</td>
    </tr>
    <tr>
    <td>_EventURL                                 </td>
    <td> </td>
    </tr>
    <tr>
    <td>_EventVenueID                             </td>
    <td>190</td>
    </tr>
    <tr>
    <td>_thumbnail_id                             </td>
    <td>58</td>
    </tr>
    <tr>
    <td>_transient_timeout_tribe_attendees        </td>
    <td>1490200300</td>
    </tr>
    <tr>
    <td>_transient_tribe_attendees                </td>
    <td>a:0:{}</td>
    </tr>
    <tr>
    <td>_tribe_deleted_attendees_count            </td>
    <td>4</td>
    </tr>
    <tr>
    <td>_tribe_hide_attendees_list                </td>
    <td>1</td>
    </tr>
    <tr>
    <td>_tribe_modified_fields                    </td>
    <td>a:13:{s:15:”_EventStartDate”;d:1490293076;s:13:”_E…</td>
    </tr>
    <tr>
    <td>_tribe_post_root                          </td>
    <td>JSE2-</td>
    </tr>
    <tr>
    <td>_tribe_progressive_ticket_current_number  </td>
    <td>5</td>
    </tr>
    <tr>
    <td>_tribe_ticket_global_stock_level          </td>
    <td>148</td>
    </tr>
    <tr>
    <td>_tribe_ticket_header                      </td>
    <td>58</td>
    </tr>
    <tr>
    <td>_tribe_ticket_use_global_stock            </td>
    <td> </td>
    </tr>
    <tr>
    <td>_wp_old_slug                              </td>
    <td>jse-1</td>
    </tr>
    <tr>
    <td>_wp_old_slug                              </td>
    <td>jse-4</td>
    </tr>
    </tbody>
    </table>

    These are all the meta_keys and their associated values for that Event. For the purposes of what I wanted I’ll need _EventStartDate (the date and time of the event), and the value associated with key _EventVenueID (in this example, “190”) because I want some Venue information. Venues are stored under their own posts and this is the post ID for the venue information for this event. Repeating the above query, but using 190 as the post ID.

    SAMPLE VENUE POST OUTPUT:

    <table style=”height: 431px;” border=”1″ width=”454″ cellspacing=”1″ cellpadding=”4″>
    <tbody>
    <tr>
    <td style=”text-align: center;” width=”147″>meta_key             </td>
    <td style=”text-align: center;” width=”228″>meta_value</td>
    </tr>
    <tr>
    <td>_edit_last           </td>
    <td>2</td>
    </tr>
    <tr>
    <td>_edit_lock           </td>
    <td>1489854105:2</td>
    </tr>
    <tr>
    <td>_EventShowMap        </td>
    <td> </td>
    </tr>
    <tr>
    <td>_EventShowMapLink    </td>
    <td> </td>
    </tr>
    <tr>
    <td>_VenueAddress        </td>
    <td>The Stables Market, Chalk Farm Road</td>
    </tr>
    <tr>
    <td>_VenueCity           </td>
    <td>Camden</td>
    </tr>
    <tr>
    <td>_VenueCountry        </td>
    <td>United Kingdom</td>
    </tr>
    <tr>
    <td>_VenueOrigin         </td>
    <td>events-calendar</td>
    </tr>
    <tr>
    <td>_VenuePhone          </td>
    <td>0207 428 4922</td>
    </tr>
    <tr>
    <td>_VenueProvince       </td>
    <td>London</td>
    </tr>
    <tr>
    <td>_VenueShowMap        </td>
    <td>TRUE</td>
    </tr>
    <tr>
    <td>_VenueShowMapLink    </td>
    <td>TRUE</td>
    </tr>
    <tr>
    <td>_VenueState          </td>
    <td> </td>
    </tr>
    <tr>
    <td>_VenueStateProvince  </td>
    <td>London</td>
    </tr>
    <tr>
    <td>_VenueURL            </td>
    <td>www.gilgameshbar.com</td>
    </tr>
    <tr>
    <td>_VenueZip            </td>
    <td>NW1 8AH</td>
    </tr>
    </tbody>
    </table>

    I’ll need _VenueProvince, but I also want the Venue name which isn’t in that bunch of keys! Hmmm. After a bit of rooting about I discovered that the folks at Modern Tribe have a function reference (found here) that list all the functions available. One is tribe_get_venue which returns the Venue name using that post ID – we’ll use that later in function.

    So we now know all the keys for the various bits and pieces we want to display. So armed with that, how do we display it? Well we use the Woocommerce hook woocommerce_after_shop_loop_item_title. That’s the entry point to create our own function to automatically interrogate these keys and display them on each Woo ticket product on the shop page.

    Below is the function I wrote to process all those keys we discovered and display them. Comments are at the main sections explaining what’s going on. Add the code snippet into your theme’s functions.php file (preferably, for safety, your CHILD theme’s functions.php):

    /*
     * Adds some post fields from a ticket's post meta data and corresponding Event's meta data so
     * they appear below Event titles in the Woo shop page.
     */
    add_action( 'woocommerce_after_shop_loop_item_title', 'add_shop_event_details', 9 );
    function add_shop_event_details() {
    	// 1. Get the current Ticket post ID
    	$ticket_post_id = get_the_id();
    
    	// 2. Get correlating Event ID for this ticket product
    	$evt_id = get_post_meta( $ticket_post_id , "_tribe_wooticket_for_event", true );
    
    	// 3. Pull event time info 
    	$evt_datetime = get_post_meta( $evt_id, "_EventStartDate", true );
    	$evt_datetime = date("D jS M Y @ g:ma",strtotime($evt_datetime));
    	echo '<div class="product-meta-time" style="color: grey;">' . $evt_datetime . '</div>';
    
    	// 4.Pull out some Venue info
    	$venue_id = get_post_meta( $evt_id, "_EventVenueID", true );
    	echo '<div class="product-meta-venue" style="color: grey;">Venue: ' .
    		tribe_get_venue($venue_id) . ', ' . get_post_meta( $venue_id, "_VenueProvince", true ) .
    			'</div>';
    
    	// 5.Pull stock status and ticket sale start / end date
    	$today		= strtotime( date('Y-m-d H:i:s') );	// The date and time now.
    
    	$stock_status	= get_post_meta( $ticket_post_id , "_stock_status", true );
    	
    	// 6. Determine when ticket sales can start
    	$ticket_start_sale_date = get_post_meta( $ticket_post_id , "_ticket_start_date", true );
    	$ticket_start_sale_date = trim( strtotime($ticket_start_sale_date) );
    	
    	// 7. If no sale start date supplied in the ticket, make sure the start date will be just 
    	//    before "now".
    	if ($ticket_start_sale_date == '') {		
    		$ticket_start_sale_date = $today - 1;	 
    	}
    	
    	// 8. Determine when ticket sales stop
    	$ticket_end_sale_date   = get_post_meta( $ticket_post_id , "_ticket_end_date", true );
    	$ticket_end_sale_date   = trim( strtotime($ticket_end_sale_date) );
    	
    	// 9. If no sale end date supplied in the ticket, default the close of sales 24 hours before 
    	//    Event finishing time
    	if ($ticket_end_sale_date == '') {			
    		$ticket_end_sale_date = get_post_meta( $evt_id , "_EventEndDate", true );
    		$ticket_end_sale_date = strtotime($ticket_end_sale_date);
    		$ticket_end_sale_date = $ticket_end_sale_date - (24*60*60);	// Subtract 24 hours	
    	}
    	
    	if ( $stock_status == "outofstock" ) {
    		$stock_msg = '<div class="product-meta-stock" style="color: red;"><b>' .
    			'Sorry, this Event is<br />SOLD OUT</b></div>';
    	
    	} else if ( ( $ticket_start_sale_date <= $today ) && ( $today <= $ticket_end_sale_date ) ) {
    		$stock_msg = '<div class="product-meta-stock" style="color: green;"><b>' .
    			'Tickets are now AVAILABLE<br />to purchase</b></div>';
    
    	} else if ( $ticket_end_sale_date <= $today ) {
    		$stock_msg = '<div class="product-meta-stock" style="color: red;"><b>' .
    			'Tickets sales for this Event<br />are now CLOSED</b></div>';
    
    	} else {
    		$stock_msg = '<div class="product-meta-stock" style="color: orange;"><b>' .
    			'Tickets go on SALE<br />' . date( "D jS M Y @ g:ma", $ticket_start_sale_date ) . 
    				'</b></div>';
    	}
    
    	echo $stock_msg;
    }

    NOTE: I’ve manually coloured the stock status messages. Other than that, all the elements output have their own CSS class so you can customise them through CSS further if you wish.

    Below is the other snippet you can optionally add. This changes the text on the button under an Event on the shop page from “Add to Cart” to “Event Details”, and changes the button’s link to point to the appropriate Single Event page.

    /*
     * Replace Add to Cart button with a button that goes to the product details 
     * 
     * First, remove default add to cart button on shop page 
     */
    function remove_loop_button(){
       remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
    }
    add_action('init','remove_loop_button');
    /*
     * Now add new button that links to appropriate single event page 
     */
    add_action('woocommerce_after_shop_loop_item','replace_add_to_cart');
    function replace_add_to_cart() {
       global $product;
       $link = $product->get_permalink();
       echo do_shortcode('Event Details');
    }

    That’s pretty much it. If it’s useful to you, please use it.

    #1260073
    Adam
    Participant

    Hmm – Apologies, the rendering is bad. My assumption on using HTML was clearly misjudged. 🙁

    If you can remove this altogether I will re-add, but using images for tables and using only the tag buttons this tool allows. Or if this isn’t the right place anyway – let me know.

    Thanks

    #1260487
    Caroline
    Member

    Hi Adam,

    Thanks so much for taking the time to write this up and share it with our customers–this is great information, and we truly appreciate your efforts to help the greater user community here! 🙂 We’re operating on limited capacity here at Modern Tribe this week due to our yearly team retreat, but I’d love to connect with you off the forums and see if we can’t find a way to present your findings with proper formatting (and proper credit to you, of course). Would you mind taking a moment to reach out to us via email with a reference to this thread and a link to your write-up with original formatting intact (such as a Google Doc)? You can choose “Help accessing my account” from the drop-down menu to access the full email form.

    Thanks again, and we look forward to hearing from you! 😀

    #1260500
    Adam
    Participant

    Sure, and glad it could be useful.

    I saw you guys were “out”, I’ll get something back to you in the next day
    or so.

    I can give you the source Html, so when viewed in a browser it looks
    correct. Plus I’ll do a Word version. I’ll put both on Google docs, or one
    drive.

    🙂

    #1260507
    Caroline
    Member

    Hi Adam,

    Perfect–all sounds great, and we’ll keep an eye out for your message! 🙂 I’m going to go ahead and close out this thread to keep things moving along, but please feel free to reference it in your email to us, and we’ll continue the conversation there!

    Cheers, and thanks again!

Viewing 5 posts - 1 through 5 (of 5 total)
  • The topic ‘HOW TO: Display Extra Meta Data For Ticketed Events on a Woocommerce Shop Page’ is closed to new replies.