Smart Tech for a better Web

Sharing images with the Facebook SDK

von

I don't like Facebook, but my customers do. From time to time I have to add features that are not covered by tools like AddThis or my preferred open source solution SocialiteJS.

Facebook shares

Recently I was close to despair when I tried to share a specific image from my website. The usual response to such kind of problems is, you would have to set some meta tags:

<meta property="og:title" content="My title" />
<meta property="og:site_name" content="Grobmeier.de"/>
<meta property="og:url" content="http://www.grobmeier.de" />
<meta property="og:description" content="Hello World" />
<meta property="og:image" content="http://www.grobmeier.de/myimage.jpg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />

Having something like that in your HTML-head will help Facebook to identify the correct image to use when your website is shared.

But it was not enough for me. I had some kind of gallery of which I wanted to share a specific image. Sure, you could use the approach above and somehow manipulate the meta tags using JavaScript. But this is not nice and I already heard Facebook is caching the images that would cause problems with this approach.

I was searching the Facebook SDK. I found the documentation looks beauty but is horrible to read and understand. Maybe it's just me and my ignorance? No idea.

The trick is straightforward, once you understand these meta tags are part of the so-called OpenGraph API. It's in fact just a "shareable story", in Facebook terms. And the SDK provides you some methods to create these shareable stories.

Here we go, step by step.

1. Create your Facebook app

First, log in to Facebook and create your app. If you don't know how to do this, you should read the basics. At least this is well explained on the Facebook web pages.

2. Initialize your Facebook SDK

This is the code you will need to initialize your app:

window.fbAsyncInit = function() {
  FB.init({
    appId      : FB_ID,
    xfbml      : true,
    version    : 'v2.4'
  });
};

(function(d, s, id){
   var js, fjs = d.getElementsByTagName(s)[0];
   if (d.getElementById(id)) {return;}
   js = d.createElement(s); js.id = id;
   js.src = "//connect.facebook.net/en_US/sdk.js";
   fjs.parentNode.insertBefore(js, fjs);
 }(document, 'script', 'facebook-jssdk'));

It will asynchronously load the SDK. Please have in mind, it still adds to your page speed loading time. You should try to load this when you actually need it. In example, when the user scrolls to a specific part of your page or clicks on some detail view.

The appId is an ID you get from the Facebook App dialogue at developers.facebook.com. Just copy/paste it and you are done.

3. Test your Facebook app local

Facebook does not allow requests from localhost by default. You need to create a new Facebook app for each environment you work with. There is some support for it: you can create a "Test App" from your original App.

In the settings of your test domain, change "app domain" to be your testing domain. Same goes to "site url".

Please note: Facebook will not allow "localhost" as valid app domain. You can redirect some domains to your localbox when you edit /etc/hosts (Mac/Linux, not sure how people do it on Windows 98).

I added:

127.0.0.1       box.dev
::1             box.dev
fe80::1%lo0     box.dev

I could reach "localhost" then by typing "box.dev" into my browser.

In the end, I have one original app and two derived testing apps: one for localhost, one for the staging area where my customer can preview my changes.

Unfortunately each app has it's own App-ID. We need to make an if/else at some point to get the right environment:

var ENV, FB_ID, BASE_URL;
if (document.domain === 'box.dev') {
  ENV = 'local';
  FB_ID = 'XXXXXX';
  BASE_URL = 'http://box.dev';
} else if (document.domain === 'mytest.grobmeier.de') {
  ENV = 'staging';
  FB_ID = 'XXXXXX';
  BASE_URL = 'http://mytest.grobmeier.de';
} else {
  ENV = 'production';
  FB_ID = 'XXXXXXX';
  BASE_URL = 'http://www.example.com';
}

I don't like the above, as my staging URL will be visible to the public, except I add some more code to my build scripts. sigh. You might come up with better solutions for JS configurations - let me know in the comments.

4. Shareable stories

Now we are getting serious. I have created a button, and on click I want a specific image to be shared, not just the one I defined in the HTML-header.

Here is my code:

var galleryItem = // ..item to share

$('.js-share-facebook').on('click', function() {
    FB.ui({
        method: 'share_open_graph',
        action_type: 'og.shares',
        action_properties: JSON.stringify({
            object : {
               'og:url': BASE_URL,
               'og:title': galleryItem.title,
               'og:description': galleryItem.description,
               'og:og:image:width': '2560',
               'og:image:height': '960',
               'og:image': BASE_URL + '/images/works/galleries' + galleryItem.image
            }
        })
    });
  });

I use the FB.ui to create a new method called "shareopengraph" which executes the action "og.shares".

"sharedopengraph" is the big brother to the "normal share", which uses the HTML header. With the action_type "og.shares" you can create your own "Share"-Object programmatically. I haven't actually found docs for og.shares, only for og.likes. You can also use og.likes, but the share dialog will be a bit different. For me "shares" was perfect as the image is bigger.

This was one of the biggest issues I faced. The Facebook docs felt incomplete to me, left me to a lot of Googling and trying things out. Even in the "complete list" of actions I could not find anything to og.shares.

Finally, I come to the action_properties. This is a stringified version of my shareable object. You can find the documentation to all of the used properties here.

Please note: when you change image dynamically, you will find out you need to unbind the click event at some point before you rebind it. You can do it with off(): MinifiedJS / jQuery.

Credits

  • The wonderful Facebook image was taken by mkhmarketing and can be found on Flickr

Tags: #JavaScript #Facebook #Social Media

Newsletter

ABMELDEN

BLOG-POST TEILEN

When you load these comments, you'll be connected to Disqus. Privacy Statement.