del.icio.us .:. tweet

Blog Juice .:. kentbrewster.com

Here's a toolbar bookmarklet that looks for a MyBlogLog identifier on the page you're on, and uses the MyBlogLog API to dig out information about its reader roll:

Blog Juice

You can try it here, or drag it to your bookmarks toolbar and run it anywhere else on the Web. (On IE, right-click, add to favorites, say Yes to continue past scary warning, and choose Links. You may then need to fiddle around with your Tools drop-down in order to get Links to show in your chrome.)

Things to Do and Notice

  • Each reader comes up in a toggle-able list item. You'll see a MyBlogLog avatar, a name, and possibly some tags. Click the name to visit the MyBlogLog profile; click the tag to see a list of other users with that tag.
  • Click anywhere else in the reader record to open it up and see details from ten different social networks. At the moment, they are: MyBlogLog, Twitter, Upcoming, Digg, LinkedIn, Delicious, Flickr, Last.fm, StumbleUpon, and YouTube.
  • Inside the detail you'll be able to click the item to go over to the other site and view it.
  • Up top are a series of icons that match the detail icons for each service. Mouse over them to only show reader roll items.
  • The MyBlogLog icon (first on the left at the top) will show the user's authored blogs. Click the image to open its reader roll up, right there in the badge without leaving the page you're on. Click the text link to visit the blog.
  • Each user has a checkbox. If you check it, the user will be added to your Stalk List, and a small icon resembling a guy cradling a loaf of French bread will show up at the bottom of the badge. Click the French Bread Guy to see all your buddies.
  • As of the latest version, the widget comes up in an iframe. This works seamlessly in all browsers except IE. We're using an iframe because the CSS is much easier to construct, and when you bookmark a user for your Stalk List, the cookie will be set to my domain, not the domain you're on, so it will be available no matter where you go on the Web.

Rolling Our Own API with Pipes

Astute readers will immediately recognize that some of the services we're querying don't actually have APIs, and those that do have vastly differing endpoints. To cut down on the amount of scripting required to send and receive data, I've rolled my own APIs for each of them, using Pipes.

Each takes an S parameter, the user id, and an optional N parameter, the number of items you want back from each endpoint, which defaults to 3. Output from all of these pipes looks substantially like this:

"items":[
   {
      "u":"http:\/\/twitter.com\/jlam\/statuses\/717107112",
      "t":"jlam: Would anyone like to catch http:\/\/tinyurl.com\/3xz6kc tonite?"
   },
   {
      "u":"http:\/\/twitter.com\/jlam\/statuses\/717097392",
      "t":"jlam: @dearlazyweb a 713733562 Ben, John http:\/\/ejohn.org is writing one now. Meanwhile, see http:\/\/jQuery.com and http:\/\/learningJQuery.com"
   },
   {
      "u":"http:\/\/twitter.com\/jlam\/statuses\/705479382",
      "t":"jlam: Indeed @Coley Hong Kong has unbelievably awesome public transportation! The subway costs $0.10\/mile but profitable, and did an IPO in 2000."
   }
]

If there's a thumbnail in the API, it shows up in the n object. Using Pipes eases the strain on these outside sites and provides a consistent output stream from many different sources, so a single subroutine can render all the many different results.

getActivity : function(mbl, api, nick, id) {
   var callback = trueName + '_' + mbl + '_' + api + '_' + nick + '_' + id.replace(/@/, '');
   window[callback] = function(z) {
      var t = callback.split('_');
      var mbl = t[1];
      var api = t[2];
      var nick = t[3];
      var id = t[4];
      if (t.length > 4) {
         var n = t.length - 1;
         for (var i = 5; i < n; i++) {
            nick += '_' + t[i];
         }
         id = t[n];
      }
      if (z && z.value && z.value.items) {
         var r = z.value.items;
         for (var i = 0; i < r.length; i++) {
            var li = document.createElement('LI');
            li.className = api;
            var img = document.createElement('IMG');
            img.src = 'http://l.yimg.com/us.yimg.com/i/us/mbl/services/i' + api + '.png';
            img.align = 'absmiddle';
            li.appendChild(img);
            var tx = r[i].t;
            if (api == 'twitter') {
               var tx = tx.replace(/http:\/\/([^\s,-]*)/gi, '<a href="http://$1" target="_blank">http://$1</a>').replace(/@([^\s,.!-]*)/gi, '@<a href="http://twitter.com/$1" target="_blank">$1</a>');
               r[i].u = '';
            }
            if (r[i].u) {
               var a = document.createElement('A');
               a.href = r[i].u;
               a.target = '_blank';
               if (r[i].n) {
                  var img = document.createElement('IMG');
                  img.className = 'v';
                  if (api == 'flickr') {
                     img.className = 'q';
                  }
                  img.align = 'absmiddle';
                  img.src = r[i].n;
                  a.appendChild(img);
                  li.appendChild(a);
                  var a = document.createElement('A');
                  a.target = '_blank';
                  a.href = r[i].u;
               }
            } else {
               var a = document.createElement('SPAN');
            }
            a.innerHTML = tx;
            li.appendChild(a);
            $.s.c.bd[mbl].appendChild(li);
         }
      }
      $.f.addServiceIcon(mbl, api);
      $.f.removeScript(callback);
   };
   if (id) {
      nick = id;
   }
   var url = 'http://pipes.yahoo.com/kentbrew/blogjuice_' + api + '?_render=json&_callback=' + callback + '&s=' + nick;
   $.f.runScript(url, callback);
}

This function is almost entirely generic; only a couple of exceptions (to remove the @ from Flickr ids, apply a special class name to Flickr thumbnails, and hotlink URLs in Twitter tweets) come into play. Feel free to clone or use my Pipes for your projects; they're all published and available.

We're using some techniques from Case-Hardened JavaScript here, most notably the practice of creating a single anonymous variable and a private global to hang all the code from; references to $.f and $.s refer to functions and structure.

When we create our dynamic script tags, we're naming them with window[callback] and passing information about what their user IDs, service nicknames, and API endpoints are inside the callback name. This allows us to remove each dynamically-generated script tag from the inside, once it's run.

Filtering URLs in Tweets

To filter API output tx, we double down on our regular expressions. The first looks for http://; the second looks for an @:

var tweet = tx.replace(/http:\/\/([^\s,-]*)/gi, '<a href="http://$1" target="_blank">http://$1</a>').replace(/@([^\s,.!-]*)/gi, '@<a href="http://twitter.com/$1" target="_blank">$1</a>');

Caveats and Gotchas

  • Firefox, IE7, Opera, and Safari all work ... but the iframe is giving me trouble on IE. It's ugly.
  • If it hangs forever, something's busted in one of ten or eleven API endpoints we're banging on. Suggestions? Clear your cache; I might be monkeying with the script. If all else fails, bring up Firebug to track this down.
  • We're leaning heavily on several different APIs here, so this thing is almost guaranteed to be flaky. Sorry about that; for best results, please be patient, wait for the page to load before trying to juice it, and keep an eye on your status bar.

Directions for Future Development

  • Right, it would be great to have some indication of when it was done, and when it was stuck on something. Working on it!

Thank You:

Adam Platti, Andrew Wooldrige, Aramys Miranda, Ash Patel, Ava Hristova, Bill Scott, Bob Zoller, Bradley Horowitz, Cameron Marlowe, Chad Dickerson, Chanel Wheeler, Chip Morningstar, Chris Goffinet, Christian Heileman, Dan Theurer, Dav Glass, Dave Balmer, David Filo, David Flanagan, Doug Crockford, Dustin Diaz, Ed Ho, Eric Marcoullier, Eric Wu, Ernie Hsiung, Gina Groom, Havi Hoffman, Hedger Wang, Ian Kennedy, Ian Lamb, Isaac Schleuter, JR Conlin, Jason Schupp, Jean-Paul Cozzatti, Jenny Han, Jeremy Gillick, Jeremy Zawodny, Jimmy Byrum, John Greene, Jonathan Trevor, Julian Lecomte, Kevin Brown, Lauri Voss, Leslie Sommer, Luke Wroblewski, Matt McAlister, Matt Sweeney, Micah Laaker, Mike Lee, Nate Koechley, Nathan Arnold, Nicholas Zakas, Norm Francis, PPK, Paul Hammond, Randy Farmer, Scott Schiller, Sean Michael Imler, Steve Souders, Steven Wheeler, Tenni Theurer, Thomas Sha, Tim O'Reilly, Todd Klootz, Todd Sampson, Tom Coates, and (most of all!) Vickie Brewster.

Comments from before Disqus:

Kent Brewster .:. 2009-12-23 08:51:55
ReadWriteWeb says that MyBlogLog will be shut down shortly. Blog Juice and FOAFster will stay up until they don't work any more, and then we'll all go pour out a beer for MyBlogLog.

Very sorry to hear this, if it's true.
Kent Brewster .:. 2008-06-14 08:36:47
We're back. While we're waiting for JSON (and serialized PHP) output to be fixed, I've created a couple of Pipes that return the XML from the two MyBlogLog API calls I was making as JSON. This will have a benefit to MyBlogLog and a drawback for everybody else: since Pipes runs are cached for a short while, there may be a minor delay between when a fresh user hits a page and when he or she shows up on Blog Juice.

I've tested it on a variety of pages and performance seems acceptable ... I don't think I'd use either of these pipes in a badge that loaded every time a page came up, but in a situation where the user has to click to see the badge, they seem fine.
Kent Brewster .:. 2008-06-13 11:31:50
We're a tiny bit broken right now; the MyBlogLog API isn't giving back properly formatted JSON and serialized PHP. Will update later after it's fixed; sorry for the trouble.
Brian Cantoni .:. 2008-04-30 17:00:02
Kent, I thought of a possible improvement to the Blog Juice script: include the blog author(s) as well, maybe indicated separately at the list top. It would kind of break down for multiple-author sites (like YDN), but could limit it to the first few in that case.
Olivier D. alias ze kat .:. 2008-03-12 17:27:15
Kent & Brian : Yeaah :o)

But try Operator. Contextual menu with dedicated sub-menu (for LinkedIn, Flick, Delicious) could be more usefull. And Firefox extension is most easily to install or manage (while updated) than GM script ;o)
Kent Brewster .:. 2008-03-12 10:01:54
Brian: neat!

Olivier: seems like the answer is Yes; check out Brian's GM script.
Brian Cantoni .:. 2008-03-11 13:43:36
I wrote a quick GreaseMonkey script to automatically add a 'MyBlogLog' logo image in the upper left corner of any MBL-enabled page. Clicking on the logo brings up the Blog Juice explorer. The UI leaves a lot to be desired, but it's a handy way to notice and explore pages with MyBlogLog tracking.

Requires Firefox & Greasemonkey. Install from here: http://www.cantoni.org/files/blogjuice.user.js
Olivier D. alias ze kat .:. 2008-03-10 18:10:23
I just imagine nice Firefox extension with BlogJuice feature...

Do you known Operator Firefox extension which could detect MicroFormats ?

I submit same extension as MyBlogLog icon which appear in address bar (while detect MBL widget) with contextual menu to MBL, LinkedIn, Flickr profiles, etc :o) .oO(Ian may read this)
Dan N. Moldovan .:. 2008-03-08 08:13:36
Nice Yahoo Pipes. Please take a look of my MacrosReader and run more than 25 Yahoo Pipes.
http://reader.macrostandard.com/
Thank you!
Henk-Jan van der Klis .:. 2008-02-22 13:04:03
Kent,

Thanks for delivering this bookmarklet. It works fine. I'll feature this blog and Blog Juice on my weblog soon, some of the upcoming days. Regards from the Netherlands.

Henk-Jan.
Dan .:. 2008-02-22 13:04:03
Kent that is a really interesting solution. it seems that you going to produce a little "milestone" in the webhistory. is it tweaked in combination with Googles Social Graph Api?
Wulffy .:. 2008-02-21 04:43:00
This is a absolutely great work you did, Kent. If I think of Google Social Graph API and the things that will be possible in future, I am crazy about it. In 7 hours or so I will write about you and this script in my German blog to let the Germans know about it. Take care!
Kent Brewster .:. 2008-02-19 19:18:07
Added the new services--ActiveRain, FriendFeed, Multiply, Trulia, Tumblr and Zillow--and created a pipe at http://pipes.yahoo.com/kentbrew/blogjuice_tumblr for Tumblr, which I strongly recommend. All this was done in a matter of minutes; I cloned the Twitter pipe, rejiggered the profile URL, and it worked the first time I tried it. Boy, do I love Pipes. :)
Kent Brewster .:. 2008-02-19 15:57:05
Getting closer ... IE looks much better, but the Stalk List is busted. Everbody else's Stalk List icon (guy with French bread, remember) will now show up at the top, in amongst the rest of the service icons. This is unsatisfactory and will change.
Kent Brewster .:. 2008-02-19 11:38:40
Of course, study away! I was just warning you it wasn't really ready to look at yet.
Olivier D. alias ze kat .:. 2008-02-19 10:44:26
@Kent: be quiet. I just requested to study your method. Sure, I will coding all myself. And I like introduce new user-experience me too. Not make simple copy ;o)
Kent Brewster .:. 2008-02-18 21:01:49
Oliver: you should probably hold off a few more days until I button things up a bit tighter, especially if you're an IE user. Made a few improvements this weekend; still working....
Olivier D. alias ze kat .:. 2008-02-18 03:15:54
So usefull !

Do you allow me to study your source-code ? It could be nice as mouse-over popup on LiFE2Front profiles (which support MBL) ;o)
sumit gupta .:. 2008-02-15 20:21:38
Kent, it seems you are the inspiration behind http://www.mybloglog.com/buzz/help#a2008021323451521

are you involved or did they just stole your idea?
Joe Lazarus .:. 2008-02-15 08:10:21
Wow. Awesome hack. This really helps to communicate the power of the MBL API as a way to connect all these services.
Kent Brewster .:. 2008-02-14 10:07:57
Marshall, Jesse, Daniel, Brian, Daniela, Ian: thanks for the love! Please look for me and Blog Juice at Graphing Social Patterns, Etech, and SxSW.

Justin: you know ... that sounds really good ... but it should run because of a conscious decision made by the user, not automatically for every page you visit. The extra traffic on all those APIs seems really wasteful unless there's an actual live human being watching.

Next up I'm going to investigate putting the whole thing into an iframe, so cookies will be set on my domain and not the page you're looking at. This will fix the bug where the list of folks you're stalking only shows up on the page you were looking at when you clicked them. There's also an update I'm waiting for; at the moment I can't get a response for (say) the 10th through 20th records for any particular MyBlogLog API call.
Brian Oberkirch .:. 2008-02-14 09:41:59
Kent: this is great. Thanks for sharing this. I really want to dig down into some ways to use Pipes more, and this is inspiring.
Daniel Raffel .:. 2008-02-13 23:48:17
nice work, kent - very cool.
Jesse .:. 2008-02-13 12:31:18
Very very cool. Great work!
Justin Kistner .:. 2008-02-13 11:35:25
Wow, I would love to have this in the sidebar of my browser. Lovin' the pipes too (already thinking of sweet applications for them). Thank you for sharing this great idea!
Marshall Kirkpatrick .:. 2008-02-13 09:47:15
Hot, blogging it now. Thanks
daniela barbosa .:. 2008-02-12 22:43:21
Ran home from the SDforum Search SIG Meeting in Sunnyvale to give this bugger a try. Awesome and very useful- well done!
Ian Kennedy .:. 2008-02-12 19:23:51
Kent the foo master strikes again!

Copyright Kent Brewster 1987-2014 .:. FAQ .:. RSS .:. Contact