How to eliminate the excessive HTTP requests when using pinterest “pin it” buttons?
-
25-05-2021 - |
Question
The design of pinterest "pin it" button for websites, shown on their goodies page, calls for a web designer to insert a specially-marked anchor tag into their web page. Then the page must invoke the pinit.js boilerplate.
The special anchor tag must be like this:
<a href="http://pinterest.com/pin/create/button/?
url=http%3A%2F%2Fpage%2Furl
&media=http%3A%2F%2Fimage%2Furl"
class="pin-it-button" count-layout="horizontal"></a>
and the pinit.js boilerplate must look like this, and must be placed after the last pin.
<script type="text/javascript" src="//assets.pinterest.com/js/pinit.js">
</script>
As far as I can tell, what the pinit.js code does is this:
- scans the page for anchor tags
- looks for the special markings, specifically the "pin-it-button" class and the href prefix
- replaces the anchor tags with reformatted IFRAMEs. The
src
attributes for these iframes get normalized URLs that point to a different server, not pinterest.com, but rather a server from the CDN that pinterest uses.
This is fine on a static webpage but:
- it doesn't work on a dynamic page where "pin it" buttons might be dynamically generated via jquery logic and injected into the page markup in response to user actions.
- it requires one iframe per "pin it" button, which means one HTTP GET per "pin it" button. If you have 10 photos, each with a pinit button, then there are 10 HTTP GETs to pinterests' CDN. All of these GETs are for similarly-named resources, but they are all slightly different, based on the url of the image to be pinned, and as such cannot be cached.
What I would like to do is eliminate the excessive GETs. Any ideas?
One idea I had was:
- insert exactly one anchor tag, within a div styled as
display:none;
. - invoke pinit.js, which results in the magic replacement of that anchor tag, and the loading of a new iframe. It is invisible, because it still resides in the invisible div.
- run some additional JS logic to inspect the URL on the src attribute for the generated iframe, saving the hostname for the pinterest CDN.
- ?
I can then generate the "normalized" URLs for the pinterest CDN, but... if I simply use them as src for an iframe my logic generates, then I have the same problem with excessive GETs. All I have done is eliminated the successive calls to pinit.js (which is cacheable anyway).
Has anyone confronted this?
I have to believe this design is going to change - it seems not scalable for pinterest the way it works now.
EDIT
I read elsewhere that pinterest provides an "asynchronous" mechanism for "pin it" buttons on a page, suitable for use when there are lots of "pin it" buttons. Not sure what that is; I couldn't find it.
Solution
I am answering my own question.
I looked but could not find any detailed doc from pinterest that describes how to approach this problem. I think their API is simply too new, too immature to cover this.
The problem I found was that for each "pin it" button, there was a single IFRAME, and that iframe loaded source from the pinterest CDN. 10 images meant 10 iframes and 10 HTTP GETs.
I did find a way to insert a single button on a webpage that allows a user to pin any of the 10 images. This was via the pinmarklet.js script, provided by pinterest. But, that script didn't work for me, and it had several bugs, so I modified it to suit my purposes.
Now when I click a "pin it" button, it fills only one IFRAME, requires just one HTTP GET, regardless of how many photos are available on a page. The UI looks like this:
...although you could make it anything you like, I guess.
What problems did I fix?
The pinmarklet was
(a) kludgy. It defined an anonymous script, and a page would need to re-request the JS every time it needed to popup the pinterest interaction form. No need for that. Let's just do it once.
(b) broken. There were several bugs, including a race condition in the code that tries to determine the natural size of an image. Because of that bug, the pinmarklet form would not show, sometimes. Lame!
I modified the code to fix these things, and it works well now, for me.