<?xml version="1.0" encoding="utf-8"?>

























	
	



	
	
	

	
		
		
		

		
		
			
			
			
			
		
	
	
	
	
	
	


<rss version="2.0">	
	<channel>
		<title>Radiant Core: platform tag</title>
		<link>http://www.radiantcore.com/</link>
		<description>All of the Radiant Core posts tagged with platform.</description>
		<language>en-ca</language>
		<copyright>Copyright 2006, Radiant Core Inc. All rights reserved.</copyright>
		<managingEditor>webmaster@radiantcore.com</managingEditor>
		<webMaster>webmaster@radiantcore.com</webMaster>
		
			
			
			
			
			
			
			
			

			
				
			
			<item>
				<title><![CDATA[Deconstructing Facebook Beacon JavaScript]]></title>
				<author>Jay Goldman &lt;info@radiantcore.com&gt;</author>
				<link>http://www.radiantcore.com/blog/archives/23/11/2007/deconstructingfacebookbeaconjavascript</link>
				<guid isPermaLink="true">http://www.radiantcore.com/blog/archives/23/11/2007/deconstructingfacebookbeaconjavascript</guid>
				<comments>http://www.radiantcore.com/blog/archives/23/11/2007/deconstructingfacebookbeaconjavascript#comments</comments>
				<description><![CDATA[<div id="syndicatePage">Hello! If you enjoy this post, could you take a moment to stop by <a href="http://digg.com/programming/Deconstructing_Facebook_Beacon_JavaScript" title="Digg: Deconstructing Facebook Beacon JavaScript">Digg</a> and help promoted it? Thanks!</div><br /><br /> <p>On November 6th, 2007, Facebook launched a series of new tools to help advertisers target the 54 million people now regularly using their site. They're still throwing around a 3% weekly growth rate and have a target of 60 million active users by the end of the year, so it's not hard to picture the day in the not-so-distant future when hospitals Facebook babies before handing them over and the little bundle of joy comes with a neural implant that pokes their parental units when the diaper is full.</p><br /><br /><p>The new tools round out the <a href="http://www.facebook.com/business" title="Facebook Business">Facebook Business</a> offerings to an even six:</p><ul>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<li><a href="http://www.facebook.com/business/?socialads" title="Facebook: Social Ads"><img src="http://static.ak.facebook.com/images/business_portal/socialads_48.png?12:67999" style="vertical-align: middle;" height="42" width="48"> Social Ads</a></li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<li><a href="http://www.facebook.com/business/?pages" title="Facebook: Pages"><img src="http://static.ak.facebook.com/images/business_portal/pages_48.png?12:67999" style="vertical-align: middle;" height="42" width="48"> Pages</a></li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<li><a href="http://www.facebook.com/business/?beacon" title="Facebook: Beacon"><img src="http://static.ak.facebook.com/images/business_portal/beacon_48.png?12:67999" style="vertical-align: middle;" height="42" width="48"> Beacon</a></li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<li><a href="http://www.facebook.com/business/?insights" title="Facebook: Insights"><img src="http://static.ak.facebook.com/images/business_portal/insights_48.png?12:67999" style="vertical-align: middle;" height="42" width="48"> Insights</a></li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<li><a href="http://www.facebook.com/business/?platform" title="Facebook: Platform"><img src="http://static.ak.facebook.com/images/business_portal/applications_48.png?12:68202" style="vertical-align: middle;" height="42" width="48"> Platform</a></li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<li><a href="http://www.facebook.com/business/?polls" title="Facebook: Polls"><img src="http://static.ak.facebook.com/images/business_portal/polls_48.png?12:67999" style="vertical-align: middle;" height="42" width="48"> Polls</a></li></ul><p>Platform and Polls are old news to anyone following the company, so the really interesting news is in the other four. All of them are very much interlinked, so that you create a Page for your brand or product, advertise it through Social Ads to a very targeted market, learn about your success through Insights, and connect to your off-Facebook (off-Book?) service via Beacon, build custom apps for your Page on Platform, and learn about your users through Polls. It's a marketer's dream, but what does it mean for you as a user? The web is somewhat up in arms about Beacon particularly because it just stinks of privacy violations, at least if you care about things like companies tracking your every move online. This post is going to dig deep in Beacon and see what makes it tick from a purely technical perspective, but we'd be happy to do a follow-up post about the ethical question if there's enough interest. Leave a comment and let us know!</p><br /><br /><h2>Pinging Beacon</h2><p>This post is an in-depth look at Beacon, and is broken down into a few sections to make it easier for you to navigate:</p><br /><ul><li><a href="http://www.radiantcore.com/blog/archives/23/11/2007/deconstructingfacebookbeaconjavascript#nutshell" title="Beacon in a Nutshell">Beacon in a Nutshell:</a> an overview of Beacon and a visual tour of the user interface elements</li><li><a href="http://www.radiantcore.com/blog/archives/23/11/2007/deconstructingfacebookbeaconjavascript#10000" title="Beacon from 10,000 Feet">Beacon from 10,000 Feet:</a> a look at the technology behind Beacon from way up high. Read this if you don't want the finer details but do want an idea of how it works.</li><li><a href="http://www.radiantcore.com/blog/archives/23/11/2007/deconstructingfacebookbeaconjavascript#blocking" title="Blocking Beacon">Blocking Beacon:</a> if you're concerned about privacy and want to stop Beacon, check this part out.</li><li><a href="http://www.radiantcore.com/blog/archives/23/11/2007/deconstructingfacebookbeaconjavascript#code" title="Walking through the Code">Walking through the Code:</a> this is the section for you if you're the type of person who loves reading code listings and wants to know exactly what makes it tick.</li></ul><br /><br /><h2><a name="nutshell"></a>Beacon in a Nutshell</h2><p>Here's what Facebook has to say:</p><blockquote>Allow your customers to share with their friends the actions they take on your website. For user actions you define, Facebook Beacon will publish a story in the user's profile and to friends' News Feeds with a link back to your site.</blockquote><p>What that means in real terms, is that you can add a recipe to your recipe box on <a href="http://www.epicurious.com" title="Epicurious">Epicurious</a>, and you'll get a very familiar looking Facebook pop-up in the bottom right corner of your window letting you know that your new recipe is being sent to your news feed:</p><br /><br /><p style="text-align: center;"><img src="http://www.radiantcore.com/images/blogposts/facebookBeacon/facebook-toast.png" alt="Facebook Beacon Pop-up Window (a.k.a. Toast)" height="134" width="366"></p><br /><br /><p>If you do nothing, you have effectively opted-in and you have consented for the item to be published (i.e.: Facebook will assume your consent to publish the content). The window will disappear eventually, and the next time you log into Facebook, you'll see a notice like this one at the top of your homepage:</p><br /><br /><p style="text-align: center;"><img src="http://www.radiantcore.com/images/blogposts/facebookBeacon/facebook-notification.png" alt="Facebook Epicurious Notification" height="70" width="441"></p><br /><br /><p>If you go to your Profile page, the items will appear mixed in with everything else in you mini-feed:</p><br /><br /><p style="text-align: center;"><img src="http://www.radiantcore.com/images/blogposts/facebookBeacon/facebook-mini-feed.png" alt="Facebook Mini-Feed" height="36" width="381"></p><br /><br /><p>You'll notice that those two screen captures show different recipes being added, which is because Beacon isn't entirely without issues. Although I've been playing with it for a few hours now, items about Epicurious recipes stopped being added to my feed just after 7:30pm. There may be some internal limitations applied by the algorithm to stop feeds from being overloaded with actions from any one site, or it might just be broken :). The <a href="http://www.epicurious.com/services/help/facebook" title="Epicurious: Facebook Action Sharing and Story Publishing">help page</a> on Epicurious explains that they are sending four types of actions to Facebook:</p><br /><ol>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<li>Rate a recipe</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li>Review a recipe</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li>Add a recipe to your Recipe Box</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li>Register on Epicurious</li></ol><br /><br /><p>Encounters with Beacon are slowly starting to be reported on other sites as well. A post from yesterday on Groundswell documents a <a href="http://blogs.forrester.com/charleneli/2007/11/close-encounter.html" title="Groundswell: Close encounter with Facebook Beacon">Close encounter with Facebook Beacon</a> in which <a href="http://www.forrester.com/rb/analyst/charlene_li" title="Charlene Li">Charlene Li</a> (Vice President, Principal Analyst for Forrester Research) had her first run-in on <a href="http://www.overstock.com" title="Overstock.com">Overstock.com</a>. In her post, she explains how she bought a coffee table from that site and was surprised to discover, when she logged into Facebook later that week, that there was a notice at the top of her page about the purchase:</p><br /><br /><p style="text-align: center;"><img src="http://www.radiantcore.com/images/blogposts/facebookBeacon/facebook-overstock.jpg" alt="Charlene's Facebook Mini-Feed" height="118" width="440"></p><br /><br /><p>Charlene should have been shown the pop-up window as well but she might have missed it or something might have failed to show it while she was on Overstock (there's a slight delay before it pops up, so it's possible that she navigated away from the page or closed the window before she saw it). It's unfortunate that it didn't work as advertised because, as she says:</p><blockquote>The biggest problem is the lack of transparency. Facebook is right in that I would really like to have some things that I do on third party sites to conveniently appear in newsfeed, e.g. events I'm attending from Evite or eBay/craigslist listings so that my friends know about them. That's the promise of Beacon. But I need to be in control and not get blindsided as I did in the example above. I was seriously wigged out, but wouldn't have been if Overstock had simply told me that they were inserting a Facebook Beacon and given me the opportunity at that time to opt-in to Beacon.</blockquote><p>As I mentioned above, this isn't a post about the privacy or security concerns of Beacon (though it will address some of them below). There's some pretty neat web technology at play which we thought would interest our more technical readers, and so, just like we used to do with Dad's calculator we're going to take Beacon apart and put it back together again (hopefully in one piece – sorry Dad!).</p><br /><br /><h2><a name="10000"></a>Beacon from 10,000 Feet</h2><p>That basically wraps up our tour of how Beacon does what it does. It's a fairly long explanation, so here's a quick summary:</p><br /><ol>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li>The partner site page includes the beacon.js file, sets a <pre style="margin: 0px; display: inline;">&lt;meta&gt;</pre> tag with a name, and then calls <em>Facebook.publish_action</em>.</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li><em>Facebook.publish_action</em> builds a query_params object and then passes it to <em>Facebook._send_request</em>.</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li><em>Facebook._send_request</em> dynamically generates an <pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> which loads the URL http://www.facebook.com/beacon/auth_iframe.php and passes the query_params. At this point, Facebook now knows about the news feed item whether you choose to publish it or not.</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li>The <pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> loads a <em>facebook_helper.html</em> file, which lives on the partner site, and which contains a call to <em>Facebook.process_message_from_helper</em>.</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li><em>Facebook.process_message_from_helper</em> parses a call to <em>Facebook._perform_action</em> from its own query_string and calls it.</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li><em>Facebook._perform_action</em> dynamically creates the toast pop-up and displays it in the bottom right corner of the window.</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li>The user is given the choice of cancelling the publication (i.e.: opting-out), which will cause the item not to appear in their news feed.</li></ol><br /><br /><p>And there you go! A very clever series of steps to allow for a very simple integration by partners and a neat side-step of the Cross-site Scripting security features in modern browsers.</p><br /><br /><h2><a name="blocking">Blocking Beacon</a></h2><p>Those of you wearing tin foil hats (or hats at all, really), are probably wondering how you can block this nefarious beast from spreading all of your secrets. You've got a few options:</p><br /><ul><li><strong>If you're not worried about Facebook knowing what you do but are worried about your friends finding out</strong>, you can go into the <a href="http://www.facebook.com/privacy.php?view=unconfirmed_actions" title="Facebook: Privacy Settings for External Websites">External Websites</a> area of your <a href="http://www.facebook.com/privacy.php" title="Facebook: Privacy">Privacy</a> settings and set specific sites to never publish. They'll only show up after you've triggered them the first time, so the list will only contain sites you've already visited which are Beacon-enabled.</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li><strong>If you're worried about Facebook and you're friends knowing what you do on other sites</strong>, make sure you don't browse other sites while you're logged into Facebook. When you add a recipe to your recipe box and aren't logged in, a request is still made for the beacon.js file and gets as far as creating the <pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> and loading auth_iframe in it, but that page now returns "no user" and the process stops.</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li><strong>If you're paranoid about the entire process (or don't trust yourself to always log out of Facebook before browsing other sites)</strong>, and you just want to make sure that nothing gets through, and you're using Firefox, follow Nate Weiner's excellent instructions in his <a href="http://www.ideashower.com/blog/block-facebook-beacon/" title="the IDEA SHOWER: Block Facebook Beacon">Block Facebook Beacon</a> post (basically, install the <a href="https://addons.mozilla.org/en-US/firefox/addon/3145" title="Add-ons: BlockSite">BlockSite</a> add-on and add www.facebook.com/beacon/* and facebook.com/beacon/* to the list). If you're running InternetExplorer, you can try following <a href="http://www.mvps.org/winhelp2002/restricted.htm" title="Adding sites to the restricted zone">these instructions</a> to add the same two URLs to your restricted zone, but your life would really be much improved by <a href="http://www.getfirefox.com" title="Get Firefox!">downloading Firefox</a> so I'd recommend you do that instead. <strong>UPDATE: </strong> we've confirmed that the exceptionally useful <a href="https://addons.mozilla.org/en-US/firefox/addon/1865" title="Mozilla Add-ons: AdBlockPlus">AdBlockPlus</a> for Firefox will also block Beacon if you add a pattern for http://*facebook.com/beacon* to the list of filters. The script tag embed for the beacon.js file gets blocked which prevents the rest of the app from working. Note that you can set ABP to be disabled for certain sites (a virtual necessity if you use them often and they have heavy Flash requirements), which will in turn allow Beacon to work.<br /></li></ul><br /><br /><h2><a name="code"></a>Walking Through the Code</h2><p><strong>IMPORTANT NOTE: All of the code shown here is copyright and all rights reserved and please-don't-sue-us owned by the respective parties who wrote and publish it. It was not disassembled for profit and we used only publicly available free tools (<a href="http://www.mozilla.com/firefox/" title="Mozilla Firefox">Firefox</a> with the <a href="http://addons.mozilla.org/firefox/addon/1843" title="Mozilla Add-ons: FireBug">FireBug</a> and <a href="http://addons.mozilla.org/firefox/addon/966" title="TamperData">TamperData</a> Add-Ons installed) and source which was available through standard web protocols.</strong></p><br /><br /><p>It has traditionally been very difficult to connect two websites together and exchange information between them without building complex backend integrations. Sure, they could have built Beacon by implementing a <a href="http://en.wikipedia.org/wiki/Web_service" title="Wikipedia: web service">web service</a> in which the third party servers (like Epicurious) would contact the Facebook services through an entirely backend channel whenever I did a certain something (like add a recipe to my recipe box), but that would have meant asking partners to invest some fairly serious engineering effort in order to support it, and the opportunity to display a fun pop-up window to allow me to opt-out would have been gone. Instead, Facebook followed the route of having partners embed a JavaScript file on their site, and make a simple JavaScript call to populate the item. Let's take a look at an example:</p><br /><br /><p>I'm a big fan of risotto – so big, in fact, that one of the reasons I married my wife was to get better access to her Risotto Milanese. I can't think of anything I'd really rather have for breakfast, so we're going to use a recipe for <a href="http://www.epicurious.com/recipes/food/views/240748" title="Epicurious: Breakfast Risotto">Breakfast Risotto</a> as our example (you should load that page in another tab so that you can flip back and forth).</p><br /><br /><p>If you take a look at the source and search for Facebook, you'll find two entries. The first is on line 133 and sets up the name of this item for the news feed entry:</p><br /><br /><pre>&lt;meta name="facebook_label" content="Breakfast Risotto Recipe"&gt;</pre><br /><p>The second is on line 167 and actually pulls in the Facebook JavaScript file:</p><br /><br /><pre>&lt;script type="text/javascript" src="http://facebook.com/beacon/beacon.js.php?source=5194643289"&gt;&lt;/script&gt;</pre><br /><p>The source ID (5194643289) identifies Epicurious and corresponds to a list maintained internally by Facebook, which allows them to validate sources. You can actually load that file <a href="http://facebook.com/beacon/beacon.js.php?source=5194643289" title="Facebook: beacon.js">directly</a> and you'll find a suprisingly well formatted JavaScript class called window.Facebook. We'll dig into it a little bit later on, but the first method deserves mention all by itself, entirely based on its name:</p><br /><br /><pre>write_awesome : function(url) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;return '';<br />},<br /></pre><br /><p>The two lines we're particularly interested in on the Epicurious page have to do with adding this recipe to our recipe box, and you'll find them on lines 1195 and 1197:</p><br /><br /><pre>&lt;a href="javascript:void(0);" id="addRecipeButton"&gt;Save To Recipe Box&lt;/a&gt;<br />&lt;script type="text/javascript"&gt;new LoginRequiredLink('240748',<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;'addRecipeButton',<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;'/user/recipebox/save?id=240748&amp;returnto=/recipes/food/views/240748',<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;'recipeBox',<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;'recipeBox');&lt;/script&gt;</pre><br /><p>For all intents and purposes, this has nothing to do with Beacon and basically just rewrites the addRecipeButton link to point to the right URL for saving it if you're logged in (note: a more modern approach would be to use Ajax to send a message to the server to save this recipe and prevent having to actually go to a different page, which would improve the experience here since the back button from the save page takes you back to effectively the same page in the pre-saved state). If you want to follow the rest of the way through this you're going to need to register an account on Epicurious, so go ahead and do that and I'll wait right here. Done? Great. Reload that page and you should now have an enabled Save to Recipe Box" button. Now, before you go and click on it to watch Beacon in action, you'll need to make sure that you've logged into Facebook in another tab or window. <strong>This is critical and is in fact overlooked by a lot of the people who are upset about the potential privacy violations: don't leave yourself logged into Facebook and you won't have a problem with other people using your machine and logging Beacon events.</strong> Go ahead and login and then hit that button.</p><br /><br /><p>You should now be on a page which shows the recipe as added. There's a lot of Epicurious-centered JavaScript at play on this page which we're not overly concerned about, so I'm not going to mention it except where it affects the Beacon integration. As on the previous page, we have a </p><pre style="margin: 0px; display: inline;">&lt;meta&gt;</pre> tag with the recipe name in it, and the inclusion of the JavaScript file (line 133 and 167 again), but now we have some more code which actually makes the magic happen. The next mention of Facebook is way down on line 1184, in a function called runOnLoad:<p></p><br /><br /><pre>&lt;script language="javascript"&gt;<br />&nbsp;&nbsp;&nbsp; runOnLoad(function() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (Facebook) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Facebook.publish_action('queue',<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;'http://www.epicurious.com/recipes/food/views/240748?mbid=fbfeed');<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; });&lt;/script&gt;</pre><br /><p>Basically, if the Facebook object was instantiated when the beacon.js file was included, go ahead and publish an action of type 'queue' with the URL of this page as the link (with a tracker on the end so Epicurious knows you came to the recipe from a Facebook feed). The runOnLoad function gets called down on line 1330 from inside a </p><pre style="margin: 0px; display: inline;">&lt;script&gt;</pre> tag. Now we're making progress! Let's take a look at what the publish_action function does – you'll find it on line 20 of beacon.js in unadulterated form, or right here all marked up:<p></p><br /><br /><pre>publish_action : function(action, urls) {<br />&nbsp;&nbsp;&nbsp; urls = urls || window.location.href;<br /></pre><br /><p>Set the urls variable to the value passed in or the location of the current page.</p><br /><br /><pre>&nbsp;&nbsp;&nbsp; setTimeout(function() {</pre><br /><p>Set a timeout of 50 milleseconds and then call the following function.</p><br /><br /><pre>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (Facebook._BROADCAST_ACTIONS[action]) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var query_params = [['action_name', action]];</pre><br /><p>Check to see if we were passed a valid type of action and set the action_name to the value passed in. The list of available actions is quite extensive: buy, wish_list, queue, sign_up, bid, review, add, book, comment, create, design, download, find, fly, get, join, play, post, rate, rent, shop, stay, subscribe, support, update, view, vote, watch, enjoy, order.</p><br /><br /><pre>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (typeof urls == 'object') {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; urls.length; ++i) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; query_params = query_params.concat([['urls[' + i + ']', urls[i]]]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; query_params = query_params.concat([['urls[0]', urls]]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Facebook._send_request('http://www.facebook.com/beacon/auth_iframe.php', query_params);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }, 50);},<br /></pre><br /><p>Manipulate the URL if required to build the request and then send it to facebook using the _send_request function.</p><br /><br /><br /><p>The next piece of code is key to how this whole thing works. Those of you familiar with JavaScript will know that browsers spend a lot of effort preventing something called Cross-Site Scripting (often shortened to XSS). We covered this back in July 2006 with a post on <a href="http://www.radiantcore.com/blog/archives/18/07/2006/5xsstips" title="5 Tips for Protecting Your Site Against XSS">5 Tips for Protecting Your Site Against XSS</a>, and Wikipedia has an excellent a very in-depth look at the issue in their <a href="http://en.wikipedia.org/wiki/Cross_site_scripting" title="Wikipedia: Cross-site Scripting">Cross-site Scripting</a> entry. The gist of it is that you can't have a script from one site run on another site and you can't drop a cookie from one site and read it from another, so how does your news event from Epicurious get posted into Facebook without using a backend server connection? All thanks to the humble _send_request function (line 75 in beacon.js):</p><br /><br /><pre>_send_request : function(url, query_params) {<br />&nbsp;&nbsp;&nbsp; query_params = query_params.concat([['source_id', Facebook._source_id],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ['random', Math.random()],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ['ref_url', window.location.href]]);<br />&nbsp;&nbsp;&nbsp; var src = url + '?' + Facebook._form_query_string(query_params);<br /></pre><br /><p>This is pretty simple – parse the info handed to this function and get ready for below.</p><br /><br /><pre>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setTimeout(function() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var ifr = document.createElement('iframe');<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifr.style.display&nbsp;&nbsp;&nbsp;&nbsp; = 'block';<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifr.style.width&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = '0px';<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifr.style.height&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = '0px';<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifr.style.border&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = '0px';<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifr.style.margin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = '0px';<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifr.style.padding&nbsp;&nbsp;&nbsp;&nbsp; = '0px';<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifr.style.overflow&nbsp;&nbsp;&nbsp; = 'hidden';<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifr.style.visibility&nbsp; = 'hidden';<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifr.src = src;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.body.appendChild(ifr);<br />&nbsp;&nbsp;&nbsp; }, 0);<br />},<br /></pre><br /><p>This is where it all goes down. This code creates an </p><pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> on the fly and inserts into the document, using the URL that got passed in from publish_action above.<p></p><br /><br /><p>So, an </p><pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> on the page loads content from the Facebook server, getting passed in the action you performed and the URL to link back to. If you look above, you'll see that the <pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> is loading content from <a href="http://www.facebook.com/beacon/auth_iframe.php" title="Facebook: auth_iframe.php">http://www.facebook.com/beacon/auth_iframe.php</a>, which you can try to load directly but will likely get an "invalid ref url" error. We can fake it out by passing in the same values which would be built into query_params and passed in: <a href="http://www.epicurious.com/facebook_helper.html?function_name=_perform_action&amp;arg1=null&amp;arg2=a%3A2%3A%7Bi%3A0%3Bi%3A1858902535%3Bi%3A1%3Bs%3A64%3A" b7181317b360040b558a92dcbe83c8c71c5302bc81a663a0c3f9d248c7339551="" %3b}&amp;random="1609429394&quot;" title="Facebook: auth_iframe.php full URL">http://www.epicurious.com/facebook_helper.html?function_name=_perform_action&amp;arg1=null&amp;arg2=&lt;auth_token_redacted&gt;&amp;random=1609429394</a>. Two notes: 1) There's a piece in the URL which looks like it's encoded in <a href="http://en.wikipedia.org/wiki/Json" title="Wikipedia: JSON">JavaScript Object Notation (JSON)</a>, which I've removed for publishing this post. It's impossible to tell by looking at it, but it might contain a key which relates back to my Facebook account. It's not needed for the purposes of understanding the functionality, and if you'd really like to see what it looks like, you can recreate the steps up to this point and check it out for yourself. 2) You'll need to use a URL Encoder to pass in the ref_url parameter – I usually use Eric Meyer's <a href="http://meyerweb.com/eric/tools/dencoder/" title="Meyerweb: URL"> Decoder/Encoder</a>. If you follow that URL, you'll get a page with a simple block of HTML on it, which is what loads in the <pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> (it will make a blank page in your browser – view source to see what's in it):<p></p><br /><br /><pre><!--Install this file onto your domain if you want to broadcast your user actions to Facebook.-->&lt;html&gt;&lt;body&gt;&lt;script type="text/javascript"&gt;window.onload = function() {<br />&nbsp;&nbsp;&nbsp; window.top.Facebook.process_message_from_helper(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window.location.search.substring(1),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window.location.hash.substring(1));}&lt;/script&gt;<br />&lt;/body&gt;&lt;/html&gt;</pre><br /><p>Nice and short: when the page loads into the </p><pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre>, call the process_message_from_helper function in the Facebook object at the top level of this window (being the page on Epicurious which instantiated the <pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre>). You may not have known that window.location had a bunch of really useful properties within it, including search (everything in the query string of a URL, or after the ?), and hash (the anchor tag on a page, or everything after the #). Back to the beacon.js file, line 290:<p></p><br /><br /><pre>process_message_from_helper : function(query_string, hash_string) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;var params = Facebook._parse_query_string(query_string);<br /></pre><br /><p>Facebook._parse_query_string is to an internal function (beacon.js, line 276) which pulls about the key/value pairs from the query string (e.g."action_name=queue") and returns an array containing the key and value (e.g.: ["action_name", "queue"]).</p><br /><br /><pre>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;var argument_list = [];<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;var function_name = '';<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;for (var i = 0; i &lt; params.length; ++i) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;var key = params[i][0];<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;var val = params[i][1];<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (key.substring(0, 3) == 'arg') {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;argument_list[parseInt(key.substring(3))] = val;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}</pre><br /><p>Some of the keys stored in the query_string start with 'argx' to denote that they arguments (where x is an integer indicating which argument this is – arg0, arg1, arg2, etc.). If that's the case, store the value in the argument_list array at that location (e.g.: arg0 goes into the argument_list[0]).</p><br /><br /><pre>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;if (key == 'function_name') {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;function_name = val;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;Facebook[function_name].apply(null, argument_list);<br />}</pre><br /><p>If the key is 'function_name', then we want to call that function in the Facebook object. That </p><pre style="margin: 0px; display: inline;">if</pre> really could have been an <pre style="margin: 0px; display: inline;">else</pre> (extending the previous <pre style="margin: 0px; display: inline;">if</pre>) since it's impossible for the key to start with arg and be equal to 'function_name', but maybe there's more code to come or something has been removed. Either way, the final step is to call any functions that got passed in and pass them the argument_list which we've built up.<p></p><br /><br /><p>It's interesting to note that none of the arguments which got stored when we built the query_string above started with arg or had a key of function_name. Since we had to fake our way into seeing the auth_iframe.php page, we didn't get a look at the full set of arguments passed into it from Epicurious. The trail would have gone cold here, were it not for the wonderful Firefox add-on called <a href="http://addons.mozilla.org/firefox/addon/966" title="Add-ons: TamperData">TamperData</a>. With the add-on installed and the sidebar open, you can watch all of the GET and POST requests that a page makes as it loads. The recipe save page from Epicurious makes 116 requests to build the page, pulling from three servers (www.epicurious.com, www.google-analytics.com, and www.facebook.com). We only really care about the ones made to Facebook, of which there are 6. The GET call to auth_iframe.php is the one we're after, and it looks like this:</p><br /><br /><blockquote>http://www.facebook.com/beacon/auth_iframe.php?action_name=queue<br />&amp;urls[0]=http%3A%2F%2Fwww.epicurious.com%2Frecipes%2Ffood%2Fviews%2F240748%3Fmbid%3Dfbfeed<br />&amp;source_id=5194643289<br />&amp;random=0.2268030104517741<br />&amp;ref_url=http%3A%2F%2Fwww.epicurious.com%2Frecipes%2Ffood%2Fviews%2F240748%3Frecipename%3DBREAKFAST%2520RISOTTO%26saved_to_box%3Dy</blockquote><br /><p>Which is not dissimilar to the version we constructed. Thanks to TamperData, we can get the response to that request, which contains the following location:</p><br /><br /><blockquote>Location=http://www.epicurious.com/facebook_helper.html?function_name=_perform_action<br />&amp;arg0=queue<br />&amp;arg1=%5B%22http%3A%5C%2F%5C%2Fwww.epicurious.com%5C%2Frecipes%5C%2Ffood%5C%2F<br />views%5C%2F240748%3Fmbid%3Dfbfeed%22%5D<br />&amp;arg2=&lt;auth_token_redacted&gt;<br />&amp;random=1305590124</blockquote><br /><p>When the call gets made from Epicurious rather than by us, the response fits right into the pattern that process_message_from_helper is looking for. In fact, if you go to <a href="http://www.epicurious.com/facebook_helper.html?function_name=_perform_action&amp;arg0=queue&amp;arg1=%5B%22http%3A%5C%2F%5C%2Fwww.epicurious.com%5C%2Frecipes%5C%2Ffood%5C%2Fviews%5C%2F240748%3Fmbid%3Dfbfeed%22%5D&amp;arg2=%3Cauth_token_redacted%3E&amp;random=1305590124" title="Facebook_helper on Epicurious">that URL</a> and view the source, you'll seem the same thing we saw when we loaded auth_iframe directly, except now being served from Epicurious instead of Facebook. Applying what we know from process_message_from_helper, we've now essentially called:</p><br /><br /><pre>_perform_action(queue, ["http://www.epicurious.com/recipes/food/views/240748?mbid=fbfeed"], &lt;auth_token_redacted&gt;, 1305590124);</pre><br /><p>Note that we've made a trip through the Facebook server to get here, which means Facebook has already recorded this news feed item whether we choose to publish it or not. This is a much longer function so I've edited out some parts which are not key to the core functionality. If you'd like to see the whole thing, we're now on line 159 of beacon.js. One thing to note before we dive in: the term 'toast' will only make sense if you've actually seen the pop-up appear. Since it rises up from the bottom edge of the window frame, it looks a lot like toast popping up in a toaster :)</p><br /><br /><pre>_perform_action : function(action_name, urls, auth_token) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;Facebook._kill_toast();</pre><br /><p>Although it may sound like it, no one at Facebook has a vendetta against breakfast foods (that we know of). This just kills the window if it's already visible from a previous instantiation.</p><br /><br /><pre>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; var toast = Facebook._toast = document.createElement('div');<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; var query_param = [['action_name', action_name],<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; ['urls', urls],<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; ['source_id', Facebook._source_id],<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; ['ref_url', window.location.href],<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; ['random', Math.random()]];<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; if (auth_token) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; query_param.push(['auth_token', auth_token]);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; }<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; var src = Facebook._action_toast_url + '?' + Facebook._form_query_string(query_param);<br /></pre><br /><p>Create the HTML element that will hold our toast, then setup the query_params. The toast window contains another </p><pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> into which we will once again pass our familiar query_params (see below). The next block is formatting for the <pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> and has been removed.<p></p><br /><br /><pre>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; [...redacted...]<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; var iframe_style = 'width: 345px; height: auto; left: 0px;'<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;+ 'border: 0px; margin: 0px; padding: 0px; display: block; position: absolute; background: transparent;';<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; toast_inner.innerHTML = '&lt;iframe src="%27%20+%20src%20+%20%27" style="" <br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;allowtransparency="true" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;';</pre><br /><p>Format the </p><pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> and then set the innerHTML of the inside of our toast window to contain it, passing in the src variable defined above. _action_toast_url is defined in beacon.js as http://www.facebook.com/beacon/action_toast.php.<p></p><br /><br /><pre>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; var iframe = Facebook._toast_iframe =<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; toast_inner.getElementsByTagName('iframe')[0];<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; iframe.style.bottom = '-150px';<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; toast.appendChild(toast_inner);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; document.body.appendChild(toast);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; [...redacted...]<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; }}<br /></pre><br /><p>Lastly, append the inner_toast div to the toast div which we created at the top. The next block calculates the position of the div and sets some style values.</p><br /><br /><p>We're almost done, honest. Referring back to our TamperData output, the URL for the </p><pre style="margin: 0px; display: inline;">&lt;iframe&gt;</pre> in the toast window that actually gets called by Epicurious is:<p></p><br /><br /><pre>http://www.facebook.com/beacon/action_toast.php?action_name=queue&amp;urls=["http%3A%2F%2Fwww.epicurious.com%2Frecipes%2Ffood%2F<br />views%2F240748%3Fmbid%3Dfbfeed"]&amp;source_id=5194643289&amp;ref_url=http%3A%2F%2Fwww.epicurious.com%2Frecipes%2Ffood&gt;%2Fviews%2F240748%3F<br />recipename%3DBREAKFAST RISOTTO%26saved_to_box%3Dy&amp;random=0.820036078758848&amp;auth_token=&lt;auth_token_redacted&gt;</pre><br /><p>If you were logged into Facebook, and I hadn't removed the auth_token, and you load that URL in a window, you would probably see the contents of the toast window rendered in all of its glory. Since you can't do that, I'll just repeat the screenshot of the toast window from above:</p><br /><br /><p style="text-align: center;"><img src="http://www.radiantcore.com/images/blogposts/facebookBeacon/facebook-toast.png" alt="Facebook Beacon Pop-up Window (a.k.a. Toast)" height="134" width="366"></p><br /><br /><p>You have five options at this point:</p><br /><ol>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li><strong>Close:</strong> closes the toast window and sends the news item to your news feed.</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li><strong>Learn More:</strong> takes you to a page on the Epicurious site with more information about the Facebook integration (<a href="http://www.epicurious.com/services/help/facebook" title="Epicurious: Facebook Action Sharing and Story Publishing">Facebook Action Sharing and Story Publishing</a>).</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li><strong>This isn't me:</strong> pops up a new window with a Facebook login in it so that you can login and add the item to your own news feed. This closes the toast window, but closing the login window without logging in didn't seem to log me out of Facebook. The recipe hasn't shown up in my feed, so I'm assuming that still blocked it from being published.</li>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <li><strong>No Thanks:</strong> closes the toast window and stops the story from being published.</li></ol><br /><br /><p>One important privacy consideration, despite this not being a privacy post, is that Facebook still knows that you added a recipe to your recipe box (or bought a book on Amazon, or a coffee table on Overstock.com, even if block the item from being posted to your news feed. I haven't seen any evidence here that shows that Beacon is sending along anything other than basically an action type, a name (in the </p><pre style="margin: 0px; display: inline;">&lt;meta&gt;</pre> tag), and a URL to link the name to, but that doesn't mean that it isn't hiding it in some of the encoded values along the way. Also, adding recipes to your recipe box is a lot more innocent than, say, purchasing adult DVDs or registering for Monster.com when you already have a job, so carefully consider what information you're broadcasting.<p></p><br /><br /><h2>Wrapping Up</h2><p>That well and truly brings us to the end of our look at Facebook Beacon. It seems impossible that you might have read all this way down and not have been lulled into sleep, but if you're still awak (hi!) and have questions, leave them in the comments below and I'll do my best to answer them. If you're interested in reading more about this topic, and particularly about the privacy concerns or integration between Beacon and the other Business tools, let me know! Thanks for reading :)</p>]]></description>
				<category>Facebook, JavaScript</category>
				<pubDate>Fri, 23 Nov 2007 17:00:00 GMT</pubDate>
			</item>
		
			
			
			
			
			
			
			
			

			
				
			
			<item>
				<title><![CDATA[Microsoft User Experience Round Table Trip Report Part 4: Expression]]></title>
				<author>Jay Goldman &lt;info@radiantcore.com&gt;</author>
				<link>http://www.radiantcore.com/blog/archives/15/03/2007/msuxroundtablereport4</link>
				<guid isPermaLink="true">http://www.radiantcore.com/blog/archives/15/03/2007/msuxroundtablereport4</guid>
				<comments>http://www.radiantcore.com/blog/archives/15/03/2007/msuxroundtablereport4#comments</comments>
				<description><![CDATA[<div id="syndicatePage">This is the fourth post in the <a href="http://www.radiantcore.com/blog/archives/12/03/2007/msuxroundtablereport1" title="Radiant Core Blog: Microsoft UX Round Table">Microsoft UX Round Table</a> series.</div><br /><br /><p>Today we take a look at <a href="http://www.microsoft.com/products/expression/en/expression-studio/default.mspx" title="Microsoft: Expression Studio">Expression Studio</a>,&nbsp; billed as:</p><blockquote>Better Designer Tools for Better End-User Experiences</blockquote><p>The suite includes tools for visual and web designers (Design and Web respectively), a media cataloguing tool (Media), and a cross-discipline Windows application development environment (Blend - mentioned in <a href="http://www.radiantcore.com/blog/archives/14/03/2007/msuxroundtablereport3" title="Design Matters (Maybe?)">yesterday's post</a>). If you haven't heard of it yet, it's only because most of them are still in Beta. Expect the hype machine to kick into action when the full suite is ready for purchase - until then, you can buy <a href="http://www.microsoft.com/products/expression/en/expression-media/default.mspx" title="Microsoft: Expression Media">Expression Media</a>, buy or try <a href="http://www.microsoft.com/products/expression/en/expression-web/default.mspx" title="Microsoft: Expression Web">Expression Web</a>, play with the RC1 (Release Candidate 1) release of <a href="http://www.microsoft.com/products/expression/en/expression-blend/default.mspx" title="Microsoft: Expression Blend">Expression Blend</a>, or play with the Beta1 release of <a href="http://www.microsoft.com/products/expression/en/expression-design/default.mspx" title="Microsoft: Expression Design">Expression Design</a>.</p><br /><br /><h2>Express Yourself</h2><p>Expression Suite is really interesting in some regards and business as usual in others. The tools share some common DNA with <a href="http://msdn2.microsoft.com/en-us/vstudio/default.aspx" title="Microsoft: Visual Studio">Visual Studio</a> in that they're all part of the .NET 3.0 framework (forgive the occasionally incorrect terminology as we're not a Microsoft development shop - it may be more correct to say that they are built on the .NET 3.0 framework). With the exception of Media, they all communicate using a new XML-based markup language invented by Microsoft, called <a href="http://en.wikipedia.org/wiki/XAML" title="Wikipedia: XAML">eXtensible Application Markup Language (XAML)</a> (prounced zammel). The team behind Expression comes from a varied background of well-known players, including <a href="http://en.wikipedia.org/wiki/Silicon_Beach_Software" title="Wikipedia: Silicon Beach">Silicon Beach</a> (among many other things, makers of the awesome <a href="http://en.wikipedia.org/wiki/Dark_Castle" title="Wikipedia: Dark Castle">Dark Castle</a> series of games), Avid, Adobe, Aldus, and Macromedia.</p><br /><br /><p>Our Expression day started off with a great intro by Angela Baxley, Product Manager (Expression), who stepped in for Erich Zocher, General Manager Tools (Expression), who couldn't make the morning. Despite her warnings about being new to the material, Angela did a great job presenting an overview of the platform based on one of the better PowerPoint decks we saw. As mentioned back on <a href="http://www.radiantcore.com/blog/archives/13/03/2007/msuxroundtablereport2" title="The New Microsoft (Again)">Day 2</a>, her presentation saw a return of the equation Platform + Tools + Craft = UX, although in this case she was talking about the Platform + Tools piece while Darren was addressing the craft bit. Between Web and Blend (think ASP.NET and .NET Framework respectively) where the actual development work happens, the new platform provides the tools to build everything that a modern dev shop needs to produce.</p><br /><br /><h2>The Value of Open Standards: XHTML vs. XAML</h2><p>Most readers of our blog don't need a lecture on why web standards are important (for more information, see <a href="http://en.wikipedia.org/wiki/Web_standards" title="Wikipedia: Web Standards">Web Standards on Wikipedia</a>), nor do you need to be told that Microsoft has not exactly been known to embrace Open Standards in the past. Given that, you would presumably find yourselves equally as curious as I was to find out what was <em>really</em> meant by:</p><blockquote>Expression Web is a professional design tool to create modern, standards-based sites which deliver superior quality on the Web.</blockquote>Turns out, they mean what they say. Web really does produce clean looking XHTML and includes built-in tools to validate the code. Wayne Smith gave a very thorough demo - which I'll get to in a second - but it set the stage for a day of appreciating a new leaf turned and daydreams of a world in which everyone plays on a level playing field.<p></p><br /><br /><p>Which really makes XAML all that much odder. David and I got in a debate with Arturo about whether XAML was actually an 'open standard', during which he confirmed that it was created at Microsoft and is controlled by them. By my books, that makes XAML a published file format rather than a standard and certainly not an open one by any means. This isn't a particularly new effort, as this handy <a href="http://en.wikipedia.org/wiki/Comparison_of_user_interface_markup_languages" title="Wikipedia: Comparision of User Interface Languages">Comparison of user interface markup languages</a> tells us, and some of the projects go back ten years. We're familiar with a different XML-based approach called <a href="http://en.wikipedia.org/wiki/XUL" title="Wikipedia: XUL">XUL</a> (eXtensible User interface Language - pronounced zool as in the ancient Sumerian deity called Zuul, who you know from Ghostbusters). The cynic in me says that having Web do proper XHTML/CSS is an admission of defeat in the sense that Microsoft has been trying for years to&nbsp; <a href="http://en.wikipedia.org/wiki/Embrace_and_extend" title="Wikipedia: Embrace and Extend">embrace and extend</a> the HTML/CSS standards and maybe they've finally given up. Or maybe they got tired of people bashing the horrible HTML that came out of FrontPage and decided to fix it. Either way, standards support is almost always a good thing so yay! But then why not open up XAML or choose to contribute and work on one of the existing efforts? This is an important issue because anyone who choses to use Expression to build their applcations will be held hostage by the XAML file format and may have to make substantial changes to future versions of their software depending on what Micrsoft chooses to do with the format. Truly Open Standards are controlled by independent third parties who have (or at least appear to have) no particular bias towards any one firm and can therefore (theoretically) make decisions which drive the whole industry forward (e.g.: the <a href="http://www.w3.org/" title="W3">W3</a> 'owns' a number of standards including <a href="http://www.w3.org/html/" title="W3: HTML">HTML</a> and <a href="http://www.w3.org/Style/CSS/" title="W3">CSS</a>). Maybe some of the Microsoft folks want to weigh in on this in the comments.</p><br /><br /><h2>Expression Web</h2><img src="http://www.radiantcore.com/images/blogposts/microsoft/expression-web.jpg" alt="Expression Web" style="margin: 0px 0px 10px 10px; float: right;" height="171" width="250"><p>Web replaces FrontPage and is an effort to bring Microsoft's web design technology up to current levels by building a new application and environment rather than trying to fix the old stuff. It's designed to do HTML and XHTML, CSS formatting and code management, and XML/XLSTs, as well as to integrate closely with ASP.NET libraries for things like <a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29" title="Wikipedia: AJAX">AJAX</a> (via the <a href="http://ajax.asp.net/" title="Microsoft: ASP.NET AJAX">AJAX Extensions</a>). The demo was given by Wayne Smith, Senior Product Manager (Expression), who started with a really quick rundown of why standards are important:</p><ol><li>Speed</li><li>Search Engine Indexing</li><li>Efficiency</li><li>Future Proofing the Web</li><li>It's professional!</li></ol><p>We've spent more time cursing at InternetExplorer's lack of support for standards than most people will ever even spend in front of a browser, so this is a very welcome change in tune from the maker of the most popular browser in the world (though, I suppose, it remains to be seen how much the one hand talks to the other). I agree with all of Wayne's points here - we've been building standard compliant sites since we started the company because they just make more sense. In addition to the standards support, Web has a bunch of other great features:</p><ul><li><strong>CSS Box Model:</strong> In 'design mode', the interface goes to great lengths to expose the box model (see <a href="http://www.brainjar.com/css/positioning/" title="BrainJar: CSS Positioning">BrainJar's CSS Positioning</a>, or a neat-o <a href="http://www.hicksdesign.co.uk/boxmodel/" title="Hicks Design: boxmodel">3D rendering by Jon Hicks</a>). Wayne showed us how Web uses shaded borders to make the padding and margins more obvious, which you can kinda see at about 17:50 of this <a href="http://www.learnexpression.com/Videos/EW-01/Video4/Introduction-to-Microsoft-Expression-Web-04.html" title="LearnExpression: Intro to Expression Web Video 4 - Formatting and Styling">training video</a>. Grab the 'crop marks' on the edge of any element to change the margin, or hold down shift and drag to change the padding.</li><li><strong>Style Application Mode:</strong> Web's Page Editor options allow you to toggle between having styles applied in either Auto Mode or Manual Mode, with Manual giving choices between inline, as classes in the head of this page, or as classes in an included document. You can also configure the Manual setting on different types of elements to behave differently (e.g.: apply h1...h6 styles inline but divs get styled in the included CSS).</li><li><strong>Multiple Doctype Support:</strong> Web supports proper <a href="http://en.wikipedia.org/wiki/Doctype" title="Wikipedia: doctype">doctype</a> declarations for XHTML1.0 Transitional and Strict, which will affect the doctype output at the top of the page as well as the options in the IntelliSense code completion menus. Web also supports a Secondary Schema, consisting of various versions of InternetExplorer, which will be used to check code compatibility when rendering Quirks Mode pages.</li><li><strong>Style Manager:</strong> If you've ever used Word's Styles properly, then you're familiar with the way the Style Manager works. <a href="http://en.wikipedia.org/wiki/Wysiwyg" title="Wikipedia: WYSIWYG">WYSIWYG</a> previews of styles make it easy to pick the right text formatting and apply with a simple click.</li></ul><p>Overall, I was really impressed with the product. If they ever released a version for Mac OS there's a good chance we might start using it internally (although it looked good, it didn't look good enough to run Parallels and Vista just to use it). If you're a Windows-based web shop, especially one that does ASP.NET work, you should take a look.</p><h2 style="clear: right;">Expression Design</h2><img src="http://www.radiantcore.com/images/blogposts/microsoft/expression-design.jpg" alt="Expression design" style="margin: 0px 10px 10px 0px; float: left;" height="171" width="250"><p>Arturo Toledo took over to show us Expression Design, a vector-based graphic design tool. I actually have no notes from his demo other than <a href="http://www.adobe.com/products/illustrator/" title="Adobe: Illustrator">"Adobe Illustrator"</a>, which will tell you pretty much all you need to know. Challenging Adobe in this space is like trying to take them on in the Photoshop arena, which is ill-advised unless you're even bigger than they are and have mountains of cash. Which Microsoft happens to be and have. They may, in fact, be the only company out there who could reasonably stand a chance of taking any substantial market share away from the 800-pound gorrila. Right now I think you'll have a tough time ahead of you if you need to get your designers to try and switch over, unless the tools, keyboard shortcuts, and menu items mimick Illustrator pretty closely and your designers don't have to give up years of training and muscle memory. The biggest (only?) reason you would do this is to take advantage of the fact that Design can output XAML files to pull straight into Blend. That said, <a href="http://blogs.msdn.com/mswanson/" title="Mike Swanson's blog">Mike Swanson</a> (a Technical Evangelist with Microsoft) has released an <a href="http://www.mikeswanson.com/xamlexport/" title="Mike Swanson: Adobe Illustrator to XAML Format">Adobe Illustrator to XAML Export</a> plugin with reasonably good support for the Illustrator feature set and better support coming soon (some of the unsupported features aren't available in Design or XAML), so yeah. Draw your own conclusions (get it? draw? ha!).</p><br /><br /><h2 style="clear: left;">Expression Blend</h2><img src="http://www.radiantcore.com/images/blogposts/microsoft/expression-blend.jpg" alt="Expression Blend" style="margin: 0px 0px 10px 10px; float: right;" height="171" width="250"><p>In the same way that you can think of Web replacing FrontPage, Blend basically replaces VisualBasic. The primary intent for the Blend is to build Windows applications on the <a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation" title="Wikipedia: Windows Presentation Foundation">Windows Presentation Foundation (WPF)</a>. Arturo showed us a few demos of the kinds of things which Blend is intended for (the now defunct <a href="http://channel9.msdn.com/showpost.aspx?postid=156065" title="Microsoft: Max">Microsoft Max</a> project and the <a href="http://channel9.msdn.com/Showpost.aspx?postid=109413" title="Microsoft: Avalon Patient Monitor">Avalon Patient Monitor</a> specifically), which made for really cool looking interfaces with debatable practical value (like the now famous <a href="http://youtube.com/watch?v=ysEVYwa-vHM" title="YouTube: Jeff Han's Perceptive Pixel promo video">Jeff Han video</a>). I'm always slightly suspicious of totally avant garde interfaces for medical applications which include snazzy animations and effects - when life-threatening decisions need to be made, I sure hope my doctor has to wade through flipping menus and rotating panels! - but it works very well as a proof of concept to show off how flexible Blend's toolset is. I was also slightly put off by Arturo's repeated statements that Blend finally lets you escape the tyranny of the boring gray button (and the <a href="http://msdn2.microsoft.com/en-us/library/aa511258.aspx" title="Microsoft: Windows Vista User Experience Guidelines">Microsoft UX Guidelines</a>) and map full motion video to your spinning control surfaces, which brought to mind thousands of horrendous Flashtastrophes (and one of my favourite <a href="http://www.penny-arcade.com/comic/1999/03/03" title="Penny Arcade: Macromedia FlashDance">Penny Arcade</a> cartoons ever). At any rate, if we built Windows apps (or if <a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation#WPF.2FE" title="Wikipedia: Windows Presentation Foundation Everywhere">WPF/E</a> does become a potential competitor to Flash and gets widespread adoption as a browser plugin), it looks like a great environment for building interfaces. I think we, as a group, were a little confused about who it's being aimed at (see <a href="http://www.radiantcore.com/blog/archives/14/03/2007/msuxroundtablereport3" title="Design Matters (Maybe?)">yesterday's post</a> if you haven't already), but once we had sorted out their definition of 'designer', it all made sense. I was particularly impressed when Arturo pulled in an application that only its developer could love, built in Visual Studio, and then reskinned it without affecting the functionality (I grabbed two photos of the finished <a href="http://flickr.com/photos/chesh2000/399512380/in/set-72157594546050781/" title="Flickr: Expression Demo Login Screen">login</a> and <a href="http://flickr.com/photos/chesh2000/399513411/in/set-72157594546050781/" title="Flickr: Expression Demo Welcome Screen">welcome</a> screens). Going on personal experience, I have a suspicion that a lot of shops will end up using Blend by having their Dev team build off a spec and then having their UX/Visual team polish things, so it's great to see that the app works that way too.</p><h2 style="clear: right;">Expression Media</h2><img src="http://www.radiantcore.com/images/blogposts/microsoft/expression-media.jpg" alt="Expression Media" style="margin: 0px 10px 10px 0px; float: left;" height="171" width="250"><p>Media is actually iView Media Pro, formerly made by <a href="http://www.iview-multimedia.com/" title="iView Multimedia">iView Multimedia</a> out of London, and acquired by Microsoft on June 27th, 2006, and is the only product in the Expression Suite which is available for Mac OS X. Media is a Digital Asset Management (DAM) Tool (which is fun to say - Dam Tool!), which basically sucks in all of your media in a whole littany of formats and then provides tagging and sorting capabilities. There's an important distinction in the DAM world between <em>browsers</em> (which just read the info available in the media files themselves - like <a href="http://en.wikipedia.org/wiki/Exif" title="Wikipedia: EXIF">EXIF</a> data in <a href="http://en.wikipedia.org/wiki/Jpg" title="Wikipedia: JPEG">JPEGs</a>) and <em>catalogues</em> (which store their own meta data about the files and can therefore provide much easier and more efficient sorting). If you've used anything like Apple's <a href="http://www.apple.com/ilife/iphoto/" title="Apple: iPhoto">iPhoto</a> or <a href="http://www.apple.com/aperture/" title="Apple: Aperture">Aperture</a>, Adobe's <a href="http://www.adobe.com/products/photoshoplightroom/" title="Adobe: Lightroom">Lightroom</a>, or even Google's <a href="http://picasa.google.com/" title="Google: Picasa">Picasa</a>, you're familiar with the basics. Media goes further in that you can build up all kinds of ways of looking at photos, including adding custom fields (e.g.: a pro photographer might add price to track how much to charge for her images), and build collections for quick access (e.g.: all potentially good backgrounds in one area). It looked like an excellent media catalogue and something that we might make use of to store assets from different clients for easy retrieval by all of our Professional Services team members. There was some discussion about how much support was included for sharing the library files (could they be checked into a version control system? read of a network mount?) which I think was left open, so if any of the Microsoft folk know the answer, please feel free to leave a comment.</p><h2 style="clear: left;">Final Expressions</h2><p>I really had to work at putting myself in the mindset of a potential purchaser/user of the software since our Mac bias basically rules us out. Someone did ask Erich Zocher if there were plans to do Mac versions and there clearly aren't, which I think is a real shame. We spend a lot of time in the trenches of this industry and we're seeing more and more glowing Apples while we're down there - particularly amongst the <a href="http://en.wikipedia.org/wiki/Digerati" title="Wikipedia: digerati">digerati</a> whose influence reaches far and wide</p>. Although we know some web shops who work on Windows, the vast majority are Mac-based or are in the process of switching over, so they are increasingly unlikely to use products like Design and Web. That said, if we were a Windows-based shop and we built sites and applications on ASP.NET and the .NET Framework (which sounds like a weird techno band), we would almost certainly use Expression. I return to something I said way back on Monday - in the end, they're all just tools - and if you buy into the Microsoft way, these looked like great tools.<p></p><br /><br /><p>That's it for Day 4 - tune in tomorrow for the <strong>big wrap up</strong>!</p>]]></description>
				<category>Trip Reports, User Experience, Taking Care of Business</category>
				<pubDate>Thu, 15 Mar 2007 09:00:00 GMT</pubDate>
			</item>
		
	</channel>
</rss>