Template integration

The single-event page is rendered by the plugin's own template, with action hooks at the points where integrations usually need to add something.

The hooks

Event registration feedback uses POM Theme's mt-125 helper (1.25rem), including feedback inserted by JavaScript. Keep the plugin and theme on matching rem-helper versions when upgrading; custom spacing overrides should target the new class or the component rather than the retired mt-20 helper.

In render order:

Hook Position
pom_events_single_before_main_block Before the page's main block
pom_events_single_details_before_place In the details sidebar, before the place
pom_events_single_details_after_place In the sidebar, after the place and organizer
pom_events_before_single_content Above the event content
pom_events_after_single_content Below the event content
pom_events_single_before_related_posts Before the related-content block
pom_events_single_after_related_posts After it
pom_events_after_before_main_block After the main block

The sidebar hooks receive the event ID; the others take no arguments and run inside the loop, so get_the_ID() is available.

Rendering a stored field

The most common use: printing a value that the supplied template does not print — the event's hashtag, or a field you added yourself.

add_action( 'pom_events_single_details_after_place', function ( $post_id ) {
    $meta    = get_post_meta( $post_id, 'pom', true );
    $hashtag = $meta['custom_hashtag'] ?? '';

    if ( '' === $hashtag ) {
        return;
    }

    printf(
        '<div class="event-hashtag"><p class="h6 label">%s</p><p class="h5">%s</p></div>',
        esc_html__( 'Hashtag', 'my-plugin' ),
        esc_html( $hashtag )
    );
}, 10, 1 );

Match the surrounding markup so your block does not look bolted on, and return early when the value is empty — the template's own convention is that empty fields render nothing.

Adding content around the description

add_action( 'pom_events_after_single_content', function () {
    $event_id = get_the_ID();
    // Print a sponsor block, a map, a programme.
} );

Filtering values the template prints

Two value filters exist:

Filter Purpose
pom_events_single_meta_contact_number The contact number before it is printed
pom_events_event_form_inputs The registration form's field definitions

The first is useful for formatting a number consistently, or for substituting a central number:

add_filter( 'pom_events_single_meta_contact_number', function ( $number, $post_id ) {
    return $number ? $number : get_option( 'my_default_events_phone' );
}, 10, 2 );

Changing the registration form's fields

add_filter( 'pom_events_event_form_inputs', function ( $inputs ) {
    $inputs['event_signup_company'] = array(
        'label' => __( 'Company', 'my-plugin' ),
        'args'  => array(
            'type'        => 'text',
            'class'       => 'form-control',
            'placeholder' => __( 'Company', 'my-plugin' ),
        ),
    );

    return $inputs;
} );

Adding a field renders it. Storing its value is your responsibility — hook the registration action and write what you need. See Registration lifecycle hooks.

Previous and next navigation

The query behind the arrows is filterable:

add_filter( 'pom_single_event_prev_next_args', function ( $args, $post_id ) {
    // For example, keep navigation within the same category.
    return $args;
}, 10, 2 );

The plugin prints related events after a post's content using the theme's own after-content hook. To change that placement, unhook the plugin's callback and render it where you prefer.

The results template

Event list items are rendered by the plugin's results template. Prefer adding around it — with the search form filter and your own styling — over replacing it, so plugin updates keep working.

Guard everything

Every hook in this article exists only on the POM theme:

add_action( 'init', function () {
    if ( ! post_type_exists( 'event' ) ) {
        return;
    }

    add_action( 'pom_events_after_single_content', 'my_events_extra' );
}, 20 );