Building Custom Event Pages for Stager Events on Your Site


This guide explains how to customize the layout and design of the default event pages that are generated for your Stager events by the WP Stager Integration plugin. Youāll learn how event pages are structured, which building blocks you can reuse, and different ways to customize the layout in your theme.
We also discuss how to build completely custom templates from scratch, offering you complete freedom on how your event pages look, and what content they display. This guide assumes youāve already completed the plugin setup, and confirmed that events are syncing correctly.
š” Looking for an integration partner who does the full integration for you? Every license comes with a Free Configuration Service, and we also offer a paid Full Integration Service!

The WP Stager Integration plugin stores each synced Stager event as a unique entry in your site’s database (using a custom post type). WordPress then serves the pages for these events with specific URLs that you can choose yourself, using the customizable “Permalink base”.
The URLs for your events pages will look like {yoursite.com}/{permalink_base}/{permalink_structure}, where {yoursite.com} is your site’s domain, the {permalink_base} is the Permalink base that you can choose yourself (e.g. events), and the {permalink_structure} is the Permalink structure that is unique for every event. For the permalink structure, you can use the Event ID, or the Event name, or a combination of the two.
š” For example: if you define your permalink base as events, and use the event name as the permalink structure, then the URLs of the event pages will look something like: yoursite.com/events/example-event-name.
The raw event data is stored in post meta. To retrieve the event data on single event pages, you can use the get_single_event_data() method of the Event class. For example:
// Get raw Stager event data
$event = \WP_Stager_Integration\Event::get_single_event_data();š” The above example returns an array of raw Stager event data. For an overview of all available Event properties, see the Stager Push Feed documentation.
The WP Stager Integration plugin hooks into the the_content filter to output the event page markup as post content on event pages. By default, the plugin renders a standard layout for your events. The markup is rendered by the filter_event_content() method of the Event class (more on that below).
The WP Stager Integration plugin can parse the raw event data coming from Stager into JSON-LD structured data (Event Schema Markup). It does this using the output_structured_data() method of the Event class.
To automatically output the Event Schema Markup in your template, simply call:
// Output Event Schema Markup
\WP_Stager_Integration\Event::output_structured_data();If you want to manually output the Schema Markup somewhere else, you can retrieve the data using the generate_structured_data() method of the Event class and handle it how you want. For example:
// Get raw Stager event data
$event = \WP_Stager_Integration\Event::get_single_event_data();
// Retrieve Event Schema Markup
$structured_data = \WP_Stager_Integration\Event::generate_structured_data( $event );
// Custom logic here...The default layout is located in template-parts/single-event-content.php. Itās responsible for building the default event page markup. At a high level it:
div.wpstager-single-eventdiv.wpstager-eventheader.wpstager-event__header (header section) containing:div.wpstager-event__main-info (main column)div.wpstager-event__sidebar (sidebar)š” If you like the default structure but just want to control where it appears within your theme, you can keep this template and only customize the surrounding theme layout. If you want a very different design, you can either override this templateās output or build your own from scratch (covered below).
The WP Stager Integration plugin has built-in blocks for every event page component (more info on components below). For example, the event name, subtitle, main image, content, tickets, etc. If your site is running a Block Theme, you can use the WordPress Site Editor (which uses the Block Editor) to build a completely custom layout using these building blocks.

The WP Stager Integration plugin also has built-in patterns that you can use as a starting point for building a custom layout, or you can use them directly.

You can use Elementor’s Theme Builder to build a custom template for Event pages using our dedicated Elementor widgets. Every event component has its own Elementor widget (e.g. Event name, Event subtitle, Event tickets, Event featured image, etc). This way, you can build completely custom layouts and place every event component exactly where you want, which will be populated dynamically with the event’s data on every separate event page.

If you want to keep the default layout of event pages but only want to modify the surrounding markup, then there is an easy way to do this. This means you don’t have to rewrite everything, since you can leverage your theme templates and WP Stager Integration’s builtāin utilities.
For example, the plugin provides a dedicated conditional method to check if youāre on a single event page:
// Check if the current page is an "Event" page
$is_event_page = \WP_Stager_Integration\Event::is_single_event();This method uses is_singular() under the hood, and is the recommended way to check for event page queries in your theme or plugin code. For example, you could use it in:
single.php or singular.phppage.phpindex.phpIf you want to reuse a pre-existing page or post template for your event pages, you can use the conditional helper to add custom content only on event pages within an existing template:
if ( \WP_Stager_Integration\Event::is_single_event() ) {
// Custom content for event pages here...
}This way, the plugin will still replace the post content with its default event layout using the the_content filter hook; but youāre able to add your own markup around it.
An easy pattern for building custom event pages is:
Event::is_single_event() method, such as:This keeps your event body consistent while still allowing for a branded outer layout.
If you prefer to use a dedicated template for the Stager event pages, you can add a single-wpstager_event.php template to your theme folder. WordPress will automatically use this template for event pages. Inside it, you can:
get_header(), get_footer(), etc.).the_content() call, so the pluginās filter_event_content() still provides the core event markup when the_content() is called.the_content() in layout elements specific to events.A very simple example skeleton of an event page template could something look like:
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
get_header( 'event' ); // Render 'event' header if available
?><main class="site-main event-page"><?php
while ( have_posts() ) {
the_post();
?><div class="my-custom-event-wrapper"><?php // Custom event wrapper
the_content(); // Plugin outputs its event layout here
?></div><?php
}
?></main><?php
get_footer( 'event' ); // Render 'event' footer if availableWhen you want full control over the event page layout and design, you can override/filter the pluginās default event page content. This way you can build your own custom templates while parsing event data yourself, and/or using the built-in components as building blocks.
The plugin exposes a filter hook for modifying the final event HTML markup. You can hook into this filter to completely replace the output rendered on single event pages.
/**
* Filters the post content on single event pages.
*
* @param string $event_content The event content HTML.
* @param int $event_id The Stager event ID.
* @param array $event The raw Stager event data.
*
* @return string Must return an HTML string.
*/
$event_content = (string) (apply_filters( 'wpstagerintegration_content_single_event', $event_content, $event_id, $event )For example, in your theme or plugin, you can override the default event page content by doing something like this:
add_filter( 'wpstagerintegration_content_single_event', function( $event_content, $event_id, $event ) {
// Parse arguments
$args = array(
'event_id' => $event_id,
'event' => $event,
);
// Render custom content template and return the HTML using output buffering
ob_start();
get_template_part( 'content', 'event', $args );
return ob_get_clean();
}, 10, 3 );This lets you keep the pluginās syncing and data model, but use a completely custom template for your event page content, while still using the default surrounding markup of your theme’s template.
Internally, the default event page template is built from reusable components. The components are rendered by the Component class, which contains helper methods for rendering individual components component. For event pages specifically, components are rendered via the render_event_* helper methods. You can call these methods from your own templates to build a completely custom layout and design.
Some examples:
š” These are just a few examples of all of the available components. For a full overview of all event page components and their respective render_event_* methods, refer to the Component class documentation so you can pick exactly the building blocks you need!
If you decide to build your own event page template from scratch, the easiest way to do it is as follows:
This gives you maximum flexibility and allows you to build completely custom layouts. Here’s an example of how a event page content template could look:
<?php
// Get event data
$event = \WP_Stager_Integration\Event::get_single_event_data();
// Output structured data
\WP_Stager_Integration\Event::output_structured_data();
// Render custom layout
?><div class="my-event-wrapper">
<header class="my-event-header"><?php
\WP_Stager_Integration\Component::render_event_name();
\WP_Stager_Integration\Component::render_event_subtitle();
\WP_Stager_Integration\Component::render_event_featured_image();
?></header>
<div class="my-event-body"><?php
\WP_Stager_Integration\Component::render_event_content();
\WP_Stager_Integration\Component::render_event_meta_table();
\WP_Stager_Integration\Component::render_event_tickets();
?></div><?php
// Work with custom event data
$event_updated_at = $event[ 'updatedAt' ];
...š” You can use the built-in components to quickly build your own layout, while still having the flexibility to work with the event data directly.
There might be cases where you’d like to work with specific properties from your event data, for which a respective built-in component doesn’t exist. In these cases, you can access the event data directly, and retrieve the data you need manually.
$event = \WP_Stager_Integration\Event::get_single_event_data();name, subtitle, textHtml, etc. esc_html() for plain text.wp_kses_post() for trusted HTML from Stager if needed.esc_url() for URLs.esc_attr() for attributesHere’s an example of displaying a custom āshort summaryā for your event:
<?php
// Get event data
$event = \WP_Stager_Integration\Event::get_single_event_data();
// Retrieve specific field to use as summary
$summary = (string) $event['subtitle'] ?? $event['text'] ?? '';
if ( $summary ) {
?><p class="event-short-summary"><?php
echo esc_html( wp_trim_words( $summary, 30 ) );
?></p><?php
}As mentioned earlier, the plugin can automatically generate Schema.org Event Structured Data as JSONāLD. In the default event content template, this is done at the start of the file. This means that a <script type="application/ld+json">ā¦</script> block for the current event is automatically added.
If you build your own template, you should call this yourself early in the markup:
\WP_Stager_Integration\Event::output_structured_data();Make sure you donāt output the structured data twice, which could potentially invalidate it. This could happen if you:
Also, if you’re using other SEO plugins (Yoast, Rank Math, etc.), check how your SEO plugin handles event schema. In many cases youāll want to let WP Stager Integration handle event schema and disable overlapping āeventā schema features in the SEO plugin.
š” You can always validate your Schema markup is rendered correctly by using a Schema Validator tool or Google’s Rich Results tester.
Tickets are a central part of most event pages. The plugin handles the most common scenarios automatically.
Component::render_event_tickets() looks at:
And then decides:
You can:
For example:
<section class="my-event-cta">
<h2>Get your tickets</h2>
<?php \WP_Stager_Integration\Component::render_event_tickets(); ?>
</section>If you need even more control, you can directly use the ticketāshop widget component and pass custom widget options to Stager’s advanced ticket shop widgets. Thatās a more advanced, developerāoriented path, and works well if youāre tightly integrating shop behavior into your design. Any array/object of data passed under the 'widget_options' key in the arguments will get passed directly to the widget initialization function. For example:
// Render the ticket shop widget with the cookie banner disabled
Component::render_ticket_shop_widget_event( array(
'widget_options' => array(
'cookieBannerEnabled' => false,
),
) );š” See Stager’s “Advanced widget integration” guide for all information on the available options to pass to the widget rendering functions.
Here’s a full working example, putting all of the above information together. The file below could be dropped into a theme folder as single-wpstager_event.php. In short, is does the following:
<?php
if (! defined( 'ABSPATH' )) {
exit; // Exit if accessed directly
}
get_header( 'event' ); // Render 'event' header if available
?><main class="site-main event-page"><?php
while ( have_posts() ) {
the_post();
// Get event data
$event = \WP_Stager_Integration\Event::get_single_event_data();
// Output structured data
\WP_Stager_Integration\Event::output_structured_data();
// Render custom layout
?><div class="my-event-wrapper">
<header class="my-event-header"><?php
\WP_Stager_Integration\Component::render_event_name();
\WP_Stager_Integration\Component::render_event_subtitle();
\WP_Stager_Integration\Component::render_event_featured_image();
?></header>
<div class="my-event-body"><?php
\WP_Stager_Integration\Component::render_event_content();
\WP_Stager_Integration\Component::render_event_meta_table();
\WP_Stager_Integration\Component::render_event_tickets();
?></div>
</div><?php
}
?></main><?php
get_footer( 'event' ); // Render 'event' footer if availableIf you wish to use multiple different custom templates for one or more specific conditions only, you can follow the stategy below. This could be useful if you wish to have different templates for different event types, categories, labels or tags, or even specific event ID’s. This is how you can achieve it:
For example:
add_filter( 'wpstagerintegration_content_single_event', function( $event_content, $event_id, $event ) {
// Init, default template
$template = 'event';
// Use a specific template for events of type "Festival"
if ( 'Festival' === $event[ 'type' ] ) {
$template = 'event-festival';
}
// Use a specific template for "Cancelled" events
if( 'CANCELLED' === $event[ 'status' ] ) {
$template = 'event-cancelled';
}
// Use a custom template for a specific event ID
if( 12345 === $event_id) {
$template = 'event-12345';
}
// Parse arguments
$args = array(
'event_id' => $event_id,
'event' => $event,
);
// Render the content template and return the HTML using output buffering
ob_start();
get_template_part( 'content', $template, $args );
return ob_get_clean();
}, 10, 3 );The example above will effectively render the content-event.php by default, content-event-festival.php for “Festival” type events, content-event-cancelled.php for cancelled events, and content-event-12345.php for the event with the ID 12345.
Maintainability
Component::render_* methods and Event::get_single_event_data() instead of duplicating logic.Performance
User experience
the_content() in the template it uses for event pages. This could be single-wpstager_event.php or a more generic template like single.php, singular.php, page.php,Ā index.php, or another custom template.the_content.Event::filter_event_content() hasnāt been unintentionally removed by calling remove_filter().If this doesn’t work, don’t hesitate to reach out!
Use the browser inspector to see which stylesheet āwinsā. Increase CSS specificity in your stylesheet selectors, or adjust the load order in your theme.
ticketGroups field, then that means no tickets are added to the event. Also verify the shopId field matches the Shop ID you configured in your ticket shop in the plugin’s settings.Component::render_event_tickets() in your custom layout.If this doesn’t work, don’t hesitate to reach out!
Avoid calling Event::output_structured_data() more than once. Also check if your SEO plugin is also outputting event schema and adjust accordingly. Also, make sure you haven’t removed the structured data through the wpstagerintegration_event_structured_data filter hook, or disabled the output using theĀ wpstagerintegration_output_structured_data filter hook.
If this doesn’t work, don’t hesitate to reach out!
š” Looking for an integration partner who does the full integration for you? Every license comes with a Free Configuration Service, and we also offer a paid Full Integration Service!

š Limited offer: Use code WELCOME26 to get your first month for free!