URL previews are a way of organizing the URLs in the textarea in such a way that the URL is visible in a more organized way to the user instead of a just plain link. The plain URL makes no sense most of the time because of the advent of URL shorteners. With the increasing usage of social media websites and social media share plugins it becomes very difficult to identify spammy and non-spammy posts on the internet and with URL previews we could help such websites differentiate on our apps by showing URL previews every time someone shares a URL in the message box, blog post or anywhere else.
Hence I think, URLs previews are nowadays must have features on chat and blog based applications. This is used in many forms like on Facebook, WhatsApp, LinkedIn, Skype etc, on pasting a URL in the text box the URL preview with the title, webpage image and a short description are fetched. While on Flowdock, when we paste a GitHub PR URL it automatically fetches the PR name and the organization it belongs to.
Today I'll be showing how to add URL previews on your web apps by Javascript.
This can be done in many ways. In many JS frameworks, we get a direct plugin to do this but it is always good to understand how to do things manually when you need to be in charge of your code.
We have react-native-link-preview for ReactJS, jQuery URLive (didn't work on my testing), etc, but let's see how can we do it manually.
To do this manually we have two ways one to fetch the page to load on the server side and send the required data (title, image, and description) back on the client side and second is to use some third party service to do this exact same thing. The reason why we need to do this on the server side is that you cannot make cross origin (a.k.a Cross Origin Resource Sharing) web requests on the client side using Javascript. Which means you cannot make request outside of you domain on the client side.
I believe we should go ahead and do this to see what happens. To do this open Browser web console and type following code => Make sure you are not trying this on "https://google.com" because if we do that we will not be making cross origin web requests as the URL requested and the current domain will be from the same origin.
$.ajax({
url: "https://google.com",
async: true,
success: function(data) {
var matches = data.match(/<title>(.*?)<\/title>/);
alert(matches[0]);
},
error: function(e) {alert(e);}
});
We get the following error on execution:
XMLHttpRequest cannot load https://google.com/?_=1501418732316. Redirect from 'https://google.com/?_=1501418732316' to 'https://www.google.co.in/?gws_rd=cr&ei=sCR-WfSjLoTkvgT-9L-oAw' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://stackoverflow.com' is therefore not allowed access.
Which means we are not allowed to make requests to sites outside of our domain. This brings us back to the using server side rendering or using third party services.
To make Cross Origin Resource Sharing requests I found following services worth mentioning some are paid while most are free.
- Link Preview REST API which is free for up to 60 requests/month and then we have plans for more requests
- crossorigin.me which is free but is not very reliable as many URLs didn't work
- Link-Preview runs using PHP so needs to be deployed on the cloud to run, so we'll be using a hack to use this one.
I'll demonstrate each one them but 1st one Link Preview REST API needs keys to use, so might want to register on their website first.
- Link Preview REST API
This is the simplest of all and gives the direct result in JSON format in the following format.
{
"title":"Google",
"description":"Search webpages, images, videos and more.",
"image":"https:\/\/www.google.com\/images\/logo.png",
"url":"https:\/\/www.google.com\/"
}
To make API request you need to use following code as per their documentation on their website
var target = 'https://www.google.com';
$.ajax({
url: "http://api.linkpreview.net",
dataType: 'jsonp',
data: {q: target, key: '123456'},
success: function (data) {
console.log(data.match(/<title>(.*?)<\/title>/));
}
});
A CORS proxy is a service that allows developers to access resources from other websites, without having to own that website.
Following code can be used to make CORS request using corssorigin,me
//getTitle()
var target = 'https://hackernoon.com/working-of-yarn-and-npm-974b79f10341';
$.ajax({
url: "https://crossorigin.me/"+target,
success: function (data) {
console.log(data.match(/<title>(.*?)<\/title>/)[1]);
}
});
But as I said before it is not very reliable as it doesn't work for many websites for example if we try following code we get
//getTitle()
var target = 'https://www.cnet.com/';
$.ajax({
url: "https://crossorigin.me/"+target,
success: function (data) {
console.log(data.match(/<title>(.*?)<\/title>/)[1]);
}
});
We get following error,
jquery.min.js:formatted:4208 GET https://crossorigin.me/https://www.cnet.com/?_=1501418732338 500 ()
This is because of web site dealing with such request in a different way.
Also we need to extract all the data from HTML page manually using JavaScript unlike other two which format the data directly and give us the JSON response.
This is one needs to be deployed along with your web app to execute but I have one website which is already using it so I will use that as our API for this particular example.
Playground.ajaxtown have a simple demo and code of this example I will use that to hit the request to Link-Preview code.
//getTitle()
var target = 'https://www.forbes.com/sites/aarontilley/2017/07/28/samsung-steals-intels-spot-as-worlds-biggest-chipmaker/';
function getTitle(externalUrl){
$.ajax({
url: "http://playground.ajaxtown.com/link_preview/class.linkpreview.php?url"+target,
success: function (data) {
console.log(data.match(/<title>(.*?)<\/title>/)[1]);
}
});
This is one gives the thumbnail, description, and title like Link Preview REST API does but needs to be deployed on a server to run.
Following code will help you extract URLs from text boxes and use that to make all the above requests to get title, description, and thumbnail.
//to detect and extract url from textarea or input box
function urlify(text) {
var urlRegex = /(https?:\/\/[^\s]+)/g;
return text.match(urlRegex);
}
function getTitle(externalUrl){
//document.getElementById("test").innerHTML += "<bR>in title";
$.ajax({
url: "https://crossorigin.me/"+externalUrl,
success: function(data) {
document.getElementById("test").innerHTML += "success";
var matches = data.match(/<title>(.*?)<\/title>/);
alert(match[1]);
return(matches[1]);
},
error: function(e) {
document.getElementById("test").innerHTML += "error";
alert("error! " + e);
}
});
}
function urlifyAndDisplayTitle(){
var text = document.getElementById("url").value;
//document.getElementById("test").innerHTML += "found text <br>";
var url = urlify(text);
//document.getElementById("test").innerHTML += "found url " + url;
var title = "<a href = '"+url+"'>"+getTitle(url)+"<a>";
//document.getElementById("test").innerHTML = "<br>found title" + title;
var newText = text.replace(url,title);
document.getElementById("url").innerHTML = newText;
}
You can use a method call onblur
event of text area or input box as follows
<textarea rows="4" cols="50" type="text" value="" id="url" onblur="urlifyAndDisplayTitle()"> </textarea>