Instagram Embed Plugin - is it possible?

I, along with my users, prefer the way an Instagram embed looks compared to the onebox of an Instagram image/post. With their embed you can tell right away that you’re looking at an Instagram image, and the full caption is shown.

I was wondering if it’s possible to build a plugin that overrides the native Discourse onebox for Instagram and replaces it with the regular Instagram embed? I have been looking to get my feet wet into Discourse development and I figure this would be a fairly simple project, if it’s doable.

This is the process I came up with:

  1. Plugin is installed and enabled
  2. User adds their Instagram API authentication credentials to the plugin’s settings
  3. Add Instagram to the onebox domains blacklist Discourse admin setting (not sure if this can be automated when the plugin is enabled or if it has to be done manually by the user)
  4. Plugin detects Instagram link in post content upon saving a post (I would prefer not to use a custom BBCode but if that’s the only possible way then I’ll do that)
  5. Plugin makes call to the Instagram API with the URL it detected and obtains the embed code
  6. Embed code is saved into the cooked post

For reference, this is what the embed code looks like:

<blockquote class="instagram-media" data-instgrm-captioned data-instgrm-permalink="https://www.instagram.com/p/Bi44Jb6Da4n/" data-instgrm-version="8" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);">
  <div style="padding:8px;">
    <div style=" background:#F8F8F8; line-height:0; margin-top:40px; padding:62.5% 0; text-align:center; width:100%;">
      <div style=" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAMUExURczMzPf399fX1+bm5mzY9AMAAADiSURBVDjLvZXbEsMgCES5/P8/t9FuRVCRmU73JWlzosgSIIZURCjo/ad+EQJJB4Hv8BFt+IDpQoCx1wjOSBFhh2XssxEIYn3ulI/6MNReE07UIWJEv8UEOWDS88LY97kqyTliJKKtuYBbruAyVh5wOHiXmpi5we58Ek028czwyuQdLKPG1Bkb4NnM+VeAnfHqn1k4+GPT6uGQcvu2h2OVuIf/gWUFyy8OWEpdyZSa3aVCqpVoVvzZZ2VTnn2wU8qzVjDDetO90GSy9mVLqtgYSy231MxrY6I2gGqjrTY0L8fxCxfCBbhWrsYYAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;">
      </div>
    </div>
    <p style=" margin:8px 0 0 0; padding:0 4px;">
      <a href="https://www.instagram.com/p/Bi44Jb6Da4n/" style=" color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;" target="_blank">When you don’t hear Laurel or Yanny so you don’t care about Laurel or Yanny... #dontaskmeagainsusan #laurelsoundlikeababetho #hitmeuplaurel #illbeyoyanny</a>
    </p>
    <p style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;">A post shared by <a href="https://www.instagram.com/waltergeoffreythefrenchie/" style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px;" target="_blank"> •w a l t e r•</a> (@waltergeoffreythefrenchie) on <time style=" font-family:Arial,sans-serif; font-size:14px; line-height:17px;" datetime="2018-05-17T18:31:44+00:00">May 17, 2018 at 11:31am PDT</time>
    </p>
  </div>
</blockquote>
<script async defer src="//www.instagram.com/embed.js"></script>

Here are two problems I see regarding the embed code:

  • The plugin will need to whitelist a lot of those tags/attributes. For that, I will reference this topic: https://meta.discourse.org/t/whitelisting-some-html-tags/24280
  • The script tag is not allowed, and I’m not sure if it can be whitelisted. If not, I could possibly add it before the footer? It’s just 3kb so I don’t care if it’s loaded when it’s not necessary.

Any and all feedback regarding this would be greatly appreciated! Thanks in advance!

1 Like

If it has variable height it will destroy topic scrolling, be warned. Variable height is an absolute cancer when it comes to infinite scroll.

Provided you can set the height, or know the height and define it so the HTML layout knows the height before render, then you’ll be fine. If not, I highly recommend abandoning this approach because there will be tears :sob:

5 Likes

@codinghorror thanks for the insight! After doing a search for “variable height” here on the forum, I’m surprised I did not come across that important info already.

From the API docs, this is the response:

{
    "author_id": 9538472,
    "author_name": "diegoquinteiro",
    "author_url": "http://instagram.com/diegoquinteiro",
    "height": null,
    "html":"...",
    "media_id": "558717847597368461_9538472",
    "provider_name": "Instagram",
    "provider_url": "http://instagram.com/",
    "title": "Wii Gato (Lipe Sleep)",
    "type": "rich",
    "thumbnail_url": "http://distilleryimage5.ak.instagram.com/5dceebb02c5811e3b57222000a9e07e9_8.jpg",
    "thumbnail_width": 640,
    "thumbnail_height": 640,
    "version": "1.0",
    "width": 658
}

Here are the request parameters:

PARAMETERS

URL A short link, like http://instagr.am/p/fA9uwTtkSN/.
MAXWIDTH Maximum width of returned media. This value is optional and must be greater than 320. Note that the maxheight parameter is not supported and always returns null. This is because the embed code is responsive and its height varies depending on its width and lenght of the caption.
HIDECAPTION If set to true, the embed code hides the caption. Defaults to false.
OMITSCRIPT If set to true, the embed code does not include the script tag. This is useful for websites that want to handle the loading of the embeds.js script by themselves. To manually initialize the embed code, call the JS function instgrm.Embeds.process().
CALLBACK A JSON callback to be invoked.

Instagram Developer Documentation

While the oembed GET request doesn’t give you the height, there is a link that can be visited that gives you a direct link to the image file.

Medium Example:
https://instagram.com/p/Bi44Jb6Da4n/media/?size=m

Large Example:
https://instagram.com/p/Bi44Jb6Da4n/media/?size=l

The dimensions from the medium link could be used to get the image’s proportions and then I could combine that with the width from oEmbed request response to get the height.

I’m assuming the “variable height” problem applies to the entire embed box though, not just the image/video, correct? If so, then the caption might introduce issues too.

2 Likes

My understanding is the issue with “variable height” isn’t so much that it can’t be properly calculated, but that when the page first loads the embed will have zero-height, then after the embed script runs it will populate the embed location and push everything below it down, causing the user to be thrown around the page.

This applies to most of those third-party embed scripts, like Twitter too.

Compare to when the Instagram OneBox loads it’ll already have the caption there, and an <img> tag with the proper height, so no content gets moved around after the image loads.

4 Likes

Thanks @Cameron_D. That makes sense.

While typing my previous reply I had the idea to create a “pseudo-embed” with the information provided in the Instagram API response and styling it like an Instagram embed. It sounds like this is essentially what OneBox does, and this is probably the best route for me to take.

2 Likes