Australia's Leading Digital Marketing Experts. T. 1300 235 433  |  Aggregation Enquires Welcome

# Count Sentences, Words, and Syllables to Return a Flesch Reading Ease Score

We manage the learning management of a number of business and often get requests that go beyond the scope of most packaged learning systems - including our own. One of our customers asked if we could count assess all test answers, survey answers, and emails (most importantly) for a Flesch Reading Ease score. Measuring the quality of an individual's writing was an efficient means of scoring and measuring the improvement of a particular student over time. The idea was that it didn't matter where and how writing material found its way to faculty, incoming text would always be scored (in context).

The Flesch Reading Ease formula was first developed in 1943 by Rudolf Flesch in his PhD dissertation, Marks of a Readable Style. The early works of Fletch have found their way into two formulas that are most often applied to assess general readability - the Reading Ease score and the The Flesch–Kincaid formula. The former algorithm returns a score from 0 to 100, with 0 equivalent to a college graduate and 100 equivalent to the 5th grade. The latter formula presents a score as a U.S. grade level, making it easier for teachers, parents, librarians, and others to judge the readability level of various books and texts.

The Flesch Reading Ease score is so ubiquitous that a number of U.S states requires that insurance policies be written with a score that equates to a 4th grade level, and publishers have adopted score-testing to increase their readership - generally aiming for a score of 50 or higher (in comparison to academic and scientific papers that most often score lower than 30).

The Flesch–Kincaid score was developed in 1975 alongside the US Navy, and they later adopted the score to assess incoming cadets, internal forms, and text book readability. The score returns a U.S grade level approximation (adding a value of 5 to the result returns the approximate age of an individual in that grade).

No formula is entirely accurate... although the Flesch–Kincaid formula has withstood the test of time and is said to correlate with a score of 0.91 when measured again more traditional reading assessments.

### Used in Marketing and Blogging

When you write marketing copy, sales copy, or an article on your website, you should generally aim for a Flesch Reading Ease score of around 60 so your efforts appeal to the largest readership. While there's a number of WordPress plugins that will make an attempt to score your article readability, few (if any) will return the result a graded results to your website's front-end... and none of them are overly accurate.

✓ Example Usage
You might choose to return a readability score for each article on your website the same way tutorials are graded from beginner, intermediate, and advanced.

It's unknown if search engine algorithms apply any readability assessment to pages. However, from a holistic SEO point-of-view, it can't be ignored.

The Flesch Reading Ease and Flesch–Kincaid Grade Level algorithms are as follows:

In the Flesch Reading-Ease Test (FRES). Higher scores indicate material that is easier to read; lower numbers mark passages that are more difficult to read. It's the Flesch formula that is applied to our example results below.

206.835 - 1.015 (text{total words} / text{total sentence}) - 84.6 (text{total syllables} / text{total words})

The "Flesch–Kincaid Grade Level Formula" presents a score as a U.S. grade level.

0.39 (text{total words} / text{total sentence}) + 11.8 (text{total syllables} / text{total words}) - 15.59

There are other readability formulas that are often used in addition to those above; they're reproduced below.

### PHP Considerations

To assess the Flesch Reading Ease score, we require the total words, total sentences, and total syllables in a string... with the latter presenting the most significant hurdle.

First, to determine the number of sentences in a string of text, the following expression may be used:

1
$sentences = preg_split('/(?<=[.?!])\s+(?=[a-z])/i',$string);
2
$number_sentences = count($sentences);

We'll clean the text to retain only words and numbers (we're yet to receive a definitive answer on how numbers should be used).

1
$string = preg_replace('/[^a-zA-Z0-9\s]/', '',$string);

PHP's str_word_count() function can be used to return an array of words. We use this array to count the number of words in a string, and then we iterate over all the values to determine the number of syllables in each.

To determine the number of syllables in a word is tricky. After trying a few PHP functions (none of which we could rely upon), we landed upon Text-Statistics - a library hosted on Github. The library is good but, not unlike some of the functions we wrote ourselves, wouldn't come close to returning the required accuracy. The syllable count is extremely important because of the significant impact it might have upon the Flesch score when erroneous data is returned. We determined that the only way of efficiently ensuring accurate results was to maintain a database of words and their syllable count.

An API was the logical means of returning data to our clients that required it (this also makes maintaining an accurate dictionary a crowd-sourced effort).

We accept three requests; one that requires a basic word => count be returned, another with the syllable count, and a last one with other data (such as vowel and consonant count for each word). Default usage returns only the count. The array that returns the word and syllables looks a little like this:

1
'zero' => array('number' => '2', 'syllables' => array('0' => 'ze','1' => 'ro ') ),
2
'zeroed' => array('number' => '2', 'syllables' => array('0' => 'ze','1' => 'roed ') ),
3
'zeroing' => array('number' => '3', 'syllables' => array('0' => 'ze','1' => 'ro','2' => 'ing ') ),
4
'zigzag' => array('number' => '2', 'syllables' => array('0' => 'zig','1' => 'zag ') ),
5
'zigzagged' => array('number' => '2', 'syllables' => array('0' => 'zig','1' => 'zagged ') ),
6
'zigzagging' => array('number' => '3', 'syllables' => array('0' => 'zig','1' => 'zag','2' => 'ging ') ),
7
'zilch' => array('number' => '1', 'syllables' => array('0' => 'zilch ') ),
8
'zillion' => array('number' => '2', 'syllables' => array('0' => 'zil','1' => 'lion ') ),

If a word isn't found in our database, it is recorded for manual inclusion. It's only if a word isn't included in our dictionary that we'll apply a less-efficient means of determining the syllable count via a PHP algorithm.

API Endpoint: http://api.beliefmedia.com/readability/api.php. A POST request expects at least 2 parameters: apikey and message.

A sample function to submit post is as follows:

1
<?php
2
/*
3
Count Sentences, Words, and Syllables to Return a Flesch Reading Ease Score
4
5
*/
6

7
function beliefmedia_post_readability($content) { 8 9 /* Data array */ 10$data = array(
11
"apikey" => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
12
"summary" => '0',
13
"message" => $content 14 ); 15 16 /* JSON Data */ 17$data = json_encode($data, JSON_HEX_QUOT | JSON_HEX_TAG); 18 19 /* API URL */ 20$url = 'http://api.beliefmedia.com/readability/api.php';
21

22
/* Send POST Request */
23
$ch = curl_init($url);
24
curl_setopt($ch, CURLOPT_POST, true); 25 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
26
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 27 curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 28 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
29
$result = curl_exec($ch);
30
curl_close($ch); 31 32 /* Return array */ 33$result = json_decode($result, true); 34 return (array)$result;
35
}

A function to return the array should be used to check for errors and valid JSON (omitted for the sake of the example).

1
<?php
2
/*
3
Count Sentences, Words, and Syllables to Return a Flesch Reading Ease Score
4
5
*/
6

7
function beliefmedia_readability_array($text) { 8$result = beliefmedia_text_readability($text); 9 return ($result['error'] == '200') ? (array) $result : false; 10 } 11 12 The returned JSON data unfolds into an array that looks something like this: 13 <pre>Array 14 ( 15 [code] => 200 16 [error] => 200 17 [data] => Array 18 ( 19 [sentences] => 4 20 [number_words] => 96 21 [syllables] => 145 22 [flesch] => 54.69 23 [flesch_kincaid] => 11.59 24 ) 25 26 ) The code of 200 simply means we process your request. A returned error of anything other than 200 means that no result is returned. The final result should be cached so values might be retrieved (and displayed) if required. ### WordPress Function Note: Because of the nuisance processing overhead associated with each request, we only make the API available to our clients. The WordPress function will cache the result for just 5 minutes if saving a draft. Since the syllable dictionary will evolve over time, a post when published will cache the result for only 60 days (a fresh request is made periodically to return a more reliable score over time). Copy and paste the WordPress function into your theme's functions.php file or, if you sensibly have one installed, your custom functions plugin. 1 <?php 2 /* 3 Count Sentences, Words, and Syllables to Return a Flesch Reading Ease Score 4 http://www.beliefmedia.com/readability 5 */ 6 7 function beliefmedia_readability_scores() { 8 9 global$post;
10
$post_id =$post->ID;
11
$cache = (get_post_status($post_id) != 'publish') ? 300 : 3600 * 24 * 60;
12

13
$transient = 'flesch_' . md5($post_id);
14
$cachedresult = get_transient($transient);
15

16
if ($cachedresult !== false) { 17 return$cachedresult['data']['flesch'];
18

19
} else {
20

21
/* Clean WP text */
22
$text = get_post($post_id);
23
$text =$text->post_content;
24
$text = preg_replace ('/$flesch(.*?)$/s' , '',$text);
25
$text = preg_replace ('/$fleschscore(.*?)$/s' , '',$text);
26
$text = do_shortcode($text);
27

28
$result = beliefmedia_post_readability($text);
29
$flesch = ($result['error'] != '200') ? 'Error' : $result['data']['flesch']; 30 set_transient($transient, $result,$cache);
31

32
return $flesch; 33 } 34 } 35 add_shortcode('fleschscore', 'beliefmedia_readability_scores'); Note: The beliefmedia_post_readability function is also required. ### Usage To return a flesch score for an entire post, use the shortcode of [fleschscore]. [flesch]This page is a really bad example because of the technical nature of the subject and, as such, returns a Flesch score of around 45. The problem with making attempts to score articles like this one (and lots of other tutorial-type posts) is that they're far from the typical texts intended to be scrutinized and scored - they're just far too removed from the typical text required to assess literacy (as determined by the simple formula). For this reason, you might consider scoring individual paragraphs by wrapping your text in opening and closing [flesch] tags. For the sake of the example we simply tack the result on the end of a paragraph as follows (in real world use you'll record the result and use it elsewhere): [/flesch] The sample function to return what we've described above is as follows: 1 <?php 2 /* 3 Count Sentences, Words, and Syllables to Return a Flesch Reading Ease Score 4 http://www.beliefmedia.com/readability 5 This is a sample shortcode only. Resulting array stored in transient. 6 */ 7 8 function beliefmedia_readability_score($atts, $content = null) { 9 10$atts = shortcode_atts(array(
11
'shortcodes' => 1
12
), $atts); 13 14 /* Cache period determined if published or not */ 15$cache = (get_post_status(get_the_ID()) != 'publish') ? 300 : 3600 * 24 * 60;
16

17
$transient = 'flesch_c_' . md5($content . serialize($atts)); 18$cachedresult =  get_transient($transient); 19 20 if ($cachedresult !== false) {
21
return '' . do_shortcode($content) . ' Flesch Readability Score: ' .$cachedresult['data']['flesch'] . '.';
22

23
} else {
24

25
/* Get WP text */
26
$content = ($atts['shortcodes']) ? do_shortcode($content) : preg_replace("/$([^\[$]++|(?R))*+\]/", '',$content);
27

28
/* Make request and return result */
29
$result = beliefmedia_post_readability($content);
30
$flesch = ($result['error'] != '200') ? 'Error' : $result['data']['flesch']; 31 set_transient($transient, $result,$cache);
32

33
return '' . $content . ' Flesch Readability Score: ' .$flesch . '.';
34
}
35
}
36

Our plugin provides an option to include a score for every post in your WP publish META box.

### Considerations

• If you're after a vowel and/or consonant count, the following expression will do the job (there's probably more efficient ways of doing so).
1
<?php
2
preg_match_all('/[aeiou]/i', $string,$vowels);
3
preg_match_all('/[bcdfghjklmnpqrstvwxyz]/i', $string,$consonants);
4

5
$vowel_count = count($vowels['0']);
6
$consonant_count = count($consonants['0']);
• Processing posts with code is problematic because the readability algorithm assesses the complexity of a sentence without discriminating against any of the text. For that reason we remove anything between pre and code tags, and HTML. How the inclusion of numbers is used for the purpose of the assessment seems to vary from one organisation to another. Consider the three-syllable word "29th" - do we include this in our count? Should titles and headings be considered a sentence? The existing web tools seemingly make their own interpretations meaning that scoring on one tool rarely matches that of another.
• We include numbers in the word count and generally exclude them from the syllable count. To find the balance we were happy with we turned to Microsoft Office and compared our count to theirs when measured against a full copy of Harry Potter (we matched the novel assessment with 98.4% accuracy). This comparison required that we included a large number of very bizarre words to our dictionary! For comparison, the premium service Readable returns 84 percent accuracy.
• As noted above, Microsoft Office will return a Flesch and other scores. Navigate to File -> Options -> Proofing and tick the box that says "Show Readability Statistics". Select "Spelling & Grammar" when writing to see the results.

• We make attempts to remove anything other than the necessary text required to return a score. It might be prudent to exclude text, code, or anything else you don't want assessed.
• For those interested, the math formulas on this page were generated with Mathjax.
• Our tool scores word documents, PDF documents, and bulk uploads (in addition to numerous other features). It's likely we'll turn it into a report-to-email service after our dictionary is more comprehensive (at the time of writing it's at 75,000 words).
• We won't stop working on improving our algorithms!