Embedding Twitter Status

In building this iteration of the blog, I decided to follow that trendiest of trends and embed my latest Twitter status on my sidebar. Despite having been on Twitter for awhile and having my site linked from my Twitter account, I didn't really have anything pushing people from my site back to Twitter.

Problem solved: add status to sidebar. But what's the best way to keep it up to date? I could pull in my Twitter status via PHP and display it on every request. Polling that often isn't very practical. I could cache that data. That makes sense. This is how I do the delicious.com sidebar links. About once an hour, it'll pull in the 5 most recent links and display them.

However, I can sometimes get into a spree of updates and I don't necessarily want the sidebar to get out of sync too quickly. It's also not critical information. Due to the transient nature of this less important information, I wanted to keep the burden on my servers to a minimum. As a result, I decided to look at embedding a Twitter badge on my site.

Twitter Badges

Twitter offers up a few different ways to embed a badge on your site that automatically pulls in your latest status updates. If you choose Other, you have the choice between Flash or HTML-based widgets.

I took a look at the HTML-based version and noticed that it calls in two scripts. One has a function that creates new nodes in an HTML unordered list. The other makes a call to the API but using a callback approach:

<script src="http[...].json?callback=twitterCallback&amp;count=5"></script>

Within the JSON API call, a callback function is specified along with a count. All I had to do then was define my own callback function and change the count to 1 (since I only want the very latest entry).

The callback approach returns a JSON format and passes that information through to the function name I specified.

The HTML

First, let's take a look at what my default HTML looks like:

<div id="twitter" class="container">
	<a href="http://twitter.com/snookca"><img src="/img/twitter.png" alt="Follow me on Twitter"></a>
	<p><a id="twitter-post" 
		href="http://twitter.com/snookca">I say witty things on Twitter.</a></p>
</div>

When users don't have JavaScript enabled (or if the script fails to run for whatever reason), the default code is perfectly usable. It still links people to my twitter account with a little tagline to hopefully draw people to check it out.

I've added an ID, twitter-post, to the link as I'll use that to retrieve the element in my callback function.

Always consider what should happen when users don't have JavaScript enabled.

The JavaScript

Here's the callback function that Twitter will call:

function twitterCallback(o) {
o = o[0]; // o is always an array, so just get the first (and only entry)
var e = document.getElementById('twitter-post');
e.innerHTML = o.text;
e.href = 'http://twitter.com/snookca/status/' + o.id;
}

When Twitter runs the callback, it'll return an array of statuses. With only one status to retrieve, the script goes ahead and assigns that to a simple variable. Then I grab my twitter-post link and change the contents from my witty default to my current status. I also change the URL to point to that specific tweet, instead of simply linking to my Twitter home page.

And that's it! Four lines of code with not a single JavaScript framework to be found!

Published February 18, 2009 · Updated February 18, 2009
Categorized as JavaScript
Short URL: https://snook.ca/s/930

Conversation

38 Comments · RSS feed
Mike T. said on February 18, 2009

Very nice. I especially like how your version degrades without JavaScript--I don't think I've seen that before.

Lim Chee Aun said on February 18, 2009

I think the callback function should have some fallback checking in case Twitter (API) is down? :P

Jonathan Snook said on February 18, 2009

@Lim Chee Aun: The callback function only gets called if the script from Twitter loads. So, if Twitter is down, callback doesn't run. Problem solved. :)

saurabh shah said on February 18, 2009

nice post ... short and simple :) ... thanx for sharing ..

Jason Lengstorf said on February 18, 2009

I had written a custom solution as well, but this one is far and away easier than mine.

Kind of makes mine look like a DailyWTF, actually...

Thanks!

Paul Decowski said on February 19, 2009

I’m curious about your decision to link a tweet’s text to the status on Twitter. This way if you post a link (or @) it won’t be clickable directly from your website.

Wouldn’t it be a smarter choice to include the “posted X ago” and permalink that, leaving the ability to click on any links in your tweet?

Of course you’d need to parse the @s and links because Twitter returns plain text (that’s what I do on my website, if you want regexes—give me a shout).

Jonathan Snook said on February 19, 2009

I linked it through to the status because of two reasons. 1) The twitter badge isn't meant to disemminate information (that's what I have the blog and delicious links for). Which leads me to number 2) The twitter badge is meant to let people know that I Twitter, so I'm trying to direct people to my Twitter page.

Ben Carlson said on February 19, 2009

Would it be a good idea to only display specific tweets with a self-defined hashtag? Maybe #w for website. I'm certainly not the perfect Twitter user, but I know that some of my tweets aren't valuable: a reply to someone's comment, a thank you to someone helping me out, etc. With a hash tag I could make sure that what's on my web site is relevant.

Just a thought.

Michael Hoskins said on February 19, 2009

Thanks for this post. I was under the impression that Twitter could only be accessed through a specific API that I didn't want to learn. I was able to get a basic Twitter sidebar going in about 10 minutes this way.

John Cartago said on February 19, 2009

I've seen different ways to embed twitter updates, but this way seems to load so much faster than ones I've previously used. Thanks for the share!

Chris said on February 19, 2009

A few months ago I wrote my own, solely-image-based Twitter badge, and decided to throw a frontend on it for public use.

You can find it at http://twitstamp.com

It updates every 15 minutes right now, because realtime updates were killing the server.

Chris Wallace said on February 19, 2009

I like the simplicity of your twitter badge. I am using a WordPress plugin that my homeslice Rogie gave me that makes use of Twitter Search. It basically pulls my own tweets and @replies into the stream so it turns it into a conversation. It caches the tweets for 15 minutes.

Matthew Pennell said on February 20, 2009

I went the slurp and cache route with my Twitter status when I redesigned, but I like this approach too, especially the fallback (mine is that if Twitter is down, I still have the last successful tweet cached as static HTML).

One thing I did add was some basic language parsing - removing "is" or "has" from the start (if present), capitalising the first word, and converting URLs and @replies into live links.

Byron Rode said on February 22, 2009

I am busy designing my new blog and saw this in NewsFire.

It is a very interesting approach, but wanted a bit more functionality, so I had a look through their function they call to style the output and took it apart a bit and used what I could from their function in my own, and mine now is pretty much similiar to that of most apps.

all @links work, as well as showing the relative time, with a link to the actual status on Twitter.com as well as the app used to make the last tweet.

Code included below. Lets hope it shows correctly.


function twitterCallback(o) {
	obj = o[0];
	var output = document.getElementById('twitter-text');
	output.text = obj.text.replace(/((https?|s?ftp|ssh)://[^"s<>]*[^.,;'">:s<>)]!])/g,function(F){return''+F+""}).replace(/B@([_a-z0-9]+)/ig,function(F){return F.charAt(0)+''+F.substring(1)+""});
	output.src  = obj.source;
	output.href = 'http://twitter.com/byronrode/status/' + obj.id;
	output.time = '' + get_relative_time(obj.created_at) + '';

	function get_relative_time(obj){
		var b=obj.split(" ");
		obj=b[1]+" "+b[2]+", "+b[5]+" "+b[3];
		var a=Date.parse(obj);
		var d=(arguments.length>1)?arguments[1]:new Date();
		var e=parseInt((d.getTime()-a)/1000);
		e=e+(d.getTimezoneOffset()*60);
		if(e<60){return"less than a minute ago"}else{if(e<120){return"about a minute ago"}else{if(e<(60*60)){return(parseInt(e/60)).toString()+" minutes ago"}else{if(e<(120*60)){return"about an hour ago"}else{if(e<(24*60*60)){return"about "+(parseInt(e/3600)).toString()+" hours ago"}else{if(e<(48*60*60)){return"1 day ago"}else{return(parseInt(e/86400)).toString()+" days ago"}}}}}}
	};

	output.innerHTML = output.text + '<span class="twitter-info">' + output.time + ' via ' + output.src + '</span>' ;

}
Byron Rode said on February 22, 2009

The code showed nicely, but due to the availability of HTML within the comments some of code was converted to an actual link. Full code can be found here.

http://pastebin.com/f3075854

Jason Green said on February 24, 2009

Nice tutorial! Cheers

Nick Rinylo said on February 25, 2009

I have installed the HTML and java and it doesn't seem to recall my latest post. Can i just put the java in a general script file or does it need to be embedded into the html?

I think i may be doing it slightly wrong.

Remy Sharp said on February 25, 2009

For those asking about linkifying the @replies - I wrote a small Twitter library that gives you a bunch of options, but also includes some pretty solid linkify logic - which you're more than welcome to steal :-)

Just run the o.text through the following function:

function linkify(s) {
  var entities = {
    '"' : '&quot;',
    '&' : '&amp;',
    '<' : '&lt;',
    '>' : '&gt'
  };

  return s.replace(/[A-Za-z]+://[A-Za-z0-9-_]+.[A-Za-z0-9-_:%&?/.=]+/g, function(m) {
    return m.link(m);
  }).replace(/(^|[^w])(@[dw-]+)/g, function(d, m1, m2) {
    return m1 + '@<a href="http://twitter.com/' + m2.substr(1) + '">' + m2.substr(1) + '</a>';
  }).replace(/"&<>/, function (m) {
    return entities[m];
  });
}
zeen said on March 02, 2009

If this site is in CakePHP then check out the model I created on my site which will grab your Twitter feeds. It needs a bit of fine tuning though.

J.Naveen said on March 03, 2009

Hi, this is really impressed but I have a doubt you said twitter will call the call back function that is written by us and placed in our page. actually i am trying to write a code that is I want to provide a widget to my site when the user looking at my articles if he is logged in gmail account in the another tab or in the another window then I have to show the message dialogue box when ever he gets the messages from others so I to did the same thing

script src='http://mail.google.com/mail/?callback=testing'
but my call back function is not getting call so how to achieve this cross domain call problem

Jonathan Snook said on March 03, 2009

@J.Naveen: The callback is part of the Twitter API. It literally creates the code to call that function you define as the callback. But it's not something that all sites offer. Google Mail in all likelihood does not offer that capability and it will not work, no matter what you do.

J.Naveen said on March 04, 2009

thx....

Phim Online said on March 07, 2009

I wonder if this Twitter application can bring benefit to my website. But however, I would like to try it out since in seems interesting and beneficial to my website.

Trouwen said on March 09, 2009

Sweet, I never noticed the badges provided. I'll probably implement one on my site this week!

Katelyn Cole said on March 11, 2009

So much information, so little mind to try and put it into, mine!!!! Thanks!!!

Sofft said on March 28, 2009

Thanks for the code, I was searching all over for it.

Pallian said on April 08, 2009

Give http://www.tweetizen.com a try - we're a vancouver based startup and have hopefully made twitter grouping and embedding effortless.

Holly said on April 13, 2009

Like 8 Ben Carlson (February 19, 2009), I'm looking to have my javascript output a more defined json result set, defined by a hashtag and a username. Any thoughts on how to structure this URL?

web design norwich said on April 24, 2009

Thanks for sharing this useful feature

Naveed Dastgir Chheena said on May 12, 2009

hi guess do any one help me!
I want to update the status from my clients website. This is working ok. but i want to change the tag "form web" to "from chheena" on clicking "chheena" it will redirect to my site.
How can i change this tag.
Thanks for helping be before.

Kevin said on February 13, 2011

Is there any way to set this up so that each List Item automatically has a different class (ie. tweet1, tweet2, tweet3)? This would be useful for me because I want each tweet to be a different color, so that the older ones blend in with the background and the newer ones contrast more. The effect I'm going for is that the tweets are more prominent as they get newer, or more faded as they get older. If anyone has advice, feel free to email me at kevindosi at g mail dot com.

Jonathan Snook said on February 13, 2011

@kevin, in my case, I had just wanted the most recent one. If you were to loop through each of the statuses, it would be a matter of doing something like el.className = "tweet" + i; where i is the variable inside a for loop.

Justin said on March 29, 2011

Jonathan, thanks for the how-to, very well laid out.

A question though: You said "I could pull in my Twitter status via PHP and display it on every request. Polling that often isn't very practical."

Why not? I actually did this on a site, and it seemed to work great. Is this something I should be avoiding? Would this be that much more server intensive than querying a server each time you load a page?

I'm experienced enough to eventually get a page to do what I want it to, and new enough that it still is occasionally a spectacularly inefficient way to do it. Working on that. . .

Thanks,
Justin

Jonathan Snook said on March 29, 2011

@Justin: You're depending on the speed and availability of twitter on every page request. If Twitter goes down, a stalled request to their API could slow your site to a crawl. In my case, I pull in Twitter, Delicious, and Flickr feeds. These requests are cached so as not to impact every page view. You may not notice the performance issues on a small site but ramp up your traffic and you'll start to see bottlenecks.

Justin said on March 31, 2011

@Jonathan: Ah, thank you. That clears up a lot.

Although, I am curious: Is it only if Twitter goes down that you'd have problems? Couldn't you just do a PHP query at the beginning, some if() statement that checks if the queries are coming back correctly?

This is all just academic for me at this point as you have already provided a very nice solution to this issue.

Jonathan Snook said on March 31, 2011

@Justin: If you're relying on a 3rd party API of any service on every request, then you still have to deal with the problem of it going down. If the servers are slow, when do you time things out? Your page should be loading in one or two seconds at most. The data used to build the page should be cached and/or locally accessible as much as possible.

Justin said on April 01, 2011

Thank you! I shall add this to my practices whenever it's applicable. It wasn't something I thought of, though after you've explained the issues it seems painfully obvious.

Also, thank you for your fast responses; I see that this topic is several years old. I appreciate you still taking the time to revisit it.

Andy said on April 27, 2011

How exactly is all of this set-up? Does the function twitterCallback javascript code go into a script tag in the HTML doc? Also, do I include the json?callback script in the HTML doc too? Any direction would be great! Thanks!

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.

Want to learn about scaling CSS for large projects?

I'm available for full and half-day workshops on scalable CSS architecture. I can provide on-site training for your team. Interested?
Get in touch.