Coding a Social Share Widget

Root Beer Float image by Darin House via Wikimedia Commons

Suppose you want a homegrown share widget: perhaps for page load speed, perhaps for styling control, perhaps to avoid adding a vendor’s tracking code to your site. As it turns out, this is straightforward to do for a lot of social networks with a little JavaScript: add an onclick attribute opening a window at the appropriate URL, and you’re done.

Email is even simpler – no JavaScript required. Mailto: links have been around since the early days of the web. (Not that everyone’s browser is configured correctly to use their preferred mail client.) For a share button the destination is omitted but the subject and body are set via parameters.

href="mailto:?subject=[encoded string]&body=[encoded string]"

I found just one complication: if you encode the ampersand between subject and body in the mailto link, as most places instruct, the body will be cut off in many circumstances. One of the problematic setups is Outlook on Windows, yet even MSDN says to encode the ampersand!

Twitter, Facebook, and Pinterest sharing buttons follow. For each of them, you will be opening a window at a specific address. The links get the following attribute:
onclick="window.open('[network-specific link]', 'window', 'menubar=no, toolbar=no, resizable=yes, scrollbars=yes, height=600, width=600')"

Twitter is the second-simplest to set up. Its network-specific link is
https://twitter.com/intent/tweet?text=[encoded string]

Facebook’s complication is that you need an app ID. This ID will be exposed, so do not use an app that Facebook users sign up for. A special app that is used for nothing but this widget is best. Incidentally, if someone clicks the Facebook share button when they are not logged in, they will see the name of the app (a la “Sign in to Facebook to use XYZ”), so you may want to give it a name that will make sense to the user.

Facebook makes its own decisions about what to show for a shared page, so you only provide it the URL:
https://www.facebook.com/dialog/share?app_id=[app ID]&href=[encoded page URL]

The minimalist network-specific link for Pinterest is almost as simple as Twitter’s:
https://www.pinterest.com/pin/create/button/?url=[encoded page URL]&description=[encoded text]

That will open a window that allows you to choose an image from the page to pin, as though you’d pinned by URL from within Pinterest itself. It’s great … provided you’re not trying to manage which images are pinnable.

Once upon a time, to exclude an individual image from being pinned, you gave it the attribute nopin="nopin". That’s not valid HTML5, though, so now there is also the attribute data-pin-nopin="true". If you are using, say, the Pinterest browser extension, adding the data-attribute to exclude images works great and allows your page to validate. However, in the context of choosing an image to pin after inputting a URL to Pinterest, nopin="nopin" is still current. Imagine my joy upon discovering my sitewide update from nopin to data-pin-nopin attributes was not as much of an update as I thought!

Fortunately, it isn’t too complicated to build an image selection overlay which excludes disallowed images regardless of syntax. Mine also kicks out any images that are too small (using size as displayed) or too landscape-oriented, but pulls in anything that appears to have special Pinterest markup – whether that be from a data-pin-media attribute or based on a CSS class name. And then why not take it a step further – if there is only a single pinnable image, go straight to a Pinterest window to pin that image.

Here’s a pseudocode skeleton for a pinnable image gate:

showPinnableImages:
  A. grab all images with neither data-pin-nopin="true" nor nopin="nopin" attribute; set a counter to 0.
  B. for each image, check
    1. does it have a data-pin-media attribute or a class including "pinterest"?
      > if so, push the data-pin-media value (falling back to src and then to srcset) into a media array, and the alt text (falling back to title + metadescription) into a description array; increment the counter.
    2. if not, is it at least 236px wide with a height at least 2/3 of its width?
      > if so, push the src (falling back to srcset) into the media array, and the alt text (falling back to title + metadescription) into the description array; increment the counter.
  C. if there is more than one image, build HTML of an overlay displaying the images with their description value as alt text.
  D. if there is only one image, open a Pinterest window to pin that image.
  E. set a click handler for the overlay and its contents, to close or pin as desired.

Once you’ve chosen an image, the network-specific link for Pinterest for the window.open command looks like this:
https://www.pinterest.com/pin/create/button/?url=[encoded page URL]&description=[encoded text]&media=[encoded image URL]

The one major limitation to the home-grown share button is that if the Pinterest gate finds zero pinnable images, it will simply do nothing. There does exist open source code to generate a “text on solid color” image, but if that is overkill you can add another “if” to the block about number of pinnable images and pop up a pin window with a default image.

Other than the six-week period where Facebook was rate-limiting apps severely (and contrary to its documentation), these have worked quite well, eliminating problems with slow and obvious loading. I was really pleased with them!


Root beer float original by Darin House via Wikimedia Commons.

Leave a Reply

Your email address will not be published. Required fields are marked *