vertner.net

Better Facebook and Twitter Integration for Octopress

Such Octo. Much Press. Wow.Such Octo. Much Press. Wow.

Given that I haven’t taken web development seriously since around 2000, when HTML 4 wasn’t yet widely supported and CSS was still a novelty, all this social stuff has been pretty exciting to learn. As I previously discussed, I’ve been using Octopress as my blogging framework. While there’s amount of support for Wordpress (which I avoid for security reasons, sometimes finding good tutorials for Octopress developers at my level can be a bit hit or miss. Considering that, here’s brief tutorial with what I’ve done so far.

Octopress: Already Social Out of the Box

If you’ve already got a Twitter account, simply adding your username and enabling the asides/twitter.html in your _config.yml file is easy. With Twitter and the other 3rd party settings in the _config.yml, just setting your twitter_tweet_button, google_plus_one, and facebook_like to true will get you some nifty Tweet, G+1, Like, and Share, buttons. You may notice that the facebook Like and Share icons aren’t quite in line with the others; that’s easy to fix by just opening up your /sass/custom/styles.scss file and adding the following anywhere:

1
2
//fix for the FB alignment issue
.fb_iframe_widget span { vertical-align: baseline !important; }

Voila! Now everything looks a bit better. For grins, I decided to add Pinterest, LinkedIn, and E-mail sharing buttons, just to see what I could do on my own. Pinterest and LinkedIn, like most social media sites, includes excellent pages on how to integrate their buttons or widgets into your site. E-mail sharing took a little bit of google searching, but here’s ultimately what I ended up with in my /source/_includes/post/sharing.html:

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
29
30
<div class="sharing">
<!-- Twitter -->
  {% if site.twitter_tweet_button %}
  <a href="//twitter.com/share" class="twitter-share-button" data-url="{{ site.url }}{{ page.url }}" data-via="{{ site.twitter_user }}" data-counturl="{{ site.url }}{{ page.url }}">Tweet</a>
  {% endif %}

<!-- Facebook -->
  {% if site.facebook_like %}
  <div class="fb-like" data-href="{{ site.url }}{{ page.url }}" data-layout="button_count" data-action="like" data-show-faces="false" data-share="true" data-width="450"></div>
  {% endif %}

<!-- LinkedIn -->
  <span id="linkedin"><script src="//platform.linkedin.com/in.js" type="text/javascript">
    lang: en_US
  </script>
  <script type="IN/Share" data-url="{{ site.url }}{{ page.url }}" data-counter="right"></script></span>
  
<!-- Google Plus -->
  {% if site.google_plus_one %}
  <div class="g-plusone" data-size="{{ site.google_plus_one_size }}"></div>
  {% endif %}
  
<!-- Pinterest -->
  <a href="//www.pinterest.com/pin/create/button/" data-pin-do="buttonBookmark" id="pin"><img src="//assets.pinterest.com/images/pidgets/pinit_fg_en_rect_gray_20.png" /></a>
  <!-- Please call pinit.js only once per page -->
  <script type="text/javascript" async src="//assets.pinterest.com/js/pinit.js"></script>
  
<!-- E-mail -->
  <a href="mailto:?subject=I wanted you to see this article&body=Check out this site, {{ site.url }} {{ page.url }}." title="Share by Email"><img src="/images/mail2.png" id="mail"></a>
</div>

I switched up the order a bit from the defaults and added some id tags to make it easier to format with CSS. Some of them are difficult to format around in their current setup (that’s right, I mean you Twitter and Google Plus). I also updated the default facebook SDK call in the /source/_includes/facebook_like.html page to what they are currently pushing:

1
2
3
4
5
6
7
8
<div id="fb-root"></div>
<script>(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.0";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>

Sharing Made Pretty

I knew there were ways to exert more control over how my pages were presented on social media, so I looked into both Twitter and facebook’s meta tags. In the process of doing so, I stumbled upon Zac Clancy’s fantastic post on easily integrating both. The first things I needed to do were to update my _config.yml with the following at the botting:

1
2
3
# Facebook Insights/Open Graph
facebook_app_id: XXXXXXXXXX
facebook_page: https://www.facebook.com/user.page

Then, I went to facebook’s Insights page, clicked on Add your Domain, and replaced those X’s with the App ID. Make sure you replace the facebook_page address with the static address for your facebook page. Once the domain was verified, I was good to go and could actually start using facebook’s analytic offerings as well as customize my link presentation.

I didn’t necessarily need the granular control Zac offered and had some funky errors with nesting the header data in the markdown files, so I simplified it a bit in the /source/_includes/custom/head.html file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- Social media content metadata -->
{% if site.facebook_app_id %}
<meta property="fb:admins" content="{{ site.facebook_app_id }}" />
<meta property="og:title" content="{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}" />
<meta property="og:site_name" content="{{ site.title }}" />
<meta property="og:url" content="{% if canonical %}{{ canonical }}{% else %}{{ site.url }}{% endif %}/" />
<meta property="og:description" content="{{ description | strip_html | condense_spaces | truncate:200 }}" />
<meta property="og:author" content="{{ site.facebook_page }}" />
{% if page.social_image %}<meta property="og:image" content="{{ page.social_image }}" />{% endif %}
{% endif %}

{% if site.twitter_user %}
<meta property="twitter:card" content="{% if page.twitter_card_type %}{{ page.twitter_card_type}}{% else %}summary{% endif %}" />
<meta property="twitter:site" content="{{ site.twitter_user }}" />
<meta property="twitter:url" content="{% if canonical %}{{ canonical }}{% else %}{{ site.url }}{% endif %}" />
<meta property="twitter:title" content="{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}" />
<meta property="twitter:description" content="{{ description | strip_html | condense_spaces | truncate:200 }}" />
<meta property="twitter:creator" content="{% if page.twitter_card_creator %}{{ page.twitter_card_creator }}{% else %}{{ site.twitter_user }}{% endif %}" />
{% if page.social_image %}<meta property="twitter:image:src" content="{{ page.social_image }}" />{% endif %}
{% endif %}

If you compare my code with Zac’s, you may notice that I replaced the calls for different Twitter and facebook preview images with a single social_image variable and took out any nested calls. That ended all of the errors Octopress seemed to be getting, so that’s a big win. Finally, because I’m lazy, I edited my Rakefile to start adding this stuff to my new_post and new_page commands like so:

1
2
3
4
5
6
7
8
9
10
11
puts "Creating new post: #{filename}"
open(filename, 'w') do |post|
  post.puts "---"
  post.puts "layout: post"
  post.puts "title: \"#{title.gsub(/&/,'&')}\""
  post.puts "date: #{Time.now.strftime('%Y-%m-%d %H:%M:%S %z')}"
  post.puts "comments: true"
  post.puts "categories: "
  post.puts "social_image: http://vertner.net/images/"
  post.puts "twitter_card_type: summary"
  post.puts "---"

Now I’ve got buttons and sweet-looking Twitter/facebook shares… what next?

Comments on Your Comments

Since the high-profile Disqus vulnerability discussed earlier this year, I’ve been leery about using Octopress’ baked-in support for the commenting function. Since we’re calling on facebook’s SDK anyway, let’s see if we can implement it instead. Going a step further, instead of updating both /source/_layouts/page.html and /source/_layouts/post.html pages, I replaced the Disqus if statement with {% include comments.html %} and created a /source/_includes/comments.html page. In case I change my mind and don’t feel like reinventing the wheel, I opted to include the capability of switching back to Disqus like so:

1
2
3
4
5
6
7
8
9
<section>
  <h1>Comments</h1>
  <div id="comments">
    <div class="fb-comments" data-href="{{ site.url }}{{ page.url }}" data-numposts="5" data-colorscheme="light"></div>
  {% if site.disqus_short_name and page.comments == true %}
  <div id="disqus_thread" aria-live="polite">{% include post/disqus_thread.html %}</div>
  {% endif %}
  </div>
</section>

Again, facebook made it easy to copy/paste right off of their page. Moderation of the comments if even baked-in by default using the App ID. I added an additional <div> tag so that I could manipulate the whole comments area in CSS. Hooray!

Final Observations

In addition to their massive audiences, I see a huge reason why Twitter and facebook are such dominating social media platforms: their developer support is fantastic. The documentation was very approachable and came with built-in analytic resources to learn more about how users interact with your site and their respective platforms. There are a lot of customization options and they’re both very flexible with how you might want to integrate them with your web site. I’m pretty excited to see how I might further integrate and customize those (and potentially other) social platforms in the future.

Now that you can, I look forward to your comments below!

UPDATE: Thanks, Jim Pravetz. I was banging my head trying to figure out how to get Liquid to not process any {% liquid tags %} when they are inserted into a {% codeblock %}.

Comments