Build Your Own Instagram Search Engine Using jQuery and PHP

Ever since Google introduced instant search features, they have become a popular trend in web design. These techniques are straightforward enough that even web developers with moderate jQuery skills can master programming APIs and JSON data.

In this tutorial, I’ll show you how to create an instant search web application similar to Google’s. However, instead of sourcing images from Google, we’ll tap into Instagram – a platform that has seen exponential growth in just a few years.

Instagram began as an iOS mobile app, allowing users to snap photos, engage with friends via comments, and share their creations on third-party networks like Flickr. After being acquired by Facebook, Instagram expanded with a new app for Android, significantly growing its user base. Now, developers have the opportunity to create incredible mini-apps, such as the instasearch demo we will explore.

View demo Download source

Getting Started with Instagram API Credentials

Before diving into project files, it’s crucial to understand the basics of the Instagram API. You’ll need to create an account at the developer’s portal, which provides helpful guides for beginners. To access the Instagram database, the key piece of information we need is a “Client ID”.

In the top toolbar, click on the Manage Clients link, then select the green “Register a New Client” button. You’ll need to enter a name for your application, a brief description, and a website URL. In this scenario, the URL and Redirect URI can be the same because user authentication isn’t required. Just complete the form to generate your new application details.

You’ll receive a long string of characters known as the CLIENT ID. Keep this key handy, as it will be vital when we start coding the backend script. For now, let’s start building our jQuery instant search application.

Setting Up the Default Webpage

The actual HTML of our project is quite minimal considering the functionality we aim to achieve. Since most of the image data is appended dynamically, only a few HTML elements are necessary. Below is the code located in 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 am utilizing jQuery 1.7.2, along with external CSS and JS files. The search field does not have a surrounding form element to avoid page reloads upon submission. I have also disabled certain keystrokes within the search field to limit user input errors. The photo data will be dynamically inserted into the #photos section, maintaining our page’s clean and readable layout.

Connecting to the Instagram API

Let’s begin by setting up our dynamic PHP script before moving on to jQuery. Our script, named instasearch.php, will manage the critical backend interactions with 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 script begins by setting the output as JSON, which is essential for the JavaScript functions to interpret the data correctly. It includes variables for the application client ID, user search input, and the API endpoint. Remember to replace the $client string with your actual client ID.

To retrieve data from this API, we either parse the content with a custom function get_curl() or use cURL functions. The get_curl() function checks if cURL is enabled in the PHP configuration and uses it to fetch data. If cURL is not available, it falls back to file_get_contents(), which is slower but equally effective.

$response = get_curl($api);

Streamlining Data Organization & Retrieval

While we could simply return the raw JSON data received from Instagram, it often contains excess information that complicates data handling. Instead, I prefer to streamline the Ajax response by extracting only the essential data.

Initially, we set up an empty array to hold image data. Using a foreach() loop, we extract three specific values from the JSON objects: $src (the URL of the full-size image), $thumb (the URL for the thumbnail image), and $url (the 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)
        );
    }
}

If PHP loops are new to you, don’t worry if the syntax seems complex. We’ll store between 16-20 unique photo entries in our array, based on their recent publication dates, and then we can display these images via a jQuery Ajax response on the webpage.

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

With this backend setup complete, let’s turn our attention to the frontend scripting. I’ve prepared an ajax.js file with several event handlers linked to the search field. Stay tuned as we’re nearing the completion of our project!

Handling jQuery Key Events

Upon loading the document, the ready() function initializes several variables. These include direct selectors for the search field and the photos container, as well as a JavaScript timer to delay the search query until 900 milliseconds after the user has stopped typing.

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

We manage input with two main functions. The first function is activated by a .keydown() event when the user interacts with the search field. It checks if the input key is restricted, blocking the event if necessary. If the key is permissible, the default timer is cleared, and a new one is set to activate the instaSearch() function after a 900ms delay.

/** 
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); 
    }
});

This setup ensures that each new input automatically triggers a search for fresh results. We’ve chosen not to block additional key codes to keep the tutorial concise.

Enhancing the Ajax instaSearch() Function

In this custom function, we start by adding a “loading” class to the search field, updating the camera icon to a new loading GIF. It’s also essential to clear any leftover data in the photos section. The query variable is dynamically retrieved from the 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 href="'+data[i].src+'" class="fullsize"><img src="img/full-image.png" alt="fullsize"></a> <a href="'+data[i].url+'"><img src="'+data[i].thumb+'" alt="thumbnail"></a></div>';
                $(container).append(ncode);
            });
        },
        error: function(xhr, type, exception) { 
            $(sfield).removeClass("loading");
            $(container).html("Error: " + type); 
        }
    });
}

If you’re acquainted with jQuery’s .ajax() function, these parameters will look familiar. We pass the user’s search term “q” as POST data. Both success and failure handlers remove the “loading” class and manage the response in the #photos section.

Within the success handler, we loop through the JSON data to create individual div elements using the $.each() function, targeting our response data array. The error handler straightforwardly displays any response errors from the API.

Live Instant Search Web App for Instagram Photos

View demo Download source

Concluding Insights

The Instagram team has excelled at scaling their application impressively. Although the API can occasionally be slow, the data is always well-formatted and straightforward to handle. This tutorial showcases the robust capabilities available when leveraging third-party applications.

Currently, Instagram search limits queries to a single tag, which is a restriction for our demo, but it doesn’t diminish its appeal. Explore the live example above and download the source code to experiment further. We’d love to hear your thoughts in the post discussion area below.

WebsiteFacebookTwitterInstagramPinterestLinkedInGoogle+YoutubeRedditDribbbleBehanceGithubCodePenWhatsappEmail