How to easily display a twitter feed using javascript
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
Leave a Reply
Meet the Author
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.
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!
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!
Ah, I see. Thanks for the quick reply - and thanks again for the clever solution.
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. 😉
You are quite right, thanks for the catch. I've updated the post as well as the example project.
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
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.
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
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.
Matt,
That's just great! Thank you so much for your expertice and quick response.
All the best,
Eric
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
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.
Thanks for that, i've been looking for a while for a reliable solution. This works just fine.
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 :/
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.
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
Chris,
You can add a css style for the following selector:
#twitter-feed p{color:green;}
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!
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
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.
Twitter no longer allows unauthorised requests for public tweets.. Any chance we can get an update using oAuth, which is now required?
Cheers.
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/
I have downloaded the zip file but it is not working. Why?
Alamin,
This method will no longer work now that Twitter forces API v1.1 with OAuth. Have a look at this proxy you can use to re-enable this functionality: https://github.com/mombrea/twitter-api-php-cached
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...
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?
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.