Pinterest engineering blog

  • Back to all posts
  • Jun 3, 2013
  • Share

How to make Pinterest widgets work on Tumblr

Updated: good news, everyone! It looks like Tumblr is now allowing data attributes past their editor. Please try your Pinterest widgets without our hacky fix.

The Problem

As you may have noticed, Tumblr’s post editor is very enthusiastic about stripping “nonstandard" tags and attributes, including many that are standard in HTML5.

Unfortunately, Pinterest widgets are all built around links with configuration instructions—including the ones that tell the widget script that this is a widget, and any special configuration options—passed as data attributes.

To make widgets work on Tumblr, we’ll hide our data attributes somewhere the editor won’t look, and then convert them to widgets with JavaScript. For this example we’ll stash our data in the rev attribute, which is rarely used any more but still perfectly good HTML.

Pin It Button

Here’s the generated code for a Pin It button, hot off the Widget Builder:

<a href="//pinterest.com/pin/create/button/?url=http%3A%2F%2Fwww.flickr.com%2Fphotos%2Fkentbrew%2F6851755809%2F&media=http%3A%2F%2Ffarm8.staticflickr.com%2F7027%2F6851755809_df5b2051c9_z.jpg&description=Next%20stop%3A%20Pinterest"
data-pin-do="buttonPin"
data-pin-config="above">
<img src="//assets.pinterest.com/images/pidgets/pin_it_button.png" />
</a>

Here it is translated for a Tumblr post:

<a class="pinterestWidget"
rev="data-pin-do=buttonPin data-pin-config=above"
href="//pinterest.com/pin/create/button/?url=http%3A%2F%2Fwww.flickr.com%2Fphotos%2Fkentbrew%2F6851755809%2F&media=http%3A%2F%2Ffarm8.staticflickr.com%2F7027%2F6851755809_df5b2051c9_z.jpg&description=Next%20stop%3A%20Pinterest"><img src="//assets.pinterest.com/images/pidgets/pin_it_button.png" /></a>

See the difference? We are adding class name pinterestWidget and moving the data attributes and values into the rev attribute. Here’s what that button looks like:

image

Embedded Pin

Here’s what an embedded pin looks like straight from the Widget Builder:

<a data-pin-do="embedPin" href="http://pinterest.com/pin/99360735500167749/">
</a>

Here it is translated for a Tumblr post:

<a class="pinterestWidget"
rev="data-pin-do=embedPin" href="http://pinterest.com/pin/99360735500167749/">
</a>

Here’s what it looks like on the page:

Embedded Board

Here’s a more complicated example, an embedded board with configuration options:

<a data-pin-do="embedBoard" href="http://pinterest.com/pinterest/pin-pets/"
data-pin-scale-width="115"
data-pin-scale-height="400"
data-pin-board-width="720">
</a>

Here it is translated for a Tumblr post:

<a class="pinterestWidget"
rev="data-pin-do=embedBoard data-pin-scale-width=115 data-pin-scale-height=400 data-pin-board-width=720"
href="http://pinterest.com/pinterest/pin-pets/">
</a>

In this example we took all three data attributes and moved them into the rev attribute. To be super clear: we are removing the quotes around “115,“ “400,” and “720,“ concatenating all the data-pin key/value pairs into a single string, and putting quotes around it to make it the value of the rev tag.

Here’s what our embedded board widget looks like on Tumblr:

The Script

To make Tumblr work, you’ll need to edit your template. Copy this script and paste it in at the very end, just before the closing </body> tag:

<script>
// be sure this script doesn't mess up anything else on this page
(function (d, att) {
  // declare some variables
  var link, pair, part, i, j, k, n, hazWidget, script;
  // find all the links on the page
  link = d.getElementsByTagName('A');
  // go through them one at a time
  for (i = 0, n = link.length; i < n; i = i + 1) {
    // do we have a rev and a class name that matches our pattern?
    if (link[i][att]) {
      // split the attribute into individual directives
      pair = link[i][att].split(' ');
      // loop through each directive
      for (j = 0, k = pair.length; j < k; j = j + 1) {
        // split into parts: first is key, second is value
        part = pair[j].split('=');
        // do we have two parts?
        if (part[0] && part[1]) {
          // set the attribute on the link
          link[i].setAttribute(part[0], part[1]);
          // after this is all done, build a widget
          if (part[0] === 'data-pin-do') {
            hazWidget = true;
          }
        }
      }
    }
  }
  // do we need to build a widget?
  if (hazWidget === true) {
    // make a script
    script = d.createElement('SCRIPT');
    // set the type
    script.setAttribute('type', 'text/javascript');
    // set the character set
    script.setAttribute('charset', 'utf-8');
    // set the source
    script.setAttribute('src', '//assets.pinterest.com/js/pinit.js');
    // carefully append it to the body
    d.getElementsByTagName('BODY')[0].appendChild(script);
  }
// if you would like to use some other attribute instead of rev, change it here
}(document, 'rev'));
</script>

Have fun with this, and please leave any comments or pull requests on GitHub.

Latest Article

Sep 2, 2015

On every Pinner’s profile there’s a count for the number of Pins they’ve both saved and liked. Similarly, each board shows the number of Pins saved to it. At times, Pinners would report that counts were incorrect, and so we built an internal tool to correct the issue by recomputing the count.

Popular

Sep 2, 2015

On every Pinner’s profile there’s a count for the number of Pins they’ve both saved and liked. Similarly, each board shows the number of Pins saved to it. At times, Pinners would report that counts were incorrect, and so we built an internal tool to correct the issue by recomputing the count.

Discover

Aug 21, 2015

One Thursday afternoon, I was playing ping pong while watching a couple engineers saw through a slab of wood and add LED lights that map to some of our continuous build statistics.