Tutorial Details
- Program: jQuery, Twitter API, PHP, Cron
- Difficulty: Intermediate
- Estimated Completion Time: 60-90 Minutes
Final Product What You'll Be Creating
As of March 2011, the current average number of “Tweets” the world sends per day is 140 million. This tutorial demonstrates how to create a custom Twitter widget from scratch that uses the Twitter API, Web Intents and @Anywhere. Using the Twitter platform to create a fun, interactive tool for your website can be beneficial both in the learning and promotion departments!
A Few Pros and Cons
Pros:
- Greater Customization than the default Twitter widget.
- Cache file prevents problems with Twitter API Rate Limiting and over capacity issues
Cons:
- Requires Twitter oAuth if you want to incorporate the advanced functionality of @Anywhere
- Setting up a Cron Job can be tricky (there are many web hosting server configurations and control panels)
Now, lets get started!
Step 1. Markup and Styling
This tutorial assumes that you have some CSS and HTML knowledge, and starts out with the basic markup and styling for the widget. Note that the content of the widget is located in <div id="tweet"></div> and is created using jQuery, Twitter API and PHP.
The HTML
<!-- Begin Content --> <div id="content"> <!-- Begin Twitter Feed Area --> <div class="twitterfeed"> <img src="images/twitter_bird.png" width="99" height="75" alt="Follow Nettuts+ and Tuts+ on Twitter" /> <h3>Follow <a href="http://twitter.com/envatowebdev">Nettuts+</a> and <a href="http://twitter.com/tutsplus">Tuts+</a> on Twitter</h3> <div id="tweet"></div> </div> <!-- End Twitter Feed Area --> </div> <!-- End Content -->
The CSS
#content .twitterfeed {
float: left;
background-color: #fff;
width: 385px;
margin: 10px 0px 30px 10px;
border: 1px solid #d8d8d8;
padding: 5px 5px 15px 5px;
}
#content img {
margin: 5px 0px 0px 10px;
}
#content h3 {
float: right;
color: #000;
background-color: #f2f2f2;
font-size: 18px;
font-weight: bold;
width: 235px;
padding: 10px 5px 10px 10px;
margin: 10px 10px 25px 0px;
text-shadow: 0 1px 0 #fff;
border: 1px solid #d8d8d8;
}
#content h3 a {
text-decoration: none;
}
#content hr {
width: 90%;
height: 1px;
background: #dfdfdf;
display: block;
border: none;
margin: 20px 0px 20px 18px;
}
#tweet {
float: none;
clear: both;
}
#tweet p {
margin: 15px 15px 10px 15px;
}
#web_intent {
margin: 0px 0px 0px 15px;
}
#web_intent a:link, #web_intent a:visited, #web_intent a:active {
margin: 0px 10px 0px 0px;
}
#web_intent img {
margin: 0px 3px 0px 0px;
position: relative;
top: 2px;
}
#web_intent .time {
margin: 0px 10px 0px 0px;
}
#follow-envatowebdev {
margin: 0px 10px 0px 75px;
}
.log-button {
margin: 10px 10px 0px 115px;
}
The #content ID may need to be changed based on your theme and placement of the widget (Ex. #content, #sidebar, #footer)
Step 2. PHP “Cache File” Script
As of this writing, the Twitter limit for Unauthenticated API calls is 150 requests per hour. OAuth calls are permitted at 350 requests per hour and are measured against the oauth_token used in the request.
To ensure that our custom Twitter widget does not run into problems with Twitter API rate limiting, a PHP “cache file” script needs to be created. This script retreives the Twitter API “GET statuses/user_timeline” information and stores it in a “TXT” file located in the cache directory on your server.
If you do not already have a cache directory, you will need to create one. You will also need to create a directory on your server for the PHP cache file script.
Create a PHP file that contains the following code.
<?php
$cache = dirname(__FILE__) . '/../cache/twitter-json.txt';
$data = file_get_contents('http://api.twitter.com/1/statuses/user_timeline/twitter_screen_name.json?count=3&include_rts=true&include_entities=true');
$cachefile = fopen($cache, 'wb');
fwrite($cachefile,utf8_encode($data));
fclose($cachefile);
?>
The “count=3″ portion of the code controls how many “tweets” will be displayed in your Twitter widget. If you want to display only one tweet, then change the code to “count=1″.
Note that the "&include_rts=true" needs to be included if you want your Twitter widget to display “retweets”. Visit the Twitter API doumentation “GET statuses/user_timeline” for more information and available options.
Step 3. Set Up Cron Job
Next, a Cron job needs to be created that executes the PHP script at a set number of times per hour. How the Cron job is set up depends on your web hosting control panel. Please refer to “Scheduling Tasks with Cron Jobs” for an in depth tutorial.
Below is an example of Cron tab settings for a Plesk control panel that runs a Cron job (4) times per hour (every fifteen minutes), every day.
- Minute = */15
- Hour = *
- Day of the Month = *
- Month = *
- Day of the Week = *
- Command = /usr/bin/curl -s http://your_domain.com/twitter-widget/twitter-cron.php > /dev/null
Step 4. Add jQuery and Twitter Web Intents Script Tags
We need to make sure that our web page references the jQuery library. For this tutorial, the jQuery library is included through the use of the jQuery CDN.
Between the head tags of your web page add
<script src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
In addition to using the Twitter API, the Twitter widget uses Twitter Web Intents to add “Retweet”, “Reply” and “Favorite” functionality.
Just below the jQuery script tag, add
<script src="http://platform.twitter.com/widgets.js"></script>
Step 5. The jQuery Code
An external JavaScript file, “twitter-widget.js,” needs to be created. This JavaScript file contains the jQuery code that generates the “content” of the Twitter widget. The jQuery code retreives the Twitter API information from the cache file that was created by the PHP script in Step two.
In the JS file, add the following jQuery code.
// Display Latest Tweet
$(document).ready(function(){
$.getJSON('cache/twitter-json.txt', function(data){
$.each(data, function(index, item){
$('#tweet').append('<div><p>' + item.text.linkify() + '</p></div>' + '<div id="web_intent">' + '<span class="time">' + relative_time(item.created_at) + '</span>' + '<img src="images/retweet_mini.png" width="16" height="16" alt="Retweet">' + '<a href="http://twitter.com/intent/retweet?tweet_id=' + item.id_str + '">' + 'Retweet</a>' + '<img src="images/reply_mini.png" width="16" height="16" alt="Reply">' + '<a href="http://twitter.com/intent/tweet?in_reply_to=' + item.id_str + '">' + 'Reply</a>' + '<img src="images/favorite_mini.png" width="16" height="16" alt="Favorite">' + '<a href="http://twitter.com/intent/favorite?tweet_id=' + item.id_str + '">' + 'Favorite</a>' + '</div>' + '<hr />');
});
});
jQuery .getJSON() is used to load the JSON-encoded data from the cache TXT File. Using jQuery .append(), the content is displayed through the <div id=”tweet”></div> of the XHTML markup. Each Twitter API item is prefixed with “item.”. The Twitter API items used in the jQuery code are:
- text (item.text) – The text of each tweet
- created_at (item.created_at) – The date each tweet was posted
- id_str (item.id_str) – The unique ID number of each tweet
Editor’s Note: If you’d prefer to get that muddy HTML out of your JavaScript, consider using the jQuery templating plugin.
Step 6. Converting Twitter Time Stamp to Relative Time (Time Ago)
The data that is retrieved using the Twitter API is “raw” data and needs to be fixed up for the Twitter widget.
In the twitter-widget.js file, below the jQuery code, add the following JavaScript code.
// Convert Twitter API Timestamp to "Time Ago"
function relative_time(time_value) {
var values = time_value.split(" ");
time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
var parsed_date = Date.parse(time_value);
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
delta = delta + (relative_to.getTimezoneOffset() * 60);
var r = '';
if (delta < 60) {
r = 'a minute ago';
} else if(delta < 120) {
r = 'couple of minutes ago';
} else if(delta < (45*60)) {
r = (parseInt(delta / 60)).toString() + ' minutes ago';
} else if(delta < (90*60)) {
r = 'an hour ago';
} else if(delta < (24*60*60)) {
r = '' + (parseInt(delta / 3600)).toString() + ' hours ago';
} else if(delta < (48*60*60)) {
r = '1 day ago';
} else {
r = (parseInt(delta / 86400)).toString() + ' days ago';
}
return r;
}
});
This code converts the Twitter Time stamp to relative time, such as “3 hours ago.”
Step 7. Creating Workable Anchor Links
In the twitter-widget.js file, below the convert timestamp code, add the following JavaScript code.
// Create Usable Links
String.prototype.linkify = function() {
return this.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+/, function(m) {
return m.link(m);
});
};
When using the Twitter API, the links contained in Twitter posts are displayed in text format only, not workable anchor links. The above code converts standard URL text only links into workable anchor links.
Step 8. Adding Advanced Features Using Twitter @Anywhere
We have now created a rather neat, custom Twitter widget that includes some basic user interactivity. But what if we want to add really cool, advanced functionality to our Twitter widget? Thanks to the Twitter @Anywhere Service, we can accomplish this fairly easily.
Sign up for the Twitter @Anywhere Service at https://dev.twitter.com/apps/new.
Create a New “App” and complete the steps of the online registration process. Visit this article for detailed help on completing the registration process.
“The callback URL property (Set in your @Anywhere account) of your application must match both the subdomain and domain of the web application utilizing @Anywhere. ”
The next few steps of this tutorial explain how to add Twitter @Anywhere advanced functionality.
Step 9. Add @Anywhere Script Tag
As close to the top of the web page as possible, add the @Anywhere script Tag:
<script src="http://platform.twitter.com/anywhere.js?id=Your_Consumer_Key&v=1"></script>
Note that your Twitter oAuth Consumer Key needs to be added to the script tag.
Step 10. User Login and Authorization
Certain features of the Twitter @Anywhere service do not require the user to be logged into Twitter. Hover Cards and Auto-linkification of Twitter usernames as examples. However, most @Anywhere features DO require the user to login and authorize your site for access. The “Connect with Twitter” button allows users to authenticate securely with Twitter.
Below <div id=”tweet”></div>, add the following code.
<div class="log-button"> <span id="login-logout"></span> <script src="js/twitter-login.js"></script> </div>
Now, create an external JavaScript file “twitter-login.js” containing the following code.
<script>
jQuery(function () {
twttr.anywhere(function (T) {
if (T.isConnected()) {
$("#login-logout").append('<button id="signout" type="button">Sign out of Twitter</button>');
$("#signout").bind("click", function () {
twttr.anywhere.signOut();
});
}
else {
T("#login-logout").connectButton();
}
});
});
</script>
Step 11. Determining the Connected State

@Anywhere provides several ways of determining whether a user is already logged into Twitter and has already granted your application authorization for access. For this tutorial, we are going to use authComplete and signOut events.
Just below the web page <body> tag, add the following:
<script>
twttr.anywhere(function (T) {
T.bind("authComplete", function (e, user) {
// triggered when auth completed successfully
});
T.bind("signOut", function (e) {
// triggered when user logs out
});
});
</script>
By adding the above code, the authComplete and signOut events are now triggered by ANY @Anywhere functionality.
Step 12. Adding Hovercard Functionality

A Hovercard displays data about a Twitter user in a tooltip and also includes a follow/unfollow button.
To add a hovercard that is “expanded” by default, add the following code below the authComplete and signOut code, just below the web page <body> tag:
<script type="text/javascript">
twttr.anywhere(function (T) {
T("#tweet").hovercards({ expanded: true });
});
</script>
Note that if you add Hovercard functionality, the Auto-linkification of Twitter usernames is also added by default. This makes adding the "T.linkifyUsers()" function to your webpage unnecessary.
Step 13. Adding a Follow Button

To add a Twitter follow button to the widget, below <div id="tweet"></div>, add the following code.
<span id="follow-twitter_screen_name"></span>
<script type="text/javascript">
twttr.anywhere(function (T) {
T('#follow-twitter_screen_name').followButton("twitter_screen_name");
});
</script>
Note that you need to add your Twitter screen name to the above code.
Step 14. Adding a Tweet Box

If you would like to add a Tweet Box instead of a follow button, below <div id=”tweet”></div> add the following code.
<div id="tbox"></div>
<script type="text/javascript">
twttr.anywhere(function (T) {
T("#tbox").tweetBox({
height: 90,
width: 350,
});
});
</script>
All Done!
View the completed demo. Creating a Twitter driven widget from scratch that uses the Twitter API, Web Intents and @Anywhere takes a bit of work. However, you can create something interactive and fun for visitors of your website!
Please note that the JavaScript codes for Relative Time and Creating Workable Anchor Links are thanks to this article.
For those of you who would rather create a basic Twitter driven widget without using Twitter oAuth and @Anywhere, there are basic demos included in the source files zip. There are also two demos that display Twitter profile images next to each tweet.
If you have any questions about this tutorial, please ask them using the “Add a Comment Box” below.


I will try it.
Thx
Great tutorial! Is it possible to use this widget to pull in tweets from two different accounts?
Hi Jason,
Your question really interested me, so I did a little research and found a way to retrieve the latest tweets for multiple Twitter screen names. What I ended up doing was creating a Twitter list and then used the Twitter API “GET lists/statuses” to pull the latest tweets from the members on the list. You can set the code to pull a specific “page” of your Twitter list and then set the number of “results” to display. I created a new demo to show how this works: http://www.webcodepro.net/twitter-demo-7/twitter-widget.html There’s a link on the demo page to download the source files of this new demo. I hope this is what you had in mind..
Regards!
Janet
A-M-A-Z-I-N-G !!! Tanks for the tutorial !
WOW! great demo. nice write up! clear and details. Thanks :)
I think the actual usage of this “widget” on your own site, isn’t that useful. Don’t get me wrong, some of the features are, but this seems a bit overkill.
But in a tutorials sense, this isn’t a bad thing at all. The only thing that could be improved on is say this section for example, “Converting Twitter Time Stamp to Relative Time (Time Ago)”. Rather than people blindly copy and pasting this rather quite lengthy function. Why not explain what it’s doing?
Everyone can rip a Twitter widget, there’s no point in re-inveting the wheel. It’s these little tips that go into building it that people really want to know, well me at least anyway.
Hi Benjamin,
I agree, For most sites an advanced widget is probably overkill. Included in the zip file are a few “basic” demos for this reason. My goal for the tutorial is to show people some of the really cool things you can do with Twitter API and other Twitter resources.
I’ll also keep your comment in mind about the “Relative Time” code when I’m writing future tutorials. The more details and explanations that are in a tutorial, the more helpful it will be.
Regards!
Janet
Is there an error in step 5 JS?
hint: closing argument .. just verifying.
Hi Alex,
My eyesight might be going, because I just don’t see it.. Can you explain what you mean?
Thanks!
Janet
@alex,
I think the problem is that the “$(document).ready(function(){” doesn’t have a matching closing brace. It’s easy enough to fix though just add “});” to the end of the script.
your document.ready is function never gets closed. Needs another }); on a new line at end of example.
I did a quick test to see what would happen if I added the closing brace “});” to Step 5 as suggested, and it broke the widget. The document.ready function actually does get closed, but it happens in step 6 after the “Time Ago” code. Next time I’ll try to remember to write a note if a closing tag ends up in a different step of the tutorial. Thanks for the comments!
Nice tutorial. I’ve been wanting to learn the Twitter API and this is a great start for me :-)
Nice Tutorial, Now we can maintain the looks and beauty of the website with this cool look :) But will have to add jquery framework :(
This would make a great WordPress plug-in.
Great Tut @Anywhere Rocks!
Awesome! I was looking for just such a thing!
Great tut. I already have a published twitter plugin for WP myself, but, this gives me some ideas to implement to my next version. i do all my parsing with PHP before being sent to the screen since I want the google spiders to see the text when scanning the source, and is the only reason i have stayed away from making all the functionality with jQuery instead. This looks and functions amazingly though. again, great tut.
Awesome- I love the hovercard, I cant believe I’ve never seen that in the wild before.
Nice Tutorial. Thanks
thank you for this …
would be a great wordpress plugin… :D
No all hosting providers allow cron jobs, so as a work around instead of asking the server to check you could check the the files age over a certain period i.e 10 minutes.
function getTwitterFeed($userid,$limit){
$cache_file = dirname(__FILE__).’/cache/-twitter-cache.xml’;
$last = filemtime($cache_file);
$now = time();
$interval = 600; // ten minutes 600
// check the cache file
if ( !$last || (( $now – $last ) > $interval) ) {
$feed = “http://twitter.com/statuses/user_timeline/”.$userid.”.xml?count=”.$limit;
// cache file doesn’t exist, or is old, so refresh it
if($feed != “”) {
$cache_rss = file_get_contents($feed);
}
if (!$cache_rss) {
// we didn’t get anything back from twitter
// ““;
} else {
// we got good results from twitter
// ““;
file_put_contents($cache_file,$cache_rss);
}
}
return simplexml_load_file($cache_file) or die(“could not connect”);
}
i ll try it? for my site ….. :)
I have a idea. Using this code like a feedback/chatting form.
But I have a question, is it possible to automatically make Tweet Box becomes Reply Box?
I mean in this tweetbox, add a ‘@adminTwitterID’ as default.
How to, please?
Hi – The Tweet Box was added using the @Anywhere service so there is no way that I know of to just change that code and make it a chat/reply box. You could look into using the Twitter API to create some sort of custom Twitter chat box/reply box if the Twitter API offers that functionality. I’m really not sure how to implement the features you are looking for. Thank you for commenting though. Janet
can it be used as a wordpress widget or are there any plugins for it?
Hi – one of the commenters Justin St. Germain mentioned that he already has a WordPress Plugin for something similar to this. I don’t have plans right now to create a WordPress plugin, but maybe sometime down the road I’ll consider doing something like that.. Thank you for commenting! Janet
hey it’s works fine for me ,thanks for the grate tutorial .
Thanks for this tutorial. It works really fine and also helped me to get more followers.
Thank you for the comments.. I’m glad that you were able to gain more Twitter followers! Janet
because the text-box is loading through an iframe. Can you style the text area with css? how would you go about stylizing the elements that are generated?
Thank you.
Hi – You should be able to style pretty much any elements of this widget. What is it that you want to apply CSS formatting to? Thanks Janet
Hi – you should be able to style pretty much any elements of the widget using CSS. What part of the content did you want to apply CSS to?
Hello,
Thanks for this tutorial. I would like to add that, following this brilliant tutorial I was able to develop a Joomla Module and I am giving it free to all, which can be downloaded following this link http://www.joomlaseo.org/download/cat_view/14-joomla-modules.html.
Thanks
Sweta
Mantapss….
Nice inpo