
Bookmarklets, Twitter, TinyURL, and bit.ly – Lessons Learned
September 10, 2008When I first started playing with Twitter, I wanted to be able to easily post the link of any page I was reading in a tweet. That was easy enough when browsing on my computer, but the lack of cut and paste on my iPhone seemed to make it impossible to share pages found while browsing the internet in my pocket.
Then I remembered that bookmarklets can be used to add a lot of functionality to the iPhone. Surely, I thought, someone has written a bookmarklet to shorten a URL and post it to Twitter. And I was right, but nothing I found was exactly what I was looking for.
- TwitThis is dependant on the third party TwitThis.com and requires entering your Twitter name and password into that site. Non-starter.
- A post at myopiclunacy was promising, but turned out to require setting up a PHP page on a server. I was looking for a 100% browser solution.
- The URL shortening services such as TinyURL, bit.ly, and is.gd all provide stock bookmarklets, but those don’t address the Twitter posting.
C’mon, I thought, I’m not the first guy wanting to Twitter from an iPhone. Why has no one written a simple bookmarklet that calls the shortening service API for the current URL and then redirects the user to Twitter populating the status textbox with the shortened URL?
As usual, the internet is smarter than me, and there are a few reasons why my dream bookmarklet doesn’t exist.
Twitter Shortens URLs Automatically
As you may have been screaming at me to this point, Twitter already does URL shortening. Just include your long URL in your tweet, and if it’s longer than a certain number of characters, Twitter calls TinyURL behind the scenes and includes the shortened URL in the tweet that everyone sees. Knowing that, you can just populate the full URL of the current page to the Twitter status textbox with the following bookmarklet:
javascript:void(location.href='http://twitter.com/home?status='+location.href)
To try it, just create a new browser bookmark and copy the above line as the bookmark location. And with that bookmark synced to my iPhone, I can easily post a tweet linking to the great site I’m on right now.
However, this solution is not perfect:
- TinyURL is the only option. If you are preferential to bit.ly or is.gd, too bad.
- When you visit twitter from an iPhone (and likely any mobile browser), you get redirected to Twitter’s mobile site. The status text box on the mobile site only allows 140 characters of input. So if your URL is 80 characters, you only have 60 characters left for the rest of your tweet despite the fact that the URL will eventually be shortened. And URLs can get a lot longer than 80 characters.
- It can be ungainly to type the rest of your twitter post into the mobile site when the input box is already populated with a long URL, especially if you were hoping to add text both before and after the URL.
Bookmarklets Can’t Do That
If no one else was going to write the obvious URL-shortening Twitter bookmarklet, I guessed it was up to me. I came up with the following, formatted for readability:
javascript:(function(){
var xmlhttp=false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
@end @*/
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
try {
xmlhttp = new XMLHttpRequest();
} catch (e) {
xmlhttp=false;
}
}
if (!xmlhttp && window.createRequest) {
try {
xmlhttp = window.createRequest();
} catch (e) {
xmlhttp=false;
}
}
var url = escape(location.href);
//xmlhttp.open("GET", "http://tinyurl.com/api-create.php?url="+url,true);
//xmlhttp.open("GET", "http://is.gd/api.php?longurl="+url,true);
xmlhttp.open("GET", "http://bit.ly/api?url="+url,true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
location.href="http://twitter.com/home?status=" + xmlhttp.responseText
}
};
xmlhttp.send(null)
})()
Everything up to the declaration of the “url” var is boilerplate code to get a browser-appropriate XMLHttpRequest object, which is needed to call the URL shortening service. Next, we open a connection to the REST API at our URL shortening service of choice. Then we set a function to be called when the request is complete that redirects us to Twitter with the shortened URL. Finally, the request is sent. Awesome, right?
Too bad it doesn’t work.
If you want to try the bookmarklet, create a new bookmark with the crunched version of the above code (remove the line breaks):
javascript:(function(){var xmlhttp=false;if(!xmlhttp&&typeof XMLHttpRequest!='undefined')
{try{xmlhttp=new XMLHttpRequest();}catch(e){xmlhttp=false;}}
if(!xmlhttp&&window.createRequest){try{xmlhttp=window.createRequest();}
catch(e){xmlhttp=false;}}var url=escape(location.href);
xmlhttp.open("GET","http://bit.ly/api?url="+url,true);
xmlhttp.onreadystatechange=function(){if(xmlhttp.readyState==4){
location.href="http://twitter.com/home?status="+xmlhttp.responseText}};
xmlhttp.send(null)})()
When you click the bookmark, nothing will happen and you’ll see an error in your browser’s javascript error console saying something like “Access to restricted URL denied” or “NS_ERROR_DOM_BAD_URI”. The problem is that, for security reasons, browsers do not allow the XMLHttpRequest object to open connections to any server other than the one hosting the current page. What might not be obvious (and wasn’t to me) is that javascript in a bookmarklet is considered part of the current page, so opening a connection to any URL shortening service using my bookmarklet will fail because that service is on a different server than the current page. (The interesting exception to this is if you are actually on the web site of the URL shortening service. In fact, the bookmarklet code above does work if you are on bit.ly’s site.)
So I guess that explains why I can’t find the bookmarket I want on the internet anywhere. At least the next person to try will have this failure story to save their time.
Wait a Minute! That bit.ly Bookmarklet Actually *Is* the Holy Grail
It wasn’t until I starting writing up this post that I took a closer look at the stock bit.ly bookmarklet and said, “What is that javascript doing?” And to my surprise, it does something genius. If you want to try it, go to bit.ly and drag the bookmark link to your browser toolbar, or create a new bookmark and add the following code as the location (remove the line breaks):
javascript:var%20e=document.createElement('script');
e.setAttribute('language','javascript');
e.setAttribute('src','http://bit.ly/bookmarklet/load.php');
document.body.appendChild(e);void(0);
It adds a sidebar to the current page with content pulled from bit.ly’s site, and the sidebar includes the shortened URL and links to various services, including Twitter. I haven’t dug into exactly how it works, but I think it does the URL shortening on the server side and thus avoids the problem I ran into above. And it works like a charm on my iPhone. So a tip of the hat to bit.ly. This is the bookmarklet that I’ll be using.
The bookmarklet that you use from bit.ly indeed is the same the one at myopiclunacy.com as both do the shortening bit on the server side. The difference is that the code at myopiclunacy.com is provided if you wanted to host/alter the code yourself on your own server and, of course, only uses tinyurl.
But thank you for identifying the bit.ly solution. I have to take a look at it.
BTW – the bookmarklet you have would only work if the url shortening service exposed a JSON api. Anything else would need some sort of additional server-side connection.
also check out BigTweet and tr.im.
Excellent article. At first reading I did not understand everything. After stepping throught all the same failures I now understand the complete article #(
Looks like that there is no real alternative to twitthis.com at the very moment. With the backdraft that users have to login at twitthis instead of twitter…