Wednesday, February 22, 2012

Return Home
Contact Me

Instagram Hashtag Atom Feed Parser

Instagram Instagram recently released some new features in their latest iPhone App build.

While there are a few unofficial Instagram API’s floating around out there, I thought I’d spend a little time playing with the feed until an official API is released. Below is a fairly simple explanation of converting the Atom feed into a HTML display with some jQuery effects added.


What the Atom Feed Offers

The feed offers links to the following:

  • The large 612px by 612px image
  • The thumbnail 150px by 150px image
  • The image title
  • The date posted
  • The photo hashtags
  • The username of the photographer

<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:georss="http://www.georss.org/georss" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>Photos tagged as "lomogre" on Instagram</title>
    <link>http://instagr.am</link>
    <description>Photos tagged as "lomogre" on Instagram</description>
    <atom:link href="http://instagr.am/tags/lomogre/feed/recent.rss" rel="self"></atom:link>
    <language>en</language><lastBuildDate>Sun, 30 Jan 2011 12:07:15 -0800</lastBuildDate>
    <item>
      <title>Vinyl Sunday: Hank Mobley - The Flip</title>
      <link>http://distillery.s3.amazonaws.com/media/2011/01/30/4d160443c57641a2bcd5701e93679b2b_7.jpg</link>
      <description><img src="http://distillery.s3.amazonaws.com/media/2011/01/30/4d160443c57641a2bcd5701e93679b2b_7.jpg"/></description>
      <pubDate>Sun, 30 Jan 2011 12:07:15 -0800</pubDate>
      <guid>http://distillery.s3.amazonaws.com/media/2011/01/30/4d160443c57641a2bcd5701e93679b2b_7.jpg</guid>
      <media:title>Vinyl Sunday: Hank Mobley - The Flip</media:title>
      <media:description><img src="http://distillery.s3.amazonaws.com/media/2011/01/30/4d160443c57641a2bcd5701e93679b2b_7.jpg"/></media:description>
      <media:content url="http://distillery.s3.amazonaws.com/media/2011/01/30/4d160443c57641a2bcd5701e93679b2b_7.jpg" width="612" type="image/jpeg" height="612"></media:content>
      <media:thumbnail url="http://distillery.s3.amazonaws.com/media/2011/01/30/4d160443c57641a2bcd5701e93679b2b_5.jpg" width="150" height="150"></media:thumbnail>
      <media:keywords>lomogre,albumart,vinylsunday,vinyl</media:keywords>
      <media:credit role="photographer">lomogre</media:credit>
    </item>
  </channel>
</rss>

What’s Included?

I basically just took a look at what the Atom feed offers by viewing a hashtag at http://instagr.am/tags/[hashtag name]/feed/recent.rss. I chose to use SimplePie to parse the XML and then output the thumbnails and full sized images to be viewed using the jQuery lightBox plugin by Leandro Vieira Pinho.

With the heavy lifting taken care of, here’s what was left:

Parsing the XML Using SimplePie

To start things off, I needed a tag to set the default feed. My username on Instagram is lomogre, so I chose this. I also offered the date format as a variable since it is without a doubt a globally used app.


/* Set the default feed */
$default="lomogre";
/* Set the date format - http://php.net/manual/en/function.date.php */
$dateformat="j M Y";

I’m using the GET method to determine the hashtag I’m parsing the feed of, so I’ll check to see if my GET variable is empty, and if not use my default hashtag. I also need to instantiate my SimplePie object and input some settings before initializing it.

One other important thing to note is the use of the set_cache_location() function, it’s important that this directory is writeable


include('simplepie.inc');
$hashtag=(empty($_GET['hashtag']))?$default:strtolower(trim($_GET['hashtag']));
$feedurl=(get_magic_quotes_gpc())?stripslashes("http://instagr.am/tags/".$hashtag."/feed/recent.rss"):"http://instagr.am/tags/".$hashtag."/feed/recent.rss";
$feed=new SimplePie();
$feed->set_feed_url($feedurl);
$feed->set_item_class();
$feed->enable_cache(true);
$feed->set_cache_duration(3600);
$feed->set_cache_location('cache');
$feed->init();
$feed->handle_content_type();

Preparing for Output

I prefer heredoc for creating my final output, so I have to create a few different variables to hold different chunks of my output.

For each image in the feed, I want to output the following HTML:


<div class="ig_photo">
  <div class="ig_thumb_col">
    <a href="LARGE IMAGE LINK" title="IMAGE TITLE"><img src="THUMBNAIL URL" width="150" height="150" alt="IMAGE TITLE" /></a>
  </div>
  <div class="ig_photo_data_col">
    <h5>IMAGE TITLE</h5>
    <ul>
      <li><strong>Posted:</strong> DATE POSTED</li>
      <li><strong>Photo Hashtags:</strong> <a href="?hashtag=HASHTAG" title="View recent photos on Instagram tagged with HASHTAG">#HASHTAG</a></li>
      <li><strong>Instagram User:</strong> USERNAME</li>
    </ul>
  </div>
  <div class="clear"></div>
</div>

Using available SimplePie functions, I’m able to pull all the necessary data to create this output.


$output="<div id=\"ig_results\">"."\n";
if($feed->data){
  $items=$feed->get_items();
  $output.="  <h2>".$feed->get_description()."</h2>";
  $output.="  <p class=\"ig_feed_quantity\">Displaying ".$feed->get_item_quantity()." most recent entries. <span class=\"ig_instruct\">(Click a thumbnail to view a larger image.)</span></p>"."\n";
  foreach($items as $item){
    $permalink=$item->get_permalink();
    $title=$item->get_title();
    $nodoubletitle=str_replace("\"","'",$title);
    $date=$item->get_date($dateformat);
    $id=$item->get_id();
    $hashtags="";
    $thumbnail="";
    $photographer="";
    if($enclosure = $item->get_enclosure(0)){
      foreach ((array) $enclosure->get_keywords() as $keyword){
        $hashtags.="<a href=\"?hashtag=".$keyword."\" title=\"View recent photos on Instagram tagged with ".$keyword."\">#".$keyword."</a>, ";
      }
      $hashtags=substr($hashtags,0,-2);
      $thumbnail.=$enclosure->get_thumbnail();
      foreach ((array) $enclosure->get_credits() as $credit){
        $photographer=$credit->get_name();
      }
    }
    $output.=<<<HTML
  <div class="ig_photo">
    <div class="ig_thumb_col">
      <a href="$id" title="$nodoubletitle"><img src="$thumbnail" width="150" height="150" alt="$title" /></a>
    </div>
    <div class="ig_photo_data_col">
      <h5>$title</h5>
      <ul>
        <li><strong>Posted:</strong> $date</li>
        <li><strong>Photo Hashtags:</strong> $hashtags</li>
        <li><strong>Instagram User:</strong> $photographer</li>
      </ul>
    </div>
    <div class="clear"></div>
  </div>\n
HTML;
  }
}

I put in an else statement in case there are no photos for the feed and added a form that searches for a hashtag feed input by the user.


else {
  $output.="  <h2>".$hashtag." returned zero results.</h2>"."\n";
}
$output.=<<<HTML
  <form action="" method="get" id="ig_form">
    # <input type="text" name="hashtag" id="hashtag" class="text" value="Type a Hashtag to Search" />
    <input type="submit" value="Search »" class="submit" />
  </form>
</div>\n
HTML;

After all this, I just echo the output in the HTML body.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>Instagram Feed for Hashtag "<?php echo $hashtag; ?>"</title>
  <link href="css/ig_styles.css" rel="stylesheet" type="text/css" media="screen" />
  <link href="css/jquery.lightbox-0.5.css" rel="stylesheet" type="text/css" media="screen" />
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js"></script>
  <script type="text/javascript" src="js/jquery.lightbox-0.5.min.js"></script>
  <script type="text/javascript" src="js/ig_init.js"></script>
</head>
<body>
<?php echo $output; ?>
</body>
</html>

23 Responses

  1. becca says:

    I was wondering if you could do this using the large (612px) image instead of the thumbnail? Thanks for posting!

    • Matt says:

      Hi Becca,
      Just change some code. Look for this:

      <a href="$id" title="$nodoubletitle" rel="nofollow"><img src="$thumbnail" width="150" height="150" alt="$title" /></a>

      and change it to:

      <a href="$id" title="$nodoubletitle" rel="nofollow"><img src="$id" width="612" height="612" alt="$title" /></a>

      If you’re using the same layout as the demo, you will have to adjust the CSS to make room for the larger image.

  2. becca says:

    Hi Matt,
    Thanks for the response. I thought it was that simple , until I gave it a try. It looks like because we’re pulling from instagrams thumbnail feed the image size is 150x150px and if you change it to 612x612px it pixelates it.

    I think I need to pull from intstagram’s large image feed and that’s where I get lost…

    Thanks again!

    • Matt says:

      Hi Becca,
      Make sure you are also changing the source of the image tag from $thumbnail to $id, as $id contains the URL to the full sized image.

    • becca says:

      Oh wow, totally missed that the first time. Thanks so much! — b

  3. Shane says:

    Hi Matt,

    I uploaded all the files and made the changes you recommended. However, both my default page and my search page returns zero results.

    I’m using basic shared server space with my hosting company but I’ve changed permissions to allow write access. Could that be the issue?

    Thanks, Shane

    • Matt says:

      Hi Shane,
      Can you post a URL to your site? Also, what is the default hashtag you set it to load on?

  4. Shane says:

    Hey Matt, thanks for the quick response.

    I set the default to ‘stdoyle’ which is my Instagram account. The URL is hashgram.com

    Thanks much, Shane

    • Matt says:

      Hi Shane,
      The RSS feed provided by Instagram is for hashtags only, so you have to tag your photos with #stdoyle in order to have something show up for that search term. I just ran a search for that hashtag within Instagram and was returned 0 results.

  5. Shane says:

    Hmmm…, but wouldn’t other hashtags like #sunset return results in the search?

    When I use your demo, the search returns any hashtagged item.

    When I mentioned ‘stdoyle’, I was referring to this section in your code:

    /* Set the default feed */
    $default=”stdoyle”;
    /* Set the date format – http://php.net/manual/en/function.date.php */
    $dateformat=”j M Y”;

    • Matt says:

      Shane,
      My mistake, I just checked your default tag before testing the script on your site.

      It’s hard to get to the bottom of it without seeing some specific server settings. I know you mentioned that you set some permissions, but maybe just double check that the cache directory is at 777. If that doesn’t work try replacing the line $feed->set_cache_location('cache'); with $feed->set_cache_location(dirname(__file__)."/cache");

  6. Shane says:

    Hey Matt, still scratching my head on this end. I made the recommended changes, adjusted the cache to 777 and even replaced the line of code above…, but still no luck.

    I’d be glad to setup an FTP user for you if you think that would help…, let me know and I will send a login.

    Thanks much!!

  7. Jason says:

    Hi Matt,
    I’ve been trying to take this demo and apply it to my WordPress theme, so far no luck. Any tips on what would be the best way to implement this into a WordPress blog? Thanks the post, it’s great.

    • Matt says:

      Hi John,
      What you will probably want to do is rename the index.php file to something like ig_tag_feed.php and then copy / paste all the files in the instagram_atom_parser directory to your theme’s inc directory (just create an inc directory if you don’t have one).

      Next, just duplicate your page.php file in your template directory and rename it page-n.php where n is the id of your page. Then in your page-n.php use the php include function to include ig_tag_feed.php, <?php include( TEMPLATEPATH.'/inc/ig_tag_feed.php'); ?>. Put this line where you want the feed to be displayed.

      You will have to change a few things in ig_tag_feed.php. First, replace the line include('simplepie.inc'); with include(dirname(__FILE__).'/simplepie.inc');. Then delete lines 86 – 100 (the HTML doctype, head, body, etc…) and put echo $output; on the last line before the closing ?>.

      You’ll have to copy / paste the styles from the style sheet into your themes style sheet and make adjustments on colors / layout.

      That should do it.

  8. abraxas says:

    Hi, thx for the script. Is there a way to change the the result / number of the pictures?

    • Matt says:

      As far as I know, you can only get 20 pictures per feed. If you want more than that, you’ll need to look into the Instagram API.

      Thanks for reading!

  9. Daniel Boone says:

    Hello, First thanks so much for this post. Is there a way to only set my hastag and nothing else? I set the default to my companies hashtag name but every once and a while I will get random hastag’s on search engines.

    • Matt says:

      Sorry for the delayed response! The easiest way to make the script static is to take down the form and find this line $hashtag=(empty($_GET['hashtag']))?$default:strtolower(trim($_GET['hashtag'])); and change it to $hashtag=$default;. That should do it.

  10. I’m also trying to integrate this into a wordpress theme, but without luck. I followed the directions you gave above, but without luck. Everything else on the page is still displaying fine, but I’m not getting any output or any errors for the instagram feed.

  11. just figured it out…when using a child theme you’ll need to use “stylesheetpath” instead of “templatepath”.

  12. Manny says:

    Thanks for the files Matt! You saved me a lot of time! Only one question, what would it entail to make this for a user account and not a hashtag?

  13. Manny says:

    Thanks Matt! If only I knew what it all meant lol

Comments

Please post your comments, questions, or suggestions here.

* Denotes a required field.

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Recent Posts: