Log in

Stamp.Show Companion for WordPress

For organizers who run their expo's website on WordPress while Stamp.Show stays the system of record. The plugin shows the expo's public content with shortcodes or blocks, keeps it up to date through webhooks, and takes applications from your site. It talks to the Stamp.Show API with your expo's key. GPL-2.0-or-later. Requires WordPress 6.0 and PHP 7.4.

Download the latest zip · Source code on GitHub (issues and pull requests are welcome).

Install and connect

  1. Download the zip from the latest release, install it (Plugins → Add New → Upload Plugin) and activate it.
  2. In Stamp.Show, open the expo's API keys tab and create a key. Copy the key and the webhook secret.
  3. In WordPress, open Settings → Stamp.Show. Paste the API key and the webhook secret; leave the base URL as https://api.stamp.show. Save, then Test connection.
  4. Back in the API keys tab, set the webhook URL to https://your-site/wp-json/stamp-show/v1/webhook (the settings page shows it) and tick results.published, content.changed and, if you take applications, application.accepted and application.rejected.

The key stays on your server: pages are rendered by PHP, and browsers never see it.

Shortcodes and blocks

Each module is a shortcode and also a block (search Stamp.Show in the editor). Both render the same output on the server.

ShortcodeShows
[stampshow_palmares]Awards table (medal, points, title, exhibitor, country) and the special prizes awarded. Until the palmares is published it prints a short notice, with the date if one is scheduled.
[stampshow_sponsors category="Platinum"]Sponsor logos and names. category is optional and case-insensitive: it limits the list to one category.
[stampshow_special_prizes]Special prizes with donor and conditions.
[stampshow_judges]The jury: photo, name and country of the judges who confirmed.
[stampshow_commissioners]Active commissioners, the countries they cover and their languages.
[stampshow_catalog]Catalog table of accepted exhibits: number, title, exhibitor, country, class and medal.
[stampshow_apply classes="Traditional,Thematic" max_frames="4"]Application form. classes (comma separated) turns the class field into a drop-down; empty means free text. max_frames caps the frame count (default and maximum 10).

A list with nothing to show prints nothing. Administrators see an error line instead when the API cannot be reached; visitors never do.

Application form

The form creates an application in your expo through POST /api/v1/applications. The expo must have API among its registration methods and registration must be open. The visitor sees a confirmation and, as with any application, the decision arrives by e-mail. The form carries a nonce and a honeypot field.

If the expo reviews applications by hand, Settings → Stamp.Show lists the applications with Accept and Reject buttons for pending ones (administrators only). Exhibitors then continue in the Exhibitor Portal, as they do for any other registration method.

Cache and webhooks

Each resource is cached for an hour. The webhook clears it earlier:

EventEffect
results.publishedClears the palmares and the catalog.
content.changedClears the resource named in data.resource.
application.accepted, application.rejectedClears the catalog.

The endpoint is POST /wp-json/stamp-show/v1/webhook. It verifies X-StampShow-Signature (hex HMAC-SHA256 of the raw body with the webhook secret) and answers 401 when it does not match. Clear cache in the settings page empties everything by hand.

For theme and plugin developers

Every shortcode and block goes through the same filters, so what you hook applies to both. $module is one of palmares, sponsors, special_prizes, judges, commissioners, catalog or apply; $resource is the API path (special-prizes with a hyphen).

Filters

Hook
stamp_show_shortcode_atts( $atts, $module )The shortcode or block attributes, before they are read. The standard shortcode_atts_stampshow_sponsors and shortcode_atts_stampshow_apply also work.
stamp_show_data( $data, $resource )What the API returned (from the cache), before rendering: hide or reorder items, add a field.
stamp_show_item_html( $html, $item, $resource )The inside of one list entry (sponsors, special prizes, judges, commissioners).
stamp_show_output( $html, $module, $atts )The final HTML of any module.
stamp_show_cache_ttl( $seconds, $resource )How long a resource is cached (default one hour). Return 0 to not cache it.
stamp_show_request_args( $args, $method, $path )The wp_remote_request() arguments of every API call: timeout, extra headers, sslverify.
stamp_show_application_payload( $payload, $post )The body the application form sends to POST /applications, for instance to add an external_reference_id. Return a WP_Error to refuse the submission with that message.

Actions

Hook
stamp_show_event( $event, $data )After every verified webhook, with the event name and its data.
stamp_show_event_{$event}( $data )The same, for one event: stamp_show_event_results.published, stamp_show_event_application.accepted...
stamp_show_cache_flushed( $resource )After the cache of a resource is cleared, by a webhook or by the button.
stamp_show_application_submitted( $application, $payload )The API accepted an application from the form; $application is its answer.
stamp_show_application_failed( $error, $payload )The application could not be sent ($error is a WP_Error).

Basic examples

Put the code in your child theme's functions.php, or in a small plugin of your own (a Code Snippets plugin works too). Each hook receives the data the plugin already has; you return it changed (filters) or just do something with it (actions). Everything printed in HTML must be escaped with esc_html() / esc_url(), as these examples do.

Show something different for each judge

The stamp_show_item_html filter gets the HTML of one list entry and the raw $item from the API. For judges it has name, country and photo_url. Here every judge shows the country in brackets after the name, and the photo is left out:

add_filter( 'stamp_show_item_html', function ( $html, $item, $resource ) {
    if ( 'judges' !== $resource ) {
        return $html; // leave every other list as it is
    }
    $country = ! empty( $item['country'] ) ? ' (' . esc_html( $item['country'] ) . ')' : '';
    return '<strong>' . esc_html( $item['name'] ) . '</strong>' . $country;
}, 10, 3 );

The photo is gone because the code never prints $item['photo_url']. To keep the default and only add to it, return $html . '...'.

Hide or reorder items

stamp_show_data runs before rendering and works on the whole answer of an endpoint, so it can remove items. This hides the sponsors of the Media category and sorts the judges by name:

add_filter( 'stamp_show_data', function ( $data, $resource ) {
    if ( 'sponsors' === $resource ) {
        $data['items'] = array_values( array_filter(
            $data['items'],
            fn ( $s ) => 'Media' !== $s['category']
        ) );
    }
    if ( 'judges' === $resource ) {
        usort( $data['items'], fn ( $a, $b ) => strcmp( $a['name'], $b['name'] ) );
    }
    return $data;
}, 10, 2 );

Change a shortcode's attributes from code

Force every application form on the site to offer the same classes, whatever the editor typed:

add_filter( 'stamp_show_shortcode_atts', function ( $atts, $module ) {
    if ( 'apply' === $module ) {
        $atts['classes'] = 'Traditional,Thematic,Open';
    }
    return $atts;
}, 10, 2 );

Wrap the output

stamp_show_output sees the final HTML of any module, which is handy for a heading or a container your theme styles:

add_filter( 'stamp_show_output', function ( $html, $module ) {
    if ( 'palmares' === $module && '' !== $html ) {
        return '<section class="my-palmares"><h2>Results</h2>' . $html . '</section>';
    }
    return $html;
}, 10, 2 );

Do something when an event arrives

Actions are for side effects. This purges your page cache plugin when the results come out (use your cache plugin's own purge function):

add_action( 'stamp_show_event_results.published', function ( $data ) {
    if ( function_exists( 'my_page_cache_purge' ) ) {
        my_page_cache_purge( '/palmares/' );
    }
} );

Get an e-mail for every application

add_action( 'stamp_show_application_submitted', function ( $application, $payload ) {
    wp_mail(
        get_option( 'admin_email' ),
        'New application: ' . $payload['title'],
        'From ' . $payload['exhibitor']['email'] . ', ' . $payload['frame_count'] . ' frame(s).'
    );
}, 10, 2 );

Cache less (or not at all) for one resource

add_filter( 'stamp_show_cache_ttl', function ( $seconds, $resource ) {
    return 'catalog' === $resource ? 5 * MINUTE_IN_SECONDS : $seconds;
}, 10, 2 );

Troubleshooting