Opens in a new tab

Calculate all WordPress Posts How Many Words there are

add this to your functions.php and it will add Word Count named page to the dashboard and it will show the total word count for all posts.

 

// Add a custom page to the WordPress admin menu
function word_count_admin_menu() {
    add_menu_page(
        'Word Count',
        'Word Count',
        'manage_options',
        'word-count',
        'word_count_admin_page',
        'dashicons-editor-spellcheck',
        20
    );
}
add_action('admin_menu', 'word_count_admin_menu');

// Display the total word count of all posts in the custom admin page
function word_count_admin_page() {
    global $wpdb;
    
    $total_word_count = 0;
    $results = $wpdb->get_results("SELECT post_content FROM $wpdb->posts WHERE post_status = 'publish' AND post_type = 'post'");

    foreach ($results as $result) {
        $word_count = str_word_count(strip_tags($result->post_content));
        $total_word_count += $word_count;
    }
    ?>
    <div class="wrap">
        <h1>Total Word Count</h1>
        <p>The total number of words in all posts: <?php echo esc_html($total_word_count); ?></p>
    </div>
    <?php
}

 

UPDATED

this coutns bouth wordpress editor and briks eeditor contents as well.

<?php 

/**
 * Word Count admin page (classic/Gutenberg + Bricks).
 * Counting logic mirrors WPML (WPML_TM_Word_Calculator) and the Bricks WPML integration
 * (only text / textarea / editor / repeater controls are treated as content).
 */

function word_count_admin_menu() {
	add_menu_page( 'Word Count', 'Word Count', 'manage_options', 'word-count', 'word_count_admin_page', 'dashicons-editor-spellcheck', 20 );
}
add_action( 'admin_menu', 'word_count_admin_menu' );

// WPML-style word counter: decode entities, strip tags/URLs/shortcode tags, split on whitespace + punctuation
function word_count_count( $string ) {
	if ( ! is_string( $string ) || $string === '' ) {
		return 0;
	}
	$s = html_entity_decode( $string, ENT_QUOTES, 'UTF-8' );
	$s = wp_strip_all_tags( $s );
	$s = preg_replace( '#(https?|ftp|file)://[^[:space:]]+#i', '', $s );
	$s = preg_replace( '#[[]/?[^]/]+/?[]]#', '', $s );
	$words = preg_split( '#[[:space:][:punct:]]+#u', trim( $s ), -1, PREG_SPLIT_NO_EMPTY );
	return $words ? count( $words ) : 0;
}

// Text of one Bricks element, using the element's own control definitions (same as Bricks' WPML integration)
function word_count_bricks_element_text( $element ) {
	$settings = isset( $element['settings'] ) && is_array( $element['settings'] ) ? $element['settings'] : array();
	if ( ! $settings || empty( $element['name'] ) ) {
		return '';
	}

	$types    = array( 'text', 'textarea', 'editor' );
	$exclude  = array( 'customTag', '_gridTemplateColumns', '_gridTemplateRows', '_cssId', 'targetSelector' );
	$controls = array();

	$bricks_elements = 'Bricks' . chr( 92 ) . 'Elements'; // no backslashes: snippet plugin strips them
	if ( class_exists( $bricks_elements ) ) {
		$config   = call_user_func( array( $bricks_elements, 'get_element' ), array( 'name' => $element['name'] ) );
		$controls = ! empty( $config['controls'] ) && is_array( $config['controls'] ) ? $config['controls'] : array();
	}

	$out = '';

	// Fallback when Bricks isn't loaded / element unknown: common text keys
	if ( ! $controls ) {
		foreach ( array( 'text', 'title', 'content', 'label', 'subtitle', 'description' ) as $k ) {
			if ( ! empty( $settings[ $k ] ) && is_string( $settings[ $k ] ) ) {
				$out .= ' ' . $settings[ $k ];
			}
		}
		return $out;
	}

	foreach ( $controls as $key => $control ) {
		if ( empty( $settings[ $key ] ) || in_array( $key, $exclude, true ) ) {
			continue;
		}
		$type = isset( $control['type'] ) ? $control['type'] : '';

		if ( in_array( $type, $types, true ) && is_string( $settings[ $key ] ) ) {
			$out .= ' ' . $settings[ $key ];
		} elseif ( $type === 'repeater' && is_array( $settings[ $key ] ) && ! empty( $control['fields'] ) ) {
			foreach ( $settings[ $key ] as $item ) {
				foreach ( (array) $item as $f_key => $f_val ) {
					$f_type = isset( $control['fields'][ $f_key ]['type'] ) ? $control['fields'][ $f_key ]['type'] : '';
					if ( in_array( $f_type, $types, true ) && is_string( $f_val ) ) {
						$out .= ' ' . $f_val;
					}
				}
			}
		}
	}

	return $out;
}

function word_count_admin_page() {
	global $wpdb;

	$post_types = array( 'post', 'page' ); // add CPTs here
	$in         = implode( ',', array_fill( 0, count( $post_types ), '%s' ) );

	// Direct query so language/translation plugins can't filter posts out
	$posts = $wpdb->get_results( $wpdb->prepare(
		"SELECT ID, post_title, post_type, post_content FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_type IN ($in) ORDER BY post_type, ID",
		$post_types
	) );

	$rows  = array();
	$total = $total_bricks = $total_classic = 0;

	foreach ( $posts as $p ) {
		$elements  = get_post_meta( $p->ID, '_bricks_page_content_2', true );
		$is_bricks = get_post_meta( $p->ID, '_bricks_editor_mode', true ) === 'bricks' && is_array( $elements ) && $elements;

		if ( $is_bricks ) {
			$text = '';
			foreach ( $elements as $el ) {
				$text .= ' ' . word_count_bricks_element_text( $el );
			}
			$count          = word_count_count( $text );
			$total_bricks  += $count;
		} else {
			$count          = word_count_count( $p->post_content );
			$total_classic += $count;
		}
		$total += $count;
		$rows[] = array( $p, $is_bricks ? 'Bricks' : 'Classic/Gutenberg', $count );
	}
	?>
	<div class="wrap">
		<h1>Total Word Count</h1>
		<p>Total words: <strong><?php echo esc_html( number_format_i18n( $total ) ); ?></strong>
			(<?php echo esc_html( count( $posts ) ); ?> published items)</p>
		<p>Bricks: <?php echo esc_html( number_format_i18n( $total_bricks ) ); ?> &middot;
			Classic/Gutenberg: <?php echo esc_html( number_format_i18n( $total_classic ) ); ?></p>

		<table class="widefat striped" style="max-width:800px">
			<thead><tr><th>ID</th><th>Title</th><th>Type</th><th>Source</th><th>Words</th></tr></thead>
			<tbody>
			<?php foreach ( $rows as $r ) : ?>
				<tr>
					<td><?php echo (int) $r[0]->ID; ?></td>
					<td><a href="<?php echo esc_url( get_edit_post_link( $r[0]->ID ) ); ?>"><?php echo esc_html( $r[0]->post_title ); ?></a></td>
					<td><?php echo esc_html( $r[0]->post_type ); ?></td>
					<td><?php echo esc_html( $r[1] ); ?></td>
					<td><?php echo esc_html( number_format_i18n( $r[2] ) ); ?></td>
				</tr>
			<?php endforeach; ?>
			</tbody>
		</table>
	</div>
	<?php
}