Add a Custom Pinterest Button to your Website (Part 2)
When I started out searching for a global solution with a “one and done” approach to placing Pinterest’s “pin it” button on a page and wrote about it in this post, I didn’t quite expect the sheer volume of responses from users out there searching for the same thing. I was even more pleasantly surprised when one of our readers took the time to make this even better and provided a write-up on what he discovered.
Thanks to Cameron Clark, I’d like to offer you a follow up (alternate) solution to the original article I posted here.
Background
Like many developers, Cameron wanted to give his visitors the ability to pin a variety images from his site to their Pinterest boards. For a little background re-cap, on the Pinterest site, when you enter a URL to pin, it collects all the images from the webpage and allows you to choose which one you want to pin. Pinterest also provides a very clever bookmarklet code that you can add to your browser to do the same thing from whatever webpage you’re currently on.
But if you use Pinterest’s official code to add a “pin it” button to your webpage, you have no such ability—you have to pre-select the image for the user to pin. The code looks something like this:
<a href="http://pinterest.com/pin/create/button/?url=yourpageurl.html&media=yourimgurl.html&description=yourdescriptiontext" target="_blank" count-layout="none"><img border="0" src="pin-it-button.png" title="Pin It"></a>
This seems unintuitive and rather limiting. Lots of other developers have been frustrated by this too, and have discovered a solution: call the Pinterest bookmarklet.js code from your website, which seems to work great.
But when the JavaScript code was thoroughly examined, the inefficiency of this method became very evident. The bookmarklet code is structured as a self-executing anonymous JavaScript function, which simply means that it runs immediately after you load the file—and in fact that’s the only way to run it. So every time somebody clicks the “pin it” button, you have to load the JavaScript file, even if it’s already been loaded. Furthermore, this file was being retrieved with a randomly-generated number added to the end of the URL to prevent caching. At 24 Kb, it’s a good-sized file. On a fast Internet connection, this may take only a fraction of a second, but on slower connections, such as the data network on your phone or tablet, this is a significant amount of data to load. And it just seemed crazy to prevent the file from being cached.
The Pinterest team was contacted to ask if they had a better solution. You would think they might have a variation on their bookmarklet.js code for use on individual websites. And since the bookmarklet code resides on their servers, and that’s where everybody’s calling it from, seems like they would want to provide a better solution to reduce needless traffic on their servers. Pinterest failed to respond.
Solution
Cameron was able to go through the bookmarklet.js code and tried to make it more flexible and efficient. While not fully understanding everything Pinterest was trying to do, here is a variation on their code that will hopefully be a little simpler to use and more efficient.
Sample: http://www.brandaiddesignco.com/tutorials/pinterest/
Script: http://www.brandaiddesignco.com/tutorials/pinterest/pinimages.js (or minifed: http://www.brandaiddesignco.com/tutorials/pinterest/pinimages.min.js)
First it was converted from a self-executing anonymous function to a function named selectPinImage(). Once the script is loaded, call this function whenever the “pin it” button is pressed.
The script can be loaded in a regular <script> tag, then the selectPinImage() can be called:
<script type="text/javascript" src="pinimages.js"></script> <a href="javascript:selectPinImage()"><img border="0" src="pin-it-button.png" title="Pin It"></a>
Or the script can be loaded dynamically when the pin it button is pressed. Here’s an xample with JQuery:
<a href="javascript:$.getScript("pinimages.js", function() { selectPinImage() })"><img border="0" src="pin-it-button.png" title="Pin It"></a>
Either way, the script file should cache after it’s first loaded.
Ideally, you should use this code in conjunction with the standard Pinterest code which specifies an preselected image. That way, if the JavaScript fails for some reason, the “pin it” button still works, but just doesn’t let you select an image. Example:
<script type="text/javascript" src="pinimages.js"></script> <a href="http://pinterest.com/pin/create/button/?url=yourpageurl.html&media=yourimgurl.html&description=yourdescriptiontext" target="_blank" count-layout="none" onclick="selectPinImage(); return false"><img border="0" src="pin-it-button.png" title="Pin It"></a>
The revised version of the script seems to work fine in IE 7 and IE8. It’s unclear what the issue was preventing the original version from working in those browsers.
For the description for the pinned image, the original version of the script grabs any text that the user has selected on the page, the alt or title attributes of each image, or a prefined ‘pinDesc’ value (in that order). The ability has been added to specify text to be dropped in before or after the pin description. (For example, you could append the HTML page title.) You can specify it like this:
selectPinImage('text to add before the pin description','text to add after');
Original version checks elements for display:none or visibility:hidden and excludes them, so you could only pin images that are visible. In addition, in IE only, elements that are effectively not visible—because a parent element was not visible—were also excluded because invisible elements have no width or height in IE. (This is an issue with pages on a site that are tabbed, and images on any tab except the currently visible one are excluded. Also excluded are any images in JavaScript-based slideshows that aren’t visible at the exact moment the script runs.) For consistency between browsers, code was added that checks more rigorously to see if an element is actually visible. An optional parameter was also added to the function to specify whether you want hidden elements included in the pin list or not. It defaults to not including hidden elements. Below is an example of how to make hidden elements pinnable:
selectPinImage('text to add before the description','text to add after',true);
The original version collects pinnable elements from the entire page. Further added was the ability to specify an element within the page and to only gather pinnable elements from that. Example:
selectPinImage('text to add before the description','text to add after',document.getElementById('pageContent'));
Also added is the ability to define which HTML elements to collect for pinning. Defaults to “meta”, “iframe”, “embed”, “object”, “img”, “video”, “a”. But you could limit this list to, say, just “img” tags:
selectPinImage('text to add before the description','text to add after',document.getElementById('pageContent'),['img']);
The original function checked the page for a PINTEREST=NOPIN meta tag, and popped up an error message if it was found and exited. This seemed pointless since you wouldn’t add this to any page from which you didn’t want to pin things from, so it was removed.
The original function excludes any elements with the attribute nopin=”nopin”. This seemed useful, so it was left in.
Conclusion
Whew! So there you have it. Again, a big hearty thanks to Cameron Clark for taking the time to digest the problem and come up with a viable solution!
Happy pinning, and click here to read the first edition of this article.
Sorry, but what is the final code in it’s entirety then that should be used?