How to easily display a twitter feed using javascript

easily-display-java

Update: March 2013

This method of retrieving timeline data from Twitter is going to be shut down very soon. Please see my follow up article on the death of the Twitter API v1 for more details on why it will no longer be possible to use JavaScript for the Twitter API.


Twitter. For better or worse it's everywhere. You'd be hard pressed to find a new website or blog that is not incorporating a twitter feed into the site somewhere. There are tons of plugins, libraries, and extensions that help you get up and running with a twitter feed quickly, but many times they can be overkill for what you need.

One of the great things about twitter is how accessible it is. The team at twitter has done a really good job of creating an API that is simple, powerful, and flexible all at the same time. If you just need to read a single timeline (your own or someone else) you can skip all the 3rd party plugins and libraries and just roll your own JavaScript solution.

The example I'm going to discuss could be used to read a list of status updates for a user, or just the latest tweet, and display it anywhere you like in a website or blog. For convenience sake I'm using jQuery since we are generally using it in every project these days anyway.

Getting the data URL

Twitter's API is pretty straight forward, you can get to whatever data you need with ease by reading their REST documentation. In our case, we are using the Get Statuses method call. The syntax is:

https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count=1

In our case we are limiting the response to 1 because we are only concerned with the latest tweet. If you remove the count parameter you get back the most recent 15 status updates. You can use the same URL to get the timeline of the account you are interested in, just replace cypressnorth.json with youraccountname.json.

Similarly, if you'd prefer to work with XML, you can change the extension of the request to youraccountname.xml and XML will be returned.

Making the AJAX Request

Now that we know the URL to retrieve our data, it's time to make the request. In my case I'm only interested in working with JSON data, so to save time I can use the jQuery $.getJSON() function to both make the request and parse the results. An added benefit of using this shortcut is that it is compatible with Internet Explorer so you don't need to make a separate XDR request.

$(document).ready(function() {
	loadLatestTweet();
});

function loadLatestTweet(){
	var _url = 'https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count=1';
	$.getJSON(_url,function(data){
		//data is holding a JSON object
	});
}

We now have the timeline back as JSON in the data object.

Building the HTML

Now that we have the status update, we need to display it somewhere. An easy way to do it is to create a <DIV> element with a unique ID for your twitter feed like so:

<div id="twitter-feed"></div>

Using jQuery, you can fill this div with the twitter response:

function loadLatestTweet(){
	var _url = 'https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count=1';
	$.getJSON(_url,function(data){
		var tweet = data[0].text;
		$("#twitter-feed").html('<p>'+tweet+'</p>');
	});
}

You have successfully retrieved your twitter status update and placed it on the page. The trouble is, it looks terrible and is pretty useless at the moment. Usually when you see a twitter post, it has links to the @Users and #hashtags mentioned in the posts and shows the date stamp of the update.

Parsing the Response

To make the status update more friendly and meaningful, we want to parse out any URL's, @Usernames, and #Hashtags so that they are links. In addition we want to parse the date stamp of the update into a nice format which links to the original status update. To do that, we have a date parsing function and 3 JavaScript extensions to make our lives easier (thank you to Simon Whatley for the prototype extensions).

//Twitter Parsers
String.prototype.parseURL = function() {
	return this.replace(/[A-Za-z]+://[A-Za-z0-9-_]+.[A-Za-z0-9-_:%&~?/.=]+/g, function(url) {
		return url.link(url);
	});
};
String.prototype.parseUsername = function() {
	return this.replace(/[@]+[A-Za-z0-9-_]+/g, function(u) {
		var username = u.replace("@","")
		return u.link("http://twitter.com/"+username);
	});
};
String.prototype.parseHashtag = function() {
	return this.replace(/[#]+[A-Za-z0-9-_]+/g, function(t) {
		var tag = t.replace("#","%23")
		return t.link("http://search.twitter.com/search?q="+tag);
	});
};
function parseDate(str) {
    var v=str.split(' ');
    return new Date(Date.parse(v[1]+" "+v[2]+", "+v[5]+" "+v[3]+" UTC"));
}

Using these methods we can create a nice looking and helpful status update with ease:

function loadLatestTweet(){
	var _url = 'https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count=1';
	$.getJSON(_url,function(data){
		var tweet = data[0].text;
		var created = parseDate(data[0].created_at);
                var createdDate = created.getDate()+'-'+(created.getMonth()+1)+'-'+created.getFullYear()+' at '+created.getHours()+':'+created.getMinutes();
                tweet = tweet.parseURL().parseUsername().parseHashtag();
		tweet += '<div class="tweeter-info"><div class="uppercase bold"><a href="https://twitter.com/#!/CypressNorth" target="_blank" class="black">@CypressNorth</a></div><div class="right"><a href="https://twitter.com/#!/CypressNorth/status/'+data[0].id_str+'">'+createdDate+'</a></div></div>'
		$("#twitter-feed").html('<p>'+tweet+'</p>');
	});
}

*Note: The reason for the parseDate() function is to normalize the date format as it is not the same across browsers. If you skip that step it may fail in Internet Explorer (surprise).

Full Solution

Bringing it all together you have the full script ready for use, all you need to do is edit the HTML and CSS to suite your needs.

You can download the script and sample HTML file here: Twitter-Feed-Reader.zip

$(document).ready(function() {
	loadLatestTweet();
});

//Twitter Parsers
String.prototype.parseURL = function() {
	return this.replace(/[A-Za-z]+://[A-Za-z0-9-_]+.[A-Za-z0-9-_:%&~?/.=]+/g, function(url) {
		return url.link(url);
	});
};
String.prototype.parseUsername = function() {
	return this.replace(/[@]+[A-Za-z0-9-_]+/g, function(u) {
		var username = u.replace("@","")
		return u.link("http://twitter.com/"+username);
	});
};
String.prototype.parseHashtag = function() {
	return this.replace(/[#]+[A-Za-z0-9-_]+/g, function(t) {
		var tag = t.replace("#","%23")
		return t.link("http://search.twitter.com/search?q="+tag);
	});
};
function parseDate(str) {
    var v=str.split(' ');
    return new Date(Date.parse(v[1]+" "+v[2]+", "+v[5]+" "+v[3]+" UTC"));
}

function loadLatestTweet(){
	var _url = 'https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count=1';
	$.getJSON(_url,function(data){
		var tweet = data[0].text;
                var created = parseDate(data[0].created_at);
                var createdDate = created.getDate()+'-'+(created.getMonth()+1)+'-'+created.getFullYear()+' at '+created.getHours()+':'+created.getMinutes();
                tweet = tweet.parseURL().parseUsername().parseHashtag();
		tweet += '<div class="tweeter-info"><div class="uppercase bold"><a href="https://twitter.com/#!/CypressNorth" target="_blank" class="black">@CypressNorth</a></div><div class="right"><a href="https://twitter.com/#!/CypressNorth/status/'+data[0].id_str+'">'+createdDate+'</a></div></div>'
		$("#twitter-feed").html('<p>'+tweet+'</p>');
	});
}

UPDATE API 1.1

To load more than just the latest tweet, modify the loadLatestTweet() function to look like the following (and change the count parameter to the number of tweets you want):

function loadLatestTweet(){
	var numTweets = 1;
    var _url = 'https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count='+numTweets+'&include_rts=1';
    $.getJSON(_url,function(data){
    for(var i = 0; i< data.length; i++){
            var tweet = data[i].text;
            var created = parseDate(data[i].created_at);
            var createdDate = created.getDate()+'-'+(created.getMonth()+1)+'-'+created.getFullYear()+' at '+created.getHours()+':'+created.getMinutes();
            tweet = tweet.parseURL().parseUsername().parseHashtag();
            tweet += '<div class="tweeter-info"><div class="uppercase bold"><a href="https://twitter.com/#!/CypressNorth" target="_blank" class="black">@CypressNorth</a></div><div class="right"><a href="https://twitter.com/#!/CypressNorth/status/'+data[i].id_str+'">'+createdDate+'</a></div></div>'
            $("#twitter-feed").append('<p>'+tweet+'</p>');
        }
    });
}

27 Comments

  1. Author's Headshot
    Thomas van Zuijlen March 19, 2012
    Reply

    Thanks for the easy-to-follow guide, Matt!

    Something to take note of with regard to date parsing: The code you've posted here, will produce a zero-based month number (e.g. created.getMonth() returns a '2' for March) and a day number based on the day of the week rather than that of the month (e.g. created.getDay() returns a '0' for Sundays).

    To hammer out a more human-comprehensible date display, I've substituted line 32 of your Full Solution code example with the following:

    var createdDate = created.getDate()+'-'+(created.getMonth()+1)+'-'+created.getFullYear()+' at '+created.getHours()+':'+created.getMinutes();

    So adding 1 to the month obtained from created.getMonth, and replacing the week-based created.getDay with the month-based created.getDate. Also, I've added created.getFullYear() to get the tweet's year.

    The above line results in something like '19-03-2012 at 15:21' for March 19th, 3:21 PM.

    Hope this is a decent addition to your solution!

    • Author's Headshot
      Matt Mombrea March 19, 2012

      Thanks Tom, I've updated the solution with your contribution. I admit the date formatting was done hastily, In the actual project I was using the jQuery DateFormat extension but refactored it out of the example. I should have done more testing!

    • Author's Headshot
      Thomas van Zuijlen March 19, 2012

      Ah, I see. Thanks for the quick reply - and thanks again for the clever solution.

  2. Author's Headshot
    Mike May 7, 2012
    Reply

    I think there might be a typo in the code. When I run the example, I get the following error:

    Uncaught SyntaxError: Unexpected token . it seems there is a missing + before
    'created.getHours()+'

    It should be '+created.getHours()+'

    I'm a noob. So forgive me if I've just embarrassed myself. 😉

    • Author's Headshot
      Matt Mombrea May 7, 2012

      You are quite right, thanks for the catch. I've updated the post as well as the example project.

  3. Author's Headshot
    Eric September 5, 2012
    Reply

    Hey Matt!

    First of all, nice work!

    I have noticed one thing that's not working tho(assuming I've done it all correctly). If I set the count to, let say, five and on the timeline I'm displaying there are 3 tweets, 1 retweet and then 1 more tweet. The script only displays a total of 4 tweets instead of just showing the next tweet(making it five). Or why not show retweets aswell?

    The reason why this is important to me is that I have a client who want to display the 5 latest tweets and I can't really tell them not to retweet anything or else they'll mess it up.

    Is there a solution for this? Let me know if you need any code etc.

    Cheers!
    /Eric

    • Author's Headshot
      Matthew Mombrea September 5, 2012

      Eric,

      Thanks! This example is not currently set up for multiple tweets, just the latest 1. To modify it to handle more tweets you'll need to change the function loadLatestTweet(). I've added an example to the end of this post.

  4. Author's Headshot
    Eric September 6, 2012
    Reply

    Hey Matt,

    Thanks you for the quick response! Your solution worked great but there is still the problem with the feed skipping retweets and thus showing the incorrect tweetcount.

    Is this something that can be fixed? Either show all posts on the chosen timeline or continue to pick just the tweets, ignore all the retweets and still show the correct count.

    Cheers,
    Eric

    • Author's Headshot
      Matthew Mombrea September 6, 2012

      Eric,

      My mistake. It doesn't look like version 1 of the API includes retweets in the feed but does count them toward your max results. I've updated the example to use the API v1.1 with the include_rts=1 flag set which seems to work better. I've also updated the project file download to reflect this change. I think that should solve the issue for you.

  5. Author's Headshot
    Eric September 7, 2012
    Reply

    Matt,

    That's just great! Thank you so much for your expertice and quick response.

    All the best,
    Eric

  6. Author's Headshot
    Dave October 1, 2012
    Reply

    Hi, thanks for explaining and sharing! I looked at the .js file and it doesn't look like you're using the API 1.1. I've been trying to understand how that works because we need to Authenticate to get the data back from Twitter.

    Have you been able to make this approach work with the 1.1 API?

    Kind regards,
    Dave

  7. Author's Headshot
    Adam J October 11, 2012
    Reply

    Thanks so much for this. I've been looking for examples of 1.1 recent tweet widgets. This was perfect. They should really have more straightforward documentation on the twitter dev site.

  8. Author's Headshot
    kevin October 11, 2012
    Reply

    Thanks for that, i've been looking for a while for a reliable solution. This works just fine.

  9. Author's Headshot
    Johan Danforth October 24, 2012
    Reply

    Hi, good post but you're not Calling the version 1.1 api, which requires oauth to work. Version 1.0 of the api is said to stop working in april 2013 :/

  10. Author's Headshot
    Sean C January 26, 2013
    Reply

    Thanks for this clear well-written post, but would also love to see an update that addresses the recent 1.1 changes to the Twitter api which requires OAuth.

  11. Author's Headshot
    chris February 18, 2013
    Reply

    How would I go about changing the text colour? I have tried CSS and that changes everything but the hashtag, date and username?

    Cheers
    Chris

    • Author's Headshot
      Matthew Mombrea February 18, 2013

      Chris,

      You can add a css style for the following selector:
      #twitter-feed p{color:green;}

  12. Author's Headshot
    Apostolis March 4, 2013
    Reply

    Maybe it's a bit late for this party guys but a have a noobie question. The first line of code with the https where should I put it? I can imagine after the in terms of getting the data etc. but I can't put it in a tag because it treats the "//" as a comment in JavaScript language. Sorry I am so new in JavaScript / jQuery.
    Cheers!

    • Author's Headshot
      Matthew Mombrea March 4, 2013

      That first code snippet is just an example of the API call that will be made later, it's not meant to go into your code.

      Toward the bottom of this post is a link to the source code for this example that you can download and it should work out of the box.

      As a heads up, this method of retrieving twitter timelines via javascript is going to be shut down by twitter very soon and will no longer work.

      See here for a follow up: http://www.itworld.com/unified-communications/343649/death-twitter-api-or-new-beginning

  13. Author's Headshot
    Ellis May 3, 2013
    Reply

    Around 150 games in total, but that's relatively small compared to our users. Don't leave the landscape designing
    and terrain optimization to the last moment. Well, you
    can have that same chess engine on your Android
    mobile phone, courtesy of Droid - Fish.

  14. Author's Headshot
    Chris H June 11, 2013
    Reply

    Twitter no longer allows unauthorised requests for public tweets.. Any chance we can get an update using oAuth, which is now required?

    Cheers.

  15. Author's Headshot
    Tom July 4, 2013
    Reply

    Checkout this post if anyone needs a JavaScript twitter feed and guide that authenticates (via PHP) for public timelines
    http://www.webdevdoor.com/javascript-ajax/custom-twitter-feed-integration-jquery/

  16. Author's Headshot
    Alamin August 20, 2013
    Reply

    I have downloaded the zip file but it is not working. Why?

  17. Author's Headshot
    Th@guy January 30, 2014
    Reply

    You should maybe update this to reference the new API 1.1 OAuth requirements - Or at least make a statement about the update at the top of the post...

    • Author's Headshot
      Matthew Mombrea January 31, 2014

      You mean like the very first statement in a huge title tag at the top of the post? Along with the one at the bottom?

  18. Author's Headshot
    Balu March 26, 2017
    Reply

    Hi Matthew,

    I tried to use this functionality but getting below error,
    /**/({"errors":[{"message":"The Twitter REST API v1 is no longer active. Please migrate to API v1.1. https://dev.twitter.com/docs/api/1.1/overview.","code":64}]});

    Can you please suggest the solution for this issue.

Leave a Reply

Your email address will not be published. Required fields are marked *

Meet the Author

mmombrea-headshot
CTO / Partner

Matthew Mombrea

Matt is our Chief Technology Officer and one of the founders of our agency. He started Cypress North in 2010 with Greg Finn, and now leads our Buffalo office. As the head of our development team, Matt oversees all of our technical strategy and software and systems design efforts.

With more than 19 years of software engineering experience, Matt has the knowledge and expertise to help our clients find solutions that will solve their problems and help them reach their goals. He is dedicated to doing things the right way and finding the right custom solution for each client, all while accounting for long-term maintainability and technical debt.

Matt is a Buffalo native and graduated from St. Bonaventure University, where he studied computer science.

When he’s not at work, Matt enjoys spending time with his kids and his dog. He also likes to golf, snowboard, and roast coffee.