Writing a wordpress read time plugin6 min read

Lately, I have been seeing estimated read times near post titles. It went like “2 min read”, “5 min red” , and as a reader it felt good to know how much time I’am going to waste on some random article ? .

So I have decided pass on the luxury ????  . It must be obvious by now that this blog runs on wordpress. There are many plugins available to add this feature to a wordpress blog, but ???? you know…

How to create a wordpress plugin?

It may seem like an uphill task, but actually you can finish one in a few minutes. To learn more, buy my eBook wordpress plugins for dumm.. ? , ehmmm a little bit of PHP and HTML and you are good to go.

For a detailed and fairly simple documentation go to Start here – Writing a plugin.

You need to add the necessary header and license information on top of your main PHP page for wordpress to identify it as a plugin.

It would look something like this –

Plugin Name: Calc read time
Plugin URI:
Description: Estimates read time for posts and shows it near post titles.
Version:     1
Author:      Jijnasu
Author URI:
License:     GPL2
License URI:
Text Domain: wporg
Domain Path: /languages

The read time plugin

Estimating the read time

After time and brain intensive calculations, I have come to the conclusion that an average adult can read about 200-250 words per minute (wpm).

Link to my research material – Average reading speed.

So we get the number of words in an article, divide it by 250 and we have our average reading time. As simple as that.

But that’s in english, in PHP it would look like

$post = "Hi guys, today let's talk about the top ten reasons why is the best blog in the world";
$post_word_count = str_word_count($post);
$words_read_per_min = 250;
$words_read_per_sec = 250 / 60;
$post_read_time_in_sec = ceil($post_word_count / $words_read_per_sec);

PHP – str_word_count.

WordPress integration

WordPress gives events we can register different functions on, like the events in javascript (in usage).

There are two types of events

  1. add_action ( string $tag, callable $function_to_add, int $priority = 10int $accepted_args = 1 )
  2. add_filter ( string $tag, callable $function_to_add, int $priority = 10int $accepted_args = 1 )

$tag represent the event.

Let’s add a filter

add_filter( 'wp_insert_post_data', 'calc_read_time_calc', 1, 2 );

The function ‘calc_read_time_calc’ would run everytime a post is inserted or updated. The event name being ‘wp_insert_post_data’.

The calc_read_time_calc function

// function to save word count of posts

function calc_read_time_calc($data, $postarr)
  $post_word_count = str_word_count($data['post_content']);

  // update meta data if exists else update
  // meta_key: calc_read_time_word_count
  // meta_value : $post_word_count

  if (!add_post_meta($postarr['ID'], 'calc_read_time_word_count', $post_word_count, true))
    update_post_meta($postarr['ID'], 'calc_read_time_word_count', $post_word_count);

  return $data;

On insert or update of posts the word count is calculated and saved as meta data with key calc_read_time_word_count .

Showing it to the reader

We can doing this by adding one more filter

add_filter( 'the_title', 'calc_read_time_add_read_text_in_title', 1, 2 );

With this filter we can update the post title (the_title) before printing it on the screen.

We would use the calc_read_time_add_read_text_in_title ? function, to append read time to the post title.

The calc_read_time_add_read_text_in_title function

// function to append read time
// to the post title

function calc_read_time_add_read_text_in_title($title, $post_id)

  // add read time to only posts
  // and not pages or other stuff
  // also not in admin pages

  if (get_post_type($post_id) != 'post' || is_admin())
    return $title;

  // retrive word count saved
  // as meta data

  $word_count = get_post_meta($post_id, 'calc_read_time_word_count', true);

  // if word count was not set
  // set it for this post

  if (empty($word_count))
      'post_content' => get_post_field('post_content', $post_id)
    ) , array(
      'ID' => $post_id
    $word_count = get_post_meta($post->ID, 'calc_read_time_word_count', true);

  $word_count = (int)$word_count;
  if ($word_count == 0)
    return $title;

  // append word count to the title

  return $title . '<span class="calc_read_time_shower_title_span">' . calc_read_time_create_text($word_count) . '</span>';

If word count was not set for some post, it would be set inside this function.

If you paid any attention at all, which is highly unlikely, u must have noticed another function calc_read_time_create_text at the end.

It is used to calculate the reading time with the word count as input.

The calc_read_time_create_text function

// function to calculate
// read time with word_count

function calc_read_time_create_text($post_word_count)

  // words read per minute

  $wpm = 240;

  // words read per second

  $wps = $wpm / 60;
  $secs_to_read = ceil($post_word_count / $wps);
  $read_time_text = $secs_to_read < 60 ? $secs_to_read . ' sec' : round($secs_to_read / 60) . ' min';
  $read_time_text.= ' read';

  // ex - 5min read

  return $read_time_text;

Ideally the user should be able to set the words read per minute, but let’s look at it later.

And finally let’s add some CSS.

The style sheet
  display: block;
  font-size: 15px;
  background: inherit;
  color: inherit;

Adding style sheets in wordpress

add_action( 'wp_enqueue_scripts', 'calc_read_time_add_styles' );

Use the add action to add style-sheets or scripts to your pages.

The calc_read_time_add_styles function
function calc_read_time_add_styles()
  wp_enqueue_style('calc-read-time-styles', plugin_dir_url(__FILE__) . 'calc-read-time-styles.css', array() , null);


  • The function names must be unique.
  • The style-sheet names must be unique.
  • The plugin folder name should not contain spaces. Replace spaces with hyphens. Ex- ‘calc-read-time’ not ‘Calc read time’.
  • Zip the plugin folder and upload it to your wordpress site.

Download the plugin – calc-read-time.

Download it on – Calc Read Time

Good day ????

Leave a Reply

Your email address will not be published. Required fields are marked *