Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Get Instagram media on WordPress using the current Instagram (Facebook) API (details: https://www.gsarigiannidis.gr/instagram-feed-api-after-june-2020/)
<?php
/**
* Get Instagram media on WordPress using the current Instagram (Facebook) API
*
* @param $token // Info on how to retrieve the token: https://www.gsarigiannidis.gr/instagram-feed-api-after-june-2020/
* @param $user // User ID can be found using the Facebook debug tool: https://developers.facebook.com/tools/debug/accesstoken/
* @param int $limit // Add a limit to prevent excessive calls.
* @param string $fields // More options here: https://developers.facebook.com/docs/instagram-basic-display-api/reference/media
* @param array $restrict // Available options: IMAGE, VIDEO, CAROUSEL_ALBUM
*
* @return array|mixed // Use it like that (minimal example): get_instagram_media(TOKEN, USER_ID);
*/
function get_instagram_media(
$token,
$user,
$limit = 10,
$fields = 'media_url,permalink,media_type,caption',
$restrict = [ 'IMAGE' ]
) {
// The request URL. see: https://developers.facebook.com/docs/instagram-basic-display-api/reference/user
$request_url = 'https://graph.instagram.com/' . $user . '?fields=media&access_token=' . $token;
// We use transients to cache the results and fetch them once every hour, to avoid bumping into Instagram's limits (see: https://developers.facebook.com/docs/graph-api/overview/rate-limiting#instagram-graph-api)
$output = get_transient( 'instagram_feed_' . $user ); // Our transient should have a unique name, so we pass the user id as an extra precaution.
if ( false === ( $data = $output ) || empty( $output ) ) {
// Prepare the data variable and set it as an empty array.
$data = [];
// Make the request
$response = wp_safe_remote_get( $request_url );
$response_body = '';
if ( is_array( $response ) && ! is_wp_error( $response ) ) {
$response_body = json_decode( $response['body'] );
}
if ( $response_body && isset( $response_body->media->data ) ) {
$i = 0;
// Get each media item from it's ID and push it to the $data array.
foreach ( $response_body->media->data as $media ) {
if ( $limit > $i ) {
$request_media_url = 'https://graph.instagram.com/' . $media->id . '?fields=' . $fields . '&access_token=' . $token;
$media_response = wp_safe_remote_get( $request_media_url );
if ( is_array( $media_response ) && ! is_wp_error( $media_response ) ) {
$media_body = json_decode( $media_response['body'] );
}
if ( in_array( $media_body->media_type, $restrict, true ) ) {
$i ++;
$data[] = $media_body;
}
}
}
}
// Store the data in the transient and keep if for an hour.
set_transient( 'instagram_feed_' . $user, $data, HOUR_IN_SECONDS );
// Refresh the token to make sure it never expires (see: https://developers.facebook.com/docs/instagram-basic-display-api/guides/long-lived-access-tokens#refresh-a-long-lived-token)
wp_safe_remote_get( 'https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=' . $token );
$output = $data;
}
return $output;
}
@thiagobraga

This comment has been minimized.

Copy link

@thiagobraga thiagobraga commented Jul 20, 2020

Thank you friend, your post helped me a lot. I've used your implementation in JavaScript and it worked perfectly. Facebook has made this process of obtaining data from the API increasingly bureaucratic. It seems that it is not for anyone to use.

@esbenholk

This comment has been minimized.

Copy link

@esbenholk esbenholk commented Aug 1, 2020

This is perfect! @thiagobragga, i am also very interested in hearing how the js syntax has played out for you?

@gsarig

This comment has been minimized.

Copy link
Owner Author

@gsarig gsarig commented Aug 1, 2020

@esbenholk
If you want to use it with JavaScript, and given that we always need it on a WordPress implementation, the simplest way I could think of, would be to simply pass the output of the PHP function to your script using wp_localize_script().

@thiagobraga

This comment has been minimized.

Copy link

@thiagobraga thiagobraga commented Aug 3, 2020

This is perfect! @thiagobragga, i am also very interested in hearing how the js syntax has played out for you?

Hi friend, I created this Gist. There's some code specific from my project, like the render() function or some jQuery selectors, I'm sorry 🤷‍♂️
Maybe I cleanup sometime lol. I hope it helps anyway!

https://gist.github.com/thiagobraga/0794a33f908eef48d590d19d95fe5e75

@LukeVibes

This comment has been minimized.

Copy link

@LukeVibes LukeVibes commented Dec 16, 2020

First of all, incredible article. Well written, well coded. One of the only websites explaining this annoying change by Facebook so well :).

My one worry is how you use Transients. According to the WordPress documentation:
transient expiration times are a maximum time. There is no minimum age. Transients might disappear one second after you set them, or 24 hours, but they will never be around after the expiration time.

So it seems possible for the call to be made many times within an hour, as the hour parameter is only acting as a maximum time to wait. Am I misunderstanding something?

@gsarig

This comment has been minimized.

Copy link
Owner Author

@gsarig gsarig commented Dec 16, 2020

First of all, incredible article. Well written, well coded. One of the only websites explaining this annoying change by Facebook so well :).

My one worry is how you use Transients. According to the WordPress documentation:
transient expiration times are a maximum time. There is no minimum age. Transients might disappear one second after you set them, or 24 hours, but they will never be around after the expiration time.

So it seems possible for the call to be made many times within an hour, as the hour parameter is only acting as a maximum time to wait. Am I misunderstanding something?

Hi Luke, and thank you for your comment.

Indeed, you can't rely on transients for time sensitive data, as they can be deleted by a plugin or some other unexpected factor. On that particular case, though, they seem like a nice fit, as we only use them to make sure that no excessive calls will be made. Doing a few more calls withing the timeframe of an hour, which is Instagram's limit, won't hurt, as it is highly unlikely that they will be enough to exceed the limit.

On that note, one improvement that I want to make at some point (probably during Christmas, when hopefully I'll find some free time) is to locally download and store the photos and their IDs. That way, we can have a fallback in case the API call fails to fetch all the photos (on which case we would have to wait an hour until we re-fetch them) and we could also minimize the API calls, avoiding to re-fetch already existing photos, or even further optimize them locally.

@LukeVibes

This comment has been minimized.

Copy link

@LukeVibes LukeVibes commented Dec 16, 2020

Ah yes! Storing this data Locally as a back-up would be a great idea! Thanks for the response!

Also where do you recommend this code be placed? I am not a WordPress pro (yet) so I'm still not very confident on where to best house this kind of code within a WordPress structure.

@gsarig

This comment has been minimized.

Copy link
Owner Author

@gsarig gsarig commented Dec 17, 2020

Ah yes! Storing this data Locally as a back-up would be a great idea! Thanks for the response!

Also where do you recommend this code be placed? I am not a WordPress pro (yet) so I'm still not very confident on where to best house this kind of code within a WordPress structure.

As a general principle, I would store this in a plugin. For my personal use, I've included it on DareDev, the mu-plugin that I use on most of my sites. In general, anything that has to do with the site's appearance should go to the theme (e.g. the functions.php), and functionality should be on plugins. That way, you can keep the functionality when switching themes.

@Jamiewarb

This comment has been minimized.

Copy link

@Jamiewarb Jamiewarb commented Apr 19, 2021

Thanks, this was super helpful. Instagram don't make it clear how to do this unless you know exactly what you're looking for

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment