This is part two of a series on the Instagram API. In this tutorial, I'll guide you through using Instagram's Media Endpoints, which allow you to search for popular images from a specific time and place.
You can download code for each episode by using the GitHub repository link in the sidebar. You may also be interested in my two-part Tuts+ series, Locating Potential Crime Scene Witnesses With Social Media APIs.
The code for these tutorials is written in PHP using the Yii Framework. You can learn more about Yii in Introduction to the Yii Framework (Tuts+) and in the Programming With Yii2 Series (Tuts+). You can also easily adapt the code segments for your own PHP application.
I do participate in the discussions. If you have a question or topic suggestion, please post a comment below. You can also reach me on Twitter @reifman or email me directly.
Let's begin by registering as a developer with Instagram.
Getting Started
To get started, visit the Instagram API page for developers and click Register Your Application:
You'll need to sign up for a developer account:
Then you can register a new application to receive your Client ID:
On the Manage Clients dashboard, you'll see your Client ID and Client Secret, so make note of these:
Using the Media Endpoints
As web service APIs go, the Instagram API is robust, and in my experience works very well. Instagram offers a handful of API endpoints:
For this tutorial, we'll focus on the Media endpoints:
With Media endpoints, you can retrieve information about an Instagram photo or video by referencing its ID or the shortcode from its URL, e.g. 0EyZ53Ja9X from https://instagram.com/p/0EyZ53Ja9X. It also provides geosearch capabilities to find media posted from a specific time and place as we did in Locating Potential Crime Scene Witnesses With Social Media APIs. And finally, it allows you to retrieve popular, trending Instagram posts.
The API Console
To help you get started and debug, Instagram has an API console powered by Apigee:
You can try out queries against the Media endpoints using the API console. Here's an example result for media/popular:
Obviously, you can see how useful this is for working with media from the popular mobile photography service.
Let's move on to installing our sample codebase and configuring it to work with your Instagram client application.
Installing the Codebase
For this series, I'm going to continue to build on the Eyewitness codebase from Locating Potential Crime Scene Witnesses With Social Media APIs. You can clone the GitHub repository located in the sidebar to run our sample code.
cd ~/Sites/eyew https://github.com/link-in-sidebar/eyew.git
You'll need to configure your local Apache configuration. I use MAMP, so it looks something like this:
cd /Applications/MAMP/htdocs ln -s ~/Sites/eyew/web /Applications/MAMP/htdocs/eyew
You need to create a database locally. I use PHPMyAdmin to create one graphically:
Then I create an initialization file in /var/secure/eyew.ini
with my database credentials and Instagram IDs and keys. I described this process recently in another Tuts+ tutorial: Protecting Your Keys From GitHub.
My ini file looks like this:
mysql_host="localhost" mysql_db="eyew" mysql_un="xxxxxxxxx" mysql_pwd="xxxxxxxxxxxx" instagram_client_id = "4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7" instagram_client_secret = "1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4"
Update your Composer and its vendor libraries:
sudo composer self-update sudo composer update
Then initialize our database. The first migration installs user tables for our Yii2-User by developer Dmeroff extension, and the second creates our app-specific tables:
./yii migrate/up --migrationPath=@vendor/dektrium/yii2-user/migrations ./yii migrate/up
Again, you can learn more about setting up a Yii Framework application in my Programming With Yii2 series for Tuts+.
Here's the MySQL schema for our Instagram image table—we call it the Gram table. We'll use it to store geosearch results.
class m150308_184606_create_gram_table extends Migration { public function up() { $tableOptions = null; if ($this->db->driverName === 'mysql') { $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; } $this->createTable('{{%gram}}', [ 'id' => Schema::TYPE_PK, 'moment_id' => Schema::TYPE_INTEGER . ' NOT NULL', 'username' => Schema::TYPE_STRING . ' NOT NULL DEFAULT 0', 'link' => Schema::TYPE_STRING . ' NOT NULL DEFAULT 0', 'image_url' => Schema::TYPE_STRING . ' NOT NULL DEFAULT 0', 'text' => Schema::TYPE_TEXT . ' NOT NULL ', 'created_time' => Schema::TYPE_INTEGER . ' NOT NULL', 'created_at' => Schema::TYPE_INTEGER . ' NOT NULL', 'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL', ], $tableOptions); $this->addForeignKey('fk_gram_moment', '{{%gram}}', 'moment_id', '{{%moment}}', 'id', 'CASCADE', 'CASCADE'); }
The Home Page
I've renamed the sample application "Instapi", short for Instagram API.
Here's a look at what you should see when you visit the site in your browser:
Performing Media Searches
To implement media searches in our Instapi application, I'm using Galen Grover's Instagram PHP package.
Search Popular Images
First, let's implement a search for media/popular
. We'll query the API and display the results in a table.
I've created an action called popular in GramController.php:
public function actionPopular() { $gram = new Gram(); $media = $gram->searchPopular(); return $this->render('popular', [ 'media' => $media, ]); }
It calls searchPopular()
in the Gram.php model:
<?php namespace app\models; use Yii; use yii\db\ActiveRecord; use Instagram; ... public function searchPopular() { $instagram = new Instagram\Instagram; $instagram->setClientID( \Yii::$app->params['instagram']['client_id'] ); $media = $instagram->getPopularMedia(); return $media; }
In /views/gram/popular.php
, we set up an HTML table structure:
<?php use yii\helpers\Html; /* @var $this yii\web\View */ /* @var $searchModel app\models\InstagramSearch */ /* @var $dataProvider yii\data\ActiveDataProvider */ $this->title = 'Instagrams'; $this->params['breadcrumbs'][] = $this->title; ?> <div class="instagram-index"> <table class="table"> <thead> <tr class="small-header"> <td>Image ID</td> <td>User</td> <td >Thumbnail</td> <td >Caption</td> <td >Created at</td> </tr> </thead> <?php foreach ($media as $m) { echo $this->render('_item', [ 'm' => $m, ]); } ?> </table> </div>
and include the _item.php
partial view to display individual media results:
<tr> <td><a href="/eyew/gram/lookup/?id=<?= $m->id ?>"><?= $m->id ?></a></td> <td><a href="https://instagram.com/<?= $m->user->username ?>"><?= $m->user->username ?></a></td> <td><a href="<?= $m->link ?>"><img src="<?= $m->images->thumbnail->url ?>"></a></td> <td> <?php echo (isset($m->caption->text)?$m->caption->text:''); ?> </td> <td><?= $m->created_time ?></td> </tr>
Here are the results of Instagram media popular queries. Go ahead and refresh the page in your app. It's fun to see what comes up next.
Look Up Information About an Image or Video
I've linked the Instagram media ID in the first column to a controller action that calls the media endpoint which gets us more information:
public function actionLookup($id) { $gram = new Gram(); $media = $gram->lookup($id); print_r($media); }
Here's the lookup function in the Instagram model:
public function lookup($id) { $instagram = new Instagram\Instagram; $instagram->setClientID( \Yii::$app->params['instagram']['client_id'] ); $media = $instagram->getMedia( $id ); return $media; }
Here's a screenshot of the data dumped to the screen:
Obviously, you could use and store this information however you would like.
Search for Media From a Time and Place
Now, let's search for images from a specific time and place. For this example, I'll review our Eyewitness example.
Our codebase allows you to define a moment as a place and time. It consists of a friendly descriptor, a location (latitude and longitude), a start time and a duration (in minutes). For my first example, I'm looking for Instagram users who were present at Macklemore's video shooting on the evening of Wednesday, July 24, 2013 at Seattle's landmark Dick's Drive In.
Using Google Maps, I can get the GPS latitude and longitude for Dick's. It's 47.6195 -122.321.
From the article, I learned that the production shut down at 1 am. I'm going to choose a start time of 10 pm and a duration of 3 hours.
Instagram accepts start times in GMT so I've hardcoded an eight-hour time change adjustment from my timezone (PST). You may need to change this in the code.
public function actionCreate() { $model = new Moment(); if ($model->load(Yii::$app->request->post())) { // convert date time to timestamp $model->start_at = strtotime($model->start_at); // adjust for GMT $model->start_at+=(3600*8); // validate the form against model rules if ($model->validate()) { // all inputs are valid $model->save(); return $this->redirect(['view', 'id' => $model->id]); } else { return $this->render('create', [ 'model' => $model, ]); } } else { return $this->render('create', [ 'model' => $model, ]); } }
To search Instagram, just click on the camera icon below:
The actual search is fairly straightforward: $instagram->searchMedia( $this->latitude, $this->longitude,$params );
<?php namespace app\models; use Yii; use yii\db\ActiveRecord; use app\models\Gram; use Instagram; ... public function searchInstagram() { $instagram = new Instagram\Instagram; $instagram->setClientID( \Yii::$app->params['instagram']['client_id'] ); $end_at = $this->start_at + ($this->duration*60); $params = array('min_timestamp'=>$this->start_at,'max_timestamp'=>$end_at,'distance'=>$this->distance,'count'=>50); $media = $instagram->searchMedia( $this->latitude, $this->longitude,$params ); foreach ($media as $m) { if (isset($m->caption->text)) { $caption = $m->caption->text; } else { $caption =''; } $i = new Gram(); $i->add($this->id,$m->user->username,$m->link,$m->created_time,$m->images->thumbnail->url,$caption); } }
The results are stored in the Gram table, which we can then browse:
public function add($moment_id,$username,$link,$created_time,$image_url,$text) { if (!Gram::find()->where(['moment_id' => $moment_id])->andWhere(['link'=>$link])->andWhere(['created_time'=>$created_time])->exists()) { $i = new Gram(); $i->moment_id = $moment_id; $i->username = $username; $i->link = $link; $i->created_time = $created_time; $i->image_url = $image_url; $i->text = $text; $i->save(); } }
Here's the first page of results from my search. You can see the crowds and Macklemore's Cadillac limo driving up.
Then on page three, an Instagram user named Joshua Lewis has a shot of Macklemore exiting the Cadillac:
Here's Macklemore:
This example clearly shows the power that the Instagram search API provides. In just a few moments, we found a variety of eyewitnesses to an event from the summer of 2013.
What's Next?
I hope you've enjoyed learning about the Instagram API thus far. In the next episode, we'll explore OAuth authentication so that we can query areas of the Instagram service that require user authorization.
In the meantime, please feel free to post your questions and comments below. You can also reach me on Twitter @reifman or email me directly. You can also browse my Tuts+ instructor page to see other tutorials I've written.
Related Links
- The Instagram API
- The Instagram Developers Blog
-
Locating Potential Crime Scene Witnesses with Social Media APIs
- Yii2 Developer Exchange
The preview image is modified from a result that came up in our API search.
Comments