Custom Instagram Feed and Stats Integration for High Traffic

One of the modules on the semi-recently redesigned/ updated Love Taza site (designed by Bre from Rowan Made) was an Instagram sidebar area that shows images and stats from both Naomi and Josh’s accounts:

love-taza-instagram-module

The left side is all Naomi, with two of her most recent images and her stats for followers, posts and the number of other accounts she’s following, and the right side shows the same for Josh.

The Problem with Plugins

I tend to use existing plugins when I can for features like this, but none of the plugins I found handled the stats (the best I could get was a plugin that would let me show one user’s follower count). I implemented a modification of an existing plugin but we quickly realized that the plugin’s lack of caching system was going to be a big problem given their high levels of traffic – we kept hitting Instagram’s API rate limit and losing the data displays.

Finally, I sat down with the Instagram API docs and wrote them a custom module that uses WordPress transients to store the data and limit the number of API calls we’re making.

The Custom Setup

Let’s dig through the code needed to get a feed similar to the one on Love Taza (and/or stats) up and running on WordPress (or any PHP site).

Authentication & API Access

The first thing to deal with in an API integration is authentication. In this case, we only need to get data from Instagram (we aren’t modifying their accounts in any way) so the integration is easier and has a lower barrier of authentication than if we wanted two-way control.

In order to get the necessary access, we need an access token for each account.

If you don’t already have an access token, you can head to this page to get one. You’ll need to authenticate by logging into your account and giving permission, but none of your data is stored on this site. The page uses client side authentication so your data never even hits my server. Once you’ve authenticated, the token will be displayed on the page and you can copy it and paste it to your working file.

Setting Up the Data

I used a lot of what I learned about accessing API data from the Shopify integration I wrote for another site to build this integration. You can check out this GitHub Gist for the full code, but let’s break it all down in more detail.

NOTE: In this example, I’m only showing a single account but for Love Taza there are two accounts in play. I essentially just duplicated this code for the second account, replacing all instances of `user` with a different string for the second user, and changed out the access token.

So first up, I created a couple of variables for the base data:

// Set variables
$image_number = 2;
$image_size = 'low_resolution'; //options: low_resolution (306), thumbnail (150), standard_resolution (612)

// Create the API URL for the user data
$user_access_token = '123456.xxxxxxxx.zzzzzzzzzzzzzzzzzzzzzzz';
$user_data_url = 'https://api.instagram.com/v1/users/self/?access_token=' . $user_access_token;

I’ve set the image number and size to variables to make it super easy to change them if I want to in the future, and I’ve also set that access token to a variable and then used it to create the API access URL. I did all of this in variables because it made it a lot easier to manage multiple accounts, but also because it makes the code easier to use for other applications in the future without having to do a lot of find and replace action within the markup.

Accessing the Account Stats (with Transient)

Now we’re ready to actually use that $user_data_url to access the API and get the account data, but as I mentioned Instagram has rate limits and we kept hitting them on Love Taza, killing our feeds.

The solution is to wrap the feed access in a WordPress transient, which stores the data for the specified amount of time and reuses it instead of repeatedly calling the API. Here’s the code:

// Use a transient for the feed URL (performance boost)
if ( false === ( $user_data = get_transient( 'instagram_user_data' ) ) ) {
    $user_data = @file_get_contents( $user_data_url );

    // Put the results in a transient. Expire after 4 hours.
    set_transient( 'instagram_user_data', $user_data, 4 * HOUR_IN_SECONDS );
}

This code checks for the “instagram_user_data” transient (similar to a cookie) and if it doesn’t find it then it gets that file data and creates that transient, set to expire after 4 hours. Two notes about this method:

  1. The @ symbol in @file_get_contents suppresses errors, which I wanted in this case but which will suppress errors that may be useful as well. If you are running into problems with your feed you may find it helpful to temporarily remove that for troubleshooting.

  2. Since the feed only gets updated about every 4 hours, it isn’t quite real-time. Sometimes it’s a couple hours behind the actual Instagram account, which is usually fine but is something to know if you’re implementing this.

As a result of this snippet, we have all the feed data stored in $user_data and ready to use.

Next, I set the stats from Instagram to a series of variables. Again, this is something I did for organizational purposes to make it easier to use multiple accounts and to see exactly what is going on in my code.

$user_stats = json_decode( $user_data, true );
$user_image_count = $user_stats['data']['counts']['media'];
$user_followers_count = $user_stats['data']['counts']['followed_by'];
$user_follows_count = $user_stats['data']['counts']['follows'];

The first line decodes the JSON file that the API returns, and the next three set the data points we’re going to be displaying to a series of variables for use in our markup later on. The first is the media count, which is the number of posts (images or videos), the second is the number of followers, and the third is the number of users this account follows.

Accessing the Image Feed (with Transient)

So far we’ve tackled the stats, but we also need to feed in a few of the recent images. To do this, we’ll set up another API call with another transient:

// Create the API URL for the user feed
$user_feed_url = 'https://api.instagram.com/v1/users/self/media/recent/?access_token=' . $user_access_token . '&COUNT=' . $image_number;

// Use a transient for the feed URL (performance boost)
if ( false === ( $user_feed = get_transient( 'instagram_user_feed' ) ) ) {
    $user_feed = @file_get_contents( $user_feed_url );

    // Put the results in a transient. Expire after 4 hours.
    set_transient( 'instagram_user_feed', $user_feed, 4 * HOUR_IN_SECONDS );
}

// Decode the JSON in the file
$user_images = json_decode( $user_feed, true );

Here, we’ve again set up a feed URL (this one uses that $image_number variable we set back in the beginning to tell Instagram how many images to send back), and then we’ve created another transient for the feed data with the same expiration time frame. Finally, we’ve set the decoded data to $user_images.

Setting Up the Display

Now that we’ve got the data and images we need, we can set up the display in a combination of HTML markup and PHP to spit out all that account information.

The Image Feed

Here’s the rough markup for the image feed:

<div id="instagram-feed">
    <?php $image = 0;
    // Loop through images in the feed
    for ( $user_image = 0; $user_image < $image_number; $user_image++ ) {
            $user_image_data = $user_images['data'][$image];

            // Display the images:
            $user_link = $user_image_data['link'];
            $user_caption = $user_image_data['caption']['text'];
            $user_image_url = $user_image_data['images'][$image_size]['url'];
            ?>
            <div class="instagram-image">
                <a href="<?php echo $user_link; ?>" target="_blank"><img src="<?php echo $user_image_url; ?>" alt="<?php echo $user_caption; ?>" /></a>
            </div>
        <?php 
        $image++;
    } ?>
</div>

We’re using PHP to loop through each image and grab its link, caption, and the image file URL. Instagram helpfully uses the same format for image previews for videos, so the $user_image_url will work even for video posts.

Then we use the variables we’ve created to display the image inside a link, inside a div (for layout and styling purposes).

The Account Data

The markup for the account data is also fairly simple, pulling in those variables we set earlier in the code:

<div class="instagram-info">
    <a href="http://instagram.com/username" target="_blank">@username</a><br>
    <?php echo $user_followers_count; ?> followers<br>
    <?php echo $user_image_count; ?> posts<br>
    <?php echo $user_follows_count; ?> following
</div>

The first linked line is just a regular HTML link to the account (you’d want to replace “username” with the actual account username, though). The next three lines show how to echo out and display the account stats using our variables.

The actual Love Taza display has more markup than this example in order to allow for the formatting and font styles, but this gives you the actual data display to work with.

Customization

That’s all there is to this custom implementation! Don’t forget, you can check out the full code in the gist.

The nice thing about going custom like this is that you have total control over the output, and how the data is handled and stored. You could get much more about each image, for example (comment count, likes, filter used, location data), or you could pull in the user’s profile photo and bio. It’s just down to the design at this point!

Blogging Tip: iCal Post Feeds

If you’re a calendar person like I am (I use both a paper calendar and synced online calendars), you may find it helpful to have your blog posts show up across whatever digital calendar system you use.

Here’s how mine looks in Apple’s Calendar app, with only the blog calendar feed visible:

blog ical feed month view

Click to enlarge

It’s easy to set this up by generating an iCal feed from your WordPress site, then adding that to your calendar software.

Generating Your iCal Feed

There’s a great plugin that generates iCal feeds. I’ve used it for awhile now and found it to be stable, and the developer is responsive to feature requests (always nice).

Setup

It’s basically plug-and-play – install and activate the plugin, and then head to the settings page to grab your iCal feed URL.

As you can see in the (partially redacted) screenshot below, the plugin provides you with a bunch of different feeds to choose from:

ical feed plugin settings

The public URL contains all posts that are already published, but if you want to also include future (scheduled) posts you can do that by setting a secret parameter value. Your new secret feed URL is then provided for you lower on the page. That’s what I use, since I want to see my upcoming scheduled posts on my calendar.

There’s a setting for how long each calendar “event” should be, which is something I asked the developer to add. I like to have posts on my calendar but I don’t want them taking up a huge chunk of my calendar space so I’ve got mine set to 5 minutes. The time on the calendar matches the publication time for the post (and the calendar item includes the post URL):

ical post detail

You can also grab individual iCal feeds for each category, or for a custom selection of categories:

ical feed multiple categories

I am not really sure why you’d want to separate out your categories like that, unless you are really insane about your color coding, but it’s an option.

Using the Feeds

Most digital calendar apps make it pretty easy to add an iCal/ .ics feed.

Apple Calendar

In Calendar, you go File > New Calendar Subscription, then enter the URL:

add feed to Calendar app

Google Calendar

In a Google Calendar, you go to Other Calendars in the sidebar, then click the dropdown icon and select “Add by URL” then enter the calendar URL:

Google calendar add feed

But why?

Having your blog posts show up on your calendar is definitely not a necessity by any stretch of the imagination, but it’s one of those nice little things that may make your life a little easier.

For me, I find it helpful to mentally plan social media efforts out if I can see my whole week in one view, from client work and launches to holidays, to days I’m particularly busy, to my upcoming posts on the calendar (they’re in yellow in this weekly view, which is what I usually look at):

Calendar weekly view

Click to enlarge

Conversely, I also find it help it helpful to have my whole calendar in view as I plan out and schedule future posts. It helps me post things relevant to upcoming holidays, for example (as a hazard of self-employment, I tend to forget many federal holidays).

And, to tell you the truth, I also just kind of enjoy seeing my posts on there. Enjoyment matters!

Neatly Polished Update, with Sample Lesson

Neatly Polished is clear, friendly, in-depth online front-end web development classes

It has been a long time coming (my goodness, those lessons took a lot longer to write than I expected), but I’m happy to say that all 26+ lessons in my Neatly Polished course on WordPress Theme Development are finally live.

In case you aren’t familiar with this project, Neatly Polished is a subscription-model site I created for more in-depth tutorials and lessons than are really reasonable to provide for free via this blog. There are the lessons, plus a support forum where I answer questions and discuss the lessons (and other stuff, sometimes) with participants.

The first full “course” is on WordPress Theme Development, and basically walks through all the files you’d use in a WordPress theme, along with the various theme components and some workflow tips throughout. You can check out the entire course outline, along with a single full sample lesson, on page templates.

Subscriptions run $29 for a monthly membership and $79 for a quarterly membership, and include all current and future content for the life of the membership.

Future plans for the site include a similar course on Shopify theme development, as well as mini-courses on things like PHP basics, HTML/ CSS layout modules, and other TBD topics. You can keep up to date with what’s going on over there (since I don’t post here about everything) via Twitter and/or by signing up for the Neatly Polished email list.

I’m pretty excited about this project, in part because of the fabulous feedback I’ve gotten that has both helped me keep improving the lessons over time, and also has just made me feel even more sure that sharing what I know like this is the right thing to be doing.

I’ll leave you with some of the awesome things members have said about the lessons and program:

“Awesome lesson! I have used many fabulous tutorials (free and paid) on WordPress theme development, but find that even though the information is valuable , it is not “streamlined” as well as yours.”

Very specific. The checklist was clutch. I was missing 3 things (due to my horrible skimming skills and my antsy pants that are so excited to be learning this stuff). With the checklist, I was able to make sure that I didn’t miss a beat!”

“Great! Can’t believe I picked this up so quickly. Really appreciate your simple and easy to follow instructions.”

If you’d like to register, you can do so here.

Top Hidden Costs of Website Projects

7 Common (But Easily Overlooked) Website Costs

Over a couple of years of client projects, one thing I’ve learned is that there are a lot of costs for website that site owners often don’t know to anticipate or plan for. It is not fun being the bearer of unexpected news about additional costs, so I try to be pretty up front about these potential “extra” costs at the contract and invoicing stage of the project.

There are seven main costs that many clients may not know about (especially if it’s their first big web project):

1. Hosting (Especially Quality Hosting)

While most clients know that they’ll have to pay for hosting of some sort, many don’t realize that quality business-level hosting can be pricey. While inexpensive shared hosting may be okay for some sites, there are definite downsides to cut-rate hosting (everything from reliability to security issues to variable customer service quality).

Once you move beyond inexpensive shared hosting, the cost for hosting can vary wildly and tends to increase pretty rapidly in price. This can be a real surprise for clients, and is something worth discussing early in the process. It helps to be able to discuss the benefits of more premium hosting services.

Typical Cost: $3-6/ month for inexpensive shared hosting, $15/ month and up for premium hosting

2. Domain Registration

If you’ve been working with websites for awhile, it’s easy to forget that the concepts of domain registration versus hosting are not actually that obvious to the general internet user. It’s a good idea to check in early with clients to make sure they’ve got a domain registered, and you’ll also want to help them understand the cost for registration.

Some things clients may not know about domain registration include:

  • It’s a recurring (usually yearly) cost
  • Some (but not all) hosting providers include a year or more of free domain registration with a new plan
  • There are add-on services needed along with the domain for things like privacy or added security
  • The domain can be registered separately from the hosting, if desired

I’ve found that clients also appreciate tips on registering similar domains, such as the .org version of the primary domain or a common misspelling.

Typical Cost: starts at about $10/ year per domain registration alone (more for high-value domains and certain TLDs)

3. Email Accounts

Some hosting providers include email of some sort (forwarding accounts, or even email inboxes) with hosting plans, others do not. Since many people are used to free personal email accounts, it may not occur to them that business-class email often comes at a cost and that the cost may be per-email-address.

I typically recommend Google Apps for Work as a great business-class email option, and that service runs $5/ inbox/ month, or $50/ inbox/ year.

Typical Cost: $50 per inbox per year

4. Licenses

It’s not uncommon for clients to believe that any and all functionalities and design elements within a website are part of the overall project cost, but I tend to separate out license fees from my rates unless I already have an unlimited developer license for a particular purpose.

One of the reasons I do it this way is that I prefer to have licenses for each project in the client’s name. This is especially true for things with recurring costs like subscription font services, but is also true for one-off licenses that require a new license for each site.

Font Licenses

I’ve written at length on web fonts and licensing, but those are not topics that the average site owner is going to know a lot about.

Ideally, font licensing comes up in the design phase of a project but I like to cover myself by also bringing it up in my invoices and contracts. That way I don’t have to be the one telling the client late in the project that the fonts they’ve fallen in love with are going to cost them a lot of money.

Typical Cost: varies widely from free to hundreds of dollars per year depending on font(s) chosen, traffic levels, etc.

Software Licenses

Beyond font licensing, some jQuery plugins, WordPress plugins, and Shopify apps come at added cost. For example, MagicZoom is a very popular jQuery plugin for e-commerce product zoom functionality, and it has a per-site cost unless you’ve got a developer license you’re using for all your clients.

This is another place where it’s a good idea to talk early about special functionality requirements and for the designer and developer to be on the same page about functionality that is “free” (or built into a regular scope of work) versus functionality that may have associated extra licensing costs.

Typical Cost: varies – jQuery plugins tend to run $30-100 for a one-time license, premium WordPress plugins and Shopify apps often have yearly or monthly recurring costs

5. Security Provisions

Depending on the type of site and the setup, there may be added security needs.

SSL and Dedicated IPs

If you’re running any kind of secure content through your site, you’ll likely need an SSL certificate, which is an added yearly cost for most hosting accounts. SSL also requires a dedicated IP address, another added cost in some cases (especially on shared hosting).

Typical Cost: on one shared host, a dedicated IP address is just over $3 per month on top of a regular hosting plan; SSL certificates tend to run $20-50 per year up to $200+ for wildcard coverage

Monitoring Services

Even if you’re not storing or using sensitive information, it can be helpful to have security monitoring on your site. For WordPress, this typically looks like third-party services that keep an eye out for hacked sites or for necessary updates/ upgrades. Some clients may also want ongoing help with their site updates, which is a long-term cost that will need to be negotiated.

Typical Cost: leading provider Sucuri has an antivirus plan runs $89.99/ year for a single site

6. Backup/ Restore

This is another feature that depends on the site and hosting provider, but that sometimes incurs extra costs. Regular automated backups and a one-click restore are one of the reasons I really like WP Engine hosting [affiliate link], but other hosting providers may not include those things standard, or may only allow access to parts of the backups.

Sometimes you can add better backup systems through a hosting provider for an additional cost, or there are third-party tools and services such as VaultPress and BackupBuddy.

Typical Cost: VaultPress runs $55/ year for their “Lite” backup/ restore plan

7. SPAM Filtering (WordPress)

For WordPress blogs, in particular, there’s typically a need for additional SPAM filtering. While there are some free options out there, I prefer using Akismet as it’s a tried-and-true provider that does a good job filtering out SPAM with few false positives. You can use it for free for a personal blog, but it does have a fee for commercial sites.

Typical Cost: Akismet is $5/ month


Total Cost

Looking at a “typical” WordPress business site that includes a blog a reasonable cost breakdown might be something like:

Shared Hosting:

Since it’s a lower price point, shared hosting is often a good place for a new business to start. The downsides are usually reliability and service/ support, and as traffic grows or as storage needs increase, shared hosting may become less of a viable option.

Service Yearly Cost
Domain Registration $10
Whois Privacy $3
Hosting $60
Email (provided by hosting) $0
Sucuri Monitoring $90
VaultPress Backup Bundle (includes Akismet) $99
Total: $262 (plus any one-time licensing fees)

Premium Hosting:

While clearly more expensive, premium hosting can be worth the price for ease of use, uptime and site speed, and quality of customer service. Premium hosting providers also often optimize for things like traffic spikes and dedicated WordPress hosting providers have WordPress-specific features that can save site owners time.

Service Yearly Cost
Domain Registration $10
Whois Privacy $3
WP Engine (“Personal” Plan*) $348
Email $50
Akismet $60
Total: $471 (plus any one-time licensing fees)

* The personal plan is the lowest plan offered by WP Engine and is based on the number of visits per month, despite the name it can be used for business sites.


There you have it – an overview of some of the most common website project costs along with some very approximate numbers for rough budgeting purposes. I’m sure I’m missing something(s), so if you’ve got something that pops up a lot in your projects that I haven’t mentioned, post it in a comment.

Marking Posts as New in WordPress

I was updating my bookmarks page and wanted a way to indicate the stuff that I’d added recently, which led me to thinking about how to identify posts from a particular timeframe.

The Question

How can I mark recent posts based on a particular timeframe?

The Result

I considered a couple of options (listed below) and ended up with a fairly simple solution using relative time, something WordPress has built-in. On the front-end, it just adds a little clock icon next to the title of any resource added within the last 30 days:

new resource indicator

Potential Solutions

My first thought was that I could use PHP to check whether the post date was within a certain range.

1. Compare Year and Month

I was thinking maybe I’d check the post year against the current year, then if it matched I’d check against the current month. However, I dismissed that before I got past about 20 characters of code because I realized that it would throw off the time frame of the results depending on where in the month we are. Oh well, we all have bad ideas sometimes.

2. Date Calculations

Then I was thinking I’d use PHP to check the date against a relative time frame, e.g. the last 30 days. Something like the reverse of this Stack Overflow question and solution.

That would work, but then I remembered that WordPress has relative post date built in, where you can display the time as “1 day ago” or “30 minutes ago” using the function human_diff_time (function reference). Hooray, even better!

3. Using Relative Time

So then I was thinking, with that relative time I just need to check and see if we’re in the right time frames to be what I’d consider “recent.” The numerical values returned won’t be useful but the words are definitely useful. I double checked when the transition in words happens by looking at the core code underneath that function. I was able to confirm that anything with a relative time in minutes, hours or days has been posted in the last 30 days, and I’d consider that recent.

Full Solution

Here’s the full solution I ended up with (limited to just the template code within the loop, since the rest of the template is irrelevant to the question):

<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
    <?php
        $postdate = human_time_diff( get_the_time('U'), current_time('timestamp') ); // get the post date in relative time
        $recentvals = array('min','mins','hour','hours','day','days'); // the values I consider "recent"
    ?>                          
    <li class="filterable">
        <a href="<?php the_field('url'); ?>">
            <span class="project-title"><?php the_title(); ?><?php foreach ( $recentvals as $recentval ) : if ( strpos($postdate, $recentval) !== FALSE) : echo ' <i class="fa fa-clock-o"></i><span style="display:none;">new</span>'; endif; endforeach; ?></span>
        </a>
        <span class="small"><?php the_field('description'); ?></span>
    </li>
<?php endwhile; ?>

The Breakdown

Let’s take a closer look piece by piece at what this code does:

Set Variables

First up, there are two pieces of information I want to use in my comparison. That’s this part of the code:

<?php
        $postdate = human_time_diff( get_the_time('U'), current_time('timestamp') ); // get the post date in relative time
        $recentvals = array('min','mins','hour','hours','day','days'); // the values I consider "recent"
    ?>

There are two variables set up here:

  1. The post’s relative publication date, meaning how long ago it was posted in words (e.g. “20 mins” or “2 days”)
  2. The time frames I want to include as “recent,” using the words provided by that relative time function (options are: “mins,” “hours”, “days,” “weeks,” “months,” and “years” and the singular of each of those)

For the first, I just used WordPress’s built-in function, straight off the Codex page except I’m assigning it to a variable rather than echoing it (displaying it) on the page.

For the second, I have created an array of the words I’ll accept as “recent,” using both the singular and plural forms. I’m actually not sure if it’s possible to just use the singular and I don’t feel like testing it so I’ve just used both for safety’s sake.

Compare the Two

Next, I need to figure out whether the current post date for each post contains any of the words in my array. I referenced this thread on Stack Overflow for this code:

<?php 
foreach ( $recentvals as $recentval ) : 
    if ( strpos($postdate, $recentval) !== FALSE) : 
        echo ' <i class="fa fa-clock-o"></i><span style="display:none;">new</span>'; 
    endif; 
endforeach; 
?>

This runs through each of the allowed time frame words in my array and compares them against the post date. If one comes up as a match, it prints out the code in the echo line.

Show the Icon, Plus Search

The printed HTML from that snippet is:

<i class="fa fa-clock-o"></i><span style="display:none;">new</span>

That creates the Font Awesome clock icon along with a hidden span (I know, I know, lazy inline CSS). The hidden span is there so that it’s possible to use the in-page “search” function to pull up the new posts.

Implementation Keys

If you’re going to implement this yourself, the key things to remember are:

  1. The code needs to be within the loop, including the bit where you set the variables.
  2. You’ll need to determine which words constitute “recent” and update your array accordingly.
  3. You’ll likely also need to update your icon/ display HTML to fit your purposes (whether it’s just displaying text or adding in an image or another icon font or whatever).