How to build an auto-ranking Twitter list with WordPress

My team and I recently built an awesome list template on WordPress that ranks a set of Twitter users based on follower count. It allows a content writer to easily add a list of Twitter handles, and generate a well designed post.

The first piece of content we created with it generated a 1,212% increase in traffic to our site. Check out the tutorial below if you’re interested in building it as well.

Requirements

Input

  • Twitter Handle (required)
  • Name (optional)
  • Tagline (optional)
  • Image (optional)
  • Bio (optional)
  • Personal Website (optional)
  • Tags(optional)

Features

  • Content writer needs to be able to easily set all data points.
  • Every optional field set in WordPress needs to override any data retrieved from Twitter.
  • The output needs to be sorted by the number of Twitter followers.
  • The output needs to be filterable on the front-end by a set of tags.
  • All data needs to be saved in local storage so Twitter is not called on every page load.

Output

A beautiful list of Twitter accounts — sorted by follower count — and filterable by tag. Check out the result!

How to build an infinite list in WordPress

First things first, you’ll need to create the data.

Step 1

Install the Advanced Custom Fields Pro WordPress plugin. ACF allows you to easily create a set of fields for your content writers to fill out. The pro version offers the Repeater and Flexible Content fields – both necessary for this project as they allow the content writer to duplicate fields.

Step 2

Create a field group called “listicle”. In reality, you can name this whatever you feel is most appropriate as it will show up in the Post Editor. You can also decide which posts or pages to show the field set on. We decided that we only wanted it to show on the single post we were creating.

Step 3

Add a flexible content field called “twitter list” to the “listicle” field group. Flexible Content fields allow you to create different, easily-duplicated, “layouts”. We wanted to allow content writers to add new handles endlessly; but also preserve the ability to create different Twitter layouts for other data in the future. For this reason, we chose Flexible Content instead of Repeater.

Step 4

Add a Flexible Content Layout called “User” to the “twitter list” field. Flexible Content fields are amazing. We use them for most of our website to allow writers to easily construct pages without bulky drag & drop editors.

Step 5

Add each of the seven fields — handle (text/required), name (text), tagline (text), bio (textarea), link (text), image (image/URL), and tags (repeater/text) — to the “User” layout. Make note of their field names and field types, you’ll be using them later.

Step 6

You’ve now added the ability for any author to add these extra data fields an infinite number of times. They won’t show up anywhere just yet, but they can be created, read, updated, and deleted.

How to display an infinite list in WordPress

Now that we have the data, let’s show it off!

Step 7

Open single.php, single-id.php, singular.php, or index.php in a text editor. Depending on your theme, you may have one or all of the above file names in your theme directory. Make sure to create a child theme, since you don’t want these edits overwritten by the next theme update.

You should also be aware that every theme is different, so you may need to adapt the following instructions. Do not edit your theme through the editor. If you break something, you will not be able to undo it through the editor.

Step 8

Add ACF conditional statements to your file. First, you need to check if ACF has any data. You’ll need to do this within the loop.

<?php
// check if the flexible content field has rows of data
if( have_rows('twitter_list') ) {} 
?>

Step 9

Initialize the user_data_array array. You need a variable that stores every single user so you can pass it through the sorting function.

Step 10

In the code below, you’ll loop through all rows added by the content writer, set each data point to a local variable, add the local variables to a user array, and then push the single user array into the user_data_array.

<?php 
// build containing array for sorting
$user_data_array = array();

// loop through all rows in the field group
while ( have_rows('twitter_list') ) : the_row();

    // get current flexible content field layout name
    $row_type = get_row_layout();

    // check if the flexible content field is 'user'
    if ( $row_type == 'user' ) {

        // get field data
        $handle     = get_sub_field('handle');
        $name       = get_sub_field('name');
        $tagline    = get_sub_field('tagline');
        $bio        = get_sub_field('bio');
        $tags       = get_sub_field('tags');
        $site       = get_sub_field('website');
        $image      = get_sub_field('image_url');

        // get tags
        if( have_rows('tags') ):
        
            // initialize a variable to store tag html
            $tags_html ='';
            
            // loop through the rows of data
            while ( have_rows('tags') ) : the_row();

                $tag = get_sub_field('tag');

                // not exactly; shortened for easy reading
                $tags_html = $tags_html . $tag;

            endwhile;
        endif;

        // single user array contruction
        $user = array(
            'handle'    => $handle,
            // we didn't add followers as an ACF field because we always wanted live data. we'll come back to this when we call Twitter.
            //'followers' => $followers,
            'img'       => $user_img,
            'tags_html' => $tags_html,
            'name'      => $user_name,
            'website'   => $user_site,
            'tagline'   => $tagline,
            'bio'       => $user_bio,
        );

        // add user to users array
        array_push($user_data_array, $user);
    }

endwhile;
?>

I know what you’re thinking. “Why is he running two loops? You can just output the data as you run through the first loop!” You could very well do that, but you would need to find another way to sort the list by followers.

Step 11

Loop through the user_data_array and display each Twitter user’s manually entered data. Since we haven’t retrieved Twitter data yet, we can’t sort by followers, so we’ll need to simply display our results as they’ve been ordered in the Post Editor.

<?php 
// Display users
$i = 1;
foreach ( $user_data_array as $user ) {
    echo $user['handle'];
    echo $user['img'];
    echo $user['name'];
    echo $user['website'];
    echo $user['tags_html'];
    echo $user['tagline'];
    echo $user['bio'];
    // we didn't add followers as an ACF field because we always wanted live data. we'll come back to this when we call Twitter.
    //echo $user['followers'];
}
?>

This will run through every single user, and display the information you’ve stored. Use $i to display the rank number if you prefer.

Step 12

Style the output as you see fit. You’ll need to add your own HTML and CSS since you likely use a different framework than we do. Check out our finished product for an idea on how to style it.

How to add Twitter data to your infinite list

So now that you can show all the manually entered data, let’s go grab data from Twitter. For simplicity’s sake, we used the TwitterAPIExchange PHP library to add a set of functions that could easily grab Twitter data.

Step 13

Create a custom function to retrieve Twitter data. You’ll need to pass your own Twitter API details, but the function below will return a Twitter object. Add the function into functions.php (or wherever you load custom functions), and make sure it includes the library from the right location.

<?php 
function nnr_get_twitter_user( $username ) {

    require_once( get_template_directory() .'/inc/twitter/TwitterAPIExchange.php' );

    // Set up your settings with the keys you get from the dev site
    $settings = array(
        'oauth_access_token' => "XXXX",
        'oauth_access_token_secret' => "XXXX",
        'consumer_key' => "XXXX",
        'consumer_secret' => "XXXX"
    );

    // Chooose the url you want from the docs, this is the users/show
    $url = 'https://api.twitter.com/1.1/users/show.json';

    // The request method, according to the docs, is GET, not POST
    $requestMethod = 'GET';

    // Set up your get string, we're using my screen name here
    $getfield = '?screen_name=' . $username;

    // Create the object
    $twitter = new TwitterAPIExchange($settings);

    // Make the request and get the response into the $json variable
    $json =  $twitter->setGetfield($getfield)
                     ->buildOauth($url, $requestMethod)
                     ->performRequest();

    // It's json, so decode it into an array
    $result = json_decode($json);

    // Echo the array
    return $result;
} 
?>

Step 14

Use the required handle from each ACF row to call Twitter; and retrieve the Twitter User Object inside a transient function, so we don’t call Twitter on every page load. Map the necessary data points to the existing data model, and make sure to add in some simple if/else statements to allow ACF to override Twitter data.

<?php 
// build containing array for sorting
$user_data_array = array();

// loop through all rows in the field group
while ( have_rows('twitter_list') ) : the_row();

    // get current flexible content field layout name
    $row_type = get_row_layout();

    // check if the flexible content field is 'user'
    if ( $row_type == 'user' ) {

        // get field data
        $handle     = get_sub_field('handle');
        $name       = get_sub_field('name');
        $tagline    = get_sub_field('tagline');
        $bio        = get_sub_field('bio');
        $tags       = get_sub_field('tags');
        $site       = get_sub_field('website');
        $image      = get_sub_field('image_url');

        // get tags
        if( have_rows('tags') ):

            // initialize a variable to store tag html
            $tags_html ='';

            // loop through the rows of data
            while ( have_rows('tags') ) : the_row();

                $tag = get_sub_field('tag');

                // not exactly; shortened for easy reading
                $tags_html = $tags_html . $tag;

            endwhile;
        endif;

        // set transient for each handle
        if ( false === ( $user_data = get_transient( 'nnr_tw_infl_' . $handle ) ) ) {
            // this code runs when there is no valid transient set
            $user_data  = nnr_get_twitter_user($handle);
            set_transient( 'nnr_tw_infl_' . $handle, $user_data, 60*60*24);
        }

        // map user data from Twitter User Object
        $followers  = $user_data->followers_count;
        $lists      = $user_data->listed_count;
        $user_name  = $user_data->name;
        $user_bio   = $user_data->description;
        $user_site  = $user_data->entities->url->urls[0]->expanded_url;
        $user_img   = $user_data->profile_image_url;

        // override user data if field is defined in ACF
        if      ( isset($name)      && $name        != '' ) { $user_name = $name;           }
        if      ( isset($bio)       && $bio         != '' ) { $user_bio  = $bio;            }
        if      ( isset($image)     && $image       != '' ) { $user_img  = $image;          }
        if      ( isset($site)      && $site        != '' ) { $user_site = $site;           }
        else if ( isset($user_site) && $user_site   != '' ) { $user_site = $user_site;      }
        else                                                { $user_site = $user_data->url; }

        // single user array contruction
        $user = array(
            'handle'    => $handle,
            'followers' => $followers,
            'img'       => $user_img,
            'tags_html' => $tags_html,
            'name'      => $user_name,
            'website'   => $user_site,
            'tagline'   => $tagline,
            'bio'       => $user_bio,
        );

        // add user to users array
        array_push($user_data_array, $user);
    }

endwhile;
?>

How to sort and filter your infinite list

Step 15

Now that you have the Twitter follower count, you can sort the list by number of followers. Use a simple usort() function in functions.php for this.

Step 16

After you loop through all the Twitter handles and user_data_array is complete, run it through your custom usort() function:

<?php 
// Sort user by followers
usort($user_data_array, 'nnr_sort_followers');
?>

Step 17

Use jQuery to target elements with the ACF tag_html your content writers added. We defined a tag universe, and hard coded it to match with some simple HTML link elements; but there are a ton of different methods and effects you can use for this.

Step 18

Save and publish all your changes (after backing up of course), and you’ve built yourself an auto-ranking Twitter list! Check out what we created with it!

Finishing up

Awesome! Now you have live Twitter data that merges with ACF data and displays on the front end. You now have a repeatable template for ranking and filtering Twitter users.

Fill it up with content and share that baby all over the Twittersphere!

James is a physicist turned WordPress developer and entrepreneur. He has since developed themes and plugins for Gabfire Themes and 99 Robots. James has architected and overseen the development of large scale web application projects while travelling across five continents. Follow him on Twitter @wpmonty More articles by James Montgomery
  • kjbenk .

    Great Article! It really shows how transients can increase the speed of your site when loading a lot of data.

    • James Montgomery

      Thanks! Yeah, the load speed was insanely improved by that transient setup. Can’t be calling Twitter 99 times on every page load 🙂

  • Sree

    Can’t wait to try this, very detailed description!

Home CSS Deals HTML HTML5 Java JavaScript jQuery Miscellaneous Mobile MySQL News PHP Resources Security Snippet Tools Tutorial Web Development Web Services WordPress