Skip to main content
The BeyondWords for WordPress plugin allows you to automatically generate and embed audio and video versions of your posts.
Per-post settings default to your BeyondWords project settings. Configure project defaults in the dashboard—script templates, video templates, voices, and player settings.

Requirements

  • WordPress: 5.8 or higher
  • PHP: 8.0 or higher (including PHP 8.4)
  • WordPress: 5.8 or higher
  • PHP: 8.0 or higher (including PHP 8.4)
For the latest WordPress version the plugin has been tested against, see the plugin directory listing.

Install the plugin

1

Create a BeyondWords project

If you haven’t already, create a project in BeyondWords to store your content and settings.Go to Settings → Integrations → WordPress in your project dashboard and note your API key and Project ID for step 3.
2

Install the plugin

Install and activate BeyondWords – Text to Speech from the WordPress plugin directory.
3

Add your credentials

In WordPress, open the BeyondWords plugin settings and paste your API key and project ID on the Authentication tab.Click Save changes.
4

Configure the plugin

Set your Integration and Preferences (see below), then configure per-post Settings in the post editor before publishing.
5

Publish as normal

Publish posts in WordPress as normal. BeyondWords generates the assets you configured and embeds the player if Embed and player visibility are enabled.

Generate content for existing posts

To generate content for posts published before the plugin was installed:
  1. Go to All Posts in the WordPress dashboard
  2. Select the posts you want to process
  3. From the Bulk actions dropdown, select Generate audio and click Apply
Configure generation and embed settings per post in the BeyondWords panel before running bulk actions, or update individual posts afterwards.

Plugin settings

The plugin settings page has three tabs:

Authentication

Add your API key and Project ID to connect the plugin to your BeyondWords project. Find these in Settings → Integrations → WordPress in your project dashboard.

Integration

Choose how the plugin creates and updates content items in BeyondWords:
MethodUse when
REST API (default)Most WordPress sites—the plugin uses the BeyondWords API directly
Magic Embed (Client-side)Page builders such as Elementor cause issues with the REST API—the plugin uses Magic Embed instead. You must also configure Magic Embed in your BeyondWords dashboard

Preferences

Site-wide defaults for new posts in the editor:
  • Posts or Pages—which post types are preselected for generation. Defaults to Posts.
  • Include excerpt—prepend the WordPress Excerpt to the start of generated content. Applies to both audio and video. Disabled by default.
  • Player UI—whether the BeyondWords player appears on published posts:
    • Enabled (default)—embed the player on posts
    • Headless—generate content without embedding the player. Use when building your own UI.
    • Disabled—do not show the player on posts

Post editor

The BeyondWords panel in the block editor and classic editor exposes the same sections: Preview, Settings, Data, Help, and Inspect. Per-post fields default to your BeyondWords project settings unless overridden.

Generate audio

In the block editor, the Generate audio checkbox is always visible in the BeyondWords panel.
  • Checked—saving or updating the post sends the content to BeyondWords for generation (or regeneration when the post body changes).
  • Unchecked—saving the post does not regenerate audio from the updated content. Use this when you have edited the post but want to keep the existing audio.

Preview

Hidden until audio or video has been generated for the post. Once content exists, shows a preview of the BeyondWords player for the asset currently selected in Settings → Player → Embed. Toggle whether the player is visible on the published post, directly below the preview.

Settings

Content

  • Source—what to generate from: Post, Script, or Post + Script. Defaults to project settings.
  • Script template—shown when Source includes Script. Choose which script template to use. Defaults to project settings.

Format

  • Output—what to generate: Audio, Video, or Audio + Video. Defaults to project settings.
  • Video template—shown when Output includes Video. Defaults to project settings. See video generation.
  • Video size—shown when Output includes Video. Defaults to project settings.

Voice

  • Language—defaults to project settings
  • Voice—filtered by the selected language; defaults to project settings
  • Model—shown when the selected voice has more than one model; defaults to project settings

Player

  • Embed—which generated asset to show on this post. Options are derived from your Source and Output selections. Only one asset can be embedded per post—all other generated assets remain available in BeyondWords.
SourceOutputEmbed options
PostAudioNone, Audio (post)
PostVideoNone, Video (post)
ScriptAudioNone, Audio (script)
Post + ScriptAudio + VideoNone, Audio (post), Audio (script), Video (post), Video (script)

Data

Enter a Content ID to link an existing BeyondWords content item to this WordPress post when you know the ID.

Help

Links and guidance for using the plugin. No configuration options.

Inspect

View, copy, or remove the BeyondWords data stored in WordPress for this post. Used for debugging and support—see Support and troubleshooting below. In the block editor, Fetch retrieves audio that already exists in BeyondWords and restores the link to this WordPress post—without regenerating audio. Use this when the connection between the post and its BeyondWords content is missing or broken but the audio still exists in your project.

WordPress filters

The plugin provides WordPress filters to customize content sent to the API, player rendering, SDK behavior, and plugin settings.
FilterWhat it does
beyondwords_content_paramsControl what the plugin sends to the BeyondWords API (body, metadata, and more)
beyondwords_player_htmlModify the player HTML embedded in posts
beyondwords_player_script_onloadAppend JavaScript to the player script’s onload handler
beyondwords_player_sdk_paramsModify player SDK parameters passed at initialization
beyondwords_settings_player_stylesModify player style options in plugin settings and the post editor
beyondwords_settings_post_statusesControl which post statuses trigger audio processing
beyondwords_settings_post_typesControl which post types the plugin supports

How to add a filter

Every example below uses add_filter(). You can add that code to your WordPress site in one of two ways:
ApproachBest for
Code Snippets pluginMost publishers—no theme edits, easy to enable or disable, survives theme updates
Child theme functions.phpDevelopers comfortable editing theme files
1

Install Code Snippets (recommended)

In WordPress admin, go to Plugins → Add New, search for Code Snippets, then install and activate it.
2

Create a new snippet

Go to Snippets → Add New, give it a name (for example, “BeyondWords player customisation”), and paste your add_filter() code.
3

Set scope and activate

Set the snippet to run on the front end only unless the filter only needs the admin area. Save and activate.
Alternatively, add the same code to your child theme’s functions.php file. Use a child theme so parent theme updates do not overwrite your customisations.
You do not need to change the filter hook names or signatures—copy any example below into either approach.

beyondwords_content_params

Filters the content parameters sent to the BeyondWords API during generation when using the REST API integration method. Use it to control what gets sent—for example, modify $params['body'] (the post HTML), adjust title or metadata, or pass custom fields. As with other integrations, you can also configure content filters in Settings → Extraction → Filters to include or exclude parts of the HTML during processing. The plugin sends content with type set to auto_segment, so dashboard filters apply to $params['body'] on the BeyondWords side. Use content filters for recurring page elements (newsletter sign-ups, related-article blocks); use this PHP filter for WordPress-specific changes before content is sent. When using Magic Embed (Client-side), content is extracted from the live page instead. Use content filters and data attributes to control what gets ingested.
ArgumentTypeDescription
$paramsarrayParameters sent to the BeyondWords API, including body, title, source_id, and metadata
$post_idintWordPress post ID
Prepend the author name and publish date
function my_beyondwords_content_params( $params, $post_id ) {
    $name = get_the_author_meta( 'display_name', $post_id );
    $date = get_the_date( '', $post_id );

    $prepend = '';

    if ( $name ) {
        $prepend .= '<p>By ' . esc_html( $name ) . '</p>';
    }

    if ( $date ) {
        $prepend .= '<p>' . esc_html( $date ) . '</p>';
    }

    $params['body'] = $prepend . $params['body'];

    return $params;
}

add_filter( 'beyondwords_content_params', 'my_beyondwords_content_params', 10, 2 );
Send a custom field as metadata
function my_beyondwords_content_params( $params, $post_id ) {
    if ( is_object( $params['metadata'] ) ) {
        $params['metadata']->my_custom_key = get_post_meta( $post_id, 'my_custom_field', true );
    }

    return $params;
}
add_filter( 'beyondwords_content_params', 'my_beyondwords_content_params', 10, 2 );
Forward a custom field to ads_enabled
function my_beyondwords_content_params( $params, $post_id ) {
    $params['ads_enabled'] = (bool) get_post_meta( $post_id, 'my_ads_enabled', true );

    return $params;
}
add_filter( 'beyondwords_content_params', 'my_beyondwords_content_params', 10, 2 );

beyondwords_player_html

Filters the HTML of the BeyondWords player.
ArgumentTypeDescription
$htmlstringPlayer HTML—the SDK may fail to locate the target if you remove the default contents
$post_idintWordPress post ID
$project_idstringBeyondWords project ID
$content_idstringBeyondWords content ID
$contextstringauto if prepended to the_content, or shortcode if inserted via shortcode
Wrap the player in a container
function my_beyondwords_player_html( $html, $post_id, $project_id, $content_id, $context ) {
    return '<div class="my-container">' . $html . '</div>';
}
add_filter( 'beyondwords_player_html', 'my_beyondwords_player_html', 10, 5 );
Hide the player for non-signed-in users
function my_beyondwords_player_html( $html, $post_id, $project_id, $content_id, $context ) {
    $current_user = wp_get_current_user();

    if ( $current_user->exists() ) {
        return $html;
    }

    return '';
}
add_filter( 'beyondwords_player_html', 'my_beyondwords_player_html', 10, 5 );
Hide the auto player but keep shortcode/block players
function beyondwords_remove_auto_player( $html, $post_id, $project_id, $content_id, $context ) {
    if ( $context === 'auto' ) {
        return '';
    }

    return $html;
}
add_filter( 'beyondwords_player_html', 'beyondwords_remove_auto_player', 10, 5 );

beyondwords_player_script_onload

Filters the onload attribute of the BeyondWords player script. Strings should use double quotes—the output is run through esc_js() before being added to the DOM.
ArgumentTypeDescription
$onloadstringThe onload script string
$paramsarraySDK params for the current post, including projectId and contentId
Append a custom command
function my_beyondwords_player_script_onload( $onload, $params ) {
    return $onload . 'initializeCustomUserInterface();';
}
add_filter( 'beyondwords_player_script_onload', 'my_beyondwords_player_script_onload', 10, 2 );
Log player params to the console
function my_beyondwords_player_script_onload( $onload, $params ) {
    $my_command = 'console.log("🔊", ' . wp_json_encode( $params, JSON_FORCE_OBJECT | JSON_UNESCAPED_SLASHES ) . ');';

    return $my_command . $onload;
}
add_filter( 'beyondwords_player_script_onload', 'my_beyondwords_player_script_onload', 10, 2 );

beyondwords_player_sdk_params

Filters the BeyondWords player SDK parameters. See player properties for available options.
ArgumentTypeDescription
$paramsarraySDK parameters
$post_idintWordPress post ID
Set a custom text color
function my_beyondwords_player_sdk_params( $params, $post_id ) {
    $params['textColor'] = 'rgba(255, 0, 0, 0.8)';

    return $params;
}
add_filter( 'beyondwords_player_sdk_params', 'my_beyondwords_player_sdk_params', 10, 2 );
Set advert consent for all users
function my_beyondwords_player_sdk_params( $params, $post_id ) {
    $params['advertConsent'] = 'non-personalized';

    return $params;
}
add_filter( 'beyondwords_player_sdk_params', 'my_beyondwords_player_sdk_params', 10, 2 );
Use a different icon color for posts tagged “News”
function my_beyondwords_player_sdk_params( $params, $post_id ) {
    $tags = get_the_tags( $post_id );

    foreach ( $tags as $tag ) {
        if ( isset( $tag->name ) && $tag->name === 'News' ) {
            $params['iconColor'] = '#000080';
        }
    }
    return $params;
}
add_filter( 'beyondwords_player_sdk_params', 'my_beyondwords_player_sdk_params', 10, 2 );
Skip ads for signed-in users
function my_beyondwords_player_sdk_params( $params, $post_id ) {
    $current_user = wp_get_current_user();

    if ( $current_user->exists() ) {
        $params['adverts'] = [];
    }

    return $params;
}
add_filter( 'beyondwords_player_sdk_params', 'my_beyondwords_player_sdk_params', 10, 2 );
For a complete example that sets accessTier based on MemberPress subscription status, see MemberPress under Paywall providers in the access tiers guide.

beyondwords_settings_player_styles

Filters the player style options shown in the plugin settings and post edit screens.
ArgumentTypeDescription
$stylesarrayAssociative array of player styles
Remove “Small” from the player style dropdown
function my_beyondwords_settings_player_styles( $styles ) {
    if ( array_key_exists( 'small', $styles ) ) {
        unset( $styles['small'] );
    }

    return $styles;
}
add_filter( 'beyondwords_settings_player_styles', 'my_beyondwords_settings_player_styles' );

beyondwords_settings_post_statuses

Filters the post statuses BeyondWords considers for audio processing.
ArgumentTypeDescription
$statusesstring[]Post statuses to process
Add a custom post status
function my_beyondwords_settings_post_statuses( $statuses ) {
    $statuses[] = 'your_custom_status';

    return $statuses;
}
add_filter( 'beyondwords_settings_post_statuses', 'my_beyondwords_settings_post_statuses' );

beyondwords_settings_post_types

Filters the post types supported by BeyondWords. Defaults to all post types with custom-fields support—content and project IDs are stored in custom fields, so unsupported post types will not work as expected.
ArgumentTypeDescription
$post_typesstring[]Supported post type names
Limit support to posts only
function my_beyondwords_settings_post_types( $post_types ) {
    return [ 'post' ];
}
add_filter( 'beyondwords_settings_post_types', 'my_beyondwords_settings_post_types' );

Support and troubleshooting

When contacting support, include:
  • Site health—go to Tools → Site Health → Info, click Copy site info to clipboard, and paste the result
  • Inspect panel data—copy the BeyondWords data for the affected post from the Inspect section of the BeyondWords panel (block editor and classic editor)

404 not found

If the BeyondWords sidebar shows a #404: Not Found error in beyondwords_error_message, the WordPress post has become disconnected from its BeyondWords content.
1

Open the Inspect panel

Access the Inspect section in the block or classic editor (see above).
2

Try Fetch (block editor)

In the block editor, click Fetch in the Inspect panel to retrieve the existing audio from BeyondWords and restore the link—without regenerating audio.If Fetch succeeds, save the post and confirm the player works on the published page.
3

Link by Content ID (optional)

If you know the BeyondWords content ID, enter it in the Data section instead.
4

Remove and regenerate (last resort)

If the content no longer exists in BeyondWords, click Remove in Inspect to delete the stored data, then save your post. Recent plugin versions also attempt to delete the corresponding content from your BeyondWords dashboard.Ensure Generate audio is checked, configure generation in Settings, then republish to trigger new content generation.
If this error occurs regularly, contact support.