While writing the blog post for the workshop air filter that I made, I noticed that the usual Instagram feed that I’ve placed on the bottom of my website was missing and I knew that I haven’t touched that part of the site in more than a year.
I quickly opened up the developer tools on the browser by pressing F12 on the keyboard and I was very happily greeted with a message that said “This endpoint has been retired”.
SLOW CLAP!
Well, congratulations on your retirement. Now what?
Based on that message I noticed that the error comes for a file called instafeed.js and I remembered that I’ve used that library when I was building the site.
Looking through the code of my site, I found the part where I first load Instafeed, and then I located the other script where I actually initialize it to load 12 of the latest images from Instagram and show them based on the specified template.
To be able to access my feed, I have provided an API key to the script, and from what I could see this should have still been working. If for some reason you don’t know what an API key is, Tom Scott has an excellent video on the topic.
OK, so the conclusion is that Instagram changed something. OK, fair enough, I’m sure that Instafeed is on top of this and that they have an updated version that I can just replace and it will all work again in 5 minutes.
Well, as it turns out, it won’t be as easy as just switching to another script. The old Instagram API no longer works and it is now replaced with the Basic Display API where the biggest difference is the authentication process used to access the API.
The old one used an API key that was sent with each request to provide it info who accessed it. The Basic Display API replaces this with OAuth where a physical user now needs to log in and approve an application, to then get an access token. This access token is then used to make the API request but that token will eventually expire and a new one will then be needed.
Exactly how OAuth works is a topic for a separate article but what is important to know now, is that we will need some piece of server code that will periodically contact Instagram to refresh the token.
Instafeed recommended solution is to use an Instagram Token Agent, which is a separate app that you can run as a service on Heroku for free, at least for now, that will then refresh and keep track of access tokens.
No, thank you!
I already manage my site that is built with Laravel, so the idea to have a separate service and manage that just for showing an Instagram feed to my site sounds like too much work so I looked for other options and I came across a Laravel package that claims to be able to do the same process from Laravel.
The package is called Laravel Instagram Feed and it is built by a marketing agency from Taiwan called Dymantic.
The process with the integration of this package starts by first installing it to our project through Composer. This can take a few minutes based on your network and computer speed but in the meantime, we can go and set up the Facebook app required for the OAuth flow to work.
First, you can navigate to developers.facebook.com, where we need to create an app. On the create popup, select the last option that says “Something else” and then enter the application name.
Once this is created, we need to add the Basic Display API as a product to the app, so to do that, we need to add a platform to our app that we just created. This platform is just the place where your app will be used and in my case, this is my website so I choose “Website” as the platform.
The only thing you need to add here is the full URL of your website and click save.
We can now return to the Basic Display setup page and create an Instagram app for it. This will give us an App ID and a Secret key that we will need to set up in the config file of the package.
By now, the package should be installed and we need to first publish its vendor assets by running php artisan vendor:publish and choosing the right package number and then run the migrations of the package with php artisan migrate.
To start setting up the package configuration, we can open the “instagram-feed.php” configuration file where we first need to set up our App ID and secret key from before. These will be stored in the .env configuration file and be included here through the env helper method.
Never, ever, add the service keys, or any other keys, directly in the files and commit them to your repositories. Bad things will happen!
In the configuration file, we also have the redirect URL that this package provides, and this one is used to store the tokens provided by Instagram after a successful authorization. We need to copy this URL and go back to the Basic Display API setup screen where we need to enter this along with the full domain of our site.
When setting up these URLs, keep in mind that OAuth will only work with HTTPS or localhost URLs so in your local environment, if you use virtual hosts you will need to have the site running with an SSL. I use Laragon for this and the SSL is set up by default.
So now that we have the app ready, the package installed and the config and URLs setup, we need to start the process of connecting it all up inside our own Laravel website.
The Instagram feed package works with so-called profiles that are just entities that we need in order to associate the tokens with. The package provides a model that fits this role so we first need to create one and for that, there is a command that the package provides.
We can run php artisan instagram-feed:profile {username}, where username will be tastethecode in my case and that creates the necessary record in the database.
On this profile model, there is now a method available, getInstagramAuthUrl, that we can call in order to get the full authentication URL that we need for Instagram.
To get the output of that method I’ll be using Tinker, and if you don’t know, Tinker is a Laravel console tool that allows you to interact with your application from the command line. You can basically do anything and execute any code against your app, so that is exactly what I’ll do.
I’ll first retrieve the model that we just created and I’ll then execute the method from before in order to get the URL for authentication.
Before we access this through the browser, we need to do one more thing over at the Facebook application and that is to add my Instagram account as a tester to the application. In this case, I don’t want the application to be public so only added users can actually pull data through it.
To add a test user, navigate to the Roles section of the Facebook application you’ve created and scroll down to Instagram testers. Here click on Add Instagram Testers and enter your Instagram account username.
Next, log in to Instagram in the browser and navigate to Edit Profile > Apps and Websites > Tester Invites where you will see your invite and you will have to accept it.
We can now copy the link that we generated for the authentication and open that up in the browser. This will show the authorization screen from Instagram where we now need to allow our application to access our profile information.
When we click on Authorize, if everything goes well, we will be redirected back to our website to a URL that indicates success, but since we don’t have a route for it, the website will show a 404 page which is OK as the tokens were still saved.
We can confirm this by going to the database and inspecting the tokens table where we should see the token for our user and we can also go back to the console and by calling the feed method on the created profile we can get the 10 latest Instagram images as a response.
Now that we have everything ready we can proceed with displaying our feed, back to the same place on the website.
So first, I removed all the JavaScript code that was connected with Instafeed but I used the template that I had created to create a blade template with the same HTML.
This blade template is included everywhere that I want the feed to be displayed so I can keep it centralized for management. Here, I first check if the feed is present in the view data and if it is, I loop through all of the images retrieved, and display an image for each.
<div class="row no-gutters popup-gallery" id="instafeed">
@isset($data['instagram_feed'])
@foreach ($data['instagram_feed'] as $item)
<div class="col-xl-1 col-lg-2 col-sm-3 col-4">
<a href="{{ $item['permalink'] }}" target="_blank" class="portfolio-box">
<img src="{{ $item['url'] }}" class="img-fluid" alt="" style="width: 100%;height: 100%">
</a>
</div>
@endforeach
@endisset
</div>
The anchor tag “href” attribute, gets populated with the permalink to the post on Instagram while the image tag that it surrounds is populated with the actual URL of the post image.
The view data is populated by first retrieving the profile that we created with the feed package and then I’m calling the feed method with the number of images that I want to show.
This data needs to be added everywhere where you will want to display the feed but it can also be done with view composer but that is a topic for another video.
To finish off the integration, we need to add two more things to the Laravel scheduler. The Laravel scheduler is a mechanism that exists inside the framework that is able to execute a piece of code on a regular basis.
The first thing that we need to add is the code that will periodically refresh the feed since the method that we used for displaying will only get the feed once, cache its return and then display the feed from cache every time it is called.
To make sure that we periodically get the new posts from Instagram we need to call the refreshFeed method which will replace the cache with the newest posts from Instagram. I choose to add this call to be executed twice per day as I don’t post more often than that and I can live with the feed being off by a few hours but you can choose any frequency that you want.
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
try {
Profile::where('username', 'tastethecode')->first()->refreshFeed(12);
} catch (Exception $e) {
Log::error('Failed retrieving Instagram feed', ['message' => $e->getMessage()]);
}
})->twiceDaily();
$schedule->command("instagram-feed:refresh-tokens")->monthlyOn(15, '03:00');
}
The second and last thing that we need to add is another call inside the Laravel scheduler to a command that the Instagram feed package provides, ‘instagram-feed:refresh-tokens’ that handles the refresh of the OAuth access tokens.
The initial token that Instagram provided in the first authorization is only valid for up to 60 days so we need to periodically refresh it with a special call before that. For the sake of convenience, I choose to refresh it once per month on the 15th day of the month at 3 AM so it is outside of most of the visits on the site when the server is idle.
Now, I know that this was maybe sounding a bit complicated and that it might scare you at first depending on the experience you have but that should not deter you from achieving what you want. Follow it step by step and go back, watch the video once again while repeating the steps on your end and you should be fine.
If for any reason you stumble upon any issues, let me know down in the comments and I’ll do my best to help you out.
If you want to help me, then hit the subscribe button, ring the bell, and of course like and share this video with your friends. If you want to help me even more, head out to Patreon where you can support the channel on a monthly basis for as low as $1.
That was all for today, I hope you enjoyed it and I’ll see you all in the next one.
All of my sites are hosted on Dreamhost and by clicking on the link below you can get 50% off!!!
https://www.dreamhost.com/r.cgi?2405711/promo/dreamsavings50/