Design System is here - Read the release post

Learn GeneratePress

Developers

Registering dynamic tags

GenerateBlocks dynamic tags insert dynamic content into blocks using a {{tag_name}} syntax. The registration system lets you create your own tags, which people insert through the editor UI.

To change how existing tags output data, see Dynamic tags: output and rendering. For who can use tags and which data they can read, see Dynamic tags: meta access and security.

Jump to

Overview

A tag is a name, a callback that returns its output, and settings for how it appears in the editor. GenerateBlocks registers 15 tags itself, such as post_title, post_meta and featured_image, in includes/dynamic-tags/class-dynamic-tags.php. GenerateBlocks Pro registers more, such as the archive, site, user meta, term meta and loop tags.

Back to top

Basic registration

GB Free

Dynamic tags are registered using the GenerateBlocks_Register_Dynamic_Tag class, typically on the init action:

add_action( 'init', function() {
    new GenerateBlocks_Register_Dynamic_Tag( [
        'title'    => __( 'Post Title', 'textdomain' ),
        'tag'      => 'post_title',
        'type'     => 'post',
        'supports' => [ 'link', 'source' ],
        'return'   => 'my_callback_function',
    ] );
} );

The class does nothing if tag, return or title is missing.

Related: Registration parameters Guide: Dynamic Tags

Back to top

Registration parameters

Required parameters

  • title (string): the human-readable name shown in the tag selector UI.
  • tag (string): the tag identifier used in content, {{tag_name}}. Use lowercase with underscores.
  • return (callable): the callback that generates the tag’s output. It receives ($options, $block, $instance).

Optional parameters

type (string), default 'post': the entity type this tag relates to. The options are:

  • 'post': WordPress posts, pages and custom post types
  • 'author': post authors (users)
  • 'user': any WordPress user
  • 'term': taxonomy terms
  • 'media': media library items

supports (array), default []: the features available for this tag:

  • 'source': allow selecting a specific entity (post ID, user ID and so on)
  • 'link': wrap the output in a link
  • 'meta': access meta fields with the key: parameter
  • 'date': date formatting options
  • 'image-size': image size selector
  • 'taxonomy': taxonomy selector
  • 'comments': comments-related features
  • 'instant-pagination': query pagination support

options (array): custom UI controls shown in the tag modal. Each key is the option name with its config:

'options' => [
    'length' => [
        'type'        => 'number',
        'label'       => __( 'Excerpt Length', 'textdomain' ),
        'placeholder' => '55',
        'default'     => 55,
        'help'        => __( 'Number of words to display.', 'textdomain' ),
    ],
    'useTheme' => [
        'type'    => 'checkbox',
        'label'   => __( 'Use Theme Defaults', 'textdomain' ),
        'default' => true,
        'help'    => __( 'Use theme settings.', 'textdomain' ),
    ],
    'format' => [
        'type'    => 'select',
        'label'   => __( 'Format', 'textdomain' ),
        'default' => 'plain',
        'options' => [
            [ 'value' => 'plain', 'label' => 'Plain Text' ],
            [ 'value' => 'html', 'label' => 'HTML' ],
        ],
    ],
    'separator' => [
        'type'        => 'text',
        'label'       => __( 'Separator', 'textdomain' ),
        'placeholder' => ', ',
        'help'        => __( 'Text between items.', 'textdomain' ),
    ],
],

Option types: 'text', 'number', 'checkbox', 'select'.

description (string): help text shown below the tag selector in the UI.

visibility (array): controls when the tag appears in the selector. It can be:

  • true: always visible (the default)
  • false: never visible
  • [ 'context' => [ 'key1', 'key2' ] ]: only when the block’s editor context has every one of the keys
  • [ 'attributes' => [ ... ] ]: conditional on the block’s attributes. Every condition must match. Each condition has a name, a value and a compare operator.

Example visibility based on the block’s tagName:

'visibility' => [
    'attributes' => [
        [
            'name'    => 'tagName',
            'value'   => [ 'a', 'button', 'img' ],
            'compare' => 'NOT_IN',
        ],
    ],
],

Comparison operators: '===' (the default), '!==', 'IN' and 'NOT_IN'.

Related: generateblocks.editor.tagSpecificControls Guide: Dynamic Tags

Back to top

Writing callback functions

Callbacks receive three parameters and must return a string:

function my_tag_callback( $options, $block, $instance ) {
    // $options - Parsed tag parameters from {{tag param1:value|param2:value}}
    // $block - The block data array
    // $instance - Block instance object with context

    // Get the source ID (respects user's source selection)
    $id = GenerateBlocks_Dynamic_Tags::get_id( $options, 'post', $instance );

    if ( ! $id ) {
        return ''; // No output if no ID
    }

    // Get your data
    $output = get_post_meta( $id, 'my_meta_key', true );

    // Apply transformations and wrapping
    return GenerateBlocks_Dynamic_Tag_Callbacks::output( $output, $options, $instance );
}

$options always includes tag_name, the name of the tag being resolved.

The output() helper

GenerateBlocks_Dynamic_Tag_Callbacks::output() applies the built-in transformations:

  • trunc:50: truncate to 50 characters
  • trunc:10,words: truncate to 10 words
  • trim, trim:left, trim:right: remove whitespace
  • case:lower, case:upper, case:title: transform case
  • replace:"old","new": string replacement
  • wpautop: add paragraph tags
  • link:post: wrap in a link (if supported)

Always use output() as your return unless you need raw output. Its result passes through generateblocks_dynamic_tag_output.

Related: generateblocks_dynamic_tag_id Guide: Dynamic Tags

Back to top

Complete examples

Example 1: simple meta field tag

new GenerateBlocks_Register_Dynamic_Tag( [
    'title'    => __( 'Product SKU', 'textdomain' ),
    'tag'      => 'product_sku',
    'type'     => 'post',
    'supports' => [ 'source' ],
    'return'   => function( $options, $block, $instance ) {
        $id = GenerateBlocks_Dynamic_Tags::get_id( $options, 'post', $instance );
        $sku = get_post_meta( $id, '_sku', true );
        return GenerateBlocks_Dynamic_Tag_Callbacks::output( $sku, $options, $instance );
    },
] );

Usage: {{product_sku}} or {{product_sku id:123}}

Example 2: tag with custom options

new GenerateBlocks_Register_Dynamic_Tag( [
    'title'   => __( 'User Bio', 'textdomain' ),
    'tag'     => 'user_bio',
    'type'    => 'user',
    'supports' => [ 'source' ],
    'options' => [
        'length' => [
            'type'    => 'number',
            'label'   => __( 'Max Words', 'textdomain' ),
            'default' => 50,
        ],
    ],
    'return' => function( $options, $block, $instance ) {
        $user_id = GenerateBlocks_Dynamic_Tags::get_id( $options, 'user', $instance );
        $bio = get_user_meta( $user_id, 'description', true );

        // Use custom option
        $length = $options['length'] ?? 50;
        $bio = wp_trim_words( $bio, $length );

        return GenerateBlocks_Dynamic_Tag_Callbacks::output( $bio, $options, $instance );
    },
] );

Usage: {{user_bio length:25}}

Example 3: image tag with multiple keys

new GenerateBlocks_Register_Dynamic_Tag( [
    'title'    => __( 'Author Avatar', 'textdomain' ),
    'tag'      => 'author_avatar',
    'type'     => 'author',
    'supports' => [ 'source' ],
    'options'  => [
        'key' => [
            'type'    => 'select',
            'label'   => __( 'Output', 'textdomain' ),
            'default' => 'url',
            'options' => [ 'url', 'id', 'alt' ],
        ],
        'size' => [
            'type'    => 'number',
            'label'   => __( 'Size (px)', 'textdomain' ),
            'default' => 96,
        ],
    ],
    'return' => function( $options, $block, $instance ) {
        $id = GenerateBlocks_Dynamic_Tags::get_id( $options, 'post', $instance );
        $author_id = get_post_field( 'post_author', $id );
        $size = $options['size'] ?? 96;

        switch ( $options['key'] ?? 'url' ) {
            case 'id':
                return (string) $author_id;
            case 'alt':
                return get_the_author_meta( 'display_name', $author_id );
            case 'url':
            default:
                $url = get_avatar_url( $author_id, [ 'size' => $size ] );
                return GenerateBlocks_Dynamic_Tag_Callbacks::output( $url, $options, $instance );
        }
    },
] );

Example 4: conditional visibility

Only show for non-interactive elements:

new GenerateBlocks_Register_Dynamic_Tag( [
    'title'      => __( 'Term Links', 'textdomain' ),
    'tag'        => 'term_links',
    'type'       => 'post',
    'supports'   => [ 'source', 'taxonomy' ],
    'visibility' => [
        'attributes' => [
            [
                'name'    => 'tagName',
                'value'   => [ 'a', 'button' ],
                'compare' => 'NOT_IN',
            ],
        ],
    ],
    'return' => 'my_term_links_callback',
] );

Back to top

Available filters

Each of these filters has its own entry in Dynamic tags: output and rendering, with the full list of parameters.

Modify tag replacement

See generateblocks_dynamic_tag_replacement.

add_filter( 'generateblocks_dynamic_tag_replacement', function( $replacement, $args ) {
    // $args contains: tag, full_tag, content, block, instance, options, supports
    return $replacement;
}, 10, 2 );

Before tag replacement (modify HTML)

See generateblocks_before_dynamic_tag_replace.

add_filter( 'generateblocks_before_dynamic_tag_replace', function( $content, $args ) {
    // Manipulate content before tag is replaced
    return $content;
}, 10, 2 );

Filter the source ID

See generateblocks_dynamic_tag_id.

add_filter( 'generateblocks_dynamic_tag_id', function( $id, $options, $instance ) {
    // Override which post/user/term ID is used
    return $id;
}, 10, 3 );

Filter output after all transformations

See generateblocks_dynamic_tag_output.

add_filter( 'generateblocks_dynamic_tag_output', function( $output, $options, $raw_output ) {
    // Modify final output
    return $output;
}, 10, 3 );

Add custom source options

This is a JavaScript filter, so add it with wp.hooks.addFilter() in a script that loads in the block editor. See generateblocks.dynamicTags.sourceOptions.

wp.hooks.addFilter(
    'generateblocks.dynamicTags.sourceOptions',
    'my-plugin/source-options',
    ( options, context ) => [ ...options, { label: 'Custom Source', value: 'custom' } ]
);

Back to top

Tag parameter syntax

Users insert tags with this syntax:

{{tag_name}}                           // Simplest form
{{tag_name id:123}}                    // With source ID
{{tag_name id:123|key:meta_field}}     // Multiple parameters
{{tag_name param:value|trunc:50}}      // With transformations
{{tag_name sep:\|}}                    // Escaped special chars

Built-in parameters, available on all tags:

  • id:123: a specific entity ID
  • required:false: don’t render the block if the tag is empty
  • link:post: wrap in a link (if supported)
  • trunc:N: truncate the output
  • case:lower|upper|title: transform case
  • trim, wpautop, replace:"a","b": text transformations

Parameters are separated by a pipe (|). A value with a colon or pipe in it needs a backslash in front of that character.

Back to top

Quick reference

Get the current post in a loop:

$id = GenerateBlocks_Dynamic_Tags::get_id( $options, 'post', $instance );

Get post meta:

$value = GenerateBlocks_Meta_Handler::get_post_meta( $id, $key, true );

Get user meta:

$value = GenerateBlocks_Meta_Handler::get_user_meta( $user_id, $key );

Access a custom option:

$my_option = $options['my_option'] ?? 'default_value';

Conditional output:

if ( empty( $output ) ) {
    return ''; // Block won't render
}

Meta values read through GenerateBlocks_Meta_Handler follow the access rules in Dynamic tags: meta access and security.

Back to top