Hey, I'm Lyndon, a Creative Designer in Canada πŸ‡¨πŸ‡¦ 

Hire Me

How to get The Events Calendar WordPress Plugin as Dynamic Data in Bricks

Getting a proper calendar system in bricks has been something more frustrating then I would have liked. There are several plugins out there but none of them have feature parity with one another. I almost went with EventIn but it was missing a key feature for one of my clients, Waitlists. So I went back to the drawing board and ended up re-installing the Events Calendar.

The one thing that frustrates me about the events calendar is that the screenshots that they present on their website are not at all a representation of what you get when you install the plugin yourself. It is wildly different.

Some things are the same, but much is not.

Further, their customization leads much to be desired…It’s clunky, and hard to do.

As someone who thrives on creating custom templates and sections for every party of my website, I’ve LOVED Bricks Builders ability to use Dynamic Data to fully customize every aspect of a website. I wanted to see if I could leverage Dynamic Data with a calendar plug-in to regain some control over the design.

Unfortunately The Events Calendar does not support Dynamic Data for Bricks natively, nor does it have any built in system to do so.

What it does have though is a well documented knowledge base with information on its shortcodes, and thats all I needed.

See Bricks has a toggle able feature that you can enable via your functions.php file to let you use Shortcodes in Dynamic Data via the code. With some edits to our functions.php file, I can enable Bricks to call this data in a way that is friendly enough for us to make some custom templates.

Here’s a couple screenshots from a recent client website. These are fully customized templates, built in bricks, calling data from The Events Calendar. I was even able to make a super basic calendar view for clients who prefer to have their events in a client list.

It’s still a work in progress and there’s more I would like to do in order to make the templates look a bit better and more professional, but at least now I have FULL CONTROL inside of Bricks.

So how can you do it? I’m happy to share the weeks of testing and research with you for free.

Below is a code that you can add to your functions.php (I’d recommend you use a child theme to avoid losing this, and maybe Ill make it a plugin in the future)

Once you add the code, here are the shortcodes and dynamic data that you can use inside of Bricks to pull the data. It works on Query Loops and Single Post Templates.

Note: I did set The Events Calendar to use the Page Template instead of the Events template.

For tickets, the ticket shortcode just calls the actual ticket shortcode block. I haven’t gotten around to re-styling that so for now its the same block as before.

One of the main problems I had was the single post page not pulling the correct post ID in order to fill the content so in the functions.php I have added code to account for that and make sure that the correct post ID is always fetched even if the template is not natively serving it properly.

NameShortcodeBricks Dynamic Data
Debug Event Info[event_dbg]{echo:do_shortcode('[event_dbg]')}
Event Start Date[event_start_date]{echo:do_shortcode('[event_start_date]')}
Event Start Time[event_start_time]{echo:do_shortcode('[event_start_time]')}
Event End Time[event_end_time]{echo:do_shortcode('[event_end_time]')}
Tickets Remaining[event_tickets_remaining]{echo:do_shortcode('[event_tickets_remaining]')}
Ticket Price[event_ticket_price]{echo:do_shortcode('[event_ticket_price]')}
Venue Name[event_venue_name]{echo:do_shortcode('[event_venue_name]')}
Event Category[event_category]{echo:do_shortcode('[event_category]')}
Venue Address (multiline)[event_venue_address]{echo:do_shortcode('[event_venue_address]')}
Add to Calendar Buttons[event_add_to_calendar_button]{echo:do_shortcode('[event_add_to_calendar_button]')}
Tickets Add-to-Cart Form[event_add_to_cart]{echo:do_shortcode('[event_add_to_cart]')}
Tickets Block (Modern TEC UI)[event_tickets_block]{echo:do_shortcode('[event_tickets_block]')}
Venue Address (inline)[event_venue_address_inline]{echo:do_shortcode('[event_venue_address_inline]')}
Venue Coordinates (lat,lng)[event_venue_coords]{echo:do_shortcode('[event_venue_coords]')}
Custom Events Calendar Grid[custom_events_calendar]{echo:do_shortcode('[custom_events_calendar]')}
/**
 * Full TEC + Bricks Shortcodes with Robust ID Resolver
 * Paste this at the end of your child theme’s functions.php (or a ΞΌ-plugin),
 * replacing any previous event_* shortcode code.
 */

add_action( 'init', function() {

    //──────────────────────────────────────────────────────────────────────────
    // Helper: resolve an event ID for any context
    // 1) [shortcode post_id="123"]
    // 2) single-event template (is_singular)
    // 3) loop/global $post if it's tribe_events
    //──────────────────────────────────────────────────────────────────────────
    if ( ! function_exists( 'mt_resolve_event_id' ) ) {
        function mt_resolve_event_id( $atts = [] ) {
            $atts = shortcode_atts( [ 'post_id' => 0 ], $atts, '' );

            // 1) explicit override?
            if ( ! empty( $atts['post_id'] ) ) {
                return absint( $atts['post_id'] );
            }

            // 2) single Event template?
            if ( is_singular( 'tribe_events' ) ) {
                return (int) get_queried_object_id();
            }

            // 3) loop/global context?
            if ( get_post_type() === 'tribe_events' ) {
                return (int) get_the_ID();
            }
            global $post;
            if ( isset( $post->post_type ) && $post->post_type === 'tribe_events' ) {
                return (int) $post->ID;
            }

            // nothing matched
            return 0;
        }
    }

    //──────────────────────────────────────────────────────────────────────────
    // Debug: [event_dbg] β†’ prints resolved ID & post type
    //──────────────────────────────────────────────────────────────────────────
    add_shortcode( 'event_dbg', function( $atts ) {
        $id   = mt_resolve_event_id( $atts );
        $type = $id ? get_post_type( $id ) : 'none';
        return "Resolved ID: {$id} (type: {$type})";
    } );

    //──────────────────────────────────────────────────────────────────────────
    // Event Start Date: [event_start_date]
    //──────────────────────────────────────────────────────────────────────────
    add_shortcode( 'event_start_date', function( $atts ) {
        $id  = mt_resolve_event_id( $atts );
        $raw = $id ? get_post_meta( $id, '_EventStartDate', true ) : '';
        return $raw ? date( 'M j, Y', strtotime( $raw ) ) : '';
    } );

    //──────────────────────────────────────────────────────────────────────────
    // Event Start Time: [event_start_time]
    //──────────────────────────────────────────────────────────────────────────
    add_shortcode( 'event_start_time', function( $atts ) {
        $id  = mt_resolve_event_id( $atts );
        $raw = $id ? get_post_meta( $id, '_EventStartDate', true ) : '';
        return $raw ? date( 'g:ia', strtotime( $raw ) ) : '';
    } );

    //──────────────────────────────────────────────────────────────────────────
    // Event End Time: [event_end_time]
    //──────────────────────────────────────────────────────────────────────────
    add_shortcode( 'event_end_time', function( $atts ) {
        $id  = mt_resolve_event_id( $atts );
        $raw = $id ? get_post_meta( $id, '_EventEndDate', true ) : '';
        return $raw ? date( 'g:ia', strtotime( $raw ) ) : '';
    } );

    //──────────────────────────────────────────────────────────────────────────
    // Tickets Remaining: [event_tickets_remaining]
    //──────────────────────────────────────────────────────────────────────────
    add_shortcode( 'event_tickets_remaining', function( $atts ) {
        $id      = mt_resolve_event_id( $atts );
        if ( ! $id ) return '';
        $tickets = Tribe__Tickets__Tickets::get_all_event_tickets( $id );
        $left    = array_sum( array_map( fn( $t ) => $t->available(), $tickets ) );
        return $left > 0 ? "{$left} tickets left" : 'Sold out';
    } );

    //──────────────────────────────────────────────────────────────────────────
    // Ticket Price: [event_ticket_price]
    //──────────────────────────────────────────────────────────────────────────
    add_shortcode( 'event_ticket_price', function( $atts ) {
        $id      = mt_resolve_event_id( $atts );
        if ( ! $id ) return '';
        $tickets = Tribe__Tickets__Tickets::get_all_event_tickets( $id );
        if ( empty( $tickets ) ) return 'Free';

        $prices = array_map( fn( $t ) => $t->price, $tickets );
        $min    = min( $prices );
        $max    = max( $prices );

        if ( $min === $max ) {
            return $min > 0 ? '$' . intval( $min ) : 'Free';
        }
        return '$' . intval( $min ) . ' – $' . intval( $max );
    } );

    //──────────────────────────────────────────────────────────────────────────
    // Venue Name: [event_venue_name]
    //──────────────────────────────────────────────────────────────────────────
    add_shortcode( 'event_venue_name', function( $atts ) {
        $id       = mt_resolve_event_id( $atts );
        $venue_id = $id ? tribe_get_venue_id( $id ) : 0;
        return $venue_id ? get_the_title( $venue_id ) : '';
    } );

    //──────────────────────────────────────────────────────────────────────────
    // Event Category: [event_category]
    //──────────────────────────────────────────────────────────────────────────
    add_shortcode( 'event_category', function( $atts ) {
        $id    = mt_resolve_event_id( $atts );
        $terms = $id ? get_the_terms( $id, 'tribe_events_cat' ) : [];
        if ( empty( $terms ) || is_wp_error( $terms ) ) return '';
        return implode( ', ', wp_list_pluck( $terms, 'name' ) );
    } );

    //──────────────────────────────────────────────────────────────────────────
    // Venue Address: [event_venue_address]
    //──────────────────────────────────────────────────────────────────────────
    add_shortcode( 'event_venue_address', function( $atts ) {
        $id       = mt_resolve_event_id( $atts );
        $venue_id = $id ? tribe_get_venue_id( $id ) : 0;
        return $venue_id ? tribe_get_full_address( $venue_id ) : '';
    } );

    //──────────────────────────────────────────────────────────────────────────
    // Add-to-Calendar Button: [event_add_to_calendar_button]
    //──────────────────────────────────────────────────────────────────────────
    add_shortcode( 'event_add_to_calendar_button', function( $atts ) {
        $id   = mt_resolve_event_id( $atts );
        if ( ! $id ) {
            return '<em>⚠️ No event detected</em>';
        }
        $gcal = function_exists( 'tribe_get_gcal_link' ) ? tribe_get_gcal_link( $id ) : '';
        $ics  = function_exists( 'tribe_get_ical_link' ) ? tribe_get_ical_link( $id ) : '';
        if ( ! $gcal && ! $ics ) {
            return '<em>⚠️ Calendar links unavailable</em>';
        }
        ob_start(); ?>
        <div class="event-add-to-calendar">
          <?php if ( $gcal ): ?>
            <a href="<?php echo esc_url( $gcal ); ?>" target="_blank" rel="noopener">Google Calendar</a>
          <?php endif; ?>
          <?php if ( $ics ): ?>
            <?php if ( $gcal ) echo ' | '; ?>
            <a href="<?php echo esc_url( $ics ); ?>" target="_blank" rel="noopener">Download .ICS</a>
          <?php endif; ?>
        </div>
        <?php
        return ob_get_clean();
    } );

} );

add_shortcode('event_add_to_cart', function() {
    // Try global $post
    global $post;
    $event_id = 0;

    if ($post && isset($post->ID)) {
        $event_id = $post->ID;
    }

    // Fallback to queried object
    if (!$event_id) {
        $qo = get_queried_object();
        if ($qo && isset($qo->ID)) {
            $event_id = $qo->ID;
        }
    }

    // Bail if still no ID
    if (!$event_id) return '<p><em>⚠️ Could not detect event ID.</em></p>';

    // Check if ticket form function exists
    if (!function_exists('tribe_get_ticket_form')) {
        return '<p><em>⚠️ tribe_get_ticket_form() is unavailable. Is Event Tickets active?</em></p>';
    }

    // Render ticket form
    $form = tribe_get_ticket_form($event_id);
    if (empty($form)) {
        return '<p><em>⚠️ No tickets available for this event.</em></p>';
    }

    return $form;
});

add_shortcode('custom_events_calendar', function($atts) {
    $month = isset($_GET['month']) ? (int)$_GET['month'] : (int)date('m');
    $year = isset($_GET['year']) ? (int)$_GET['year'] : (int)date('Y');

    $start_date = sprintf('%04d-%02d-01', $year, $month);
    $end_date = date('Y-m-t', strtotime($start_date));

    $events = tribe_get_events([
        'start_date' => $start_date,
        'end_date'   => $end_date,
        'posts_per_page' => -1,
    ]);

    $event_map = [];
    foreach ($events as $event) {
        $event_date = tribe_get_start_date($event, false, 'Y-m-d');
        $event_map[$event_date][] = $event;
    }

    // Navigation logic
    $prev_month = $month - 1;
    $prev_year = $year;
    if ($prev_month < 1) {
        $prev_month = 12;
        $prev_year--;
    }

    $next_month = $month + 1;
    $next_year = $year;
    if ($next_month > 12) {
        $next_month = 1;
        $next_year++;
    }

    ob_start();
    ?>
    <div class="custom-calendar-nav">
        <a href="?month=<?= $prev_month ?>&year=<?= $prev_year ?>">&laquo; <?= date('F', mktime(0, 0, 0, $prev_month, 1)) ?></a>
        <strong><?= date('F Y', strtotime($start_date)) ?></strong>
        <a href="?month=<?= $next_month ?>&year=<?= $next_year ?>"><?= date('F', mktime(0, 0, 0, $next_month, 1)) ?> &raquo;</a>
    </div>
    <div class="custom-calendar-grid" style="display: grid; grid-template-columns: repeat(7, 1fr); gap: 10px;">
        <?php
        $first_day = date('w', strtotime($start_date)); // Sunday=0
        for ($i = 0; $i < $first_day; $i++) {
            echo "<div class='calendar-cell empty'></div>";
        }

        $days_in_month = date('t', strtotime($start_date));
        for ($day = 1; $day <= $days_in_month; $day++) {
            $date_key = sprintf('%04d-%02d-%02d', $year, $month, $day);
            echo "<div class='calendar-cell'>";
            echo "<div class='calendar-date'><strong>$day</strong></div>";

            if (!empty($event_map[$date_key])) {
                foreach ($event_map[$date_key] as $event) {
                    echo "<div class='calendar-event'>";
                    echo "<a href='" . get_permalink($event) . "'>" . esc_html(get_the_title($event)) . "</a>";
                    echo "</div>";
                }
            }

            echo "</div>";
        }
        ?>
    </div>
    <?php
    return ob_get_clean();
});


add_action( 'bricks/single/after_content', function() {
  if ( tribe_events_has_tickets_on_sale( get_the_ID() ) ) {
    // Preferred: uses the block API
    \Tribe__Tickets__Tickets_View::get_tickets_block( get_the_ID() );
  }
}, 20 );

// 1️⃣ Register a new β€œtickets block” shortcode
add_action( 'init', function() {

  add_shortcode( 'event_tickets_block', function( $atts ) {

    // 1) Parse any passed post_id
    $atts     = shortcode_atts( [ 'post_id' => 0 ], $atts, 'event_tickets_block' );
    $event_id = absint( $atts['post_id'] );

    // 2) Bricks Builder preview fallback
    if ( function_exists( 'bricks_is_builder' )
      && bricks_is_builder()
      && ! $event_id
    ) {
      $preview = get_posts([
        'post_type'      => 'tribe_events',
        'posts_per_page' => 1,
        'fields'         => 'ids',
      ]);
      if ( ! empty( $preview ) ) {
        $event_id = $preview[0];
      }
    }

    // 3) Front-end fallback if still no ID
    if ( ! $event_id ) {
      if ( function_exists( 'tribe_get_event_id' ) ) {
        $event_id = tribe_get_event_id();
      } elseif ( is_singular( 'tribe_events' ) ) {
        $event_id = get_queried_object_id();
      }
    }

    // 4) Bail if not an event
    if ( ! $event_id || get_post_type( $event_id ) !== 'tribe_events' ) {
      return '';
    }

    // 5) Swap global $post to our event
    global $post;
    $original_post = $post;
    $post          = get_post( $event_id );
    setup_postdata( $post );

    // 6) Render the tickets block via the Tickets_View instance
    if ( class_exists( '\Tribe__Tickets__Tickets_View' ) ) {
      // grab the singleton and call the method (non-static)
      $view = \Tribe__Tickets__Tickets_View::instance();
      // pass false so it returns HTML instead of echoing
      $html = $view->get_tickets_block( $event_id, false );
    } else {
      // fallback to the legacy shortcode
      $html = do_shortcode( '[tribe_tickets post_id="' . $event_id . '"]' );
    }

    // 7) Restore original global state
    wp_reset_postdata();
    $post = $original_post;

    return $html;
  } );

} );

//──────────────────────────────────────────────────────────────────────────
// Single-Line Venue Address for Maps
// Usage in Bricks Google Maps element via Shortcode: [event_venue_address_inline]
//──────────────────────────────────────────────────────────────────────────
add_shortcode( 'event_venue_address_inline', function( $atts ) {
    $id = mt_resolve_event_id( $atts );
    if ( ! $id ) {
        return '';
    }

    $venue_id = tribe_get_venue_id( $id );
    if ( ! $venue_id ) {
        return '';
    }

    // Grab individual parts
    $street  = tribe_get_address( $venue_id );
    $city    = tribe_get_city( $venue_id );
    $region  = tribe_get_region( $venue_id );
    $postal  = tribe_get_postal_code( $venue_id );
    $country = tribe_get_country( $venue_id );

    // Join with commas, skip any empty parts
    $parts = array_filter( [ $street, $city, $region, $postal, $country ] );
    return implode( ', ', $parts );
} );

//──────────────────────────────────────────────────────────────────────────
// Venue Coordinates for Maps
// Usage in Bricks Google Maps element via Shortcode: [event_venue_coords]
//──────────────────────────────────────────────────────────────────────────
add_shortcode( 'event_venue_coords', function( $atts ) {
    $id = mt_resolve_event_id( $atts );
    if ( ! $id ) {
        return '';
    }

    $venue_id = tribe_get_venue_id( $id );
    if ( ! $venue_id ) {
        return '';
    }

    // These meta keys come from The Events Calendar venue fields
    $lat = get_post_meta( $venue_id, '_VenueLat', true );
    $lng = get_post_meta( $venue_id, '_VenueLng', true );

    if ( ! $lat || ! $lng ) {
        return '';
    }

    // β€œlat,lng” is understood by most Maps elements
    return $lat . ',' . $lng;
} );


// // ────────────────────────────────────────────────────────────────────────────
// Enable PHP functions inside Bricks Code/Basic Text elements
// ────────────────────────────────────────────────────────────────────────────
add_filter( 'bricks/code/echo_function_names', function( $allowed ) {
    // Ensure we have an array
    if ( ! is_array( $allowed ) ) {
        $allowed = [];
    }

    // Add any functions you want Bricks to be able to call with 
    $allowed[] = 'do_shortcode';
    $allowed[] = 'mt_resolve_event_id';
    $allowed[] = 'get_post_meta';
    $allowed[] = 'tribe_get_venue_id';
    $allowed[] = 'get_the_title';
    // …add more as needed…

    return $allowed;
} );

Leave the first comment