How to Build Your Own Instagram Search Engine With jQuery and PHP

Ever since Google rolled out instant search features, it has become a popular trend in web design. The techniques are all fairly straightforward, where even a web developer with moderate jQuery experience can pick up programming APIs and JSON data.

For this tutorial, I want to explain how we can build a similar instant search web application. Instead of pulling images from Google we can use Instagram which has grown tremendously in just a few short years.

This social network started off as a mobile app for iOS. Users could take photos and share them with their friends, leave comments, and upload them to 3rd party networks such as Flickr. The team was recently acquired by Facebook and had published a brand new app for the Android Market. Their userbase has grown tremendously, and now developers can build amazing mini-apps just like this instasearch demo.

Obtaining API Credentials

Before creating any project files, we should first look into the ideas behind Instagram’s API system. You will need an account to access the developer’s portal which offers useful instructions for beginners. All we need to query the Instagram database is a “Client ID”.

In the top toolbar click the Manage Clients link, then click the green button “Register a New Client”. You’ll need to give the application a name, a short description, and a website URL. The URL and Redirect URI can be the same value in this instance only because we don’t need to authenticate any users. Just fill in all the values and generate the new application details.

You’ll see a long string of characters named CLIENT ID. We will need this key later on when building the backend script, so we’ll return to this section. For now we can begin the construction of our jQuery instant search application.

Default Webpage Content

The actual HTML is very slim for the amount of functionality we’re using. Since most of the image data is appended dynamically we only require a few smaller elements inside the page. This code is found inside the index.html file.

<!doctype html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>Instagram Photo Instant Search App with jQuery</title>
  <meta name="author" content="Jake Rocheleau">
  <link rel="stylesheet" type="text/css" href="style.css">
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
  <script type="text/javascript" src="ajax.js"></script>
</head>

<body>
	<div id="w">
	  <section id="sform">
	    <small>Note: No spaces or punctuation allowed. Searches are limited to one(1) keyword.</small>
	    <input type="text" id="s" name="s" class="sfield" placeholder="Enter a search tag..." autocomplete="off">
	  </section>
		
	  <section id="photos"></section>
	</div>
</body>
</html>

I’m using the latest jQuery 1.7.2 library along with two external .css and .js resources. The input search field has no outer form wrapper because we don’t want to ever submit the form and cause a page reload. I have disabled a few keystrokes inside the search field so that there are more limited restrictions when users are typing.

We will populate all the photo data inside the middle section ID #photos. It keeps our basic HTML clean and easy to read. All the other internal HTML elements will be added via jQuery, and also removed before each new search.

Pulling from the API

I’d like to start first by creating our dynamic PHP script and then move into jQuery. My new file is named instasearch.php which will contain all the important backend hooks into the API.

<?php
header('Content-type: application/json');

$client = "YOURCLIENTIDHERE";
$query = $_POST['q'];
$api = "https://api.instagram.com/v1/tags/".$query."/media/recent?client_id=".$client;

function get_curl($url) {
    if(function_exists('curl_init')) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL,$url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
        $output = curl_exec($ch);
        echo curl_error($ch);
        curl_close($ch);
        return $output;
    } else{
        return file_get_contents($url);
    }
}

The first line denotes that our return data is formatted as JSON instead of plaintext or HTML. This is necessary for JavaScript functions to read the data properly. Afterwards I’ve got a few variables setup containing the application client ID, user search value, and the final API URL. Make sure you update the $client string value to match your own application.

To access this URL data we need to parse the file contents or use cURL functions. The custom function get_curl() is just a small bit of code which checks against the current PHP configuration.

If you do not have cURL activated this will attempt to activate the feature and pull data via their own functions library. Otherwise we can simply use file_get_contents() which tends to be slower, but still works just as well. Then we can actually pull this data into a variable like so:

$response = get_curl($api);

Organizing & Returning Data

We could just return this original JSON response from Instagram with all the information loaded up. But there is so much extra data and it’s very annoying to loop through everything. I prefer to organize Ajax responses and pull out exactly which pieces of data we need.

First we can setup a blank array for all the images. Then inside a foreach() loop we’ll pull out the JSON data objects one-by-one. We only need three(3) specific values which are the $src(full-size image URL), $thumb(thumbnail image URL), and $url(unique photo permalink).

$images = array();
if($response){
	foreach(json_decode($response)->data as $item){		
        $src = $item->images->standard_resolution->url;
        $thumb = $item->images->thumbnail->url;
		$url = $item->link;
		
        $images[] = array(
        "src" => htmlspecialchars($src),
        "thumb" => htmlspecialchars($thumb),
        "url" => htmlspecialchars($url)
        );

    }
}

Those who are unfamiliar with PHP loops may get lost in the process. Don’t focus so much on these code snippets if you don’t understand the syntax. Our array of images will contain at most 16-20 unique entries of photos pulled from the most recent publication date. Then we can output all this code onto the page as a jQuery Ajax response.

print_r(str_replace('\\/', '/', json_encode($images)));
die();

But now that we’ve had a look behind the scenes we can jump into frontend scripting. I’ve created a file ajax.js which contains a couple event handlers tied on to the search field. If you’re still following up till now then get excited we’re so close to completion!

jQuery Key Events

When first opening the document ready() event I’m setting up a couple variables. The first two behave as direct target selectors for the search field and photos container. I’m also using a JavaScript timer to pause the search query until 900 millisecond after the user has finished typing.

$(document).ready(function(){
  var sfield = $("#s");
  var container = $("#photos");
  var timer;

There are only two main function blocks we’re working with. The primary handler is triggered by a .keydown() event when focused on the search field. We first check if the key code matches any of our forbidden keys, and if so negate the key event. Otherwise clear the default timer and wait 900ms before calling instaSearch().

/** 
 * keycode glossary 
 * 32 = SPACE
 * 188 = COMMA
 * 189 = DASH
 * 190 = PERIOD
 * 191 = BACKSLASH
 * 13 = ENTER
 * 219 = LEFT BRACKET
 * 220 = FORWARD SLASH
 * 221 = RIGHT BRACKET
 */
$(sfield).keydown(function(e){
  if(e.keyCode == '32' || e.keyCode == '188' || e.keyCode == '189' || e.keyCode == '13' || e.keyCode == '190' || e.keyCode == '219' || e.keyCode == '221' || e.keyCode == '191' || e.keyCode == '220') {
	 e.preventDefault();
   } else {
		clearTimeout(timer);
	
		timer = setTimeout(function() {
		  instaSearch();
		}, 900);   
   }
});

Every time you update the value it’ll automatically go fetch new search results. There are also many of other key codes we could have blocked from triggering the Ajax function – but too many for listing in this tutorial.

The Ajax instaSearch() Function

Inside my new custom function we are first adding a “loading” class onto the search field. This class will update the camera icon for a new loading gif image. We also want to empty any possible data left over within the photos section. The query variable is pulled dynamically from the current value entered in the search field.

function instaSearch() {
	$(sfield).addClass("loading");
	$(container).empty();
	var q = $(sfield).val();
	
	$.ajax({
		type: 'POST',
		url: 'instasearch.php',
		data: "q="+q,
		success: function(data){
			$(sfield).removeClass("loading");
			
			$.each(data, function(i, item) {
				var ncode = '<div class="p"><a target="_blank" href="'+data[i].src+'" class="fullsize" target="_blank"><img src="img/full-image.png" alt="fullsize"></a> <a target="_blank" href="'+data[i].url+'" target="_blank"><img src="'+data[i].thumb+'"></a></div>';
				$(container).append(ncode);
			});
		},
		error: function(xhr, type, exception) { 
			$(sfield).removeClass("loading");
			$(container).html("Error: " + type); 
		}
	});
}

If you’re familiar with the .ajax() function then all these parameters should look familiar. I’m passing the user search parameter “q” as the POST data. Upon success and failure we remove the “loading” class and append any response back into the #photos wrapper.

Within the success function we are looping through the final JSON response to pull out individual div elements. We can accomplish this looping with the $.each() function and targeting our response data array. Otherwise the failure method will directly output any response error message from the Instagram API. And that’s really all there is to it!

Live Instant Search Web App for Instagram Photos

Final Thoughts

The Instagram team has done a wonderful job scaling such a tremendous application. The API can be slow at times, but response data is always properly formatted and very easy to work with. I hope this tutorial can demonstrate that there is a lot of power working off 3rd party applications.

Unfortunately the current Instagram search queries do not allow more than 1 tag at a time. This is limiting to our demo, but it certainly doesn’t remove any of its charm. You should check out the live example above and download a copy of my source code to play around with. Additionally let us know your thoughts in the post discussion area below.

WebsiteFacebookTwitterInstagramPinterestLinkedInGoogle+YoutubeRedditDribbbleBehanceGithubCodePenWhatsappEmail