How to Create a Voice-Powered WordPress Plugin and Host It
Why a Voice‑Powered WordPress Plugin? Voice interfaces are no longer a novelty—they’re becoming a core part of how users interact with digital products. Adding text‑to‑speech (TTS) or voice‑cloning capabilities to a Wo
Why a Voice‑Powered WordPress Plugin?
Voice interfaces are no longer a novelty—they’re becoming a core part of how users interact with digital products. Adding text‑to‑speech (TTS) or voice‑cloning capabilities to a WordPress site can:
- Make content more accessible for visually‑impaired visitors.
- Keep readers engaged while they multitask (think “listen while you cook”).
- Give you a unique branding voice that can be reused across posts, podcasts, and ads.
In this guide we’ll build a lightweight WordPress plugin that sends article text to ElevenLabs (the industry‑leading TTS & voice‑cloning service) and streams the generated audio back to the front‑end. When the plugin is ready, we’ll deploy it on Bluehost, the affordable, one‑click WordPress host that makes publishing a breeze.
Prerequisites
| What you need | Why |
|---|---|
| A fresh WordPress install (≥ 5.8) | The plugin hooks into the the_content filter. |
| PHP 7.4+ (the default on most hosts) | Required for cURL calls to the ElevenLabs API. |
| An ElevenLabs API key (sign up here) | To generate audio files. |
| A Bluehost account (sign up here) | Easy, affordable hosting for WordPress sites. |
| Basic knowledge of PHP & JavaScript | To understand the snippets below. |
1. Scaffold the Plugin
Create a folder called voice‑tts inside wp-content/plugins/ and add a main file voice-tts.php:
<?php
/**
* Plugin Name: Voice‑Powered TTS
* Description: Adds ElevenLabs text‑to‑speech to posts.
* Version: 1.0
* Author: Your Name
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Prevent direct access.
}
// Enqueue front‑end script.
function vt_enqueue_scripts() {
wp_enqueue_script(
'vt-player',
plugins_url( 'vt-player.js', __FILE__ ),
array( 'jquery' ),
'1.0',
true
);
}
add_action( 'wp_enqueue_scripts', 'vt_enqueue_scripts' );
// Hook into post content.
function vt_append_audio( $content ) {
if ( is_singular() && in_the_loop() && is_main_query() ) {
$audio_html = '<div class="vt-audio-player" data-post-id="' . get_the_ID() . '">
<button class="vt-play">🔊 Play Article</button>
<audio controls style="display:none;"></audio>
</div>';
return $content . $audio_html;
}
return $content;
}
add_filter( 'the_content', 'vt_append_audio' );
The plugin does two things:
- Adds a button after each post.
-
Loads a small JavaScript file (
vt-player.js) that will request audio from ElevenLabs when the button is clicked.
2. The JavaScript Bridge (vt-player.js)
jQuery(document).ready(function($){
$('.vt-play').on('click', function(){
const $wrapper = $(this).closest('.vt-audio-player');
const postId = $wrapper.data('post-id');
// Disable button while we fetch.
$(this).prop('disabled', true).text('Generating…');
$.ajax({
url: vt_ajax.ajax_url,
method: 'POST',
data: {
action: 'vt_generate_audio',
post_id: postId,
_ajax_nonce: vt_ajax.nonce
},
success: function(res){
if (res.success) {
const audio = $wrapper.find('audio')[0];
audio.src = res.data.url;
audio.style.display = 'block';
audio.play();
} else {
alert('Error: ' + res.data);
}
$('.vt-play').prop('disabled', false).text('🔊 Play Article');
}
});
});
});
We’ll expose a tiny AJAX endpoint in PHP next.
3. AJAX Handler & ElevenLabs Integration
Add the following to voice-tts.php below the previous code:
// Localize script with AJAX data.
function vt_localize_script() {
wp_localize_script( 'vt-player', 'vt_ajax', array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'vt_nonce' )
) );
}
add_action( 'wp_enqueue_scripts', 'vt_localize_script' );
// AJAX callback.
function vt_generate_audio() {
check_ajax_referer( 'vt_nonce', '_ajax_nonce' );
$post_id = intval( $_POST['post_id'] );
$post = get_post( $post_id );
if ( ! $post ) {
wp_send_json_error( 'Invalid post.' );
}
// Prepare request to ElevenLabs.
$api_key = 'YOUR_ELEVENLABS_API_KEY'; // <-- replace!
$voice_id = 'YOUR_VOICE_ID'; // pick a voice from ElevenLabs dashboard.
$payload = array(
'text' => wp_strip_all_tags( $post->post_content ),
'voice_settings' => array(
'stability' => 0.75,
'similarity_boost' => 0.85
)
);
$ch = curl_init( "https://api.elevenlabs.io/v1/text-to-speech/{$voice_id}/stream" );
curl_setopt_array( $ch, array(
CURLOPT_HTTPHEADER => array(
"Content-Type: application/json",
"xi-api-key: {$api_key}"
),
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode( $payload ),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30
) );
$audio = curl_exec( $ch );
$err = curl_error( $ch );
curl_close( $ch );
if ( $err ) {
wp_send_json_error( $err );
}
// Store audio in WP uploads.
$upload_dir = wp_upload_dir();
$filename = "post-{$post_id}.mp3";
$file_path = $upload_dir['path'] . '/' . $filename;
file_put_contents( $file_path, $audio );
$url = $upload_dir['url'] . '/' . $filename;
wp_send_json_success( array( 'url' => $url ) );
}
add_action( 'wp_ajax_vt_generate_audio', 'vt_generate_audio' );
add_action( 'wp_ajax_nopriv_vt_generate_audio', 'vt_generate_audio' );
What’s happening?
- The AJAX request sends the post ID to the server.
- PHP pulls the post content, strips HTML, and posts it to ElevenLabs’
/streamendpoint. - The returned MP3 binary is saved to the WordPress uploads folder.
- The URL is sent back to the front‑end, where the
<audio>element starts playing.
Tip: If you want voice cloning instead of a generic voice, create a custom voice in your ElevenLabs dashboard, copy its
voice_id, and replaceYOUR_VOICE_IDabove. The same endpoint works for cloned voices, giving you a signature sound for your brand.
4. Test Locally
- Activate the plugin from the WordPress admin.
- Open any single post, click Play Article, and you should hear the generated speech.
- Check
wp-content/uploads/– you’ll see an MP3 file for each post you’ve processed.
If anything fails, inspect the browser console and the WordPress debug log (wp-content/debug.log). Common issues are missing API keys or cURL not being enabled on the server.
5. Deploy to Bluehost – The Easy Way
When you’re happy with the local prototype, it’s time to go live. Bluehost offers a one‑click WordPress installer, automatic SSL, and a built‑in file manager, making the deployment process almost frictionless.
- Create a new site using the Bluehost dashboard → “Create New Site”.
- Choose a domain (or a sub‑domain) and let Bluehost set up WordPress for you.
- Open the File Manager or connect via SFTP (Bluehost supplies credentials).
- Upload the
voice‑ttsfolder towp-content/plugins/. - Activate the plugin from the WordPress admin, paste your ElevenLabs API key and voice ID in the PHP file, and you’re done.
Bluehost’s managed environment already includes cURL and the required PHP version, so you won’t need to tweak server settings. Plus, their affordable plans start at just a few dollars a month, making it a perfect fit for hobby projects or small‑business sites.
6. Going Further
- Cache audio files – Store the generated MP3 URL in post meta so you only call ElevenLabs once per post.
-
Add a shortcode – Let users embed a player anywhere with
[voice_tts]. -
Support multiple languages – ElevenLabs supports several locales; pass
languagein the payload. - Integrate with Gutenberg – Create a block that automatically adds the button while editing.
All of these enhancements can be built on top of the simple foundation we just created.
Wrap‑Up
You now have a fully functional voice‑powered WordPress plugin that leverages ElevenLabs for high‑quality text‑to‑speech and voice cloning, and you know how to host it on Bluehost with minimal hassle. The combination of a powerful AI service and an easy‑to‑use hosting platform means you can focus on content and user experience rather than server gymnastics.
Ready to give your readers a new way to consume your posts? Grab an ElevenLabs API key here and spin up your WordPress site on Bluehost today with the link below. Happy coding—and happy listening!
Try ElevenLabs now: https://try.elevenlabs.io/kr07zfuqn1bp
Deploy on Bluehost: https://bluehost.sjv.io/5k0d52
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.