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!

Three different examples of a custom event page displaying the exact same event, all built using only built-in event page Component building blocks.

How Stager event pages work in the WP Stager Integration plugin

Event page URLs

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.

Stager Event data

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.

Event page content

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).

SEO & Event Schema Markup (Structured Data)

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 event page template

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:

  • Wraps everything in:
    • div.wpstager-single-event
    • div.wpstager-event
    • header.wpstager-event__header (header section) containing:
      • div.wpstager-event__main-info (main column)
      • div.wpstager-event__sidebar (sidebar)
  • Displays main info in the header, like:
    • The main image
    • Event name and subtitle
    • A table with event meta (date, time, location)
    • Event labels
    • The main description
  • Displays tickets in the sidebar
  • Renders additional sections below the header, like:
    • The event program
    • Spotify players of linked acts
    • Image gallery
    • Video embeds
    • Audio embeds
    • Location details

šŸ’” 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).

Using the Block Editor / Site Editor

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.

Use built-in blocks to build custom event page layouts in the Site Editor.

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 or customize one of the built-in block patterns to build your event page template.

Using Elementor’s Theme Builder

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.

Using the default layout

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.

Using the built‑in conditional helper

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.php
  • page.php
  • index.php
  • Or any other “generic” template where you want special handling for events.

If 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.

Adding markup around the plugin’s default content

An easy pattern for building custom event pages is:

  1. Letting the plugin handle the main event body/post content
  2. Add additional markup in existing theme templates, using the Event::is_single_event() method, such as:
    • A custom hero section.
    • Additional CTAs above or below the event details.
    • Related events or blog posts.

This keeps your event body consistent while still allowing for a branded outer layout.

Creating a dedicated event page template

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:

  • Use your theme’s usual structure (get_header(), get_footer(), etc.).
  • Keep the standard loop and the_content() call, so the plugin’s filter_event_content() still provides the core event markup when the_content() is called.
  • Wrap 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 available

Coding completely custom event page layouts

When 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.

Filtering or replacing the default content

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.

Components: building blocks you can reuse

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!

Building your own ā€œsingle eventā€ template from scratch

If you decide to build your own event page template from scratch, the easiest way to do it is as follows:

  1. Add a custom template in your theme folder (optional, only if you want custom surrounding markup)
  2. Use the above-mentioned filter hook to include a custom template for your event page content
  3. In the content template, retrieve the event data
  4. Output structured data (optional but recommended)
  5. Build your own layout by either:
    • Using the built in components as building blocks, or
    • Adding custom markup using the $event data directly

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.

Working with 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.

  1. Retrieve the raw event data using:
    $event = \WP_Stager_Integration\Event::get_single_event_data();
  2. Retrieve the property you need, such as name, subtitle, textHtml, etc.
  3. Sanitize and/or validate data where needed, and output any data safely, making sure it’s escaped properly:
    • Use esc_html() for plain text.
    • Use wp_kses_post() for trusted HTML from Stager if needed.
    • Use esc_url() for URLs.
    • Use esc_attr() for attributes
    • etc… See the WordPress Security API’s for more information!

Here’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

}

Structured Data & SEO on Custom Event Pages

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:

  • Call output_structured_data() in your template, and
  • Keep the default template running

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.

Ticket shops

Tickets are a central part of most event pages. The plugin handles the most common scenarios automatically.

Default tickets block

Component::render_event_tickets() looks at:

  • Whether ticket shops are configured.
  • The integration type (basic vs advanced).
  • The event’s ticketGroups.

And then decides:

  • To render an advanced event widget (embedded shop), or
  • To render a basic ā€œbuy ticketsā€ button that links to a full‑screen shop (= basic widget), or
  • To render a static list of ticket groups with prices and their respective links to the Stager-hosted ticket shop.

Customizing the ticket area

You can:

  • Move the tickets block higher on the page (e.g. right under the title).
  • Wrap it in your own CTA section.
  • Combine it with custom messaging (ā€œLimited seats availableā€, etc.).

For example:

<section class="my-event-cta">

    <h2>Get your tickets</h2>

    <?php \WP_Stager_Integration\Component::render_event_tickets(); ?>

</section>

Advanced widget integration

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.

Full working example

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:

  • It renders an event specific header (if available)
  • Within the main loop, it outputs the structured data, and then
  • It renders custom event page markup making use of the built-in components
  • It closes with an event specific footer (if available)
<?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 available

Using multiple layouts for specific conditions

If 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:

  • Hook into the earlier-mentioned filter hook to modify the event page content
  • Check for your specific criteria (e.g. a specific event, status, category, title, label, ID, etc)
  • Only modify the content if the conditions are met, and use the default content otherwise.

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.

Best practices & recommendations

Maintainability

  • Prefer reusing Component::render_* methods and Event::get_single_event_data() instead of duplicating logic.
  • Keep custom templates and CSS in a child theme, so updates to your main theme don’t wipe them out.

Performance

  • Don’t overload single event pages with too many heavy embeds (videos, large galleries)
  • Keep markup as lean as possible when you build custom templates.

User experience

  • Make sure date, time, and location are instantly visible.
  • Keep the tickets CTA easy to find and consistent across event pages.
  • Test your design on mobile—most visitors will experience events on a phone.

Troubleshooting custom event pages

  1. Check if your theme is calling 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.
  2. Ensure no other plugin is filtering or removing content by hooking into the_content.
  3. Confirm that Event::filter_event_content() hasn’t been unintentionally removed by calling remove_filter().
  4. If you’re using Elementor’s Theme Builder: Check the template used for single Stager events. Make sure it either contains the Event page components you want to display, or the default Event page layout widget called “Full Stager Event Page Layout”.

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.

    1. Verify that ticket shops are configured correctly in the WP Stager Integration settings.
    2. In Stager, make sure your event actually has tickets added to it, and that the tickets are marked as “Online”.
    3. Check the event’s Stager data (ticket groups, shop ID, etc.). If no ticket groups are listed under the 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.
    4. Make sure you haven’t removed the call to 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!

    Get WP Stager Integration

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