# Event Structured Data for an Events Post Type

> Adds Event JSON-LD (dates, venue or online location, price and organizer) to single events, so they can appear in Google's event listings.

- Type: PHP
- Runs: Frontend only
- Category: [SEO](https://wpide.com/library/category/seo/)
- Tags: schema, events, json-ld
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/seo-event-schema/

## Code

```php
// Currency for ticket prices.
$wpide_event_currency = 'USD';

add_action( 'wp_head', function () use ( $wpide_event_currency ) {
    if ( ! is_singular( 'event' ) ) {
        return;
    }

    $post = get_queried_object();
    $get  = function ( $key ) use ( $post ) {
        return trim( (string) get_post_meta( $post->ID, '_event_' . $key, true ) );
    };

    $start = $get( 'start' ) ? date_create_immutable( $get( 'start' ), wp_timezone() ) : false;

    if ( ! $start ) {
        return;
    }

    $url   = get_permalink( $post );
    $place = array(
        '@type'   => 'Place',
        'name'    => $get( 'venue' ) ? $get( 'venue' ) : $get( 'address' ),
        'address' => $get( 'address' ),
    );
    $online = array( '@type' => 'VirtualLocation', 'url' => $get( 'tickets' ) ? $get( 'tickets' ) : $url );
    $mode   = $get( 'mode' ) ? $get( 'mode' ) : 'offline';
    $modes  = array( 'offline' => 'OfflineEventAttendanceMode', 'online' => 'OnlineEventAttendanceMode', 'mixed' => 'MixedEventAttendanceMode' );

    $data = array(
        '@context'            => 'https://schema.org',
        '@type'               => 'Event',
        'name'                => wp_strip_all_tags( get_the_title( $post ) ),
        'description'         => wp_strip_all_tags( get_the_excerpt( $post ) ),
        'url'                 => $url,
        'startDate'           => $start->format( DATE_W3C ),
        'eventStatus'         => 'https://schema.org/EventScheduled',
        'eventAttendanceMode' => 'https://schema.org/' . ( $modes[ $mode ] ?? $modes['offline'] ),
        'location'            => 'online' === $mode ? $online : ( 'mixed' === $mode ? array( $place, $online ) : $place ),
        'image'               => get_the_post_thumbnail_url( $post, 'full' ),
        'organizer'           => array( '@type' => 'Organization', 'name' => get_bloginfo( 'name' ), 'url' => home_url( '/' ) ),
    );

    $end = $get( 'end' ) ? date_create_immutable( $get( 'end' ), wp_timezone() ) : false;

    if ( $end && $end > $start ) {
        $data['endDate'] = $end->format( DATE_W3C );
    }

    if ( is_numeric( $get( 'price' ) ) ) {
        $data['offers'] = array(
            '@type'         => 'Offer',
            'price'         => (string) ( 0 + $get( 'price' ) ),
            'priceCurrency' => $wpide_event_currency,
            'url'           => $get( 'tickets' ) ? $get( 'tickets' ) : $url,
            'availability'  => 'https://schema.org/InStock',
        );
    }

    echo '<script type="application/ld+json">' . wp_json_encode( array_filter( $data ), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG ) . "</script>\n";
} );
```

## Notes

Reads the fields saved by the Event Details meta box snippet. Set your currency at the top.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Event Structured Data for an Events Post Type" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
