Genuity Tech Blog

Tidbits of Ruby, Rails, and all things related

Pinterest extension for Spree

TL; DR

spree_pinterest is a Spree extension for adding a Pinterest Pin it button to your Spree store. Install it by adding it to your Gemfile.



The last project I worked on, the client needed shopping cart capabilities added to thier site. I chose to use the open-source Spree shopping cart Rails engine.

Spree is a great piece of software that doesn’t try to cover every edge case in the e-commerce world. It provides what 98% of most sites need to run an online store. The last project I worked on fell within the other 2% though, and I had to heavily customize it for that particular project. I’ll save those customizations for another post.

What I want to talk about today is a new Spree extension I wrote recently, called spree_pinterest. It’s a simple extension that adds a Pinterest Pin it button to the Spree product index and show views.

Spree makes it really easy to create an extension. I won’t go into the details of that here, but you can read all about that in the Creating Extensions section of the Spree Guides.

Creating a Pin it button

Pinterest provides the instructions for adding a Pin it button on their website. It basically consists of two parts:

  1. Inserting some Javascript in your page
  2. Adding a link, which the Javascript converts to the button

The Javascript

Step 2 above is slightly misleading. The Javascript actually converts the link to an IFRAME which contains the newly-rendered link styled as a button. Not sure of the reason for the IFRAME. I honestly didn’t dive in to how the Pinterest pin_it.js script actually works.

First, I added the Javascript to the spree_pinterest.js Javascript file created when I ran the spree extension command:

app/assets/javascripts/store/spree_pinterest.js GitHub
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//= require store/spree_core

(function() {
    window.PinIt = window.PinIt || { loaded:false };
    if (window.PinIt.loaded) return;
    window.PinIt.loaded = true;
    function async_load(){
        var s = document.createElement("script");
        s.type = "text/javascript";
        s.async = true;
        if (window.location.protocol == "https:")
            s.src = "https://assets.pinterest.com/js/pinit.js";
        else
            s.src = "http://assets.pinterest.com/js/pinit.js";
        var x = document.getElementsByTagName("script")[0];
        x.parentNode.insertBefore(s, x);
    }
    if (window.attachEvent)
        window.attachEvent("onload", async_load);
    else
        window.addEventListener("load", async_load, false);
})();

This is the Javascript provided in the advanced option on the Pinterest website. I may end up converting this to Coffescript, but I was in a hurry at the time :)

The views

Next, we need to add the link to our views that will get converted to the Pin it buttons. For this extension I decided to add two buttons. One for each image on the products index view just to the left of the price, and one directly under each image on the products show view.

First, I created a helper method that would generate the link:

app/helpers/spree/pinterest_helper.rb GitHub
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module Spree
  module PinterestHelper
    def pin_it_button(product)
      return if product.images.empty?

      url = escape spree.product_url(product)
      media = escape absolute_image_url(product.images.first.attachment.url)
      description = escape product.name

      link_to("Pin It",
              "http://pinterest.com/pin/create/button/?url=#{url}&media=#{media}&description=#{description}",
              :class => "pin-it-button",
              "count-layout" => "horizontal").html_safe
    end

    private

    def escape(string)
      URI.escape string, /[^#{URI::PATTERN::UNRESERVED}]/
    end

    def absolute_image_url(url)
      return url if url.starts_with? "http"

      request.protocol + request.host + url
    end
  end
end

There are two mandatory, and one optional pieces of information you need to supply in the href of the link:

  1. url (mandatory) - This is the product page URL
  2. media (mandatory) - This is the URL to the image which is being pinned. In the event you’ve specified an asset_host for your app, or you are using S3 with paperclip, the URL will be used as is. If not, the url method from paperclip will only be a path, so the helper will prepend the protocol and host.
  3. description (optional) - This is the description that will be used in the pin

You can see the values being used for each of the variables in lines 6-8 above.

Now we need to add the links to the views. For this I used a Deface override. I created one override file that contains two Deface overrides, one for each view:

app/overrides/products/pin_in_button.rb GitHub
1
2
3
4
5
6
7
8
9
Deface::Override.new(:virtual_path => "spree/shared/_products",
                     :insert_bottom => "[data-hook='products_list_item']",
                     :text => "<%= pin_it_button(product) %>",
                     :name => "index_pin_it")

Deface::Override.new(:virtual_path => "spree/products/show",
                     :insert_after => "#main-image",
                     :text => "<%= pin_it_button(@product) %>",
                     :name => "show_pin_it")

For more information on Deface, check out the Using Deface section of the Spree Guides referenced above, and also take a look at the project on GitHub.

The style

I used CSS to postion the button to left of the product price on the index view, and directly under the image on the show view:

app/assets/stylesheets/store/pin_it_button.css.sass GitHub
1
2
3
4
5
6
7
8
9
iframe[src*='pinit.html']
  margin-top: 4px

[data-hook='products_list_item']
  iframe[src*='pinit.html']
    float: left

  span.price
    float: right

I had to use iframe in the CSS to position the button, not a, because as I said before the Javascript turns the link into an IFRAME.

That’s it! The extension is complete. Here is what the Pin it button looks like in the default Spree theme:

Pin it - index Pin it - show

If you are interested in using the spree_pinterest extension, just include the gem in your Gemfile. Also, the extension’s source code is available to browse.

Thanks for reading!

Comments