Software Developer

How To Use WordPress.org API To Get Theme Stats From The Themes Directory

This is how you can use the WordPress.org API to get information and stats about themes in the WordPress.org theme directory.

I used this code to get the top ten themes with the most active installs.

First, I’ll show you the generic PHP code to make a request to the WordPress.org API to get theme information. I’ll give a few examples of requests. Then, I’ll give two example use cases for the API. The first use case will get a list of the top ten themes with the most active installs in the WordPress.org theme directory. The second use case will get a list of the top ten themes with the most 5-star ratings in the theme directory.

You can skip down to the example use cases:

How To Make a Request To The WordPress.org Themes API

This is the function that will be used to make requests to the WordPress.org Themes API.

Code block 1A

/**
 * Makes a call to the WordPress.org Themes API, v1.0
 * @param string $action Either query_themes (a list of themes), theme_information (Information about a specific theme), hot_tags (List of the most popular theme tags), feature_list (List of valid theme tags)
 * @param array $api_params
 * @return object Only the body of the raw response as a PHP object.
 */
function isa_call_wp_api_themes( $action, $api_params = array() ) {
	$url = 'https://api.wordpress.org/themes/info/1.0/';
	if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) {
		 $url = set_url_scheme( $url, 'https' );
	}
	$args = (object) $api_params;
	$http_args = array(
		'body' => array(
		'action' => $action,
		'timeout' => 15,
		'request' => serialize( $args )
		)
	); 
	
	$request = wp_remote_post( $url, $http_args ); 

	if ( is_wp_error( $request ) ) {
		// error_log('WP_ERROR = ');error_log( print_r( $request, true ) );
		return false;
	}

	return maybe_unserialize( wp_remote_retrieve_body( $request ) );
}

The function takes two parameters:

isa_call_wp_api_themes( $action, $api_params )

The first parameter, $action, can be either query_themes (a list of themes), theme_information (Information about a specific theme), hot_tags (List of the most popular theme tags), or feature_list (List of valid theme tags). For the examples on this page, we are only going to use query_themes and theme_information.

The second parameter, $api_params, is the array of arguments for the API request. You can see the list of allowed arguments and their descriptions on the WordPress.org API page. I’ll list them here without repeating their descriptions.

  • search
  • tag
  • theme
  • author
  • page
  • per_page
  • browse
  • fields

The only thing that I would add here is a note about the fields argument for the query_themes action. The fields argument tells what information about the themes to return. It’s an associative array of fields which are either set to true or false. Only fields that are set to true will be returned. This is the default:

  • description – true (gives the theme description)
  • sections – false
  • rating – true (Gives the rating percent. Also has a companion field, num_ratings, which gives the total number of ratings.)
  • ratings – false

    The ratings field gives an array of how many of each type of rating, e.g. how many 1-star ratings, 2-star ratings, 3-star ratings, 4-star ratings, and 5-star ratings. For example:

    [ratings] => Array
    	(
    		[1] => 2
    		[2] => 2
    		[3] => 6
    		[4] => 2
    		[5] => 27
    	)
    

     

  • downloaded – false (gives total number of downloads)
  • download_link – false (doesn’t return anything)
  • last_updated – false (date format is 2016-08-30)
  • homepage – true (a link to the theme’s WordPress.org page)
  • tags – false
  • screenshot_url – true
  • active_installs – false
  • template – true (for child themes, will give the slug of the parent theme)
  • version – true (the current version)
  • versions – false lists all the versions and gives a link to the download .zip for each version, for example:
    [versions] => Array
    	(
    		[1.0] => https://downloads.wordpress.org/theme/twentyseventeen.1.0.zip
    		[1.1] => https://downloads.wordpress.org/theme/twentyseventeen.1.1.zip
    	)
    

     

  • parent – false

    For child themes, the parent field gives an array of theme info for the parent theme, for example:

    [parent] => Array
    	(
    		[slug] => twentyfifteen
    		[name] => Twenty Fifteen
    		[homepage] => https://wordpress.org/themes/twentyfifteen/
    	)         
    

 

Some Usage Examples

Here are a few examples of basic requests for a list of themes. To get a list of themes, we use the query_themes action. For all of these examples, I set the ‘per_page’ argument to ‘-1’ to give us all of the results, otherwise we would only get the first 24 results.

Get a list of all themes with the tag “buddypress.”

$api_params = array(
	'tag'		=> 'buddypress',
	'per_page'	=> -1
);
$themes_object = isa_call_wp_api_themes( 'query_themes', $api_params );

$themes_list = $themes_object->themes;

Get a list of all themes with the tag “accessibility-ready” and with the word “WooCommerce” in the description.

$api_params = array(
	'tag'		=> 'accessibility-ready',
	'search'	=> 'WooCommerce',
	'per_page'	=> -1
);

$themes_object = isa_call_wp_api_themes( 'query_themes', $api_params );

$themes_list = $themes_object->themes;

Get a list of all themes by WooThemes.

$api_params = array(
	'author'	=> 'woothemes',
	'per_page'	=> -1
);

$themes_object = isa_call_wp_api_themes( 'query_themes', $api_params );

$themes_list = $themes_object->themes;

For each of the examples above, you can get the total number of themes returned, like this:

$count = $themes_object->info->results;

 

↑ Top

Use Case 1: List The Top 10 Themes With The Most Active Installs in The Directory

This example will walk you through how to get a list of the top ten themes with the most active installs on the .org theme directory.

First, be sure to include the function isa_call_wp_api_themes (code block 1A) because that’s what we’re going to use to make the request to the WordPress.org Themes API.

Next, I’ll set up the arguments for the API request.

By default, the query_themes action will give us a list of only 24 themes. I want a list of all the themes, so I’ll set the “per_page” argument to “-1”. Since this list will have over 2400 theme objects, (at my last count, there were 2429 themes in the WordPress.org themes repository), I want to eliminate some of the extra information in order to lighten the load. Here, I set some of the fields to false, including the homepage, description, and screenshot_url. We need to get the number of active installs for each theme, so I set the active_installs to true. These are my API parameters:

Code block 2A

$api_params = array(
	'per_page' => -1,
	'fields' => array(
					'homepage'			=> false,
					'description'		=> false,
					'screenshot_url'	=> false,
					'active_installs'	=> true
		)
);

Next, we make the actual request.

$response = isa_call_wp_api_themes( 'query_themes', $api_params );

We are going to be sorting the results. I don’t want to sort a list of 2400+ themes because it takes up a lot of resources and time. So, at this point, I am going to shrink our list. I grab only the themes that have more than 10,000 active installs. That will shrink our list to around 50 themes, give or take a few.

I’m also going to eliminate the official WordPress themes by WordPress.org because those themes are bundled with WordPress, so they are actively installed on most WordPress sites. These are Twenty Seventeen, Twenty Sixteen, etc. If you don’t want to eliminate these, then remove lines 7–9 in the following code snippet.

To shrink the list, first add this callback function:

Code block 2B

/**
 * Callback to filter themes by most active installs.
 * Eliminates themes with less than 10K installs.
 * Also eliminates official WP Themes by WordPress.org.
 */
function isa_filter_themes_by_installs( $v ) {
	if ( 'wordpressdotorg' == $v->author ) {
		return false;
	}
	return ( (int) $v->active_installs > 10000 );
}

Now, to actually shrink the list of themes, use this:

Code block 2C

// get only those with active installs over 10K

$top_themes = array_filter( $response->themes, 'isa_filter_themes_by_installs' );

Next, we are going to sort the list of themes by the number of active installs. We want them sorted in descending order, with the highest number of active installs first. To do the sort, we are going to use a callback function with the PHP usort() function. So, first add this callback function:

Code block 2D

// Callback to sort by number of active installs, descending
function isa_sort_themes_by_installs( $a, $b ) {
    return $b->active_installs - $a->active_installs;
}

Then, do the actual sorting with this:

Code block 2E

// sort by number of active installs, descending

usort( $top_themes, 'isa_sort_themes_by_installs' );

Now, $top_themes holds the top 50, or so, themes. We only want the top 10. You may be tempted, at this point, to just grab the top 10 results from this array. But that is a bad idea.

Here is why. It’s common for the theme repository to have several themes at a tie with the same number of installs because active installs is a rounded number. So, there may be five themes with a tie for 10th place. We wouldn’t want to grab just one of those five, and leave out the rest.

Before we eliminate the rest of the themes after number 10, let’s check if there is a tie for 10th place. If there are any themes in a tie for 10th place, they will be added to our new $top_ten array.

Code block 2F

$count = count( $top_themes );

$top_ten = array_slice( $top_themes, 0, 10 );

if ( $count > 10 ) {

	// Check all themes over 10th place for a tie with 10th place

	for ( $i = 10; $i < ( $count - 1 ); $i++ ) {

		if ( $top_themes[9]->active_installs === $top_themes[ $i ]->active_installs ) {

			// This is a tie. Add it to the array of top 10.
			$top_ten[] = $top_themes[ $i ];

		}

	}
	
}

Next, I want to do one more sort. By default, if there is a tie for any place, those tied themes are listed in an order that I don’t like. For example, if four themes are tied for first place, the one with the lowest rating will usually be listed first. I don’t like this. If there are tied themes, I want the one with the highest rating to be listed first.

So, at this point, I sort the list so that if there are any ties for the same number of active installs, those will be sorted by the highest rating, in descending order. To do this sort, we need another callback function:

Code block 2G

/* Callback to sort ties (if themes have a tie in the number of active installs)
 * by highest rating, descending
 */
function isa_sort_theme_ties_by_rating( $a, $b ) {
	return ( $a->active_installs === $b->active_installs ) ? ( $b->rating - $a->rating ) : $b->active_installs - $a->active_installs;
}

Do the actual sort:

Code block 2H

// If there are any ties for the same number of active installs, sort by highest rating, descending

usort( $top_ten, 'isa_sort_theme_ties_by_rating' );

Finally, $top_ten holds an array of the top ten themes with the highest number of active installs, unless there is a tie for 10th place, in which case it will hold more than ten.

You can do what you want with that.

I’ll give two examples of HTML output in case you want to display this information.

  1. If you just want to display basic information, including the theme name, author, number of active installs, rating out of 5 stars, and a link to the preview, then you can do it with the information we already got from the API. (Note that the preview link is a link to a live demo of the theme, but not to its homepage.)

    First, add this function to hold the HTML for a single theme listing.

    Code block 2J

    /**
     * Get the HTML for a basic theme listing
     * @param object $theme A theme object containing the theme information
     */
    function isa_get_theme_listing( $theme ) {
    	$out = '<li><strong>' . esc_html( $theme->name ) . '</strong> by ' . esc_html( $theme->author ) . '. &nbsp; ';
    	$out .= ( $theme->active_installs / 1000 ) . 'K active installs. &nbsp; ';
    	$out .= 'Rating: ' . ( $theme->rating / 100 * 5 ) . ' &nbsp; ';
    	$out .= ' (<a href="' . esc_url( $theme->preview_url ) . '" target="_blank">preview</a>)';
    	$out .= '</li>';
    	return $out;
    }
    
    

    Then, this will display all 10 themes in an HTML ordered list:

    
    $html = '<ol>';
    
    // list the first 9
    
    for ( $i = 0; $i < 9; $i++ ) {
    	$html .= isa_get_theme_listing( $top_ten[ $i ] );
    }
    
    // List 10th place tie, if there is a tie.
    
    $top_ten_count = count( $top_ten );
    
    if ( $top_ten_count > 10 ) {
    	$html .= '<li><p>10th Place is a tie between the following themes: </p><ul>';
    
    	for ( $i = 9; $i < ( $top_ten_count - 1 ); $i++ ) {
    		$html .= isa_get_theme_listing( $top_ten[ $i ] );
    	}
    
    	$html .= '</ul></li>';
    
    } else {
    	// No tie, just show #10
    	$html .= isa_get_theme_listing( $top_ten[9] );
    
    }
    
    $html .= '</ol>';
    
    echo $html;
    
    
  2. If you want to display more information about each theme, such as a screenshot, description, and a link to its homepage, use this.

    First, we are going to loop through the $top_ten array to get more individual theme information for each theme in the top 10.

    Code block 2K

    // Get theme info for each theme in the top 10
    
    foreach ( $top_ten as $theme ) {
    
    	$api_params = array(
    		'slug' => $theme->slug,
    		'fields' => array(
    					'tags' => false,
    					'active_installs' => true,
    		)			
    	);
    
    	$list[] = isa_call_wp_api_themes( 'theme_information', $api_params );
    
    }
    

    Now, the $list variable holds our new list of the top 10 themes.

    Next, add this function to hold the HTML for a single theme listing.

    Code block 2L

    /**
     * Get the HTML for a full theme listing which includes a screenshot, description, and more.
     * @param object $theme A theme object containing the theme information
     * @param int $index The index # of this theme in the top 10 list. Blank for a tie.
     */
    function isa_get_enhanced_theme_listing( $theme, $index = '' ) {
    	$out = '<h3>';
    	 
    	if ( $index ) {
    		$out .= (int) $index . '. &nbsp; ';
    	}
    	
    	$out .= esc_html( $theme->name ) . ' by ' . esc_html( $theme->author ) . '</h3>';
    
    	$out .= '<img alt="" src="' . esc_url( $theme->screenshot_url ) . '" />';
    	$out .= '<p>Rating: ' . ( $theme->rating / 100 * 5 ) . '<br />';
    	$out .= ( $theme->active_installs / 1000 ) . 'K active installs </p>';
    	$out .= '<p>' . esc_html( $theme->sections['description'] ) . '</p>';
    	$out .= '<p><a href="' . esc_url( $theme->homepage ) . '">Visit the theme's homepage.</a></p>';
    	return $out;
    }
    

    Finally, this will display the HTML output for the 10 themes. Each theme listing will show its name, author, screenshot image, rating, number of active installs, theme description, and a link to the theme’s homepage.

    $html = '';
    
    // list the first 9
    
    for ( $i = 0; $i < 9; $i++ ) {
    	$html .= isa_get_enhanced_theme_listing( $list[ $i ], ( $i + 1 ) );
    }
    
    // List 10th place tie, if there is a tie.
    
    $top_ten_count = count( $list );
    
    if ( $top_ten_count > 10 ) {
    	$html .= '<h3>10th Place is a tie between the following themes:</h3>';
    
    	for ( $i = 9; $i < ( $top_ten_count - 1 ); $i++ ) {
    		$html .= isa_get_enhanced_theme_listing( $list[ $i ] );
    	}
    
    } else {
    	// No tie, just show #10
    	$html .= isa_get_enhanced_theme_listing( $list[9], 10 );
    
    }
    
    echo $html;
    

 

↑ Top

Use Case 2: List The Top 10 Themes With The Most 5-star Ratings in The Directory

To get a list of the top 10 themes with the most 5 star ratings, follow the same steps for the previous use case from above, but modify some of the code blocks. Here, I’ll explain which code blocks to modify.

First, we are going to modify code block 2A. We want to get the number of star ratings. So, we are going to set the ‘ratings’ field to true. Code block 2A becomes this:

$api_params = array(
	'per_page' => -1,
	'fields' => array(
					'homepage'			=> false,
					'description'		=> false,
					'screenshot_url'	=> false,
					'active_installs'	=> true,
					'ratings'			=> true
		)
);

Since our list focuses on 5-star ratings rather than active installs, we are going to completely change code block 2B. We want to eliminate from the list those themes that have less than 100 5-star ratings. That will shrink the list to about 19 themes. Change code block 2B to this:

/**
 * Callback to filter themes by most 5-star ratings.
 * Eliminates themes with less than 100 5-star ratings.
 */
function isa_filter_themes_by_five_star_ratings( $v ) {
	return ( (int) $v->ratings[5] > 100 );
}

Change code block 2C to this:

// get only those with more than 100 5-star ratings

$top_themes = array_filter( $response->themes, 'isa_filter_themes_by_five_star_ratings' );

We want to sort the list by number of 5-star ratings rather than by number of active installs. So, change code block 2D to this:

// Callback to sort by number of active installs, descending
function isa_sort_themes_by_five_star_ratings( $a, $b ) {
    return $b->ratings[5] - $a->ratings[5];
}

Change code block 2E to this:

// sort by number of 5-star ratings, descending order

usort( $top_themes, 'isa_sort_themes_by_five_star_ratings' );

Change line 11 from code block 2F to this:

if ( $top_themes[9]->ratings[5] === $top_themes[ $i ]->ratings[5] ) {

For this use case, omit code blocks 2G and 2H. We don’t need those because the number of 5-star ratings for a theme is not rounded like the number of active installs. It is rare for 2 themes to have the same exact number of 5-star ratings.

To display the number of 5-star ratings, let’s look at code block 2J. Replace lines 7–9 in code block 2J with just this line:

$out .= (int) $theme->ratings[5] . ' 5-star ratings! &nbsp; ';

If you’re using the 2nd HTML example, which shows more theme information, such as the screenshot, then you’ll have to modify code block 2K. We’re just going to add the ‘ratings’ field to it. Change code block 2K to this:

// Get theme info for each theme in the top 10

foreach ( $top_ten as $theme ) {

	$api_params = array(
		'slug' => $theme->slug,
		'fields' => array(
					'tags' => false,
					'active_installs' => true,
					'ratings' => true					
		)			
	);

	$list[] = isa_call_wp_api_themes( 'theme_information', $api_params );

}

Finally, to display the number of 5-star ratings in the HTML output for the full listing, look at code block 2L. In code block 2L, insert this into line 16 (push the existing code on line 16 down).

$out .= '5-star Ratings: ' . (int) $theme->ratings[5] . '<br />';

 

↑ Top

I hope you get some use out of these examples. See a live example where I use this code.

By

Questions and Comments are Welcome

Your email address will not be published. All comments will be moderated.

Please wrap code in "code" bracket tags like this:

[code]

YOUR CODE HERE 

[/code]