<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>HTMList.com, A Web Development Blog by Synapse Studios</title>
	
	<link>http://www.htmlist.com</link>
	<description>A Web Development Blog by Synapse Studios</description>
	<lastBuildDate>Thu, 28 Jan 2010 23:46:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/HTMList" /><feedburner:info uri="htmlist" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /><feedburner:emailServiceId>HTMList</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Extending PHP 5.3 Closures with Serialization and Reflection</title>
		<link>http://feedproxy.google.com/~r/HTMList/~3/wNdIG5J-IOE/</link>
		<comments>http://www.htmlist.com/development/extending-php-5-3-closures-with-serialization-and-reflection/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 22:32:57 +0000</pubDate>
		<dc:creator>Jeremy Lindblom</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[classes]]></category>
		<category><![CDATA[closures]]></category>
		<category><![CDATA[magic methods]]></category>
		<category><![CDATA[methods]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[reflection]]></category>
		<category><![CDATA[serialization]]></category>

		<guid isPermaLink="false">http://www.htmlist.com/?p=551</guid>
		<description><![CDATA[Our developer examines Closures in PHP 5.3]]></description>
			<content:encoded><![CDATA[<p>PHP 5.3 has brought with it some powerful and much-needed features like <a href="http://php.net/manual/en/language.oop5.late-static-bindings.php">late static bindings</a>, <a href="http://us3.php.net/manual/en/language.namespaces.rationale.php">namespaces</a>, and closures (also referred to as anonymous functions and lambda functions). Anyone who is experienced with JavaScript or who has worked with programming languages like Scheme or Lisp should realize the value that anonymous functions can bring to PHP. The <a title="PHP Closures (Anonymous Functions)" href="http://www.php.net/manual/en/functions.anonymous.php">PHP Manual explains closures</a> like this:</p>
<blockquote><p>Anonymous functions, also known as closures, allow the creation of functions which have no specified name. They are most useful as the value of callback parameters, but they have many other uses. Closures can also be used as the values of variables; PHP automatically converts such expressions into instances of the Closure internal class.</p></blockquote>
<p>PHP has very few <a title="PHP predefined classes" href="http://php.net/manual/en/reserved.classes.php">predefined classes</a> that are part of the core language, so naturally I was intrigued by the Closure class. The PHP Manual has this to say about the class:</p>
<blockquote><p>The predefined final class Closure was introduced in PHP 5.3.0. It is used for internal implementation of anonymous functions. The class has a constructor forbidding the manual creation of the object (issues <code>E_RECOVERABLE_ERROR</code>) and the <code>__invoke()</code> method with the calling magic.</p></blockquote>
<p>The <a href="http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.invoke">invoke magic method</a> is also a new feature in PHP 5.3. It is called when an object is used in the context of a function (e.g. <code>$object($parameter);</code>). Since Closure objects will be used like functions, this is a critical feature of the Closure object. The Closure class may be perfectly equipped to act like an anonymous function, but it does not provide any extra utility beyond that. A <code>var_dump()</code> of a closure will reveal the functions parameters, but there is no way to get any other information about the Closure (like the actual code of the function). Trying to serialize the Closure throws an Exception and <code>json_encode()</code> just returns an empty JSON string. To make matters worse, the Closure class is <a href="http://us.php.net/manual/en/language.oop5.final.php">final</a>, so there is no way to extend it.</p>
<p>That simply wasn&#8217;t going to cut it for me. I wanted to make my own Closure class that was at least able to do the following: <span id="more-551"></span></p>
<ol>
<li>Invoke the Closure (with <code>__invoke()</code>) just like the PHP Closure class</li>
<li>Retrieve the actual code of the Closure</li>
<li>Retrieve detailed data about the Closure&#8217;s parameters</li>
<li>Retrieve the names and values of any variables inherited from the Closure&#8217;s parent&#8217;s scope (with the <code>use</code> construct)</li>
<li>Serialize and unserialize the Closure</li>
</ol>
<p>I decided to play around with the <a href="http://php.net/manual/en/book.reflection.php">Reflection API</a> to see what kind of information I could get from the Closure. A Closure is a function, so using the <a href="http://us.php.net/manual/en/class.reflectionfunction.php">ReflectionFunction class</a> provides the same information about Closures as it does about any other functions. PHP 5.3 also added the <code>isClosure()</code> method to the ReflectionFunction (in case you weren&#8217;t convinced that reflection would be helpful). After some tinkering, it became apparent that I would be able to accomplish all of my desires. I will walk you through the construction of my &#8220;SuperClosure&#8221; class and explain how the creative use of Reflection allows us to find ways around the problems normally blocking the ability to have my desired features.</p>
<h2 id="toc-1-grant-the-ability-to-invoke-the-closure">1. Grant the ability to invoke the Closure</h2>
<p>The first goal was to create the basic SuperClosure class that both encapsulates and allows invocation of the Closure. To do this I wrote a simple class with a constructor and the magic <code>__invoke()</code> method. I also included an accessor method (getter) for the actual Closure. In the constructor I created an instance of the ReflectionFunction class and stored it as a class member that helped allow invocation of the closure with a variable number of arguments. It also helped me accomplish other things later. The following code shows the basic class upon which I will be building. The complete will be shown at the end of the article.</p>
<pre class="brush: php">class SuperClosure {

	protected $closure = NULL;
	protected $reflection = NULL;

	public function __construct($function)
	{
		if ( ! $function instanceOf Closure)
			throw new InvalidArgumentException();

		$this-&gt;closure = $function;
		$this-&gt;reflection = new ReflectionFunction($function);
	}

	public function __invoke()
	{
		$args = func_get_args();
		return $this-&gt;reflection-&gt;invokeArgs($args);
	}

	public function getClosure()
	{
		return $this-&gt;closure;
	}
}</pre>
<p>The <code>__invoke()</code> method allows the SuperClosure object to be used exactly as if it was a Closure object. I had to recreate this functionality for the SuperClosure class since I was not able to extend the Closure to begin with. In order to pass arguments through to the real Closure, I used a combination of the <a href="http://php.net/manual/en/function.func-get-args.php"><code>func_get_args()</code></a> function and the <code>invokeArgs()</code> method of ReflectionFunction to ensure that any variable number of arguments could be used. I could have also used <code>call_user_func_array()</code> function, but I prefer Reflection, and since I already had an instance of the ReflectionFunction, the <code>invokeArgs()</code> method seemed like a better choice.</p>
<h2 id="toc-2-retrieve-the-actual-code-of-the-function">2. Retrieve the actual code of the function</h2>
<p>Secondly, I added code that allowed the SuperClosure class to find and store the actual code defining the closure. This feature is actually the key to doing the serialization later and is the most complicated part of the program. To accomplish this portion of the program, I used the instance of ReflectionFunction from Step 1 and the <a href="http://php.net/manual/en/class.splfileobject.php">SplFileObject</a> class, an SPL class which provides a nice object-oriented interface for dealing with files. The <code>getFileName()</code>, <code>getStartLine()</code>, and <code>getEndLine()</code> methods of the ReflectionFunction class allowed me to retrieve all the information I needed to find the source code of the Closure function. Using the SplFileObject to open and read from the source file and in combination with some string manipulation, I was able to obtain the closure&#8217;s source code. The following code shows the protected <code>_fetchCode()</code> method used to parse the closure&#8217;s code out of its source file:</p>
<pre class="brush: php">protected function _fetchCode()
{
	// Open file and seek to the first line of the closure
	$file = new SplFileObject($this-&gt;reflection-&gt;getFileName());
	$file-&gt;seek($this-&gt;reflection-&gt;getStartLine()-1);

	// Retrieve all of the lines that contain code for the closure
	$code = &#039;&#039;;
	while ($file-&gt;key() &lt; $this-&gt;reflection-&gt;getEndLine())
	{
		$code .= $file-&gt;current();
		$file-&gt;next();
	}

	// Only keep the code defining that closure
	$begin = strpos($code, &#039;function&#039;);
	$end = strrpos($code, &#039;}&#039;);
	$code = substr($code, $begin, $end - $begin + 1);

	return $code;
}</pre>
<p>The only limitations with the current version of this function are that you cannot have multiple closures on a single line and you cannot use the word &#8220;function&#8221; anywhere besides the actual closure&#8217;s declaration.</p>
<h2 id="toc-3-retrieve-detailed-data-about-the-closures-parameters">3. Retrieve detailed data about the Closure&#8217;s parameters</h2>
<p>Retrieving information about the closure&#8217;s parameters was as simple as adding a method that simply returns the result of the <code>getParameters()</code> method the SuperClosure&#8217;s instance of ReflectionFunction. That&#8217;s all. The <code>getParameters()</code> method returns ReflectionParameter objects which have several methods for getting information about the parameters including their names, values, default values, and more.</p>
<h2 id="toc-4-retrieve-the-names-and-values-of-any-variables-inherited-from-the-closures-parents-scope">4. Retrieve the names and values of any variables inherited from the Closure&#8217;s parent&#8217;s scope</h2>
<p>One of the biggest problems I had was retrieving the names and values of the variables added to the Closure&#8217;s scope with the <code>use</code> construct. There isn&#8217;t a documented way of doing this as far as I know, but I was able to figure out a way to do it after playing around some more with the ReflectionFunction class (it is just so helpful). These variables are actually included in the results of the <code>getStaticVariables()</code> method. If the closure declares any variables with the <code>static</code> keyword, these will also be included in the results. To get around this I added the <code>_fetchUsedVariables()</code> method that uses a combination of the <code>getStaticVariables()</code> method and some string manipulation of the Closure&#8217;s code (from Step 2) to find only the variables that were inherited from the parent&#8217;s scope. The following code shows the <code>_fetchUsedVariables()</code> method:</p>
<pre class="brush: php">protected function _fetchUsedVariables()
{
	// Make sure the use construct is actually used
	$use_index = stripos($this-&gt;code, &#039;use&#039;);
	if ( ! $use_index)
		return array();

	// Get the names of the variables inside the use statement
	$begin = strpos($this-&gt;code, &#039;(&#039;, $use_index) + 1;
	$end = strpos($this-&gt;code, &#039;)&#039;, $begin);
	$vars = explode(&#039;,&#039;, substr($this-&gt;code, $begin, $end - $begin));

	// Get the static variables of the function via reflection
	$static_vars = $this-&gt;reflection-&gt;getStaticVariables();

	// Only keep the variables that appeared in both sets
	$used_vars = array();
	foreach ($vars as $var)
	{
		$var = trim($var, &#039; $&amp;amp;&#039;);
		$used_vars[$var] = $static_vars[$var];
	}

	return $used_vars;
}</pre>
<h2 id="toc-5-grant-the-ability-to-serialize-and-unserialize-the-closure">5. Grant the ability to serialize and unserialize the Closure</h2>
<p>Finally, I implemented the serialization capabilities. Since an actual closure object cannot be serialized (it gives a fatal error), I had to be creative to come up with a way to do my own serialization. The code I wrote for Step 2 and Step 4 made this possible. The <a href="http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.sleep">sleep magic method</a> allows you to hook into the serialization process, so I used this method to prepare my SuperClosure class for serialization. In order for my class to be serialized, I needed to first stop the Closure object and the ReflectionFunction object representing the Closure from being serialized. The <code>__sleep()</code> method should return an array of the class members you are serializing, so I simply left those variables out of the list. Because I was serializing the Closure&#8217;s code and static variables, it made possible in the <code>__wakeup()</code> magic method to recreate the Closure object using the code. To do this I had to use the <code>extract()</code> function on my array of used variables to import them back into the scope. Then I performed an <code>eval()</code> operation on the Closure&#8217;s code in order to recreate the Closure. <code>eval()</code> is always a risky operation, but in this case it makes sense. If you are planning to use this code for any of your own projects, I urge you to take precautions.  The following code shows the complete SuperClosure class with the additions of the <code>__sleep(</code>) and <code>__wakeup()</code> methods.</p>
<pre class="brush: php">class SuperClosure {

	protected $closure = NULL;
	protected $reflection = NULL;
	protected $code = NULL;
	protected $used_variables = array();

	public function __construct($function)
	{
		if ( ! $function instanceOf Closure)
			throw new InvalidArgumentException();

		$this-&gt;closure = $function;
		$this-&gt;reflection = new ReflectionFunction($function);
		$this-&gt;code = $this-&gt;_fetchCode();
		$this-&gt;used_variables = $this-&gt;_fetchUsedVariables();
	}

	public function __invoke()
	{
		$args = func_get_args();
		return $this-&gt;reflection-&gt;invokeArgs($args);
	}

	public function getClosure()
	{
		return $this-&gt;closure;
	}

	protected function _fetchCode()
	{
		// Open file and seek to the first line of the closure
		$file = new SplFileObject($this-&gt;reflection-&gt;getFileName());
		$file-&gt;seek($this-&gt;reflection-&gt;getStartLine()-1);

		// Retrieve all of the lines that contain code for the closure
		$code = &#039;&#039;;
		while ($file-&gt;key() &lt; $this-&gt;reflection-&gt;getEndLine())
		{
			$code .= $file-&gt;current();
			$file-&gt;next();
		}

		// Only keep the code defining that closure
		$begin = strpos($code, &#039;function&#039;);
		$end = strrpos($code, &#039;}&#039;);
		$code = substr($code, $begin, $end - $begin + 1);

		return $code;
	}

	public function getCode()
	{
		return $this-&gt;code;
	}

	public function getParameters()
	{
		return $this-&gt;reflection-&gt;getParameters();
	}

	protected function _fetchUsedVariables()
	{
		// Make sure the use construct is actually used
		$use_index = stripos($this-&gt;code, &#039;use&#039;);
		if ( ! $use_index)
			return array();

		// Get the names of the variables inside the use statement
		$begin = strpos($this-&gt;code, &#039;(&#039;, $use_index) + 1;
		$end = strpos($this-&gt;code, &#039;)&#039;, $begin);
		$vars = explode(&#039;,&#039;, substr($this-&gt;code, $begin, $end - $begin));

		// Get the static variables of the function via reflection
		$static_vars = $this-&gt;reflection-&gt;getStaticVariables();

		// Only keep the variables that appeared in both sets
		$used_vars = array();
		foreach ($vars as $var)
		{
			$var = trim($var, &#039; $&amp;amp;&#039;);
			$used_vars[$var] = $static_vars[$var];
		}

		return $used_vars;
	}

	public function getUsedVariables()
	{
		return $this-&gt;used_variables;
	}

	public function __sleep()
	{
		return array(&#039;code&#039;, &#039;used_variables&#039;);
	}

	public function __wakeup()
	{
		extract($this-&gt;used_variables);

		eval(&#039;$_function = &#039;.$this-&gt;code.&#039;;&#039;);
		if (isset($_function) AND $_function instanceOf Closure)
		{
			$this-&gt;closure = $_function;
			$this-&gt;reflection = new ReflectionFunction($_function);
		}
		else
			throw new Exception();
	}
}</pre>
<h2 id="toc-conclusion">Conclusion</h2>
<p>With some cleverness and reflection, I was able to create the SuperClosure class and extend the Closure&#8217;s normal capabilities. Although my class does not enhance the typical use of a PHP Closure it does make it possible to serialize and transport a closure and provides an interface for examining the parameters and inherited variables. This means that we can do:</p>
<pre class="brush: php">$closure = new SuperClosure(
	function($num1, $num2) {return $num1 + $num2;}
);
$serialized_closure = serialize($closure);
$unserialized_closure = unserialize($serialized_closure);
echo $unserialized_closure(1, 5);
</pre>
<p>without worrying about errors. Also, it would technically be possible to send closures through a remote service.</p>
<p>From what I have read in the PHP Manual, this class may have to be changed in the future. The Manual states this regarding anonymous functions:</p>
<blockquote><p>Anonymous functions are currently implemented using the Closure class. This is an implementation detail and should not be relied upon.</p></blockquote>
<p>So according to this, future versions of PHP might implement closures differently, and my class would have to be rewritten.</p>
<p>If you would like a copy of the code from this article (and an example of its use) you can find it on <a href="http://github.com/jeremeamia/super_closure">my Github account</a>.</p>
<img src="http://www.htmlist.com/wordpress/?ak_action=api_record_view&id=551&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/HTMList/~4/wNdIG5J-IOE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.htmlist.com/development/extending-php-5-3-closures-with-serialization-and-reflection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.htmlist.com/development/extending-php-5-3-closures-with-serialization-and-reflection/</feedburner:origLink></item>
		<item>
		<title>Facebook vs. Twitter Clickthroughs: More Bang For Your Buck</title>
		<link>http://feedproxy.google.com/~r/HTMList/~3/gG2bCG9Jues/</link>
		<comments>http://www.htmlist.com/cool-stuff/facebook-vs-twitter-clickthroughs-more-bang-for-your-buck/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 17:00:09 +0000</pubDate>
		<dc:creator>Chris Cardinal</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Cool Stuff]]></category>
		<category><![CDATA[analytics]]></category>
		<category><![CDATA[clickthroughs]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[Social Networking]]></category>
		<category><![CDATA[statistics]]></category>
		<category><![CDATA[threadknits]]></category>
		<category><![CDATA[threadless]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[viral]]></category>

		<guid isPermaLink="false">http://www.htmlist.com/?p=530</guid>
		<description><![CDATA[We look at clickthrough rates from Twitter and Facebook and see how they compare.]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="size-full wp-image-532 aligncenter" title="Facebook vs Twitter" src="http://www.htmlist.com/wordpress/wp-content/uploads/2010/01/facebook_vs_twitter.jpg" alt="Facebook vs Twitter" width="381" height="214" /></p>
<p>While managing your social networking presence on Twitter and Facebook, it can be difficult to quantify the impact of each medium. While I&#8217;m a huge fan of Twitter, traffic results from earlier today on one of my sites confirmed for me what may sound like common sense: <strong>Facebook fans drive far more traffic per-user than Twitter followers for a given promotional message.</strong></p>
<p>I&#8217;m currently running a contest in association with T-shirt company <a title="Threadless.com" href="http://clickserve.cc-dt.com/link/tplclick?lid=41000000027278770&amp;pubid=21000000000210012">Threadless</a>. (It&#8217;s called <a title="Threadknits" href="http://www.threadknits.com/">Threadknits</a>, and it&#8217;s based on knitting and crocheting their t-shirt designs into crafts.) Today, Threadless posted a message on their Facebook page and  Twitter, both with essentially the same content: an invitation to check out Threadknits. They were both posted at nearly the same time.</p>
<p>The numbers are what might surprise you. Threadless has almost 1,500,000 followers on Twitter, and &#8220;only&#8221; 102,000 fans on Facebook. With the posts made within an hour of each other, my traffic on the site shot up, with a couple thousand visitors hitting by day&#8217;s end. Here&#8217;s the breakdown of traffic driven from each:</p>
<table border="1" style="border:1px dashed #000;" width="80%" cellpadding="3">
<thead>
<tr>
<td><strong>Medium:</strong></td>
<td><strong>Fans:</strong></td>
<td><strong>Visitors:</strong></td>
<td><strong>% Audience Clickthroughs:</strong></td>
</tr>
</thead>
<tbody>
<tr>
<td>Facebook</td>
<td>~102,000</td>
<td>~1,110</td>
<td><strong>~1.08%</strong></td>
</tr>
<tr>
<td>Twitter</td>
<td>~1,490,000</td>
<td>~682</td>
<td><strong>~0.04%</strong></td>
</tr>
</tbody>
</table>
<p>&nbsp;<br />
The difference is absolutely staggering. Whereas Facebook generated an approximate 1.08% clickthrough rate, Twitter&#8217;s was closer to, well, 0%. 232 visitors came from Twitter or related sites directly and 450 additional clicks landed on the home page without a referrer, which I&#8217;m chalking up to clicks from Twitter clients. (Though, to be fair, this could easily overstate Twitter&#8217;s influence.)</p>
<p>On a <a title="Threadcakes" href="http://www.threadcakes.com/">previous contest</a>, Threadless would tweet and I&#8217;d see between 1,000-2,000 clicks on their roughly 1.4 million followers, so while it may be a bit low today, I think the point stands: Even at its best, Twitter for large audiences generates clickthrough rates dramatically lower than Facebook. For 2,000 clicks, the rate at 1.4M followers stood at 0.14%. A quick look at the bit.ly stats on a few links from <a href="http://www.twitter.com/aplusk">Ashton Kutcher</a> (the #1 Twitter personality by followers) shows they typically net about 20,000-30,000 clickthroughs, on 4.3M followers, gaining a decent amount on the Threadless best-case scenario all the way up to 0.48% ~ 0.60%. (This accounts somewhat for the viral nature of Twitter as bit.ly clicks are counted for retweets as well.) Naturally, clickthrough rates will vary dramatically even amongst popular Twitter personalities for a variety of reasons. I&#8217;d like to focus more on the significant difference between the Facebook and Twitter rates I witnessed today.</p>
<p>There are likely several possible reasons for this:</p>
<ul>
<li>The audience may be slightly different—people willing to consider themselves &#8220;fans&#8221; on Facebook may be more picky with their allegiance than those willing to follow an account on Twitter.</li>
<li>The phrasing and formatting of the message were slightly different—not exactly apples-to-apples as Facebook includes the logo and a text clip from the website, but I imagine this had a negligible effect.</li>
<li>My mileage may vary—this is an admittedly small sample size, but I think the evidence and logic around these results indicate they&#8217;re not anomalous.</li>
<li>Most importantly, <strong>Facebook lingers while Twitter sails by. </strong>Users are probably more likely to follow links during their Facebook time than from a passing Twitter notification unless it&#8217;s of particular interest to them.</li>
</ul>
<p>That last point is particularly important. Facebook, having reconfigured their News Feed yet again, no longer sorts things there chronologically. They&#8217;ve merged the Highlights functionality back into the News Feed which they now use to keep certain posts &#8220;stickier&#8221; than others based on what they believe you might be interested in. (It manages to do a strikingly horrible job at this compared to how it used to perform, but that&#8217;s a conversation for a different post.)</p>
<p><strong>With Twitter, the very nature of real-time can be summed up: blink and you miss it.</strong> While you can use a Twitter client to review tweets over the past day or two, it&#8217;s still less likely your tweet was as visible over Twitter as a post would be on Facebook&#8217;s News Feed. I&#8217;d like to see some more statistics on total audience reach. The clickthrough rate surely only tells part of the story—I&#8217;d be far more interested to learn what percentage of each audience even <em>saw</em> the post, and determine true clickthrough rates from that.</p>
<p>In the end, it&#8217;s important to consider the overall spirit of the findings here. Twitter is great for growing virally and interacting with customers, but your message on Facebook may have a far more lasting impression and generate greater returns, even if fans are more of a fight to procure. Engage on both, but recognize the differences between them and leverage each of their strengths. I&#8217;ll likely post about the best way to do that for each site in the near future.</p>
<p><small><em>(The above graphic represents the total clickthrough breakdown by medium assuming a linear progression of Threadless&#8217; Facebook audience to match their Twitter audience, maintaining the same clickthrough rates from today&#8217;s traffic. It&#8217;s likely the Facebook clickthrough rate could in fact fall some as their audience grew, but it&#8217;s my belief that it would still beat Twitter, user for user.)</em></small></p>
<img src="http://www.htmlist.com/wordpress/?ak_action=api_record_view&id=530&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/HTMList/~4/gG2bCG9Jues" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.htmlist.com/cool-stuff/facebook-vs-twitter-clickthroughs-more-bang-for-your-buck/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://www.htmlist.com/cool-stuff/facebook-vs-twitter-clickthroughs-more-bang-for-your-buck/</feedburner:origLink></item>
		<item>
		<title>Nexus One Subsidy Hack: Drop Your Data Plan, Get $100</title>
		<link>http://feedproxy.google.com/~r/HTMList/~3/LucMGK_J_sI/</link>
		<comments>http://www.htmlist.com/tech-news/nexus-one-subsidy-hack-drop-your-data-plan-for-100-bucks/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 06:04:08 +0000</pubDate>
		<dc:creator>Chris Cardinal</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[Tech News]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[cell phones]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[nexus one]]></category>
		<category><![CDATA[subsidies]]></category>
		<category><![CDATA[t-mobile]]></category>

		<guid isPermaLink="false">http://www.htmlist.com/?p=524</guid>
		<description><![CDATA[Google releases their new Nexus One phone and we look at some of the problems with the subsidized price and their checkout process.]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-525" title="nexus_one" src="http://www.htmlist.com/wordpress/wp-content/uploads/2010/01/nexus_one.jpg" alt="nexus_one" width="178" height="350" />Google officially released their Nexus One Android phone today under the guise of a $179 subsidized price tag ($529 unsubsidized and unlocked). As many T-Mobile customers discovered today, that price only applied if you <em>weren&#8217;t</em> already a loyal customer. Instead, TMO customers were shafted subsidized based on their contract status and the presence of an existing data plan.</p>
<p>The official <a href="http://www.google.com/support/android/bin/answer.py?hl=en&amp;answer=171784">Google Support</a> page describes the following subsidy tiers:</p>
<ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-size: 12px; line-height: 20px; padding: 0px; border: 0px initial initial;">
<li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 15px; padding-top: 3px; padding-right: 0px; padding-bottom: 3px; padding-left: 0px; list-style-type: circle !important; list-style-position: inside !important; list-style-image: initial !important; border: 0px initial initial;">Nexus One without service: $529</li>
<li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 15px; padding-top: 3px; padding-right: 0px; padding-bottom: 3px; padding-left: 0px; list-style-type: circle !important; list-style-position: inside !important; list-style-image: initial !important; border: 0px initial initial;">Nexus One with new, 2-year T-Mobile US service plan for new customers: $179</li>
<li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 15px; padding-top: 3px; padding-right: 0px; padding-bottom: 3px; padding-left: 0px; list-style-type: circle !important; list-style-position: inside !important; list-style-image: initial !important; border: 0px initial initial;">Nexus One with new, 2-year T-Mobile US service plan for qualifying existing T-Mobile customers who are adding data plans: $279</li>
<li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 15px; padding-top: 3px; padding-right: 0px; padding-bottom: 3px; padding-left: 0px; list-style-type: circle !important; list-style-position: inside !important; list-style-image: initial !important; border: 0px initial initial;">Nexus One with new, 2-year T-Mobile US service plan for qualifying existing T-Mobile customers who are upgrading their data plans: $379</li>
</ul>
<p>I&#8217;ve been a T-Mobile customer for a little over seven years now, and off-contract for pretty much that entire time. I&#8217;m thus now open to what T-Mobile calls their full subsidy. Except with the Google phone, where Google manages the subsidy, not T-Mobile. Since I had a $10/month sad, EDGE-based data plan with TMO, Google informed me after polling the TMO servers that I was eligible for the $150 subsidy, for a Nexus One price of $379. The next subsidy tier up is $100 cheaper for a price of $279.</p>
<p>The only distinction lies in whether you are &#8220;upgrading your data plan&#8221; or &#8220;adding a data plan.&#8221; This seemed like a simple enough problem to fix: I called T-Mobile support and asked them to cancel my data plan. They said it would be no problem, since I&#8217;m not under contract. I worried briefly that it wouldn&#8217;t be visible to the Google-based powers that be until the next billing cycle, but the TMO rep informed me that the change is instant. Since I knew I was buying a Nexus either way, I pulled the trigger.</p>
<p>Wouldn&#8217;t you know it, not five minutes later when I went to make the purchase again Google&#8217;s web store fetched my data and lo and behold, my Nexus price was now just $279. Easy-peasy, that.</p>
<p>The ironic part is that I&#8217;m moderately sure I could re-activate the data plan now without incurring any real additional fees in the day-and-a-half I may have to wait for the overnight shipping to get here, but I don&#8217;t use the slow EDGE service enough to warrant wrecking my cool here.</p>
<p>After all the dust settled, I realized how asinine Google had decided to make the checkout process by managing sales and subsidies of the device themselves. They limit you to <em>just one rate plan </em>during your purchase, which is more than a little infuriating as I received different answers from TMO reps over whether upping my minutes would cause Google to come after me for the subsidy. (It appears that you CAN upgrade your account to another Even More plan according to a recently-added note on <a href="http://www.google.com/support/android/bin/answer.py?hl=en&amp;answer=166524">this</a> Google Support page.) The pricing rates are buried under a Support knowledge base article and not at all transparent. Google says $179 and then pulls an enormous J/K on you as they fetch your account information, seemingly pulling a figure out of thin air as it suits them. The T-Mobile reps can&#8217;t do anything about it since the purchase isn&#8217;t on their side of the pond at all. And Google is nowhere to be found.</p>
<p>Strange to me that a company so intent on delivering a device with their brand and full-throated support would instantly fawn off users to HTC and T-Mobile so that they don&#8217;t need to support their customers in any meaningful way. This isn&#8217;t the first time Google has proved shockingly absent with matters of support, but it feels very different when you&#8217;re purchasing a product subject to additional cancellation fees.</p>
<p>Further, it seems completely short-sighted to limit the subsidy as they have. Restricting the best price to new T-Mobile customers alone is frustrating, but they make it nearly impossible for anyone with a family plan to switch at the subsidized price. Worse, the subsidy at its lower rates really just amortizes the cost of the phone out over those two years, as the Even More plans cost $10/month more—that&#8217;s $240 over two years right there. <strong>Let&#8217;s be clear:</strong> <strong>At $379, you&#8217;re better off financially buying the unlocked phone and using the Even More Plus plan,</strong> which costs $10 less, for a total savings of $90 over the two year term. Even better since you&#8217;re not under any contract at the $529 rate.</p>
<p>Creating barriers to entry for new customers is always a bad idea, made all the worse when those barriers seem arbitrary and class-based. Google needs to stop with the silly tiers and subsidize the damn phone like they&#8217;re usually subsidized through carriers. They should allow purchases under family plans and not take the data plan into account. And they should allow you to select from any of T-Mobile&#8217;s Even More tiers, which would save me a phone call with T-Mobile&#8217;s (admittedly friendly and typically knowledgeable) support.</p>
<p><em><b>[1/18/2010 Edit: It was reported last week that Google is nixing the $379 rate entirely, so existing T-Mobile subscribers of all (out-of-contract) stripes will now qualify for the $279 offer. Early adopters who got hit with the $379 rate will have a refund check sent to them. Good on Google, but it'd be nice if it were $179 for all.]</b></em></p>
<img src="http://www.htmlist.com/wordpress/?ak_action=api_record_view&id=524&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/HTMList/~4/LucMGK_J_sI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.htmlist.com/tech-news/nexus-one-subsidy-hack-drop-your-data-plan-for-100-bucks/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.htmlist.com/tech-news/nexus-one-subsidy-hack-drop-your-data-plan-for-100-bucks/</feedburner:origLink></item>
		<item>
		<title>Twitter Advice for Companies: Engage Intelligently</title>
		<link>http://feedproxy.google.com/~r/HTMList/~3/oZnk2j5fr1s/</link>
		<comments>http://www.htmlist.com/how-to/twitter-advice-for-companies-engage-intelligently/#comments</comments>
		<pubDate>Sun, 27 Dec 2009 17:16:44 +0000</pubDate>
		<dc:creator>Chris Cardinal</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[companies]]></category>
		<category><![CDATA[social media]]></category>
		<category><![CDATA[Social Networking]]></category>
		<category><![CDATA[social presence]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[twitter advice]]></category>
		<category><![CDATA[twitter for business]]></category>

		<guid isPermaLink="false">http://www.htmlist.com/?p=516</guid>
		<description><![CDATA[Companies are moving to engage their customers left and right over Twitter. Here are a few tips to offer your customers the most bang for the buck.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.htmlist.com/wordpress/wp-content/uploads/2009/12/sp_twitter.jpg"><img class="alignleft size-medium wp-image-517" title="Sarah Palin Twitter" src="http://www.htmlist.com/wordpress/wp-content/uploads/2009/12/sp_twitter-300x162.jpg" alt="sp_twitter" width="300" height="162" /></a>As more and more companies move to engage their customers over Twitter, I thought it might be useful to outline a few guidelines companies should use when tweeting.</p>
<p>Naturally your mileage will vary, but these are tips I&#8217;ve put together based on my experience with companies who are doing Twitter right, and some who haven&#8217;t quite got the hang yet:<br />
<span id="more-516"></span></p>
<ol>
<li><strong>DO: SPELL THINGS CORRECTLY. </strong>Don&#8217;t treat Twitter like you&#8217;re a third-grader sending a text message. If your message is so long that you find yourself having to edit &#8220;see&#8221; to &#8220;c&#8221; or &#8220;you&#8221; to &#8220;u&#8221;, find a way to make it shorter without resorting to sounding like an idiot. (I&#8217;m looking at you, <a href="http://www.twitter.com/sarahpalinusa">@SarahPalinUSA</a>.) Use the emdash (hold alt and press 0151 on the pc keypad) to break up thoughts—without spaces on either side—instead of ellipses, or other &#8220;open set&#8221; punctuation. Breaking messages down into &#8220;leet speak&#8221; or SMS chatter is unprofessional and sloppy. If it absolutely must be said in more than 140 characters, seriously consider a blog.</li>
<li><strong>DO: TWEET SPECIAL OFFERS OCCASIONALLY</strong>. Use Twitter to incentivize your followers to stick around, but don&#8217;t spam them dozens of times throughout the day. Assume that one or two offers a day is a good maximum. (See tip #7.) Consider offering discounts or free products with a &#8220;code word&#8221; like <a href="http://www.twitter.com/sprinkles">Sprinkles Cupcakes</a> does. Nearly every day, they give away a free cupcake to the first 25 or so customers who whisper their coupon phrase that day. This has the wonderful benefit of getting people in to your store, where they&#8217;ll likely make a purchase even if they&#8217;re not one of the 25. There&#8217;s also a good chance that they&#8217;ll buy something else even if they get the free cupcake, and by limiting it to the first few customers, you can contain your costs outright. Even if you&#8217;re not a brick and mortar, special offers can encourage customers to make purchases they had been holding off on but wouldn&#8217;t have otherwise known about. Dell claims to have booked <a href="http://www.pcworld.com/article/184076/dell_proves_that_twitter_can_be_profitable.html">$6.5 million in sales</a> directly through their Twitter presence over the past two years.</li>
<li><strong>DON&#8217;T: BE BORING. </strong>Special offers are great and might be enough to keep followers around, but you can engage your customers on a much deeper level by talking about your product, your business practices, and even offering some single-tweet behind the scene glimpses into how you operate. Restaurants especially can make use of this, and one local eatery called <a title="Liberty Market" href="http://www.twitter.com/libertymarket">Liberty Market</a> does a great job tweeting about new menu items they&#8217;re working on, showing pictures, and discussing special offerings of the day. It keeps your brand on people&#8217;s minds and makes the brand far more personable.</li>
<li><strong>DO: PROACTIVELY ENGAGE CUSTOMERS.</strong> Use Twitter&#8217;s search capacity or any respectable Twitter client to set up a search with your brand or company name in it. For smaller businesses, you&#8217;ll likely see feedback directed to your Twitter account as a mention, but larger brands are going out of their way to engage customers who simply tweet ABOUT them. <a href="http://twitter.com/pizzahut">Pizza Hut</a> is a fantastic example of a corporation that really engages their customers intelligently. They reply back to people simply mentioning Pizza Hut, asking what they had and thanking them for their patronage. They also try to resolve issues, which is my next tip.</li>
<li><strong>DO: RESOLVE ISSUES WITH CUSTOMERS. </strong>Twitter is a valuable tool for companies to identify trends and monitor feedback about their brand. It&#8217;s also a powerful tool for customers to share their dissatisfaction. Because conversations through mentions/replies are public, it&#8217;s in a company&#8217;s best interest to identify negative tweets and attempt to engage the customer and make their problem right. Pizza Hut does this with nearly any negative experience tweet that comes through. You should focus on making things right, but feel free to move things off the &#8220;public&#8221; side of Twitter to resolve the issue.Similarly, I tweeted to <a href="http://www.twitter.com/hpsupport">@hpsupport</a> about a problem my brother had with his HP laptop and they engaged me directly, asking me to send an email to one of their Twitter support staff. They&#8217;ve now set up a call next Monday. This is a level of service that&#8217;s above and beyond what I was expecting from going through normal channels, and you can believe that it&#8217;s in part because the alternative is a vocal, upset customer.</li>
<li><strong>DO: TWEET THROUGHOUT THE DAY. </strong> Twitter is a different medium than an email newsletter. While mail can lose itself in the shuffle, it&#8217;s likely that a customer will at least see the message&#8217;s presence in their inbox even if they simply delete it. With Twitter, there is no such assurance. Depending on your audience, your customers may very likely not see tweets about offers or important news simply because you mentioned them earlier in the day. Most clients only fetch the last hundred or so tweets so a user who has just opened their client will likely miss a tweet from a day ago. If you&#8217;re going to have a Twitter presence, commit. An account with no new updates for three months looks worrisome.</li>
<li><strong>DON&#8217;T: TWEET NONSTOP OR SPAM YOUR USERS. </strong>Keep things to a balanced 7-12 tweets a day. Don&#8217;t repeat yourself over and over, but don&#8217;t count replies (tweets starting with someone else&#8217;s name)  in that number. Encourage users to tweet back by asking questions about what your customers like or want to see more of. Hold mini contests, discuss upcoming events, or talk about your history. But keep things in check and try to spread out your tweets. <a href="http://www.cotweet.com/">CoTweet</a> is a wonderful tool for scheduling tweets to go out so that you don&#8217;t have to be in front of a computer managing your account all day.</li>
<li><strong>DO: FOLLOW COMPETITORS &amp; OTHER LOCALS. </strong>Even though you compete with other local businesses, it&#8217;s vitally important that you follow them and see what they&#8217;re doing on Twitter, but you can also feel free to engage them online and stay friendly out in the open. You should also make a concerted effort to track down local businesses whom you work with and follow their accounts and engage with them. Word of mouth is everything and the people following your favorite businesses are likely to be great potential customers for you as well. Strike up conversations with others and you can bet they&#8217;ll return the favor. When other companies mention you (@reply within a message), it appears in their follower&#8217;s feeds, linking right to your name. A great way to earn free word of mouth is just to have productive conversations with your favorite local fellow businesses.</li>
</ol>
<p>Twitter is a quick growing medium that companies are still feeling their way around within. It&#8217;s really exciting to see companies taking customer feedback over Twitter to heart, engaging users directly, offering great deals, and using Twitter to solve problems. Still, jumping in to social networking can be a bit of a challenge and is something that does require time and effort. If you need more advice or want some help establishing your Twitter or Facebook social media presence, we&#8217;d love for you to <a title="Phoenix, Arizona web development and design" href="http://www.synapsestudios.com/contact">contact us</a>. In the meantime, I&#8217;d love to hear any tips or favorite practices you&#8217;ve seen other companies make use of that I might have left out.</p>
<img src="http://www.htmlist.com/wordpress/?ak_action=api_record_view&id=516&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/HTMList/~4/oZnk2j5fr1s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.htmlist.com/how-to/twitter-advice-for-companies-engage-intelligently/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.htmlist.com/how-to/twitter-advice-for-companies-engage-intelligently/</feedburner:origLink></item>
		<item>
		<title>Let’s Be Clear: There IS A Page Fold</title>
		<link>http://feedproxy.google.com/~r/HTMList/~3/AcQwj0nbCX8/</link>
		<comments>http://www.htmlist.com/design/lets-be-clear-there-is-a-page-fold/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 10:29:40 +0000</pubDate>
		<dc:creator>Chris Cardinal</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[break]]></category>
		<category><![CDATA[eye-tracking]]></category>
		<category><![CDATA[page fold]]></category>
		<category><![CDATA[screen resolution]]></category>
		<category><![CDATA[scrolling]]></category>
		<category><![CDATA[the fold]]></category>
		<category><![CDATA[usability]]></category>
		<category><![CDATA[user experience]]></category>
		<category><![CDATA[users]]></category>

		<guid isPermaLink="false">http://www.htmlist.com/?p=510</guid>
		<description><![CDATA[Some think there is no page fold in web design. But it still matters a great deal what first appears to your users.]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-large wp-image-512" title="please_scroll" src="http://www.htmlist.com/wordpress/wp-content/uploads/2009/12/please_scroll-96x1024.jpg" alt="please_scroll" width="96" height="1024" />Over the past day or two, the website <a href="http://www.thereisnopagefold.com/">thereisnopagefold.com</a> has been <a href="http://search.twitter.com/search?lang=en&amp;max_id=6824894453&amp;page=2&amp;q=thereisnopagefold.com">making the rounds</a>. In a rather succinct, but incredibly tall manner, it states the following:</p>
<blockquote>
<p style="padding-left: 90px;">WELCOME TO THE WORLD WIDE WEB, AN INTERACTIVE MEDIUM IN WHICH SCREEN RESOLUTION STATISTICS ARE TRIVIAL, BROWSER VIEWPORTS ARE VARIABLE, AND SCROLLING BEHAVIOUR IS A STANDARD. THERE IS NO PAGE FOLD. LOVE YOUR SCROLLBAR.</p>
</blockquote>
<p>The buzz on Twitter from &#8220;designer&#8221; types appears to be a knee-jerk &#8220;ZOMG YES SO TRUE!!!111one&#8221; while responses on the site&#8217;s <a href="http://www.reddit.com/r/web_design/comments/ag6ph/there_is_no_page_fold/">reddit thread</a> have been more measured. I especially appreciate the following comment, by one fletcher_t:</p>
<blockquote>
<p style="padding-left: 90px;">Well of course it depends on the context of what the site is providing&#8230; but there is indeed a fold and if you&#8217;re ignorant of that, may god have mercy on your soul.</p>
</blockquote>
<p>Let&#8217;s be perfectly clear: There IS a &#8220;fold&#8221;. For the uninitiated, the &#8220;fold&#8221; refers to the literal crease in a newspaper. Editors recognized the importance of catching their reader&#8217;s interest &#8220;above the fold&#8221;, because the likelihood a reader will bother to look under the fold is lower as a whole. Readers who might not typically read the sports section, for instance, will notice a story above the fold if it&#8217;s of interest to them. If they&#8217;re just flipping past as they always do, they&#8217;re far less likely to look beneath the fold.</p>
<p>The assertion made by the &#8220;no fold&#8221; site is that, because technology has provided us with infinite page lengths, we should design our pages accordingly. We can space things out more, we can use larger print and increase readability, and we shouldn&#8217;t be so concerned with what lies above the fold because <strong>users will scroll anyway!</strong> We were on a roll there up until that third point, weren&#8217;t we?</p>
<p>The reality is that the science of <a href="http://www.htmlist.com/design/highlighted-links-and-improving-web-readability-people-are-lazy/">user attention is a tricky one</a>, and more of an art than anything. Heat maps and eye-tracking studies frequently show huge dividends by presenting the initial page-load in a clear, concise manner, with well delineated courses of action visible to the user and readily accessible. <strong>Users will <em>absolutely</em> scroll, if you&#8217;ve given them a compelling reason to believe anything of interest lies beneath the fold. </strong>Users are fickle types, though, who scan quickly, look for large visual cues, and make an off-the-cuff and perhaps misinformed decision to bounce away from your site in an incredibly short amount of time, if you don&#8217;t captivate them instantly. To capture their interest, you simply must pay attention to the content that resides above the fold.</p>
<p>With Google&#8217;s release of <a href="http://www.htmlist.com/design/google-browser-size-drawn-by-five-year-olds/">Browser Size</a> the other day, Tech Crunch mentioned that Google saw a 10% increase in the number of installs of Google Earth, simply by moving the download button up 100 pixels. By placing the call to action and primary focus of the page above the fold, users were far more likely to follow through. Naturally, this will vary from site to site. Amazon.com has a rather long page, which they use to show multiple categories of products they think you&#8217;ll be interested in. Their primary feature and what they hope will have the most success is always at the top, though—a compelling enticement to scroll further and see what else they got right.</p>
<p>Understand, this is by no means an argument for cramming everything of any importance above the fold. Not even a little bit. (And I understand that the no-fold site is likely directed at those types—but does anyone <em>actually</em> try to force entire sites above the fold anymore?) Whitespace should be well utilized, large print is totally acceptable, and designers shouldn&#8217;t force pages to fit into any idea of a &#8220;standard&#8221; vertical viewport. CXPartners even <a href="http://www.cxpartners.co.uk/thoughts/the_myth_of_the_page_fold_evidence_from_user_testing.htm">argues</a> that including <em>less</em> information above the fold can encourage users to scroll more, arguably by reducing the utility of the site to the point where they&#8217;re <em>forced</em> to scroll.</p>
<p>It&#8217;s not my claim the no-fold site is implying you should ignore the above-fold design or disregard its design entirely, but the cheeky site title and its assertion that there is NO page fold degrades the importance of how you construct your pages for those first 700 or so pixels. Encourage your users to scroll, not by reducing utility but by increasing interest. Facilitate this behavior by keeping large, blocking horizontal lines and blocks at bay (advice from CXPartners&#8217; piece) and providing clear paths downward. Ensure that users see that additional content exists further down. But don&#8217;t forget that your site&#8217;s first impression is above the fold.</p>
<img src="http://www.htmlist.com/wordpress/?ak_action=api_record_view&id=510&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/HTMList/~4/AcQwj0nbCX8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.htmlist.com/design/lets-be-clear-there-is-a-page-fold/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.htmlist.com/design/lets-be-clear-there-is-a-page-fold/</feedburner:origLink></item>
		<item>
		<title>Google Browser Size: Drawn By Five-Year-Olds</title>
		<link>http://feedproxy.google.com/~r/HTMList/~3/Q3at92CODZQ/</link>
		<comments>http://www.htmlist.com/design/google-browser-size-drawn-by-five-year-olds/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 06:21:24 +0000</pubDate>
		<dc:creator>Chris Cardinal</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[browser size]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google labs]]></category>
		<category><![CDATA[half-baked]]></category>
		<category><![CDATA[screen resolution]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://www.htmlist.com/?p=505</guid>
		<description><![CDATA[Google launches a new Labs product called Browser Size, allowing you to see what portion of your websites users are most likely to see first. We just think it's a little half-baked.]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-506" title="Browser Size" src="http://www.htmlist.com/wordpress/wp-content/uploads/2009/12/htmlist_browsersize.jpg" alt="Browser Size" width="300" height="192" />Google announced a new <a title="Google Labs" href="http://www.googlelabs.com/">Labs</a> product called <a href="http://browsersize.googlelabs.com/">Browser Size</a>. At first I thought this might be a useful tool to complement their recent spate of great developer-oriented releases. Instead, I was assaulted by a hideous overlay that requires a left-aligned design. (Though they&#8217;re ostensibly working on that.)</p>
<p>Browser Size allows you to enter any URL  and see an overlay of visible browser space broken up by user demographics. Specifically, you can see what percentage of the Google-using populous would be able to see what portion of your screen on an initial page load. Apparently, this is based on typical browser dimensions for users, and not screen resolutions outright. (Taking into account non-maximized browsers.)</p>
<p>I understand that Labs products are by their nature not fully baked, but this one lands on the other extreme: half-assed. Perhaps the overlay is a rough attempt at being cheeky, but to me, it&#8217;s ugly, and its jagged, hand-drawn lines reduce its utility, rather than amping up its &#8220;cute&#8221; factor. The percentages aren&#8217;t even consistently rendered—it&#8217;s like My First Photoshop session here.</p>
<p>This isn&#8217;t to say that the concept isn&#8217;t a good one. I just wish they let this one cook a bit more before releasing it.</p>
<p><a title="Browsersize" href="http://browsersize.googlelabs.com/">Browser Size</a> | <a title="Google Labs" href="http://www.googlelabs.com/">Google Labs</a> via <a href="http://www.techcrunch.com/2009/12/16/google-browser-size/">TechCrunch</a></p>
<img src="http://www.htmlist.com/wordpress/?ak_action=api_record_view&id=505&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/HTMList/~4/Q3at92CODZQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.htmlist.com/design/google-browser-size-drawn-by-five-year-olds/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.htmlist.com/design/google-browser-size-drawn-by-five-year-olds/</feedburner:origLink></item>
		<item>
		<title>TweetNotebook: Custom Notebooks Filled With Your Tweets</title>
		<link>http://feedproxy.google.com/~r/HTMList/~3/sLWzSdOk8ME/</link>
		<comments>http://www.htmlist.com/tech-news/tweetnotebook-custom-notebooks-filled-with-your-tweets/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 10:03:58 +0000</pubDate>
		<dc:creator>Chris Cardinal</dc:creator>
				<category><![CDATA[Cool Stuff]]></category>
		<category><![CDATA[Tech News]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[notebook]]></category>
		<category><![CDATA[products]]></category>
		<category><![CDATA[threadless]]></category>
		<category><![CDATA[tweetnotebook]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.htmlist.com/?p=499</guid>
		<description><![CDATA[TweetNotebook prints notebooks filled with the wisdom of your tweets, right in the footer.]]></description>
			<content:encoded><![CDATA[<p><a title="TweetNotebook" href="http://www.tweetnotebook.com/"><img class="alignleft size-full wp-image-500" title="TweetNotebook Logo" src="http://www.htmlist.com/wordpress/wp-content/uploads/2009/12/tweetnotebook_logo.png" alt="TweetNotebook Logo" width="220" height="75" /></a><a title="TweetNotebook" href="http://www.tweetnotebook.com/">TweetNotebook</a> is a fun site by an interactive company from Belgium called <a href="http://www.boondoggle.eu/#/home">Boondoggle</a>. The premise is simple: enter your Twitter username and it generates a notebook filled with a random selection of your tweets in the footer of each page. For $12, you get a 320-page notebook with a different tweet on every page. The site lets you select your choice of cover (and print a specific message on the cover as well) before peppering each page with a random tweet from your Twitter history.</p>
<p>You can preview the book beforehand and regenerate the notebook as many times as you&#8217;d like, though for now, you can&#8217;t hand-pick tweets for the notebook. The notebook also appears to only have non-ruled pages much to my chagrin, but it sounds like TweetNotebook is planning on beefing up their offering in the near future if this takes off. For now, they have three different covers available, onto which your current avatar and cover tweet appears. Here&#8217;s mine:</p>
<p><img class="alignnone size-full wp-image-501" title="my_tweetbook" src="http://www.htmlist.com/wordpress/wp-content/uploads/2009/12/my_tweetbook.png" alt="my_tweetbook" width="506" height="163" /></p>
<p>Suffice to say, I&#8217;ve already bought mine. I think it&#8217;s a fun conversation piece, and I think that it&#8217;s a fun look into what was relevant to you a few days, weeks, or for some of us, even a year or two ago, in a blurb. It&#8217;s almost like thumbing through a diary in a sense, a simple snapshot at the bottom of each page that makes you pause and try to remember what context surrounded that tweet.</p>
<p>We&#8217;ve seen <a title="Threadless.com" href="http://bit.ly/124yOk">Threadless</a> make <a href="http://clickserve.cc-dt.com/link/click?lid=41000000029722768">T-shirts out of great tweets</a>, and I think it&#8217;s no stretch to imagine other potential products that can be built out of a users&#8217; Twitter feed. Consider a timeline, complete with tag cloud, friend diagrams, statistics, and more. Twitter lends itself to these sort of changes in medium because of their brevity and relevance—no one&#8217;s wearing a shirt with excerpts from their blog on it, but a poster that shows off my activity on Twitter is fun enough even if you&#8217;re not a raging narcissist.</p>
<p>For now, there&#8217;s also nothing to stop you from using someone else&#8217;s tweets, like a celebrity. (Or a friend, for a gift.) That situation may change if copyright issues arise. All told, my order was just $14.50, including shipping to Tempe, Arizona. Here&#8217;s hoping they&#8217;ll offer different sizes, bindings, and rulings in the future.</p>
<p><a title="TweetNotebook" href="http://www.tweetnotebook.com/">TweetNotebook</a> | via <a href="http://www.techcrunch.com/2009/12/16/tweetnotebook/">TechCrunch</a></p>
<img src="http://www.htmlist.com/wordpress/?ak_action=api_record_view&id=499&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/HTMList/~4/sLWzSdOk8ME" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.htmlist.com/tech-news/tweetnotebook-custom-notebooks-filled-with-your-tweets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.htmlist.com/tech-news/tweetnotebook-custom-notebooks-filled-with-your-tweets/</feedburner:origLink></item>
		<item>
		<title>Google Speed Tracer Makes AJAX Optimization Easier</title>
		<link>http://feedproxy.google.com/~r/HTMList/~3/ico0W3pDKOs/</link>
		<comments>http://www.htmlist.com/tech-news/google-speed-tracer-makes-ajax-optimization-easier/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 06:54:29 +0000</pubDate>
		<dc:creator>Chris Cardinal</dc:creator>
				<category><![CDATA[Cool Stuff]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Tech News]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[Google Chrome]]></category>
		<category><![CDATA[google web toolkit]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[profiling]]></category>
		<category><![CDATA[speed tracer]]></category>

		<guid isPermaLink="false">http://www.htmlist.com/?p=493</guid>
		<description><![CDATA[Google announced their Speed Tracer profiling tool to allow developers to better analyze performance problems in their web applications.]]></description>
			<content:encoded><![CDATA[<p><img class="size-medium wp-image-495 alignright" title="SpeedTracer-SluggishnessDetail" src="http://www.htmlist.com/wordpress/wp-content/uploads/2009/12/SpeedTracer-SluggishnessDetail-300x297.png" alt="SpeedTracer-SluggishnessDetail" width="180" height="178" />Google today announced <a title="Google Speed Tracer" href="http://code.google.com/webtoolkit/speedtracer/">Speed Tracer</a> as part of their <a href="http://code.google.com/webtoolkit/overview.html">Google Web Toolkit</a> offerings. While most of the GWT focuses on enabling developers to create web applications in Java (which compiles down to optimized JavaScript), Speed Tracer is a useful profiling tool for any developer wrestling with XMLHttpRequest.</p>
<p><strong>What makes Speed Tracer different?</strong></p>
<p>Developers have long used Firebug to identify what AJAX requests were causing bottlenecks and to analyze responses to those requests. Firebug is an extremely powerful tool and does a serviceable job with this approach, but Speed Tracer takes things one step further, analyzing the &#8220;sluggishness&#8221; of your application by examining how busy or blocked the UI is in your browser. This can help developers analyze why their application feels slow, instead of simply focusing on network-based bottlenecks.</p>
<p>Speed Tracer makes use of specific, unique APIs built into Webkit for this very purpose, which gives it a unique advantage compared to other profiling tools. Instead of simply guessing and checking, developers will now have full visibility into what&#8217;s causing their applications to appear slow:<br />
<blockquote>Using Speed Tracer you are able to get a better picture of where time is being spent in your application. This includes problems caused by JavaScript parsing and execution, layout, CSS style recalculation and selector matching, DOM event handling, network resource loading, timer fires, XMLHttpRequest callbacks, painting, and more.</p></blockquote>
<p>Very cool stuff. What&#8217;s more, it&#8217;s free, open source, and <a title="Speed Tracer getting started" href="http://code.google.com/webtoolkit/speedtracer/get-started.html">available for users of Google Chrome right now</a>. Check out their tutorial below:</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://www.youtube.com/v/Sn_3rJaexKc&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/Sn_3rJaexKc&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p><a title="Google Speed Tracer" href="http://code.google.com/webtoolkit/speedtracer/">Google Speed Tracer</a></p>
<img src="http://www.htmlist.com/wordpress/?ak_action=api_record_view&id=493&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/HTMList/~4/ico0W3pDKOs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.htmlist.com/tech-news/google-speed-tracer-makes-ajax-optimization-easier/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.htmlist.com/tech-news/google-speed-tracer-makes-ajax-optimization-easier/</feedburner:origLink></item>
		<item>
		<title>Anatomy of a Smart Survey: Netflix Email Surveys</title>
		<link>http://feedproxy.google.com/~r/HTMList/~3/qHS8fqWQlS4/</link>
		<comments>http://www.htmlist.com/design/anatomy-of-a-smart-survey-netflix-email-surveys/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 09:40:18 +0000</pubDate>
		<dc:creator>Chris Cardinal</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[customer feedback]]></category>
		<category><![CDATA[feedback]]></category>
		<category><![CDATA[lists]]></category>
		<category><![CDATA[netflix]]></category>
		<category><![CDATA[surveys]]></category>
		<category><![CDATA[usability]]></category>
		<category><![CDATA[user experience]]></category>

		<guid isPermaLink="false">http://www.htmlist.com/?p=489</guid>
		<description><![CDATA[Netflix understands the key to a successful customer satisfaction survey: keeping it simple. We look at how to incorporate some of their best practices in your next survey.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.htmlist.com/wordpress/wp-content/uploads/2009/11/netflix_survey.gif"><img class="size-full wp-image-490 alignleft" title="Netflix Survey Screenshot" src="http://www.htmlist.com/wordpress/wp-content/uploads/2009/11/netflix_survey.gif" alt="netflix_survey" width="300" height="217" /></a><a title="Netflix" href="http://www.netflix.com/">Netflix</a> is a company built entirely around efficiency. When you deal with the volume Netflix does, every penny, every action, every little detail counts immensely. Take their mailer: Over the years, it has evolved from a cardboard-backed affair, to a paper-based piece with a foam insert, to today&#8217;s design: thin, simple paper. (They determined the breakage rates didn&#8217;t decrease enough with the padding to make it cost-effective.)</p>
<p>It&#8217;s no surprise then that they&#8217;d take the time to get surveys right. Netflix (like most companies trying to make a profit) has a need for constant feedback from their customers. They want to know how their distribution system is working, where there may be bottlenecks, and other things like how their new instant streaming service is performing. Instead of producing staid, time-consuming, multi-page affairs, they send an email with a single question.</p>
<p>In my most recent survey, that question read &#8220;How was the picture and audio quality?&#8221; Simple enough. The real stroke of genius lies in how the user is asked to respond: Three links are displayed, each with a different quality option: &#8220;The quality was very good&#8221;, acceptable, or unacceptable. You click the link and your survey response is sent. Done. That&#8217;s all there is to it.</p>
<p>The survey requires exactly one click to respond to. Users aren&#8217;t asked to login, fill out demographic data, attempt to remember details they aren&#8217;t likely to, or even read anything to qualify their answer. They are given three relatively unambiguous options and clicking the link from within the email submits their response.</p>
<p>Since not every company has the luxury of being able to boil their customer feedback loop down into simple multiple choice questions, let&#8217;s look at a few key points almost anyone can replicate:<span id="more-489"></span></p>
<ol>
<li><strong>Keep it simple. </strong>Remember that users value their time, and while they may like to let you know what they think of your company and how you&#8217;re doing, they may simply not have the time. Focus on a few measurements that can be easily procured and ask just a couple of questions. Consider anything else an imposition for the sake of a casual survey.</li>
<li><strong>Don&#8217;t require a login. </strong>If your users have accounts with you, don&#8217;t require them to login to complete their survey. Include a hash tag unique to the individual survey in every call to action link and compile your results from that. Every additional step a user has to complete is another hoop that will encourage them to close their browser and forget about responding. Remember that when you consider adding a confirmation screen, for instance.</li>
<li><strong>Provide a call to action. </strong>Even if you can&#8217;t find a way to boil a survey down into a completely self-contained piece like Netflix does, provide the user with an initial call to action. Have them answer a single question up front, and present the user with an optional means to supply more information based on their response. In the Netflix example, the user might be prompted to explain the issue if they mark the quality as unacceptable.</li>
<li><strong>Require as little data entry as possible. </strong>This goes back to items one and two: every next step or request for additional information is an opportunity to frustrate your user. In order to ensure the highest quality data, don&#8217;t give your users those opportunities to jump ship.</li>
<li><strong>Allow users to opt-out or set email frequencies. </strong>Don&#8217;t abuse users with surveys, or you&#8217;ll find they&#8217;re no longer users. Provide an unsubscribe link that does the work for them so that they can go back to enjoying your service and so that you don&#8217;t frustrate them.</li>
<li><strong>Keep the design simple, too. </strong>More than just the format of the survey itself, consider paring the design down dramatically. If you&#8217;re emailing the survey, the user shouldn&#8217;t have to activate images to make a selection. A logo, a border, and some simple elements that tie your corporate color scheme in are acceptable, but making the entire email HTML-based is yet another barrier for users to hit when they may have otherwise completed your survey.</li>
<li><strong>Provide context.</strong> Users love to know they&#8217;re making a difference. While it may seem obvious, just mentioning that you&#8217;re issuing the survey as a means of proactively enhancing their experience can go a long way. Feel free to let some personality come through, but don&#8217;t forget to keep it simple overall. The less users have to read, the better your response rate will be.</li>
<li><strong>Say &#8220;thank you.&#8221; </strong>This may seem like a no-brainer, but since the user will be directed to a page upon clicking your call to action/survey response link, make sure you thank them and provide them with options to navigate back to your site if they so desire<strong>.</strong></li>
</ol>
<p>Even with these tenets in mind, you may find it difficult to break out of the mold and build surveys based around such narrow data points. Consider it an exercise in analyzing what really makes your customers happy and what makes your business tick. Think a bit outside the box and consider: If you can only ask your customers one question about their experience with you, (a multiple-choice at that!) what would it be? Remember that you can rotate questions around of course, but start there.</p>
<p>Finally, if you&#8217;re reading this and not sure how to implement this sort of survey system on your own website, by all means please <a title="Contact Synapse Studios" href="http://www.synapsestudios.com/contact">contact us</a> over at <a title="Phoenix, Arizona Web Application Development and Custom Software" href="http://www.synapsestudios.com/">Synapse Studios</a>. It&#8217;s what we do!</p>
<img src="http://www.htmlist.com/wordpress/?ak_action=api_record_view&id=489&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/HTMList/~4/qHS8fqWQlS4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.htmlist.com/design/anatomy-of-a-smart-survey-netflix-email-surveys/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.htmlist.com/design/anatomy-of-a-smart-survey-netflix-email-surveys/</feedburner:origLink></item>
		<item>
		<title>Senior PHP Developer Position in Tempe, Arizona</title>
		<link>http://feedproxy.google.com/~r/HTMList/~3/AB5WxbaAPXQ/</link>
		<comments>http://www.htmlist.com/announcements/senior-php-developer-position-in-tempe-arizona/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 20:30:11 +0000</pubDate>
		<dc:creator>Chris Cardinal</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[developers]]></category>
		<category><![CDATA[jobs]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[synapse studios]]></category>

		<guid isPermaLink="false">http://www.htmlist.com/?p=485</guid>
		<description><![CDATA[
Our company Synapse Studios is hiring a senior PHP developer right now. Specifically, we&#8217;re looking for someone who can help lead our talented team and establish methodologies that scale and make for a more powerful team. More information on the position is available here, but you&#8217;d be working in our offices in downtown Tempe, Arizona, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-486" title="synapse_office" src="http://www.htmlist.com/wordpress/wp-content/uploads/2009/09/synapse_office-300x200.jpg" alt="synapse_office" width="300" height="200" /></p>
<p>Our company <a href="http://www.synapsestudios.com/">Synapse Studios</a> is hiring a senior PHP developer right now. Specifically, we&#8217;re looking for someone who can help lead our talented team and establish methodologies that scale and make for a more powerful team. More information on the position is available <a title="Senior PHP Developer job" href="http://www.synapsestudios.com/jobs/php_guru/">here</a>, but you&#8217;d be working in our offices in downtown Tempe, Arizona, right on Mill Avenue. It&#8217;s a great space with fun people and exciting work, so if you&#8217;re interested, view the job post on our site and follow our instructions over there.</p>
<p><a href="http://www.synapsestudios.com/jobs/php_guru/">Senior PHP Developer Job Posting</a> | Synapse Studios</p>
<img src="http://www.htmlist.com/wordpress/?ak_action=api_record_view&id=485&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/HTMList/~4/AB5WxbaAPXQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.htmlist.com/announcements/senior-php-developer-position-in-tempe-arizona/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.htmlist.com/announcements/senior-php-developer-position-in-tempe-arizona/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.705 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-01-28 16:47:12 -->
