AtlasVoice Text To Speech

⌘K
  1. Home
  2. Docs
  3. AtlasVoice Text To Speech
  4. Usage & Setup
  5. Content Extraction & CSS Selectors Guide

Content Extraction & CSS Selectors Guide

How AtlasVoice Reads Your Content

AtlasVoice automatically detects and reads your post content. By default, no configuration is needed — the plugin finds the content area automatically for most WordPress themes and page builders.

For advanced control, you can configure exactly which parts of your page the player reads using CSS selectors.

Default Behavior (No Configuration)

When no CSS selectors are configured, AtlasVoice uses this priority chain to find content:

  1. Content wrapper (when “Add Button Automatically” is enabled)
  2. Common theme content selectors (.entry-content[itemprop="articleBody"], etc.)
  3. PHP-extracted post content (final fallback)

This works automatically with most WordPress themes including Astra, GeneratePress, OceanWP, Kadence, and block themes.


Include Content By CSS Selectors (Pro)

Use this to tell AtlasVoice exactly which page areas to read.

Format

One CSS selector per line:

.entry-content
.custom-field-area

How It Works

  • Each selector targets a specific DOM element on your page
  • Content is read top-to-bottom in the order you list the selectors
  • Only target post/page body content — do not include header, sidebar, or footer selectors
  • If left empty, the plugin automatically detects the content area

Common Selectors by Theme/Builder

Theme/BuilderContent Selector
Most WordPress themes.entry-content
Elementor.elementor-widget-theme-post-content .elementor-widget-container
Divi.et_pb_post_content
Beaver Builder.fl-post-content or .fl-builder-content
GeneratePress.entry-content
Astra.entry-content or .ast-article-single .entry-content
Kadence.entry-content
OceanWP.entry-content or .oceanwp-content-area .entry-content
Block themes (FSE).wp-block-post-content
Flavor/Flavor theme.td-post-content

Tips

  • Use your browser’s DevTools (right-click > Inspect) to find the correct CSS selector for your theme
  • If the title is inside your selector (e.g., you used article), AtlasVoice will automatically avoid reading it twice
  • You can add multiple selectors to combine content from different page areas

Exclude Content By CSS Selectors (Pro)

Remove specific elements within the included content areas.

Format

One CSS selector per line:

.social-share
.related-posts
.author-bio

How It Works

  • These selectors are applied within each “Include” selector — not the whole page
  • Matching elements are removed before the text is extracted
  • Use this for widgets, CTAs, or sections you don’t want read aloud

Example Selectors (not applied by default)

  • .social-share.share-buttons — social sharing widgets
  • .related-posts.yarpp-related — related posts sections
  • .author-bio.author-box — author information
  • .wp-caption-textfigcaption — image captions
  • .toc.table-of-contents — table of contents
  • .ad-container.advertisement — ad blocks
  • .comments-area — comments section
  • navaside — navigation and sidebars (if inside content area)

You can also add the class .atlasvoice_no_read to any HTML element in your theme to exclude it from being read.


Exclude HTML Tags To Speak (Pro)

Remove all instances of specific HTML tag types within the included content.

Format

Pipe-separated tag names (no angle brackets):

sub|sup|blockquote|code|pre

How It Works

  • Tags are removed within each “Include” selector scope
  • scriptstylefigure, and figcaption are always excluded automatically
  • Only add tags you specifically want to skip

Example Tags (not applied by default)

  • sub — subscript text
  • sup — superscript text (footnote markers)
  • blockquote — quoted text
  • codepre — code snippets
  • caption — table captions
  • nav — navigation elements

Exclude Texts To Speak (Pro)

Remove exact text patterns from the spoken content.

Format

Pipe-separated text strings:

Read more...|Advertisement|Sponsored Content|Click here

How It Works

  • Applied after all CSS selector and tag exclusions
  • Matches exact text strings (case-sensitive)
  • Useful for removing repeated phrases, CTAs, or boilerplate text that appears in content

ACF Fields Integration

AtlasVoice can read content from Advanced Custom Fields (ACF) alongside your main post content.

How to Set Up

  1. Go to AtlasVoice > Compatibility
  2. Under “Add ACF Fields To Posts”, select the fields you want read
  3. Save

How It Works

  • Selected fields are read after the main article content
  • Fields are read in the order you select them
  • Supports text fields and repeater/flexible content fields
  • If a field is already visible in your post content area, it may be read twice

When to Use CSS Selectors Instead

If your ACF fields are rendered on the page by your theme template, use “Include Content By CSS Selectors” instead. This gives you control over the reading order and avoids potential duplication.

Use the ACF integration in Compatibility for fields that are:

  • Not displayed on the front-end page
  • Stored as metadata only
  • Used programmatically by your theme

Per-Post Overrides (Pro)

You can override global CSS selector settings on individual posts.

How to Set Up

  1. Edit a post in WordPress
  2. Find the “AtlasVoice CSS Selectors” meta box
  3. Enable “Use Own CSS Selectors”
  4. Configure the selectors for this specific post
  5. Save

How It Works

  • Per-post settings override global settings for that post only
  • Only non-empty per-post fields override the global values
  • Empty per-post fields keep the global setting
  • Useful for posts with unique layouts or special content structures

For Developers: Custom Plugin Integration

If you’re a theme or plugin developer, you can add custom content to AtlasVoice using the tts_pro_compatible_plugins_content filter:

add_filter( 'tts_pro_compatible_plugins_content', function( $data, $compatible_data, $post ) {
// Example: Add content from Meta Box plugin
if ( function_exists( 'rwmb_get_value' ) ) {
$value = rwmb_get_value( 'my_custom_field', array(), $post->ID );
if ( is_string( $value ) && ! empty( $value ) ) {
$data['meta_box_my_field'] = wp_strip_all_tags( $value );
}
}
return $data;
}, 10, 3 );

JavaScript Filters

Custom content area selectors — add your theme’s content selector to the automatic detection chain. This filter runs when no “Include Content By CSS Selectors” are configured in Settings AND the .tts_content_wrapper_X div is not found (shortcode mode, custom themes, page builders). It does NOT run when the user has configured explicit include selectors — those take priority.

wp.hooks.addFilter( 'ttsCommonContentSelectors', 'my-theme', function( selectors ) {
// Add your theme's content selector at the beginning (highest priority)
selectors.unshift( '.my-theme-content-area' );
return selectors;
} );

Custom title selectors — add your theme’s title selector to the title detection chain. This filter runs every time the player extracts content from the DOM to find the post title. It is used for title prepending and title deduplication. It does NOT run when DOM reading is disabled (Read Content From Dom is off) — in that case the title comes from the PHP variable.

wp.hooks.addFilter( 'ttsTitleSelectors', 'my-theme', function( selectors ) {
// Add your theme's title selector at the beginning (highest priority)
selectors.unshift( '.my-theme-post-title' );
return selectors;
} );

Default title selectors (in priority order): .entry-title.post-title.wp-block-post-title.elementor-heading-title.elementor-page-title.page-title.ast-single-post-title.oceanwp-single-titlearticle h1.hentry h1.post h1h1

Filter DOM content before text extraction — modify the cloned DOM element before AtlasVoice extracts text from it. This filter runs when DOM reading is enabled. Use it to remove specific elements that the exclude CSS selectors setting can’t target (e.g., elements that follow a specific text pattern rather than having a unique class).

wp.hooks.addFilter( 'tts_before_dom_content_extract', 'my-plugin', function( dom, buttonId ) {
// Example: Remove all elements with a specific data attribute
dom.querySelectorAll( '[data-no-tts]' ).forEach( function( el ) { el.remove(); } );
return dom;
} );

Example: Remove “Read also:” blocks and their link paragraphs — this is a real-world example used by a news site. The “Read also:” label is followed by <p><a> link paragraphs that should not be read. Add this as a JS snippet via a code snippets plugin:

(function checkWpHooks() {
if (window.wp && wp.hooks) {
wp.hooks.addFilter("tts_before_dom_content_extract", "tts/remove-read-also", function(dom) {
var paragraphs = Array.from(dom.querySelectorAll("p"));
for (var i = 0; i < paragraphs.length; i++) {
var text = paragraphs[i].textContent.trim().toLowerCase();
if (text === "read also:" || text === "read also") {
var nextSibling = paragraphs[i].nextElementSibling;
paragraphs[i].remove();
while (nextSibling) {
var current = nextSibling;
nextSibling = current.nextElementSibling;
if (current.tagName === "P" && current.children.length === 1 && current.children[0].tagName === "A") {
current.remove();
} else {
break;
}
}
break;
}
}
return dom;
});
} else {
setTimeout(checkWpHooks, 50);
}
})();

PHP Filters

Control content wrapper — enable or disable the .tts_content_wrapper_X div that wraps post content:

// Disable the content wrapper globally
add_filter( 'tts_should_add_content_wrapper', '__return_false' );

// Disable for a specific post
add_filter( 'tts_should_add_content_wrapper', function( $should_add, $content, $btn_no, $post ) {
if ( $post && $post->ID === 123 ) {
return false;
}
return $should_add;
}, 10, 4 );

Filter content before HTML is stripped — modify the raw HTML content before wp_strip_all_tags() runs. This filter works when DOM reading is off (PHP content path). Use it to remove specific HTML patterns like “Read also:” blocks that can’t be targeted by CSS selectors because they’re plain <p> tags without unique classes.

// Example: Remove "Read also:" label and its following link paragraphs.
// Handles WordPress block comments (<!-- wp:paragraph -->) between paragraphs.
add_filter( 'tta_before_clean_content', function ( $content ) {
$pattern = '/<p[^>]*>\s*<strong>\s*Read also:\s*<\/strong>\s*<\/p>(\s*(?:<!--.*?-->\s*)*<p[^>]*>\s*<a\s[^>]*>[^<]*<\/a>\s*<\/p>)*/is';
return preg_replace( $pattern, '', $content );
} );

Note: The tta_before_clean_content filter receives the raw HTML with tags intact. The tta_clean_content filter receives the cleaned plain text after all processing is done. Use tta_before_clean_content to remove HTML elements, and tta_clean_content to modify the final text.


Exclude Content: DOM On vs DOM Off

The “Exclude Content By CSS Selectors” setting works in both paths:

PathHow It Works
DOM reading on (JS)Uses querySelectorAll(selector).remove() on the cloned DOM — full CSS selector support
DOM reading off (PHP)Converts selectors to balanced HTML tag matching — supports .class#id, and tag.class selectors

When DOM reading is off, the PHP path strips matching elements from the raw HTML before wp_strip_all_tags() runs. This ensures the same content is excluded regardless of which path is active.

The .atlasvoice_no_read class works in both paths — add it to any HTML element to exclude it from TTS reading.


Troubleshooting

ProblemCauseSolution
Player reads only the titleContent selector not foundAdd your theme’s content selector to “Include Content By CSS Selectors”
Content is read twiceInclude selector captures the title elementFixed automatically in latest version
Wrong reading orderSelectors listed in wrong orderReorder your Include selectors (read top-to-bottom)
Player reads sidebar/footerSelector is too broadUse a more specific selector (e.g., .entry-content instead of article)
Reading time is wrongContent was extracted differently than expectedFixed automatically — reading time recalculates on the frontend
ACF field read twiceField is visible on page AND selected in CompatibilityRemove from Compatibility, use CSS selectors instead
Smart quotes read as codesHTML entities not decodedFixed automatically — decodeHTMLEntities() handles &#8217; etc.
Per-post CSS selectors not appliedCache not clearedClear browser sessionStorage or wait for cache invalidation
Exclude selector doesn’t work with DOM offPHP can’t parse CSS selectors like JSOnly .class#id, and tag.class selectors work in PHP path. Complex selectors (:nth-child>+) require DOM reading on
“Read also:” or link previews still readNot excluded by CSS selectorsUse tta_before_clean_content PHP filter or tts_before_dom_content_extract JS filter (see examples above)
Words joined together (e.g., “onKharg”)HTML tags stripped without spacesFixed in TTS-235 — wp_strip_all_tags now adds spaces before tags
Hebrew/Arabic text shows as Non-UTF-8 regex corrupting multibyte charsFixed in TTS-235 — all regex patterns use /u flag for Unicode safety
&nbsp; causes joined wordsNon-breaking space removed instead of convertedFixed in TTS-235 — &nbsp; now converts to regular space
Visual spacer dots read as “dot dot”Authors use . . . as section dividersFixed in TTS-235 — visual spacer dots automatically cleaned from content

How can we help?