Tutorial·4 min·May 22, 2026

How to add audio to WordPress in under five minutes

No plugin required — paste one embed snippet and your posts get a styled audio player. A step-by-step walkthrough.

Adding a narrated audio player to WordPress is one snippet of HTML. There's no plugin to install, no FTP, no theme files to edit, and nothing to keep updated. This walks through the whole thing, plus the two or three details that decide whether the audio comes out clean or full of your own navigation menu.

Why not a plugin?

Most "text to speech for WordPress" results are plugins. A plugin means another thing in your update queue, another thing that can conflict with your theme, and another thing slowing down admin. An embed is a single <script> tag. It renders in the post, it can't touch the rest of your install, and it works identically on WordPress.com, self-hosted WordPress, and any other CMS you migrate to later.

Step 1 — Create and style a player

Sign up at app.butterreader.blog and create a player — a reusable, styled widget. The free plan includes managed AI voices (Chirp 3 HD and Gemini Flash), so there's no API key to configure.

Style it once: colours, shape, and whether you want a visualizer or a plain bar. Every post that uses this player inherits the styling, and restyling later updates every post at once — you never re-paste the snippet.

Step 2 — Paste the snippet into a Custom HTML block

Open your post in the block editor, add a Custom HTML block where the player should appear, and paste:

<script src="https://butter-reader.web.app/widget/AudioPlayerWidget.bundle.js"
        data-player-id="YOUR_PLAYER_ID"></script>

By default the widget injects itself exactly where the script tag sits. If you'd rather control placement precisely, give it a container to mount into:

<div data-butter-player-id="YOUR_PLAYER_ID"></div>
<script src="https://butter-reader.web.app/widget/AudioPlayerWidget.bundle.js"
        data-player-id="YOUR_PLAYER_ID"></script>

Step 3 — Publish

That's the install. Hit publish and your readers get a play button on the post.

Putting it on every post automatically

Pasting a block into each post gets old fast. Add the snippet to your theme's single post template instead — in a block theme, edit the Single template in the Site Editor and drop a Custom HTML block below the title; in a classic theme, add it to single.php.

Use one player per page. The same player ID can live on every post, because the widget reads whatever page it's currently on and converts that page's content. One player, one snippet, every article.

The part that actually matters: what gets read

The widget reads your article off the rendered page rather than from a hardcoded theme selector. Understanding the order it works in is the difference between clean narration and audio that opens by reading your menu:

  1. It finds the first <h1> and treats it as the title.
  2. It looks for the nearest <article>, <main>, [role="main"], .entry-content, or .post-content wrapping that <h1>.
  3. Inside that container it reads text from <p>, <h2><h6>, <li>, and <blockquote> only.
  4. It strips <nav>, <header>, and <footer>, plus anything whose class or id contains nav, menu, sidebar, widget, ad, comment, share, social, related, tag, category, author, meta, breadcrumb, pagination, or search.

Standard WordPress themes already wrap posts in <article> and .entry-content, which is why this works out of the box on the overwhelming majority of installs — considerably more reliably than on <div>-heavy page builders.

Three things that break it

Text inside bare <div> or <span> is ignored. This is the big one. If you build posts with a page builder that renders paragraphs as styled <div>s, the detector will skip them. Standard blocks output real <p> tags and are fine.

More than one <h1>. Some themes mark the site title as an <h1> alongside the post title. The widget takes the first one, so if your header comes first, it will use your site name as the article title. Fix the theme to use <h1> for the post title only — worth doing regardless, since it's a basic on-page SEO requirement too.

Content loaded after page load. Text hidden inside tabs or accordions, or injected later by JavaScript, may not be present when the widget reads the page.

Length

Each conversion handles roughly 4,000 characters, trimmed at a sentence boundary. That covers most blog posts comfortably. For a long guide, the practical move is to give the audio version its own focused summary rather than narrating 5,000 words nobody will listen to end to end.

Where to put the player

Above the fold, directly under the title. A player at the bottom of the article is a player nobody presses — the reader who wanted to listen has already left. This single placement decision moves listen rates more than any styling choice.

Next steps

Once it's working on one post, the same snippet works on Wix, Webflow, Squarespace, Ghost, or a hand-built site — you're not locked to WordPress. Worth reading next: choosing a voice that suits your writing, and what audio actually does for your search performance.

Start free and add a player to your best-performing post first.

Make your own posts listenable

Turn this kind of article into audio in minutes — free to start.

Try ButterReader →

See what it costs · Read the embedding docs