🍿 5 min. read

How to Add Instagram Timeline To a NextJS Site

Monica Powell

I recently added an Instagram timeline to my site In Digital Color and wanted to share how I added the Instagram integration to my NextJS site and document some of the hiccups I encountered along the way with authentication.

Screenshot of Instagram Timeline integration on indigitalcolor.com

Install and import instagram-web-api

We'll use the instagram-web-api npm package to do the heavy lifting for the integration. which should be installed within a NextJS site with npm install instagram-web-api or yarn add instagram-web-api. Once the package is successfully installed it should be imported into index.js file (or whichever page you would like the Instagram feed to appear on) with:

1import Instagram from "instagram-web-api"

At this point the index.js file where I imported instagram-web-api looks like this:

1import Instagram from "instagram-web-api"
2import Layout from "../components/layout"
3
4export default function Index() {
5 return <Layout>{/*Other Page Content*/}</Layout>
6}

Setup getStaticProps to Fetch Data at Build Time

Next, we need to set up a way to get fetched data into our component. In this case, I chose to use the async getStaticProps function to pass data into our component.getStaticProps is a function available to pages within NextJS that allows data to be fetched at build time and passed into page-level components.

1import Layout from "../components/layout"
2import Instagram from "instagram-web-api"
3
4// empty array of instagram posts is being
5// passed as a prop into the Index component
6export default function Index({ instagramPosts }) {
7 return <Layout>{/*Other Page Content*/}</Layout>
8}
9
10export async function getStaticProps(context) {
11 // set posts to an empty array as a placeholder
12 let posts = []
13 return {
14 props: {
15 // return the posts as the prop instagramPosts
16 // for the Index function to use
17 instagramPosts: posts,
18 },
19 }
20}

Setup Instagram Client Authentication

Before we can retrieve data from Instagram we should set up authentication instagram-web-api in getStaticProps() to be able to fetch data from Instagram. We can accomplish this by setting up a new Instagram client with new Instagram({username: IG_USERNAME, password: IG_PASSWORD}) and attempting to log in with await client.login()

1export async function getStaticProps(context) {
2 // create a new client to communicate with Instagram
3 // this service requires authentication
4 //with username and password parameters
5 const client = new Instagram({
6 username: process.env.IG_USERNAME,
7 password: process.env.IG_PASSWORD,
8 })
9
10 let images = []
11 try {
12 // attempt to log in to Instagram
13 await client.login()
14 } catch (err) {
15 // throw an error if login to Instagram fails
16 console.log("Something went wrong while logging into Instagram", err)
17 }
18
19 return {
20 props: {
21 instagramPosts: images,
22 },
23 }
24}

Credentials such as the password should be accessed via environment variables that are only available locally and at build time to avoid exposing this information. In NextJS, local environment variables can be accessed by creating a file entitled .env.development.local. Although the username is not a secret you can add it to the environment file if you'd like. env.development.local should be added to your .gitignore file to avoid committing it to version control. Separately, I set up my hosting to have access to the appropriate secrets at build time which supersedes the values in the .env file.

My env.development.local file looks like this:

1IG_USERNAME="super_cool_username"
2IG_PASSWORD="super_secret_secure_password"

In addition to the env.development.local at a minimum you should have a .env file that sets the defaults for env variables. My .env file looks like and is checked into version control:

1IG_USERNAME=""
2IG_PASSWORD=""

Confirm Instagram Client is Functional

If you're not already you should run the development server of your NextJS site with npm run next and check in the terminal that is running the server to see if there are any console errors. You might encounter the error log we added of "Something went wrong while logging into Instagram" during this stage of the process.

Resolving 4xx Authentication Errors

While I was setting up the Instagram client with the correct credentials I encountered various 4xx authentication relates errors (if you're not familiar with HTTP status codes check out my site https://www.httriri.com/) being returned to Instagram saying "Please wait a few minutes before trying again". I was able to temporarily circumnavigate the 4xx errors and "Please wait a few minutes before trying again" message by switching my IP address with a VPN (Virtual private network) and attempting to authenticate again. A VPN allows you to access the internet with a remote VPN server's IP address as opposed to your local IP address. This article shares other ways you can change your IP address. I already had a VPN configured on my computer so I found that to be the most straightforward solution in my case. Using a VPN to access the internet resolved the issues I was encountering as they were IP address level issues. You can check if your issues are IP level by trying to log into Instagram manually on the same IP address and on another device that is connected to a separate cellular network (and has its own IP). I am wondering if there's a more official way to get Instagram to recognize API usage as not being unusual activity. If you are running into a 4xx error for a different reason this is a good time to manually confirm that the credentials you are providing are correct.

Request Timeline Data from Instagram

Once authentication is successful we can request specific data from Instagram calling client.getPhotosByUsername({username: process.env.IG_USERNAME}) to fetch timeline data for the username that is passed in.

1export async function getStaticProps(context) {
2 const client = new Instagram({
3 username: process.env.IG_USERNAME,
4 password: process.env.IG_PASSWORD,
5 })
6
7 let posts = []
8 try {
9 await client.login()
10 // request photos for a specific instagram user
11 const instagram = await client.getPhotosByUsername({
12 username: process.env.IG_USERNAME,
13 })
14
15 if (instagram["user"]["edge_owner_to_timeline_media"]["count"] > 0) {
16 // if we receive timeline data back
17 // update the posts to be equal
18 // to the edges that were returned from the instagram API response
19 posts = instagram["user"]["edge_owner_to_timeline_media"]["edges"]
20 }
21 } catch (err) {
22 console.log(
23 "Something went wrong while fetching content from Instagram",
24 err
25 )
26 }
27
28 return {
29 props: {
30 instagramPosts: posts, // returns either [] or the edges returned from the Instagram API based on the response from the `getPhotosByUsername` API call
31 },
32 }
33}

Render Instagram Data with InstagramFeed component

Once we've successfully received timeline data back from the getPhotosByUsername() call we can render this data. Below is the skeleton I used to transform the data returned from the Instagram API into a digestible and visually engaging component that displays recent photos and links to them on Instagram so that visitors can click through to the actual posts.

1import Link from "next/link"
2
3export default function InstagramFeed({ instagramPosts }) {
4 return (
5 <>
6 <h2>
7 <a href="https://www.instagram.com/yourinstagramhandle/">
8 Follow Us on Instagram
9 </a>
10 .
11 </h2>
12
13 <ul>
14 {/* let's iterate through each of the
15 instagram posts that were returned
16 from the Instagram API*/}
17 {instagramPosts.map(({ node }, i) => {
18 return (
19 // let's wrap each post in an anchor tag
20 // and construct the url for the post using
21 // the shortcode that was returned from the API
22 <li>
23 <a
24 href={`https://www.instagram.com/p/${node.shortcode}`}
25 key={i}
26 aria-label="view image on Instagram"
27 >
28 {/* set the image src equal to the image
29 url from the Instagram API*/}
30 <img
31 src={node.thumbnail_src}
32 alt={
33 // the caption with hashtags removed
34 node.edge_media_to_caption.edges[0].node.text
35 .replace(/(#\w+)+/g, "")
36 .trim()
37 }
38 />
39 </a>
40 </li>
41 )
42 })}
43 </ul>
44 </>
45 )
46}

In order to actually render this component and the associated post data from Instagram we need to import InstagramFeed into index.js and render it within the Index component with the instagramPosts prop we received from getStaticProps.

1import Layout from "../components/layout"
2import Instagram from "instagram-web-api"
3import InstagramFeed from "../components/instagramFeed"
4// empty array of instagram posts is being
5// passed as a prop into the Index component
6export default function Index({ instagramPosts }) {
7 return (
8 <Layout>
9 {/*Other Page Content*/}
10 <InstagramFeed instagramPosts={instagramPosts} />
11 </Layout>
12 )
13}

If everything worked properly you should now see all of your latest Instagram posts rendered on the page and be able to click any given posts to be taken to it on Instagram. If you are not seeing any posts rendering there may have been an issue with authentication (invalid credentials or rate limited by Instagram). If so, I recommend following my above troubleshooting steps of manually verifying credentials (in case of invalid credentials) or exploring using a VPN (if your IP address has been rate limited).

This article was published on December 21, 2020.


Don't be a stranger! πŸ‘‹πŸΎ

Thanks for reading "How to Add Instagram Timeline To a NextJS Site". Join my mailing list to be the first to receive my newest web development content, my thoughts on the web and learn about exclusive opportunities.

    Β 

    I won’t send you spam. Unsubscribe at any time.

    Webmentions

    1
    • Creative Coding Utrecht
    • Sergey Chernyshev
    • Lara Littlefield
    • sylwia vargas
    • Kenny Robinson
    • Alice Chang (she/her)
    • Epwnaz πŸ³οΈβ€πŸŒˆ