Embedding Instagram Posts

In this tutorial we're going to show you how to embed Instagram posts on web pages with Scrivito. We will start with a quick and simple approach – by utilizing an existing widget. Then, we will show you a clean and robust implementation of a dedicated Instagram widget.

This tutorial requires some basic knowledge of the Scrivito workflow and React. It is based on the Scrivito Example App but can be used to extend any Scrivito app.

Get started – including Instagram’s embed code in a text widget

Like many social services, Instagram has an option to copy fully functional embed code from a post. This premade HTML/JS code makes it easy to include Instagram posts in your website in the format and design recommended by Instagram. The Example App’s text widget already has a “text” attribute of the type html. So we could just add the embed code in the widget properties. However, the embed script from Instagram needs to run so we would need to add a component to make the script available on every page. The code would look like this:

src/Components/Instagram.js
Copy
import * as React from 'react';
import Helmet from 'react-helmet';

 class Instagram extends React.Component {
   render() {
     return (
      <Helmet>
        <script async src='https://www.instagram.com/embed.js'/>
      </Helmet>
    );
  }
}
 export default Instagram;

We will also add this new component to the App.js file:

src/App.js
Copy
...
import Instagram from './Components/Instagram';
...

export default function App() {
  return (
    ...
        <Instagram />
    ...
  );
}

Finally, we will need to add the script URL, https://www.instagram.com, to our “public/_headers” file to comply with our Content Security Policy.

Now your editors can add Instagram posts to the website via a text widget. To do this they would go to Instagram, get the embed code from the post and then paste it into the widget’s “Text” field in the properties. While this is the simplest option, it is not necessarily the best. Scrivito prides itself on WYSIWYG editing, however, with this option, when in editing mode, you’ll only see placeholders for the embedded posts.

“The embed code contains a preview HTML code and a reference to the Instagram embeds.js JavaScript library. When the library is loaded, it scans the page for the HTML code and generates the fully rendered post.” – https://www.instagram.com/developer/embedding/

So if you want it quick and easy, this is the way. But we can do better, so in the next section we will build on this code and create a dedicated widget for displaying Instagram posts.

Building an Instagram widget

In this section, we will be creating an Instagram widget to provide some options to our editors in displaying the Instagram post content. To begin, we will add the react-instagram-embed package to our project with:

Copy
~$ npm install --save react-instagram-embed

Define the widget model

First things first, so let's add the file for the new widget model class in the project at “src/Widgets/InstagramWidget/” named “InstagramWidgetClass.js”.

In this file, we make the widget model known to Scrivito by calling Scrivito.provideWidgetClass and passing the widget class name, “InstagramWidget”, to it. Next to this name, we pass an attribute definition to it consisting of those attributes we want to be editable. The npm package includes several variables, so we will input the relevant ones here as attributes: url, maxWidth, and hideCaption.

src/Widgets/InstagramWidget/InstagramWidgetClass.js
Copy
import * as Scrivito from 'scrivito';

Scrivito.provideWidgetClass('InstagramWidget', {
  attributes: {
    url: 'string',
    maxWidth: 'integer',
    hideCaption: ['enum', { values: ['true', 'false'] }],
  },
});

Render the widget instances

For rendering instances of the “InstagramWidget”, we’ll now create a React component (and make it known to Scrivito). We suggest using an ES6 class to define such components (extends React.Component). Inside the render function, we can access the widget instance via the corresponding widget prop to fetch the widget attribute values.

src/Widgets/InstagramWidget/InstagramWidgetComponent.js
Copy
import * as React from 'react';
import * as Scrivito from 'scrivito';
import InstagramEmbed from 'react-instagram-embed';
import InPlaceEditingPlaceholder from '../../Components/InPlaceEditingPlaceholder';

Scrivito.provideComponent('InstagramWidget', ({ widget }) => {
  const url = widget.get('url');
  if (!url) {
    return (
      <InPlaceEditingPlaceholder center={true}>
        Use widget properties to input an Instagram Url 
      </InPlaceEditingPlaceholder>
    );
  }

  const maxWidth = widget.get('maxWidth');
  const hideCaption = widget.get('hideCaption');
  
  return (
    <InstagramEmbed
      align='center'
      url={ url }
      maxWidth={ maxWidth }
      hideCaption={ hideCaption }
      containerTagName='div'
      injectScript={ false }
      protocol=''
    />
  );
});

As you can see, we are first checking if there is a post defined and, if not, returning a placeholder so we do not create an error in the app and give a hint to the editor as to what is needed. We are importing the react-instagram-embed package and using the component to render the post with the supplied options. Note, these options have been modified from the package's defaults to better work with Scrivito.

Finally, to have Scrivito use the “InstagramWidgetComponent” for rendering instances of the “InstagramWidget”, we associate the widget class with the component using Scrivito.provideComponent.

Make the attributes editable

We want any Instagram widget’s attributes (url, maxWidth, hideCaption) to be editable via its properties dialog, so let's provide Scrivito with a UI configuration for “InstagramWidget” instances. This can be done using Scrivito.provideEditingConfig:

src/Widgets/InstagramWidget/InstagramWidgetEditingConfig.js
Copy
import * as Scrivito from 'scrivito';

Scrivito.provideEditingConfig('InstagramWidget', {
  title: 'Instagram Widget',
  description: 'A widget displaying an Instagram post',
   
   properties: ['url', 'maxWidth', 'hideCaption'],

   attributes: {
    url:{
      title: 'Url',
      description: 'Input the Url of the instagram post you wish to display.',
    },
    maxWidth:{
      title: 'Maximum Width',
      description: 'Input the maximum width you wish to display the post (minimum is 320).',
    },
    hideCaption:{
      title: 'Hide the caption?',
      description: 'Do you want to hide the caption?',
      values: [{ value: 'true', title: 'Yes' }, { value: 'false', title: 'No' }],
    },
  },
  initialContent: {
    maxWidth: 320,
    hideCaption: 'false',
  },
});

To make the widget responsive throughout the project we need to override Instagram's min-width:. Add the following to "src/assets/stylesheets/index.scss":

src/assets/stylesheets/index.scss
Copy
/* INSTAGRAM
================================================== */

.instagram-media { min-width: auto !important; }

The last step is to again add the URL, “https://api.instagram.com”, to the Content Security Policy header. After that we're done!

Now that everything is in place, fire up your Scrivito app via npm start from your project directory, then open the site in your browser (if you haven't already done so). Note that you need to add “scrivito/” to the URL to be able to switch to Edit mode. So the URL should look something like this: “http://localhost:8080/scrivito/”

Click the + icon at the top or bottom edge of a widget and select the “Instagram” widget from the widget browser. Next, input the URL of the Instagram post you want to use in the widget properties. You can update the other attributes as well or leave them with default values.

Finished!

To summarize: Every widget is comprised of

  • a model defining its attributes (Scrivito.provideWidgetClass),
  • a React component for rendering the instances (attached to the Scrivito widget class using Scrivito.provideComponent),
  • and a UI specification for making at least those attributes editable (Scrivito.provideEditingConfig) that cannot be accessed directly on the page.