Create a Facebook-style Link Preview Using jQuery & YQL

Jocelyn's picture

You know that nice little Facebook feature where you paste a url into your status and it displays the title, description and an image? Using jQuery & YQL you can build code that behaves just like it. This demo will show how to capture a url, submit it to the YQL Web Service, customize the response using XPath and display a link preview using jQuery.

Facebook Link Preview

Getting the Data Using YQL

For security reasons, you can't make cross-domain AJAX requests with jQuery. So you can't just say load() mashable.com and expect to get your results back. Using YQL though we can get around the same-domain-policy and scrape a domain for content.

SELECT * FROM html WHERE url="http://mashable.com/2012/01/25/get-old-facebook-back"

This is going to return the entire page as the result - which no doubt is more than you need. Using XPath, we can limit the DOM elements we want to return.

SELECT * FROM html WHERE url="http://mashable.com/2012/01/25/get-old-facebook-back" AND xpath="//title|//head/meta"

The important part here is the AND xpath="//title|//head/meta" which tells your query just to select the title & meta tags.

When viewing results in the YQL Console, XML is selected by default, you can switch to JSON.

YQL: Select JSON

Why Can't I Just Select the Facebook Meta Tags?

Since many sites already have Facebook specific meta tags defined you may be wondering why we're selecting all meta tags and not just the ones needed. Ideally we would just use XPath to select the meta tags with the properties we were looking to display (ex./ og:title, og:description, og:image).

YQL's html data table runs the html returned by the remote server through HTML Tidy which strips these properties (seeing them as invalid). If you look through the JSON returned by YQL you'll see any of the Facebook specific meta tags only return the content attribute.

Building the Demo

Here's the barebones code to capture a url, submit it to the YQL Web Service and display the link preview on the site.

The HTML

<form id="preview">
  <div class="row">
    <label for="url">URL</label>
    <input type="text" id="url" name="url" class="text" placeholder="http://"/>
  </div>
  <input type="submit" id="submit" value="Create Link Preview"/>
</form>

The Rest Query

To use the YQL Web Service, we need to convert our YQL statement above to a rest query. If you're using the YQL Console take a look below the results near the bottom of the page to view converted query for your statement.

YQL: The Rest Query

Using jQuery we will rewrite this with the url we've captured via the form and use that to build our rest query. Don't forget to URL encode:

var q = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent('select * from html where url="' + url + '" and xpath="//title|//head/meta"') + '&format=json&callback=?';

The jQuery

Since our result contains the html page title and all the meta tags, we're need to parse this data to extract just the title, image & description that we want to use for the link preview. The title and description are fairly straight forward. But since the image meta tag is going to return with no identifiable key, we'll need to add some logic to grab that value.

Title: The HTML title
Description: Meta Tag 'description'
Image: Loop through meta tags looking for string to match expected pattern (starts with http:// and has a . 4 characters from the end)

$('#preview').bind('submit', function(e) {
      e.preventDefault();
      // get the url - assume a valid link's been entered
      getLinkMeta($('#url').val());
      return false;
});
 
/**
  * Using the meta tags of the supplied url,
  * fetch the title, description and image to display as a preview
  */
function getLinkMeta(url) {
  // create the yql query (encoded!) with the url provided
  var q = '<a href="http://query.yahooapis.com/v1/public/yql?q='">http://query.yahooapis.com/v1/public/yql?q='</a> + encodeURIComponent('select * from html where url="' + url + '" and xpath="//title|//head/meta"') + '&format=json&callback=?';
 
  // submit the query to the YQL web service
  $.ajax({
    type: 'GET',
    url: q, 
    dataType: 'jsonp',
      success: function(data, textStatus) {
      results = data.query.results;
 
      // make sure we have some data to work with
      if (results) {
        // will contain only the data we want to display
        var result = {};
 
        // use the html title as the title
        result.title = results.title;
 
        // loop through the meta tags to grab the image & description
        $.each(data.query.results.meta, function(key, val){
          if (val.content) {	    
            // description
            if (val.name && val.name == 'description') {
              result.description = val.content;
            }
 
            // og:image (Facebook image)
            // starts with http:// and has a . 4 characters from the end
            if (val.content.substring(0, 7) == 'http://' && val.content.charAt(val.content.length - 4) == '.') {
              if (val.content != 'undefined') {
                result.img = val.content;
              }
            }
          }
        });
 
        // build output
        var text = '<article><h1>' + result.title + '</h1>';
        text += '<div class="url"><em>' + url + '</em></div>';
        text += result.img ? '<img src="' + result.img + '" class="thumb"/>' : '';
        text += '<p>' + result.description + '</p></article>';
 
        // display output
        $('#preview').after(text);
      } else {
        alert("Sorry, can't scrape anything from that url.");
      }
    }
  });
}

Comments

Chris's picture

result.title = results.title;

should be

result.title = data.query.results.title;

aashish's picture

Facebook has been the global icon in current days. FB is not just a social networking site where you meet and chat with your friends. It's a platform to promote your business through different things like creating pages and groups. Advertisement is totally out-dated. Facebook Page is the modern way to expand your business.
Almost everyone these days have Facebook account. They spend hours on Facebook.Despite the fact that facebook is used by many people, facebook users have to face problems from time to time. Login problems, updates problems and others problems.
Facebook login error problem has been the headache for many users. It has got nothing to do with your username and password, it's Facebook's internal issues. However, there is one site where you can find the solution to all these.
www.facebookloginhelp.net has been helpful for

Tomas's picture

This unfortunately does not include the thumbnail scraping that I was hoping for. The whole 'choose a thumbnail'. I suppose you could also scrape for tags via xpath and then return the full list back. The tricky part I suppose is returning the most likely relevant picture, which may depend on the size of the picture (ie not silly little icons smaller than a certain size), and which may require pre-loading to determine their sizes. So as to properly sort the list or exclude some obvious ones that wouldn't be it.

Day Milovich's picture

i try to submit my link and click preview button but the error message said: undefined. help.

Jocelyn's picture

I've updated the 'Download Source Code' link, sorry about that.

oloyede's picture

hello i want to dowload this source but i can't
someone give me another link .
tanks

oloyede's picture

thank for this source but the link to dowload source is dead please someone can give me this source

Aaron Helton's picture

I just wanted to say thanks for this. It's not everything I'm looking for, but I think it will get me pointed in the right direction.

Do you have any ideas on how to parse pages that aren't fully described in meta tags? I'm thinking of using an XPath search for the first bit of the body content, but I'm not sure how to arrange the functions.

fetr's picture

very nice

Dudley Kampner's picture

Saying thanks for for your content. I know that with today's complicated world, people have many beliefs and that has made it to be very difficult for learners like me. However, you have made the idea very easy for me to know and I now understand the correct thing. Your own continued reputation as among the top experts with this topic may be enhanced through words of appreciation from followers like me. Thanks, once again.

Bloggolite's picture

Hey, this is awesome, if you could write such a script for Wordpress, you could earn tons of money. This would be a freature everyone wants to have (and pay for)!!!

Mohamed Shehab's picture

Well, You didn't test your script :D

Add New Comment