E

A Guide for Setting Up Sharing Buttons for Jekyll


I’ve recently implemented more “intelligent” social sharing buttons for the articles I write. By that I mean instead of simply having the anchor links pointed toward www.twitter.com or www.facebook.com, I include critical pieces of information like the URL of each article, the author, the title, etc. Doing so for desktop web browsers was easy, but doing so for mobile was not. This article will be slightly longer than normal, so I’ve added a table of contents.

Enjoy!

table of contents

  1. overview
    1. what jekyll does
    2. what liquid is
  2. sharing from desktop
    1. simple schemes
    2. using liquid tags
  3. sharing from mobile
    1. generic sharing
    2. targeted sharing
    3. implementing variables
    4. simply making it work
  4. wrapping up
    1. small rant
    2. future implementations

overview

As you’re probably well-aware, I’ve been using Jekyll and GitHub for my blog. While overall I’ve been very pleased with both, static blogging on GH does have some drawbacks. One of the primary issues is I cannot use any server-side code other than what GitHub provides. This means that I can’t do anything fun like provide different URL schemes depending on the user agent without using JavaScript.

Jekyll is a static blogging platform. In essence what it does is it parses the files before they're served and every file with valid front-matter is rendered. Everything else is rendered as well, but differently. For instance, a file's front matter will probably look like this:

---
layout: post
variable: data
variable_two: data_two
---

This means that specific file will use the layout defined in the file "post.html". Post.html will probably look something like this:

<!DOCTYPE html>
<html lang="en">
{% include head.html %}
<body>
	{{ content }}
    <script src="/js/javascript.js"></script>
</body>
</html>

If you're wondering what the {% weirdtags %} are, they're called liquid tags. Liquid comes from Shopify and in a very, very basic sense is similar to some scripting languages you might be used to.

Liquid uses a configuration file where you define variables. For instance, remember the example of front-matter I gave earlier—it's the same thing, just one is global and one is not. This means if you want to reference a variable on any page, you can reference it with the word site. To get the site's URL, you can call {{ site.url }}. Because it's global, it'll be the same on any page. It's different from a local variable, which would look something like this: {{ post.url }}.

Using post will, at least for Jekyll, return the variable for a specific post. Using page will return it for the specific page. They're different variables. Liquid is Jekyll's way of serving static content in a dynamic way.

I'll be using liquid tags a lot in my article because it's how I manage to attach add content to sharing URLs without using JavaScript.

sharing from desktop

Most websites nowadays will have some sort of social media buttons that will allow the user to share the content on the page. There are a variety of ways to do this, with some of the most common being simple URLs and URLs that are manipulated through the specific media site's API. A simple URL would be something like www.twitter.com/share. If you click that link, it'll bring you to Twitter's web page for writing a tweet.

This works okay, but it forces the user to manually write the tweet, and we don't want that. If I had to include the URL, the author, etc. every time I tweeted an article, I'd probably share a lot less than I do now. So if we're using a static blog how do we write the social media posts for the users without using tricky JavaScript? Easy: liquid tags.

As I mentioned earlier, liquid allows you to store variables, and Jekyll already has some predefined variables. Here are the primary variables I use for my blog:

	
{{ site.url }}, 
{{ page.url }}, 
{{ page.title }}, and 
{{ page.author.twitter }}
	
	
  • {{ site.url }} returns the URL: https://ericlagergren.com.
  • {{ page.url }} returns the page's relative URL, meaning everything after the "/"
    • If the full URL of the web page is http://www.example.com/foo, then the {{ page.url }} variable would return /foo.
  • {{ page.title }} returns the title of the web page found in the head element.
  • Finally, {{ page.author.twitter }} returns the custom variable author.twitter found in each post's front-matter.

The front-matter looks something like this:

	author:
		twitter: elagergren
	

In order to add the variables to the URL, you need to include the respective liquid tag for each URL. Here's an example of my Twitter URL:

	https://twitter.com/share?text={{ page.title }}%20via%[email protected]{{ page.author.twitter }}&url={{ site.url }}{{ page.url }}
	

%20 is the same as a space, but in order to make the URL legal the space needs to be encoded. I've placed the liquid tags in the URL so it reads like this:

Dynamic Sharing for Jekyll via @elagergren https://www.ericlagergren.com/blog/dynamic-sharing-buttons

Honestly this is as far as most people go. It's super simple to set up if you have even a bit of knowledge about Jekyll and liquid. But I'm a sticker for making everything look and feel the best that it can, so I decided to dig deeper.

sharing from mobile

If you simply used the same URLs for iOS mobile devices (Android will open the app if you choose it in the settings IIRC) as you did for desktops, you'd run into issues like this:

Notice how the user isn't logged into Twitter? Most people aren't. Because mobile phones have apps, the large majority of users will only use social media sites on the respective apps. Personally I'm not willing to go through the hassle of logging into my Twitter, primarily because my email address is 28 characters long and my password is over 500 characters long. (Don't ask.)

I decided that the smart idea would be to open the URLs inside the native apps. Easy enough, right? Nope.

It used to be that most social media apps could be opened with a simple URL scheme that wasn't http://, ftp://, etc. To say that it's currently impossible to do so would be blatantly wrong. You can still use fb:// to open Facebook from iOS's Safari browser, but you can't actually post anything. I'll get to that in a little while, however. For now I want to focus on what you can manipulate via URL.

The only social media site that still honored the old prefix://[synonym for sharing]/[synonym for $text]?=[$text] scheme was Twitter. But I had an issue: how do I use that scheme when it changes the URL's protocol? If I changed all https://www.twitter.com to twitter:// I'd break the links on non-iOS devices.

I wanted to use server-side code to identify the device based on its user agent, but unfortunately GitHub pages doesn't offer any server-side code. So I had to resort to using JavaScript. I added this snippet to my external JavaScript file that detected the iOS user-agent.

	(function() {
if( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {
 // do stuff
}})();
	

I then had to put in code that would change the URL's protocol, so I opted to use some jQuery since I already was using it in other places of my blog. Originally I tried something that went (roughly) like this:

	if (iOS) {
	$(a#id).attr.('href', 'twitter://[rest of url as before]')
}
	

But that didn't work, because (1) twitter:// doesn't follow the same scheme as https://www.twitter.com, and (2) external JavaScript files can't receive liquid tags.

The first issue wasn't too big of a deal. A few StackOverflow searches later and I found the scheme: //post?message=. That, however, still left the issue of inserting the dynamic content into the URL. Now, as far as I'm aware, liquid will parse inline JavaScript, allowing me to simply use the variables I had already set up. I always move all my JavaScript into an external file, and that meant the JavaScript wouldn't be parsed by liquid, thus only returning the liquid tags in raw form.

Remembering that liquid renders its tags in the DOM and that JavaScript can parse the DOM, I constructed several hidden div elements that would contain the liquid tags for my variables. This what I ended up with:

<div class="pageTitle" id="Dynamic Sharing for Jekyll" style="display:none"></div>
<div class="pageAuthorTwitter" id="elagergren" style="display:none"></div>
<div class="siteUrl" id="https://ericlagergren.com" style="display:none"></div>
<div class="pageUrl" id="/blog/dynamic-sharing-buttons" style="display:none"></div>

Because liquid would return each div element's id, I could get the each id using this snippet:

	var pageTitle = $('div.pageTitle').attr('id');
	var pageAuthorTwitter = $('div.pageAuthorTwitter').attr('id');
	var siteUrl = $('div.siteUrl').attr('id');
	var pageUrl = $('div.pageUrl').attr('id');

Instead of using the liquid tags inside my JavaScript, I used the variables above. Here's final code for changing the URLs based on the device's user agent:

(function() {
	var pageTitle = $('div.pageTitle').attr('id');
	var pageAuthorTwitter = $('div.pageAuthorTwitter').attr('id');
	var siteUrl = $('div.siteUrl').attr('id');
	var pageUrl = $('div.pageUrl').attr('id');

if(/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
    $('a#twttr').attr('href', 'twitter://post?message=' + pageTitle + '%20via%20' + '@' + pageAuthorTwitter + '%20' + siteUrl + pageUrl);
    $('a#fb').attr('href', 'fb://publish/profile/me?text=' + pageTitle + '%20' + siteUrl + pageUrl);
    $('a#gplus').attr('href', 'gplus://share?url=' + siteUrl + pageUrl);
}})();
	

In short what I'm doing is calling an anonymous function that first stores the ids of my divs, and then I'm using an if statement to sniff the device's user agent and if it returns true then it changes the href attribute of each social button. Note: this probably won't work on IE < 9.

Earlier I mentioned that only Twitter still recognized the scheme that I wanted to use. Unfortunately Facebook and Google really want you to use their API which means including their snippets of JavaScript on your website. I didn't want to do that, so I just left the URLs with the respective app's protocol and let the app open itself to its home page. This is something I plan to fix ASAP. It's annoying working with APIs you don't know, and I don't know Facebook's or Google Plus'.

wrapping up

It's ridiculous that Facebook and Google Plus removed their old schemes for posting content. I understand they want to be able to include their JavaScript because of marketing reasons. But it's annoying to the developer who wants a much easier way to share content.

[Last edited: 2014-10-28 9:15 PM]

| |

comments powered by Disqus