<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Nicolas Schudel &#187; E-commerce</title>
	<atom:link href="http://nicolasschudel.name/category/e-commerce/feed/" rel="self" type="application/rss+xml" />
	<link>http://nicolasschudel.name</link>
	<description>Balancing Design and Development in Online Media</description>
	<lastBuildDate>Sun, 09 May 2010 08:42:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Bridging the Gap &#8211; A Method for Managing a Physical and Online Store in Parallel</title>
		<link>http://nicolasschudel.name/bridging-the-gap/</link>
		<comments>http://nicolasschudel.name/bridging-the-gap/#comments</comments>
		<pubDate>Thu, 28 Feb 2008 16:51:29 +0000</pubDate>
		<dc:creator>Nicolas</dc:creator>
				<category><![CDATA[E-commerce]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Zen-Cart]]></category>

		<guid isPermaLink="false">http://nicolasschudel.name/?p=164</guid>
		<description><![CDATA[Small brick-and-mortar stores run on a tight budget and often rely on open source e-commerce software for managing inventory. I describe a setup I have made for a boutique, that allows the booking of in-store purchases online.]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Small <a href="http://en.wikipedia.org/wiki/Brick_and_mortar_business">brick and mortar stores</a> run on a tight budget and often rely on open source software for managing inventory. I will discuss the setup I have made for a boutique that is running both a physical and online store.</p>
<h2>Scenario</h2>
<p>If you extend an existing <abbr title="brick and mortar">B&amp;M</abbr> store with an online shop, you will eventually run into a problem synchronizing your product inventory. Running two separate inventories may be a hassle, especially if you start moving products out of the store and into the online shop or vice versa.</p>
<h2>A Simple Solution</h2>
<p>Treat both inventories as one. The same item could be on display in both the physical and online stores. Better yet, use the physical store as the storage room for the online store &#8211; eliminating the need to pay rent for extra space.</p>
<div id="attachment_424" class="wp-caption alignright" style="width: 310px"><img src="http://nicolasschudel.name/fileadmin/articles//2008/02/3460102542_5cfc6c5fd2-300x199.jpg" alt="The in-store items can be sold via the online shop at the same time. (photo by Gastev on Flickr)" title="Store Inventory" width="300" height="199" class="size-medium wp-image-424" /><p class="wp-caption-text">The in-store items can be sold via the online shop at the same time. (photo by Gastev on Flickr)</p></div>
<p>The biggest hurdle, using this solution, is the booking of a physical product sale to the online database. This would have to happen <abbr title="as soon as possible">ASAP</abbr>, so the same product can’t be bought twice (by separate customers in both realms). A possible way, would be to use a computer as the point of sales and book directly to the online database. I had an iMac connected to a USB receipt printer and cash drawer. However, this setup did not last. It requires the computer to be online in order to book a purchase. What happens when the internet connection is lost with a line of customers to attend to? Murphy would predict this to happen. Even a slow internet connection lengthens the purchasing process unnecessarily, and nobody likes to wait at the register. Optimally, the <abbr title="point of sale">POS</abbr> software could have a caching mechanism and then synchronize the purchases with the online shop as soon as it’s back online.</p>
<p>I have chosen to revert to the “non-software-reliant” way of tackling this problem: Use a classic cash register for handling the money transaction. It’s fast and reliable; The cash register does not need to know anything about the inventory. During the purchase process, note the numbers of the products being sold; Using pen and paper, in your head, whatever is fast (and reliable).</p>
<p>Speaking of product numbers. The inventory in the database is usually numbered continuously (e.g. the first product in the database is number 1, then number 2 and so forth). Tag the actual product with that number. The shop I have this solution running in hasn’t yet reached 5 digit product numbers. This makes the number easier to handle than a long EAN code.</p>
<p>Soon after a physical purchase, when all customers are attended to, connect to the administration section of the online shop and enter the product numbers that have been purchased. I will later discuss a module I programmed to streamline this process.</p>
<p>Working this way, the product numbers do have to be remembered/written twice (during the purchase and while synchronizing with the database), but it improves the customer experience by removing the time it takes to handle the software.</p>
<h2>The Software</h2>
<p>I use the open source software named <a href="http://www.zen-cart.com/">Zen-Cart</a> to manage the product inventory. It was, in my opinion, the best option when I first created the shop in 2006. There are many newer and better projects out there in the meantime, such as <a href="http://www.magentocommerce.com/">Magento</a>, <a href="http://ofbiz.apache.org/">OFBiz</a>, and <a href="http://spreecommerce.com/">Spree</a>.</p>
<p>I adapted the Zen-Cart checkout process to allow client-side technologies such as Javascript and Flash to call it. I have also created a Zen-Cart module that books purchases based on a list of product numbers. It takes a few seconds to complete: for instance just enter “23, 612, 5, 1209” into the form and hit enter. Each purchase is entered into the database, as if it where bought online using the original checkout process.</p>
<p><a href="http://code.google.com/p/point-of-sale-services-zencart/">The project</a> is hosted on Google code. It will need some tweaking to work, so PHP and Javascript knowledge is required. <a href="http://point-of-sale-services-zencart.googlecode.com/files/pos-services-zencart-alpha2.zip">Download the services here</a>.</p>
<h2>Conclusion</h2>
<p>The described solution, where I moved the step of booking into the online database to the end of the purchase process, has worked well since it has been initiated in 2007. If anybody has an even simpler solution to run a physical and online store in parallel, please leave a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicolasschudel.name/bridging-the-gap/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Making Sign-Up Forms That Much Easier</title>
		<link>http://nicolasschudel.name/making-sign-up-forms-that-much-easier/</link>
		<comments>http://nicolasschudel.name/making-sign-up-forms-that-much-easier/#comments</comments>
		<pubDate>Mon, 18 Feb 2008 13:23:22 +0000</pubDate>
		<dc:creator>Nicolas</dc:creator>
				<category><![CDATA[E-commerce]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Forms]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://nicolasschudel.name/?p=23</guid>
		<description><![CDATA[<p>Having to create an account is a barrier for new users to join a site and should, therefore, be kept as easy as possible. I propose a user interface improvement that pre-fills the user’s city based on the entered postal code. In addition, I describe the programming process using PHP, MySQL and AJAX.</p>]]></description>
			<content:encoded><![CDATA[<img src="http://nicolasschudel.name/fileadmin/articles//2008/02/signup-forms.png" alt="Signup Forms" title="Signup Forms" width="180" height="180" class="alignleft size-full wp-image-334" />
<p>
I watched a <a href="http://www.youtube.com/watch?v=J00ehBG0VNg">useful presentation about form design</a> by Ryan Singer a while back and he makes a point that user input should be kept to the bare minimum when signing up. An article by Luke Wroblewski titled <a href="http://www.alistapart.com/articles/signupforms">Sign Up Forms Must Die</a> seconds the notion.
</p>
<p>
However, sometimes it is required for the user to do the leg-work and fill in lots information. Like registering at an online store for instance. Gotta at least know where to send the purchased goods! For users that don't have auto-fill plugins such as the <a href="http://toolbar.google.com/)">Google Toolbar</a>, Javascript can help filling in the necessary information - not just validating the user input. It would, for instance, make web forms simpler for users if their city would be filled in automatically upon entering their postcode. I timed myself typing my city of residence as quickly as possible and it took me about 3 seconds. So, all in theory of course, the improvement would skim roughly that much time off filling in a form. It's not a lot, but the users level of tolerance towards HTML forms isn't much either.
</p>
<p>
I'm now going to talk about how I “auto-fill” the city information based on the entered postcode in a HTML form using PHP, MySql and Javascript.
</p>
<h2>Setting Up the Database</h2>
<p>
First I needed to get the postcode information from somewhere. For Switzerland I found <a href="https://match.postmail.ch/">the data</a> via the Swiss Post.
</p>
<p>
Then I needed to get it into the database somehow. To do this I imported the downloaded text file (it is tab delimited) into Excel and then exported it again as a <abbr title="comma-separated values file format">CSV</abbr> file. I only imported the columns I needed which are the ones containing the Town name and the postcode.
</p>
<p>
Next I put on my white programming gloves and wrote a quick PHP script that connects to the database and runs two <abbr title="Structured Query Language">SQL</abbr> statements to import the <abbr title="comma-separated values file format">CSV</abbr> file. Change the variables to fit your setup and be sure to have the <abbr title="comma-separated values file format">CSV</abbr> file in the same folder when you run the following example.
</p>
<pre class="brush: php">
$link = mysql_connect('localhost', 'root', 'root') or die('Could not connect: ' . mysql_error());

mysql_query(&amp;amp;quot;CREATE DATABASE IF NOT EXISTS test
DEFAULT CHARACTER SET latin1 
COLLATE latin1_swedish_ci;&amp;amp;quot;
);

mysql_select_db('test') or die('Cannot select database');

mysql_query( &amp;amp;quot;CREATE TABLE postcodes (
code SMALLINT(4) NOT NULL ,
city VARCHAR(27) NOT NULL ,
PRIMARY KEY (code)
) ENGINE = MYISAM CHARACTER SET latin1 COLLATE latin1_swedish_ci&amp;amp;quot;
);

mysql_query( &amp;amp;quot;LOAD DATA LOCAL INFILE 'postcodes.csv'
INTO TABLE postcodes
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\r\n'
(code, city);&amp;amp;quot;
);

if(mysql_error()) echo mysql_error();
else echo &amp;amp;quot;Done!&amp;amp;quot;;

mysql_close($link);
</pre>
<p>
Special characters where also an issue with importing and exporting so be sure to check the city names in the database. I used the windows text format for importing.
</p>
<h2>Creating a Web Service</h2>
<p>
We now need some server side code to provide us with the data from the database. I am using the insanely cool <abbr title="JavaScript Object Notation">JSON</abbr> gateway included with <a href="http://www.amfphp.org/">AMFPHP</a> to provide the client with data. So with AMFPHP set up I could just write a simple PosteCodeFinder class and plop it into the AMFPHP's services folder. Otherwise a simple way to get the correct name would be a PHP script like this:
</p>
<pre class="brush: php">
mysql_connect('localhost', 'root', 'root') or die('Could not connect: ' . mysql_error());
mysql_select_db('zencart_shop') or die('Cannot select database');

if (isset($_GET['code']) &amp;amp;amp;&amp;amp;amp; is_numeric($_GET['code'])) $code= $_GET['code'];
else die ('Only numbers please! The URL should look something like: postcodefinder.php?code=1000');

$query = &amp;amp;quot;SELECT city FROM postcodes WHERE code =&amp;amp;quot; . $code . &amp;amp;quot; LIMIT 0 , 1 &amp;amp;quot;;

header(&amp;amp;quot;Content-Type: text/javascript; charset=utf-8&amp;amp;quot;);
echo json_encode(utf8_encode(mysql_result(mysql_query($query), &amp;amp;quot;city&amp;amp;quot;)));
</pre>
<p>
The code connects to the database, checks the input to be numeric, retrieves the city name and spits it out as <abbr title="JavaScript Object Notation">JSON</abbr>.
</p>
<p>
I had to use utf8_encode() inside the json_encode() function because it would otherwise mess up my character encoding. "Genéve", for instance, would be truncated to "Gen". It was reported as <a href="http://bugs.php.net/bug.php?id=43941">PHP bug #43941</a>.
</p>
<h2>The Client-Side Code</h2>
<p>
On to the Javascript! I am using the Prototype library here to make programming AJAX bearable.
</p>
<pre class="brush: jscript">
FormController = {
	previousResponse: &quot;&quot;,
	
	postcodeHandler:function(el) {
		var code = parseInt(el.value);
		if (code &gt;= 1000 &amp;&amp; code &lt;= 9999 &amp;&amp; $F('country') == 204) 
	  	new Ajax.Request(
			&quot;json.php/PostCodeFinder.find/&quot; + code, 
			{
	  		method: &quot;get&quot;,
	  		onSuccess: FormController.updatePostCode.bindAsEventListener(this)
	  		}
		);
	},
	
	updatePostCode:function(transport) {
		var jsonObj = eval(&quot;(&quot; + transport.responseText + &quot;)&quot;);
		if (jsonObj != undefined &amp;&amp; ($F('city') == &quot;&quot; || $F('city') == previousResponse)) {
	   	$('city').value = jsonObj;
			this.previousResponse = jsonObj;
	   }
	}
}

Event.observe(
	window,
	'load',
	function() {
		new Form.Element.Observer('postcode', 1, FormController.postcodeHandler.bindAsEventListener(this));
	}
)
</pre>
<p>
<a href="/fileadmin/postcodefinder.zip">Download all the code here.</a>
</p>
<h2>Conclusions</h2>
<h3>Usability Gain</h3>
<p>
Considering the amount of time it took me to implement, I can only recommend the postcode optimization as a final improvement to a form.   Other factors, as mentioned in Singer's video for instance, should be considered first to get the most bang for the buck.
</p>
<h3>Character Encoding</h3>
<p>
Most of my time was not spent with programming the scripts but with playing with the character encoding. Having UTF-8 all the way through form the original text file, to the database, to the PHP script, to the client side Javascript and finally the HTML document itself was easier said than done. I found a <a href="http://www.kerstner.at/downloads/utf8_webapplications_v0.2.pdf">PDF on the UTF-8 development practices</a> by Matthias Kerstener, that helped out with some of the issues. Still, character encoding issues makes me not want to be a web developer any more.
</p>]]></content:encoded>
			<wfw:commentRss>http://nicolasschudel.name/making-sign-up-forms-that-much-easier/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
