Using the_excerpt without tags
Sooner or later, using the_excerpt raises a few common questions. For example, if a post begins with a heading or other markup like <strong> or <em>, those tags show up in the excerpt too — which often looks wrong. Beyond that, you may want to strip not just the tags but their content as well.
Problem: The default the_excerpt output may include unwanted HTML tags and heading markup. You may also need two distinct excerpts for the same post: one clean auto-generated preview for the page, and one manually written version for the <meta name="description"> tag.
Solution: Override the excerpt filter with a custom function that strips headings and inline tags. The trick is using '' == !$text (instead of the standard '' == $text) — this inverts the check so the auto-generation runs when the manual Excerpt field is filled in. The manual excerpt then serves as the meta description, while the function generates a clean preview from the post content. In a previous post we covered basic usage. Here's a function that handles everything at once, including custom word count and trailing text:
/* Output excerpt without tags or shortcodes */
add_filter( 'get_the_excerpt', 'custom_get_the_excerpt_helloadmin', 5 );
function custom_get_the_excerpt_helloadmin( $text ) {
$raw_excerpt = $text;
/*
* Using '' == !$text (rather than '' == $text) enables two distinct excerpts:
* 1. Auto-generated: first 40 words of post content, stripped of headings and tags.
* 2. Manual: the "Excerpt" field on the Edit Post screen — ideal for meta description.
* Note: if the manual Excerpt field is filled in, it takes precedence by default.
*/
if ( '' == !$text ) {
$text = get_the_content( '' );
$text = strip_shortcodes( $text );
$text = apply_filters( 'the_content', $text );
$text = str_replace( ']]>', ']]>', $text );
// Strip heading tags and their content
$regex = '#(<h([1-6])[^>]*>)\s?(.*)?\s?(<\/h>)#';
$text = preg_replace( $regex, '', $text );
$excerpt_length = apply_filters( 'excerpt_length', 40 );
$excerpt_more = apply_filters( 'excerpt_more', ' ...' );
$excerpt = wp_trim_words( $text, $excerpt_length, $excerpt_more );
}
return apply_filters( 'wp_trim_excerpt', $excerpt, $raw_excerpt );
}
NOTE: The filter priority is set to 5 so it runs before other excerpt filters. The heading regex removes the tag and its content entirely — not just the HTML wrapper — which prevents partial heading text from leaking into the excerpt. If you only need to strip HTML tags without removing heading content, wp_strip_all_tags() is simpler.