Jump to content

InstagramBasicDisplayApi


nbcommunication

Recommended Posts

Thanks @Stefanowitsch,

That confirms that the issue is occurring when it tries to JSON encode the data. I'm happy for you to send the print_r() data via direct message if you want me to take a closer look. I also wonder whether trying to log serialize($data) would work, if so that output would be easier for me to work with.

Cheers,

Chris

  • Like 1
Link to comment
Share on other sites

Tutorial Time!

So finally I was able to make fetching the Instagram data work. And here's my tutorial how to achieve this.

These are my requirements:

- Load images from an instagram account and append them into a carousel slider on a website
- To reduce loading times and file sizes I want to apply a "scrollspy" behaviour that only fetches data when the carousel is about to enter the viewport 
- I only load a certain amount of data and once the user is about to reach the end of the carousel, new data is fetched and appended automatically

Using the UIKit framework comes in handy here. I am in fact using the UIKit slider component in combination with the UIKit scrollspy component here.

Let's start:

1. This piece of code has to be implemented at the very top of your template PHP file (in my case it's the home.php)

What this code does is basically: "If the this page is requested through an ajax all then get the media from the instagram account, print it out and then stop processing the rest of the template code."

<?php

$instagram = $modules->get('InstagramBasicDisplayApi');

if($config->ajax) {
    echo $instagram->getImages('USERNAME',6); // change USERNAME to the name that is authorized in the InstagramBasicDisplayApi module settings
    die();
}
?>

2. This is the HTML markup for our slider carousel (using the UIKit slider). Put it into the same template that has the code above.

<section class="instagram-feed" uk-scrollspy="cls:uk-animation-slide-bottom">
    <div class="uk-container">
        <div class="uk-text-center">
            <h2>MY INSTAGRAM FEED</h2>
        </div>
        <div class="insta-spinner uk-text-center uk-flex uk-flex-column uk-flex-middle">
            <div uk-spinner="ratio: 2"></div>
            <p><b>Loading data...</b></p>
        </div>
        <div uk-slider>
            <div class="uk-position-relative">
                <div class="uk-slider-container uk-margin">
                    <ul class="uk-slider-items uk-child-width-1-2 uk-child-width-1-5@m uk-grid" uk-scrollspy="target: > li > .last-item">
                    </ul>
                </div>
                <div class="uk-visible@s">
                    <a href="#" class="slider-arrow uk-position-center-left-out uk-position-medium" uk-slider-item="previous"><img src="/site/templates/images/icons/icon-arrow-left.svg" width="30" height="30" alt="Pfeil Links" loading="lazy"></a>
                    <a href="#" class="slider-arrow uk-position-center-right-out uk-position-medium" uk-slider-item="next"><img src="/site/templates/images/icons/icon-arrow-right.svg" width="30" height="30" alt="Pfeil Rechts" loading="lazy"></a>
                </div>
            </div>
            <ul class="uk-slider-nav uk-dotnav uk-flex-center uk-margin"></ul>
        </div>
    </div>
</section>

Note:

- I am using a loading spinner right away, this will be removed later on when data is fetched.
- We are implementing the scrollspy component for the whole markup block. So when this block enters the viewport an event is fired that allows us to then start fetching data.
- We are also implementing the scrollspy component that looks for the <li> with the "last-item" class. This will be our indicator for appending new data later on.
- There are currently no <li> elements! That is of of course what we desire. We will load images from instagram and create those <li> elements on the fly.

3. This is the script that will fetch data and append the new carousel items. Put this code below the HTML markup or in a separate JS file:


<script>

    document.addEventListener("DOMContentLoaded", () => {

        let feed = document.querySelector('.instagram-feed');
        let sliderList = document.querySelector('.uk-slider-items');
        let spinner = document.querySelector('.insta-spinner');

        // listen for the scrollspy 'inview' event and execute this function if the carousel element comes into the viewport
        feed.addEventListener('inview', () => fetchData());

        // create new carousel items and append them to the carousel
        let appendSlides = function(data) {

            data = JSON.parse(data);

            data.forEach((item) => {
                let image = document.createElement('li');
                image.innerHTML = `<a href="${item.link}" target="_blank" rel="noopener" class="uk-display-block uk-height-1-1 uk-position-relative"><img src="${item.src}" alt="${item.alt}"/></a>`;
                sliderList.appendChild(image);
            });

            // add new 'last-item' class to the second last carousel item so that new data is fetched when this element comes into the viewport
            const lastItem = sliderList.querySelector('li:nth-last-child(2) > a');
            lastItem.classList.add('last-item');

            // listen for the scrollspy 'inview' event and execute this function if the last carousel item comes into the viewport
            if (lastItem) {
                lastItem.addEventListener('inview', () => fetchData());
            }

        };

        // Make an ajax request using the fetch API 
        async function fetchData() {

            try {
                const response = await fetch(window.location.href, {
                    method: 'GET',
                    headers: {
                        'X-Requested-With': 'XMLHttpRequest'
                    }
                });

                let data = await response.text();
                
                // Once data is received pass this data to our function to generate the carousel items
                appendSlides(data);
                
                // and don't forget to remove the loading spinner!
                spinner.remove();

            } catch (error) {
                console.error(error);
            }
        }

    });

</script>

 

That's it! If everything works correctly it should look like this:

image.gif.2caa7a90d796a4ea0798720c6c61b482.gif

  • Like 3
Link to comment
Share on other sites

  • 9 months later...

Hey,

one of my feeds stopped working. I renewed the token, but it's not working - But I've noticed this message one Facebooks "Basic Display" page:

1620962955_2024-08-0119_57_05-PWimagefeed-InstagramBasicDisplay-MetaforDevelopers.thumb.png.b44430c51312b094f80f4167ba98c078.png

Anyone else having this problem?

This is how the module-page looks like:

777139580_2024-08-0120_06_41-Module_InstagramBasicDisplayAPIMozillaFirefox.thumb.png.57ae6918af161cdef8e26dd907de02d1.png

@nbcommunication Any ideas?

 

Link to comment
Share on other sites

Hi @DV-JF,

Unfortunately I suspect this may mean an end to this module being able to function. The impression I'm getting here is that the Basic Display API applications now need to be submitted for review/approval. This module took advantage of FB allowing development applications if they were created 'solely for the purpose of generating access tokens with the User Token Generator'.

It really isn't clear however.

When I try to generate an access token in the User Token Generator I get an error page on the Instagram pop-up window. I don't know whether this is because there's an issue on their end, because of the permissions thing you've highlighted, or something else.

The next token renewal we have on a site using this module is in two weeks, so it'll be then before we come up against this issue.

I'm going to ask a colleague to set up an application from scratch and see if he comes up against any issues, or other information that might shed some light on this.

Will keep you updated on what we find.

Cheers,

Chris

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Hi,

Initial findings aren't positive unfortunately. In our application, whenever I try to generate a User Token I get an Error message on the Instagram popup. I got a colleague to create an application from scratch in a FB dev account not associated with our business one, and we also got the same error when trying to generate a token.

There's a message in the App Review section indicating that reviews are delayed for Instagram apps due to volume, which suggests that they've recently made it necessary to submit for App Review and there are a lot of people scrambling to get this done.

We're going to investigate further and see if we can find some more information about this, perhaps getting confirmation through developer support and/or the community help.

If this is what is going on, this module will still work for 'Live' (reviewed) applications, but my understanding is that the process is a likely a lot of jumping through hoops, and completely overkill for what the application is trying to achieve. It isn't something we'd be attempting willingly!

Cheers,

Chris

  • Sad 2
Link to comment
Share on other sites

Hi, 

Some good news: we did manage to generate a User Token without app review, after setting a new application up from scratch. It's quite possible this bug is not connected to potential changes in the App Review policy, as initially feared.

Similar issues have been reported:

https://stackoverflow.com/questions/76473468/instagram-basic-display-api-cant-generate-access-token

https://developers.facebook.com/support/bugs/185012584505063/

https://developers.facebook.com/community/threads/636065331832545/

We will keep an eye on this.

Thanks,

Mark

  • Like 1
Link to comment
Share on other sites

Hi @DV-JF,

I've just checked in on one of our sites using this module and its token has renewed again. 

I was definitely having issues with the FB/META/IG API stuff last week, so my preferred explanation is that there have been issues on that end that's prevented token generation and renewal.

Are you still having an issue?

Cheers,

Chris

Link to comment
Share on other sites

  • 5 weeks later...

Meta is going to disable Instagram Basic Display API, starting on December 4th, 2024. I'm trying to figure out what to do next.

(Two weeks ago I was trying to use this module for the first time, for a client of mine, and the process of setting up an app with them is nuts, with the amount of data they ask from us and the confusing and complex interface of their developer thingy...)

Thanks for the module, Chris.

  • Sad 2
Link to comment
Share on other sites

Hi @tomasanjosbarao,

Thanks for letting us know. I'm not surprised!

I'm going to investigate https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login to see if this will be usable for the same purpose, and if it is, will try and get a new module together before 4/12/24!

Cheers,

Chris

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

@tomasanjosbarao Thank you for sharing this info and thank you – @nbcommunication – for further investigation. It would be great to see a new module👌

The first limitation a I see is this:

Quote

The Instagram API with Instagram Login allows Instagram professionals — businesses and creators — to use your app to manage their presence on Instagram.

Source: https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login

  • Like 1
Link to comment
Share on other sites

Hi @DV-JF,

So the limitation is that it isn't for use by personal accounts? For our use cases, I think every one is a business (and should have a business account), so I'll still explore it, but I can understand that'll be frustrating for those using this module for personal projects.

I don't think it takes much to switch to a business account - both the band accounts I have access to on Instagram are business accounts, I think it is just a case of specifying that? Or at least it was when these were set up years ago. Given the maze of Meta requirements it wouldn't surprise me if you need to submit yearly accounts to get a business account now...

Cheers,

Chris

  • Like 1
Link to comment
Share on other sites

10 minutes ago, nbcommunication said:

I don't think it takes much to switch to a business account - both the band accounts I have access to on Instagram are business accounts, I think it is just a case of specifying that? Or at least it was when these were set up years ago. Given the maze of Meta requirements it wouldn't surprise me if you need to submit yearly accounts to get a business account now...

I'm just reading the docs:

https://help.instagram.com/502981923235522
https://www.facebook.com/help/instagram/138925576505882?helpref=faq_content

I haven't read anything about any restrictions that would prevent a "normal Instagram account" from being converted into a business account, yet.

10 minutes ago, nbcommunication said:

So the limitation is that it isn't for use by personal accounts?

As I read the documentation, this seems to be the case.

https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/overview

Quote

Limitations

  • This API is only available for Instagram professional accounts
  • This API doesn't support ads, insights or tagging

 

  • Like 1
Link to comment
Share on other sites

After strolling aroung the chaotic interface of the Facebook Developers platform, I could find the place to create an Access Token. Seems you need to add the app "Instagram API with Instagram Login" and not anymore the "Instagram Basic Display".

Once you have the access token and authorize it:

$http = new WireHttp();
$http->setData([
	// Choose the fields you want; you will need the user_id at least
	'fields' => 'user_id,username,followers_count,follows_count,media_count,profile_picture_url',
	'access_token' => $igAccessToken,
]);
$response = $http->get('https://graph.instagram.com/v20.0/me');

if ($response !== false) {

  // The answer comes as JSON, I cast it to an array so I could store it in ProcessWire's cache
  $profile = (array)json_decode($response);

} else {
	
	// Your error procedure here

}

The response will be like:

[
  'user_id' => '17941778910156051',
  'username' => 'yourusername'
  'followers_count' => 1560
  'follows_count' => 294
  'media_count' => 231
  'profile_picture_url' => '...'
  'id' => '3317109405575570'
]

Pay attention to the "user_id": it is a scoped, temporary ID (valid for one hour, I guess) that you'll need to insert on the URL to finally get the posts on a subsequent request, like this:

$newHttp = new WireHttp();
$newHttp->setData([
  'fields' => 'id,caption,media_url,media_type,timestamp,permalink,thumbnail_url', // Again, choose what you need
  'limit' => '14', // Optional
  'access_token' => $igAccessToken, // The same as before
]);
$newResponse = $newHttp->get('https://graph.instagram.com/v20.0/'.$profile['user_id'].'/media');

if ($newResponse !== false) {

  // Once again this is my preference, you can use it as an object
  $posts = (array)json_decode($newResponse);

} else {
	
	// Your error procedure here

}

And by doing this I am not needing your module anymore.

Hope this is useful, and hope they don't change things too much soon.

Edited by tomasanjosbarao
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...