Block, schema and rendering hooks

Available in:Free

These hooks change what visitors and search engines see. They cover event lists, classic theme pages, venue and organizer pages, maps, weather, category colors, the iCal feed and the Event schema. Most run on every page view, so keep callbacks fast and avoid extra queries.

For the editor’s side, see building a single event page and the Event schema. New to hooks? Start with Extending HappenBoard with hooks.

What HappenBoard adds to theme pages

On a block theme, HappenBoard’s templates place its blocks. A classic theme does not read those templates, so HappenBoard adds the blocks itself:

  • around the content of an event or a booking type page (happenboard_classic_theme_blocks);
  • on the events archive and the event category and tag archives (happenboard_classic_theme_archive_blocks).

Venue and organizer pages get their address, contact details and upcoming events on both kinds of theme (happenboard_venue_organizer_page). Under Astra, the theme’s byline (author and date) is hidden on single events, venues, organizers and booking types (happenboard_hide_theme_entry_meta). For site owners, see Will it work with my theme?.

How the Event schema is built

On a single event page, HappenBoard prints Event JSON-LD in the page head:

  1. happenboard_schema_disable decides whether anything is printed.
  2. happenboard_schema_event_type sets the @type.
  3. happenboard_schema_offers collects the offers. HappenBoard Pro adds one per ticket on sale.
  4. With no offer, happenboard_event_is_ticketed decides: a ticketed event gets no offer, any other event gets a free Offer in the currency from happenboard_schema_fallback_currency, sold out once its RSVP capacity is taken.
  5. happenboard_schema_event receives the finished array.

happenboard_schema_event_type and happenboard_schema_event are documented in Events, recurrence and series hooks.

happenboard_query_attributes

Filter Free src/Block/EventQueryLoop/Block.php

Filters the attributes of the four event list blocks at the start of their render, before any value is read. $context says which block is rendering, so one callback can serve all four.

Signature

apply_filters( 'happenboard_query_attributes', array<string,mixed> $attributes, string $context )

Parameters

$attributes array<string,mixed>
The block’s saved attributes, as changed by earlier callbacks. Missing keys fall back to the block’s defaults.
$context string
event-query-loop, events-grid, events-list or upcoming-events.

Return value

array<string,mixed> The attributes the block reads. A value that is not an array becomes an empty array, and every attribute falls back to its default.

Example

add_filter(
    'happenboard_query_attributes',
    function ( $attributes, $context ) {
        if ( 'event-query-loop' !== $context ) {
            return $attributes;
        }

        // Logged-out visitors only see the "Public" category (term 12).
        if ( ! is_user_logged_in() ) {
            $attributes['categoryIds'] = array( 12 );
        }

        return $attributes;
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2 to tell the blocks apart.
  • The blocks do not read the same keys. event-query-loop reads them all, including dateRange (upcoming, today, this_week, this_month, next_month, this_year, past, all, or custom with dateFrom and dateTo), organizerId, layout and order. events-list and events-grid read count, categoryIds, tagIds, venueId and search. upcoming-events reads only count.
  • Values are limited after the filter: count is at most 50, or 24 for events-grid. The filter also runs for the upcoming events listed on venue and organizer pages (an event-query-loop with venueId or organizerId set).
  • HappenBoard Pro hooks it at priority 10 to apply the Filter Bar’s URL parameters (happenboard_categories, happenboard_tags, happenboard_venue, happenboard_organizer, happenboard_q, happenboard_range), on every block but upcoming-events.

happenboard_classic_theme_blocks

Filter Free src/Service/Frontend/ClassicThemeContent.php

Filters the blocks HappenBoard adds around the content of an event, or of a booking type page, on a classic theme. A classic theme’s single.php shows only the title, the image and the content, so HappenBoard adds the single event template’s blocks through the_content.

Signature

apply_filters( 'happenboard_classic_theme_blocks', array{before:array,after:array} $blocks, WP_Post $post )

Parameters

$blocks array{before:array,after:array}
Two lists of blockName / attrs entries, shown before and after the content. For an event: happenboard/event-date-time and happenboard/countdown before; happenboard/rsvp-form, happenboard/event-series-occurrences (headed “Upcoming dates”), happenboard/event-venue, happenboard/event-organizer, happenboard/add-to-calendar and happenboard/event-categories-tags after. On a series’ All dates page: the date and the full list of dates before, nothing after, and no content. For a booking type: happenboard/booking-page after.
$post WP_Post
The event or booking type being shown.

Return value

array{before:array,after:array} The two lists to show. Empty both to turn the details off, for a theme that shows its own. A value that is not an array leaves the content as it is.

Example

add_filter(
    'happenboard_classic_theme_blocks',
    function ( $blocks, $post ) {
        if ( 'hboard_event' !== $post->post_type ) {
            return $blocks;
        }

        // Add the weather at the end of the details.
        $blocks['after'][] = array(
            'blockName' => 'happenboard/event-weather',
            'attrs'     => array(),
        );

        return $blocks;
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2.
  • Classic themes only, for the main query’s event or booking type in the loop. It does not run on a block theme, when a block template already contains HappenBoard blocks, or for excerpts, feeds, REST responses and secondary loops.
  • Blocks already in the post content are removed from the lists before the filter, so a page laid out by hand does not show them twice. A block you add back is shown anyway.
  • It runs on the_content at priority 20. Each entry is rendered with render_block() and no inner blocks, so use blocks with a server-side render. render_block filters apply: on a paid event, HappenBoard Pro shows the Ticket Picker instead of the RSVP form.

happenboard_classic_theme_archive_blocks

Filter Free src/Service/Frontend/ClassicThemeContent.php

Filters the blocks HappenBoard shows on the events archive and on the event category and tag archives, on a classic theme. These archives then show the same blocks as the block theme templates, between the theme’s header and footer, instead of listing events as blog posts.

Signature

apply_filters( 'happenboard_classic_theme_archive_blocks', array<int,array{blockName:string,attrs:array<string,mixed>}> $blocks, string $kind )

Parameters

$blocks array<int,array{blockName:string,attrs:array<string,mixed>}>
The blocks in display order. The events archive gets happenboard/calendar and happenboard/events-list (10 events, grouped by month, with venues). A category or tag archive gets happenboard/events-grid (12 events, 3 columns, with image, date and venue).
$kind string
events, category or tag.

Return value

array<int,array{blockName:string,attrs:array<string,mixed>}> The blocks to show. Return an empty array to keep the theme’s own archive template; a value that is not an array counts as empty.

Example

add_filter(
    'happenboard_classic_theme_archive_blocks',
    function ( $blocks, $kind ) {
        if ( 'events' !== $kind ) {
            return $blocks;
        }

        // Keep the upcoming list, drop the month calendar above it.
        return array_values(
            array_filter(
                $blocks,
                fn ( $block ) => 'happenboard/calendar' !== $block['blockName']
            )
        );
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2 to receive $kind.
  • Classic themes only. HappenBoard only replaces the theme’s generic templates (archive.php, taxonomy.php, index.php). A theme’s own archive-hboard_event.php or taxonomy-happenboard_category.php is kept, and so is a block template assigned in the Site Editor.
  • It runs at least twice per request: on template_include, to decide whether to swap the template, then when the page is built. Keep the callback free of side effects.
  • The page heading and the main wrapper are not in the list. On a category or tag archive, happenboard/events-grid narrows itself to the current term, and pages with the archive, when its categoryIds and tagIds are empty.

happenboard_hide_theme_entry_meta

Filter Free src/Integration/Themes/Astra.php

Filters whether the Astra theme’s post byline (author, date, comments) is hidden on HappenBoard pages: events, venues, organizers and booking types. Return false to show it.

Signature

apply_filters( 'happenboard_hide_theme_entry_meta', bool $hide )

Parameters

$hide bool
Default true.

Return value

bool true to hide Astra’s byline, false to keep it.

Example

add_filter(
    'happenboard_hide_theme_entry_meta',
    function ( $hide ) {
        // Keep Astra's byline on organizer pages only.
        if ( is_singular( 'hboard_organizer' ) ) {
            return false;
        }

        return $hide;
    }
);

Notes

  • One argument and no post: test the page with is_singular(). The post types are hboard_event, hboard_venue, hboard_organizer and hboard_booking_type.
  • It only runs under Astra, from Astra’s astra_single_post_meta filter, and only on those single pages, a series’ All dates page included.
  • Other themes are not affected: GeneratePress already limits its entry meta to posts, and block themes use HappenBoard’s own templates.

happenboard_venue_organizer_page

Filter Free src/Service/Frontend/VenueOrganizerPages.php

Filters what HappenBoard adds after the content of a venue’s or an organizer’s page: the description, the contact details, an embedded map and the upcoming events. It runs on block and classic themes alike.

Signature

apply_filters( 'happenboard_venue_organizer_page', array{description:bool,details:bool,map:bool,upcoming:int} $parts, WP_Post $post )

Parameters

$parts array{description:bool,details:bool,map:bool,upcoming:int}
description: the venue description or organizer bio, shown when the post has no content of its own (default true). details: a venue’s address with a link to it on the map service, the phone, the website and an organizer’s email (default true). map: a venue’s embedded map under its address (default false). upcoming: how many upcoming events to list (default 10, at most 50, 0 for none).
$post WP_Post
The venue (hboard_venue) or organizer (hboard_organizer) being shown.

Return value

array|false The parts to show; missing keys keep their default. Return false to add nothing, for a theme that shows its own details.

Example

add_filter(
    'happenboard_venue_organizer_page',
    function ( $parts, $post ) {
        if ( 'hboard_venue' === $post->post_type ) {
            // Venue pages show their map and the next 5 events.
            $parts['map']      = true;
            $parts['upcoming'] = 5;
        }

        return $parts;
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2 to receive the post.
  • The map is off by default because it loads from a third party: OpenStreetMap, or Google Maps when that is the map provider and an API key is set. Turned on, it goes through happenboard_venue_map_iframe_src and happenboard_venue_map_html, and the Map Design Studio of HappenBoard Pro styles it.
  • It runs on the_content at priority 20, for the main query’s venue or organizer only. It does not run when the page’s block template already contains HappenBoard blocks, or for a password-protected post.
  • The upcoming list is an Event Query Loop block, so happenboard_query_attributes also runs for it, with the event-query-loop context.

happenboard_venue_map_iframe_src

Filter Free src/Block/EventVenue/Block.php

Filters the URL loaded in the venue map’s iframe, without touching the rest of the markup. The height, lazy loading, title and referrer policy of the default output are kept.

Signature

apply_filters( 'happenboard_venue_map_iframe_src', string $src, string $provider, array $context )

Parameters

$src string
The URL built for the provider: the OpenStreetMap embed, the Google Maps Embed API URL, or the custom iframe URL template with {lat}, {lng} and {zoom} filled in.
$provider string
osm, google or custom.
$context array
lat (float), lng (float), zoom (int) and name (string).

Return value

string The iframe URL. It goes through esc_url() afterwards, so data: and javascript: URLs end up empty.

Example

add_filter(
    'happenboard_venue_map_iframe_src',
    function ( $src, $provider, $context ) {
        // Your own map server.
        return add_query_arg(
            array(
                'lat'  => $context['lat'],
                'lng'  => $context['lng'],
                'zoom' => $context['zoom'],
            ),
            'https://maps.example.com/embed'
        );
    },
    10,
    3
);

Notes

  • Three arguments: register with 10, 3.
  • It runs for the Event Venue block’s map and for the map on a venue page, before happenboard_venue_map_html. When the Map Design Studio of HappenBoard Pro replaces the whole markup on that later filter, the URL you return here is not used.
  • The provider falls back to osm when google has no API key or custom has no URL template, so a callback that only handles custom may never act.

happenboard_venue_map_html

Filter Free src/Block/EventVenue/Block.php

Filters the whole map markup of a venue: the Event Venue block’s map and the map on a venue page. The returned string is printed as is, with no escaping afterwards, so you own the escaping.

Signature

apply_filters( 'happenboard_venue_map_html', string $html, string $provider, array $context )

Parameters

$html string
The default markup: a dd element holding a lazy-loaded iframe, already escaped.
$provider string
osm, google or custom.
$context array
lat, lng, zoom, height, name and settings (the General settings with secret keys blanked).

Return value

string The markup to print.

Example

add_filter(
    'happenboard_venue_map_html',
    function ( $html, $provider, $context ) {
        // A container your own map script fills in.
        return sprintf(
            '<dd class="my-map" data-lat="%s" data-lng="%s" data-zoom="%d" style="height:%dpx"></dd>',
            esc_attr( (string) $context['lat'] ),
            esc_attr( (string) $context['lng'] ),
            (int) $context['zoom'],
            (int) $context['height']
        );
    },
    20,
    3
);

Notes

  • Three arguments: register with 10, 3 or later.
  • In $context['settings'], the Google Maps, weather, Turnstile and Akismet keys are blanked; a boolean <key>_set says whether each one is configured.
  • It only runs when there is a map to show. For the block: “Show map” is on, the event is not virtual and the venue has coordinates. For a venue page: its map part is turned on.
  • HappenBoard Pro hooks it at priority 10. When a Map Design Studio template is chosen, it returns a MapLibre container instead of the iframe. A later callback receives that container, but $provider still names the HappenBoard provider.

happenboard_pro_map_style

Filter Pro src/Service/Maps/MapStyle.php

Filters the MapLibre style a HappenBoard Pro map is drawn with: the Events Clustered Map block, and venue maps styled by the Map Design Studio. Return any MapLibre style (version 8), such as a vector style from a tile provider.

Signature

apply_filters( 'happenboard_pro_map_style', array<string,mixed> $style, string $context, string $template )

Parameters

$style array<string,mixed>
The MapLibre style: the chosen preset, the pasted custom JSON or, for the Clustered Map with no template, the default OpenStreetMap style.
$context string
clustered-map or venue-map.
$template string
The Map Design Studio template: off, custom or a preset (light, dark, sepia, minimal, brand, satellite).

Return value

array<string,mixed> The style to use. A value that is not an array with a version key is ignored and the original style is kept.

Example

add_filter(
    'happenboard_pro_map_style',
    function ( $style, $context, $template ) {
        if ( 'clustered-map' !== $context ) {
            return $style;
        }

        // A vector style shipped with the theme.
        $json   = file_get_contents( get_stylesheet_directory() . '/map-style.json' );
        $custom = json_decode( (string) $json, true );

        return is_array( $custom ) ? $custom : $style;
    },
    10,
    3
);

Notes

  • Three arguments: register with 10, 3.
  • On venue maps it only runs while a Map Design Studio template is chosen. With off, venue maps stay HappenBoard’s iframe and this filter does not run for them. The Clustered Map always uses MapLibre, so it always runs there.
  • The style is printed in the page, as JSON in a data-style attribute, on every map render: keep the callback fast, and treat anything in it as public.
  • To change only the raster tiles, happenboard_pro_map_tile_source is simpler.

happenboard_pro_map_tile_source

Filter Pro src/Service/Maps/StylePresets.php

Filters the raster tiles behind HappenBoard Pro’s maps: the Clustered Map’s default style and every Map Design Studio preset except Satellite. Use it to move off OpenStreetMap’s own tile servers, which ask busy sites to use another provider.

Signature

apply_filters( 'happenboard_pro_map_tile_source', array{tiles:array<int,string>,tileSize:int,attribution:string} $source )

Parameters

$source array{tiles:array<int,string>,tileSize:int,attribution:string}
tiles: XYZ URL templates with {z}, {x} and {y} (default https://tile.openstreetmap.org/{z}/{x}/{y}.png). tileSize: 256 by default. attribution: the OpenStreetMap credit, as HTML.

Return value

array The tile source. Only HTTPS tile URLs are kept, and with none left the OpenStreetMap source is used. tileSize must be 256 or 512 (otherwise 256), and attribution keeps only links.

Example

add_filter(
    'happenboard_pro_map_tile_source',
    function ( $source ) {
        // Tiles from your own provider.
        return array(
            'tiles'       => array( 'https://tiles.example.com/{z}/{x}/{y}.png?key=PUBLIC_KEY' ),
            'tileSize'    => 256,
            'attribution' => '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
        );
    }
);

Notes

  • One argument.
  • It does not change the Satellite preset (Esri imagery) or a custom style pasted as JSON. To replace a whole style, use happenboard_pro_map_style.
  • The tile URLs are loaded by your visitors’ browsers and appear in the page, so any key in them is public: use a key restricted to your domain.
  • It only applies to Pro’s MapLibre maps. HappenBoard’s iframe map (Map Design Studio set to off) uses the map provider of the settings; change its URL with happenboard_venue_map_iframe_src.

happenboard_weather_data

Filter Free src/Service/Weather/WeatherRepository.php

Filters the weather data the Event Weather block receives, after the cache and any Open-Meteo request. Add fields or correct values without fetching again.

Signature

apply_filters( 'happenboard_weather_data', array<string,mixed> $result, array{lat:float,lng:float,date:string,regime:string} $ctx )

Parameters

$result array<string,mixed>
The day’s data plus regime (historical, forecast or climatology), date and unit_labels. The block reads weather_code, is_day, temp, temp_max, temp_min, precip_probability, wind_max, regime and unit_labels.
$ctx array{lat:float,lng:float,date:string,regime:string}
The request: lat, lng, date (Y-m-d in the site time zone) and regime.

Return value

array<string,mixed> The data the block shows. Keep every key the block reads.

Example

add_filter(
    'happenboard_weather_data',
    function ( $result, $ctx ) {
        // Seasonal averages: hide the daily high.
        if ( 'climatology' === $ctx['regime'] ) {
            $result['temp_max'] = null;
        }

        return $result;
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2.
  • Nothing fires until weather is turned on (“Enable weather” on the Weather card of the Integrations screen). It also does not run for coordinates out of range, a malformed date, or a lookup that failed.
  • It runs after the cache, so your changes are applied on every page view and never stored.
  • regime sets the block’s CSS class (is-regime-*) and its label. Removing or renaming it breaks the display.

happenboard_term_color_presets

Filter Free src/Taxonomy/ColorPresets.php

Filters the swatches offered by HappenBoard’s color pickers: the event category color, in the admin and in the block editor, and the booking type’s accent color.

Signature

apply_filters( 'happenboard_term_color_presets', array<int,array{name:string,color:string}> $presets )

Parameters

$presets array<int,array{name:string,color:string}>
Ten default swatches, each with name (translated label) and color (lowercase #rrggbb).

Return value

array<int,array{name:string,color:string}> The swatches. Each entry is checked afterwards, and a malformed one is dropped.

Example

add_filter(
    'happenboard_term_color_presets',
    function ( $presets ) {
        // Add your brand color to the pickers.
        $presets[] = array(
            'name'  => 'Brand',
            'color' => '#1a7f5a',
        );

        return $presets;
    }
);

Notes

  • One argument.
  • Only six-digit hex colors survive (#1a7f5a): short hex, rgb(), hsl(), color names and hex with alpha are dropped. name is optional and falls back to the hex value.
  • It only changes the pickers, not colors already saved, and has no effect on the front end. Event tags have no color picker.
  • A JavaScript filter, happenboard.term.colorPresets (@wordpress/hooks), runs after it. An empty array here falls back to the JavaScript defaults: to show no swatch at all, return an empty array from the JavaScript filter.

happenboard_ical_feed_cache_ttl

Filter Free src/Service/Cache/IcalFeedCache.php

Sets how long the site iCal feed (GET /happenboard/v1/ical/feed.ics) is kept in cache, in seconds. The cached copy is served to every subscribed calendar until an event behind it changes or this time runs out.

Signature

apply_filters( 'happenboard_ical_feed_cache_ttl', int $ttl )

Parameters

$ttl int
Default 3600 (one hour).

Return value

int The lifetime in seconds. Return 0 or less to turn the cache off and build the feed on every request.

Example

add_filter(
    'happenboard_ical_feed_cache_ttl',
    function ( $ttl ) {
        // A plugin rewrites event titles on the fly: keep copies ten minutes at most.
        return 10 * MINUTE_IN_SECONDS;
    }
);

Notes

  • One argument. It is read on every feed request, so return the same value every time.
  • You rarely need a shorter time. A change to an event, a venue, a category or the dates of an event clears the cache, and so does a change of permalinks. The lifetime only covers what no hook reports, such as a plugin filtering titles or links.
  • With the cache off, the feed still sends an ETag, answers a matching If-None-Match with a 304 and sends Cache-Control: public, max-age=300.
  • Only the site feed is cached. The single event download (GET /happenboard/v1/events/{id}/ical) is built on every request and ignores this filter.

happenboard_schema_disable

Filter Free src/Service/Schema/EventSchemaPrinter.php

Turns off HappenBoard’s Event JSON-LD for one event, for example when an SEO plugin prints its own. It runs before any part of the schema is built, so returning true costs nothing.

Signature

apply_filters( 'happenboard_schema_disable', bool $disabled, int $post_id )

Parameters

$disabled bool
Default false.
$post_id int
The event being viewed.

Return value

bool true to print nothing. The value is cast to a boolean, so the string 'false' turns the schema off.

Example

add_filter(
    'happenboard_schema_disable',
    function ( $disabled, $post_id ) {
        // Events ticked "no schema" in your own meta box.
        return $disabled || (bool) get_post_meta( $post_id, '_my_no_event_schema', true );
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2 to receive the event, or you can only turn the whole site off.
  • It runs on wp_head at priority 30, on single event pages only. The public GET /happenboard/v1/events/{id}/schema route still returns the schema.
  • Returning true skips the rest: happenboard_schema_event_type, happenboard_schema_offers, happenboard_event_is_ticketed, happenboard_schema_fallback_currency and happenboard_schema_event do not run.
  • You do not need it for SEOPress: when the event has an Event schema set up in SEOPress, HappenBoard already steps aside.

happenboard_schema_offers

Filter Free src/Service/Schema/EventSchemaBuilder.php

Filters the offers of the Event JSON-LD, a list of schema.org Offer entries. HappenBoard passes an empty list; HappenBoard Pro adds one Offer per ticket on sale.

Signature

apply_filters( 'happenboard_schema_offers', array<int,array<string,mixed>> $offers, int $event_id, string $url, Occurrence|null $occurrence )

Parameters

$offers array<int,array<string,mixed>>
Empty in HappenBoard. With Pro, one Offer per ticket on sale.
$event_id int
The event post ID.
$url string
The event permalink, for the url of each Offer.
$occurrence HappenBoard\Service\Recurrence\Occurrence|null
The date the JSON-LD describes (the one in progress, else the next, else the last), with start_utc, end_utc and sequence. On a recurring event, count the seats of this date. null for an event without dates.

Return value

array<int,array<string,mixed>> A list of Offer arrays. Entries that are not arrays are dropped, and a value that is not an array counts as empty.

Example

add_filter(
    'happenboard_schema_offers',
    function ( $offers, $event_id, $url, $occurrence ) {
        // Tickets sold elsewhere, with the price stored on the event.
        $price = (string) get_post_meta( $event_id, '_my_ticket_price', true );
        if ( '' !== $price ) {
            $offers[] = array(
                '@type'         => 'Offer',
                'url'           => $url,
                'price'         => $price,
                'priceCurrency' => 'EUR',
                'availability'  => 'https://schema.org/InStock',
            );
        }

        return $offers;
    },
    10,
    4
);

Notes

  • Four arguments: register with 10, 4 to receive the date.
  • HappenBoard Pro hooks it at priority 10. It adds one Offer per ticket whose sale is open, in the ticket’s currency, with validFrom and validThrough from the sale dates. An Offer is SoldOut when no seat is left on the date described. Add to $offers rather than replacing it.
  • isAccessibleForFree follows what you return: false as soon as one Offer has a price above 0. Entries are not checked, so give each a numeric price, a priceCurrency and an availability.
  • An empty list does not always mean free: see happenboard_event_is_ticketed. To print an Event without offers, unset the key on happenboard_schema_event.

happenboard_event_is_ticketed

Filter Free src/Service/Schema/EventSchemaBuilder.php

Filters whether an event is sold through tickets. It decides what the Event JSON-LD says when happenboard_schema_offers returns no Offer: a ticketed event gets no Offer and no isAccessibleForFree, any other event gets one free Offer.

Signature

apply_filters( 'happenboard_event_is_ticketed', bool $ticketed, int $event_id )

Parameters

$ticketed bool
Default false.
$event_id int
The event post ID.

Return value

bool true when the event’s admission is sold through tickets, whether a sale is open or not.

Example

add_filter(
    'happenboard_event_is_ticketed',
    function ( $ticketed, $event_id ) {
        // Events sold on an outside ticketing site.
        if ( '' !== (string) get_post_meta( $event_id, '_my_ticket_url', true ) ) {
            return true;
        }

        return $ticketed;
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2.
  • HappenBoard Pro answers true at priority 10 for an event that has any ticket, paid or free, on sale or not. A closed sale then removes the offers instead of making the event look free. Keep a true you receive.
  • It only runs when no Offer came back. The free Offer it leads to is priced 0, in the currency from happenboard_schema_fallback_currency, and marked SoldOut once the RSVP capacity is taken.
  • It runs inside the schema builder, which the public GET /happenboard/v1/events/{id}/schema route also calls: do not rely on page conditions such as is_singular().

happenboard_schema_fallback_currency

Filter Free src/Service/Schema/EventSchemaBuilder.php

Filters the currency of the free Offer an event gets when it has no Offer and is not ticketed. It has no effect on real offers.

Signature

apply_filters( 'happenboard_schema_fallback_currency', string $currency )

Parameters

$currency string
The site currency: Currency under HappenBoard → Settings → General, after the happenboard_currency filter.

Return value

string A three-letter ISO 4217 code. It is uppercased, not checked.

Example

add_filter(
    'happenboard_schema_fallback_currency',
    function ( $currency ) {
        // Free events listed in Swiss francs.
        return 'CHF';
    }
);

Notes

  • One argument. Most sites need no callback: the default already follows the site currency.
  • It only runs when happenboard_schema_offers returned no Offer and happenboard_event_is_ticketed returned false. The free Offer is priced 0, so the currency does not make the event look paid.
  • An invalid code is printed as is, and search engines reject the Offer.
  • It runs inside the schema builder, which the public GET /happenboard/v1/events/{id}/schema route also calls: do not rely on page conditions such as is_singular().

Next steps